From c94c5cddb137069640fc9fc61435204d6f63fc5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 19 Aug 2024 16:05:10 +0100 Subject: [PATCH] feat(upgrade): support `deno upgrade 1.46.0` (#25096) This commit changes `deno upgrade` subcommand to accept a positional argument that can be either a version, release channel name or a git hash, making invocations of `deno upgrade` much more concise: ``` # before $ deno upgrade --version 1.46.0 # after $ deno upgrade 1.46.0 ``` ``` # before $ deno upgrade --canary # after $ deno upgrade canary ``` ``` # specific canary version before $ deno upgrade --canary --version f042c39180c1b345de8e7b5f0dfae5d0a49b161f # after $ deno upgrade f042c39180c1b345de8e7b5f0dfae5d0a49b161f ``` Old flags are still supported, but hidden from the help output. --- cli/args/flags.rs | 46 +++++++++++++-- cli/tools/upgrade.rs | 132 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 162 insertions(+), 16 deletions(-) diff --git a/cli/args/flags.rs b/cli/args/flags.rs index d0a6900453..495b844689 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -412,6 +412,7 @@ pub struct UpgradeFlags { pub canary: bool, pub version: Option, pub output: Option, + pub version_or_hash_or_channel: Option, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -3018,8 +3019,23 @@ The declaration file could be saved and used for typing information.", fn upgrade_subcommand() -> Command { command( "upgrade", - "Upgrade deno executable to the given version. -Defaults to latest. + color_print::cstr!("Upgrade deno executable to the given version. + +Latest + + deno upgrade + +Specific version + + deno upgrade 1.45.0 + deno upgrade 1.46.0-rc.1 + deno upgrade 9bc2dd29ad6ba334fd57a20114e367d3c04763d4 + +Channel + + deno upgrade stable + deno upgrade rc + deno upgrade canary The version is downloaded from https://github.com/denoland/deno/releases @@ -3027,7 +3043,7 @@ and is used to replace the current executable. If you want to not replace the current Deno executable but instead download an update to a different location, use the --output flag: - deno upgrade --output $HOME/my_deno", + deno upgrade --output $HOME/my_deno"), UnstableArgsConfig::None, ) .hide(cfg!(not(feature = "upgrade"))) @@ -3037,7 +3053,8 @@ update to a different location, use the --output flag: Arg::new("version") .long("version") .help("The version to upgrade to") - .help_heading(UPGRADE_HEADING), + .help_heading(UPGRADE_HEADING)// NOTE(bartlomieju): pre-v1.46 compat + .hide(true), ) .arg( Arg::new("output") @@ -3067,7 +3084,8 @@ update to a different location, use the --output flag: .long("canary") .help("Upgrade to canary builds") .action(ArgAction::SetTrue) - .help_heading(UPGRADE_HEADING), + .help_heading(UPGRADE_HEADING)// NOTE(bartlomieju): pre-v1.46 compat + .hide(true), ) .arg( Arg::new("release-candidate") @@ -3075,7 +3093,16 @@ update to a different location, use the --output flag: .help("Upgrade to a release candidate") .conflicts_with_all(["canary", "version"]) .action(ArgAction::SetTrue) - .help_heading(UPGRADE_HEADING), + .help_heading(UPGRADE_HEADING) + // NOTE(bartlomieju): pre-v1.46 compat + .hide(true), + ) + .arg( + Arg::new("version-or-hash-or-channel") + .help(color_print::cstr!("Version (v1.46.0), channel (rc, canary) or commit hash (9bc2dd29ad6ba334fd57a20114e367d3c04763d4)")) + .value_name("VERSION") + .action(ArgAction::Append) + .trailing_var_arg(true), ) .arg(ca_file_arg()) .arg(unsafely_ignore_certificate_errors_arg()) @@ -4911,6 +4938,8 @@ fn upgrade_parse(flags: &mut Flags, matches: &mut ArgMatches) { let release_candidate = matches.get_flag("release-candidate"); let version = matches.remove_one::("version"); let output = matches.remove_one::("output"); + let version_or_hash_or_channel = + matches.remove_one::("version-or-hash-or-channel"); flags.subcommand = DenoSubcommand::Upgrade(UpgradeFlags { dry_run, force, @@ -4918,6 +4947,7 @@ fn upgrade_parse(flags: &mut Flags, matches: &mut ArgMatches) { canary, version, output, + version_or_hash_or_channel, }); } @@ -5426,6 +5456,7 @@ mod tests { release_candidate: false, version: None, output: None, + version_or_hash_or_channel: None, }), ..Flags::default() } @@ -5445,6 +5476,7 @@ mod tests { release_candidate: false, version: None, output: Some(String::from("example.txt")), + version_or_hash_or_channel: None, }), ..Flags::default() } @@ -9435,6 +9467,7 @@ mod tests { release_candidate: false, version: None, output: None, + version_or_hash_or_channel: None, }), ca_data: Some(CaData::File("example.crt".to_owned())), ..Flags::default() @@ -9455,6 +9488,7 @@ mod tests { release_candidate: true, version: None, output: None, + version_or_hash_or_channel: None, }), ..Flags::default() } diff --git a/cli/tools/upgrade.rs b/cli/tools/upgrade.rs index dba573e260..db43b8be17 100644 --- a/cli/tools/upgrade.rs +++ b/cli/tools/upgrade.rs @@ -547,7 +547,7 @@ pub async fn upgrade( Ok(()) } -#[derive(Debug)] +#[derive(Debug, PartialEq)] enum RequestedVersion { Latest(ReleaseChannel), SpecificVersion(ReleaseChannel, String), @@ -556,20 +556,34 @@ enum RequestedVersion { impl RequestedVersion { fn from_upgrade_flags(upgrade_flags: UpgradeFlags) -> Result { let is_canary = upgrade_flags.canary; - let is_release_candidate = upgrade_flags.release_candidate; + let re_hash = lazy_regex::regex!("^[0-9a-f]{40}$"); + let channel = if is_canary { + ReleaseChannel::Canary + } else if upgrade_flags.release_candidate { + ReleaseChannel::Rc + } else { + ReleaseChannel::Stable + }; + let mut maybe_passed_version = upgrade_flags.version.clone(); - let Some(passed_version) = upgrade_flags.version else { - let channel = if is_canary { - ReleaseChannel::Canary - } else if is_release_candidate { - ReleaseChannel::Rc + if let Some(val) = &upgrade_flags.version_or_hash_or_channel { + if let Ok(channel) = ReleaseChannel::deserialize(&val.to_lowercase()) { + // TODO(bartlomieju): print error if any other flags passed? + return Ok(Self::Latest(channel)); + } else if re_hash.is_match(val) { + return Ok(Self::SpecificVersion( + ReleaseChannel::Canary, + val.to_string(), + )); } else { - ReleaseChannel::Stable - }; + maybe_passed_version = Some(val.to_string()); + } + } + + let Some(passed_version) = maybe_passed_version else { return Ok(Self::Latest(channel)); }; - let re_hash = lazy_regex::regex!("^[0-9a-f]{40}$"); let passed_version = passed_version .strip_prefix('v') .unwrap_or(&passed_version) @@ -1039,6 +1053,104 @@ mod test { use super::*; + #[test] + fn test_requested_version() { + let mut upgrade_flags = UpgradeFlags { + dry_run: false, + force: false, + release_candidate: false, + canary: false, + version: None, + output: None, + version_or_hash_or_channel: None, + }; + + let req_ver = + RequestedVersion::from_upgrade_flags(upgrade_flags.clone()).unwrap(); + assert_eq!(req_ver, RequestedVersion::Latest(ReleaseChannel::Stable)); + + upgrade_flags.version = Some("1.46.0".to_string()); + let req_ver = + RequestedVersion::from_upgrade_flags(upgrade_flags.clone()).unwrap(); + assert_eq!( + req_ver, + RequestedVersion::SpecificVersion( + ReleaseChannel::Stable, + "1.46.0".to_string() + ) + ); + + upgrade_flags.version = None; + upgrade_flags.canary = true; + let req_ver = + RequestedVersion::from_upgrade_flags(upgrade_flags.clone()).unwrap(); + assert_eq!(req_ver, RequestedVersion::Latest(ReleaseChannel::Canary)); + + upgrade_flags.version = + Some("5c69b4861b52ab406e73b9cd85c254f0505cb20f".to_string()); + let req_ver = + RequestedVersion::from_upgrade_flags(upgrade_flags.clone()).unwrap(); + assert_eq!( + req_ver, + RequestedVersion::SpecificVersion( + ReleaseChannel::Canary, + "5c69b4861b52ab406e73b9cd85c254f0505cb20f".to_string() + ) + ); + + upgrade_flags.version = None; + upgrade_flags.canary = false; + upgrade_flags.release_candidate = true; + let req_ver = + RequestedVersion::from_upgrade_flags(upgrade_flags.clone()).unwrap(); + assert_eq!(req_ver, RequestedVersion::Latest(ReleaseChannel::Rc)); + + upgrade_flags.release_candidate = false; + upgrade_flags.version_or_hash_or_channel = Some("v1.46.5".to_string()); + let req_ver = + RequestedVersion::from_upgrade_flags(upgrade_flags.clone()).unwrap(); + assert_eq!( + req_ver, + RequestedVersion::SpecificVersion( + ReleaseChannel::Stable, + "1.46.5".to_string() + ) + ); + + upgrade_flags.version_or_hash_or_channel = Some("2.0.0-rc.0".to_string()); + let req_ver = + RequestedVersion::from_upgrade_flags(upgrade_flags.clone()).unwrap(); + assert_eq!( + req_ver, + RequestedVersion::SpecificVersion( + ReleaseChannel::Rc, + "2.0.0-rc.0".to_string() + ) + ); + + upgrade_flags.version_or_hash_or_channel = Some("canary".to_string()); + let req_ver = + RequestedVersion::from_upgrade_flags(upgrade_flags.clone()).unwrap(); + assert_eq!(req_ver, RequestedVersion::Latest(ReleaseChannel::Canary,)); + + upgrade_flags.version_or_hash_or_channel = Some("rc".to_string()); + let req_ver = + RequestedVersion::from_upgrade_flags(upgrade_flags.clone()).unwrap(); + assert_eq!(req_ver, RequestedVersion::Latest(ReleaseChannel::Rc,)); + + upgrade_flags.version_or_hash_or_channel = + Some("5c69b4861b52ab406e73b9cd85c254f0505cb20f".to_string()); + let req_ver = + RequestedVersion::from_upgrade_flags(upgrade_flags.clone()).unwrap(); + assert_eq!( + req_ver, + RequestedVersion::SpecificVersion( + ReleaseChannel::Canary, + "5c69b4861b52ab406e73b9cd85c254f0505cb20f".to_string() + ) + ); + } + #[test] fn test_parse_upgrade_check_file() { // NOTE(bartlomieju): pre-1.46 format