Implement leo add command

This commit is contained in:
raychu86 2020-08-16 14:01:32 -07:00
parent 3f8134f890
commit 502eea7ddd
8 changed files with 137 additions and 4 deletions

105
leo/commands/add.rs Normal file
View File

@ -0,0 +1,105 @@
//
// Usage:
//
// leo add -a author -p package_name -v version
// leo add -a author -p package_name
//
use crate::{
cli::CLI,
cli_types::*,
credentials::*,
errors::{AddError::*, CLIError::AddError},
};
use std::{collections::HashMap, env::current_dir, fs::File, io::Write};
pub const ADD_URL: &str = "api/package/fetch";
#[derive(Debug)]
pub struct AddCommand;
impl CLI for AddCommand {
// Format: author, package_name, version
type Options = (Option<String>, Option<String>, Option<String>);
type Output = ();
const ABOUT: AboutType = "Install a package from the package manager";
const ARGUMENTS: &'static [ArgumentType] = &[];
const FLAGS: &'static [FlagType] = &[];
const NAME: NameType = "add";
const OPTIONS: &'static [OptionType] = &[
// (argument, conflicts, possible_values, requires)
("[author] -a --author=<author> 'Specify a package author'", &[], &[], &[
"package_name",
]),
(
"[package_name] -p --package_name=<package_name> 'Specify a package name'",
&[],
&[],
&["author"],
),
(
"[version] -v --version=[version] 'Specify a package version'",
&[],
&[],
&["author", "package_name"],
),
];
const SUBCOMMANDS: &'static [SubCommandType] = &[];
fn parse(arguments: &clap::ArgMatches) -> Result<Self::Options, crate::errors::CLIError> {
if arguments.is_present("author") && arguments.is_present("package_name") {
return Ok((
arguments.value_of("author").map(|s| s.to_string()),
arguments.value_of("package_name").map(|s| s.to_string()),
arguments.value_of("version").map(|s| s.to_string()),
));
} else {
return Err(AddError(MissingAuthorOrPackageName));
}
}
fn output(options: Self::Options) -> Result<Self::Output, crate::errors::CLIError> {
let token = read_token()?;
let (mut result, package_name) = match options {
(Some(author), Some(package_name), version) => {
let client = reqwest::blocking::Client::new();
let url = format!("{}{}", PACKAGE_MANAGER_URL, ADD_URL);
let mut json = HashMap::new();
json.insert("author", author);
json.insert("package_name", package_name.clone());
if let Some(version) = version {
json.insert("version", version);
}
match client.post(&url).bearer_auth(token).json(&json).send() {
Ok(result) => (result, package_name),
//Cannot connect to the server
Err(_error) => {
return Err(AddError(ConnectionUnavailable(
"Could not connect to the package manager".into(),
)));
}
}
}
_ => return Err(AddError(MissingAuthorOrPackageName)),
};
let mut path = current_dir()?;
path.push(format!("{}.zip", package_name));
// TODO (raychu86) Display download progress
let mut buffer: Vec<u8> = vec![];
result.copy_to(&mut buffer).unwrap();
let mut file = File::create(path)?;
file.write_all(&buffer)?;
log::info!("Successfully added package");
Ok(())
}
}

View File

@ -12,7 +12,7 @@ use crate::{
credentials::*,
errors::{
CLIError::LoginError,
LoginError::{CannotGetToken, ConnectionUnavalaible, WrongLoginOrPassword},
LoginError::{CannotGetToken, ConnectionUnavailable, WrongLoginOrPassword},
},
};
@ -84,7 +84,7 @@ impl CLI for LoginCommand {
},
//Cannot connect to the server
Err(_error) => {
return Err(LoginError(ConnectionUnavalaible(
return Err(LoginError(ConnectionUnavailable(
"Could not connect to the package manager".into(),
)));
}

View File

@ -1,3 +1,6 @@
pub mod add;
pub use self::add::*;
pub mod build;
pub use self::build::*;

View File

@ -3,6 +3,9 @@ use leo_package::errors::*;
#[derive(Debug, Error)]
pub enum CLIError {
#[error("{}", _0)]
AddError(AddError),
#[error("{}", _0)]
BuildError(BuildError),
@ -84,6 +87,13 @@ impl From<BuildError> for CLIError {
}
}
impl From<AddError> for CLIError {
fn from(error: AddError) -> Self {
log::error!("{}\n", error);
CLIError::AddError(error)
}
}
impl From<ChecksumFileError> for CLIError {
fn from(error: ChecksumFileError) -> Self {
log::error!("{}\n", error);

View File

@ -0,0 +1,10 @@
use std::ffi::OsString;
#[derive(Debug, Error)]
pub enum AddError {
#[error("connection unavailable {:?}", _0)]
ConnectionUnavailable(OsString),
#[error("missing author or package name")]
MissingAuthorOrPackageName,
}

View File

@ -5,8 +5,8 @@ pub enum LoginError {
#[error("{:?}", _0)]
CannotGetToken(OsString),
#[error("connectin unavalaible {:?}", _0)]
ConnectionUnavalaible(OsString),
#[error("connection unavailable {:?}", _0)]
ConnectionUnavailable(OsString),
#[error("wrong login or password {:?}", _0)]
WrongLoginOrPassword(OsString),

View File

@ -1,3 +1,6 @@
pub mod add;
pub use self::add::*;
pub mod build;
pub use self::build::*;

View File

@ -35,6 +35,7 @@ fn main() -> Result<(), CLIError> {
DeployCommand::new().display_order(12),
CleanCommand::new().display_order(13),
WatchCommand::new().display_order(14),
AddCommand::new().display_order(15), // TODO update add command order
])
.set_term_width(0)
.get_matches();
@ -55,6 +56,7 @@ fn main() -> Result<(), CLIError> {
("deploy", Some(arguments)) => DeployCommand::process(arguments),
("clean", Some(arguments)) => CleanCommand::process(arguments),
("watch", Some(arguments)) => WatchCommand::process(arguments),
("add", Some(arguments)) => AddCommand::process(arguments),
_ => unreachable!(),
}
}