Gimp/app/core/gimp-user-install.c
Michael Natterer 46127dc789 Move gimpdir and thumbnails to proper places on OSX
gimpdir goes to ~/Library/Gimp/x.y
thumbnails go to ~/Library/Caches/org.freedesktop.thumbnails

The thumbnail location is not standardized yet, but is the only
location that makes sense. Also fix user install to search old
gimpdirs to migrate in both Library and the classic location.
Remove the obsolete CABON_CFLAGS from all makefiles.
(cherry picked from commit 9112d68488)
2012-05-12 14:44:08 +02:00

584 lines
15 KiB
C

/* 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 <http://www.gnu.org/licenses/>.
*/
/* 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 <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <glib/gstdio.h>
#include <glib-object.h>
#ifdef G_OS_WIN32
#include <libgimpbase/gimpwin32-io.h>
#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
{
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[] =
{
{ "gtkrc", USER_INSTALL_COPY },
{ "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 },
{ "tmp", USER_INSTALL_MKDIR },
{ "curves", USER_INSTALL_MKDIR },
{ "levels", USER_INSTALL_MKDIR },
{ "fractalexplorer", USER_INSTALL_MKDIR },
{ "gfig", USER_INSTALL_MKDIR },
{ "gflare", USER_INSTALL_MKDIR },
{ "gimpressionist", USER_INSTALL_MKDIR }
};
static gboolean gimp_user_install_detect_old (GimpUserInstall *install,
const gchar *gimp_dir);
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);
static gboolean user_install_dir_copy (GimpUserInstall *install,
const gchar *source,
const gchar *base);
static gboolean user_install_create_files (GimpUserInstall *install);
static gboolean user_install_migrate_files (GimpUserInstall *install);
GimpUserInstall *
gimp_user_install_new (gboolean verbose)
{
GimpUserInstall *install = g_slice_new0 (GimpUserInstall);
install->verbose = verbose;
gimp_user_install_detect_old (install, gimp_directory ());
#ifdef PLATFORM_OSX
if (! install->old_dir)
{
/* if the default old gimpdir was not found, try the "classic" one
* in the home folder
*/
gchar *dir = g_strdup_printf ("%s/.gimp-%s",
g_get_home_dir (), GIMP_APP_VERSION);
gimp_user_install_detect_old (install, dir);
g_free (dir);
}
#endif
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
gimp_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 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)
{
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, &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;
}
static gboolean
user_install_dir_copy (GimpUserInstall *install,
const gchar *source,
const gchar *base)
{
GDir *source_dir = NULL;
GDir *dest_dir = NULL;
gchar dest[1024];
const gchar *basename;
gchar *dirname;
gboolean success;
GError *error = NULL;
{
gchar *basename = g_path_get_basename (source);
dirname = g_build_filename (base, basename, NULL);
g_free (basename);
}
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)
{
gchar *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);
if (! user_install_file_copy (install, name, dest))
{
g_free (name);
goto error;
}
}
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);
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))
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))
{
/* 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;
}
/* skip menurc for gimp 2.0 as the format has changed */
if (install->old_minor == 0 && strcmp (basename, "menurc") == 0)
{
goto next_file;
}
g_snprintf (dest, sizeof (dest), "%s%c%s",
gimp_directory (), G_DIR_SEPARATOR, basename);
user_install_file_copy (install, source, dest);
}
else if (g_file_test (source, G_FILE_TEST_IS_DIR))
{
/* skip these directories for all old versions */
if (strcmp (basename, "tmp") == 0 ||
strcmp (basename, "tool-options") == 0)
{
goto next_file;
}
user_install_dir_copy (install, source, gimp_directory ());
}
next_file:
g_free (source);
}
/* create the tmp directory that was explicitely 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 (NULL, NULL, FALSE);
gimp_rc_migrate (gimprc);
gimp_rc_save (gimprc);
g_object_unref (gimprc);
return TRUE;
}