r23291 - gnucash/trunk/src - Prefs migration improvements
Geert Janssens
gjanssens at code.gnucash.org
Wed Oct 16 11:22:06 EDT 2013
Author: gjanssens
Date: 2013-10-16 11:22:04 -0400 (Wed, 16 Oct 2013)
New Revision: 23291
Trac: http://svn.gnucash.org/trac/changeset/23291
Modified:
gnucash/trunk/src/app-utils/gnc-gsettings.c
gnucash/trunk/src/app-utils/make-prefs-migration-script.xsl
gnucash/trunk/src/app-utils/migrate-prefs.scm
gnucash/trunk/src/gnome/gschemas/org.gnucash.gschema.xml.in
Log:
Prefs migration improvements
- check if all parents of .gconf/apps/gnucash exist before attempting migration
- wrap guile parts in catch/throw handlers to prevent GnuCash from crashing
if something goes wrong during the prefereces migration
- add more sanity checks and debugging information
- set flag after first successful migration to prevent future runs
Modified: gnucash/trunk/src/app-utils/gnc-gsettings.c
===================================================================
--- gnucash/trunk/src/app-utils/gnc-gsettings.c 2013-10-13 17:11:39 UTC (rev 23290)
+++ gnucash/trunk/src/app-utils/gnc-gsettings.c 2013-10-16 15:22:04 UTC (rev 23291)
@@ -47,12 +47,14 @@
#define CLIENT_TAG "%s-%s-client"
#define NOTIFY_TAG "%s-%s-notify_id"
+#define GNC_PREF_MIGRATE_PREFS_DONE "migrate-prefs-done"
+
static GHashTable *schema_hash = NULL;
static const gchar *gsettings_prefix;
static xmlExternalEntityLoader defaultEntityLoader = NULL;
/* This static indicates the debugging module that this .o belongs to. */
-static QofLogModule log_module = G_LOG_DOMAIN;
+static QofLogModule log_module = "gnc.app-utils.gsettings";
/************************************************************/
/* Internal helper functions */
@@ -615,26 +617,43 @@
return(NULL);
}
-
+/* Tool to migrate existing user settings from GConf to GSettings
+ *
+ * This tool will first run some sanity checks to see if migration
+ * is necessary/possible. The actual migration works directly from
+ * the GConf .xml files. Using an xsl transform it will convert them
+ * in a guile script to set most settings found.
+ *
+ * Notes:
+ * - due to some limitations in the xslt code, all the gconf xml files are
+ * first copied into a temporary directory. After the migration has finished,
+ * that temporary directory and its contents are removed.
+ * - not all settings can be migrated. All the important ones are though.
+ * The ones that are missing are mostly with respect to window position
+ * and size.
+ * - column widths/visibilities, sorting orders,... are no longer stored
+ * in gsettings, so these will obviously not be migrated either.
+ * - upon a successful run, a flag will be set to prevent the migration
+ * from running again. So in normal circumstances the migration will
+ * be executed only once.
+ */
void gnc_gsettings_migrate_from_gconf (void)
{
gchar *pkgdatadir, *stylesheet, *input, *output, *command;
+ gchar *gconf_root, *gconf_apps, *gconf_gnucash;
gchar *base_dir, *iter;
SCM migr_script, result;
xsltStylesheetPtr stylesheetptr = NULL;
xmlDocPtr inputxml, transformedxml;
FILE *outfile;
+ gboolean migration_ok = FALSE;
- pkgdatadir = gnc_path_get_pkgdatadir();
- stylesheet = g_build_filename(pkgdatadir, "make-prefs-migration-script.xsl", NULL);
- input = g_build_filename(pkgdatadir, "migratable-prefs.xml", NULL);
+ ENTER ();
- if ((!g_file_test (stylesheet, G_FILE_TEST_IS_REGULAR)) ||
- (!g_file_test (input, G_FILE_TEST_IS_REGULAR)))
+ /* Only attempt to migrate if no successful migration has been done before */
+ if (gnc_gsettings_get_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_MIGRATE_PREFS_DONE))
{
- /* Critical files not found, abort migration */
- g_free (stylesheet);
- g_free (input);
+ LEAVE ("Preferences migration ran successfully before. Skipping.");
return;
}
@@ -645,13 +664,59 @@
*iter = '/';
}
+ /* Only attempt to migrate if there is something to migrate */
+ gconf_root = g_build_filename(base_dir, ".gconf", NULL);
+ gconf_apps = g_build_filename(gconf_root, "apps", NULL);
+ gconf_gnucash = g_build_filename(gconf_apps, "gnucash", NULL);
+ migration_ok = (g_file_test (gconf_root, G_FILE_TEST_IS_DIR) &&
+ g_file_test (gconf_apps, G_FILE_TEST_IS_DIR) &&
+ g_file_test (gconf_gnucash, G_FILE_TEST_IS_DIR));
+ g_free (gconf_root);
+ g_free (gconf_apps);
+ g_free (gconf_gnucash);
+ if (!migration_ok)
+ {
+ g_free (base_dir);
+ gnc_gsettings_set_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_MIGRATE_PREFS_DONE, TRUE);
+ LEAVE ("No pre-existing GConf gnucash section found.\n"
+ "Most likely this system never ran GnuCash before.\n"
+ "Assume migration is not needed.");
+ return;
+ }
+
+ pkgdatadir = gnc_path_get_pkgdatadir();
+ stylesheet = g_build_filename(pkgdatadir, "make-prefs-migration-script.xsl", NULL);
+ input = g_build_filename(pkgdatadir, "migratable-prefs.xml", NULL);
+ g_free (pkgdatadir);
+
+ migration_ok = (g_file_test (stylesheet, G_FILE_TEST_IS_REGULAR) &&
+ g_file_test (input, G_FILE_TEST_IS_REGULAR));
+ if (!migration_ok)
+ {
+ /* Critical files not found, abort migration */
+ g_free (base_dir);
+ g_free (stylesheet);
+ g_free (input);
+ LEAVE ("Migration input file and stylesheet missing. Skip migration.");
+ return;
+ }
+
command = g_strconcat ("(use-modules (migrate-prefs))(migration-prepare \"",
base_dir, "\")", NULL);
DEBUG ("command = %s", command);
- result = scm_c_eval_string (command);
+ migration_ok = scm_is_true (scm_c_eval_string (command));
g_free (command);
+ if (!migration_ok)
+ {
+ /* Preparation step failed */
+ g_free (base_dir);
+ g_free (stylesheet);
+ g_free (input);
+ LEAVE ("Migration preparation step failed. Skip migration.");
+ return;
+ }
- output = g_build_filename(base_dir, ".gnc-migration-tmp", "migrate-prefs-user.scm", NULL);
+ output = g_build_filename(base_dir, ".gnc-migration-tmp", "migrate-prefs-user.scm", NULL);
xmlSubstituteEntitiesDefault(1);
xmlLoadExtDtdDefaultValue = 1;
defaultEntityLoader = xmlGetExternalEntityLoader();
@@ -664,27 +729,46 @@
xsltSaveResultToFile(outfile, transformedxml, stylesheetptr);
fclose(outfile);
- migr_script = scm_from_locale_string (output);
- scm_primitive_load (migr_script);
- result = scm_c_eval_string ("(use-modules (migrate-prefs-user))(run-migration)");
-
xsltFreeStylesheet(stylesheetptr);
xmlFreeDoc(inputxml);
xmlFreeDoc(transformedxml);
xsltCleanupGlobals();
xmlCleanupParser();
+ g_free (stylesheet);
+ g_free (input);
+ migr_script = scm_from_locale_string (output);
+ scm_primitive_load (migr_script);
+ g_free (output);
+
+ migration_ok = scm_is_true (scm_c_eval_string ("(use-modules (migrate-prefs-user))(run-migration)"));
+ if (!migration_ok)
+ {
+ /* Actual migration step failed */
+ g_free (base_dir);
+ LEAVE ("Actual migration step failed. Skip migration.");
+ return;
+ }
+
+ /* If we got here, the preferences were migrated successfully
+ * Mark this success in gsettings, so we won't run the migration again.
+ */
+ gnc_gsettings_set_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_MIGRATE_PREFS_DONE, TRUE);
+
+ /* All that is left now is to cleanup... */
command = g_strconcat ("(use-modules (migrate-prefs))(migration-cleanup \"",
base_dir, "\")", NULL);
DEBUG ("command = %s", command);
- result = scm_c_eval_string (command);
+ migration_ok = scm_is_true (scm_c_eval_string (command));
g_free (command);
+ if (!migration_ok)
+ {
+ /* Actual migration step failed */
+ DEBUG ("Cleanup step failed. You may need to delete %s/.gnc-migration-tmp manually.", base_dir);
+ }
- g_free (pkgdatadir);
- g_free (stylesheet);
- g_free (input);
- g_free (output);
+ LEAVE ("");
g_free (base_dir);
}
Modified: gnucash/trunk/src/app-utils/make-prefs-migration-script.xsl
===================================================================
--- gnucash/trunk/src/app-utils/make-prefs-migration-script.xsl 2013-10-13 17:11:39 UTC (rev 23290)
+++ gnucash/trunk/src/app-utils/make-prefs-migration-script.xsl 2013-10-16 15:22:04 UTC (rev 23291)
@@ -34,7 +34,7 @@
; (load-extension "libgnc-core-utils" "scm_init_sw_core_utils_module")))
;(use-modules (sw_core_utils))
-(define (run-migration)
+(define (run-migration-internal)
<xsl:for-each select="//prefsgroup">
<xsl:if test="document(gconfpath)//entry">
;; Processing preferences in group <xsl:value-of select="gschemaid"/>
@@ -47,6 +47,17 @@
(display "Preference migration has finished")(newline)
)
+(define (run-migration)
+ (catch #t
+ run-migration-internal
+ (lambda args
+ (display (string-append
+ "An error occurred while migrating preferences."
+ (newline) "The error is: "
+ (symbol->string key) " - " (car (caddr args)) "."))
+ #f))
+)
+
(export run-migration)
</xsl:template>
Modified: gnucash/trunk/src/app-utils/migrate-prefs.scm
===================================================================
--- gnucash/trunk/src/app-utils/migrate-prefs.scm 2013-10-13 17:11:39 UTC (rev 23290)
+++ gnucash/trunk/src/app-utils/migrate-prefs.scm 2013-10-16 15:22:04 UTC (rev 23291)
@@ -66,27 +66,33 @@
; cleanup first if a previous migration attempt failed to do so
(if (access? migration-dir (logior R_OK W_OK X_OK))
(begin
- (format #t "Clear previous tmp dir ~A\n" migration-dir)
+ (format #t "Clear previous migration tmp dir ~A\n" migration-dir)
(migration-cleanup-internal)))
+ (display "*** GnuCash switched to a new preferences system ***\n")
+ (display "Attempt to migrate your preferences from the old to the new system\n")
(mkdir migration-dir)
(format #t "Copy all gconf files to tmp dir ~A\n" migration-dir)
(display "Note: you can ignore the failed to load extnral entity warnings below. They are harmless.\n")
(apply find copy-one-file (list gconf-dir))
+ ; Indicate successful preparation
+ #t
)
(define (migration-prepare base-dir)
(set! gconf-dir (string-append base-dir "/.gconf/apps/gnucash"))
+ ; Note: calling script should already have checked whether
+ ; gconf-dir and its parent directories exist
(set! prefix-length (+ (string-length gconf-dir) 1))
(set! migration-dir (string-append base-dir "/.gnc-migration-tmp"))
- (if (access? gconf-dir R_OK)
- (begin
- (display "*** GnuCash switched to a new preferences system ***\n")
- (display "Attempt to migrate your preferences from the old to the new system\n")
- (catch #t
- migration-prepare-internal
- (lambda args
- (display "An error occurred when trying to migrate preferences")))
- )))
+ (catch #t
+ migration-prepare-internal
+ (lambda args
+ (display (string-append
+ "An error occurred while preparing to migrate preferences."
+ (newline) "The error is: "
+ (symbol->string key) " - " (car (caddr args)) "."))
+ #f))
+)
(define (rmtree args)
(define (zap f)
@@ -99,13 +105,23 @@
(define (migration-cleanup-internal)
(rmtree (list migration-dir))
- (rmdir migration-dir))
+ (rmdir migration-dir)
+ ; Indicate successful cleanup
+ #t)
(define (migration-cleanup base-dir)
(set! migration-dir (string-append base-dir "/.gnc-migration-tmp"))
(if (access? migration-dir (logior R_OK W_OK X_OK))
(begin
(format #t "Delete tmp dir ~A\n" migration-dir)
- (migration-cleanup-internal))))
+ (catch #t
+ migration-cleanup-internal
+ (lambda args
+ (display (string-append
+ "An error occurred while cleaning up after preferences migration."
+ (newline) "The error is: "
+ (symbol->string key) " - " (car (caddr args)) "."))
+ #f))))
+)
(export migration-prepare migration-cleanup)
\ No newline at end of file
Modified: gnucash/trunk/src/gnome/gschemas/org.gnucash.gschema.xml.in
===================================================================
--- gnucash/trunk/src/gnome/gschemas/org.gnucash.gschema.xml.in 2013-10-13 17:11:39 UTC (rev 23290)
+++ gnucash/trunk/src/gnome/gschemas/org.gnucash.gschema.xml.in 2013-10-16 15:22:04 UTC (rev 23291)
@@ -3,6 +3,7 @@
<child name="general" schema="org.gnucash.general"/>
<child name="dev" schema="org.gnucash.dev"/>
</schema>
+
<schema id="org.gnucash.general" path="/org/gnucash/general/">
<key name="save-window-geometry" type="b">
<default>true</default>
@@ -44,6 +45,11 @@
<summary>Number of automatic decimal places</summary>
<description>This field specifies the number of automatic decimal places that will be filled in.</description>
</key>
+ <key name="migrate-prefs-done" type="b">
+ <default>false</default>
+ <summary>Tool to migrate preferences from old backend (CGonf) to new one (GSettings) has run successfully.</summary>
+ <description>GnuCash switched to another backend to store user preferences between 2.4 and 2.6. To smooth the transition, most preferences will be migrated the first time a 2.6 version of GnuCash is run. This migration should only run once. This preference keeps track whether or not this migration tool has run successfully.</description>
+ </key>
<key name="retain-type-never" type="b">
<default>false</default>
<summary>Do not create log/backup files.</summary>
More information about the gnucash-changes
mailing list