Add leo update automatic functionality

This commit is contained in:
raychu86 2020-09-02 22:29:15 -07:00
parent 6392bf2826
commit 7cacef0dfb
5 changed files with 112 additions and 15 deletions

View File

@ -35,7 +35,7 @@ use std::{
io::{Read, Write}, io::{Read, Write},
}; };
pub const ADD_URL: &str = "api/package/fetch"; pub const ADD_URL: &str = "v1/package/fetch";
#[derive(Debug)] #[derive(Debug)]
pub struct AddCommand; pub struct AddCommand;

View File

@ -30,7 +30,7 @@ use crate::{
use std::collections::HashMap; use std::collections::HashMap;
pub const LOGIN_URL: &str = "api/account/authenticate"; pub const LOGIN_URL: &str = "v1/account/authenticate";
#[derive(Debug)] #[derive(Debug)]
pub struct LoginCommand; pub struct LoginCommand;

View File

@ -38,7 +38,7 @@ use reqwest::{
use serde::Deserialize; use serde::Deserialize;
use std::{convert::TryFrom, env::current_dir}; use std::{convert::TryFrom, env::current_dir};
const PUBLISH_URL: &str = "api/package/publish"; pub const PUBLISH_URL: &str = "v1/package/publish";
#[derive(Deserialize)] #[derive(Deserialize)]
struct ResponseJson { struct ResponseJson {

View File

@ -14,25 +14,54 @@
// You should have received a copy of the GNU General Public License // 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/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{cli::CLI, cli_types::*, updater::Updater}; use crate::{cli::CLI, cli_types::*, config::Config, updater::Updater};
use clap::AppSettings;
#[derive(Debug)] #[derive(Debug)]
pub struct UpdateCommand; pub struct UpdateCommand;
impl CLI for UpdateCommand { impl CLI for UpdateCommand {
type Options = (bool,); // (show_all_versions, quiet)
type Options = Option<(bool, bool)>;
type Output = (); type Output = ();
const ABOUT: AboutType = "Update Leo to the latest version"; const ABOUT: AboutType = "Update Leo to the latest version";
const ARGUMENTS: &'static [ArgumentType] = &[]; const ARGUMENTS: &'static [ArgumentType] = &[];
const FLAGS: &'static [FlagType] = &[("--list")]; const FLAGS: &'static [FlagType] = &[("--list"), ("--quiet")];
const NAME: NameType = "update"; const NAME: NameType = "update";
const OPTIONS: &'static [OptionType] = &[]; const OPTIONS: &'static [OptionType] = &[];
const SUBCOMMANDS: &'static [SubCommandType] = &[]; const SUBCOMMANDS: &'static [SubCommandType] = &[
// (name, description, options, settings)
(
AutomaticUpdate::NAME,
AutomaticUpdate::ABOUT,
AutomaticUpdate::ARGUMENTS,
AutomaticUpdate::FLAGS,
&AutomaticUpdate::OPTIONS,
&[
AppSettings::ColoredHelp,
AppSettings::DisableHelpSubcommand,
AppSettings::DisableVersion,
],
),
];
fn parse(arguments: &clap::ArgMatches) -> Result<Self::Options, crate::errors::CLIError> { fn parse(arguments: &clap::ArgMatches) -> Result<Self::Options, crate::errors::CLIError> {
match arguments.subcommand() {
("automatic", Some(arguments)) => {
// Run the `automatic` subcommand
let options = AutomaticUpdate::parse(arguments)?;
let _output = AutomaticUpdate::output(options)?;
return Ok(None);
}
_ => {}
};
let show_all_versions = arguments.is_present("list"); let show_all_versions = arguments.is_present("list");
Ok((show_all_versions,)) let quiet = arguments.is_present("quiet");
Ok(Some((show_all_versions, quiet)))
} }
fn output(options: Self::Options) -> Result<Self::Output, crate::errors::CLIError> { fn output(options: Self::Options) -> Result<Self::Output, crate::errors::CLIError> {
@ -40,20 +69,25 @@ impl CLI for UpdateCommand {
let span = tracing::span!(tracing::Level::INFO, "Updating"); let span = tracing::span!(tracing::Level::INFO, "Updating");
let _enter = span.enter(); let _enter = span.enter();
match options { let (show_all_versions, quiet) = match options {
(true,) => match Updater::show_available_releases() { Some(options) => options,
None => return Ok(()),
};
match show_all_versions {
true => match Updater::show_available_releases() {
Ok(_) => return Ok(()), Ok(_) => return Ok(()),
Err(e) => { Err(e) => {
tracing::error!("Could not fetch that latest version of Leo"); tracing::error!("Could not fetch that latest version of Leo");
tracing::error!("{}", e); tracing::error!("{}", e);
} }
}, },
(false,) => match Updater::update_to_latest_release(true) { false => match Updater::update_to_latest_release(!quiet) {
Ok(status) => { Ok(status) => {
if status.uptodate() { if status.uptodate() {
tracing::info!("Leo is already on the latest version: {}", status.version()); tracing::info!("Leo is already on the latest version {}", status.version());
} else if status.updated() { } else if status.updated() {
tracing::info!("Leo has successfully updated to version: {}", status.version()); tracing::info!("Leo has successfully updated to version {}", status.version());
} }
return Ok(()); return Ok(());
} }
@ -66,3 +100,66 @@ impl CLI for UpdateCommand {
Ok(()) Ok(())
} }
} }
#[derive(Debug)]
pub struct AutomaticUpdate;
impl CLI for AutomaticUpdate {
// (is_automatic, quiet)
type Options = (Option<bool>, bool);
type Output = ();
const ABOUT: AboutType = "Set automatic update configuration";
const ARGUMENTS: &'static [ArgumentType] = &[
// (name, description, required, index)
(
"AUTOMATIC",
"Set the automatic update configuration [possible values: true, false]",
false,
1u64,
),
];
const FLAGS: &'static [FlagType] = &[("--quiet")];
const NAME: NameType = "automatic";
const OPTIONS: &'static [OptionType] = &[];
const SUBCOMMANDS: &'static [SubCommandType] = &[];
fn parse(arguments: &clap::ArgMatches) -> Result<Self::Options, crate::errors::CLIError> {
let quiet = arguments.is_present("quiet");
match arguments.value_of("AUTOMATIC") {
Some(automatic) => {
// TODO enforce that the possible values is true or false
let automatic = match automatic {
"true" => Some(true),
"false" => Some(false),
_ => {
// TODO (raychu86) fix this log output
tracing::info!("Please set the automatic update flag to true or false");
None
}
};
Ok((automatic, quiet))
}
None => Ok((None, quiet)),
}
}
fn output(options: Self::Options) -> Result<Self::Output, crate::errors::CLIError> {
// Begin "Updating" context for console logging
if let Some(automatic) = options.0 {
Config::set_update_automatic(automatic)?;
if !options.1 {
// TODO (raychu86) fix this log output
tracing::info!("Leo automatic update configuration set to {}", automatic);
}
} else {
let config = Config::read_config()?;
tracing::info!("Leo automatic update configuration is {}", config.update.automatic);
}
Ok(())
}
}

View File

@ -33,7 +33,7 @@ impl Updater {
.repo_name(Self::LEO_REPO_NAME) .repo_name(Self::LEO_REPO_NAME)
.bin_name(Self::LEO_BIN_NAME) .bin_name(Self::LEO_BIN_NAME)
.current_version(&include_str!("./leo-version").replace('v', "")) .current_version(&include_str!("./leo-version").replace('v', ""))
.show_download_progress(true) .show_download_progress(show_output)
.no_confirm(true) .no_confirm(true)
.show_output(show_output) .show_output(show_output)
.build()? .build()?
@ -65,7 +65,7 @@ impl Updater {
pub fn print_cli() { pub fn print_cli() {
let config = Config::read_config().unwrap(); let config = Config::read_config().unwrap();
if config.auto_update { if config.update.automatic {
// If the auto update configuration is on, attempt to update the version. // If the auto update configuration is on, attempt to update the version.
if let Ok(status) = Self::update_to_latest_release(false) { if let Ok(status) = Self::update_to_latest_release(false) {
if status.updated() { if status.updated() {