mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-27 03:21:49 +03:00
Add publish an package to the package manager
This commit is contained in:
parent
3980ff8e1e
commit
cde9c0ef40
@ -1,21 +1,51 @@
|
|||||||
use crate::{cli::*, cli_types::*, commands::BuildCommand, errors::CLIError};
|
use crate::{
|
||||||
|
cli::*,
|
||||||
|
cli_types::*,
|
||||||
|
commands::{BuildCommand, LoginCommand},
|
||||||
|
errors::{
|
||||||
|
commands::PublishError::{ConnectionUnavalaible, PackageNotPublished},
|
||||||
|
CLIError,
|
||||||
|
CLIError::PublishError,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use clap::ArgMatches;
|
||||||
use leo_package::{
|
use leo_package::{
|
||||||
outputs::OutputsDirectory,
|
outputs::OutputsDirectory,
|
||||||
root::{Manifest, ZipFile},
|
root::{Manifest, ZipFile},
|
||||||
};
|
};
|
||||||
|
use reqwest::{
|
||||||
use clap::ArgMatches;
|
blocking::{multipart::Form, Client},
|
||||||
|
header::{HeaderMap, HeaderValue},
|
||||||
|
};
|
||||||
|
use serde::Deserialize;
|
||||||
use std::{convert::TryFrom, env::current_dir};
|
use std::{convert::TryFrom, env::current_dir};
|
||||||
|
|
||||||
|
const PACKAGE_MANAGER_URL: &str = "https://apm-backend-dev.herokuapp.com/";
|
||||||
|
const PUBLISH_URL: &str = "api/package/publish";
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct ResponseJson {
|
||||||
|
package_id: String,
|
||||||
|
_success: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PublishCommand;
|
pub struct PublishCommand;
|
||||||
|
|
||||||
impl CLI for PublishCommand {
|
impl CLI for PublishCommand {
|
||||||
type Options = ();
|
type Options = ();
|
||||||
type Output = ();
|
type Output = Option<String>;
|
||||||
|
|
||||||
const ABOUT: AboutType = "Publish the current package to the package manager (*)";
|
const ABOUT: AboutType = "Publish the current package to the package manager (*)";
|
||||||
const ARGUMENTS: &'static [ArgumentType] = &[];
|
const ARGUMENTS: &'static [ArgumentType] = &[
|
||||||
|
// (name, description, required, index)
|
||||||
|
(
|
||||||
|
"NAME",
|
||||||
|
"Sets the resulting package name, defaults to the directory name",
|
||||||
|
true,
|
||||||
|
1u64,
|
||||||
|
),
|
||||||
|
];
|
||||||
const FLAGS: &'static [FlagType] = &[];
|
const FLAGS: &'static [FlagType] = &[];
|
||||||
const NAME: NameType = "publish";
|
const NAME: NameType = "publish";
|
||||||
const OPTIONS: &'static [OptionType] = &[];
|
const OPTIONS: &'static [OptionType] = &[];
|
||||||
@ -23,18 +53,23 @@ impl CLI for PublishCommand {
|
|||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
fn parse(_arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
|
fn parse(_arguments: &ArgMatches) -> Result<Self::Options, CLIError> {
|
||||||
|
// match arguments.value_of("NAME") {
|
||||||
|
// Some(name) => Ok((Some(name.to_string()),)),
|
||||||
|
// None => Ok((None,)),
|
||||||
|
// }
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(tarpaulin, skip)]
|
#[cfg_attr(tarpaulin, skip)]
|
||||||
fn output(options: Self::Options) -> Result<Self::Output, CLIError> {
|
fn output(_options: Self::Options) -> Result<Self::Output, CLIError> {
|
||||||
// Build all program files.
|
// Build all program files.
|
||||||
// It's okay if there's just a lib.leo file here
|
// It's okay if there's just a lib.leo file here
|
||||||
let _output = BuildCommand::output(options)?;
|
// let _output = BuildCommand::output(options)?;
|
||||||
|
|
||||||
// Get the package name
|
// Get the package name
|
||||||
let path = current_dir()?;
|
let path = current_dir()?;
|
||||||
let package_name = Manifest::try_from(&path)?.get_package_name();
|
let package_name = Manifest::try_from(&path)?.get_package_name();
|
||||||
|
let package_version = Manifest::try_from(&path)?.get_package_version();
|
||||||
|
|
||||||
// Create the output directory
|
// Create the output directory
|
||||||
OutputsDirectory::create(&path)?;
|
OutputsDirectory::create(&path)?;
|
||||||
@ -47,6 +82,60 @@ impl CLI for PublishCommand {
|
|||||||
zip_file.write(&path)?;
|
zip_file.write(&path)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
let is_public = "false";
|
||||||
|
let form_data = Form::new()
|
||||||
|
.text("name", package_name)
|
||||||
|
.text("version", package_version)
|
||||||
|
.file("file", zip_file.get_file_path(&path))?
|
||||||
|
.text("public", is_public);
|
||||||
|
|
||||||
|
// Client for make POST request
|
||||||
|
let client = Client::new();
|
||||||
|
|
||||||
|
// Get token to make an authorized request
|
||||||
|
let token = match LoginCommand::read_token() {
|
||||||
|
Ok(token) => token,
|
||||||
|
|
||||||
|
// If not logged then try to login using JWT
|
||||||
|
Err(_errorr) => {
|
||||||
|
log::warn!("You should be logged before publish the package");
|
||||||
|
log::info!("Trying to log in using JWT...");
|
||||||
|
let options = (None, None, None);
|
||||||
|
|
||||||
|
LoginCommand::output(options)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Headers for request to publish package
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
headers.insert(
|
||||||
|
"Authorization",
|
||||||
|
HeaderValue::from_str(&format!("{} {}", "Bearer", token)).unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Make a request to publish a package
|
||||||
|
let response = client
|
||||||
|
.post(format!("{}{}", PACKAGE_MANAGER_URL, PUBLISH_URL).as_str())
|
||||||
|
.headers(headers)
|
||||||
|
.multipart(form_data)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
// Get a response result
|
||||||
|
let result = match response {
|
||||||
|
Ok(json_result) => match json_result.json::<ResponseJson>() {
|
||||||
|
Ok(json) => json,
|
||||||
|
Err(error) => {
|
||||||
|
log::warn!("{:?}", error);
|
||||||
|
return Err(PublishError(PackageNotPublished("Package not published".into())));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(error) => {
|
||||||
|
log::warn!("{:?}", error);
|
||||||
|
return Err(PublishError(ConnectionUnavalaible("Connection error".into())));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
log::info!("Packge published successfully");
|
||||||
|
Ok(Some(result.package_id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,9 @@ pub enum CLIError {
|
|||||||
#[error("{}", _0)]
|
#[error("{}", _0)]
|
||||||
ProvingKeyFileError(ProvingKeyFileError),
|
ProvingKeyFileError(ProvingKeyFileError),
|
||||||
|
|
||||||
|
#[error("{}", _0)]
|
||||||
|
PublishError(PublishError),
|
||||||
|
|
||||||
#[error("{}", _0)]
|
#[error("{}", _0)]
|
||||||
RunError(RunError),
|
RunError(RunError),
|
||||||
|
|
||||||
@ -175,6 +178,13 @@ impl From<ProvingKeyFileError> for CLIError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<PublishError> for CLIError {
|
||||||
|
fn from(error: PublishError) -> Self {
|
||||||
|
log::error!("{}\n", error);
|
||||||
|
CLIError::PublishError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<RunError> for CLIError {
|
impl From<RunError> for CLIError {
|
||||||
fn from(error: RunError) -> Self {
|
fn from(error: RunError) -> Self {
|
||||||
log::error!("{}\n", error);
|
log::error!("{}\n", error);
|
||||||
|
@ -10,6 +10,9 @@ pub use self::login::*;
|
|||||||
pub mod new;
|
pub mod new;
|
||||||
pub use self::new::*;
|
pub use self::new::*;
|
||||||
|
|
||||||
|
pub mod publish;
|
||||||
|
pub use self::publish::*;
|
||||||
|
|
||||||
pub mod run;
|
pub mod run;
|
||||||
pub use self::run::*;
|
pub use self::run::*;
|
||||||
|
|
||||||
|
10
leo/errors/commands/publish.rs
Normal file
10
leo/errors/commands/publish.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use std::ffi::OsString;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum PublishError {
|
||||||
|
#[error("connection unavailable {:?}", _0)]
|
||||||
|
ConnectionUnavalaible(OsString),
|
||||||
|
|
||||||
|
#[error("package not published {:?}", _0)]
|
||||||
|
PackageNotPublished(OsString),
|
||||||
|
}
|
@ -8,7 +8,7 @@ use std::{
|
|||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static MANIFEST_FILE_NAME: &str = "Leo.toml";
|
pub const MANIFEST_FILE_NAME: &str = "Leo.toml";
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Package {
|
pub struct Package {
|
||||||
@ -43,6 +43,10 @@ impl Manifest {
|
|||||||
self.package.name.clone()
|
self.package.name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_package_version(&self) -> String {
|
||||||
|
self.package.version.clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write_to(self, path: &PathBuf) -> Result<(), ManifestError> {
|
pub fn write_to(self, path: &PathBuf) -> Result<(), ManifestError> {
|
||||||
let mut path = path.to_owned();
|
let mut path = path.to_owned();
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
|
@ -41,6 +41,10 @@ impl ZipFile {
|
|||||||
path.exists()
|
path.exists()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_file_path(&self, current_dir: &PathBuf) -> PathBuf {
|
||||||
|
self.setup_file_path(current_dir)
|
||||||
|
}
|
||||||
|
|
||||||
// /// Reads the program bytes from the given file path if it exists.
|
// /// Reads the program bytes from the given file path if it exists.
|
||||||
// pub fn read_from(&self, path: &PathBuf) -> Result<Vec<u8>, ZipFileError> {
|
// pub fn read_from(&self, path: &PathBuf) -> Result<Vec<u8>, ZipFileError> {
|
||||||
// let path = self.setup_file_path(path);
|
// let path = self.setup_file_path(path);
|
||||||
|
Loading…
Reference in New Issue
Block a user