feat(core): introduce migrate cli command
This commit is contained in:
parent
f98ab3dffd
commit
2cf6cafdb6
65
Cargo.lock
generated
65
Cargo.lock
generated
|
@ -170,6 +170,32 @@ dependencies = [
|
|||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"lazy_static",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"regex",
|
||||
"terminal_size",
|
||||
"unicode-width",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_fn"
|
||||
version = "0.4.5"
|
||||
|
@ -281,6 +307,18 @@ dependencies = [
|
|||
"libdbus-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dialoguer"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9dd058f8b65922819fabb4a41e7d1964e56344042c26efbccd465202c23fa0c"
|
||||
dependencies = [
|
||||
"console",
|
||||
"lazy_static",
|
||||
"tempfile",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.12"
|
||||
|
@ -348,6 +386,12 @@ version = "1.6.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
|
||||
[[package]]
|
||||
name = "enum-as-inner"
|
||||
version = "0.3.3"
|
||||
|
@ -366,7 +410,9 @@ version = "1.0.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"colored",
|
||||
"crossbeam",
|
||||
"dialoguer",
|
||||
"dirs 3.0.1",
|
||||
"enum-as-inner",
|
||||
"espanso-clipboard",
|
||||
|
@ -376,11 +422,13 @@ dependencies = [
|
|||
"espanso-inject",
|
||||
"espanso-ipc",
|
||||
"espanso-match",
|
||||
"espanso-migrate",
|
||||
"espanso-modulo",
|
||||
"espanso-path",
|
||||
"espanso-render",
|
||||
"espanso-ui",
|
||||
"fs2",
|
||||
"fs_extra",
|
||||
"html2text",
|
||||
"lazy_static",
|
||||
"log",
|
||||
|
@ -392,6 +440,7 @@ dependencies = [
|
|||
"serde_json",
|
||||
"serde_yaml",
|
||||
"simplelog",
|
||||
"tempdir",
|
||||
"thiserror",
|
||||
"winapi",
|
||||
]
|
||||
|
@ -1554,6 +1603,16 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-case"
|
||||
version = "1.1.0"
|
||||
|
@ -1811,6 +1870,12 @@ dependencies = [
|
|||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd"
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.5.12"
|
||||
|
|
|
@ -31,6 +31,7 @@ espanso-render = { path = "../espanso-render" }
|
|||
espanso-path = { path = "../espanso-path" }
|
||||
espanso-ipc = { path = "../espanso-ipc" }
|
||||
espanso-modulo = { path = "../espanso-modulo", optional = true }
|
||||
espanso-migrate = { path = "../espanso-migrate" }
|
||||
maplit = "1.0.2"
|
||||
simplelog = "0.9.0"
|
||||
log = "0.4.14"
|
||||
|
@ -48,6 +49,10 @@ html2text = "0.2.1"
|
|||
log-panics = "2.0.0"
|
||||
fs2 = "0.4.3"
|
||||
serde_yaml = "0.8.17"
|
||||
fs_extra = "1.2.0"
|
||||
dialoguer = "0.8.0"
|
||||
colored = "2.0.0"
|
||||
tempdir = "0.3.7"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
named_pipe = "0.4.1"
|
||||
|
|
144
espanso/src/cli/migrate.rs
Normal file
144
espanso/src/cli/migrate.rs
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* This file is part of espanso.
|
||||
*
|
||||
* Copyright (C) 2019-2021 Federico Terzi
|
||||
*
|
||||
* espanso is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* espanso is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::{CliModule, CliModuleArgs};
|
||||
use colored::*;
|
||||
use dialoguer::Confirm;
|
||||
use fs_extra::dir::CopyOptions;
|
||||
use tempdir::TempDir;
|
||||
|
||||
pub fn new() -> CliModule {
|
||||
CliModule {
|
||||
requires_paths: true,
|
||||
requires_config: true,
|
||||
subcommand: "migrate".to_string(),
|
||||
entry: migrate_main,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn migrate_main(args: CliModuleArgs) -> i32 {
|
||||
let paths = args.paths.expect("missing paths argument");
|
||||
|
||||
if !args.is_legacy_config {
|
||||
eprintln!("Can't migrate configurations, as the default directory [1] is already encoded with the new format");
|
||||
eprintln!("[1]: {:?}", paths.config);
|
||||
eprintln!("The migration tool is only meant to convert the espanso's legacy configuration format (prior to");
|
||||
eprintln!("version 0.7.3) to the new one (since version 2.0)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO: check if legacy version is still running
|
||||
|
||||
let target_backup_dir = find_available_backup_dir();
|
||||
|
||||
println!("\n{}\n", "Welcome to espanso v2!".bold());
|
||||
println!("This migration tool will help you to smoothly transition to the new espanso v2 configuration format.");
|
||||
println!("");
|
||||
println!(
|
||||
"1. Firstly, espanso will {} your current configuration, located in:\n",
|
||||
"backup".green().bold()
|
||||
);
|
||||
println!(" {}\n", paths.config.to_string_lossy().italic());
|
||||
println!(" into this folder:\n");
|
||||
println!(" {}\n", target_backup_dir.to_string_lossy().italic());
|
||||
println!(
|
||||
"2. Then, it will {} your configuration to the new format, replacing",
|
||||
"convert".bold().green()
|
||||
);
|
||||
println!(" the current content of the config directory.");
|
||||
println!("");
|
||||
|
||||
if !Confirm::new()
|
||||
.with_prompt("Do you want to proceed?")
|
||||
.default(true)
|
||||
.interact()
|
||||
.expect("unable to read choice")
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
println!("Backing up your configuration...");
|
||||
|
||||
fs_extra::dir::copy(
|
||||
&paths.config,
|
||||
&target_backup_dir,
|
||||
&CopyOptions {
|
||||
copy_inside: true,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.expect("unable to backup the current config");
|
||||
println!("{}", "Backup completed!".green());
|
||||
|
||||
println!("Converting the configuration...");
|
||||
let temp_dir = TempDir::new("espanso-migrate-out").expect("unable to create temporary directory");
|
||||
let temp_out_dir = temp_dir.path().join("out");
|
||||
espanso_migrate::migrate(&paths.config, &paths.packages, &temp_out_dir)
|
||||
.expect("an error occurred while converting the configuration");
|
||||
println!("{}", "Conversion completed!".green());
|
||||
|
||||
println!("Replacing old configuration with the new one...");
|
||||
|
||||
let mut to_be_removed = Vec::new();
|
||||
let legacy_dir_content = fs_extra::dir::get_dir_content(&paths.config).expect("unable to list legacy dir files");
|
||||
to_be_removed.extend(legacy_dir_content.files);
|
||||
to_be_removed.extend(legacy_dir_content.directories);
|
||||
fs_extra::remove_items(&to_be_removed).expect("unable to remove previous configuration");
|
||||
fs_extra::dir::copy(
|
||||
&temp_out_dir,
|
||||
&paths.config,
|
||||
&CopyOptions {
|
||||
copy_inside: true,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.expect("unable to copy new configuration into target location");
|
||||
|
||||
let target_packages_dir = &paths.config.join("match").join("packages");
|
||||
if !target_packages_dir.is_dir() {
|
||||
std::fs::create_dir_all(target_packages_dir).expect("unable to create new packages directory");
|
||||
}
|
||||
|
||||
println!("{}", "Configuration successfully migrated!".green());
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
fn find_available_backup_dir() -> PathBuf {
|
||||
for i in 1..20 {
|
||||
let num = if i > 1 {
|
||||
format!("-{}", i)
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
|
||||
let target_backup_dir = dirs::document_dir()
|
||||
.expect("unable to generate backup directory")
|
||||
.join(format!("espanso-migrate-backup{}", num));
|
||||
|
||||
if !target_backup_dir.is_dir() {
|
||||
return target_backup_dir;
|
||||
}
|
||||
}
|
||||
|
||||
panic!("could not generate valid backup directory");
|
||||
}
|
|
@ -23,6 +23,7 @@ use espanso_path::Paths;
|
|||
|
||||
pub mod daemon;
|
||||
pub mod log;
|
||||
pub mod migrate;
|
||||
pub mod modulo;
|
||||
pub mod path;
|
||||
pub mod worker;
|
||||
|
|
|
@ -27,7 +27,7 @@ use std::path::PathBuf;
|
|||
|
||||
use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
|
||||
use cli::{CliModule, CliModuleArgs};
|
||||
use log::{error, info};
|
||||
use log::{error, info, warn};
|
||||
use logging::FileProxy;
|
||||
use simplelog::{
|
||||
CombinedLogger, ConfigBuilder, LevelFilter, TermLogger, TerminalMode, WriteLogger,
|
||||
|
@ -55,6 +55,7 @@ lazy_static! {
|
|||
cli::worker::new(),
|
||||
cli::daemon::new(),
|
||||
cli::modulo::new(),
|
||||
cli::migrate::new(),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -218,6 +219,10 @@ fn main() {
|
|||
)
|
||||
.subcommand(SubCommand::with_name("base").about("Print the default match file path.")),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("migrate")
|
||||
.about("Automatically migrate legacy config files to the new v2 format.")
|
||||
)
|
||||
// .subcommand(SubCommand::with_name("match")
|
||||
// .about("List and execute matches from the CLI")
|
||||
// .subcommand(SubCommand::with_name("list")
|
||||
|
@ -353,6 +358,11 @@ fn main() {
|
|||
cli_args.is_legacy_config = is_legacy_config;
|
||||
cli_args.config_store = Some(config_store);
|
||||
cli_args.match_store = Some(match_store);
|
||||
|
||||
if is_legacy_config {
|
||||
warn!("espanso is reading the configuration using compatibility mode, thus some features might not be available");
|
||||
warn!("you can migrate to the new configuration format by running 'espanso migrate' in a terminal");
|
||||
}
|
||||
}
|
||||
|
||||
if handler.enable_logs {
|
||||
|
|
Loading…
Reference in New Issue
Block a user