diff --git a/Cargo.toml b/Cargo.toml
index 45e7674eae..3c3b014aeb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -45,7 +45,7 @@ path = "leo/lib.rs"
[[bin]]
name = "leo"
-path = "leo/main.rs"
+path = "leo/cli/main.rs"
[features]
default = [ ]
diff --git a/leo/main.rs b/leo/cli/cli.rs
similarity index 70%
rename from leo/main.rs
rename to leo/cli/cli.rs
index 7ff965588f..5751abd9b7 100644
--- a/leo/main.rs
+++ b/leo/cli/cli.rs
@@ -14,14 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-pub mod commands;
-pub mod context;
-pub mod logger;
-pub mod updater;
-
-use crate::{commands::*, context::*};
+use crate::cli::{commands::*, context::*, helpers::*};
use leo_errors::Result;
-use leo_span::symbol::create_session_if_not_set_then;
use clap::Parser;
use std::{path::PathBuf, process::exit};
@@ -75,6 +69,11 @@ enum Commands {
#[clap(flatten)]
command: Run,
},
+ #[clap(about = "Update the Leo CLI")]
+ Update {
+ #[clap(flatten)]
+ command: Update,
+ },
// #[clap(subcommand)]
// Node(Node),
// #[clap(about = "Deploy a program")]
@@ -84,30 +83,6 @@ enum Commands {
// },
}
-fn set_panic_hook() {
- #[cfg(not(debug_assertions))]
- std::panic::set_hook({
- Box::new(move |e| {
- eprintln!("thread `{}` {}", std::thread::current().name().unwrap_or(""), e);
- eprintln!("stack backtrace: \n{:?}", backtrace::Backtrace::new());
- eprintln!("error: internal compiler error: unexpected panic\n");
- eprintln!("note: the compiler unexpectedly panicked. this is a bug.\n");
- eprintln!(
- "note: we would appreciate a bug report: https://github.com/AleoHQ/leo/issues/new?labels=bug,panic&template=bug.md&title=[Bug]\n"
- );
- eprintln!(
- "note: {} {} running on {} {}\n",
- env!("CARGO_PKG_NAME"),
- env!("CARGO_PKG_VERSION"),
- sys_info::os_type().unwrap_or_else(|e| e.to_string()),
- sys_info::os_release().unwrap_or_else(|e| e.to_string()),
- );
- eprintln!("note: compiler args: {}\n", std::env::args().collect::>().join(" "));
- eprintln!("note: compiler flags: {:?}\n", CLI::parse());
- })
- });
-}
-
pub fn handle_error(res: Result) -> T {
match res {
Ok(t) => t,
@@ -137,12 +112,8 @@ pub fn run_with_args(cli: CLI) -> Result<()> {
Commands::Build { command } => command.try_execute(context),
Commands::Clean { command } => command.try_execute(context),
Commands::Run { command } => command.try_execute(context),
+ Commands::Update { command } => command.try_execute(context),
// Commands::Node(command) => command.try_execute(context),
// Commands::Deploy { command } => command.try_execute(context),
}
}
-
-fn main() {
- set_panic_hook();
- create_session_if_not_set_then(|_| handle_error(run_with_args(CLI::parse())));
-}
diff --git a/leo/commands/build.rs b/leo/cli/commands/build.rs
similarity index 84%
rename from leo/commands/build.rs
rename to leo/cli/commands/build.rs
index eda83f5a62..cb9f6f123f 100644
--- a/leo/commands/build.rs
+++ b/leo/cli/commands/build.rs
@@ -14,14 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-use crate::{
- commands::{Command, ALEO_CLI_COMMAND},
- context::Context,
-};
+use super::*;
use leo_ast::Struct;
use leo_compiler::{Compiler, CompilerOptions, InputAst, OutputOptions};
-use leo_errors::{emitter::Handler, CliError, CompilerError, PackageError, Result};
use leo_package::{
build::BuildDirectory,
imports::ImportsDirectory,
@@ -36,43 +32,12 @@ use snarkvm::{
prelude::{ProgramID, Testnet3},
};
-use clap::Parser;
use indexmap::IndexMap;
use std::{
io::Write,
path::{Path, PathBuf},
};
-use tracing::span::Span;
-
-/// Compiler Options wrapper for Build command. Also used by other commands which
-/// require Build command output as their input.
-#[derive(Parser, Clone, Debug, Default)]
-pub struct BuildOptions {
- #[clap(long, help = "Enables offline mode.")]
- pub offline: bool,
- #[clap(long, help = "Enable spans in AST snapshots.")]
- pub enable_spans: bool,
- #[clap(long, help = "Enables dead code elimination in the compiler.")]
- pub enable_dce: bool,
- #[clap(long, help = "Writes all AST snapshots for the different compiler phases.")]
- pub enable_all_ast_snapshots: bool,
- #[clap(long, help = "Writes Input AST snapshot of the initial parse.")]
- pub enable_initial_input_ast_snapshot: bool,
- #[clap(long, help = "Writes AST snapshot of the initial parse.")]
- pub enable_initial_ast_snapshot: bool,
- #[clap(long, help = "Writes AST snapshot of the unrolled AST.")]
- pub enable_unrolled_ast_snapshot: bool,
- #[clap(long, help = "Writes AST snapshot of the SSA AST.")]
- pub enable_ssa_ast_snapshot: bool,
- #[clap(long, help = "Writes AST snapshot of the flattened AST.")]
- pub enable_flattened_ast_snapshot: bool,
- #[clap(long, help = "Writes AST snapshot of the inlined AST.")]
- pub enable_inlined_ast_snapshot: bool,
- #[clap(long, help = "Writes AST snapshot of the dead code eliminated (DCE) AST.")]
- pub enable_dce_ast_snapshot: bool,
-}
-
impl From for CompilerOptions {
fn from(options: BuildOptions) -> Self {
let mut out_options = Self {
diff --git a/leo/commands/clean.rs b/leo/cli/commands/clean.rs
similarity index 88%
rename from leo/commands/clean.rs
rename to leo/cli/commands/clean.rs
index 11deeb965c..e0dd97c708 100644
--- a/leo/commands/clean.rs
+++ b/leo/cli/commands/clean.rs
@@ -14,13 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-use crate::{commands::Command, context::Context};
-use leo_errors::Result;
-use leo_package::{build::BuildDirectory, outputs::OutputsDirectory};
-
-use clap::Parser;
-use colored::Colorize;
-use tracing::span::Span;
+use super::*;
/// Clean outputs folder command
#[derive(Parser, Debug)]
diff --git a/leo/commands/deploy.rs b/leo/cli/commands/deploy.rs
similarity index 90%
rename from leo/commands/deploy.rs
rename to leo/cli/commands/deploy.rs
index 1258014e7e..6a679fe2b9 100644
--- a/leo/commands/deploy.rs
+++ b/leo/cli/commands/deploy.rs
@@ -14,19 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-use crate::{
- commands::{Command, ALEO_CLI_COMMAND},
- context::Context,
-};
-
-use leo_errors::{CliError, PackageError, Result};
-use leo_package::build::BuildDirectory;
+use super::*;
use aleo::commands::Deploy as AleoDeploy;
-use clap::Parser;
-use tracing::span::Span;
-
/// Deploys an Aleo program.
#[derive(Parser, Debug)]
pub struct Deploy;
diff --git a/leo/commands/mod.rs b/leo/cli/commands/mod.rs
similarity index 66%
rename from leo/commands/mod.rs
rename to leo/cli/commands/mod.rs
index f783f5e222..fe2222e1c7 100644
--- a/leo/commands/mod.rs
+++ b/leo/cli/commands/mod.rs
@@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-// local program commands
pub mod build;
pub use build::Build;
@@ -33,14 +32,18 @@ pub use new::New;
pub mod run;
pub use run::Run;
-use crate::context::*;
-use leo_errors::Result;
+pub mod update;
+pub use update::Update;
+use super::*;
+use crate::cli::helpers::context::*;
+use leo_errors::{emitter::Handler, CliError, CompilerError, PackageError, Result};
+use leo_package::{build::*, outputs::OutputsDirectory, package::*};
+
+use clap::Parser;
+use colored::Colorize;
use tracing::span::Span;
-pub(crate) type Network = snarkvm::prelude::Testnet3;
-pub(crate) const ALEO_CLI_COMMAND: &str = "snarkvm";
-
/// Base trait for the Leo CLI, see methods and their documentation for details.
pub trait Command {
/// If the current command requires running another command beforehand
@@ -102,3 +105,31 @@ pub trait Command {
self.execute(context).map(|_| Ok(()))?
}
}
+
+/// Compiler Options wrapper for Build command. Also used by other commands which
+/// require Build command output as their input.
+#[derive(Parser, Clone, Debug, Default)]
+pub struct BuildOptions {
+ #[clap(long, help = "Enables offline mode.")]
+ pub offline: bool,
+ #[clap(long, help = "Enable spans in AST snapshots.")]
+ pub enable_spans: bool,
+ #[clap(long, help = "Enables dead code elimination in the compiler.")]
+ pub enable_dce: bool,
+ #[clap(long, help = "Writes all AST snapshots for the different compiler phases.")]
+ pub enable_all_ast_snapshots: bool,
+ #[clap(long, help = "Writes Input AST snapshot of the initial parse.")]
+ pub enable_initial_input_ast_snapshot: bool,
+ #[clap(long, help = "Writes AST snapshot of the initial parse.")]
+ pub enable_initial_ast_snapshot: bool,
+ #[clap(long, help = "Writes AST snapshot of the unrolled AST.")]
+ pub enable_unrolled_ast_snapshot: bool,
+ #[clap(long, help = "Writes AST snapshot of the SSA AST.")]
+ pub enable_ssa_ast_snapshot: bool,
+ #[clap(long, help = "Writes AST snapshot of the flattened AST.")]
+ pub enable_flattened_ast_snapshot: bool,
+ #[clap(long, help = "Writes AST snapshot of the inlined AST.")]
+ pub enable_inlined_ast_snapshot: bool,
+ #[clap(long, help = "Writes AST snapshot of the dead code eliminated (DCE) AST.")]
+ pub enable_dce_ast_snapshot: bool,
+}
diff --git a/leo/commands/new.rs b/leo/cli/commands/new.rs
similarity index 93%
rename from leo/commands/new.rs
rename to leo/cli/commands/new.rs
index 6a68a69a67..56faf5d846 100644
--- a/leo/commands/new.rs
+++ b/leo/cli/commands/new.rs
@@ -14,18 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-use crate::{
- commands::{Command, Network, ALEO_CLI_COMMAND},
- context::Context,
-};
-use leo_errors::{CliError, PackageError, Result};
-use leo_package::{build::BUILD_DIRECTORY_NAME, package::Package};
+use super::*;
use snarkvm::{cli::New as AleoNew, file::AleoFile};
-use clap::Parser;
-use tracing::span::Span;
-
/// Create new Leo project
#[derive(Parser, Debug)]
pub struct New {
diff --git a/leo/commands/node.rs b/leo/cli/commands/node.rs
similarity index 92%
rename from leo/commands/node.rs
rename to leo/cli/commands/node.rs
index 0e8185774b..6f026e8119 100644
--- a/leo/commands/node.rs
+++ b/leo/cli/commands/node.rs
@@ -14,18 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-use crate::{
- commands::{Command, ALEO_CLI_COMMAND},
- context::Context,
-};
-use leo_errors::{CliError, PackageError, Result};
-use leo_package::build::BuildDirectory;
+use super::*;
use aleo::commands::Node as AleoNode;
-use clap::Parser;
-use tracing::span::Span;
-
/// Commands to operate a local development node.
#[derive(Parser, Debug)]
pub enum Node {
diff --git a/leo/commands/run.rs b/leo/cli/commands/run.rs
similarity index 92%
rename from leo/commands/run.rs
rename to leo/cli/commands/run.rs
index b36698b13a..9f64a32ab8 100644
--- a/leo/commands/run.rs
+++ b/leo/cli/commands/run.rs
@@ -14,19 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-use super::build::BuildOptions;
-use crate::{
- commands::{Build, Command, ALEO_CLI_COMMAND},
- context::Context,
-};
-use leo_errors::{CliError, PackageError, Result};
-use leo_package::build::BuildDirectory;
+use super::*;
use snarkvm::cli::Run as AleoRun;
-use clap::Parser;
-use tracing::span::Span;
-
/// Build, Prove and Run Leo program with inputs
#[derive(Parser, Debug)]
pub struct Run {
diff --git a/leo/cli/commands/update.rs b/leo/cli/commands/update.rs
new file mode 100644
index 0000000000..b1342a4817
--- /dev/null
+++ b/leo/cli/commands/update.rs
@@ -0,0 +1,70 @@
+// Copyright (C) 2019-2023 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 .
+
+use super::*;
+use crate::cli::helpers::updater::Updater;
+
+/// Update Leo to the latest version
+#[derive(Debug, Parser)]
+pub struct Update {
+ /// Lists all available versions of Leo
+ #[clap(short = 'l', long)]
+ list: bool,
+ /// Suppress outputs to terminal
+ #[clap(short = 'q', long)]
+ quiet: bool,
+}
+
+impl Command for Update {
+ type Input = ();
+ type Output = ();
+
+ fn log_span(&self) -> Span {
+ tracing::span!(tracing::Level::INFO, "Leo")
+ }
+
+ fn prelude(&self, _: Context) -> Result {
+ Ok(())
+ }
+
+ fn apply(self, _: Context, _: Self::Input) -> Result
+ where
+ Self: Sized,
+ {
+ match self.list {
+ true => match Updater::show_available_releases() {
+ Ok(output) => tracing::info!("{output}"),
+ Err(error) => tracing::info!("Failed to list the available versions of Leo\n{error}\n"),
+ },
+ false => {
+ let result = Updater::update_to_latest_release(!self.quiet);
+ if !self.quiet {
+ match result {
+ Ok(status) => {
+ if status.uptodate() {
+ tracing::info!("\nLeo is already on the latest version")
+ } else if status.updated() {
+ tracing::info!("\nLeo has updated to version {}", status.version())
+ }
+ }
+ Err(e) => tracing::info!("\nFailed to update Leo to the latest version\n{e}\n"),
+ }
+ }
+ }
+ }
+ Ok(())
+ }
+}
diff --git a/leo/context.rs b/leo/cli/helpers/context.rs
similarity index 99%
rename from leo/context.rs
rename to leo/cli/helpers/context.rs
index 96d68a94a8..ef7291ac3a 100644
--- a/leo/context.rs
+++ b/leo/cli/helpers/context.rs
@@ -14,11 +14,12 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-use crate::commands::Network;
+use super::*;
use leo_errors::{CliError, PackageError, Result};
+use leo_package::build::{BuildDirectory, BUILD_DIRECTORY_NAME};
+
use snarkvm::file::Manifest;
-use leo_package::build::{BuildDirectory, BUILD_DIRECTORY_NAME};
use std::{
env::current_dir,
fs::File,
diff --git a/leo/logger.rs b/leo/cli/helpers/logger.rs
similarity index 97%
rename from leo/logger.rs
rename to leo/cli/helpers/logger.rs
index 510fe401d2..8e95ad3d94 100644
--- a/leo/logger.rs
+++ b/leo/cli/helpers/logger.rs
@@ -31,12 +31,12 @@ static START: Once = Once::new();
pub struct Format {
format: F,
#[allow(dead_code)] // todo: revisit this after merging span module
- pub(crate) timer: T,
- pub(crate) ansi: bool,
- pub(crate) display_target: bool,
- pub(crate) display_level: bool,
- pub(crate) display_thread_id: bool,
- pub(crate) display_thread_name: bool,
+ pub timer: T,
+ pub ansi: bool,
+ pub display_target: bool,
+ pub display_level: bool,
+ pub display_thread_id: bool,
+ pub display_thread_name: bool,
}
impl Format {
diff --git a/leo/cli/helpers/mod.rs b/leo/cli/helpers/mod.rs
new file mode 100644
index 0000000000..de2c63dc93
--- /dev/null
+++ b/leo/cli/helpers/mod.rs
@@ -0,0 +1,21 @@
+// Copyright (C) 2019-2023 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 .
+
+pub use super::*;
+
+pub mod context;
+pub mod logger;
+pub mod updater;
diff --git a/leo/updater.rs b/leo/cli/helpers/updater.rs
similarity index 95%
rename from leo/updater.rs
rename to leo/cli/helpers/updater.rs
index 58e075372c..d226d9c2f3 100644
--- a/leo/updater.rs
+++ b/leo/cli/helpers/updater.rs
@@ -30,7 +30,7 @@ impl Updater {
const LEO_REPO_OWNER: &'static str = "AleoHQ";
/// Show all available releases for `leo`.
- pub fn show_available_releases() -> Result<()> {
+ pub fn show_available_releases() -> Result {
let releases = github::ReleaseList::configure()
.repo_owner(Self::LEO_REPO_OWNER)
.repo_name(Self::LEO_REPO_NAME)
@@ -44,10 +44,7 @@ impl Updater {
let _ = writeln!(output, " * {}", release.version);
}
- // Forgo using tracing to list the available versions without a log status.
- println!("{output}");
-
- Ok(())
+ Ok(output)
}
/// Update `leo` to the latest release.
diff --git a/leo/cli/main.rs b/leo/cli/main.rs
new file mode 100644
index 0000000000..5127e518d2
--- /dev/null
+++ b/leo/cli/main.rs
@@ -0,0 +1,49 @@
+// Copyright (C) 2019-2023 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 .
+
+use leo_lang::cli::*;
+use leo_span::symbol::create_session_if_not_set_then;
+
+use clap::Parser;
+
+fn set_panic_hook() {
+ #[cfg(not(debug_assertions))]
+ std::panic::set_hook({
+ Box::new(move |e| {
+ eprintln!("thread `{}` {}", std::thread::current().name().unwrap_or(""), e);
+ eprintln!("stack backtrace: \n{:?}", backtrace::Backtrace::new());
+ eprintln!("error: internal compiler error: unexpected panic\n");
+ eprintln!("note: the compiler unexpectedly panicked. this is a bug.\n");
+ eprintln!(
+ "note: we would appreciate a bug report: https://github.com/AleoHQ/leo/issues/new?labels=bug,panic&template=bug.md&title=[Bug]\n"
+ );
+ eprintln!(
+ "note: {} {} running on {} {}\n",
+ env!("CARGO_PKG_NAME"),
+ env!("CARGO_PKG_VERSION"),
+ sys_info::os_type().unwrap_or_else(|e| e.to_string()),
+ sys_info::os_release().unwrap_or_else(|e| e.to_string()),
+ );
+ eprintln!("note: compiler args: {}\n", std::env::args().collect::>().join(" "));
+ eprintln!("note: compiler flags: {:?}\n", CLI::parse());
+ })
+ });
+}
+
+fn main() {
+ set_panic_hook();
+ create_session_if_not_set_then(|_| handle_error(run_with_args(CLI::parse())));
+}
diff --git a/leo/cli/mod.rs b/leo/cli/mod.rs
new file mode 100644
index 0000000000..cfa2720779
--- /dev/null
+++ b/leo/cli/mod.rs
@@ -0,0 +1,30 @@
+// Copyright (C) 2019-2023 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 .
+
+mod cli;
+pub use cli::*;
+
+mod commands;
+pub use commands::*;
+
+mod helpers;
+pub use helpers::*;
+
+pub(crate) type Network = snarkvm::prelude::Testnet3;
+pub(crate) const ALEO_CLI_COMMAND: &str = "snarkvm";
+
+#[cfg(test)]
+mod tests;
diff --git a/leo/tests/mod.rs b/leo/cli/tests/mod.rs
similarity index 97%
rename from leo/tests/mod.rs
rename to leo/cli/tests/mod.rs
index a2b4c02316..01ee7e9438 100644
--- a/leo/tests/mod.rs
+++ b/leo/cli/tests/mod.rs
@@ -33,13 +33,13 @@ use leo_errors::Result;
#[test]
pub fn init_logger() -> Result<()> {
- crate::logger::init_logger("test_init_logger", 1)?;
+ crate::cli::helpers::logger::init_logger("test_init_logger", 1)?;
Ok(())
}
#[test]
pub fn format_event() -> Result<()> {
- crate::logger::init_logger("test_format_event", 1)?;
+ crate::cli::helpers::logger::init_logger("test_format_event", 1)?;
tracing::info!("test");
Ok(())
}
diff --git a/leo/lib.rs b/leo/lib.rs
index ce69ef94e4..910f23b73f 100644
--- a/leo/lib.rs
+++ b/leo/lib.rs
@@ -15,12 +15,7 @@
// along with the Leo library. If not, see .
#![forbid(unsafe_code)]
+#![allow(clippy::module_inception)]
#![doc = include_str!("../README.md")]
-pub mod commands;
-pub mod context;
-pub mod logger;
-pub mod updater;
-
-#[cfg(test)]
-mod tests;
+pub mod cli;