mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-22 22:44:47 +03:00
Adds 'leo clone' command
This commit is contained in:
parent
d5f787cd92
commit
4fc5f3f30c
4
.circleci/leo-publish.sh
Executable file
4
.circleci/leo-publish.sh
Executable file
@ -0,0 +1,4 @@
|
||||
mkdir hello-world && cd hello-world || exit 1
|
||||
$LEO init
|
||||
ls -la
|
||||
$LEO run
|
@ -25,7 +25,7 @@ use std::{
|
||||
use structopt::StructOpt;
|
||||
use tracing::Span;
|
||||
|
||||
/// Add package from Aleo Package Manager
|
||||
/// Add a package from Aleo Package Manager
|
||||
#[derive(StructOpt, Debug)]
|
||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||
pub struct Add {
|
||||
@ -58,7 +58,7 @@ impl Add {
|
||||
}
|
||||
|
||||
/// Try to parse author/package string from self.remote
|
||||
pub fn try_read_arguments(&self) -> Result<(String, String)> {
|
||||
fn try_read_arguments(&self) -> Result<(String, String)> {
|
||||
if let Some(val) = &self.remote {
|
||||
let v: Vec<&str> = val.split('/').collect();
|
||||
if v.len() == 2 {
|
||||
@ -91,42 +91,41 @@ impl Command for Add {
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
// checking that manifest exists...
|
||||
// Check that a manifest exists for the current package.
|
||||
if context.manifest().is_err() {
|
||||
return Err(anyhow!("Package Manifest not found, try running leo init or leo new"));
|
||||
return Err(anyhow!("Package manifest not found, try running `leo init`"));
|
||||
};
|
||||
|
||||
let (author, package_name) = match self.try_read_arguments() {
|
||||
Ok((author, package)) => (author, package),
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
let version = self.version;
|
||||
|
||||
// build request body (Options are skipped when sealizing)
|
||||
let fetch = Fetch {
|
||||
author,
|
||||
package_name: package_name.clone(),
|
||||
version,
|
||||
// Attempt to fetch the package.
|
||||
let reader = {
|
||||
let fetch = Fetch {
|
||||
author,
|
||||
package_name: package_name.clone(),
|
||||
version: self.version,
|
||||
};
|
||||
let bytes = context.api.run_route(fetch)?.bytes()?;
|
||||
std::io::Cursor::new(bytes)
|
||||
};
|
||||
|
||||
let bytes = context.api.run_route(fetch)?.bytes()?;
|
||||
// Construct the directory structure.
|
||||
let mut path = context.dir()?;
|
||||
|
||||
{
|
||||
// setup directory structure since request was success
|
||||
ImportsDirectory::create(&path)?;
|
||||
path.push(IMPORTS_DIRECTORY_NAME);
|
||||
path.push(package_name);
|
||||
create_dir_all(&path)?;
|
||||
};
|
||||
|
||||
let reader = std::io::Cursor::new(bytes);
|
||||
|
||||
// Proceed to unzip and parse the fetched bytes.
|
||||
let mut zip_archive = match zip::ZipArchive::new(reader) {
|
||||
Ok(zip) => zip,
|
||||
Err(error) => return Err(anyhow!(error)),
|
||||
};
|
||||
|
||||
for i in 0..zip_archive.len() {
|
||||
let file = match zip_archive.by_index(i) {
|
||||
Ok(file) => file,
|
||||
|
160
leo/commands/package/clone.rs
Normal file
160
leo/commands/package/clone.rs
Normal file
@ -0,0 +1,160 @@
|
||||
// Copyright (C) 2019-2021 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library 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.
|
||||
|
||||
// The Leo library 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 the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{api::Fetch, commands::Command, context::Context};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
fs::{self, File},
|
||||
io::{Read, Write},
|
||||
path::Path,
|
||||
};
|
||||
use structopt::StructOpt;
|
||||
use tracing::Span;
|
||||
|
||||
/// Clone a package from Aleo Package Manager
|
||||
#[derive(StructOpt, Debug)]
|
||||
#[structopt(setting = structopt::clap::AppSettings::ColoredHelp)]
|
||||
pub struct Clone {
|
||||
#[structopt(name = "REMOTE")]
|
||||
remote: Option<String>,
|
||||
|
||||
#[structopt(name = "author", help = "Specify a package author", long = "author", short = "a")]
|
||||
author: Option<String>,
|
||||
|
||||
#[structopt(name = "package", help = "Specify a package name", long = "package", short = "p")]
|
||||
package: Option<String>,
|
||||
|
||||
#[structopt(name = "version", help = "Specify a package version", long = "version", short = "v")]
|
||||
version: Option<String>,
|
||||
}
|
||||
|
||||
impl Clone {
|
||||
pub fn new(
|
||||
remote: Option<String>,
|
||||
author: Option<String>,
|
||||
package: Option<String>,
|
||||
version: Option<String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
remote,
|
||||
author,
|
||||
package,
|
||||
version,
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to parse author/package string from self.remote
|
||||
fn try_read_arguments(&self) -> Result<(String, String)> {
|
||||
if let Some(val) = &self.remote {
|
||||
let v: Vec<&str> = val.split('/').collect();
|
||||
if v.len() == 2 {
|
||||
Ok((v[0].to_string(), v[1].to_string()))
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"Incorrect argument, please use --help for information on command use"
|
||||
))
|
||||
}
|
||||
} else if let (Some(author), Some(package)) = (&self.author, &self.package) {
|
||||
Ok((author.clone(), package.clone()))
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"Incorrect argument, please use --help for information on command use"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a directory at the provided path with the given directory name.
|
||||
fn create_directory(path: &Path, directory_name: &str) -> Result<()> {
|
||||
let mut path = Cow::from(path);
|
||||
|
||||
// Check that the path ends in the directory name.
|
||||
// If it does not, proceed to append the directory name to the path.
|
||||
if path.is_dir() && !path.ends_with(directory_name) {
|
||||
path.to_mut().push(directory_name);
|
||||
}
|
||||
|
||||
Ok(fs::create_dir_all(&path)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for Clone {
|
||||
type Input = ();
|
||||
type Output = ();
|
||||
|
||||
fn log_span(&self) -> Span {
|
||||
tracing::span!(tracing::Level::INFO, "Cloning")
|
||||
}
|
||||
|
||||
fn prelude(&self) -> Result<Self::Input> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
|
||||
let (author, package_name) = match self.try_read_arguments() {
|
||||
Ok((author, package)) => (author, package),
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
|
||||
// Attempt to fetch the package.
|
||||
let reader = {
|
||||
let fetch = Fetch {
|
||||
author,
|
||||
package_name: package_name.clone(),
|
||||
version: self.version,
|
||||
};
|
||||
let bytes = context.api.run_route(fetch)?.bytes()?;
|
||||
std::io::Cursor::new(bytes)
|
||||
};
|
||||
|
||||
// Construct the directory structure.
|
||||
let mut path = context.dir()?;
|
||||
path.push(package_name.clone());
|
||||
Self::create_directory(&path, &package_name)?;
|
||||
|
||||
// Proceed to unzip and parse the fetched bytes.
|
||||
let mut zip_archive = match zip::ZipArchive::new(reader) {
|
||||
Ok(zip) => zip,
|
||||
Err(error) => return Err(anyhow!(error)),
|
||||
};
|
||||
for i in 0..zip_archive.len() {
|
||||
let file = match zip_archive.by_index(i) {
|
||||
Ok(file) => file,
|
||||
Err(error) => return Err(anyhow!(error)),
|
||||
};
|
||||
|
||||
let file_name = file.name();
|
||||
|
||||
let mut file_path = path.clone();
|
||||
file_path.push(file_name);
|
||||
|
||||
if file_name.ends_with('/') {
|
||||
fs::create_dir_all(file_path)?;
|
||||
} else {
|
||||
if let Some(parent_directory) = path.parent() {
|
||||
fs::create_dir_all(parent_directory)?;
|
||||
}
|
||||
|
||||
File::create(file_path)?.write_all(&file.bytes().map(|e| e.unwrap()).collect::<Vec<u8>>())?;
|
||||
}
|
||||
}
|
||||
|
||||
tracing::info!("Successfully cloned {}", package_name);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -17,6 +17,9 @@
|
||||
pub mod add;
|
||||
pub use add::Add;
|
||||
|
||||
pub mod clone;
|
||||
pub use clone::Clone;
|
||||
|
||||
pub mod login;
|
||||
pub use login::Login;
|
||||
|
||||
|
11
leo/main.rs
11
leo/main.rs
@ -23,7 +23,7 @@ pub mod synthesizer;
|
||||
pub mod updater;
|
||||
|
||||
use commands::{
|
||||
package::{Add, Login, Logout, Publish, Remove},
|
||||
package::{Add, Clone, Login, Logout, Publish, Remove},
|
||||
Build,
|
||||
Clean,
|
||||
Command,
|
||||
@ -121,12 +121,18 @@ enum CommandOpts {
|
||||
command: Test,
|
||||
},
|
||||
|
||||
#[structopt(about = "Install a package from the Aleo Package Manager")]
|
||||
#[structopt(about = "Import a package from the Aleo Package Manager")]
|
||||
Add {
|
||||
#[structopt(flatten)]
|
||||
command: Add,
|
||||
},
|
||||
|
||||
#[structopt(about = "Clone a package from the Aleo Package Manager")]
|
||||
Clone {
|
||||
#[structopt(flatten)]
|
||||
command: Clone,
|
||||
},
|
||||
|
||||
#[structopt(about = "Login to the Aleo Package Manager")]
|
||||
Login {
|
||||
#[structopt(flatten)]
|
||||
@ -189,6 +195,7 @@ fn main() {
|
||||
CommandOpts::Update { command } => command.try_execute(),
|
||||
|
||||
CommandOpts::Add { command } => command.try_execute(),
|
||||
CommandOpts::Clone { command } => command.try_execute(),
|
||||
CommandOpts::Login { command } => command.try_execute(),
|
||||
CommandOpts::Logout { command } => command.try_execute(),
|
||||
CommandOpts::Publish { command } => command.try_execute(),
|
||||
|
Loading…
Reference in New Issue
Block a user