3 Commits

Author SHA1 Message Date
kpcyrd
5c3f8fbe49 Update dependencies 2019-10-20 23:27:28 +02:00
kpcyrd
c377e7937d Add uninstall command 2019-10-19 16:37:20 +02:00
kpcyrd
f8230fc094 Support module redirects 2019-10-19 15:59:29 +02:00
10 changed files with 399 additions and 432 deletions

703
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@ percent-encoding = "2.1"
chrootable-https = "0.12"
rustls = { version="0.16", features=["dangerous_configuration"] }
webpki = "0.21"
webpki-roots = "0.17"
webpki-roots = "0.18"
pem = "0.6.0"
base64 = "0.10"
data-encoding = "2.1.2"

View File

@@ -1,3 +1,5 @@
use crate::id::ModuleID;
#[derive(Debug, Serialize, Deserialize)]
pub struct WhoamiResponse {
pub user: String,
@@ -29,6 +31,7 @@ pub struct ModuleInfoResponse {
pub name: String,
pub description: String,
pub latest: Option<String>,
pub redirect: Option<ModuleID>,
}
impl ModuleInfoResponse {

View File

@@ -70,6 +70,7 @@ pub fn info(author: String, name: String, connection: db::Connection) -> ApiResu
name: module.name,
description: module.description,
latest: module.latest,
redirect: None,
}))
}

View File

@@ -143,6 +143,8 @@ pub struct Install {
pub module: ModuleID,
/// Specify the version, defaults to the latest version
pub version: Option<String>,
#[structopt(short="f", long="force")]
pub force: bool,
}
#[derive(Debug, StructOpt)]

View File

@@ -6,6 +6,7 @@ use crate::shell::Shell;
use crate::update::AutoUpdater;
use crate::worker;
use colored::Colorize;
use sn0int_common::ModuleID;
use std::fmt::Write;
use std::sync::Arc;
use structopt::StructOpt;
@@ -36,6 +37,9 @@ pub enum SubCommand {
/// Update modules
#[structopt(name="update")]
Update(Update),
/// Uninstall a module
#[structopt(name="uninstall")]
Uninstall(Uninstall),
}
#[derive(Debug, StructOpt)]
@@ -56,6 +60,11 @@ pub struct Reload {
pub struct Update {
}
#[derive(Debug, StructOpt)]
pub struct Uninstall {
module: ModuleID,
}
pub fn run(rl: &mut Shell, args: &[String]) -> Result<()> {
let args = Args::from_iter_safe(args)?;
let config = rl.config().clone();
@@ -86,7 +95,7 @@ pub fn run(rl: &mut Shell, args: &[String]) -> Result<()> {
}
},
SubCommand::Install(install) => {
registry::run_install(&install, &config)?;
registry::run_install(install, &config)?;
// trigger reload
run(rl, &[String::from("mod"), String::from("reload")])?;
},
@@ -131,6 +140,12 @@ pub fn run(rl: &mut Shell, args: &[String]) -> Result<()> {
// trigger reload
run(rl, &[String::from("mod"), String::from("reload")])?;
},
SubCommand::Uninstall(uninstall) => {
let updater = Updater::new(&config)?;
updater.uninstall(&uninstall.module)?;
// trigger reload
run(rl, &[String::from("mod"), String::from("reload")])?;
},
}
Ok(())

View File

@@ -35,6 +35,7 @@ pub fn run(rl: &mut Shell, args: &[String]) -> Result<()> {
name: module.name,
},
version: None,
force: false,
}, updater.clone())
})
.collect::<Vec<_>>();

View File

