Add pre_sudo option (#219)

* Add `pre_sudo` option
This commit is contained in:
Rebecca Turner
2022-11-24 14:15:43 -05:00
committed by GitHub
parent f2c7e4848e
commit e456155562
6 changed files with 54 additions and 9 deletions

View File

@@ -13,6 +13,10 @@
# Do not ask to retry failed steps (default: false) # Do not ask to retry failed steps (default: false)
#no_retry = true #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 inside tmux
#run_in_tmux = true #run_in_tmux = true

View File

@@ -269,6 +269,7 @@ pub struct Vim {
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
/// Configuration file /// Configuration file
pub struct ConfigFile { pub struct ConfigFile {
pre_sudo: Option<bool>,
pre_commands: Option<Commands>, pre_commands: Option<Commands>,
post_commands: Option<Commands>, post_commands: Option<Commands>,
commands: Option<Commands>, commands: Option<Commands>,
@@ -947,6 +948,12 @@ impl Config {
.unwrap_or(false) .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")] #[cfg(target_os = "linux")]
pub fn npm_use_sudo(&self) -> bool { pub fn npm_use_sudo(&self) -> bool {
self.config_file self.config_file

View File

@@ -30,6 +30,7 @@ mod self_renamer;
#[cfg(feature = "self-update")] #[cfg(feature = "self-update")]
mod self_update; mod self_update;
mod steps; mod steps;
mod sudo;
mod terminal; mod terminal;
mod utils; mod utils;
@@ -82,7 +83,7 @@ fn run() -> Result<()> {
let git = git::Git::new(); let git = git::Git::new();
let mut git_repos = git::Repositories::new(&git); let mut git_repos = git::Repositories::new(&git);
let sudo = utils::sudo(); let sudo = sudo::path();
let run_type = executor::RunType::new(config.dry_run()); 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);
@@ -119,6 +120,10 @@ fn run() -> Result<()> {
} }
} }
if config.pre_sudo() {
sudo::elevate(&ctx, sudo.as_ref())?;
}
let powershell = powershell::Powershell::new(); let powershell = powershell::Powershell::new();
let should_run_powershell = powershell.profile().is_some() && config.should_run(Step::Powershell); let should_run_powershell = powershell.profile().is_some() && config.should_run(Step::Powershell);

View File

@@ -4,6 +4,8 @@ use std::os::unix::fs::MetadataExt;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use crate::sudo;
use crate::utils::require_option; use crate::utils::require_option;
use color_eyre::eyre::Result; use color_eyre::eyre::Result;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
@@ -93,7 +95,7 @@ impl NPM {
fn upgrade(&self, run_type: RunType, use_sudo: bool) -> Result<()> { fn upgrade(&self, run_type: RunType, use_sudo: bool) -> Result<()> {
let args = ["update", self.global_location_arg()]; let args = ["update", self.global_location_arg()];
if use_sudo { if use_sudo {
let sudo_option = sudo(); let sudo_option = sudo::path();
let sudo = require_option(sudo_option, String::from("sudo is not installed"))?; let sudo = require_option(sudo_option, String::from("sudo is not installed"))?;
run_type.execute(sudo).arg(&self.command).args(args).status_checked()?; run_type.execute(sudo).arg(&self.command).args(args).status_checked()?;
} else { } else {

34
src/sudo.rs Normal file
View File

@@ -0,0 +1,34 @@
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::terminal::print_separator;
use crate::utils::which;
/// Get the path of the `sudo` utility.
///
/// Detects `doas`, `sudo`, `gsudo`, or `pkexec`.
pub fn path() -> Option<PathBuf> {
which("doas")
.or_else(|| which("sudo"))
.or_else(|| which("gsudo"))
.or_else(|| which("pkexec"))
}
/// Elevate permissions with `sudo`.
pub fn elevate(ctx: &ExecutionContext, sudo: Option<&PathBuf>) -> Result<()> {
if let Some(sudo) = sudo {
print_separator("Sudo");
ctx.run_type()
.execute(sudo)
// TODO: Does this work with `doas`, `pkexec`, `gsudo`, GNU `sudo`...?
.arg("-v")
.status_checked()
.wrap_err("Failed to elevate permissions")?;
}
Ok(())
}

View File

@@ -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> { pub fn editor() -> Vec<String> {
env::var("EDITOR") env::var("EDITOR")
.unwrap_or_else(|_| String::from(if cfg!(windows) { "notepad" } else { "vi" })) .unwrap_or_else(|_| String::from(if cfg!(windows) { "notepad" } else { "vi" }))