From c4ef712b3bc178b6881d502742c6ca0ff867e1f4 Mon Sep 17 00:00:00 2001 From: Roey Darwish Dror Date: Thu, 12 Dec 2019 20:24:22 +0200 Subject: [PATCH] TeX live manager (fix #223) (#251) --- Cargo.lock | 1 + Cargo.toml | 1 + src/config.rs | 1 + src/error.rs | 3 +++ src/main.rs | 19 ++++++++++++++++++- src/steps/generic.rs | 39 ++++++++++++++++++++++++++++++++++++++- src/utils.rs | 2 +- 7 files changed, 63 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7048103f..aca5436d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1872,6 +1872,7 @@ dependencies = [ "shellexpand 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "strum 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-process 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 63ea7edd..13fd7acb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ glob = "0.3.0" strum = { version = "0.16.0", features = ["derive"]} thiserror = "1.0.9" anyhow = "1.0.25" +tempfile = "3.1.0" [target.'cfg(unix)'.dependencies] nix = "0.15.0" diff --git a/src/config.rs b/src/config.rs index 9357d62e..78f433a7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -38,6 +38,7 @@ pub enum Step { Vcpkg, Pipx, Stack, + Tlmgr, Myrepos, Pearl, Jetpack, diff --git a/src/error.rs b/src/error.rs index 1c2325cd..76c4e4fb 100644 --- a/src/error.rs +++ b/src/error.rs @@ -6,6 +6,9 @@ pub enum TopgradeError { #[error("{0}")] ProcessFailed(ExitStatus), + #[error("Sudo is required for this step")] + SudoRequired, + #[error("Unknown Linux Distribution")] #[cfg(target_os = "linux")] UnknownLinuxDistribution, diff --git a/src/main.rs b/src/main.rs index 312976e5..c23f4252 100644 --- a/src/main.rs +++ b/src/main.rs @@ -90,7 +90,7 @@ fn run() -> Result<()> { let mut report = Report::new(); - #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] + #[cfg(unix)] let sudo = utils::sudo(); let run_type = executor::RunType::new(config.dry_run()); @@ -411,6 +411,23 @@ fn run() -> Result<()> { )?; } + if config.should_run(Step::Tlmgr) { + execute( + &mut report, + "tlmgr", + || { + generic::run_tlmgr_update( + #[cfg(unix)] + &sudo, + #[cfg(windows)] + &None, + run_type, + ) + }, + config.no_retry(), + )?; + } + if config.should_run(Step::Myrepos) { execute( &mut report, diff --git a/src/steps/generic.rs b/src/steps/generic.rs index d37da8ad..7187daae 100644 --- a/src/steps/generic.rs +++ b/src/steps/generic.rs @@ -1,12 +1,14 @@ -use crate::error::SkipStep; +use crate::error::{SkipStep, TopgradeError}; use crate::executor::{CommandExt, RunType}; use crate::terminal::{print_separator, shell}; use crate::utils::{self, PathExt}; use anyhow::Result; use directories::BaseDirs; +use log::debug; use std::env; use std::path::PathBuf; use std::process::Command; +use tempfile::tempfile_in; pub fn run_cargo_update(run_type: RunType) -> Result<()> { let cargo_update = utils::require("cargo-install-update")?; @@ -109,6 +111,41 @@ pub fn run_stack_update(run_type: RunType) -> Result<()> { run_type.execute(&stack).arg("upgrade").check_run() } +pub fn run_tlmgr_update(sudo: &Option, run_type: RunType) -> Result<()> { + let tlmgr = utils::require("tlmgr")?; + let kpsewhich = utils::require("kpsewhich")?; + let tlmgr_directory = { + let mut d = PathBuf::from( + std::str::from_utf8( + &Command::new(&kpsewhich) + .arg("-var-value=SELFAUTOPARENT") + .output()? + .stdout, + )? + .trim(), + ); + d.push("tlpkg"); + d + } + .require()?; + + let directory_writable = tempfile_in(&tlmgr_directory).is_ok(); + debug!("{:?} writable: {}", tlmgr_directory, directory_writable); + + print_separator("TeX Live package manager"); + + let mut command = if directory_writable { + run_type.execute(&tlmgr) + } else { + let mut c = run_type.execute(sudo.as_ref().ok_or(TopgradeError::SudoRequired)?); + c.arg(&tlmgr); + c + }; + command.args(&["update", "--self", "--all"]); + + command.check_run() +} + pub fn run_myrepos_update(base_dirs: &BaseDirs, run_type: RunType) -> Result<()> { let myrepos = utils::require("mr")?; base_dirs.home_dir().join(".mrconfig").require()?; diff --git a/src/utils.rs b/src/utils.rs index da5a2d09..260b1d45 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -88,7 +88,7 @@ pub fn which + Debug>(binary_name: T) -> Option { } } -#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] +#[cfg(unix)] pub fn sudo() -> Option { which("sudo").or_else(|| which("pkexec")) }