Merge branch 'master' of github.com:AleoHQ/leo into feature/local-data-commitment

This commit is contained in:
collin 2020-08-16 00:30:48 -07:00
commit f9c68910b2
37 changed files with 244 additions and 108 deletions

View File

@ -12,14 +12,14 @@ the total number of constraints in the generate circuit can vary.
To illustrate this, here are two examples to show the difference: To illustrate this, here are two examples to show the difference:
``` ```
const = 00000001 constant = 00000001
variable = abcdefgh variable = abcdefgh
--------------------------------- ---------------------------------
output = 0000000h (1 constraint) output = 0000000h (1 constraint)
``` ```
``` ```
const = 01110001 constant = 01110001
variable = abcdefgh variable = abcdefgh
--------------------------------- ---------------------------------
output = 0bcd000h (4 constraints) output = 0bcd000h (4 constraints)

View File

@ -17,7 +17,7 @@ pub enum ParserError {
#[error("{}", _0)] #[error("{}", _0)]
SyntaxError(#[from] SyntaxError), SyntaxError(#[from] SyntaxError),
#[error("Unable to construct abstract syntax tree")] #[error("Unable to construct program abstract syntax tree")]
SyntaxTreeError, SyntaxTreeError,
} }

View File

@ -35,6 +35,11 @@ impl From<Error<Rule>> for SyntaxError {
Rule::operation_div => "`/`".to_owned(), Rule::operation_div => "`/`".to_owned(),
Rule::operation_pow => "`**`".to_owned(), Rule::operation_pow => "`**`".to_owned(),
Rule::package => "package. Check package and import names for errors.".to_owned(),
Rule::package_name => {
"package name. Please use lowercase letters, numbers, and dashes `-` only.".to_owned()
}
rule => format!("{:?}", rule), rule => format!("{:?}", rule),
}); });

View File

@ -10,5 +10,8 @@ pub use package::*;
pub mod package_access; pub mod package_access;
pub use package_access::*; pub use package_access::*;
pub mod package_name;
pub use package_name::*;
pub mod star; pub mod star;
pub use star::*; pub use star::*;

View File

@ -1,4 +1,8 @@
use crate::{ast::Rule, common::Identifier, imports::PackageAccess, SpanDef}; use crate::{
ast::Rule,
imports::{PackageAccess, PackageName},
SpanDef,
};
use pest::Span; use pest::Span;
use pest_ast::FromPest; use pest_ast::FromPest;
@ -7,7 +11,7 @@ use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::package))] #[pest_ast(rule(Rule::package))]
pub struct Package<'ast> { pub struct Package<'ast> {
pub name: Identifier<'ast>, pub name: PackageName<'ast>,
pub access: PackageAccess<'ast>, pub access: PackageAccess<'ast>,
#[pest_ast(outer())] #[pest_ast(outer())]
#[serde(with = "SpanDef")] #[serde(with = "SpanDef")]

View File

@ -0,0 +1,25 @@
use crate::{
ast::{span_into_string, Rule},
SpanDef,
};
use pest::Span;
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::package_name))]
pub struct PackageName<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub value: String,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for PackageName<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.value)
}
}

View File

