diff --git a/src/rime/lever/deployment_tasks.cc b/src/rime/lever/deployment_tasks.cc index 1431eab11..ec8f5ca93 100644 --- a/src/rime/lever/deployment_tasks.cc +++ b/src/rime/lever/deployment_tasks.cc @@ -251,55 +251,66 @@ SchemaUpdate::SchemaUpdate(TaskInitializer arg) : verbose_(false) { } } -static bool IsCustomizedCopy(const string& file_name); +static bool MaybeCreateDirectory(fs::path dir) { + if (!fs::exists(dir)) { + boost::system::error_code ec; + if (!fs::create_directories(dir, ec)) { + LOG(ERROR) << "error creating directory '" << dir.string() << "'."; + return false; + } + } + return true; +} -static bool TrashCustomizedCopy(const fs::path& shared_copy, - const fs::path& user_copy, - const string& version_key, - const fs::path& trash) { +static bool RemoveVersionSuffix(string* version, const string& suffix) { + size_t suffix_pos = version->find(suffix); + if (suffix_pos != string::npos) { + version->erase(suffix_pos); + return true; + } + return false; +} + +static bool TrashDeprecatedUserCopy(const fs::path& shared_copy, + const fs::path& user_copy, + const string& version_key, + const fs::path& trash) { if (!fs::exists(shared_copy) || !fs::exists(user_copy) || fs::equivalent(shared_copy, user_copy)) { return false; } - if (IsCustomizedCopy(user_copy.string())) { - string shared_copy_version; - string user_copy_version; - Config shared_config; - if (shared_config.LoadFromFile(shared_copy.string())) { - shared_config.GetString(version_key, &shared_copy_version); - } - Config user_config; - if (user_config.LoadFromFile(user_copy.string()) && - user_config.GetString(version_key, &user_copy_version)) { - size_t custom_version_suffix = user_copy_version.find(".custom."); - if (custom_version_suffix != string::npos) { - user_copy_version.erase(custom_version_suffix); - } - } - if (CompareVersionString(shared_copy_version, user_copy_version) >= 0) { - fs::path backup = trash / user_copy.filename(); - boost::system::error_code ec; - fs::rename(user_copy, backup, ec); - if (ec) { - LOG(ERROR) << "error trashing file " << user_copy.string(); - return false; - } - return true; + string shared_copy_version; + string user_copy_version; + Config shared_config; + if (shared_config.LoadFromFile(shared_copy.string())) { + shared_config.GetString(version_key, &shared_copy_version); + // treat "X.Y.minimal" as equal to (not greater than) "X.Y" + // to avoid trashing the user installed full version + RemoveVersionSuffix(&shared_copy_version, ".minimal"); + } + Config user_config; + bool is_customized_user_copy = + user_config.LoadFromFile(user_copy.string()) && + user_config.GetString(version_key, &user_copy_version) && + RemoveVersionSuffix(&user_copy_version, ".custom."); + int cmp = CompareVersionString(shared_copy_version, user_copy_version); + // rime-installed user copy of the same version should be kept for integrity. + // also it could have been manually edited by user. + if (cmp > 0 || (cmp == 0 && is_customized_user_copy)) { + if (!MaybeCreateDirectory(trash)) { + return false; } - } - return false; -} - -static bool MaybeCreateDirectory(fs::path dir) { - if (!fs::exists(dir)) { + fs::path backup = trash / user_copy.filename(); boost::system::error_code ec; - if (!fs::create_directories(dir, ec)) { - LOG(ERROR) << "error creating directory '" << dir.string() << "'."; + fs::rename(user_copy, backup, ec); + if (ec) { + LOG(ERROR) << "error trashing file " << user_copy.string(); return false; } + return true; } - return true; + return false; } bool SchemaUpdate::Run(Deployer* deployer) { @@ -416,10 +427,10 @@ bool ConfigFileUpdate::Run(Deployer* deployer) { fs::path source_config_path(shared_data_path / file_name_); fs::path dest_config_path(user_data_path / file_name_); fs::path trash = user_data_path / "trash"; - if (TrashCustomizedCopy(source_config_path, - dest_config_path, - version_key_, - trash)) { + if (TrashDeprecatedUserCopy(source_config_path, + dest_config_path, + version_key_, + trash)) { LOG(INFO) << "deprecated user copy of '" << file_name_ << "' is moved to " << trash; } @@ -523,13 +534,8 @@ bool BackupConfigFiles::Run(Deployer* deployer) { if (!fs::exists(user_data_path)) return false; fs::path backup_dir(deployer->user_data_sync_dir()); - if (!fs::exists(backup_dir)) { - boost::system::error_code ec; - if (!fs::create_directories(backup_dir, ec)) { - LOG(ERROR) << "error creating directory '" - << backup_dir.string() << "'."; - return false; - } + if (!MaybeCreateDirectory(backup_dir)) { + return false; } int success = 0, failure = 0, latest = 0, skipped = 0; for (fs::directory_iterator iter(user_data_path), end; @@ -587,12 +593,8 @@ bool CleanupTrash::Run(Deployer* deployer) { boost::ends_with(filename, ".reverse.kct") || boost::ends_with(filename, ".userdb.kct.old") || boost::ends_with(filename, ".userdb.kct.snapshot")) { - if (!success && !failure && !fs::exists(trash)) { - boost::system::error_code ec; - if (!fs::create_directories(trash, ec)) { - LOG(ERROR) << "error creating directory '" << trash.string() << "'."; - return false; - } + if (!success && !MaybeCreateDirectory(trash)) { + return false; } fs::path backup = trash / entry.filename(); boost::system::error_code ec;