Skip to content

Commit

Permalink
feat(cli/tools/upgrade): canary support (denoland#8476)
Browse files Browse the repository at this point in the history
  • Loading branch information
crowlKats committed Nov 29, 2020
1 parent 47a16d2 commit 973af61
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 30 deletions.
10 changes: 10 additions & 0 deletions cli/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub enum DenoSubcommand {
Upgrade {
dry_run: bool,
force: bool,
canary: bool,
version: Option<String>,
output: Option<PathBuf>,
ca_file: Option<String>,
Expand Down Expand Up @@ -625,6 +626,7 @@ fn upgrade_parse(flags: &mut Flags, matches: &clap::ArgMatches) {

let dry_run = matches.is_present("dry-run");
let force = matches.is_present("force");
let canary = matches.is_present("canary");
let version = matches.value_of("version").map(|s| s.to_string());
let output = if matches.is_present("output") {
let install_root = matches.value_of("output").unwrap();
Expand All @@ -636,6 +638,7 @@ fn upgrade_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
flags.subcommand = DenoSubcommand::Upgrade {
dry_run,
force,
canary,
version,
output,
ca_file,
Expand Down Expand Up @@ -951,6 +954,11 @@ update to a different location, use the --output flag
.short("f")
.help("Replace current exe even if not out-of-date"),
)
.arg(
Arg::with_name("canary")
.long("canary")
.help("Upgrade to canary builds"),
)
.arg(ca_file_arg())
}

Expand Down Expand Up @@ -1589,6 +1597,7 @@ mod tests {
subcommand: DenoSubcommand::Upgrade {
force: true,
dry_run: true,
canary: false,
version: None,
output: None,
ca_file: None,
Expand Down Expand Up @@ -2991,6 +3000,7 @@ mod tests {
subcommand: DenoSubcommand::Upgrade {
force: false,
dry_run: false,
canary: false,
version: None,
output: None,
ca_file: Some("example.crt".to_owned()),
Expand Down
9 changes: 5 additions & 4 deletions cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -952,13 +952,14 @@ fn get_subcommand(
DenoSubcommand::Upgrade {
force,
dry_run,
canary,
version,
output,
ca_file,
} => {
tools::upgrade::upgrade_command(dry_run, force, version, output, ca_file)
.boxed_local()
}
} => tools::upgrade::upgrade_command(
dry_run, force, canary, version, output, ca_file,
)
.boxed_local(),
}
}

Expand Down
29 changes: 29 additions & 0 deletions cli/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,35 @@ fn upgrade_with_version_in_tmpdir() {
// TODO(ry) assert!(mtime1 < mtime2);
}

// Warning: this test requires internet access.
// TODO(#7412): reenable. test is flaky
#[test]
#[ignore]
fn upgrade_with_canary_in_tmpdir() {
let temp_dir = TempDir::new().unwrap();
let exe_path = temp_dir.path().join("deno");
let _ = std::fs::copy(util::deno_exe_path(), &exe_path).unwrap();
assert!(exe_path.exists());
let _mtime1 = std::fs::metadata(&exe_path).unwrap().modified().unwrap();
let status = Command::new(&exe_path)
.arg("upgrade")
.arg("--canary")
.arg("--version")
.arg("e6685f0f01b8a11a5eaff020f5babcfde76b3038")
.spawn()
.unwrap()
.wait()
.unwrap();
assert!(status.success());
let upgraded_deno_version = String::from_utf8(
Command::new(&exe_path).arg("-V").output().unwrap().stdout,
)
.unwrap();
assert!(upgraded_deno_version.contains("e6685f0"));
let _mtime2 = std::fs::metadata(&exe_path).unwrap().modified().unwrap();
// TODO(ry) assert!(mtime1 < mtime2);
}

// Warning: this test requires internet access.
// TODO(#7412): reenable. test is flaky
#[test]
Expand Down
96 changes: 70 additions & 26 deletions cli/tools/upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const RELEASE_URL: &str = "https://github.com/denoland/deno/releases";
pub async fn upgrade_command(
dry_run: bool,
force: bool,
canary: bool,
version: Option<String>,
output: Option<PathBuf>,
ca_file: Option<String>,
Expand All @@ -38,27 +39,49 @@ pub async fn upgrade_command(

let install_version = match version {
Some(passed_version) => {
if !force && output.is_none() && crate::version::deno() == passed_version
{
println!("Version {} is already installed", passed_version);
let current_is_passed = if canary {
let mut passed_hash = passed_version.clone();
passed_hash.truncate(7);
crate::version::GIT_COMMIT_HASH == passed_hash
} else if !crate::version::is_canary() {
crate::version::deno() == passed_version
} else {
false
};

if !force && output.is_none() && current_is_passed {
println!("Version {} is already installed", crate::version::deno());
return Ok(());
} else {
passed_version
}
}
None => {
let latest_version = get_latest_version(&client).await?;

let current = semver_parse(&*crate::version::deno()).unwrap();
let latest = match semver_parse(&latest_version) {
Ok(v) => v,
Err(_) => {
eprintln!("Invalid semver passed");
std::process::exit(1)
}
let latest_version = if canary {
get_latest_canary_version(&client).await?
} else {
get_latest_release_version(&client).await?
};

let current_is_most_recent = if canary {
let mut latest_hash = latest_version.clone();
latest_hash.truncate(7);
crate::version::GIT_COMMIT_HASH == latest_hash
} else if !crate::version::is_canary() {
let current = semver_parse(&*crate::version::deno()).unwrap();
let latest = match semver_parse(&latest_version) {
Ok(v) => v,
Err(_) => {
eprintln!("Invalid semver passed");
std::process::exit(1)
}
};
current >= latest
} else {
false
};

if !force && output.is_none() && current >= latest {
if !force && output.is_none() && current_is_most_recent {
println!(
"Local deno version {} is the most recent release",
crate::version::deno()
Expand All @@ -71,15 +94,27 @@ pub async fn upgrade_command(
}
};

let archive_data = download_package(client, &install_version).await?;
let download_url = if canary {
format!(
"https://dl.deno.land/canary/{}/{}",
install_version, *ARCHIVE_NAME
)
} else {
format!(
"{}/download/v{}/{}",
RELEASE_URL, install_version, *ARCHIVE_NAME
)
};

let archive_data = download_package(client, &*download_url).await?;

println!("Deno is upgrading to version {}", &install_version);

let old_exe_path = std::env::current_exe()?;
let new_exe_path = unpack(archive_data)?;
let permissions = fs::metadata(&old_exe_path)?.permissions();
fs::set_permissions(&new_exe_path, permissions)?;
check_exe(&new_exe_path, &install_version)?;
check_exe(&new_exe_path)?;

if !dry_run {
match output {
Expand All @@ -96,7 +131,9 @@ pub async fn upgrade_command(
Ok(())
}

async fn get_latest_version(client: &Client) -> Result<String, AnyError> {
async fn get_latest_release_version(
client: &Client,
) -> Result<String, AnyError> {
println!("Looking up latest version");

let res = client
Expand All @@ -108,18 +145,27 @@ async fn get_latest_version(client: &Client) -> Result<String, AnyError> {
Ok(version.replace("v", ""))
}

async fn get_latest_canary_version(
client: &Client,
) -> Result<String, AnyError> {
println!("Looking up latest version");

let res = client
.get("https://dl.deno.land/canary-latest.txt")
.send()
.await?;
let version = res.text().await?.trim().to_string();

Ok(version)
}

async fn download_package(
client: Client,
install_version: &str,
download_url: &str,
) -> Result<Vec<u8>, AnyError> {
let download_url = format!(
"{}/download/v{}/{}",
RELEASE_URL, install_version, *ARCHIVE_NAME
);

println!("Checking {}", &download_url);

let res = client.get(&download_url).send().await?;
let res = client.get(download_url).send().await?;

if res.status().is_success() {
println!("Download has been found");
Expand Down Expand Up @@ -200,13 +246,11 @@ fn replace_exe(new: &Path, old: &Path) -> Result<(), std::io::Error> {
Ok(())
}

fn check_exe(exe_path: &Path, expected_version: &str) -> Result<(), AnyError> {
fn check_exe(exe_path: &Path) -> Result<(), AnyError> {
let output = Command::new(exe_path)
.arg("-V")
.stderr(std::process::Stdio::inherit())
.output()?;
let stdout = String::from_utf8(output.stdout)?;
assert!(output.status.success());
assert_eq!(stdout.trim(), format!("deno {}", expected_version));
Ok(())
}
4 changes: 4 additions & 0 deletions cli/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ pub fn deno() -> String {
})
}

pub fn is_canary() -> bool {
option_env!("DENO_CANARY").is_some()
}

pub fn v8() -> &'static str {
deno_core::v8_version()
}

0 comments on commit 973af61

Please sign in to comment.