diff --git a/leo/commands/build.rs b/leo/commands/build.rs index badfec2e15..392859e238 100644 --- a/leo/commands/build.rs +++ b/leo/commands/build.rs @@ -45,7 +45,7 @@ impl Command for Build { tracing::span!(tracing::Level::INFO, "Build") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/clean.rs b/leo/commands/clean.rs index 0b39661f07..83c2503555 100644 --- a/leo/commands/clean.rs +++ b/leo/commands/clean.rs @@ -35,7 +35,7 @@ impl Command for Clean { tracing::span!(tracing::Level::INFO, "Cleaning") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/deploy.rs b/leo/commands/deploy.rs index 06eff0c2e6..fa421e14ab 100644 --- a/leo/commands/deploy.rs +++ b/leo/commands/deploy.rs @@ -33,7 +33,7 @@ impl Command for Deploy { tracing::span!(tracing::Level::INFO, "Deploy") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/init.rs b/leo/commands/init.rs index 7c6b3e7745..a4d07a9137 100644 --- a/leo/commands/init.rs +++ b/leo/commands/init.rs @@ -35,7 +35,7 @@ impl Command for Init { tracing::span!(tracing::Level::INFO, "Initializing") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/lint.rs b/leo/commands/lint.rs index 3e60d7ec6e..c3f948acc9 100644 --- a/leo/commands/lint.rs +++ b/leo/commands/lint.rs @@ -33,7 +33,7 @@ impl Command for Lint { tracing::span!(tracing::Level::INFO, "Linting") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/mod.rs b/leo/commands/mod.rs index 47d5994575..7f5f2349fb 100644 --- a/leo/commands/mod.rs +++ b/leo/commands/mod.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::context::{get_context, Context}; +use crate::context::Context; use anyhow::Result; use std::time::Instant; @@ -72,11 +72,6 @@ pub trait Command { /// this field may be left empty. type Output; - /// Returns the project context, which is defined as the current directory. - fn context(&self) -> Result { - get_context() - } - /// Adds a span to the logger via `tracing::span`. /// Because of the specifics of the macro implementation, it is not possible /// to set the span name with a non-literal i.e. a dynamic variable even if this @@ -86,7 +81,7 @@ pub trait Command { } /// Runs the prelude and returns the Input of the current command. - fn prelude(&self) -> Result + fn prelude(&self, context: Context) -> Result where Self: std::marker::Sized; @@ -98,11 +93,11 @@ pub trait Command { /// A wrapper around the `apply` method. /// This function sets up tracing, timing, and the context. - fn execute(self) -> Result + fn execute(self, context: Context) -> Result where Self: std::marker::Sized, { - let input = self.prelude()?; + let input = self.prelude(context.clone())?; // Create the span for this command. let span = self.log_span(); @@ -110,8 +105,6 @@ pub trait Command { // Calculate the execution time for this command. let timer = Instant::now(); - - let context = self.context()?; let out = self.apply(context, input); drop(span); @@ -127,10 +120,10 @@ pub trait Command { /// Executes command but empty the result. Comes in handy where there's a /// need to make match arms compatible while keeping implementation-specific /// output possible. Errors however are all of the type Error - fn try_execute(self) -> Result<()> + fn try_execute(self, context: Context) -> Result<()> where Self: std::marker::Sized, { - self.execute().map(|_| Ok(()))? + self.execute(context).map(|_| Ok(()))? } } diff --git a/leo/commands/new.rs b/leo/commands/new.rs index a4da67c309..c77448cfc4 100644 --- a/leo/commands/new.rs +++ b/leo/commands/new.rs @@ -38,7 +38,7 @@ impl Command for New { tracing::span!(tracing::Level::INFO, "New") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/package/add.rs b/leo/commands/package/add.rs index ef1491f2f9..5b540617ba 100644 --- a/leo/commands/package/add.rs +++ b/leo/commands/package/add.rs @@ -86,7 +86,7 @@ impl Command for Add { tracing::span!(tracing::Level::INFO, "Adding") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/package/clone.rs b/leo/commands/package/clone.rs index 5b5e6acdcf..92cad951cd 100644 --- a/leo/commands/package/clone.rs +++ b/leo/commands/package/clone.rs @@ -103,7 +103,7 @@ impl Command for Clone { tracing::span!(tracing::Level::INFO, "Cloning") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/package/login.rs b/leo/commands/package/login.rs index 25425fccb0..495f52b6e5 100644 --- a/leo/commands/package/login.rs +++ b/leo/commands/package/login.rs @@ -54,7 +54,7 @@ impl Command for Login { tracing::span!(tracing::Level::INFO, "Login") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/package/logout.rs b/leo/commands/package/logout.rs index 6bd76a2575..c6018854ef 100644 --- a/leo/commands/package/logout.rs +++ b/leo/commands/package/logout.rs @@ -34,7 +34,7 @@ impl Command for Logout { tracing::span!(tracing::Level::INFO, "Logout") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/package/publish.rs b/leo/commands/package/publish.rs index 7b86763c67..088949600b 100644 --- a/leo/commands/package/publish.rs +++ b/leo/commands/package/publish.rs @@ -46,8 +46,8 @@ impl Command for Publish { type Output = Option; /// Build program before publishing - fn prelude(&self) -> Result { - (Build {}).execute() + fn prelude(&self, context: Context) -> Result { + (Build {}).execute(context) } fn apply(self, context: Context, _input: Self::Input) -> Result { diff --git a/leo/commands/package/remove.rs b/leo/commands/package/remove.rs index f0df722146..1f5426062c 100644 --- a/leo/commands/package/remove.rs +++ b/leo/commands/package/remove.rs @@ -37,7 +37,7 @@ impl Command for Remove { tracing::span!(tracing::Level::INFO, "Removing") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/prove.rs b/leo/commands/prove.rs index da99c84aed..79c12fefcc 100644 --- a/leo/commands/prove.rs +++ b/leo/commands/prove.rs @@ -45,9 +45,9 @@ impl Command for Prove { tracing::span!(tracing::Level::INFO, "Proving") } - fn prelude(&self) -> Result { + fn prelude(&self, context: Context) -> Result { let skip_key_check = self.skip_key_check; - (Setup { skip_key_check }).execute() + (Setup { skip_key_check }).execute(context) } fn apply(self, context: Context, input: Self::Input) -> Result { diff --git a/leo/commands/run.rs b/leo/commands/run.rs index eeec6fc02d..cfdac6f6ac 100644 --- a/leo/commands/run.rs +++ b/leo/commands/run.rs @@ -40,9 +40,9 @@ impl Command for Run { tracing::span!(tracing::Level::INFO, "Verifying") } - fn prelude(&self) -> Result { + fn prelude(&self, context: Context) -> Result { let skip_key_check = self.skip_key_check; - (Prove { skip_key_check }).execute() + (Prove { skip_key_check }).execute(context) } fn apply(self, _context: Context, input: Self::Input) -> Result { diff --git a/leo/commands/setup.rs b/leo/commands/setup.rs index df1d3a0537..2553129f7d 100644 --- a/leo/commands/setup.rs +++ b/leo/commands/setup.rs @@ -49,8 +49,8 @@ impl Command for Setup { tracing::span!(tracing::Level::INFO, "Setup") } - fn prelude(&self) -> Result { - (Build {}).execute() + fn prelude(&self, context: Context) -> Result { + (Build {}).execute(context) } fn apply(self, context: Context, input: Self::Input) -> Result { diff --git a/leo/commands/test.rs b/leo/commands/test.rs index f5de8672f2..4810b8189a 100644 --- a/leo/commands/test.rs +++ b/leo/commands/test.rs @@ -47,7 +47,7 @@ impl Command for Test { tracing::span!(tracing::Level::INFO, "Test") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/update.rs b/leo/commands/update.rs index f3027e5907..605633b730 100644 --- a/leo/commands/update.rs +++ b/leo/commands/update.rs @@ -54,7 +54,7 @@ impl Command for Update { tracing::span!(tracing::Level::INFO, "Updating") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } diff --git a/leo/commands/watch.rs b/leo/commands/watch.rs index 7a98b9604f..77e9e5f304 100644 --- a/leo/commands/watch.rs +++ b/leo/commands/watch.rs @@ -43,11 +43,11 @@ impl Command for Watch { tracing::span!(tracing::Level::INFO, "Watching") } - fn prelude(&self) -> Result { + fn prelude(&self, _: Context) -> Result { Ok(()) } - fn apply(self, _context: Context, _: Self::Input) -> Result { + fn apply(self, context: Context, _: Self::Input) -> Result { let (tx, rx) = channel(); let mut watcher = watcher(tx, Duration::from_secs(self.interval)).unwrap(); @@ -64,7 +64,7 @@ impl Command for Watch { match rx.recv() { // See changes on the write event Ok(DebouncedEvent::Write(_write)) => { - match (Build {}).execute() { + match (Build {}).execute(context.clone()) { Ok(_output) => { tracing::info!("Built successfully"); } diff --git a/leo/main.rs b/leo/main.rs index a0d256230c..226dbd89fb 100644 --- a/leo/main.rs +++ b/leo/main.rs @@ -39,7 +39,7 @@ use commands::{ }; use anyhow::Error; -use std::process::exit; +use std::{path::PathBuf, process::exit}; use structopt::{clap::AppSettings, StructOpt}; /// CLI Arguments entry point - includes global parameters and subcommands @@ -54,6 +54,9 @@ struct Opt { #[structopt(subcommand)] command: CommandOpts, + + #[structopt(short, long, help = "Optional path to Leo program root folder", parse(from_os_str))] + path: Option, } ///Leo compiler and package manager @@ -170,38 +173,45 @@ enum CommandOpts { } fn main() { - // read command line arguments + // Read command line arguments. let opt = Opt::from_args(); if !opt.quiet { - // init logger with optional debug flag + // Init logger with optional debug flag. logger::init_logger("leo", match opt.debug { false => 1, true => 2, }); } + // Get custom root folder and create context for it. + // If not specified, default context will be created in cwd. + let context = handle_error(match opt.path { + Some(path) => context::create_context(path), + None => context::get_context(), + }); + handle_error(match opt.command { - CommandOpts::Init { command } => command.try_execute(), - CommandOpts::New { command } => command.try_execute(), - CommandOpts::Build { command } => command.try_execute(), - CommandOpts::Setup { command } => command.try_execute(), - CommandOpts::Prove { command } => command.try_execute(), - CommandOpts::Test { command } => command.try_execute(), - CommandOpts::Run { command } => command.try_execute(), - CommandOpts::Clean { command } => command.try_execute(), - CommandOpts::Watch { command } => command.try_execute(), - CommandOpts::Update { command } => command.try_execute(), + CommandOpts::Init { command } => command.try_execute(context), + CommandOpts::New { command } => command.try_execute(context), + CommandOpts::Build { command } => command.try_execute(context), + CommandOpts::Setup { command } => command.try_execute(context), + CommandOpts::Prove { command } => command.try_execute(context), + CommandOpts::Test { command } => command.try_execute(context), + CommandOpts::Run { command } => command.try_execute(context), + CommandOpts::Clean { command } => command.try_execute(context), + CommandOpts::Watch { command } => command.try_execute(context), + CommandOpts::Update { command } => command.try_execute(context), - 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(), - CommandOpts::Remove { command } => command.try_execute(), + CommandOpts::Add { command } => command.try_execute(context), + CommandOpts::Clone { command } => command.try_execute(context), + CommandOpts::Login { command } => command.try_execute(context), + CommandOpts::Logout { command } => command.try_execute(context), + CommandOpts::Publish { command } => command.try_execute(context), + CommandOpts::Remove { command } => command.try_execute(context), - CommandOpts::Lint { command } => command.try_execute(), - CommandOpts::Deploy { command } => command.try_execute(), + CommandOpts::Lint { command } => command.try_execute(context), + CommandOpts::Deploy { command } => command.try_execute(context), }); }