diff --git a/.github/workflows/crates-publish.yml b/.github/workflows/crates-publish.yml index 4d8c8056..2d2d0120 100644 --- a/.github/workflows/crates-publish.yml +++ b/.github/workflows/crates-publish.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: stable + toolchain: nightly-2022-08-03 override: true publish: diff --git a/.github/workflows/release-cross.yml b/.github/workflows/release-cross.yml index 9a2c8eac..16554df0 100644 --- a/.github/workflows/release-cross.yml +++ b/.github/workflows/release-cross.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: stable + toolchain: 1.57.0 profile: minimal default: true override: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e50032c4..50e4f847 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: stable + toolchain: 1.57.0 profile: minimal override: true components: rustfmt, clippy diff --git a/Cargo.lock b/Cargo.lock index 2c86ccfb..077b8794 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -225,26 +225,24 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.18" +version = "4.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +checksum = "335867764ed2de42325fafe6d18b8af74ba97ee0c590fa016f157535b42ab04b" dependencies = [ "atty", "bitflags", "clap_derive", "clap_lex", - "indexmap", - "lazy_static", + "once_cell", "strsim", "termcolor", - "textwrap", ] [[package]] name = "clap_derive" -version = "3.1.18" +version = "4.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c" +checksum = "16a1b0f6422af32d5da0c58e2703320f379216ee70198241c84173a8c5ac28f3" dependencies = [ "heck 0.4.0", "proc-macro-error", @@ -255,9 +253,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.2.4" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" dependencies = [ "os_str_bytes", ] @@ -660,9 +658,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "h2" -version = "0.3.12" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62eeb471aa3e3c9197aa4bfeabfe02982f6dc96f750486c0bb0009ac58b26d2b" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ "bytes", "fnv", @@ -985,24 +983,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.14" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", - "miow", - "ntapi", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", ] [[package]] @@ -1044,15 +1032,6 @@ dependencies = [ "zvariant_derive", ] -[[package]] -name = "ntapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" -dependencies = [ - "winapi", -] - [[package]] name = "num-integer" version = "0.1.45" @@ -1377,9 +1356,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.6" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -1625,12 +1604,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" -[[package]] -name = "shell-words" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" - [[package]] name = "shellexpand" version = "2.1.2" @@ -1780,13 +1753,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if", + "fastrand", "libc", - "rand", "redox_syscall", "remove_dir_all", "winapi", @@ -1811,12 +1784,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "textwrap" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" - [[package]] name = "thiserror" version = "1.0.37" @@ -1894,9 +1861,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.5.1" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3b82e6e823a9ee7d7f64b08f8ac3d5f08ac988f23157194bd32af3f2f92767" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ "autocfg", "bytes", @@ -1904,9 +1871,9 @@ dependencies = [ "memchr", "mio", "num_cpus", - "once_cell", "pin-project-lite", "signal-hook-registry", + "socket2", "winapi", ] @@ -1923,16 +1890,16 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.9" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", "futures-sink", - "log", "pin-project-lite", "tokio", + "tracing", ] [[package]] @@ -1968,7 +1935,6 @@ dependencies = [ "self_update", "semver", "serde", - "shell-words", "shellexpand", "strum 0.24.1", "sys-info", @@ -2236,12 +2202,13 @@ dependencies = [ [[package]] name = "which" -version = "4.1.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55551e42cbdf2ce2bedd2203d0cc08dba002c27510f86dab6d0ce304cba3dfe" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" dependencies = [ "either", "libc", + "once_cell", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index adff3ba6..85a44bae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,44 +20,43 @@ path = "src/main.rs" ##name = "topgrade_lib" [dependencies] -home = "~0.5" -directories = "~4.0" -serde = { version = "~1.0", features = ["derive"] } +home = "0.5" +directories = "4.0" +serde = { version = "1.0", features = ["derive"] } toml = "0.5" -which_crate = { version = "~4.1", package = "which" } -shellexpand = "~2.1" -clap = { version = "~3.1", features = ["cargo", "derive"] } -log = "~0.4" -walkdir = "~2.3" -console = "~0.15" -lazy_static = "~1.4" -chrono = "~0.4" -pretty_env_logger = "~0.4" -glob = "~0.3" -strum = { version = "~0.24", features = ["derive"] } -thiserror = "~1.0" -anyhow = "~1.0" -tempfile = "~3.2" -cfg-if = "~1.0" -tokio = { version = "~1.5", features = ["process", "rt-multi-thread"] } -futures = "~0.3" -regex = "~1.5" -sys-info = "~0.9" -semver = "~1.0" -shell-words = "~1.1" +which_crate = { version = "4.1", package = "which" } +shellexpand = "2.1" +clap = { version = "4.0.18", features = ["cargo", "derive"] } +log = "0.4" +walkdir = "2.3" +console = "0.15" +lazy_static = "1.4" +chrono = "0.4" +pretty_env_logger = "0.4" +glob = "0.3" +strum = { version = "0.24", features = ["derive"] } +thiserror = "1.0" +anyhow = "1.0" +tempfile = "3.2" +cfg-if = "1.0" +tokio = { version = "1.5", features = ["process", "rt-multi-thread"] } +futures = "0.3" +regex = "1.5" +sys-info = "0.9" +semver = "1.0" [target.'cfg(target_os = "macos")'.dependencies] -notify-rust = "~4.5" +notify-rust = "4.5" [target.'cfg(unix)'.dependencies] -nix = "~0.24" -rust-ini = "~0.18" -self_update_crate = { version = "~0.30", default-features = false, optional = true, package = "self_update", features = ["archive-tar", "compression-flate2", "rustls"] } +nix = "0.24" +rust-ini = "0.18" +self_update_crate = { version = "0.30", default-features = false, optional = true, package = "self_update", features = ["archive-tar", "compression-flate2", "rustls"] } [target.'cfg(windows)'.dependencies] -self_update_crate = { version = "~0.30", default-features = false, optional = true, package = "self_update", features = ["archive-zip", "compression-zip-deflate", "rustls"] } -winapi = "~0.3" -parselnk = "~0.1" +self_update_crate = { version = "0.30", default-features = false, optional = true, package = "self_update", features = ["archive-zip", "compression-zip-deflate", "rustls"] } +winapi = "0.3" +parselnk = "0.1" [profile.release] lto = true diff --git a/src/config.rs b/src/config.rs index 10727019..a9c893f5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,16 +1,16 @@ #![allow(dead_code)] -use anyhow::Context; -use anyhow::Result; -use clap::{ArgEnum, Parser}; -use directories::BaseDirs; -use log::debug; -use regex::Regex; -use serde::Deserialize; use std::collections::BTreeMap; use std::fs::write; use std::path::PathBuf; use std::process::Command; use std::{env, fs}; + +use anyhow::Result; +use clap::{Parser, ValueEnum}; +use directories::BaseDirs; +use log::debug; +use regex::Regex; +use serde::Deserialize; use strum::{EnumIter, EnumString, EnumVariantNames, IntoEnumIterator}; use sys_info::hostname; use which_crate::which; @@ -62,7 +62,7 @@ macro_rules! get_deprecated { type Commands = BTreeMap; -#[derive(ArgEnum, EnumString, EnumVariantNames, Debug, Clone, PartialEq, Eq, Deserialize, EnumIter, Copy)] +#[derive(ValueEnum, EnumString, EnumVariantNames, Debug, Clone, PartialEq, Eq, Deserialize, EnumIter, Copy)] #[clap(rename_all = "snake_case")] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] @@ -397,78 +397,78 @@ impl ConfigFile { // Command line arguments #[derive(Parser, Debug)] -#[clap(name = "Topgrade", version)] +#[command(name = "Topgrade", version)] pub struct CommandLineArgs { /// Edit the configuration file - #[clap(long = "edit-config")] + #[arg(long = "edit-config")] edit_config: bool, /// Show config reference - #[clap(long = "config-reference")] + #[arg(long = "config-reference")] show_config_reference: bool, /// Run inside tmux - #[clap(short = 't', long = "tmux")] + #[arg(short = 't', long = "tmux")] run_in_tmux: bool, /// Cleanup temporary or old files - #[clap(short = 'c', long = "cleanup")] + #[arg(short = 'c', long = "cleanup")] cleanup: bool, /// Print what would be done - #[clap(short = 'n', long = "dry-run")] + #[arg(short = 'n', long = "dry-run")] dry_run: bool, /// Do not ask to retry failed steps - #[clap(long = "no-retry")] + #[arg(long = "no-retry")] no_retry: bool, /// Do not perform upgrades for the given steps - #[clap(long = "disable", arg_enum, multiple_values = true)] + #[arg(long = "disable", value_name = "STEP", value_enum, num_args = 1..)] disable: Vec, /// Perform only the specified steps (experimental) - #[clap(long = "only", arg_enum, multiple_values = true)] + #[arg(long = "only", value_name = "STEP", value_enum, num_args = 1..)] only: Vec, /// Run only specific custom commands - #[clap(long = "custom-commands")] + #[arg(long = "custom-commands", value_name = "NAME", num_args = 1..)] custom_commands: Vec, /// Set environment variables - #[clap(long = "env", multiple_values = true)] + #[arg(long = "env", value_name = "NAME=VALUE", num_args = 1..)] env: Vec, /// Output logs - #[clap(short = 'v', long = "verbose")] + #[arg(short = 'v', long = "verbose")] pub verbose: bool, /// Prompt for a key before exiting - #[clap(short = 'k', long = "keep")] + #[arg(short = 'k', long = "keep")] keep_at_end: bool, /// Skip sending a notification at the end of a run - #[clap(long = "skip-notify")] + #[arg(long = "skip-notify")] skip_notify: bool, /// Say yes to package manager's prompt - #[clap(short = 'y', long = "yes", arg_enum, multiple_values = true, min_values = 0)] + #[arg(short = 'y', long = "yes", value_name = "STEP", value_enum, num_args = 0..)] yes: Option>, /// Don't pull the predefined git repos - #[clap(long = "disable-predefined-git-repos")] + #[arg(long = "disable-predefined-git-repos")] disable_predefined_git_repos: bool, /// Alternative configuration file - #[clap(long = "config")] + #[arg(long = "config", value_name = "PATH")] config: Option, /// A regular expression for restricting remote host execution - #[clap(long = "remote-host-limit")] + #[arg(long = "remote-host-limit", value_name = "REGEX")] remote_host_limit: Option, /// Show the reason for skipped steps - #[clap(long = "show-skipped")] + #[arg(long = "show-skipped")] show_skipped: bool, } @@ -626,16 +626,8 @@ impl Config { } /// Extra Tmux arguments - pub fn tmux_arguments(&self) -> anyhow::Result> { - let args = &self.config_file.tmux_arguments.as_deref().unwrap_or_default(); - shell_words::split(args) - // The only time the parse failed is in case of a missing close quote. - // The error message looks like this: - // Error: Failed to parse `tmux_arguments`: `'foo` - // - // Caused by: - // missing closing quote - .with_context(|| format!("Failed to parse `tmux_arguments`: `{args}`")) + pub fn tmux_arguments(&self) -> &Option { + &self.config_file.tmux_arguments } /// Prompt for a key before exiting diff --git a/src/ctrlc/interrupted.rs b/src/ctrlc/interrupted.rs index 28886d47..5322d9bb 100644 --- a/src/ctrlc/interrupted.rs +++ b/src/ctrlc/interrupted.rs @@ -1,7 +1,10 @@ +use lazy_static::lazy_static; use std::sync::atomic::{AtomicBool, Ordering}; -/// A global variable telling whether the application has been interrupted. -static INTERRUPTED: AtomicBool = AtomicBool::new(false); +lazy_static! { + /// A global variable telling whether the application has been interrupted. + static ref INTERRUPTED: AtomicBool = AtomicBool::new(false); +} /// Tells whether the program has been interrupted pub fn interrupted() -> bool { diff --git a/src/executor.rs b/src/executor.rs index b68b30a4..b568225e 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -194,12 +194,11 @@ impl DryCommand { print!( "Dry running: {} {}", self.program.to_string_lossy(), - shell_words::join( - self.args - .iter() - .map(|a| String::from(a.to_string_lossy())) - .collect::>() - ) + self.args + .iter() + .map(|a| String::from(a.to_string_lossy())) + .collect::>() + .join(" ") ); match &self.directory { Some(dir) => println!(" in {}", dir.to_string_lossy()), diff --git a/src/main.rs b/src/main.rs index d08d207e..66210df3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,7 +79,7 @@ fn run() -> Result<()> { if config.run_in_tmux() && env::var("TOPGRADE_INSIDE_TMUX").is_err() { #[cfg(unix)] { - tmux::run_in_tmux(config.tmux_arguments()?); + tmux::run_in_tmux(config.tmux_arguments()); } } @@ -351,7 +351,6 @@ fn run() -> Result<()> { runner.execute(Step::Kakoune, "Kakoune", || kakoune::upgrade_kak_plug(&ctx))?; runner.execute(Step::Node, "npm", || node::run_npm_upgrade(&ctx))?; runner.execute(Step::Node, "yarn", || node::run_yarn_upgrade(&ctx))?; - runner.execute(Step::Node, "pnpm", || node::run_pnpm_upgrade(&ctx))?; runner.execute(Step::Containers, "Containers", || containers::run_containers(&ctx))?; runner.execute(Step::Deno, "deno", || node::deno_upgrade(&ctx))?; runner.execute(Step::Composer, "composer", || generic::run_composer_update(&ctx))?; @@ -524,10 +523,7 @@ fn main() { .is_some()); if !skip_print { - // The `Debug` implementation of `anyhow::Result` prints a multi-line - // error message that includes all the 'causes' added with - // `.with_context(...)` calls. - println!("Error: {:?}", error); + println!("Error: {}", error); } exit(1); } diff --git a/src/steps/generic.rs b/src/steps/generic.rs index 7694eada..22c118f8 100644 --- a/src/steps/generic.rs +++ b/src/steps/generic.rs @@ -196,16 +196,12 @@ pub fn run_krew_upgrade(run_type: RunType) -> Result<()> { pub fn run_gcloud_components_update(run_type: RunType) -> Result<()> { let gcloud = utils::require("gcloud")?; - if gcloud.starts_with("/snap") { - Ok(()) - } else { - print_separator("gcloud"); + print_separator("gcloud"); - run_type - .execute(gcloud) - .args(["components", "update", "--quiet"]) - .check_run() - } + run_type + .execute(gcloud) + .args(["components", "update", "--quiet"]) + .check_run() } pub fn run_jetpack(run_type: RunType) -> Result<()> { diff --git a/src/steps/node.rs b/src/steps/node.rs index c702076a..ea1fbe4c 100644 --- a/src/steps/node.rs +++ b/src/steps/node.rs @@ -1,6 +1,5 @@ #![allow(unused_imports)] -use std::fmt::Display; #[cfg(unix)] use std::os::unix::prelude::MetadataExt; use std::path::PathBuf; @@ -18,71 +17,24 @@ use crate::terminal::print_separator; use crate::utils::{require, PathExt}; use crate::{error::SkipStep, execution_context::ExecutionContext}; -enum NPMVariant { - Npm, - Pnpm, -} - -impl NPMVariant { - const fn long_name(&self) -> &str { - match self { - NPMVariant::Npm => "Node Package Manager", - NPMVariant::Pnpm => "PNPM", - } - } - - const fn short_name(&self) -> &str { - match self { - NPMVariant::Npm => "npm", - NPMVariant::Pnpm => "pnpm", - } - } - - const fn is_npm(&self) -> bool { - matches!(self, NPMVariant::Npm) - } -} - -impl Display for NPMVariant { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(self.short_name()) - } -} - #[allow(clippy::upper_case_acronyms)] struct NPM { command: PathBuf, - variant: NPMVariant, } impl NPM { - fn new(command: PathBuf, variant: NPMVariant) -> Self { - Self { command, variant } - } - - /// Is the “NPM” version larger than 8.11.0? - fn is_npm_8(&self) -> bool { - let v = self.version(); - - self.variant.is_npm() && matches!(v, Ok(v) if v >= Version::new(8, 11, 0)) - } - - /// Get the most suitable “global location” argument - /// of this NPM instance. - /// - /// If the “NPM” version is larger than 8.11.0, we use - /// `--location=global`; otherwise, use `-g`. - fn global_location_arg(&self) -> &str { - if self.is_npm_8() { - "--location=global" - } else { - "-g" - } + fn new(command: PathBuf) -> Self { + Self { command } } #[cfg(target_os = "linux")] fn root(&self) -> Result { - let args = ["root", self.global_location_arg()]; + let version = self.version()?; + let args = if version < Version::new(8, 11, 0) { + ["root", "-g"] + } else { + ["root", "--location=global"] + }; Command::new(&self.command) .args(args) .check_output() @@ -98,8 +50,13 @@ impl NPM { } fn upgrade(&self, run_type: RunType, use_sudo: bool) -> Result<()> { - print_separator(self.variant.long_name()); - let args = ["update", self.global_location_arg()]; + print_separator("Node Package Manager"); + let version = self.version()?; + let args = if version < Version::new(8, 11, 0) { + ["update", "-g"] + } else { + ["update", "--location=global"] + }; if use_sudo { run_type.execute("sudo").args(args).check_run()?; } else { @@ -113,7 +70,7 @@ impl NPM { pub fn should_use_sudo(&self) -> Result { let npm_root = self.root()?; if !npm_root.exists() { - return Err(SkipStep(format!("{} root at {} doesn't exist", self.variant, npm_root.display())).into()); + return Err(SkipStep(format!("NPM root at {} doesn't exist", npm_root.display(),)).into()); } let metadata = std::fs::metadata(&npm_root)?; @@ -136,17 +93,6 @@ impl Yarn { } } - fn has_global_subcmd(&self) -> bool { - // Get the version of Yarn. After Yarn 2.x (berry), - // “yarn global” has been replaced with “yarn dlx”. - // - // As “yarn dlx” don't need to “upgrade”, we - // ignore the whole task if Yarn is 2.x or above. - let version = Command::new(&self.command).args(["--version"]).check_output(); - - matches!(version, Ok(ver) if ver.starts_with('1') || ver.starts_with('0')) - } - #[cfg(target_os = "linux")] fn root(&self) -> Result { let args = ["global", "dir"]; @@ -177,7 +123,7 @@ impl Yarn { pub fn should_use_sudo(&self) -> Result { let yarn_root = self.root()?; if !yarn_root.exists() { - return Err(SkipStep(format!("Yarn root at {} doesn't exist", yarn_root.display(),)).into()); + return Err(SkipStep(format!("NPM root at {} doesn't exist", yarn_root.display(),)).into()); } let metadata = std::fs::metadata(&yarn_root)?; @@ -216,7 +162,7 @@ fn should_use_sudo_yarn(yarn: &Yarn, ctx: &ExecutionContext) -> Result { } pub fn run_npm_upgrade(ctx: &ExecutionContext) -> Result<()> { - let npm = require("npm").map(|b| NPM::new(b, NPMVariant::Npm))?; + let npm = require("pnpm").or_else(|_| require("npm")).map(NPM::new)?; #[cfg(target_os = "linux")] { @@ -229,28 +175,9 @@ pub fn run_npm_upgrade(ctx: &ExecutionContext) -> Result<()> { } } -pub fn run_pnpm_upgrade(ctx: &ExecutionContext) -> Result<()> { - let pnpm = require("pnpm").map(|b| NPM::new(b, NPMVariant::Pnpm))?; - - #[cfg(target_os = "linux")] - { - pnpm.upgrade(ctx.run_type(), should_use_sudo(&pnpm, ctx)?) - } - - #[cfg(not(target_os = "linux"))] - { - pnpm.upgrade(ctx.run_type(), false) - } -} - pub fn run_yarn_upgrade(ctx: &ExecutionContext) -> Result<()> { let yarn = require("yarn").map(Yarn::new)?; - if !yarn.has_global_subcmd() { - debug!("Yarn is 2.x or above, skipping global upgrade"); - return Ok(()); - } - #[cfg(target_os = "linux")] { yarn.upgrade(ctx.run_type(), should_use_sudo_yarn(&yarn, ctx)?) diff --git a/src/steps/os/archlinux.rs b/src/steps/os/archlinux.rs index 892a8994..74290377 100644 --- a/src/steps/os/archlinux.rs +++ b/src/steps/os/archlinux.rs @@ -245,7 +245,7 @@ impl Aura { impl ArchPackageManager for Aura { fn upgrade(&self, ctx: &ExecutionContext) -> Result<()> { - let sudo = which("sudo").unwrap_or_else(PathBuf::new); + let sudo = which("sudo").unwrap_or(PathBuf::new()); let mut aur_update = ctx.run_type().execute(&sudo); if sudo.ends_with("sudo") { diff --git a/src/steps/os/os_release/debian b/src/steps/os/os_release/debian index 611cf746..120c51b0 100644 --- a/src/steps/os/os_release/debian +++ b/src/steps/os/os_release/debian @@ -1,9 +1,8 @@ -PRETTY_NAME="Debian GNU/Linux 11 (bullseye)" +PRETTY_NAME="Debian GNU/Linux 8 (jessie)" NAME="Debian GNU/Linux" -VERSION_ID="11" -VERSION="11 (bullseye)" -VERSION_CODENAME=bullseye +VERSION_ID="8" +VERSION="8 (jessie)" ID=debian -HOME_URL="https://www.debian.org/" -SUPPORT_URL="https://www.debian.org/support" +HOME_URL="http://www.debian.org/" +SUPPORT_URL="http://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/" diff --git a/src/steps/os/windows.rs b/src/steps/os/windows.rs index 14d57595..86c4515a 100644 --- a/src/steps/os/windows.rs +++ b/src/steps/os/windows.rs @@ -26,7 +26,7 @@ pub fn run_chocolatey(ctx: &ExecutionContext) -> Result<()> { args.insert(0, "choco"); } - let mut command = ctx.run_type().execute(cmd); + let mut command = ctx.run_type().execute(&cmd); command.args(&args); @@ -47,7 +47,7 @@ pub fn run_winget(ctx: &ExecutionContext) -> Result<()> { return Err(SkipStep(String::from("Winget is disabled by default")).into()); } - ctx.run_type().execute(&winget).args(["upgrade", "--all"]).check_run() + ctx.run_type().execute(&winget).args(&["upgrade", "--all"]).check_run() } pub fn run_scoop(cleanup: bool, run_type: RunType) -> Result<()> { @@ -55,34 +55,34 @@ pub fn run_scoop(cleanup: bool, run_type: RunType) -> Result<()> { print_separator("Scoop"); - run_type.execute(&scoop).args(["update"]).check_run()?; - run_type.execute(&scoop).args(["update", "*"]).check_run()?; + run_type.execute(&scoop).args(&["update"]).check_run()?; + run_type.execute(&scoop).args(&["update", "*"]).check_run()?; if cleanup { - run_type.execute(&scoop).args(["cleanup", "*"]).check_run()?; + run_type.execute(&scoop).args(&["cleanup", "*"]).check_run()?; } Ok(()) } fn get_wsl_distributions(wsl: &Path) -> Result> { - let output = Command::new(wsl).args(["--list", "-q"]).check_output()?; + let output = Command::new(wsl).args(&["--list", "-q"]).check_output()?; Ok(output .lines() .filter(|s| !s.is_empty()) - .map(|x| x.replace(['\u{0}', '\r'], "")) + .map(|x| x.replace('\u{0}', "").replace('\r', "")) .collect()) } fn upgrade_wsl_distribution(wsl: &Path, dist: &str, ctx: &ExecutionContext) -> Result<()> { - let topgrade = Command::new(wsl) - .args(["-d", dist, "bash", "-lc", "which topgrade"]) + let topgrade = Command::new(&wsl) + .args(&["-d", dist, "bash", "-lc", "which topgrade"]) .check_output() .map_err(|_| SkipStep(String::from("Could not find Topgrade installed in WSL")))?; - let mut command = ctx.run_type().execute(wsl); + let mut command = ctx.run_type().execute(&wsl); command - .args(["-d", dist, "bash", "-c"]) + .args(&["-d", dist, "bash", "-c"]) .arg(format!("TOPGRADE_PREFIX={} exec {}", dist, topgrade)); if ctx.config().yes(Step::Wsl) { @@ -134,7 +134,7 @@ pub fn windows_update(ctx: &ExecutionContext) -> Result<()> { } pub fn reboot() { - Command::new("shutdown").args(["/R", "/T", "0"]).spawn().ok(); + Command::new("shutdown").args(&["/R", "/T", "0"]).spawn().ok(); } pub fn insert_startup_scripts(ctx: &ExecutionContext, git_repos: &mut Repositories) -> Result<()> { diff --git a/src/steps/powershell.rs b/src/steps/powershell.rs index 3d60ea8d..78145ed1 100644 --- a/src/steps/powershell.rs +++ b/src/steps/powershell.rs @@ -46,8 +46,8 @@ impl Powershell { #[cfg(windows)] pub fn has_module(powershell: &Path, command: &str) -> bool { - Command::new(powershell) - .args([ + Command::new(&powershell) + .args(&[ "-NoProfile", "-Command", &format!("Get-Module -ListAvailable {}", command), @@ -79,7 +79,6 @@ impl Powershell { println!("Updating modules..."); ctx.run_type() .execute(powershell) - // This probably doesn't need `shell_words::join`. .args(["-NoProfile", "-Command", &cmd.join(" ")]) .check_run() } @@ -100,14 +99,14 @@ impl Powershell { let mut command = if let Some(sudo) = ctx.sudo() { let mut command = ctx.run_type().execute(sudo); - command.arg(powershell); + command.arg(&powershell); command } else { - ctx.run_type().execute(powershell) + ctx.run_type().execute(&powershell) }; command - .args([ + .args(&[ "-NoProfile", "-Command", &format!( diff --git a/src/steps/remote/ssh.rs b/src/steps/remote/ssh.rs index c94552fb..8636b895 100644 --- a/src/steps/remote/ssh.rs +++ b/src/steps/remote/ssh.rs @@ -24,7 +24,7 @@ pub fn ssh_step(ctx: &ExecutionContext, hostname: &str) -> Result<()> { #[cfg(unix)] { prepare_async_ssh_command(&mut args); - crate::tmux::run_command(ctx, &shell_words::join(args))?; + crate::tmux::run_command(ctx, &args.join(" "))?; Err(SkipStep(String::from("Remote Topgrade launched in Tmux")).into()) } diff --git a/src/steps/tmux.rs b/src/steps/tmux.rs index 388b65b4..85082b98 100644 --- a/src/steps/tmux.rs +++ b/src/steps/tmux.rs @@ -29,10 +29,12 @@ struct Tmux { } impl Tmux { - fn new(args: Vec) -> Self { + fn new(args: &Option) -> Self { Self { tmux: which("tmux").expect("Could not find tmux"), - args: if args.is_empty() { None } else { Some(args) }, + args: args + .as_ref() + .map(|args| args.split_whitespace().map(String::from).collect()), } } @@ -73,7 +75,7 @@ impl Tmux { } } -pub fn run_in_tmux(args: Vec) -> ! { +pub fn run_in_tmux(args: &Option) -> ! { let command = { let mut command = vec![ String::from("env"), @@ -81,7 +83,7 @@ pub fn run_in_tmux(args: Vec) -> ! { String::from("TOPGRADE_INSIDE_TMUX=1"), ]; command.extend(env::args()); - shell_words::join(command) + command.join(" ") }; let tmux = Tmux::new(args); @@ -106,7 +108,7 @@ pub fn run_in_tmux(args: Vec) -> ! { } pub fn run_command(ctx: &ExecutionContext, command: &str) -> Result<()> { - Tmux::new(ctx.config().tmux_arguments()?) + Tmux::new(ctx.config().tmux_arguments()) .build() .args(["new-window", "-a", "-t", "topgrade:1", command]) .env_remove("TMUX")