From da8cf9da05cf9faa43ab09ca9672fecce8053d23 Mon Sep 17 00:00:00 2001 From: Funky185540 Date: Mon, 24 Jan 2022 11:10:21 +0100 Subject: [PATCH] Enable updating Toolbx through topgrade (#830) * steps: toolbox: Add module to upgrade toolboxes This adds a module to upgrade all toolboxes found on a host system. [Toolbox][1] (More recently: `toolbx`) is a tool that easily provides mutable, containerized command line environments. It is a means to work and develop in a mutable environment on immutable operating systems such as Fedora Silverblue, CoreOS, Kinoite and much more. However, it is not limited to these use cases. The integration into topgrade works as follows: Toolbx makes many of the hosts folders available form inside the toolbx container by default. In particular, all of the hosts filesystem is mapped under `/run/host`. This module exploits this fact by: - Gathering a list of toolboxes available on the host that runs `topgrade` - Executing `toolbox run` for each of these toolboxes to run a command inside the toolboxes, **using the executing `topgrade` executable with the `--only system` arguments** [1]: https://containertoolbx.org/ * toolbx: Integrate toolbx into the application * Toolbx is Linux specific Co-authored-by: Roey Darwish Dror --- src/config.rs | 1 + src/main.rs | 1 + src/steps/mod.rs | 2 ++ src/steps/toolbx.rs | 61 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 src/steps/toolbx.rs diff --git a/src/config.rs b/src/config.rs index 42940621..9afec0b1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -126,6 +126,7 @@ pub enum Step { Tldr, Tlmgr, Tmux, + Toolbx, Vagrant, Vcpkg, Vim, diff --git a/src/main.rs b/src/main.rs index aa30c624..c8bc5d17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -329,6 +329,7 @@ fn run() -> Result<()> { #[cfg(target_os = "linux")] { + 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::Pacstall, "pacstall", || linux::run_pacstall(&ctx))?; diff --git a/src/steps/mod.rs b/src/steps/mod.rs index 1c3cf5cb..96801ae5 100644 --- a/src/steps/mod.rs +++ b/src/steps/mod.rs @@ -7,6 +7,8 @@ pub mod powershell; pub mod remote; #[cfg(unix)] pub mod tmux; +#[cfg(target_os = "linux")] +pub mod toolbx; pub mod vim; #[cfg(unix)] pub mod zsh; diff --git a/src/steps/toolbx.rs b/src/steps/toolbx.rs new file mode 100644 index 00000000..c4eafe17 --- /dev/null +++ b/src/steps/toolbx.rs @@ -0,0 +1,61 @@ +use anyhow::Result; + +use crate::config::Step; +use crate::terminal::print_separator; +use crate::{execution_context::ExecutionContext, utils::require}; +use log::debug; +use std::path::Path; +use std::{path::PathBuf, process::Command}; + +fn list_toolboxes(toolbx: &Path) -> Result> { + let output = Command::new(toolbx).args(&["list", "--containers"]).output()?; + let output_str = String::from_utf8(output.stdout)?; + + let proc: Vec = output_str + .lines() + // Skip the first line since that contains only status information + .skip(1) + .map(|line| match line.split_whitespace().nth(1) { + Some(word) => word.to_string(), + None => String::from(""), + }) + .filter(|x| !x.is_empty()) + .collect(); + + Ok(proc) +} + +pub fn run_toolbx(ctx: &ExecutionContext) -> Result<()> { + let toolbx = require("toolbox")?; + + print_separator("Toolbx"); + let toolboxes = list_toolboxes(&toolbx)?; + debug!("Toolboxes to inspect: {:?}", toolboxes); + + let mut topgrade_path = PathBuf::from("/run/host"); + // Path of the running topgrade executable + // Skip 1 to eliminate the path root, otherwise push overwrites the path + topgrade_path.push(std::env::current_exe()?.components().skip(1).collect::()); + let topgrade_path = topgrade_path.to_str().unwrap(); + + for tb in toolboxes.iter() { + let topgrade_prefix = format!("TOPGRADE_PREFIX='Toolbx {}'", tb); + let mut args = vec![ + "run", + "-c", + tb, + "env", + &topgrade_prefix, + topgrade_path, + "--only", + "system", + ]; + if ctx.config().yes(Step::Toolbx) { + args.push("--yes"); + } + + let _output = ctx.run_type().execute(&toolbx).args(&args).check_run(); + } + + Ok(()) +}