10.2.1 release (#244)
This commit is contained in:
8
.github/workflows/check-and-lint.yaml
vendored
8
.github/workflows/check-and-lint.yaml
vendored
@@ -23,10 +23,11 @@ jobs:
|
||||
uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: '${{ env.RUST_VER }}'
|
||||
targets: ${{ matrix.target }}
|
||||
components: clippy, rustfmt
|
||||
components: rustfmt
|
||||
|
||||
- name: Run cargo fmt
|
||||
env:
|
||||
TERM: xterm-256color
|
||||
run: |
|
||||
cargo fmt --all -- --check
|
||||
|
||||
@@ -72,8 +73,7 @@ jobs:
|
||||
uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: '${{ env.RUST_VER }}'
|
||||
targets: ${{ matrix.target }}
|
||||
components: clippy, rustfmt
|
||||
components: clippy
|
||||
|
||||
- name: Setup Rust Cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
109
Cargo.lock
generated
109
Cargo.lock
generated
@@ -59,11 +59,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "1.7.1"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28"
|
||||
checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833"
|
||||
dependencies = [
|
||||
"concurrent-queue 1.2.4",
|
||||
"concurrent-queue",
|
||||
"event-listener",
|
||||
"futures-core",
|
||||
]
|
||||
@@ -76,7 +76,7 @@ checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"async-task",
|
||||
"concurrent-queue 2.0.0",
|
||||
"concurrent-queue",
|
||||
"fastrand",
|
||||
"futures-lite",
|
||||
"slab",
|
||||
@@ -84,13 +84,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-io"
|
||||
version = "1.10.0"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8121296a9f05be7f34aa4196b1747243b3b62e048bb7906f644f3fbfc490cf7"
|
||||
checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"autocfg",
|
||||
"concurrent-queue 1.2.4",
|
||||
"concurrent-queue",
|
||||
"futures-lite",
|
||||
"libc",
|
||||
"log",
|
||||
@@ -99,7 +99,7 @@ dependencies = [
|
||||
"slab",
|
||||
"socket2",
|
||||
"waker-fn",
|
||||
"winapi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -131,9 +131,9 @@ checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.58"
|
||||
version = "0.1.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c"
|
||||
checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -167,7 +167,7 @@ dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"miniz_oxide 0.5.4",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
]
|
||||
@@ -208,12 +208,6 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
|
||||
|
||||
[[package]]
|
||||
name = "cache-padded"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.77"
|
||||
@@ -236,7 +230,7 @@ dependencies = [
|
||||
"js-sys",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time 0.1.44",
|
||||
"time 0.1.45",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
@@ -258,6 +252,15 @@ dependencies = [
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "3.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da92e6facd8d73c22745a5d3cbb59bdf8e46e3235c923e516527d8e81eec14a4"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.1.18"
|
||||
@@ -280,6 +283,16 @@ dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_mangen"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "121b598d1b9d63d4ff3b7dae8defd88cc23e41850ee89fd2feec2e7d992e6ec8"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"roff",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
@@ -317,15 +330,6 @@ dependencies = [
|
||||
"tracing-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "1.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c"
|
||||
dependencies = [
|
||||
"cache-padded",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "2.0.0"
|
||||
@@ -565,12 +569,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.24"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
|
||||
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
"miniz_oxide 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1046,6 +1050,15 @@ dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.7.14"
|
||||
@@ -1261,9 +1274,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.4"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
|
||||
checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@@ -1305,16 +1318,16 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "2.4.0"
|
||||
version = "2.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab4609a838d88b73d8238967b60dd115cc08d38e2bbaf51ee1e4b695f89122e2"
|
||||
checksum = "166ca89eb77fd403230b9c156612965a81e094ec6ec3aa13663d4c8b113fa748"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"log",
|
||||
"wepoll-ffi",
|
||||
"winapi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1533,6 +1546,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roff"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316"
|
||||
|
||||
[[package]]
|
||||
name = "rust-ini"
|
||||
version = "0.18.0"
|
||||
@@ -1642,18 +1661,18 @@ checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.147"
|
||||
version = "1.0.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
|
||||
checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.147"
|
||||
version = "1.0.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
|
||||
checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1830,9 +1849,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.103"
|
||||
version = "1.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
|
||||
checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1931,9 +1950,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.44"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||
@@ -2036,11 +2055,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "topgrade"
|
||||
version = "10.2.0"
|
||||
version = "10.2.1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"clap_mangen",
|
||||
"color-eyre",
|
||||
"console",
|
||||
"directories",
|
||||
|
||||
@@ -6,7 +6,7 @@ keywords = ["upgrade", "update"]
|
||||
license = "GPL-3.0"
|
||||
# license-file = "LICENSE"
|
||||
repository = "https://github.com/topgrade-rs/topgrade"
|
||||
version = "10.2.0"
|
||||
version = "10.2.1"
|
||||
authors = ["Roey Darwish Dror <roey.ghost@gmail.com>", "Thomas Schönauer <t.schoenauer@hgs-wt.at>"]
|
||||
exclude = ["doc/screenshot.gif"]
|
||||
edition = "2021"
|
||||
@@ -28,6 +28,8 @@ toml = "0.5"
|
||||
which_crate = { version = "~4.1", package = "which" }
|
||||
shellexpand = "~2.1"
|
||||
clap = { version = "~3.1", features = ["cargo", "derive"] }
|
||||
clap_complete = "~3.1"
|
||||
clap_mangen = "~0.1"
|
||||
walkdir = "~2.3"
|
||||
console = "~0.15"
|
||||
lazy_static = "~1.4"
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
# Do not ask to retry failed steps (default: false)
|
||||
#no_retry = true
|
||||
|
||||
# Run `sudo -v` to cache credentials at the start of the run; this avoids a
|
||||
# blocking password prompt in the middle of a possibly-unattended run.
|
||||
#pre_sudo = false
|
||||
|
||||
# Run inside tmux
|
||||
#run_in_tmux = true
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::process::Command;
|
||||
use std::{env, fs};
|
||||
|
||||
use clap::{ArgEnum, Parser};
|
||||
use clap_complete::Shell;
|
||||
use color_eyre::eyre;
|
||||
use color_eyre::eyre::Context;
|
||||
use color_eyre::eyre::Result;
|
||||
@@ -106,6 +107,7 @@ pub enum Step {
|
||||
HomeManager,
|
||||
Jetpack,
|
||||
Julia,
|
||||
Juliaup,
|
||||
Kakoune,
|
||||
Krew,
|
||||
Macports,
|
||||
@@ -129,6 +131,7 @@ pub enum Step {
|
||||
Remotes,
|
||||
Restarts,
|
||||
Rtcl,
|
||||
RubyGems,
|
||||
Rustup,
|
||||
Scoop,
|
||||
Sdkman,
|
||||
@@ -223,6 +226,7 @@ pub struct Brew {
|
||||
#[derive(Debug, Deserialize, Clone, Copy)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ArchPackageManager {
|
||||
GarudaUpdate,
|
||||
Autodetect,
|
||||
Trizen,
|
||||
Paru,
|
||||
@@ -269,6 +273,7 @@ pub struct Vim {
|
||||
#[serde(deny_unknown_fields)]
|
||||
/// Configuration file
|
||||
pub struct ConfigFile {
|
||||
pre_sudo: Option<bool>,
|
||||
pre_commands: Option<Commands>,
|
||||
post_commands: Option<Commands>,
|
||||
commands: Option<Commands>,
|
||||
@@ -485,6 +490,14 @@ pub struct CommandLineArgs {
|
||||
/// See: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/struct.EnvFilter.html
|
||||
#[clap(long, default_value = "info")]
|
||||
pub log_filter: String,
|
||||
|
||||
/// Print completion script for the given shell and exit
|
||||
#[clap(long, arg_enum, hide = true)]
|
||||
pub gen_completion: Option<Shell>,
|
||||
|
||||
/// Print roff manpage and exit
|
||||
#[clap(long, hide = true)]
|
||||
pub gen_manpage: bool,
|
||||
}
|
||||
|
||||
impl CommandLineArgs {
|
||||
@@ -947,6 +960,12 @@ impl Config {
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// If `true`, `sudo` should be called after `pre_commands` in order to elevate at the
|
||||
/// start of the session (and not in the middle).
|
||||
pub fn pre_sudo(&self) -> bool {
|
||||
self.config_file.pre_sudo.unwrap_or(false)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn npm_use_sudo(&self) -> bool {
|
||||
self.config_file
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
#![allow(dead_code)]
|
||||
use crate::executor::RunType;
|
||||
use crate::git::Git;
|
||||
use crate::sudo::Sudo;
|
||||
use crate::utils::require_option;
|
||||
use crate::{config::Config, executor::Executor};
|
||||
use color_eyre::eyre::Result;
|
||||
use directories::BaseDirs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::Path;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct ExecutionContext<'a> {
|
||||
run_type: RunType,
|
||||
sudo: &'a Option<PathBuf>,
|
||||
sudo: Option<Sudo>,
|
||||
git: &'a Git,
|
||||
config: &'a Config,
|
||||
base_dirs: &'a BaseDirs,
|
||||
@@ -23,7 +24,7 @@ pub struct ExecutionContext<'a> {
|
||||
impl<'a> ExecutionContext<'a> {
|
||||
pub fn new(
|
||||
run_type: RunType,
|
||||
sudo: &'a Option<PathBuf>,
|
||||
sudo: Option<Sudo>,
|
||||
git: &'a Git,
|
||||
config: &'a Config,
|
||||
base_dirs: &'a BaseDirs,
|
||||
@@ -40,18 +41,7 @@ impl<'a> ExecutionContext<'a> {
|
||||
|
||||
pub fn execute_elevated(&self, command: &Path, interactive: bool) -> Result<Executor> {
|
||||
let sudo = require_option(self.sudo.clone(), "Sudo is required for this operation".into())?;
|
||||
let mut cmd = self.run_type.execute(&sudo);
|
||||
|
||||
if sudo.ends_with("sudo") {
|
||||
cmd.arg("--preserve-env=DIFFPROG");
|
||||
}
|
||||
|
||||
if interactive {
|
||||
cmd.arg("-i");
|
||||
}
|
||||
|
||||
cmd.arg(command);
|
||||
Ok(cmd)
|
||||
Ok(sudo.execute_elevated(self, command, interactive))
|
||||
}
|
||||
|
||||
pub fn run_type(&self) -> RunType {
|
||||
@@ -62,8 +52,8 @@ impl<'a> ExecutionContext<'a> {
|
||||
self.git
|
||||
}
|
||||
|
||||
pub fn sudo(&self) -> &Option<PathBuf> {
|
||||
self.sudo
|
||||
pub fn sudo(&self) -> &Option<Sudo> {
|
||||
&self.sudo
|
||||
}
|
||||
|
||||
pub fn config(&self) -> &Config {
|
||||
|
||||
@@ -176,7 +176,7 @@ impl Executor {
|
||||
|
||||
/// An extension of `status_checked` that allows you to set a sequence of codes
|
||||
/// that can indicate success of a script
|
||||
#[cfg_attr(windows, allow(dead_code))]
|
||||
#[allow(dead_code)]
|
||||
pub fn status_checked_with_codes(&mut self, codes: &[i32]) -> Result<()> {
|
||||
match self {
|
||||
Executor::Wet(c) => c.status_checked_with(|status| {
|
||||
|
||||
48
src/main.rs
48
src/main.rs
@@ -4,6 +4,7 @@ use std::env;
|
||||
use std::io;
|
||||
use std::process::exit;
|
||||
|
||||
use clap::CommandFactory;
|
||||
use clap::{crate_version, Parser};
|
||||
use color_eyre::eyre::Context;
|
||||
use color_eyre::eyre::{eyre, Result};
|
||||
@@ -30,6 +31,7 @@ mod self_renamer;
|
||||
#[cfg(feature = "self-update")]
|
||||
mod self_update;
|
||||
mod steps;
|
||||
mod sudo;
|
||||
mod terminal;
|
||||
mod utils;
|
||||
|
||||
@@ -41,6 +43,18 @@ fn run() -> Result<()> {
|
||||
|
||||
let opt = CommandLineArgs::parse();
|
||||
|
||||
if let Some(shell) = opt.gen_completion {
|
||||
let cmd = &mut CommandLineArgs::command();
|
||||
clap_complete::generate(shell, cmd, clap::crate_name!(), &mut std::io::stdout());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if opt.gen_manpage {
|
||||
let man = clap_mangen::Man::new(CommandLineArgs::command());
|
||||
man.render(&mut std::io::stdout())?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
install_tracing(&opt.tracing_filter_directives())?;
|
||||
|
||||
for env in opt.env_variables() {
|
||||
@@ -82,10 +96,10 @@ fn run() -> Result<()> {
|
||||
let git = git::Git::new();
|
||||
let mut git_repos = git::Repositories::new(&git);
|
||||
|
||||
let sudo = utils::sudo();
|
||||
let sudo = sudo::Sudo::detect();
|
||||
let run_type = executor::RunType::new(config.dry_run());
|
||||
|
||||
let ctx = execution_context::ExecutionContext::new(run_type, &sudo, &git, &config, &base_dirs);
|
||||
let ctx = execution_context::ExecutionContext::new(run_type, sudo, &git, &config, &base_dirs);
|
||||
|
||||
let mut runner = runner::Runner::new(&ctx);
|
||||
|
||||
@@ -119,6 +133,12 @@ fn run() -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
if config.pre_sudo() {
|
||||
if let Some(sudo) = ctx.sudo() {
|
||||
sudo.elevate(&ctx)?;
|
||||
}
|
||||
}
|
||||
|
||||
let powershell = powershell::Powershell::new();
|
||||
let should_run_powershell = powershell.profile().is_some() && config.should_run(Step::Powershell);
|
||||
|
||||
@@ -197,17 +217,17 @@ fn run() -> Result<()> {
|
||||
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
runner.execute(Step::Pkg, "DragonFly BSD Packages", || {
|
||||
dragonfly::upgrade_packages(sudo.as_ref(), run_type)
|
||||
dragonfly::upgrade_packages(ctx.sudo().as_ref(), run_type)
|
||||
})?;
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
runner.execute(Step::Pkg, "FreeBSD Packages", || {
|
||||
freebsd::upgrade_packages(&ctx, sudo.as_ref(), run_type)
|
||||
freebsd::upgrade_packages(&ctx, ctx.sudo().as_ref(), run_type)
|
||||
})?;
|
||||
|
||||
#[cfg(target_os = "openbsd")]
|
||||
runner.execute(Step::Pkg, "OpenBSD Packages", || {
|
||||
openbsd::upgrade_packages(sudo.as_ref(), run_type)
|
||||
openbsd::upgrade_packages(ctx.sudo().as_ref(), run_type)
|
||||
})?;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
@@ -319,6 +339,7 @@ fn run() -> Result<()> {
|
||||
runner.execute(Step::Atom, "apm", || generic::run_apm(run_type))?;
|
||||
runner.execute(Step::Fossil, "fossil", || generic::run_fossil(run_type))?;
|
||||
runner.execute(Step::Rustup, "rustup", || generic::run_rustup(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Juliaup, "juliaup", || generic::run_juliaup(&base_dirs, run_type))?;
|
||||
runner.execute(Step::Dotnet, ".NET", || generic::run_dotnet_upgrade(&ctx))?;
|
||||
runner.execute(Step::Choosenim, "choosenim", || generic::run_choosenim(&ctx))?;
|
||||
runner.execute(Step::Cargo, "cargo", || generic::run_cargo_update(&ctx))?;
|
||||
@@ -354,6 +375,9 @@ fn run() -> Result<()> {
|
||||
runner.execute(Step::Composer, "composer", || generic::run_composer_update(&ctx))?;
|
||||
runner.execute(Step::Krew, "krew", || generic::run_krew_upgrade(run_type))?;
|
||||
runner.execute(Step::Gem, "gem", || generic::run_gem(&base_dirs, run_type))?;
|
||||
runner.execute(Step::RubyGems, "rubygems", || {
|
||||
generic::run_rubygems(&base_dirs, run_type)
|
||||
})?;
|
||||
runner.execute(Step::Julia, "julia", || generic::update_julia_packages(&ctx))?;
|
||||
runner.execute(Step::Haxelib, "haxelib", || generic::run_haxelib_update(&ctx))?;
|
||||
runner.execute(Step::Sheldon, "sheldon", || generic::run_sheldon(&ctx))?;
|
||||
@@ -374,7 +398,7 @@ fn run() -> Result<()> {
|
||||
runner.execute(Step::DebGet, "deb-get", || linux::run_deb_get(&ctx))?;
|
||||
runner.execute(Step::Toolbx, "toolbx", || toolbx::run_toolbx(&ctx))?;
|
||||
runner.execute(Step::Flatpak, "Flatpak", || linux::flatpak_update(&ctx))?;
|
||||
runner.execute(Step::Snap, "snap", || linux::run_snap(sudo.as_ref(), run_type))?;
|
||||
runner.execute(Step::Snap, "snap", || linux::run_snap(ctx.sudo().as_ref(), run_type))?;
|
||||
runner.execute(Step::Pacstall, "pacstall", || linux::run_pacstall(&ctx))?;
|
||||
runner.execute(Step::Pacdef, "pacdef", || linux::run_pacdef(&ctx))?;
|
||||
runner.execute(Step::Protonup, "protonup", || linux::run_protonup_update(&ctx))?;
|
||||
@@ -394,11 +418,11 @@ fn run() -> Result<()> {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
runner.execute(Step::System, "pihole", || {
|
||||
linux::run_pihole_update(sudo.as_ref(), run_type)
|
||||
linux::run_pihole_update(ctx.sudo().as_ref(), run_type)
|
||||
})?;
|
||||
runner.execute(Step::Firmware, "Firmware upgrades", || linux::run_fwupdmgr(&ctx))?;
|
||||
runner.execute(Step::Restarts, "Restarts", || {
|
||||
linux::run_needrestart(sudo.as_ref(), run_type)
|
||||
linux::run_needrestart(ctx.sudo().as_ref(), run_type)
|
||||
})?;
|
||||
}
|
||||
|
||||
@@ -411,12 +435,12 @@ fn run() -> Result<()> {
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
runner.execute(Step::System, "FreeBSD Upgrade", || {
|
||||
freebsd::upgrade_freebsd(sudo.as_ref(), run_type)
|
||||
freebsd::upgrade_freebsd(ctx.sudo().as_ref(), run_type)
|
||||
})?;
|
||||
|
||||
#[cfg(target_os = "openbsd")]
|
||||
runner.execute(Step::System, "OpenBSD Upgrade", || {
|
||||
openbsd::upgrade_openbsd(sudo.as_ref(), run_type)
|
||||
openbsd::upgrade_openbsd(ctx.sudo().as_ref(), run_type)
|
||||
})?;
|
||||
|
||||
#[cfg(windows)]
|
||||
@@ -448,10 +472,10 @@ fn run() -> Result<()> {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
freebsd::audit_packages(&sudo).ok();
|
||||
freebsd::audit_packages(ctx.sudo().as_ref()).ok();
|
||||
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
dragonfly::audit_packages(&sudo).ok();
|
||||
dragonfly::audit_packages(ctx.sudo().as_ref()).ok();
|
||||
}
|
||||
|
||||
let mut post_command_failed = false;
|
||||
|
||||
@@ -70,7 +70,7 @@ pub fn run_gem(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
let gem = utils::require("gem")?;
|
||||
base_dirs.home_dir().join(".gem").require()?;
|
||||
|
||||
print_separator("RubyGems");
|
||||
print_separator("Gems");
|
||||
|
||||
let mut command = run_type.execute(gem);
|
||||
command.arg("update");
|
||||
@@ -83,6 +83,23 @@ pub fn run_gem(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
command.status_checked()
|
||||
}
|
||||
|
||||
pub fn run_rubygems(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
let gem = utils::require("gem")?;
|
||||
base_dirs.home_dir().join(".gem").require()?;
|
||||
|
||||
print_separator("RubyGems");
|
||||
|
||||
let mut command = run_type.execute(gem);
|
||||
command.arg("update --system");
|
||||
|
||||
if env::var_os("RBENV_SHELL").is_none() {
|
||||
debug!("Detected rbenv. Avoiding --user-install");
|
||||
command.arg("--user-install");
|
||||
}
|
||||
|
||||
command.status_checked()
|
||||
}
|
||||
|
||||
pub fn run_haxelib_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
let haxelib = utils::require("haxelib")?;
|
||||
|
||||
@@ -175,6 +192,18 @@ pub fn run_rustup(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
run_type.execute(&rustup).arg("update").status_checked()
|
||||
}
|
||||
|
||||
pub fn run_juliaup(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> {
|
||||
let juliaup = utils::require("juliaup")?;
|
||||
|
||||
print_separator("juliaup");
|
||||
|
||||
if juliaup.canonicalize()?.is_descendant_of(base_dirs.home_dir()) {
|
||||
run_type.execute(&juliaup).args(["self", "update"]).status_checked()?;
|
||||
}
|
||||
|
||||
run_type.execute(&juliaup).arg("update").status_checked()
|
||||
}
|
||||
|
||||
pub fn run_choosenim(ctx: &ExecutionContext) -> Result<()> {
|
||||
let choosenim = utils::require("choosenim")?;
|
||||
|
||||
|
||||
@@ -12,9 +12,7 @@ use semver::Version;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::command::CommandExt;
|
||||
use crate::executor::RunType;
|
||||
use crate::terminal::print_separator;
|
||||
use crate::utils::sudo;
|
||||
use crate::utils::{require, PathExt};
|
||||
use crate::{error::SkipStep, execution_context::ExecutionContext};
|
||||
|
||||
@@ -90,14 +88,17 @@ impl NPM {
|
||||
Version::parse(&version_str?).map_err(|err| err.into())
|
||||
}
|
||||
|
||||
fn upgrade(&self, run_type: RunType, use_sudo: bool) -> Result<()> {
|
||||
fn upgrade(&self, ctx: &ExecutionContext, use_sudo: bool) -> Result<()> {
|
||||
let args = ["update", self.global_location_arg()];
|
||||
if use_sudo {
|
||||
let sudo_option = sudo();
|
||||
let sudo = require_option(sudo_option, String::from("sudo is not installed"))?;
|
||||
run_type.execute(sudo).arg(&self.command).args(args).status_checked()?;
|
||||
let sudo = require_option(ctx.sudo().clone(), String::from("sudo is not installed"))?;
|
||||
ctx.run_type()
|
||||
.execute(sudo)
|
||||
.arg(&self.command)
|
||||
.args(args)
|
||||
.status_checked()?;
|
||||
} else {
|
||||
run_type.execute(&self.command).args(args).status_checked()?;
|
||||
ctx.run_type().execute(&self.command).args(args).status_checked()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -150,17 +151,18 @@ impl Yarn {
|
||||
.map(|s| PathBuf::from(s.stdout.trim()))
|
||||
}
|
||||
|
||||
fn upgrade(&self, run_type: RunType, use_sudo: bool) -> Result<()> {
|
||||
fn upgrade(&self, ctx: &ExecutionContext, use_sudo: bool) -> Result<()> {
|
||||
let args = ["global", "upgrade"];
|
||||
|
||||
if use_sudo {
|
||||
run_type
|
||||
.execute("sudo")
|
||||
let sudo = require_option(ctx.sudo().clone(), String::from("sudo is not installed"))?;
|
||||
ctx.run_type()
|
||||
.execute(sudo)
|
||||
.arg(self.yarn.as_ref().unwrap_or(&self.command))
|
||||
.args(args)
|
||||
.status_checked()?;
|
||||
} else {
|
||||
run_type.execute(&self.command).args(args).status_checked()?;
|
||||
ctx.run_type().execute(&self.command).args(args).status_checked()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -215,12 +217,12 @@ pub fn run_npm_upgrade(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
npm.upgrade(ctx.run_type(), should_use_sudo(&npm, ctx)?)
|
||||
npm.upgrade(ctx, should_use_sudo(&npm, ctx)?)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
npm.upgrade(ctx.run_type(), false)
|
||||
npm.upgrade(ctx, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,12 +233,12 @@ pub fn run_pnpm_upgrade(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
pnpm.upgrade(ctx.run_type(), should_use_sudo(&pnpm, ctx)?)
|
||||
pnpm.upgrade(ctx, should_use_sudo(&pnpm, ctx)?)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
pnpm.upgrade(ctx.run_type(), false)
|
||||
pnpm.upgrade(ctx, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,12 +254,12 @@ pub fn run_yarn_upgrade(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
yarn.upgrade(ctx.run_type(), should_use_sudo_yarn(&yarn, ctx)?)
|
||||
yarn.upgrade(ctx, should_use_sudo_yarn(&yarn, ctx)?)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
yarn.upgrade(ctx.run_type(), false)
|
||||
yarn.upgrade(ctx, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::env::var_os;
|
||||
use std::ffi::OsString;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use color_eyre::eyre;
|
||||
use color_eyre::eyre::Result;
|
||||
@@ -10,6 +9,7 @@ use walkdir::WalkDir;
|
||||
use crate::command::CommandExt;
|
||||
use crate::error::TopgradeError;
|
||||
use crate::execution_context::ExecutionContext;
|
||||
use crate::sudo::Sudo;
|
||||
use crate::utils::which;
|
||||
use crate::{config, Step};
|
||||
|
||||
@@ -31,7 +31,10 @@ pub struct YayParu {
|
||||
impl ArchPackageManager for YayParu {
|
||||
fn upgrade(&self, ctx: &ExecutionContext) -> Result<()> {
|
||||
if ctx.config().show_arch_news() {
|
||||
Command::new(&self.executable).arg("-Pw").status_checked()?;
|
||||
ctx.run_type()
|
||||
.execute(&self.executable)
|
||||
.arg("-Pw")
|
||||
.status_checked_with_codes(&[1, 0])?;
|
||||
}
|
||||
|
||||
let mut command = ctx.run_type().execute(&self.executable);
|
||||
@@ -70,6 +73,27 @@ impl YayParu {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GarudaUpdate {
|
||||
executable: PathBuf,
|
||||
}
|
||||
|
||||
impl ArchPackageManager for GarudaUpdate {
|
||||
fn upgrade(&self, ctx: &ExecutionContext) -> Result<()> {
|
||||
let mut command = ctx.run_type().execute(&self.executable);
|
||||
command.env("PATH", get_execution_path());
|
||||
command.status_checked()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl GarudaUpdate {
|
||||
fn get() -> Option<Self> {
|
||||
Some(Self {
|
||||
executable: which("garuda-update")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Trizen {
|
||||
executable: PathBuf,
|
||||
}
|
||||
@@ -110,7 +134,7 @@ impl Trizen {
|
||||
}
|
||||
|
||||
pub struct Pacman {
|
||||
sudo: PathBuf,
|
||||
sudo: Sudo,
|
||||
executable: PathBuf,
|
||||
}
|
||||
|
||||
@@ -229,7 +253,7 @@ impl ArchPackageManager for Pamac {
|
||||
|
||||
pub struct Aura {
|
||||
executable: PathBuf,
|
||||
sudo: PathBuf,
|
||||
sudo: Sudo,
|
||||
}
|
||||
|
||||
impl Aura {
|
||||
@@ -282,14 +306,16 @@ pub fn get_arch_package_manager(ctx: &ExecutionContext) -> Option<Box<dyn ArchPa
|
||||
let pacman = which("powerpill").unwrap_or_else(|| PathBuf::from("pacman"));
|
||||
|
||||
match ctx.config().arch_package_manager() {
|
||||
config::ArchPackageManager::Autodetect => YayParu::get("paru", &pacman)
|
||||
config::ArchPackageManager::Autodetect => GarudaUpdate::get()
|
||||
.map(box_package_manager)
|
||||
.or_else(|| YayParu::get("paru", &pacman).map(box_package_manager))
|
||||
.or_else(|| YayParu::get("yay", &pacman).map(box_package_manager))
|
||||
.or_else(|| Trizen::get().map(box_package_manager))
|
||||
.or_else(|| Pikaur::get().map(box_package_manager))
|
||||
.or_else(|| Pamac::get().map(box_package_manager))
|
||||
.or_else(|| Pacman::get(ctx).map(box_package_manager))
|
||||
.or_else(|| Aura::get(ctx).map(box_package_manager)),
|
||||
config::ArchPackageManager::GarudaUpdate => GarudaUpdate::get().map(box_package_manager),
|
||||
config::ArchPackageManager::Trizen => Trizen::get().map(box_package_manager),
|
||||
config::ArchPackageManager::Paru => YayParu::get("paru", &pacman).map(box_package_manager),
|
||||
config::ArchPackageManager::Yay => YayParu::get("yay", &pacman).map(box_package_manager),
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use crate::command::CommandExt;
|
||||
use crate::executor::RunType;
|
||||
use crate::sudo::Sudo;
|
||||
use crate::terminal::print_separator;
|
||||
use crate::utils::require_option;
|
||||
use color_eyre::eyre::Result;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
pub fn upgrade_packages(sudo: Option<&PathBuf>, run_type: RunType) -> Result<()> {
|
||||
pub fn upgrade_packages(sudo: Option<&Sudo>, run_type: RunType) -> Result<()> {
|
||||
let sudo = require_option(sudo, String::from("No sudo detected"))?;
|
||||
print_separator("DragonFly BSD Packages");
|
||||
run_type
|
||||
@@ -15,7 +15,7 @@ pub fn upgrade_packages(sudo: Option<&PathBuf>, run_type: RunType) -> Result<()>
|
||||
.status_checked()
|
||||
}
|
||||
|
||||
pub fn audit_packages(sudo: &Option<PathBuf>) -> Result<()> {
|
||||
pub fn audit_packages(sudo: Option<&Sudo>) -> Result<()> {
|
||||
if let Some(sudo) = sudo {
|
||||
println!();
|
||||
Command::new(sudo)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use crate::command::CommandExt;
|
||||
use crate::execution_context::ExecutionContext;
|
||||
use crate::executor::RunType;
|
||||
use crate::sudo::Sudo;
|
||||
use crate::terminal::print_separator;
|
||||
use crate::utils::require_option;
|
||||
use crate::Step;
|
||||
use color_eyre::eyre::Result;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
pub fn upgrade_freebsd(sudo: Option<&PathBuf>, run_type: RunType) -> Result<()> {
|
||||
pub fn upgrade_freebsd(sudo: Option<&Sudo>, run_type: RunType) -> Result<()> {
|
||||
let sudo = require_option(sudo, String::from("No sudo detected"))?;
|
||||
print_separator("FreeBSD Update");
|
||||
run_type
|
||||
@@ -17,7 +17,7 @@ pub fn upgrade_freebsd(sudo: Option<&PathBuf>, run_type: RunType) -> Result<()>
|
||||
.status_checked()
|
||||
}
|
||||
|
||||
pub fn upgrade_packages(ctx: &ExecutionContext, sudo: Option<&PathBuf>, run_type: RunType) -> Result<()> {
|
||||
pub fn upgrade_packages(ctx: &ExecutionContext, sudo: Option<&Sudo>, run_type: RunType) -> Result<()> {
|
||||
let sudo = require_option(sudo, String::from("No sudo detected"))?;
|
||||
print_separator("FreeBSD Packages");
|
||||
|
||||
@@ -30,7 +30,7 @@ pub fn upgrade_packages(ctx: &ExecutionContext, sudo: Option<&PathBuf>, run_type
|
||||
command.status_checked()
|
||||
}
|
||||
|
||||
pub fn audit_packages(sudo: &Option<PathBuf>) -> Result<()> {
|
||||
pub fn audit_packages(sudo: Option<&Sudo>) -> Result<()> {
|
||||
if let Some(sudo) = sudo {
|
||||
println!();
|
||||
Command::new(sudo)
|
||||
|
||||
@@ -10,6 +10,7 @@ use crate::error::{SkipStep, TopgradeError};
|
||||
use crate::execution_context::ExecutionContext;
|
||||
use crate::executor::RunType;
|
||||
use crate::steps::os::archlinux;
|
||||
use crate::sudo::Sudo;
|
||||
use crate::terminal::{print_separator, print_warning};
|
||||
use crate::utils::{require, require_option, which, PathExt};
|
||||
use crate::Step;
|
||||
@@ -498,7 +499,7 @@ fn upgrade_neon(ctx: &ExecutionContext) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_needrestart(sudo: Option<&PathBuf>, run_type: RunType) -> Result<()> {
|
||||
pub fn run_needrestart(sudo: Option<&Sudo>, run_type: RunType) -> Result<()> {
|
||||
let sudo = require_option(sudo, String::from("sudo is not installed"))?;
|
||||
let needrestart = require("needrestart")?;
|
||||
let distribution = Distribution::detect()?;
|
||||
@@ -603,7 +604,7 @@ pub fn flatpak_update(ctx: &ExecutionContext) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_snap(sudo: Option<&PathBuf>, run_type: RunType) -> Result<()> {
|
||||
pub fn run_snap(sudo: Option<&Sudo>, run_type: RunType) -> Result<()> {
|
||||
let sudo = require_option(sudo, String::from("sudo is not installed"))?;
|
||||
let snap = require("snap")?;
|
||||
|
||||
@@ -615,7 +616,7 @@ pub fn run_snap(sudo: Option<&PathBuf>, run_type: RunType) -> Result<()> {
|
||||
run_type.execute(sudo).arg(snap).arg("refresh").status_checked()
|
||||
}
|
||||
|
||||
pub fn run_pihole_update(sudo: Option<&PathBuf>, run_type: RunType) -> Result<()> {
|
||||
pub fn run_pihole_update(sudo: Option<&Sudo>, run_type: RunType) -> Result<()> {
|
||||
let sudo = require_option(sudo, String::from("sudo is not installed"))?;
|
||||
let pihole = require("pihole")?;
|
||||
Path::new("/opt/pihole/update.sh").require()?;
|
||||
|
||||
@@ -19,17 +19,16 @@ pub fn run_chocolatey(ctx: &ExecutionContext) -> Result<()> {
|
||||
|
||||
print_separator("Chocolatey");
|
||||
|
||||
let mut cmd = &choco;
|
||||
let mut args = vec!["upgrade", "all"];
|
||||
let mut command = match ctx.sudo() {
|
||||
Some(sudo) => {
|
||||
let mut command = ctx.run_type().execute(sudo);
|
||||
command.arg(choco);
|
||||
command
|
||||
}
|
||||
None => ctx.run_type().execute(choco),
|
||||
};
|
||||
|
||||
if let Some(sudo) = ctx.sudo() {
|
||||
cmd = sudo;
|
||||
args.insert(0, "choco");
|
||||
}
|
||||
|
||||
let mut command = ctx.run_type().execute(cmd);
|
||||
|
||||
command.args(&args);
|
||||
command.args(["upgrade", "all"]);
|
||||
|
||||
if yes {
|
||||
command.arg("--yes");
|
||||
|
||||
108
src/sudo.rs
Normal file
108
src/sudo.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use color_eyre::eyre::Context;
|
||||
use color_eyre::eyre::Result;
|
||||
|
||||
use crate::command::CommandExt;
|
||||
use crate::execution_context::ExecutionContext;
|
||||
use crate::executor::Executor;
|
||||
use crate::terminal::print_separator;
|
||||
use crate::utils::which;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Sudo {
|
||||
/// The path to the `sudo` binary.
|
||||
path: PathBuf,
|
||||
/// The type of program being used as `sudo`.
|
||||
kind: SudoKind,
|
||||
}
|
||||
|
||||
impl Sudo {
|
||||
/// Get the `sudo` binary for this platform.
|
||||
pub fn detect() -> Option<Self> {
|
||||
which("doas")
|
||||
.map(|p| (p, SudoKind::Doas))
|
||||
.or_else(|| which("sudo").map(|p| (p, SudoKind::Sudo)))
|
||||
.or_else(|| which("gsudo").map(|p| (p, SudoKind::Gsudo)))
|
||||
.or_else(|| which("pkexec").map(|p| (p, SudoKind::Pkexec)))
|
||||
.map(|(path, kind)| Self { path, kind })
|
||||
}
|
||||
|
||||
/// Elevate permissions with `sudo`.
|
||||
///
|
||||
/// This helps prevent blocking `sudo` prompts from stopping the run in the middle of a
|
||||
/// step.
|
||||
///
|
||||
/// See: https://github.com/topgrade-rs/topgrade/issues/205
|
||||
pub fn elevate(&self, ctx: &ExecutionContext) -> Result<()> {
|
||||
print_separator("Sudo");
|
||||
let mut cmd = ctx.run_type().execute(self);
|
||||
match self.kind {
|
||||
SudoKind::Doas => {
|
||||
// `doas` doesn't have anything like `sudo -v` to cache credentials,
|
||||
// so we just execute a dummy `echo` command so we have something
|
||||
// unobtrusive to run.
|
||||
// See: https://man.openbsd.org/doas
|
||||
cmd.arg("echo");
|
||||
}
|
||||
SudoKind::Sudo => {
|
||||
// From `man sudo` on macOS:
|
||||
// -v, --validate
|
||||
// Update the user's cached credentials, authenticating the user
|
||||
// if necessary. For the sudoers plugin, this extends the sudo
|
||||
// timeout for another 5 minutes by default, but does not run a
|
||||
// command. Not all security policies support cached credentials.
|
||||
cmd.arg("-v");
|
||||
}
|
||||
SudoKind::Gsudo => {
|
||||
// Shows current user, cache and console status.
|
||||
// See: https://gerardog.github.io/gsudo/docs/usage
|
||||
cmd.arg("status");
|
||||
}
|
||||
SudoKind::Pkexec => {
|
||||
// I don't think this does anything; `pkexec` usually asks for
|
||||
// authentication every time, although it can be configured
|
||||
// differently.
|
||||
//
|
||||
// See the note for `doas` above.
|
||||
//
|
||||
// See: https://linux.die.net/man/1/pkexec
|
||||
cmd.arg("echo");
|
||||
}
|
||||
}
|
||||
cmd.status_checked().wrap_err("Failed to elevate permissions")
|
||||
}
|
||||
|
||||
/// Execute a command with `sudo`.
|
||||
pub fn execute_elevated(&self, ctx: &ExecutionContext, command: &Path, interactive: bool) -> Executor {
|
||||
let mut cmd = ctx.run_type().execute(self);
|
||||
|
||||
if let SudoKind::Sudo = self.kind {
|
||||
cmd.arg("--preserve-env=DIFFPROG");
|
||||
}
|
||||
|
||||
if interactive {
|
||||
cmd.arg("-i");
|
||||
}
|
||||
|
||||
cmd.arg(command);
|
||||
|
||||
cmd
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum SudoKind {
|
||||
Doas,
|
||||
Sudo,
|
||||
Gsudo,
|
||||
Pkexec,
|
||||
}
|
||||
|
||||
impl AsRef<OsStr> for Sudo {
|
||||
fn as_ref(&self) -> &OsStr {
|
||||
self.path.as_ref()
|
||||
}
|
||||
}
|
||||
@@ -67,13 +67,6 @@ pub fn which<T: AsRef<OsStr> + Debug>(binary_name: T) -> Option<PathBuf> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sudo() -> Option<PathBuf> {
|
||||
which("doas")
|
||||
.or_else(|| which("sudo"))
|
||||
.or_else(|| which("gsudo"))
|
||||
.or_else(|| which("pkexec"))
|
||||
}
|
||||
|
||||
pub fn editor() -> Vec<String> {
|
||||
env::var("EDITOR")
|
||||
.unwrap_or_else(|_| String::from(if cfg!(windows) { "notepad" } else { "vi" }))
|
||||
|
||||
80
topgrade.8
80
topgrade.8
@@ -1,80 +0,0 @@
|
||||
.hy
|
||||
.TH "topgrade" "8"
|
||||
.SH NAME
|
||||
.PP
|
||||
Topgrade \- Upgrade everything
|
||||
.SH SYNOPSIS
|
||||
.PP
|
||||
topgrade [\fIoptions\f[]]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
Keeping your system up to date usually involves invoking multiple package managers.
|
||||
This results in big, non-portable shell one-liners saved in your shell.
|
||||
To remedy this, \fBTopgrade\fR detects which tools you use and runs the appropriate commands to update them.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-\-only <only>
|
||||
Run only specific steps
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-disable <disable>
|
||||
Disable specific steps
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-c, \-\-cleanup
|
||||
Cleanup temporary or old files
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-n, \-\-dry\-run
|
||||
List the commands that would be run
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-edit\-config
|
||||
Edit the configuration file
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-h, \-\-help
|
||||
Print help information
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-k, \-\-keep
|
||||
Prompt for a key before exiting
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-no\-retry
|
||||
Do not ask to retry failed steps
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-t, \-\-tmux
|
||||
Run inside tmux
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-V, \-\-version
|
||||
Print version information
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-v, \-\-verbose
|
||||
Output logs
|
||||
.RS
|
||||
.RE
|
||||
.B \-y, \-\-yes
|
||||
Skip package manager's prompts (experimental)
|
||||
.SH ARGUMENT FORMAT
|
||||
Options can be given in any order.
|
||||
A list of steps must be provided as a list of separate arguments, i.e. 'topgrade --only system shell'.
|
||||
.SH BUGS
|
||||
For a list of bugs see <\fIhttps://github.com/r-darwish/topgrade/issues\fR>.
|
||||
.SH AUTHOR
|
||||
\fBTopgrade\fR is maintained by Roey Dror (\[aq]r\-darwish\[aq]) and many other contributors.
|
||||
You can view the full list at
|
||||
<\fIhttps://github.com/r-darwish/topgrade/graphs/contributors\fR>
|
||||
Reference in New Issue
Block a user