Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c3f8fbe49 | ||
|
|
c377e7937d | ||
|
|
f8230fc094 |
703
Cargo.lock
generated
703
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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(())
|
||||
|
||||
@@ -35,6 +35,7 @@ pub fn run(rl: &mut Shell, args: &[String]) -> Result<()> {
|
||||
name: module.name,
|
||||
},
|
||||
version: None,
|
||||
force: false,
|
||||
}, updater.clone())
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -180,6 +180,7 @@ impl Completer for CmdCompleter {
|
||||
"search",
|
||||
"reload",
|
||||
"update",
|
||||
"uninstall",
|
||||
], &cmd[1]))
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user