/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimp-user-install.c
* Copyright (C) 2000-2008 Michael Natterer and Sven Neumann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/* This file contains functions to help migrate the settings from a
* previous GIMP version to be used with the current (newer) version.
*/
#include "config.h"
#include
#include
#include
#include
#ifdef HAVE_UNISTD_H
#include
#endif
#ifdef PLATFORM_OSX
#include
#endif
#include
#include
#ifdef G_OS_WIN32
#include
#endif
#include "libgimpbase/gimpbase.h"
#include "core-types.h"
#include "config/gimpconfig-file.h"
#include "config/gimprc.h"
#include "gimp-templates.h"
#include "gimp-tags.h"
#include "gimp-user-install.h"
#include "gimp-intl.h"
struct _GimpUserInstall
{
GObject *gimp;
gboolean verbose;
gchar *old_dir;
gint old_major;
gint old_minor;
const gchar *migrate;
GimpUserInstallLogFunc log;
gpointer log_data;
};
typedef enum
{
USER_INSTALL_MKDIR, /* Create the directory */
USER_INSTALL_COPY /* Copy from sysconf directory */
} GimpUserInstallAction;
static const struct
{
const gchar *name;
GimpUserInstallAction action;
}
gimp_user_install_items[] =
{
{ "menurc", USER_INSTALL_COPY },
{ "brushes", USER_INSTALL_MKDIR },
{ "dynamics", USER_INSTALL_MKDIR },
{ "fonts", USER_INSTALL_MKDIR },
{ "gradients", USER_INSTALL_MKDIR },
{ "palettes", USER_INSTALL_MKDIR },
{ "patterns", USER_INSTALL_MKDIR },
{ "tool-presets", USER_INSTALL_MKDIR },
{ "plug-ins", USER_INSTALL_MKDIR },
{ "modules", USER_INSTALL_MKDIR },
{ "interpreters", USER_INSTALL_MKDIR },
{ "environ", USER_INSTALL_MKDIR },
{ "scripts", USER_INSTALL_MKDIR },
{ "templates", USER_INSTALL_MKDIR },
{ "themes", USER_INSTALL_MKDIR },
{ "icons", USER_INSTALL_MKDIR },
{ "tmp", USER_INSTALL_MKDIR },
{ "curves", USER_INSTALL_MKDIR },
{ "levels", USER_INSTALL_MKDIR },
{ "filters", USER_INSTALL_MKDIR },
{ "fractalexplorer", USER_INSTALL_MKDIR },
{ "gfig", USER_INSTALL_MKDIR },
{ "gflare", USER_INSTALL_MKDIR },
{ "gimpressionist", USER_INSTALL_MKDIR }
};
static gboolean user_install_detect_old (GimpUserInstall *install,
const gchar *gimp_dir);
static gchar * user_install_old_style_gimpdir (void);
static void user_install_log (GimpUserInstall *install,
const gchar *format,
...) G_GNUC_PRINTF (2, 3);
static void user_install_log_newline (GimpUserInstall *install);
static void user_install_log_error (GimpUserInstall *install,
GError **error);
static gboolean user_install_mkdir (GimpUserInstall *install,
const gchar *dirname);
static gboolean user_install_mkdir_with_parents (GimpUserInstall *install,
const gchar *dirname);
static gboolean user_install_file_copy (GimpUserInstall *install,
const gchar *source,
const gchar *dest,
const gchar *old_options_regexp,
GRegexEvalCallback update_callback);
static gboolean user_install_dir_copy (GimpUserInstall *install,
gint level,
const gchar *source,
const gchar *base,
const gchar *update_pattern,
GRegexEvalCallback update_callback);
static gboolean user_install_create_files (GimpUserInstall *install);
static gboolean user_install_migrate_files (GimpUserInstall *install);
/* public functions */
GimpUserInstall *
gimp_user_install_new (GObject *gimp,
gboolean verbose)
{
GimpUserInstall *install = g_slice_new0 (GimpUserInstall);
install->gimp = gimp;
install->verbose = verbose;
user_install_detect_old (install, gimp_directory ());
#ifdef PLATFORM_OSX
/* The config path on OSX has for a very short time frame (2.8.2 only)
been "~/Library/GIMP". It changed to "~/Library/Application Support"
in 2.8.4 and was in the home folder (as was other UNIX) before. */
if (! install->old_dir)
{
gchar *dir;
NSAutoreleasePool *pool;
NSArray *path;
NSString *library_dir;
pool = [[NSAutoreleasePool alloc] init];
path = NSSearchPathForDirectoriesInDomains (NSLibraryDirectory,
NSUserDomainMask, YES);
library_dir = [path objectAtIndex:0];
dir = g_build_filename ([library_dir UTF8String],
GIMPDIR, GIMP_USER_VERSION, NULL);
[pool drain];
user_install_detect_old (install, dir);
g_free (dir);
}
#endif
if (! install->old_dir)
{
/* if the default XDG-style config directory was not found, try
* the "old-style" path in the home folder.
*/
gchar *dir = user_install_old_style_gimpdir ();
user_install_detect_old (install, dir);
g_free (dir);
}
return install;
}
gboolean
gimp_user_install_run (GimpUserInstall *install)
{
gchar *dirname;
g_return_val_if_fail (install != NULL, FALSE);
dirname = g_filename_display_name (gimp_directory ());
if (install->migrate)
user_install_log (install,
_("It seems you have used GIMP %s before. "
"GIMP will now migrate your user settings to '%s'."),
install->migrate, dirname);
else
user_install_log (install,
_("It appears that you are using GIMP for the "
"first time. GIMP will now create a folder "
"named '%s' and copy some files to it."),
dirname);
g_free (dirname);
user_install_log_newline (install);
if (! user_install_mkdir_with_parents (install, gimp_directory ()))
return FALSE;
if (install->migrate)
if (! user_install_migrate_files (install))
return FALSE;
return user_install_create_files (install);
}
void
gimp_user_install_free (GimpUserInstall *install)
{
g_return_if_fail (install != NULL);
g_free (install->old_dir);
g_slice_free (GimpUserInstall, install);
}
void
gimp_user_install_set_log_handler (GimpUserInstall *install,
GimpUserInstallLogFunc log,
gpointer user_data)
{
g_return_if_fail (install != NULL);
install->log = log;
install->log_data = user_data;
}
/* Local functions */
static gboolean
user_install_detect_old (GimpUserInstall *install,
const gchar *gimp_dir)
{
gchar *dir = g_strdup (gimp_dir);
gchar *version;
gboolean migrate = FALSE;
version = strstr (dir, GIMP_APP_VERSION);
if (version)
{
gint i;
for (i = (GIMP_MINOR_VERSION & ~1); i >= 0; i -= 2)
{
/* we assume that GIMP_APP_VERSION is in the form '2.x' */
g_snprintf (version + 2, 2, "%d", i);
migrate = g_file_test (dir, G_FILE_TEST_IS_DIR);
if (migrate)
{
#ifdef GIMP_UNSTABLE
g_printerr ("gimp-user-install: migrating from %s\n", dir);
#endif
install->old_major = 2;
install->old_minor = i;
break;
}
}
}
if (migrate)
{
install->old_dir = dir;
install->migrate = (const gchar *) version;
}
else
{
g_free (dir);
}
return migrate;
}
static gchar *
user_install_old_style_gimpdir (void)
{
const gchar *home_dir = g_get_home_dir ();
gchar *gimp_dir = NULL;
if (home_dir)
{
gimp_dir = g_build_filename (home_dir, ".gimp-" GIMP_APP_VERSION, NULL);
}
else
{
gchar *user_name = g_strdup (g_get_user_name ());
gchar *subdir_name;
#ifdef G_OS_WIN32
gchar *p = user_name;
while (*p)
{
/* Replace funny characters in the user name with an
* underscore. The code below also replaces some
* characters that in fact are legal in file names, but
* who cares, as long as the definitely illegal ones are
* caught.
*/
if (!g_ascii_isalnum (*p) && !strchr ("-.,@=", *p))
*p = '_';
p++;
}
#endif
#ifndef G_OS_WIN32
g_message ("warning: no home directory.");
#endif
subdir_name = g_strconcat (".gimp-" GIMP_APP_VERSION ".", user_name, NULL);
gimp_dir = g_build_filename (gimp_data_directory (),
subdir_name,
NULL);
g_free (user_name);
g_free (subdir_name);
}
return gimp_dir;
}
static void
user_install_log (GimpUserInstall *install,
const gchar *format,
...)
{
va_list args;
va_start (args, format);
if (format)
{
gchar *message = g_strdup_vprintf (format, args);
if (install->verbose)
g_print ("%s\n", message);
if (install->log)
install->log (message, FALSE, install->log_data);
g_free (message);
}
va_end (args);
}
static void
user_install_log_newline (GimpUserInstall *install)
{
if (install->verbose)
g_print ("\n");
if (install->log)
install->log (NULL, FALSE, install->log_data);
}
static void
user_install_log_error (GimpUserInstall *install,
GError **error)
{
if (error && *error)
{
const gchar *message = ((*error)->message ?
(*error)->message : "(unknown error)");
if (install->log)
install->log (message, TRUE, install->log_data);
else
g_print ("error: %s\n", message);
g_clear_error (error);
}
}
static gboolean
user_install_file_copy (GimpUserInstall *install,
const gchar *source,
const gchar *dest,
const gchar *old_options_regexp,
GRegexEvalCallback update_callback)
{
GError *error = NULL;
gboolean success;
user_install_log (install, _("Copying file '%s' from '%s'..."),
gimp_filename_to_utf8 (dest),
gimp_filename_to_utf8 (source));
success = gimp_config_file_copy (source, dest, old_options_regexp, update_callback, &error);
user_install_log_error (install, &error);
return success;
}
static gboolean
user_install_mkdir (GimpUserInstall *install,
const gchar *dirname)
{
user_install_log (install, _("Creating folder '%s'..."),
gimp_filename_to_utf8 (dirname));
if (g_mkdir (dirname,
S_IRUSR | S_IWUSR | S_IXUSR |
S_IRGRP | S_IXGRP |
S_IROTH | S_IXOTH) == -1)
{
GError *error = NULL;
g_set_error (&error, G_FILE_ERROR, g_file_error_from_errno (errno),
_("Cannot create folder '%s': %s"),
gimp_filename_to_utf8 (dirname), g_strerror (errno));
user_install_log_error (install, &error);
return FALSE;
}
return TRUE;
}
static gboolean
user_install_mkdir_with_parents (GimpUserInstall *install,
const gchar *dirname)
{
user_install_log (install, _("Creating folder '%s'..."),
gimp_filename_to_utf8 (dirname));
if (g_mkdir_with_parents (dirname,
S_IRUSR | S_IWUSR | S_IXUSR |
S_IRGRP | S_IXGRP |
S_IROTH | S_IXOTH) == -1)
{
GError *error = NULL;
g_set_error (&error, G_FILE_ERROR, g_file_error_from_errno (errno),
_("Cannot create folder '%s': %s"),
gimp_filename_to_utf8 (dirname), g_strerror (errno));
user_install_log_error (install, &error);
return FALSE;
}
return TRUE;
}
/* The regexp pattern of all options changed from menurc of GIMP 2.8.
* Add any pattern that we want to recognize for replacement in the menurc of
* the next release
*/
#define MENURC_OVER20_UPDATE_PATTERN \
"\"/buffers/buffers-paste-as-new\"" "|" \
"\"/edit/edit-paste-as-new\"" "|" \
"\"/file/file-export\"" "|" \
"\"/file/file-export-to\"" "|" \
"\"/layers/layers-text-tool\"" "|" \
"\"/plug-in/plug-in-gauss\"" "|" \
"\"/tools/tools-value-[1-4]-.*\"" "|" \
"\"/vectors/vectors-path-tool\"" "|" \
"\"/tools/tools-blend\""
/**
* callback to use for updating a menurc from GIMP over 2.0.
* data is unused (always NULL).
* The updated value will be matched line by line.
*/
static gboolean
user_update_menurc_over20 (const GMatchInfo *matched_value,
GString *new_value,
gpointer data)
{
gchar *match = g_match_info_fetch (matched_value, 0);
/* "*-paste-as-new" renamed to "*-paste-as-new-image"
*/
if (g_strcmp0 (match, "\"/buffers/buffers-paste-as-new\"") == 0)
{
g_string_append (new_value, "\"/buffers/buffers-paste-as-new-image\"");
}
else if (g_strcmp0 (match, "\"/edit/edit-paste-as-new\"") == 0)
{
g_string_append (new_value, "\"/edit/edit-paste-as-new-image\"");
}
/* file-export-* changes to follow file-save-* patterns. Actions
* available since GIMP 2.8, changed for 2.10 in commit 4b14ed2.
*/
else if (g_strcmp0 (match, "\"/file/file-export\"") == 0)
{
g_string_append (new_value, "\"/file/file-export-as\"");
}
else if (g_strcmp0 (match, "\"/file/file-export-to\"") == 0)
{
g_string_append (new_value, "\"/file/file-export\"");
}
else if (g_strcmp0 (match, "\"/layers/layers-text-tool\"") == 0)
{
g_string_append (new_value, "\"/layers/layers-edit\"");
}
/* plug-in-gauss doesn't exist anymore since commit ff59aebbe88.
* The expected replacement would be filters-gaussian-blur which is
* gegl:gaussian-blur operation. See also bug 775931.
*/
else if (g_strcmp0 (match, "\"/plug-in/plug-in-gauss\"") == 0)
{
g_string_append (new_value, "\"/filters/filters-gaussian-blur\"");
}
/* Tools settings renamed more user-friendly. Actions available
* since GIMP 2.4, changed for 2.10 in commit 0bdb747.
*/
else if (g_str_has_prefix (match, "\"/tools/tools-value-1-"))
{
g_string_append (new_value, "\"/tools/tools-opacity-");
g_string_append (new_value, match + 31);
}
else if (g_str_has_prefix (match, "\"/tools/tools-value-2-"))
{
g_string_append (new_value, "\"/tools/tools-size-");
g_string_append (new_value, match + 31);
}
else if (g_str_has_prefix (match, "\"/tools/tools-value-3-"))
{
g_string_append (new_value, "\"/tools/tools-aspect-");
g_string_append (new_value, match + 31);
}
else if (g_str_has_prefix (match, "\"/tools/tools-value-4-"))
{
g_string_append (new_value, "\"/tools/tools-angle-");
g_string_append (new_value, match + 31);
}
else if (g_strcmp0 (match, "\"/vectors/vectors-path-tool\"") == 0)
{
g_string_append (new_value, "\"/vectors/vectors-edit\"");
}
else if (g_strcmp0 (match, "\"/tools/tools-blend\"") == 0)
{
g_string_append (new_value, "\"/tools/tools-gradient\"");
}
/* Should not happen. Just in case we match something unexpected by
* mistake.
*/
else
{
g_message ("(WARNING) %s: invalid match \"%s\"", G_STRFUNC, match);
g_string_append (new_value, match);
}
g_free (match);
return FALSE;
}
#define CONTROLLERRC_UPDATE_PATTERN \
"\\(map \"(scroll|cursor)-[^\"]*\\bcontrol\\b[^\"]*\""
static gboolean
user_update_controllerrc (const GMatchInfo *matched_value,
GString *new_value,
gpointer data)
{
gchar *original;
gchar *replacement;
GRegex *regexp = NULL;
/* No need of a complicated pattern here.
* CONTROLLERRC_UPDATE_PATTERN took care of it first.
*/
regexp = g_regex_new ("\\bcontrol\\b", 0, 0, NULL);
original = g_match_info_fetch (matched_value, 0);
replacement = g_regex_replace (regexp, original, -1, 0,
"primary", 0, NULL);
g_string_append (new_value, replacement);
g_free (original);
g_free (replacement);
g_regex_unref (regexp);
return FALSE;
}
#define GIMPRC_UPDATE_PATTERN \
"\\(theme [^)]*\\)" "|" \
"\\(.*-path [^)]*\\)"
static gboolean
user_update_gimprc (const GMatchInfo *matched_value,
GString *new_value,
gpointer data)
{
/* Do not migrate paths and themes from GIMP < 2.10. */
return FALSE;
}
#define GIMPRESSIONIST_UPDATE_PATTERN \
"selectedbrush=Brushes/paintbrush.pgm"
static gboolean
user_update_gimpressionist (const GMatchInfo *matched_value,
GString *new_value,
gpointer data)
{
gchar *match = g_match_info_fetch (matched_value, 0);
/* See bug 791934: both brushes are identical. */
if (g_strcmp0 (match, "selectedbrush=Brushes/paintbrush.pgm") == 0)
{
g_string_append (new_value, "selectedbrush=Brushes/paintbrush01.pgm");
}
else
{
g_message ("(WARNING) %s: invalid match \"%s\"", G_STRFUNC, match);
g_string_append (new_value, match);
}
g_free (match);
return FALSE;
}
#define TOOL_PRESETS_UPDATE_PATTERN \
"GimpImageMapOptions" "|" \
"GimpBlendOptions" "|" \
"gimp-blend-tool" "|" \
"gimp-tool-blend"
static gboolean
user_update_tool_presets (const GMatchInfo *matched_value,
GString *new_value,
gpointer data)
{
gchar *match = g_match_info_fetch (matched_value, 0);
if (g_strcmp0 (match, "GimpImageMapOptions") == 0)
{
g_string_append (new_value, "GimpFilterOptions");
}
else if (g_strcmp0 (match, "GimpBlendOptions") == 0)
{
g_string_append (new_value, "GimpGradientOptions");
}
else if (g_strcmp0 (match, "gimp-blend-tool") == 0)
{
g_string_append (new_value, "gimp-gradient-tool");
}
else if (g_strcmp0 (match, "gimp-tool-blend") == 0)
{
g_string_append (new_value, "gimp-tool-gradient");
}
else
{
g_message ("(WARNING) %s: invalid match \"%s\"", G_STRFUNC, match);
g_string_append (new_value, match);
}
g_free (match);
return FALSE;
}
/* Actually not only for contextrc, but all other files where
* gimp-blend-tool may appear. Apparently that is also "devicerc", as
* well as "toolrc" (but this one is skipped anyway).
*/
#define CONTEXTRC_UPDATE_PATTERN "gimp-blend-tool"
static gboolean
user_update_contextrc_over20 (const GMatchInfo *matched_value,
GString *new_value,
gpointer data)
{
gchar *match = g_match_info_fetch (matched_value, 0);
if (g_strcmp0 (match, "gimp-blend-tool") == 0)
{
g_string_append (new_value, "gimp-gradient-tool");
}
else
{
g_message ("(WARNING) %s: invalid match \"%s\"", G_STRFUNC, match);
g_string_append (new_value, match);
}
g_free (match);
return FALSE;
}
static gboolean
user_install_dir_copy (GimpUserInstall *install,
gint level,
const gchar *source,
const gchar *base,
const gchar *update_pattern,
GRegexEvalCallback update_callback)
{
GDir *source_dir = NULL;
GDir *dest_dir = NULL;
gchar dest[1024];
const gchar *basename;
gchar *dirname = NULL;
gchar *name;
GError *error = NULL;
gboolean success = FALSE;
if (level >= 5)
{
/* Config migration is recursive, but we can't go on forever,
* since we may fall into recursive symlinks in particular (which
* is a security risk to fill a disk, and would also block GIMP
* forever at migration stage).
* Let's just break the recursivity at 5 levels, which is just an
* arbitrary value (but I don't think there should be any data
* deeper than this).
*/
goto error;
}
name = g_path_get_basename (source);
dirname = g_build_filename (base, name, NULL);
g_free (name);
success = user_install_mkdir (install, dirname);
if (! success)
goto error;
success = (dest_dir = g_dir_open (dirname, 0, &error)) != NULL;
if (! success)
goto error;
success = (source_dir = g_dir_open (source, 0, &error)) != NULL;
if (! success)
goto error;
while ((basename = g_dir_read_name (source_dir)) != NULL)
{
name = g_build_filename (source, basename, NULL);
if (g_file_test (name, G_FILE_TEST_IS_REGULAR))
{
g_snprintf (dest, sizeof (dest), "%s%c%s",
dirname, G_DIR_SEPARATOR, basename);
success = user_install_file_copy (install, name, dest,
update_pattern,
update_callback);
if (! success)
{
g_free (name);
goto error;
}
}
else
{
user_install_dir_copy (install, level + 1, name, dirname,
update_pattern, update_callback);
}
g_free (name);
}
error:
user_install_log_error (install, &error);
if (source_dir)
g_dir_close (source_dir);
if (dest_dir)
g_dir_close (dest_dir);
if (dirname)
g_free (dirname);
return success;
}
static gboolean
user_install_create_files (GimpUserInstall *install)
{
gchar dest[1024];
gchar source[1024];
gint i;
for (i = 0; i < G_N_ELEMENTS (gimp_user_install_items); i++)
{
g_snprintf (dest, sizeof (dest), "%s%c%s",
gimp_directory (),
G_DIR_SEPARATOR,
gimp_user_install_items[i].name);
if (g_file_test (dest, G_FILE_TEST_EXISTS))
continue;
switch (gimp_user_install_items[i].action)
{
case USER_INSTALL_MKDIR:
if (! user_install_mkdir (install, dest))
return FALSE;
break;
case USER_INSTALL_COPY:
g_snprintf (source, sizeof (source), "%s%c%s",
gimp_sysconf_directory (), G_DIR_SEPARATOR,
gimp_user_install_items[i].name);
if (! user_install_file_copy (install, source, dest, NULL, NULL))
return FALSE;
break;
}
}
g_snprintf (dest, sizeof (dest), "%s%c%s",
gimp_directory (), G_DIR_SEPARATOR, "tags.xml");
if (! g_file_test (dest, G_FILE_TEST_IS_REGULAR))
{
/* if there was no tags.xml, install it with default tag set.
*/
if (! gimp_tags_user_install ())
{
return FALSE;
}
}
return TRUE;
}
static gboolean
user_install_migrate_files (GimpUserInstall *install)
{
GDir *dir;
const gchar *basename;
gchar dest[1024];
GimpRc *gimprc;
GError *error = NULL;
dir = g_dir_open (install->old_dir, 0, &error);
if (! dir)
{
user_install_log_error (install, &error);
return FALSE;
}
while ((basename = g_dir_read_name (dir)) != NULL)
{
gchar *source = g_build_filename (install->old_dir, basename, NULL);
if (g_file_test (source, G_FILE_TEST_IS_REGULAR))
{
const gchar *update_pattern = NULL;
GRegexEvalCallback update_callback = NULL;
/* skip these files for all old versions */
if (strcmp (basename, "documents") == 0 ||
g_str_has_prefix (basename, "gimpswap.") ||
strcmp (basename, "pluginrc") == 0 ||
strcmp (basename, "themerc") == 0 ||
strcmp (basename, "toolrc") == 0)
{
goto next_file;
}
else if (strcmp (basename, "menurc") == 0)
{
switch (install->old_minor)
{
case 0:
/* skip menurc for gimp 2.0 as the format has changed */
goto next_file;
break;
default:
update_pattern = MENURC_OVER20_UPDATE_PATTERN;
update_callback = user_update_menurc_over20;
break;
}
}
else if (strcmp (basename, "controllerrc") == 0)
{
update_pattern = CONTROLLERRC_UPDATE_PATTERN;
update_callback = user_update_controllerrc;
}
else if (strcmp (basename, "gimprc") == 0)
{
update_pattern = GIMPRC_UPDATE_PATTERN;
update_callback = user_update_gimprc;
}
else if (strcmp (basename, "contextrc") == 0 ||
strcmp (basename, "devicerc") == 0)
{
update_pattern = CONTEXTRC_UPDATE_PATTERN;
update_callback = user_update_contextrc_over20;
}
g_snprintf (dest, sizeof (dest), "%s%c%s",
gimp_directory (), G_DIR_SEPARATOR, basename);
user_install_file_copy (install, source, dest,
update_pattern, update_callback);
}
else if (g_file_test (source, G_FILE_TEST_IS_DIR))
{
const gchar *update_pattern = NULL;
GRegexEvalCallback update_callback = NULL;
/* skip these directories for all old versions */
if (strcmp (basename, "tmp") == 0 ||
strcmp (basename, "tool-options") == 0 ||
strcmp (basename, "themes") == 0)
{
goto next_file;
}
if (strcmp (basename, "gimpressionist") == 0)
{
update_pattern = GIMPRESSIONIST_UPDATE_PATTERN;
update_callback = user_update_gimpressionist;
}
else if (strcmp (basename, "tool-presets") == 0)
{
update_pattern = TOOL_PRESETS_UPDATE_PATTERN;
update_callback = user_update_tool_presets;
}
user_install_dir_copy (install, 0, source, gimp_directory (),
update_pattern, update_callback);
}
next_file:
g_free (source);
}
/* create the tmp directory that was explicitly not copied */
g_snprintf (dest, sizeof (dest), "%s%c%s",
gimp_directory (), G_DIR_SEPARATOR, "tmp");
user_install_mkdir (install, dest);
g_dir_close (dir);
gimp_templates_migrate (install->old_dir);
gimprc = gimp_rc_new (install->gimp, NULL, NULL, FALSE);
gimp_rc_migrate (gimprc);
gimp_rc_save (gimprc);
g_object_unref (gimprc);
return TRUE;
}