feat(core): implement first draft of package install command
This commit is contained in:
parent
5714ebe131
commit
55c8ba6b75
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -784,12 +784,14 @@ name = "espanso-package"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"fs_extra",
|
||||
"glob",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"natord",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"scopeguard",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
|
|
|
@ -29,6 +29,7 @@ pub mod launcher;
|
|||
pub mod log;
|
||||
pub mod migrate;
|
||||
pub mod modulo;
|
||||
pub mod package;
|
||||
pub mod path;
|
||||
pub mod service;
|
||||
pub mod util;
|
||||
|
|
86
espanso/src/cli/package/install.rs
Normal file
86
espanso/src/cli/package/install.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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 anyhow::{anyhow, Context, Result};
|
||||
use clap::ArgMatches;
|
||||
use espanso_package::{PackageSpecifier, SaveOptions};
|
||||
use espanso_path::Paths;
|
||||
|
||||
use crate::info_println;
|
||||
|
||||
pub fn install_package(paths: &Paths, matches: &ArgMatches) -> Result<()> {
|
||||
let package_name = matches
|
||||
.value_of("package_name")
|
||||
.ok_or(anyhow!("missing package name"))?;
|
||||
let version = matches.value_of("version");
|
||||
let force = matches.is_present("force");
|
||||
|
||||
info_println!(
|
||||
"installing package: {} - version: {}",
|
||||
package_name,
|
||||
version.unwrap_or("latest")
|
||||
);
|
||||
|
||||
let package_specifier = if let Some(git_repo) = matches.value_of("git") {
|
||||
let git_branch = matches.value_of("git-branch");
|
||||
let use_native_git = matches.is_present("use-native-git");
|
||||
|
||||
PackageSpecifier {
|
||||
name: package_name.to_string(),
|
||||
version: version.map(String::from),
|
||||
git_repo_url: Some(git_repo.to_string()),
|
||||
git_branch: git_branch.map(String::from),
|
||||
use_native_git,
|
||||
}
|
||||
} else {
|
||||
// Install from the hub
|
||||
|
||||
PackageSpecifier {
|
||||
name: package_name.to_string(),
|
||||
version: version.map(String::from),
|
||||
..Default::default()
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: if git is specified, make sure external is as well (or warn otherwise)
|
||||
|
||||
let package_provider = espanso_package::get_provider(&package_specifier)
|
||||
.context("unable to obtain compatible package provider")?;
|
||||
|
||||
info_println!("using package provider: {}", package_provider.name());
|
||||
|
||||
let package = package_provider.download(&package_specifier)?;
|
||||
|
||||
info_println!(
|
||||
"found package: {} - version: {}",
|
||||
package.name(),
|
||||
package.version()
|
||||
);
|
||||
|
||||
let archiver =
|
||||
espanso_package::get_archiver(&paths.packages).context("unable to get package archiver")?;
|
||||
|
||||
archiver.save(&*package, &package_specifier, &SaveOptions {
|
||||
overwrite_existing: force,
|
||||
}).context("unable to save package")?;
|
||||
|
||||
info_println!("package installed!");
|
||||
|
||||
Ok(())
|
||||
}
|
57
espanso/src/cli/package/mod.rs
Normal file
57
espanso/src/cli/package/mod.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 crate::{
|
||||
error_eprintln,
|
||||
exit_code::{configure_custom_panic_hook, PACKAGE_INSTALL_FAILED, PACKAGE_SUCCESS},
|
||||
};
|
||||
|
||||
use super::{CliModule, CliModuleArgs};
|
||||
|
||||
mod install;
|
||||
|
||||
pub fn new() -> CliModule {
|
||||
CliModule {
|
||||
enable_logs: true,
|
||||
disable_logs_terminal_output: true,
|
||||
requires_paths: true,
|
||||
subcommand: "package".to_string(),
|
||||
log_mode: super::LogMode::AppendOnly,
|
||||
entry: package_main,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn package_main(args: CliModuleArgs) -> i32 {
|
||||
configure_custom_panic_hook();
|
||||
|
||||
let paths = args.paths.expect("missing paths argument");
|
||||
let cli_args = args.cli_args.expect("missing cli_args");
|
||||
|
||||
if let Some(sub_matches) = cli_args.subcommand_matches("install") {
|
||||
if let Err(err) = install::install_package(&paths, sub_matches) {
|
||||
error_eprintln!("unable to install package: {:?}", err);
|
||||
return PACKAGE_INSTALL_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: uninstall, list, update
|
||||
|
||||
PACKAGE_SUCCESS
|
||||
}
|
|
@ -55,8 +55,14 @@ pub const WORKAROUND_SUCCESS: i32 = 0;
|
|||
pub const WORKAROUND_FAILURE: i32 = 1;
|
||||
pub const WORKAROUND_NOT_AVAILABLE: i32 = 2;
|
||||
|
||||
pub const PACKAGE_SUCCESS: i32 = 0;
|
||||
pub const PACKAGE_UNEXPECTED_FAILURE: i32 = 1;
|
||||
pub const PACKAGE_INSTALL_FAILED: i32 = 2;
|
||||
|
||||
use std::sync::Mutex;
|
||||
|
||||
use crate::error_eprintln;
|
||||
|
||||
lazy_static! {
|
||||
static ref CURRENT_PANIC_EXIT_CODE: Mutex<i32> = Mutex::new(MIGRATE_UNEXPECTED_FAILURE);
|
||||
}
|
||||
|
@ -80,7 +86,7 @@ pub fn configure_custom_panic_hook() {
|
|||
|
||||
match info.location() {
|
||||
Some(location) => {
|
||||
eprintln!(
|
||||
error_eprintln!(
|
||||
"ERROR: '{}' panicked at '{}': {}:{}",
|
||||
thread,
|
||||
msg,
|
||||
|
@ -88,7 +94,9 @@ pub fn configure_custom_panic_hook() {
|
|||
location.line(),
|
||||
);
|
||||
}
|
||||
None => eprintln!("ERROR: '{}' panicked at '{}'", thread, msg,),
|
||||
None => {
|
||||
error_eprintln!("ERROR: '{}' panicked at '{}'", thread, msg);
|
||||
}
|
||||
}
|
||||
|
||||
let exit_code = CURRENT_PANIC_EXIT_CODE.lock().unwrap();
|
||||
|
@ -102,4 +110,3 @@ pub fn update_panic_exit_code(exit_code: i32) {
|
|||
.expect("unable to update panic exit code");
|
||||
*lock = exit_code;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ lazy_static! {
|
|||
cli::env_path::new(),
|
||||
cli::service::new(),
|
||||
cli::workaround::new(),
|
||||
cli::package::new(),
|
||||
];
|
||||
static ref ALIASES: Vec<CliAlias> = vec![
|
||||
CliAlias {
|
||||
|
@ -79,6 +80,14 @@ lazy_static! {
|
|||
subcommand: "stop".to_owned(),
|
||||
forward_into: "service".to_owned(),
|
||||
},
|
||||
CliAlias {
|
||||
subcommand: "install".to_owned(),
|
||||
forward_into: "package".to_owned(),
|
||||
},
|
||||
CliAlias {
|
||||
subcommand: "uninstall".to_owned(),
|
||||
forward_into: "package".to_owned(),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -86,7 +95,7 @@ fn main() {
|
|||
util::attach_console();
|
||||
|
||||
let install_subcommand = SubCommand::with_name("install")
|
||||
.about("Install a package. Equivalent to 'espanso package install'")
|
||||
.about("Install a package")
|
||||
.arg(
|
||||
Arg::with_name("external")
|
||||
.short("e")
|
||||
|
@ -97,21 +106,43 @@ fn main() {
|
|||
)
|
||||
.arg(Arg::with_name("package_name").help("Package name"))
|
||||
.arg(
|
||||
Arg::with_name("repository_url")
|
||||
.help("(Optional) Link to GitHub repository")
|
||||
Arg::with_name("version")
|
||||
.long("version")
|
||||
.required(false)
|
||||
.default_value("hub"),
|
||||
.takes_value(true)
|
||||
.help("Force a particular version to be installed instead of the latest available."),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("proxy")
|
||||
.help("Use a proxy, should be used as --proxy=https://proxy:1234")
|
||||
Arg::with_name("git")
|
||||
.long("git")
|
||||
.required(false)
|
||||
.long("proxy")
|
||||
.takes_value(true),
|
||||
.takes_value(true)
|
||||
.help("Git repository from which espanso should install the package."),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("git-branch")
|
||||
.long("git-branch")
|
||||
.required(false)
|
||||
.takes_value(true)
|
||||
.help("Force espanso to search for the package on a specific git branch"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("force")
|
||||
.long("force")
|
||||
.required(false)
|
||||
.takes_value(false)
|
||||
.help("Overwrite the package if already installed"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("use-native-git")
|
||||
.long("use-native-git")
|
||||
.required(false)
|
||||
.takes_value(false)
|
||||
.help("If specified, espanso will use the 'git' command instead of trying direct methods."),
|
||||
);
|
||||
|
||||
let uninstall_subcommand = SubCommand::with_name("uninstall")
|
||||
.about("Remove an installed package. Equivalent to 'espanso package uninstall'")
|
||||
.about("Remove a package")
|
||||
.arg(Arg::with_name("package_name").help("Package name"));
|
||||
|
||||
let start_subcommand = SubCommand::with_name("start")
|
||||
|
@ -332,19 +363,14 @@ fn main() {
|
|||
// )
|
||||
// )
|
||||
// )
|
||||
// Package manager
|
||||
// .subcommand(SubCommand::with_name("package")
|
||||
// .about("Espanso package manager commands")
|
||||
// .subcommand(install_subcommand.clone())
|
||||
// .subcommand(uninstall_subcommand.clone())
|
||||
// .subcommand(SubCommand::with_name("list")
|
||||
// .about("List all installed packages")
|
||||
// .arg(Arg::with_name("full")
|
||||
// .help("Print all package info")
|
||||
// .long("full")))
|
||||
// .subcommand(SubCommand::with_name("refresh")
|
||||
// .about("Update espanso package index"))
|
||||
// )
|
||||
.subcommand(
|
||||
SubCommand::with_name("package")
|
||||
.about("package-management commands")
|
||||
.subcommand(install_subcommand.clone())
|
||||
.subcommand(uninstall_subcommand.clone())
|
||||
.subcommand(
|
||||
SubCommand::with_name("list").about("List all installed packages"), // TODO: update <Package> and update all
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("workaround")
|
||||
.subcommand(
|
||||
|
@ -352,6 +378,7 @@ fn main() {
|
|||
.about("Attempt to disable secure input by automating the common steps."),
|
||||
)
|
||||
.about("A collection of workarounds to solve some common problems."),
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("worker")
|
||||
|
@ -368,9 +395,9 @@ fn main() {
|
|||
.required(false)
|
||||
.takes_value(false),
|
||||
),
|
||||
);
|
||||
// .subcommand(install_subcommand)
|
||||
// .subcommand(uninstall_subcommand);
|
||||
)
|
||||
.subcommand(install_subcommand)
|
||||
.subcommand(uninstall_subcommand);
|
||||
|
||||
// TODO: explain that the register and unregister commands are only meaningful
|
||||
// when using the system daemon manager on macOS and Linux
|
||||
|
|
Loading…
Reference in New Issue
Block a user