Skip to content

Commit

Permalink
fix(config_file_update): clean up deprecated user copy (#193)
Browse files Browse the repository at this point in the history
* fix(config_file_update): trash deprecated user copy created by older rime version

* fix(config_file_update): create trash directory when needed to trash config files

* fix(config_file_update): prefer rime-installed user copy to shared minimal version if numbers match'
  • Loading branch information
lotem authored Mar 16, 2018
1 parent 6f7be0d commit 8d8d2e6
Showing 1 changed file with 57 additions and 55 deletions.
112 changes: 57 additions & 55 deletions src/rime/lever/deployment_tasks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 8d8d2e6

Please sign in to comment.