@ -389,8 +389,11 @@ input_tuple = _{ "(" ~ NEWLINE* ~ (input ~ ("," ~ NEWLINE* ~ input)* ~ ","?)? ~
// Declared in imports/import.rs // Declared in imports/import.rs
import = { "import " ~ package ~ LINE_END} import = { "import " ~ package ~ LINE_END}
package_name = @{ ((ASCII_ALPHA_LOWER | ASCII_DIGIT) ~ ( "-" ~ (ASCII_ALPHA_LOWER | ASCII_DIGIT))*)+ }
// Declared in imports/package.rs // Declared in imports/package.rs
package = { identifier ~ "." ~ package_access } package = { package_name ~ "." ~ package_access }
// Declared in imports/package_access // Declared in imports/package_access
package_access = { package_access = {

View File

@ -13,24 +13,24 @@ use snarkos_models::curves::{Field, PrimeField};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> { impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn store_definitions(&mut self, program: Program, imported_programs: &ImportParser) -> Result<(), ImportError> { pub fn store_definitions(&mut self, program: Program, imported_programs: &ImportParser) -> Result<(), ImportError> {
let program_name = program.name.clone(); let program_name = program.name.trim_end_matches(".leo");
// evaluate all import statements and store imported definitions // evaluate all import statements and store imported definitions
program program
.imports .imports
.iter() .iter()
.map(|import| self.store_import(program_name.clone(), import, imported_programs)) .map(|import| self.store_import(program_name.to_owned(), import, imported_programs))
.collect::<Result<Vec<_>, ImportError>>()?; .collect::<Result<Vec<_>, ImportError>>()?;
// evaluate and store all circuit definitions // evaluate and store all circuit definitions
program.circuits.into_iter().for_each(|(identifier, circuit)| { program.circuits.into_iter().for_each(|(identifier, circuit)| {
let resolved_circuit_name = new_scope(program_name.clone(), identifier.to_string()); let resolved_circuit_name = new_scope(program_name.to_owned(), identifier.to_string());
self.store(resolved_circuit_name, ConstrainedValue::CircuitDefinition(circuit)); self.store(resolved_circuit_name, ConstrainedValue::CircuitDefinition(circuit));
}); });
// evaluate and store all function definitions // evaluate and store all function definitions
program.functions.into_iter().for_each(|(function_name, function)| { program.functions.into_iter().for_each(|(function_name, function)| {
let resolved_function_name = new_scope(program_name.clone(), function_name.to_string()); let resolved_function_name = new_scope(program_name.to_owned(), function_name.to_string());
self.store(resolved_function_name, ConstrainedValue::Function(None, function)); self.store(resolved_function_name, ConstrainedValue::Function(None, function));
}); });

View File

@ -10,23 +10,19 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
import: &Import, import: &Import,
imported_programs: &ImportParser, imported_programs: &ImportParser,
) -> Result<(), ImportError> { ) -> Result<(), ImportError> {
// get imported program name from import // fetch dependencies for the current import
// get imported symbols from from import
let imported_symbols = ImportedSymbols::from(import); let imported_symbols = ImportedSymbols::from(import);
for (package, symbol) in imported_symbols.symbols { for (package, symbol) in imported_symbols.symbols {
// get imported program from hashmap // find imported program
let program = imported_programs let program = imported_programs
.get(&package) .get(&package)
.ok_or(ImportError::unknown_package(import.package.name.clone()))?; .ok_or(ImportError::unknown_package(import.package.name.clone()))?;
// resolve imported program's import statements // parse imported program
program self.store_definitions(program.clone(), imported_programs)?;
.imports
.iter()
.map(|import| self.store_import(package.clone(), import, imported_programs))
.collect::<Result<Vec<()>, ImportError>>()?;
// store the imported symbol
self.store_symbol(scope.clone(), package, &symbol, program)?; self.store_symbol(scope.clone(), package, &symbol, program)?;
} }

View File

@ -11,6 +11,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
symbol: &ImportSymbol, symbol: &ImportSymbol,
program: &Program, program: &Program,
) -> Result<(), ImportError> { ) -> Result<(), ImportError> {
// Store the symbol that was imported by another file
if symbol.is_star() { if symbol.is_star() {
// evaluate and store all circuit definitions // evaluate and store all circuit definitions
program.circuits.iter().for_each(|(identifier, circuit)| { program.circuits.iter().for_each(|(identifier, circuit)| {

View File

@ -1,4 +1,4 @@
import test_import.foo; import test-import.foo;
function main() { function main() {
assert_eq!(foo(), 1u32); assert_eq!(foo(), 1u32);

View File

@ -1,4 +1,4 @@
import test_import.( // local import import test-import.( // local import
Point, Point,
foo, foo,
); );

View File

@ -1,4 +1,4 @@
import test_import.*; // local import import test-import.*; // local import
import bar.*; // imports directory import import bar.*; // imports directory import
import bar.baz.*; // imports directory import import bar.baz.*; // imports directory import

View File

@ -66,6 +66,54 @@ fn test_alias() {
assert_satisfied(program); assert_satisfied(program);
} }
// naming tests
#[test]
#[ignore]
fn test_names_pass() {
set_local_dir();
let bytes = include_bytes!("names.leo");
let program = parse_program(bytes).unwrap();
assert_satisfied(program);
}
#[test]
#[ignore]
fn test_names_fail_1() {
set_local_dir();
let bytes = include_bytes!("names_dash_a.leo");
assert!(parse_program(bytes).is_err());
}
#[test]
#[ignore]
fn test_names_fail_2() {
set_local_dir();
let bytes = include_bytes!("names_a_dash.leo");
assert!(parse_program(bytes).is_err());
}
#[test]
#[ignore]
fn test_names_fail_3() {
set_local_dir();
let bytes = include_bytes!("names_underscore.leo");
assert!(parse_program(bytes).is_err());
}
#[test]
#[ignore]
fn test_names_fail_4() {
set_local_dir();
let bytes = include_bytes!("names_dollar.leo");
assert!(parse_program(bytes).is_err());
}
// more complex tests // more complex tests
#[test] #[test]
#[ignore] #[ignore]

View File

@ -1,4 +1,4 @@
import test_import.( import test-import.(
Point, Point,
foo foo
); );

View File

@ -0,0 +1,5 @@
import a0-f.foo;
import a-9.bar;
import hello-world.hello;
function main() {}

View File

@ -0,0 +1,3 @@
import a-.foo;
function main() {}

View File

@ -0,0 +1,3 @@
import -a.foo;
function main() {}

View File

@ -0,0 +1,3 @@
import money$.foo;
function main() {}

View File

@ -0,0 +1,3 @@
import hello_world.foo;
function main() {}

View File

@ -0,0 +1 @@
function bar() {}

View File

@ -0,0 +1 @@
function foo() {}

View File

@ -0,0 +1 @@
function hello() {}

View File

@ -1,4 +1,4 @@
import test_import.*; import test-import.*;
function main() { function main() {
let a = Point { x: 1u32, y: 0u32 }; let a = Point { x: 1u32, y: 0u32 };

View File

@ -31,7 +31,7 @@ pub enum InputParserError {
#[error("{}", _0)] #[error("{}", _0)]
SyntaxError(#[from] InputSyntaxError), SyntaxError(#[from] InputSyntaxError),
#[error("Unable to construct abstract syntax tree")] #[error("Unable to construct program input abstract syntax tree")]
SyntaxTreeError, SyntaxTreeError,
} }

View File

@ -13,16 +13,16 @@ use clap::ArgMatches;
use std::{convert::TryFrom, env::current_dir}; use std::{convert::TryFrom, env::current_dir};
#[derive(Debug)] #[derive(Debug)]
pub struct LoadCommand; pub struct AddCommand;
impl CLI for LoadCommand { impl CLI for AddCommand {
type Options = (); type Options = ();
type Output = (); type Output = ();
const ABOUT: AboutType = "Install a package from the package manager (*)"; const ABOUT: AboutType = "Install a package from the package manager (*)";
const ARGUMENTS: &'static [ArgumentType] = &[]; const ARGUMENTS: &'static [ArgumentType] = &[];
const FLAGS: &'static [FlagType] = &[]; const FLAGS: &'static [FlagType] = &[];
const NAME: NameType = "load"; const NAME: NameType = "add";
const OPTIONS: &'static [OptionType] = &[]; const OPTIONS: &'static [OptionType] = &[];
const SUBCOMMANDS: &'static [SubCommandType] = &[]; const SUBCOMMANDS: &'static [SubCommandType] = &[];
@ -39,7 +39,7 @@ impl CLI for LoadCommand {
// Get the package name // Get the package name
let _package_name = Manifest::try_from(&path)?.get_package_name(); let _package_name = Manifest::try_from(&path)?.get_package_name();
log::info!("Unimplemented - `leo load`"); log::info!("Unimplemented - `leo add`");
Ok(()) Ok(())
} }

View File

@ -1,19 +1,12 @@
// //
// Usege: // Usage:
// //
// leo login <token> // leo login <token>
// leo login -u username -p password // leo login -u username -p password
// leo login // not yet implemented // leo login // not yet implemented
// //
use crate::{ use crate::{cli::CLI, cli_types::*, errors::LoginError};
cli::CLI,
cli_types::*,
errors::{
CLIError::LoginError,
LoginError::{CannotGetToken, ConnectionUnavalaible, WrongLoginOrPassword},
},
};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::{ use std::{
collections::HashMap, collections::HashMap,
@ -56,10 +49,15 @@ impl CLI for LoginCommand {
type Options = (Option<String>, Option<String>, Option<String>); type Options = (Option<String>, Option<String>, Option<String>);
type Output = String; type Output = String;
const ABOUT: AboutType = "Login to the package manager (*)"; const ABOUT: AboutType = "Login to the Aleo Package Manager";
const ARGUMENTS: &'static [ArgumentType] = &[ const ARGUMENTS: &'static [ArgumentType] = &[
// (name, description, required, index) // (name, description, required, index)
("NAME", "Sets token for login to the package manager", false, 1u64), (
"NAME",
"Sets the authentication token for login to the package manager",
false,
1u64,
),
]; ];
const FLAGS: &'static [FlagType] = &[]; const FLAGS: &'static [FlagType] = &[];
const NAME: NameType = "login"; const NAME: NameType = "login";
@ -91,7 +89,7 @@ impl CLI for LoginCommand {
fn output(options: Self::Options) -> Result<Self::Output, crate::errors::CLIError> { fn output(options: Self::Options) -> Result<Self::Output, crate::errors::CLIError> {
let token = match options { let token = match options {
// Login using existing token // Login using existing token
(Some(token), _, _) => token, (Some(token), _, _) => Some(token),
// Login using username and password // Login using username and password
(None, Some(username), Some(password)) => { (None, Some(username), Some(password)) => {
@ -107,37 +105,50 @@ impl CLI for LoginCommand {
Ok(json) => json, Ok(json) => json,
Err(_error) => { Err(_error) => {
log::error!("Wrong login or password"); log::error!("Wrong login or password");
return Err(LoginError(WrongLoginOrPassword("Wrong login or password".into()))); return Err(LoginError::WrongLoginOrPassword("Wrong login or password".into()).into());
} }
}, },
//Cannot connect to the server //Cannot connect to the server
Err(_error) => { Err(_error) => {
return Err(LoginError(ConnectionUnavalaible( return Err(
"Could not connect to the package manager".into(), LoginError::NoConnectionFound("Could not connect to the package manager".into()).into(),
))); );
} }
}; };
match response.get("token") { match response.get("token") {
Some(token) => token.clone(), Some(token) => Some(token.clone()),
None => return Err(LoginError(CannotGetToken("There is no token".into()))), None => {
return Err(LoginError::CannotGetToken("No token was provided in the response".into()).into());
}
} }
} }
// Login using JWT // Login using JWT
(_, _, _) => { (_, _, _) => {
// TODO JWT // TODO JWT
unimplemented!() None
} }
}; };
match token {
Some(token) => {
// Create Leo credentials directory if it not exists // Create Leo credentials directory if it not exists
if !Path::new(LEO_CREDENTIALS_DIR).exists() { if !Path::new(LEO_CREDENTIALS_DIR).exists() {
create_dir(LEO_CREDENTIALS_DIR)?; create_dir(LEO_CREDENTIALS_DIR)?;
} }
LoginCommand::write_token(token.as_str())?; LoginCommand::write_token(token.as_str())?;
log::info!("Successfully logged in");
log::info!("Login successful.");
Ok(token) Ok(token)
} }
_ => {
log::error!("Failed to login. Please run `leo login -h` for help.");
Err(LoginError::NoCredentialsProvided.into())
}
}
}
} }

View File

@ -13,8 +13,8 @@ pub use self::init::*;
pub mod lint; pub mod lint;
pub use self::lint::*; pub use self::lint::*;
pub mod load; pub mod add;
pub use self::load::*; pub use self::add::*;
pub mod login; pub mod login;
pub use self::login::*; pub use self::login::*;
@ -37,8 +37,8 @@ pub use self::setup::*;
pub mod test; pub mod test;
pub use self::test::*; pub use self::test::*;
pub mod unload; pub mod remove;
pub use self::unload::*; pub use self::remove::*;
pub mod watch; pub mod watch;
pub use self::watch::*; pub use self::watch::*;

View File

@ -8,11 +8,12 @@ use crate::{
CLIError::PublishError, CLIError::PublishError,
}, },
}; };
use clap::ArgMatches;
use leo_package::{ use leo_package::{
outputs::OutputsDirectory, outputs::OutputsDirectory,
root::{Manifest, ZipFile}, root::{Manifest, ZipFile},
}; };
use clap::ArgMatches;
use reqwest::{ use reqwest::{
blocking::{multipart::Form, Client}, blocking::{multipart::Form, Client},
header::{HeaderMap, HeaderValue}, header::{HeaderMap, HeaderValue},
@ -36,16 +37,8 @@ impl CLI for PublishCommand {
type Options = (); type Options = ();
type Output = Option<String>; type Output = Option<String>;
const ABOUT: AboutType = "Publish the current package to the package manager (*)"; const ABOUT: AboutType = "Publish the current package to the Aleo 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] = &[];
@ -53,17 +46,12 @@ 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
// let _output = BuildCommand::output(options)?; // let _output = BuildCommand::output(options)?;
// Get the package name // Get the package name
@ -77,7 +65,9 @@ impl CLI for PublishCommand {
// Create zip file // Create zip file
let zip_file = ZipFile::new(&package_name); let zip_file = ZipFile::new(&package_name);
if zip_file.exists_at(&path) { if zip_file.exists_at(&path) {
log::info!("Existing package zip file found. Skipping compression.") log::debug!("Existing package zip file found. Clearing it to regenerate.");
// Remove the existing package zip file
ZipFile::new(&package_name).remove(&path)?;
} else { } else {
zip_file.write(&path)?; zip_file.write(&path)?;
} }
@ -94,8 +84,8 @@ impl CLI for PublishCommand {
let token = match LoginCommand::read_token() { let token = match LoginCommand::read_token() {
Ok(token) => token, Ok(token) => token,
// If not logged then try to login using JWT // If not logged in, then try logging in using JWT.
Err(_errorr) => { Err(_error) => {
log::warn!("You should be logged before publish the package"); log::warn!("You should be logged before publish the package");
log::info!("Trying to log in using JWT..."); log::info!("Trying to log in using JWT...");
let options = (None, None, None); let options = (None, None, None);
@ -133,7 +123,7 @@ impl CLI for PublishCommand {
} }
}; };
log::info!("Packge published successfully"); log::info!("Package published successfully");
Ok(Some(result.package_id)) Ok(Some(result.package_id))
} }
} }

View File

@ -13,16 +13,16 @@ use clap::ArgMatches;
use std::{convert::TryFrom, env::current_dir}; use std::{convert::TryFrom, env::current_dir};
#[derive(Debug)] #[derive(Debug)]
pub struct UnloadCommand; pub struct RemoveCommand;
impl CLI for UnloadCommand { impl CLI for RemoveCommand {
type Options = (); type Options = ();
type Output = (); type Output = ();
const ABOUT: AboutType = "Uninstall a package from the current package (*)"; const ABOUT: AboutType = "Uninstall a package from the current package (*)";
const ARGUMENTS: &'static [ArgumentType] = &[]; const ARGUMENTS: &'static [ArgumentType] = &[];
const FLAGS: &'static [FlagType] = &[]; const FLAGS: &'static [FlagType] = &[];
const NAME: NameType = "unload"; const NAME: NameType = "remove";
const OPTIONS: &'static [OptionType] = &[]; const OPTIONS: &'static [OptionType] = &[];
const SUBCOMMANDS: &'static [SubCommandType] = &[]; const SUBCOMMANDS: &'static [SubCommandType] = &[];
@ -40,7 +40,7 @@ impl CLI for UnloadCommand {
// Get the package name // Get the package name
let _package_name = Manifest::try_from(&path)?.get_package_name(); let _package_name = Manifest::try_from(&path)?.get_package_name();
log::info!("Unimplemented - `leo load`"); log::info!("Unimplemented - `leo remove`");
Ok(()) Ok(())
} }

View File

@ -31,7 +31,7 @@ impl CLI for WatchCommand {
let mut watcher = watcher(tx, Duration::from_secs(INTERVAL)).unwrap(); let mut watcher = watcher(tx, Duration::from_secs(INTERVAL)).unwrap();
watcher.watch(LEO_SOURCE_DIR, RecursiveMode::Recursive).unwrap(); watcher.watch(LEO_SOURCE_DIR, RecursiveMode::Recursive).unwrap();
log::info!("Watching leo's source files"); log::info!("Watching Leo source code");
loop { loop {
match rx.recv() { match rx.recv() {
// See changes on the write event // See changes on the write event
@ -39,7 +39,7 @@ impl CLI for WatchCommand {
let options = (); let options = ();
match BuildCommand::output(options) { match BuildCommand::output(options) {
Ok(_output) => { Ok(_output) => {
log::info!("Build successfully"); log::info!("Built successfully");
} }
Err(e) => { Err(e) => {
// Syntax error // Syntax error
@ -51,9 +51,11 @@ impl CLI for WatchCommand {
Ok(_event) => {} Ok(_event) => {}
// Watch error // Watch error
Err(e) => println!("watch error: {:?}", e), Err(e) => {
log::error!("watch error: {:?}", e)
// TODO (howardwu): Add graceful termination.
}
} }
} }
// Ok(())
} }
} }

View File

@ -5,9 +5,12 @@ pub enum LoginError {
#[error("{:?}", _0)] #[error("{:?}", _0)]
CannotGetToken(OsString), CannotGetToken(OsString),
#[error("connectin unavalaible {:?}", _0)] #[error("No connection found {:?}", _0)]
ConnectionUnavalaible(OsString), NoConnectionFound(OsString),
#[error("wrong login or password {:?}", _0)] #[error("No login credentials were provided")]
NoCredentialsProvided,
#[error("Wrong login or password {:?}", _0)]
WrongLoginOrPassword(OsString), WrongLoginOrPassword(OsString),
} }

View File

@ -23,18 +23,18 @@ fn main() -> Result<(), CLIError> {
NewCommand::new().display_order(0), NewCommand::new().display_order(0),
InitCommand::new().display_order(1), InitCommand::new().display_order(1),
BuildCommand::new().display_order(2), BuildCommand::new().display_order(2),
TestCommand::new().display_order(3), WatchCommand::new().display_order(3),
LintCommand::new().display_order(4), TestCommand::new().display_order(4),
LoadCommand::new().display_order(5), SetupCommand::new().display_order(5),
UnloadCommand::new().display_order(6), ProveCommand::new().display_order(6),
SetupCommand::new().display_order(7), RunCommand::new().display_order(7),
ProveCommand::new().display_order(8), LoginCommand::new().display_order(8),
RunCommand::new().display_order(9), AddCommand::new().display_order(9),
LoginCommand::new().display_order(10), RemoveCommand::new().display_order(10),
PublishCommand::new().display_order(11), PublishCommand::new().display_order(11),
DeployCommand::new().display_order(12), DeployCommand::new().display_order(12),
CleanCommand::new().display_order(13), CleanCommand::new().display_order(13),
WatchCommand::new().display_order(14), LintCommand::new().display_order(14),
]) ])
.set_term_width(0) .set_term_width(0)
.get_matches(); .get_matches();
@ -43,18 +43,18 @@ fn main() -> Result<(), CLIError> {
("new", Some(arguments)) => NewCommand::process(arguments), ("new", Some(arguments)) => NewCommand::process(arguments),
("init", Some(arguments)) => InitCommand::process(arguments), ("init", Some(arguments)) => InitCommand::process(arguments),
("build", Some(arguments)) => BuildCommand::process(arguments), ("build", Some(arguments)) => BuildCommand::process(arguments),
("watch", Some(arguments)) => WatchCommand::process(arguments),
("test", Some(arguments)) => TestCommand::process(arguments), ("test", Some(arguments)) => TestCommand::process(arguments),
("lint", Some(arguments)) => LintCommand::process(arguments),
("load", Some(arguments)) => LoadCommand::process(arguments),
("unload", Some(arguments)) => UnloadCommand::process(arguments),
("setup", Some(arguments)) => SetupCommand::process(arguments), ("setup", Some(arguments)) => SetupCommand::process(arguments),
("prove", Some(arguments)) => ProveCommand::process(arguments), ("prove", Some(arguments)) => ProveCommand::process(arguments),
("run", Some(arguments)) => RunCommand::process(arguments), ("run", Some(arguments)) => RunCommand::process(arguments),
("login", Some(arguments)) => LoginCommand::process(arguments), ("login", Some(arguments)) => LoginCommand::process(arguments),
("add", Some(arguments)) => AddCommand::process(arguments),
("remove", Some(arguments)) => RemoveCommand::process(arguments),
("publish", Some(arguments)) => PublishCommand::process(arguments), ("publish", Some(arguments)) => PublishCommand::process(arguments),
("deploy", Some(arguments)) => DeployCommand::process(arguments), ("deploy", Some(arguments)) => DeployCommand::process(arguments),
("clean", Some(arguments)) => CleanCommand::process(arguments), ("clean", Some(arguments)) => CleanCommand::process(arguments),
("watch", Some(arguments)) => WatchCommand::process(arguments), ("lint", Some(arguments)) => LintCommand::process(arguments),
_ => unreachable!(), _ => unreachable!(),
} }
} }

View File

@ -13,6 +13,9 @@ pub enum ZipFileError {
#[error("Cannot read from the provided file path - {:?}", _0)] #[error("Cannot read from the provided file path - {:?}", _0)]
FileReadError(PathBuf), FileReadError(PathBuf),
#[error("Cannot remove the provided file - {:?}", _0)]
FileRemovalError(PathBuf),
#[error("writing: {}", _0)] #[error("writing: {}", _0)]
Writing(io::Error), Writing(io::Error),

View File

@ -16,7 +16,7 @@ use crate::{
use serde::Deserialize; use serde::Deserialize;
use std::{ use std::{
fs::File, fs::{self, File},
io::{Read, Write}, io::{Read, Write},
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
@ -80,7 +80,7 @@ impl ZipFile {
// write file or directory // write file or directory
if path.is_file() { if path.is_file() {
log::info!("\tadding file {:?} as {:?}", path, name); log::info!("Adding file {:?} as {:?}", path, name);
zip.start_file_from_path(name, options)?; zip.start_file_from_path(name, options)?;
let mut f = File::open(path)?; let mut f = File::open(path)?;
@ -90,7 +90,7 @@ impl ZipFile {
} else if name.as_os_str().len() != 0 { } else if name.as_os_str().len() != 0 {
// Only if not root Avoids path spec / warning // Only if not root Avoids path spec / warning
// and mapname conversion failed error on unzip // and mapname conversion failed error on unzip
log::info!("\tadding dir {:?} as {:?}", path, name); log::info!("Adding directory {:?} as {:?}", path, name);
zip.add_directory_from_path(name, options)?; zip.add_directory_from_path(name, options)?;
} }
} }
@ -102,6 +102,18 @@ impl ZipFile {
Ok(()) Ok(())
} }
/// Removes the zip file at the given path if it exists. Returns `true` on success,
/// `false` if the file doesn't exist, and `Error` if the file system fails during operation.
pub fn remove(&self, path: &PathBuf) -> Result<bool, ZipFileError> {
let path = self.setup_file_path(path);
if !path.exists() {
return Ok(false);
}
fs::remove_file(&path).map_err(|_| ZipFileError::FileRemovalError(path.clone()))?;
Ok(true)
}
fn setup_file_path(&self, path: &PathBuf) -> PathBuf { fn setup_file_path(&self, path: &PathBuf) -> PathBuf {
let mut path = path.to_owned(); let mut path = path.to_owned();
if path.is_dir() { if path.is_dir() {
@ -115,11 +127,12 @@ impl ZipFile {
} }
fn is_excluded(path: &Path) -> bool { fn is_excluded(path: &Path) -> bool {
log::debug!("Checking if {:?} is excluded", path);
// excluded directories: `input`, `output`, `imports` // excluded directories: `input`, `output`, `imports`
if path.ends_with(INPUTS_DIRECTORY_NAME.trim_end_matches("/")) if path.ends_with(INPUTS_DIRECTORY_NAME.trim_end_matches("/"))
| path.ends_with(OUTPUTS_DIRECTORY_NAME.trim_end_matches("/")) | path.ends_with(OUTPUTS_DIRECTORY_NAME.trim_end_matches("/"))
| path.ends_with(IMPORTS_DIRECTORY_NAME.trim_end_matches("/")) | path.ends_with(IMPORTS_DIRECTORY_NAME.trim_end_matches("/"))
| path.starts_with(INPUTS_DIRECTORY_NAME)
{ {
return true; return true;
} }

View File

@ -1,5 +1,5 @@
use crate::Span; use crate::Span;
use leo_ast::common::Identifier as AstIdentifier; use leo_ast::{common::Identifier as AstIdentifier, imports::PackageName as AstPackageName};
use leo_input::common::Identifier as InputAstIdentifier; use leo_input::common::Identifier as InputAstIdentifier;
use serde::{ use serde::{
@ -37,6 +37,15 @@ impl<'ast> From<AstIdentifier<'ast>> for Identifier {
} }
} }
impl<'ast> From<AstPackageName<'ast>> for Identifier {
fn from(name: AstPackageName<'ast>) -> Self {
Self {
name: name.value,
span: Span::from(name.span),
}
}
}
impl<'ast> From<InputAstIdentifier<'ast>> for Identifier { impl<'ast> From<InputAstIdentifier<'ast>> for Identifier {
fn from(identifier: InputAstIdentifier<'ast>) -> Self { fn from(identifier: InputAstIdentifier<'ast>) -> Self {
Self { Self {