diff --git a/Cargo.toml b/Cargo.toml
index b6b70d9fcb..ef4acdf515 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -32,6 +32,8 @@ snarkos-utilities = { git = "ssh://git@github.com/AleoHQ/snarkOS.git", package =
clap = { version = "2.33.3" }
colored = { version = "2.0" }
dirs = { version = "3.0.1" }
+console = { version = "0.12.0" }
+dotenv = { version = "0.15.0" }
env_logger = { version = "0.7" }
from-pest = { version = "0.3.1" }
lazy_static = { version = "1.4.0" }
@@ -41,6 +43,7 @@ num-bigint = { version = "0.3" }
rand = { version = "0.7" }
rand_core = { version = "0.5.1" }
reqwest = { version = "0.10.7", features = ["blocking", "json"] }
+self_update = { version = "0.19.0" }
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
toml = { version = "0.5" }
diff --git a/leo/commands/mod.rs b/leo/commands/mod.rs
index b5c14e8b99..16b9e266dd 100644
--- a/leo/commands/mod.rs
+++ b/leo/commands/mod.rs
@@ -56,5 +56,8 @@ pub use self::test::*;
pub mod remove;
pub use self::remove::*;
+pub mod update;
+pub use self::update::*;
+
pub mod watch;
pub use self::watch::*;
diff --git a/leo/commands/update.rs b/leo/commands/update.rs
new file mode 100644
index 0000000000..5597011f0c
--- /dev/null
+++ b/leo/commands/update.rs
@@ -0,0 +1,95 @@
+// Copyright (C) 2019-2020 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 crate::{cli::CLI, cli_types::*};
+
+use self_update::{backends::github, cargo_crate_version};
+
+const LEO_BIN_NAME: &str = "leo";
+const LEO_REPO_OWNER: &str = "AleoHQ";
+const LEO_REPO_NAME: &str = "leo";
+
+#[derive(Debug)]
+pub struct UpdateCommand;
+
+impl UpdateCommand {
+ // Show all available releases for all platforms
+ fn show_available_releases() -> Result<(), self_update::errors::Error> {
+ let releases = github::ReleaseList::configure()
+ .repo_owner(LEO_REPO_OWNER)
+ .repo_name(LEO_REPO_NAME)
+ .build()?
+ .fetch()?;
+
+ log::info!("List of available Leo's verions");
+ for release in releases {
+ log::info!("* {}", release.version);
+ }
+ Ok(())
+ }
+
+ // Update to the latest release on the current platform
+ fn update_to_latest_release() -> Result<(), self_update::errors::Error> {
+ let status = github::Update::configure()
+ .repo_owner(LEO_REPO_OWNER)
+ .repo_name(LEO_REPO_NAME)
+ .bin_name(LEO_BIN_NAME)
+ .show_download_progress(true)
+ .current_version(cargo_crate_version!())
+ .build()?
+ .update()?;
+
+ log::info!("Leo has successfully updated to {} version", status.version());
+ Ok(())
+ }
+}
+
+impl CLI for UpdateCommand {
+ type Options = (bool,);
+ type Output = ();
+
+ const ABOUT: AboutType = "Update Leo itself";
+ const ARGUMENTS: &'static [ArgumentType] = &[];
+ const FLAGS: &'static [FlagType] = &[("--list")];
+ const NAME: NameType = "update";
+ const OPTIONS: &'static [OptionType] = &[];
+ const SUBCOMMANDS: &'static [SubCommandType] = &[];
+
+ fn parse(arguments: &clap::ArgMatches) -> Result {
+ let show_all_versions = arguments.is_present("list");
+ Ok((show_all_versions,))
+ }
+
+ fn output(options: Self::Options) -> Result {
+ match options {
+ (true,) => match UpdateCommand::show_available_releases() {
+ Ok(_) => return Ok(()),
+ Err(e) => {
+ log::error!("Cannot get Leo version");
+ log::error!("Log: {}", e);
+ }
+ },
+ (false,) => match UpdateCommand::update_to_latest_release() {
+ Ok(_) => return Ok(()),
+ Err(e) => {
+ log::error!("Cannot update Leo");
+ log::error!("Log: {}", e);
+ }
+ },
+ }
+ Ok(())
+ }
+}
diff --git a/leo/main.rs b/leo/main.rs
index 27a08d90da..5d2fdae163 100644
--- a/leo/main.rs
+++ b/leo/main.rs
@@ -51,6 +51,7 @@ fn main() -> Result<(), CLIError> {
DeployCommand::new().display_order(12),
CleanCommand::new().display_order(13),
LintCommand::new().display_order(14),
+ UpdateCommand::new().display_order(15),
])
.set_term_width(0)
.get_matches();
@@ -71,6 +72,7 @@ fn main() -> Result<(), CLIError> {
("deploy", Some(arguments)) => DeployCommand::process(arguments),
("clean", Some(arguments)) => CleanCommand::process(arguments),
("lint", Some(arguments)) => LintCommand::process(arguments),
+ ("update", Some(arguments)) => UpdateCommand::process(arguments),
_ => unreachable!(),
}
}