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
This commit is contained in:
parent
468ea6df58
commit
9658e9e3b4
3 changed files with 177 additions and 3 deletions
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue