247 lines
8.4 KiB
Diff
247 lines
8.4 KiB
Diff
|
From 9658e9e3b41e9f851384c2a0ddce187fd40f1414 Mon Sep 17 00:00:00 2001
|
||
|
From: Michael Gratton <mike@vee.net>
|
||
|
Date: Tue, 13 Oct 2020 23:42:53 +1100
|
||
|
Subject: [PATCH 092/124] Geary.Controller: Migrate release config if needed
|
||
|
|
||
|
If the current config directory is empty, go looking for config data
|
||
|
in other well known locations and if found, copy it all across from
|
||
|
the most recently modified directory.
|
||
|
|
||
|
This supports migrating config from non-Flatpak to Flatpak locations,
|
||
|
and release config to devel profile locations.
|
||
|
|
||
|
Fixes #326
|
||
|
---
|
||
|
.../application/application-client.vala | 28 ++++
|
||
|
.../application/application-controller.vala | 3 +
|
||
|
src/client/util/util-migrate.vala | 149 +++++++++++++++++-
|
||
|
3 files changed, 177 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/src/client/application/application-client.vala b/src/client/application/application-client.vala
|
||
|
index 9bd05c31..a61a6855 100644
|
||
|
--- a/src/client/application/application-client.vala
|
||
|
+++ b/src/client/application/application-client.vala
|
||
|
@@ -858,6 +858,34 @@ public class Application.Client : Gtk.Application {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+ /**
|
||
|
+ * Returns a set of paths of possible config locations.
|
||
|
+ *
|
||
|
+ * This is useful only for migrating configuration from
|
||
|
+ * non-Flatpak to Flatpak or release-builds to non-release builds.
|
||
|
+ */
|
||
|
+ internal GLib.File[] get_config_search_path() {
|
||
|
+ var paths = new GLib.File[] {};
|
||
|
+ var home = GLib.File.new_for_path(GLib.Environment.get_home_dir());
|
||
|
+ paths += home.get_child(
|
||
|
+ ".config"
|
||
|
+ ).get_child(
|
||
|
+ "geary"
|
||
|
+ );
|
||
|
+ paths += home.get_child(
|
||
|
+ ".var"
|
||
|
+ ).get_child(
|
||
|
+ "app"
|
||
|
+ ).get_child(
|
||
|
+ "org.gnome.Geary"
|
||
|
+ ).get_child(
|
||
|
+ "config"
|
||
|
+ ).get_child(
|
||
|
+ "geary"
|
||
|
+ );
|
||
|
+ return paths;
|
||
|
+ }
|
||
|
+
|
||
|
/**
|
||
|
* Displays an error notification.
|
||
|
*
|
||
|
diff --git a/src/client/application/application-controller.vala b/src/client/application/application-controller.vala
|
||
|
index a70b702b..2237aa61 100644
|
||
|
--- a/src/client/application/application-controller.vala
|
||
|
+++ b/src/client/application/application-controller.vala
|
||
|
@@ -182,6 +182,9 @@ internal class Application.Controller :
|
||
|
|
||
|
// Migrate configuration if necessary.
|
||
|
Util.Migrate.xdg_config_dir(config_dir, data_dir);
|
||
|
+ Util.Migrate.release_config(
|
||
|
+ application.get_config_search_path(), config_dir
|
||
|
+ );
|
||
|
|
||
|
// Hook up cert, accounts and credentials machinery
|
||
|
|
||
|
diff --git a/src/client/util/util-migrate.vala b/src/client/util/util-migrate.vala
|
||
|
index edb07b45..31109c45 100644
|
||
|
--- a/src/client/util/util-migrate.vala
|
||
|
+++ b/src/client/util/util-migrate.vala
|
||
|
@@ -1,8 +1,10 @@
|
||
|
-/* Copyright 2016 Software Freedom Conservancy Inc.
|
||
|
+/*
|
||
|
+ * Copyright © 2016 Software Freedom Conservancy Inc.
|
||
|
+ * Copyright © 2020 Michael Gratton <mike@vee.net>
|
||
|
*
|
||
|
* This software is licensed under the GNU Lesser General Public License
|
||
|
- * (version 2.1 or later). See the COPYING file in this distribution.
|
||
|
- */
|
||
|
+ * (version 2.1 or later). See the COPYING file in this distribution.
|
||
|
+n */
|
||
|
|
||
|
namespace Util.Migrate {
|
||
|
private const string GROUP = "AccountInformation";
|
||
|
@@ -102,6 +104,145 @@ namespace Util.Migrate {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+ /**
|
||
|
+ * Migrates configuration from release build locations.
|
||
|
+ *
|
||
|
+ * This will migrate configuration from release build locations to
|
||
|
+ * the current config directory, if and only if the current config
|
||
|
+ * directory is empty. For example, from the standard
|
||
|
+ * distro-package config location to the current Flatpak location,
|
||
|
+ * or from either to a development config location.
|
||
|
+ */
|
||
|
+ public static void release_config(GLib.File[] search_path,
|
||
|
+ GLib.File config_dir)
|
||
|
+ throws GLib.Error {
|
||
|
+ if (is_directory_empty(config_dir)) {
|
||
|
+ GLib.File? most_recent = null;
|
||
|
+ GLib.DateTime most_recent_modified = null;
|
||
|
+ foreach (var source in search_path) {
|
||
|
+ if (!source.equal(config_dir)) {
|
||
|
+ GLib.DateTime? src_modified = null;
|
||
|
+ try {
|
||
|
+ GLib.FileInfo? src_info = source.query_info(
|
||
|
+ GLib.FileAttribute.TIME_MODIFIED, 0
|
||
|
+ );
|
||
|
+ if (src_info != null) {
|
||
|
+ src_modified =
|
||
|
+ src_info.get_modification_date_time();
|
||
|
+ }
|
||
|
+ } catch (GLib.IOError.NOT_FOUND err) {
|
||
|
+ // fine
|
||
|
+ } catch (GLib.Error err) {
|
||
|
+ debug(
|
||
|
+ "Error querying release config dir %s: %s",
|
||
|
+ source.get_path(),
|
||
|
+ err.message
|
||
|
+ );
|
||
|
+ }
|
||
|
+ if (most_recent_modified == null ||
|
||
|
+ (src_modified != null &&
|
||
|
+ most_recent_modified.compare(src_modified) < 0)) {
|
||
|
+ most_recent = source;
|
||
|
+ most_recent_modified = src_modified;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (most_recent != null) {
|
||
|
+ try {
|
||
|
+ debug(
|
||
|
+ "Migrating release config from %s to %s",
|
||
|
+ most_recent.get_path(),
|
||
|
+ config_dir.get_path()
|
||
|
+ );
|
||
|
+ recursive_copy(most_recent, config_dir);
|
||
|
+ } catch (GLib.Error err) {
|
||
|
+ debug("Error migrating release config: %s", err.message);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ private bool is_directory_empty(GLib.File dir) {
|
||
|
+ bool is_empty = true;
|
||
|
+ GLib.FileEnumerator? existing = null;
|
||
|
+ try {
|
||
|
+ existing = dir.enumerate_children(
|
||
|
+ GLib.FileAttribute.STANDARD_TYPE, 0
|
||
|
+ );
|
||
|
+ } catch (GLib.IOError.NOT_FOUND err) {
|
||
|
+ // fine
|
||
|
+ } catch (GLib.Error err) {
|
||
|
+ debug(
|
||
|
+ "Error enumerating directory %s: %s",
|
||
|
+ dir.get_path(),
|
||
|
+ err.message
|
||
|
+ );
|
||
|
+ }
|
||
|
+
|
||
|
+ if (existing != null) {
|
||
|
+ try {
|
||
|
+ is_empty = existing.next_file() == null;
|
||
|
+ } catch (GLib.Error err) {
|
||
|
+ debug(
|
||
|
+ "Error getting next child in directory %s: %s",
|
||
|
+ dir.get_path(),
|
||
|
+ err.message
|
||
|
+ );
|
||
|
+ }
|
||
|
+
|
||
|
+ try {
|
||
|
+ existing.close();
|
||
|
+ } catch (GLib.Error err) {
|
||
|
+ debug(
|
||
|
+ "Error closing directory enumeration %s: %s",
|
||
|
+ dir.get_path(),
|
||
|
+ err.message
|
||
|
+ );
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ return is_empty;
|
||
|
+ }
|
||
|
+
|
||
|
+ private static void recursive_copy(GLib.File src,
|
||
|
+ GLib.File dest,
|
||
|
+ GLib.Cancellable? cancellable = null
|
||
|
+ ) throws GLib.Error {
|
||
|
+ switch (src.query_file_type(NONE, cancellable)) {
|
||
|
+ case DIRECTORY:
|
||
|
+ try {
|
||
|
+ dest.make_directory(cancellable);
|
||
|
+ } catch (GLib.IOError.EXISTS err) {
|
||
|
+ // fine
|
||
|
+ }
|
||
|
+ src.copy_attributes(dest, NONE, cancellable);
|
||
|
+
|
||
|
+ GLib.FileEnumerator children = src.enumerate_children(
|
||
|
+ GLib.FileAttribute.STANDARD_NAME,
|
||
|
+ NONE,
|
||
|
+ cancellable
|
||
|
+ );
|
||
|
+ GLib.FileInfo? child = children.next_file(cancellable);
|
||
|
+ while (child != null) {
|
||
|
+ recursive_copy(
|
||
|
+ src.get_child(child.get_name()),
|
||
|
+ dest.get_child(child.get_name())
|
||
|
+ );
|
||
|
+ child = children.next_file(cancellable);
|
||
|
+ }
|
||
|
+ break;
|
||
|
+
|
||
|
+ case REGULAR:
|
||
|
+ src.copy(dest, NONE, cancellable);
|
||
|
+ break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ // no-op
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
public const string OLD_APP_ID = "org.yorba.geary";
|
||
|
private const string MIGRATED_CONFIG_KEY = "migrated-config";
|
||
|
|
||
|
@@ -130,4 +271,6 @@ namespace Util.Migrate {
|
||
|
|
||
|
newSettings.set_boolean(MIGRATED_CONFIG_KEY, true);
|
||
|
}
|
||
|
+
|
||
|
+
|
||
|
}
|
||
|
--
|
||
|
2.29.2
|
||
|
|