@@ -96,7 +96,7 @@ fn run() -> Result<()> {
Some(SubCommand::Login(_)) => auth::run_login(&config),
Some(SubCommand::New(new)) => run_new(&args, &new),
Some(SubCommand::Publish(publish)) => registry::run_publish(&args, &publish, &config),
Some(SubCommand::Install(install)) => registry::run_install(&install, &config),
Some(SubCommand::Install(install)) => registry::run_install(install, &config),
Some(SubCommand::Search(search)) => {
let engine = Engine::new(false, &config)?;
registry::run_search(&engine, &search, &config)

View File

@@ -10,7 +10,7 @@ use sn0int_common::ModuleID;
use sn0int_common::api::ModuleInfoResponse;
use sn0int_common::metadata::Metadata;
use std::fs;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use crate::paths;
use crate::term;
@@ -34,35 +34,68 @@ impl Updater {
self.client.query_module(module)
}
pub fn install(&self, install: &Install) -> Result<String> {
let version = match install.version {
Some(ref version) => version.to_string(),
None => self.client.query_module(&install.module)
.context("Failed to query module infos")?
.latest
.ok_or_else(|| format_err!("Module doesn't have a latest version"))?,
};
let module = self.client.download_module(&install.module, &version)
.context("Failed to download module")?;
fn path(&self, module: &ModuleID) -> Result<PathBuf> {
let path = paths::module_dir()?
.join(format!("{}/{}.lua", install.module.author,
install.module.name));
.join(format!("{}/{}.lua", module.author,
module.name));
Ok(path)
}
fs::create_dir_all(path.parent().unwrap())
.context("Failed to create folder")?;
pub fn install(&self, install: Install) -> Result<String> {
if let Some(version) = install.version {
let module = self.client.download_module(&install.module, &version)
.context("Failed to download module")?;
fs::write(&path, module.code)
.context(format_err!("Failed to write to {:?}", path))?;
let path = self.path(&install.module)?;
Ok(version)
fs::create_dir_all(path.parent().unwrap())
.context("Failed to create folder")?;
fs::write(&path, module.code)
.context(format_err!("Failed to write to {:?}", path))?;
Ok(version.to_string())
} else {
let infos = self.query_module(&install.module)
.context("Failed to query module infos")?;
if !install.force {
if let Some(redirect) = infos.redirect {
return self.install(Install {
module: redirect,
version: None,
force: install.force,
});
}
}
let latest = infos
.latest
.ok_or_else(|| format_err!("Module doesn't have a latest version"))?;
self.install(Install {
module: install.module,
version: Some(latest),
force: install.force,
})
}
}
pub fn uninstall(&self, module: &ModuleID) -> Result<()> {
let path = self.path(module)?;
fs::remove_file(&path)?;
// try to delete parent folder if empty
if let Some(parent) = path.parent() {
fs::remove_dir(parent).ok();
}
Ok(())
}
}
pub fn run_publish(_args: &Args, publish: &Publish, config: &Config) -> Result<()> {
let session = auth::load_token()
.context("Failed to load auth token")?;
.context("Failed to load auth token, login first")?;
let mut client = Client::new(&config)?;
client.authenticate(session);
@@ -129,7 +162,7 @@ impl Task for InstallTask {
}
fn run(self, tx: &EventSender) -> Result<()> {
let version = self.client.install(&self.install)?;
let version = self.client.install(self.install)?;
let label = format!("installed v{}", version);
tx.log(LogEvent::Success(label));
Ok(())
@@ -137,7 +170,7 @@ impl Task for InstallTask {
}
pub fn run_install(arg: &Install, config: &Config) -> Result<()> {
pub fn run_install(arg: Install, config: &Config) -> Result<()> {
let label = format!("Installing {}", arg.module);
worker::spawn_fn(&label, || {
let client = Updater::new(config)?;
@@ -178,13 +211,27 @@ impl Task for UpdateTask {
debug!("Latest version: {:?}", infos);
let latest = infos.latest.ok_or_else(|| format_err!("Module doesn't have any released versions"))?;
if installed != latest {
if let Some(redirect) = infos.redirect {
let label = format!("Replacing {}: {}", self.name(), redirect);
tx.log(LogEvent::Status(label));
self.client.install(Install {
module: self.module.id(),
version: None,
force: false,
})?;
self.client.uninstall(&self.module.id())?;
let label = format!("replaced with {}", redirect);
tx.log(LogEvent::Success(label));
} else if installed != latest {
let label = format!("Updating {}: v{} -> v{}", self.name(), installed, latest);
tx.log(LogEvent::Status(label));
self.client.install(&Install {
self.client.install(Install {
module: self.module.id(),
version: None,
version: Some(latest.clone()),
force: false,
})?;
let label = format!("updated v{} -> v{}", installed, latest);

View File

@@ -180,6 +180,7 @@ impl Completer for CmdCompleter {
"search",
"reload",
"update",
"uninstall",
], &cmd[1]))
}
},