diff --git a/src/rime/lever/deployment_tasks.cc b/src/rime/lever/deployment_tasks.cc index 5e2e6d9d5..639db48ac 100644 --- a/src/rime/lever/deployment_tasks.cc +++ b/src/rime/lever/deployment_tasks.cc @@ -4,6 +4,7 @@ // // 2011-12-10 GONG Chen // +#include #include #include #include @@ -30,6 +31,51 @@ namespace fs = boost::filesystem; namespace rime { +DetectModifications::DetectModifications(TaskInitializer arg) { + try { + data_dirs_ = boost::any_cast>(arg); + } + catch (const boost::bad_any_cast&) { + LOG(ERROR) << "DetectModifications: invalid arguments."; + } +} + +bool DetectModifications::Run(Deployer* deployer) { + time_t last_modified = 0; + try { + for (auto dir : data_dirs_) { + fs::path p = fs::canonical(dir); + last_modified = (std::max)(last_modified, fs::last_write_time(p)); + if (fs::is_directory(p)) { + for (fs::directory_iterator iter(p), end; iter != end; ++iter) { + fs::path entry(iter->path()); + if (fs::is_regular_file(fs::canonical(entry)) && + entry.extension().string() == ".yaml" && + entry.filename().string() != "user.yaml") { + last_modified = + (std::max)(last_modified, fs::last_write_time(entry)); + } + } + } + } + } catch(const fs::filesystem_error& ex) { + LOG(ERROR) << "Error reading file information: " << ex.what(); + return true; + } + + // TODO: store as 64-bit number to avoid the year 2038 problem + int last_build_time = 0; + { + the user_config(Config::Require("config")->Create("user")); + user_config->GetInt("var/last_build_time", &last_build_time); + } + if (last_modified > (time_t)last_build_time) { + LOG(INFO) << "modifications detected. workspace needs update."; + return true; + } + return false; +} + bool InstallationUpdate::Run(Deployer* deployer) { LOG(INFO) << "updating rime installation info."; fs::path shared_data_path(deployer->shared_data_dir); @@ -188,6 +234,11 @@ bool WorkspaceUpdate::Run(Deployer* deployer) { } LOG(INFO) << "finished updating schemas: " << success << " success, " << failure << " failure."; + + the user_config(Config::Require("config")->Create("user")); + // TODO: store as 64-bit number to avoid the year 2038 problem + user_config->SetInt("var/last_build_time", (int)time(NULL)); + return failure == 0; } @@ -263,6 +314,7 @@ bool SchemaUpdate::Run(Deployer* deployer) { LOG(INFO) << "patched copy of schema '" << schema_id << "' is moved to trash"; } + // TODO: compile the config file if needs update string dict_name; if (!config->GetString("translator/dictionary", &dict_name)) { @@ -281,6 +333,7 @@ bool SchemaUpdate::Run(Deployer* deployer) { if (verbose_) { dict_compiler.set_options(DictCompiler::kRebuild | DictCompiler::kDump); } + // TODO: use compiled schema instead of the YAML file alone if (!dict_compiler.Compile(schema_file_)) { LOG(ERROR) << "dictionary '" << dict_name << "' failed to compile."; return false; @@ -317,6 +370,7 @@ bool ConfigFileUpdate::Run(Deployer* deployer) { trash)) { LOG(INFO) << "patched copy of '" << file_name_ << "' is moved to trash."; } + // TODO: compile the config file if needs update return true; } diff --git a/src/rime/lever/deployment_tasks.h b/src/rime/lever/deployment_tasks.h index d742be68f..66a9815f0 100644 --- a/src/rime/lever/deployment_tasks.h +++ b/src/rime/lever/deployment_tasks.h @@ -7,11 +7,23 @@ #ifndef RIME_DEPLOYMENT_TASKS_H_ #define RIME_DEPLOYMENT_TASKS_H_ +#include #include namespace rime { -// initialize/update installation.yaml, default.yaml +// detects changes in either user configuration or upgraded shared data +class DetectModifications : public DeploymentTask { + public: + DetectModifications(TaskInitializer arg = TaskInitializer()); + // Unlike other tasks, its return value indicates whether modifications + // has been detected and workspace needs update. + bool Run(Deployer* deployer); + protected: + vector data_dirs_; +}; + +// initialize/update installation.yaml class InstallationUpdate : public DeploymentTask { public: InstallationUpdate(TaskInitializer arg = TaskInitializer()) {} diff --git a/src/rime/lever/levers_module.cc b/src/rime/lever/levers_module.cc index e49d9bebf..e5ad1f2d9 100644 --- a/src/rime/lever/levers_module.cc +++ b/src/rime/lever/levers_module.cc @@ -24,6 +24,7 @@ static void rime_levers_initialize() { Registry& r = Registry::instance(); // deployment tools + r.Register("detect_modifications", new Component); r.Register("installation_update", new Component); r.Register("workspace_update", new Component); r.Register("schema_update", new Component); diff --git a/src/rime_api.cc b/src/rime_api.cc index 8322040f6..02271b25e 100644 --- a/src/rime_api.cc +++ b/src/rime_api.cc @@ -105,8 +105,9 @@ RIME_API Bool RimeStartMaintenance(Bool full_check) { } if (!full_check) { TaskInitializer args{ - make_pair("default.yaml", "config_version")}; - if (!deployer.RunTask("config_file_update", args)) { + vector{deployer.user_data_dir, deployer.shared_data_dir} + }; + if (!deployer.RunTask("detect_modifications", args)) { return False; } LOG(INFO) << "changes detected; starting maintenance.";