diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index 1cf66ce..e639774 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -402,18 +402,6 @@ jobs: - uses: sigstore/cosign-installer@v3.3.0 - - name: Setup Podman - shell: bash - run: | - # from https://askubuntu.com/questions/1414446/whats-the-recommended-way-of-installing-podman-4-in-ubuntu-22-04 - ubuntu_version='22.04' - key_url="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/Release.key" - sources_url="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}" - echo "deb $sources_url/ /" | sudo tee /etc/apt/sources.list.d/devel-kubic-libcontainers-unstable.list - curl -fsSL $key_url | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/devel_kubic_libcontainers_unstable.gpg > /dev/null - sudo apt-get update - sudo apt-get install -y podman - - uses: actions-rust-lang/setup-rust-toolchain@v1 - uses: actions/checkout@v4 @@ -446,18 +434,6 @@ jobs: - uses: sigstore/cosign-installer@v3.3.0 - - name: Setup Buildah - shell: bash - run: | - # from https://askubuntu.com/questions/1414446/whats-the-recommended-way-of-installing-podman-4-in-ubuntu-22-04 - ubuntu_version='22.04' - key_url="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/Release.key" - sources_url="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}" - echo "deb $sources_url/ /" | sudo tee /etc/apt/sources.list.d/devel-kubic-libcontainers-unstable.list - curl -fsSL $key_url | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/devel_kubic_libcontainers_unstable.gpg > /dev/null - sudo apt-get update - sudo apt-get install -y buildah - - uses: actions-rust-lang/setup-rust-toolchain@v1 - uses: actions/checkout@v4 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dc7ee52..4115d80 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -507,18 +507,6 @@ jobs: - uses: sigstore/cosign-installer@v3.3.0 - - name: Setup Podman - shell: bash - run: | - # from https://askubuntu.com/questions/1414446/whats-the-recommended-way-of-installing-podman-4-in-ubuntu-22-04 - ubuntu_version='22.04' - key_url="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/Release.key" - sources_url="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}" - echo "deb $sources_url/ /" | sudo tee /etc/apt/sources.list.d/devel-kubic-libcontainers-unstable.list - curl -fsSL $key_url | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/devel_kubic_libcontainers_unstable.gpg > /dev/null - sudo apt-get update - sudo apt-get install -y podman - - uses: actions-rust-lang/setup-rust-toolchain@v1 # Setup repo and add caching @@ -554,18 +542,6 @@ jobs: - uses: sigstore/cosign-installer@v3.3.0 - - name: Setup Podman - shell: bash - run: | - # from https://askubuntu.com/questions/1414446/whats-the-recommended-way-of-installing-podman-4-in-ubuntu-22-04 - ubuntu_version='22.04' - key_url="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/Release.key" - sources_url="https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}" - echo "deb $sources_url/ /" | sudo tee /etc/apt/sources.list.d/devel-kubic-libcontainers-unstable.list - curl -fsSL $key_url | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/devel_kubic_libcontainers_unstable.gpg > /dev/null - sudo apt-get update - sudo apt-get install -y buildah - - uses: actions-rust-lang/setup-rust-toolchain@v1 # Setup repo and add caching diff --git a/Cargo.lock b/Cargo.lock index 43c8d10..58a524c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -364,6 +364,7 @@ dependencies = [ "clap_complete", "clap_complete_nushell", "colored", + "comlexr", "fuzzy-matcher", "indexmap 2.7.0", "indicatif", @@ -404,6 +405,7 @@ dependencies = [ "chrono", "clap", "colored", + "comlexr", "indexmap 2.7.0", "indicatif", "indicatif-log-bridge", @@ -472,6 +474,7 @@ dependencies = [ "bon", "chrono", "clap", + "comlexr", "directories", "docker_credential", "format_serde_error", @@ -488,9 +491,9 @@ dependencies = [ [[package]] name = "bon" -version = "2.3.0" +version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97493a391b4b18ee918675fb8663e53646fd09321c58b46afa04e8ce2499c869" +checksum = "fe7acc34ff59877422326db7d6f2d845a582b16396b6b08194942bf34c6528ab" dependencies = [ "bon-macros", "rustversion", @@ -498,14 +501,16 @@ dependencies = [ [[package]] name = "bon-macros" -version = "2.3.0" +version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2af3eac944c12cdf4423eab70d310da0a8e5851a18ffb192c0a5e3f7ae1663" +checksum = "4159dd617a7fbc9be6a692fe69dc2954f8e6bb6bb5e4d7578467441390d77fd0" dependencies = [ "darling", "ident_case", + "prettyplease", "proc-macro2", "quote", + "rustversion", "syn 2.0.89", ] @@ -753,6 +758,17 @@ dependencies = [ "memchr", ] +[[package]] +name = "comlexr" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab00d94d115dea65c19267edbaa5d1b63f0da13dbaa254f3d2e35b340383005" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.89", +] + [[package]] name = "console" version = "0.15.8" diff --git a/Cargo.toml b/Cargo.toml index 43a7b25..51ea778 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,11 +10,12 @@ categories = ["command-line-utilities"] version = "0.9.2" [workspace.dependencies] -bon = "2" +bon = "3" cached = "0.53" chrono = "0.4" clap = "4" colored = "2" +comlexr = "1" indexmap = { version = "2", features = ["serde"] } indicatif = { version = "0.17", features = ["improved_unicode"] } log = "0.4" @@ -84,6 +85,7 @@ yaml-rust2 = { version = "0.9", optional = true } cached.workspace = true clap = { workspace = true, features = ["derive", "cargo", "unicode", "env"] } colored.workspace = true +comlexr.workspace = true indexmap.workspace = true indicatif.workspace = true log.workspace = true diff --git a/process/Cargo.toml b/process/Cargo.toml index e573f8d..ab5ad3b 100644 --- a/process/Cargo.toml +++ b/process/Cargo.toml @@ -28,6 +28,7 @@ cached.workspace = true chrono.workspace = true clap = { workspace = true, features = ["derive", "env"] } colored.workspace = true +comlexr.workspace = true indicatif.workspace = true indexmap.workspace = true log.workspace = true diff --git a/process/drivers/buildah_driver.rs b/process/drivers/buildah_driver.rs index 73c4b5d..8d6a4f8 100644 --- a/process/drivers/buildah_driver.rs +++ b/process/drivers/buildah_driver.rs @@ -1,7 +1,8 @@ use std::{io::Write, process::Stdio}; -use blue_build_utils::{cmd, credentials::Credentials}; +use blue_build_utils::credentials::Credentials; use colored::Colorize; +use comlexr::cmd; use log::{debug, error, info, trace}; use miette::{bail, miette, IntoDiagnostic, Result}; use semver::Version; diff --git a/process/drivers/cosign_driver.rs b/process/drivers/cosign_driver.rs index 6b619ad..a837e0e 100644 --- a/process/drivers/cosign_driver.rs +++ b/process/drivers/cosign_driver.rs @@ -1,11 +1,11 @@ use std::{fmt::Debug, fs, io::Write, path::Path, process::Stdio}; use blue_build_utils::{ - cmd, constants::{COSIGN_PASSWORD, COSIGN_PUB_PATH, COSIGN_YES}, credentials::Credentials, }; use colored::Colorize; +use comlexr::cmd; use log::{debug, trace}; use miette::{bail, miette, Context, IntoDiagnostic, Result}; @@ -27,10 +27,13 @@ impl SigningDriver for CosignDriver { let mut command = cmd!( "cosign", "generate-key-pair", - COSIGN_PASSWORD => "", - COSIGN_YES => "true", + // COSIGN_PASSWORD => "", + // COSIGN_YES => "true", ); - command.current_dir(path); + command + .current_dir(path) + .env(COSIGN_PASSWORD, "") + .env(COSIGN_YES, "true"); let status = command.status().into_diagnostic()?; @@ -49,9 +52,10 @@ impl SigningDriver for CosignDriver { "cosign", "public-key", format!("--key={priv_key}"), - COSIGN_PASSWORD => "", - COSIGN_YES => "true", + // COSIGN_PASSWORD => "", + // COSIGN_YES => "true", ); + command.env(COSIGN_PASSWORD, "").env(COSIGN_YES, "true"); trace!("{command:?}"); let output = command.output().into_diagnostic()?; @@ -93,10 +97,11 @@ impl SigningDriver for CosignDriver { username, "--password-stdin", registry, - stdin = Stdio::piped(), - stdout = Stdio::piped(), - stderr = Stdio::piped(), ); + command + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); trace!("{command:?}"); let mut child = command.spawn().into_diagnostic()?; @@ -135,9 +140,10 @@ impl SigningDriver for CosignDriver { if let Some(ref key) = opts.key => format!("--key={key}"), "--recursive", opts.image.to_string(), - COSIGN_PASSWORD => "", - COSIGN_YES => "true", + // COSIGN_PASSWORD => "", + // COSIGN_YES => "true", ); + command.env(COSIGN_PASSWORD, "").env(COSIGN_YES, "true"); trace!("{command:?}"); if !command.status().into_diagnostic()?.success() { @@ -151,17 +157,14 @@ impl SigningDriver for CosignDriver { let mut command = cmd!( "cosign", "verify", - |c| { - match &opts.verify_type { - VerifyType::File(path) => cmd!(c, format!("--key={}", path.display())), - VerifyType::Keyless { issuer, identity } => cmd!( - c, - "--certificate-identity-regexp", - identity as &str, - "--certificate-oidc-issuer", - issuer as &str, - ), - }; + match &opts.verify_type { + VerifyType::File(path) => format!("--key={}", path.display()), + VerifyType::Keyless { issuer, identity } => [ + "--certificate-identity-regexp", + &**identity, + "--certificate-oidc-issuer", + &**issuer, + ], }, opts.image.to_string(), ); diff --git a/process/drivers/docker_driver.rs b/process/drivers/docker_driver.rs index 507baf0..7e4af78 100644 --- a/process/drivers/docker_driver.rs +++ b/process/drivers/docker_driver.rs @@ -7,13 +7,13 @@ use std::{ }; use blue_build_utils::{ - cmd, constants::{BB_BUILDKIT_CACHE_GHA, CONTAINER_FILE, DOCKER_HOST, GITHUB_ACTIONS}, credentials::Credentials, string_vec, }; use cached::proc_macro::cached; use colored::Colorize; +use comlexr::cmd; use log::{debug, info, trace, warn}; use miette::{bail, miette, IntoDiagnostic, Result}; use once_cell::sync::Lazy; @@ -204,10 +204,11 @@ impl BuildDriver for DockerDriver { username, "--password-stdin", registry, - stdin = Stdio::piped(), - stdout = Stdio::piped(), - stderr = Stdio::piped(), ); + command + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()); trace!("{command:?}"); let mut child = command.spawn().into_diagnostic()?; @@ -253,17 +254,18 @@ impl BuildDriver for DockerDriver { }); let buildx = scope.spawn(|| { + let run_setup = !env::var(DOCKER_HOST).is_ok_and(|dh| !dh.is_empty()); + + if run_setup { + Self::setup()?; + } + cmd!( "docker", "buildx", "prune", "--force", - |command|? { - if !env::var(DOCKER_HOST).is_ok_and(|dh| !dh.is_empty()) { - Self::setup()?; - cmd!(command, "--builder=bluebuild"); - } - }, + if run_setup => "--builder=bluebuild", if opts.all => "--all", ) .message_status("docker buildx prune", "Pruning Docker Buildx") @@ -293,16 +295,58 @@ impl BuildDriver for DockerDriver { warn!("Squash is deprecated for docker so this build will not squash"); } - let mut command = cmd!( + let run_setup = !env::var(DOCKER_HOST).is_ok_and(|dh| !dh.is_empty()); + + if run_setup { + Self::setup()?; + } + + let final_images = match (opts.image, opts.archive_path.as_deref()) { + (Some(image), None) => { + let images = if opts.tags.is_empty() { + let image = image.to_string(); + string_vec![image] + } else { + opts.tags + .iter() + .map(|tag| { + format!("{}/{}:{tag}", image.resolve_registry(), image.repository()) + }) + .collect() + }; + + images + } + (None, Some(archive_path)) => { + string_vec![archive_path.display().to_string()] + } + (Some(_), Some(_)) => bail!("Cannot use both image and archive path"), + (None, None) => bail!("Need either the image or archive path set"), + }; + + let first_image = final_images.first().unwrap(); + + let command = cmd!( "docker", "buildx", - |command|? { - if !env::var(DOCKER_HOST).is_ok_and(|dh| !dh.is_empty()) { - Self::setup()?; - cmd!(command, "--builder=bluebuild"); - } - }, + if run_setup => "--builder=bluebuild", "build", + ".", + match (opts.image, opts.archive_path.as_deref()) { + (Some(_), None) if opts.push => [ + "--output", + format!( + "type=image,name={first_image},push=true,compression={},oci-mediatypes=true", + opts.compression + ), + ], + (Some(_), None) if env::var(GITHUB_ACTIONS).is_err() => "--load", + (None, Some(archive_path)) => [ + "--output", + format!("type=oci,dest={}", archive_path.display()), + ], + _ => [], + }, "--pull", if !matches!(opts.platform, Platform::Native) => [ "--platform", @@ -320,73 +364,19 @@ impl BuildDriver for DockerDriver { ], ); - let final_images = match (opts.image, opts.archive_path.as_deref()) { - (Some(image), None) => { - let images = if opts.tags.is_empty() { - let image = image.to_string(); - cmd!(command, "-t", &image); - string_vec![image] - } else { - opts.tags.iter().for_each(|tag| { - cmd!( - command, - "-t", - format!("{}/{}:{tag}", image.resolve_registry(), image.repository()) - ); - }); - opts.tags - .iter() - .map(|tag| { - format!("{}/{}:{tag}", image.resolve_registry(), image.repository()) - }) - .collect() - }; - let first_image = images.first().unwrap(); - - if opts.push { - cmd!( - command, - "--output", - format!( - "type=image,name={first_image},push=true,compression={},oci-mediatypes=true", - opts.compression - ), - ); - - // We don't want to load the image into docker as it will double disk usage - } else if env::var(GITHUB_ACTIONS).is_err() { - cmd!(command, "--load"); - } - images - } - (None, Some(archive_path)) => { - cmd!( - command, - "--output", - format!("type=oci,dest={}", archive_path.display()) - ); - string_vec![archive_path.display().to_string()] - } - (Some(_), Some(_)) => bail!("Cannot use both image and archive path"), - (None, None) => bail!("Need either the image or archive path set"), - }; - let display_image = final_images.first().unwrap(); // There will always be at least one image - - cmd!(command, "."); - trace!("{command:?}"); if command - .build_status(display_image, "Building Image") + .build_status(first_image, "Building Image") .into_diagnostic()? .success() { if opts.push { - info!("Successfully built and pushed image {}", display_image); + info!("Successfully built and pushed image {}", first_image); } else { - info!("Successfully built image {}", display_image); + info!("Successfully built image {}", first_image); } } else { - bail!("Failed to build image {}", display_image); + bail!("Failed to build image {}", first_image); } Ok(final_images) } @@ -408,15 +398,16 @@ fn get_metadata_cache(opts: &GetMetadataOpts) -> Result { trace!("DockerDriver::get_metadata({opts:#?})"); let image_str = opts.image.to_string(); + let run_setup = !env::var(DOCKER_HOST).is_ok_and(|dh| !dh.is_empty()); + + if run_setup { + DockerDriver::setup()?; + } + let mut command = cmd!( "docker", "buildx", - |command|? { - if !env::var(DOCKER_HOST).is_ok_and(|dh| !dh.is_empty()) { - DockerDriver::setup()?; - cmd!(command, "--builder=bluebuild"); - } - }, + if run_setup => "--builder=bluebuild", "imagetools", "inspect", "--format", diff --git a/process/drivers/local_driver.rs b/process/drivers/local_driver.rs index 1dbf593..85aecfa 100644 --- a/process/drivers/local_driver.rs +++ b/process/drivers/local_driver.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; -use blue_build_utils::{cmd, string_vec}; +use blue_build_utils::string_vec; +use comlexr::cmd; use log::trace; use super::{opts::GenerateTagsOpts, CiDriver, Driver}; diff --git a/process/drivers/podman_driver.rs b/process/drivers/podman_driver.rs index 2debe61..a76f9b5 100644 --- a/process/drivers/podman_driver.rs +++ b/process/drivers/podman_driver.rs @@ -6,9 +6,10 @@ use std::{ time::Duration, }; -use blue_build_utils::{cmd, credentials::Credentials}; +use blue_build_utils::credentials::Credentials; use cached::proc_macro::cached; use colored::Colorize; +use comlexr::cmd; use indicatif::{ProgressBar, ProgressStyle}; use log::{debug, error, info, trace}; use miette::{bail, miette, IntoDiagnostic, Report, Result}; diff --git a/process/drivers/skopeo_driver.rs b/process/drivers/skopeo_driver.rs index 881eae8..667d6f3 100644 --- a/process/drivers/skopeo_driver.rs +++ b/process/drivers/skopeo_driver.rs @@ -1,8 +1,8 @@ use std::{process::Stdio, time::Duration}; -use blue_build_utils::cmd; use cached::proc_macro::cached; use colored::Colorize; +use comlexr::cmd; use indicatif::{ProgressBar, ProgressStyle}; use log::{debug, trace}; use miette::{bail, IntoDiagnostic, Result}; @@ -46,8 +46,8 @@ fn get_metadata_cache(opts: &GetMetadataOpts) -> Result { ], "inspect", format!("docker://{image_str}"), - stderr = Stdio::inherit(), ); + command.stderr(Stdio::inherit()); trace!("{command:?}"); let output = command.output().into_diagnostic()?; diff --git a/process/signal_handler.rs b/process/signal_handler.rs index a2fd78c..45cb680 100644 --- a/process/signal_handler.rs +++ b/process/signal_handler.rs @@ -6,7 +6,7 @@ use std::{ thread, }; -use blue_build_utils::cmd; +use comlexr::cmd; use log::{debug, error, trace, warn}; use nix::{ libc::{SIGABRT, SIGCONT, SIGHUP, SIGTSTP}, diff --git a/src/commands/init.rs b/src/commands/init.rs index 5f67a98..1312780 100644 --- a/src/commands/init.rs +++ b/src/commands/init.rs @@ -11,12 +11,10 @@ use blue_build_process_management::drivers::{ opts::GenerateKeyPairOpts, CiDriver, Driver, DriverArgs, GitlabDriver, SigningDriver, }; use blue_build_template::{GitlabCiTemplate, InitReadmeTemplate, Template}; -use blue_build_utils::{ - cmd, - constants::{COSIGN_PUB_PATH, RECIPE_FILE, RECIPE_PATH, TEMPLATE_REPO_URL}, -}; +use blue_build_utils::constants::{COSIGN_PUB_PATH, RECIPE_FILE, RECIPE_PATH, TEMPLATE_REPO_URL}; use bon::Builder; use clap::{crate_version, Args, ValueEnum}; +use comlexr::cmd; use log::{debug, info, trace}; use miette::{bail, miette, Context, IntoDiagnostic, Report, Result}; use requestty::{questions, Answer, Answers, OnEsc}; @@ -316,14 +314,8 @@ impl InitCommand { let dir = self.dir.as_ref().unwrap(); - let mut command = cmd!( - "git", - "commit", - "-a", - "-m", - "chore: Initial Commit", - current_dir = dir, - ); + let mut command = cmd!("git", "commit", "-a", "-m", "chore: Initial Commit"); + command.current_dir(dir); trace!("{command:?}"); let status = command @@ -345,7 +337,8 @@ impl InitCommand { let dir = self.dir.as_ref().unwrap(); - let mut command = cmd!("git", "add", ".", current_dir = dir,); + let mut command = cmd!("git", "add", "."); + command.current_dir(dir); trace!("{command:?}"); let status = command diff --git a/src/commands/switch.rs b/src/commands/switch.rs index 05b274b..a64d3aa 100644 --- a/src/commands/switch.rs +++ b/src/commands/switch.rs @@ -8,16 +8,17 @@ use blue_build_process_management::{ logging::CommandLogging, }; use blue_build_recipe::Recipe; -use blue_build_utils::{ - cmd, - constants::{ARCHIVE_SUFFIX, LOCAL_BUILD, OCI_ARCHIVE, OSTREE_UNVERIFIED_IMAGE}, +use blue_build_utils::constants::{ + ARCHIVE_SUFFIX, LOCAL_BUILD, OCI_ARCHIVE, OSTREE_UNVERIFIED_IMAGE, }; use bon::Builder; use clap::Args; use colored::Colorize; +use comlexr::cmd; use indicatif::ProgressBar; use log::{debug, trace, warn}; use miette::{bail, IntoDiagnostic, Result}; +use nix::unistd::Uid; use tempfile::TempDir; use crate::{commands::build::BuildCommand, rpm_ostree_status::RpmOstreeStatus}; @@ -89,15 +90,17 @@ impl BlueBuildCommand for SwitchCommand { let temp_file_path = tempdir.path().join(&image_file_name); let archive_path = Path::new(LOCAL_BUILD).join(&image_file_name); - warn!( - "{notice}: {} {sudo} {}", - "The next few steps will require".yellow(), - "You may have to supply your password".yellow(), - notice = "NOTICE".bright_red().bold(), - sudo = "`sudo`.".italic().bright_red().bold(), - ); - Self::sudo_clean_local_build_dir()?; - Self::sudo_move_archive(&temp_file_path, &archive_path)?; + if !Uid::effective().is_root() { + warn!( + "{notice}: {} {sudo} {}", + "The next few steps will require".yellow(), + "You may have to supply your password".yellow(), + notice = "NOTICE".bright_red().bold(), + sudo = "`sudo`.".italic().bright_red().bold(), + ); + } + Self::clean_local_build_dir()?; + Self::move_archive(&temp_file_path, &archive_path)?; // We drop the tempdir ahead of time so that the directory // can be cleaned out. @@ -117,11 +120,7 @@ impl SwitchCommand { let status = if status.is_booted_on_archive(archive_path) || status.is_staged_on_archive(archive_path) { - let mut command = cmd!("rpm-ostree", "upgrade"); - - if self.reboot { - cmd!(command, "--reboot"); - } + let command = cmd!("rpm-ostree", "upgrade", if self.reboot => "--reboot"); trace!("{command:?}"); command @@ -131,11 +130,12 @@ impl SwitchCommand { path = archive_path.display() ); - let mut command = cmd!("rpm-ostree", "rebase", &image_ref); - - if self.reboot { - cmd!(command, "--reboot"); - } + let command = cmd!( + "rpm-ostree", + "rebase", + &image_ref, + if self.reboot => "--reboot", + ); trace!("{command:?}"); command @@ -152,9 +152,9 @@ impl SwitchCommand { Ok(()) } - fn sudo_move_archive(from: &Path, to: &Path) -> Result<()> { + fn move_archive(from: &Path, to: &Path) -> Result<()> { trace!( - "SwitchCommand::sudo_move_archive({}, {})", + "SwitchCommand::move_archive({}, {})", from.display(), to.display() ); @@ -163,8 +163,17 @@ impl SwitchCommand { progress.enable_steady_tick(Duration::from_millis(100)); progress.set_message(format!("Moving image archive to {}...", to.display())); - trace!("sudo mv {} {}", from.display(), to.display()); - let status = cmd!("sudo", "mv", from, to).status().into_diagnostic()?; + let status = { + let c = if Uid::effective().is_root() { + cmd!("mv", from, to) + } else { + cmd!("sudo", "mv", from, to) + }; + trace!("{c:?}"); + c + } + .status() + .into_diagnostic()?; progress.finish_and_clear(); @@ -179,7 +188,7 @@ impl SwitchCommand { Ok(()) } - fn sudo_clean_local_build_dir() -> Result<()> { + fn clean_local_build_dir() -> Result<()> { trace!("SwitchCommand::clean_local_build_dir()"); let local_build_path = Path::new(LOCAL_BUILD); @@ -188,13 +197,17 @@ impl SwitchCommand { debug!("Cleaning out build dir {LOCAL_BUILD}"); trace!("sudo ls {LOCAL_BUILD}"); - let output = String::from_utf8( - cmd!("sudo", "ls", LOCAL_BUILD) - .output() - .into_diagnostic()? - .stdout, - ) - .into_diagnostic()?; + let mut command = { + let c = if Uid::effective().is_root() { + cmd!("ls", LOCAL_BUILD) + } else { + cmd!("sudo", "ls", LOCAL_BUILD) + }; + trace!("{c:?}"); + c + }; + let output = + String::from_utf8(command.output().into_diagnostic()?.stdout).into_diagnostic()?; trace!("{output}"); @@ -212,7 +225,17 @@ impl SwitchCommand { progress.set_message("Removing old image archive files..."); trace!("sudo rm -f {files}"); - let status = cmd!("sudo", "rm", "-f", files).status().into_diagnostic()?; + let status = { + let c = if Uid::effective().is_root() { + cmd!("rm", "-f", files) + } else { + cmd!("sudo", "rm", "-f", files) + }; + trace!("{c:?}"); + c + } + .status() + .into_diagnostic()?; progress.finish_and_clear(); @@ -226,9 +249,17 @@ impl SwitchCommand { local_build_path.display() ); - let status = cmd!("sudo", "mkdir", "-p", LOCAL_BUILD) - .status() - .into_diagnostic()?; + let status = { + let c = if Uid::effective().is_root() { + cmd!("mkdir", "-p", LOCAL_BUILD) + } else { + cmd!("sudo", "mkdir", "-p", LOCAL_BUILD) + }; + trace!("{c:?}"); + c + } + .status() + .into_diagnostic()?; if !status.success() { bail!("Failed to create directory {LOCAL_BUILD}"); diff --git a/src/rpm_ostree_status.rs b/src/rpm_ostree_status.rs index aa27a70..584177c 100644 --- a/src/rpm_ostree_status.rs +++ b/src/rpm_ostree_status.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, path::Path}; -use blue_build_utils::cmd; +use comlexr::cmd; use log::trace; use miette::{bail, IntoDiagnostic, Result}; use serde::Deserialize; diff --git a/utils/Cargo.toml b/utils/Cargo.toml index c72fd62..a8956a8 100644 --- a/utils/Cargo.toml +++ b/utils/Cargo.toml @@ -20,6 +20,7 @@ which = "7" chrono.workspace = true clap = { workspace = true, features = ["derive", "env"] } +comlexr.workspace = true log.workspace = true miette.workspace = true serde.workspace = true diff --git a/utils/src/lib.rs b/utils/src/lib.rs index 775a8cf..daff6fc 100644 --- a/utils/src/lib.rs +++ b/utils/src/lib.rs @@ -20,6 +20,7 @@ use blake2::{ Blake2bVar, }; use chrono::Local; +use comlexr::cmd; use format_serde_error::SerdeError; use log::{trace, warn}; use miette::{miette, Context, IntoDiagnostic, Result}; diff --git a/utils/src/macros.rs b/utils/src/macros.rs index a9a4a71..672d43d 100644 --- a/utils/src/macros.rs +++ b/utils/src/macros.rs @@ -1,141 +1,3 @@ -/// Creates or modifies a `std::process::Command` adding args. -/// -/// # Examples -/// ``` -/// use blue_build_utils::cmd; -/// -/// const NAME: &str = "Bob"; -/// let mut command = cmd!("echo", "Hello world!"); -/// cmd!(command, "This is Joe.", format!("And this is {NAME}")); -/// command.status().unwrap(); -/// ``` -#[macro_export] -macro_rules! cmd { - ($command:expr) => { - ::std::process::Command::new($command) - }; - ($command:ident, $($tail:tt)*) => { - $crate::cmd!(@ $command, $($tail)*) - }; - ($command:expr, $($tail:tt)*) => { - { - let mut c = $crate::cmd!($command); - $crate::cmd!(@ c, $($tail)*); - c - } - }; - (@ $command:ident $(,)?) => { }; - (@ $command:ident, for $for_expr:expr $(, $($tail:tt)*)?) => { - { - for arg in $for_expr { - $crate::cmd!($command, arg); - } - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, for $iter:pat in $for_expr:expr => [ $($arg:expr),* $(,)? ] $(, $($tail:tt)*)?) => { - { - for $iter in $for_expr { - $($crate::cmd!(@ $command, $arg);)* - } - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, for $iter:pat in $for_expr:expr => $arg:expr $(, $($tail:tt)*)?) => { - { - for $iter in $for_expr { - $crate::cmd!(@ $command, $arg); - } - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, if let $let_pat:pat = $if_expr:expr => [ $($arg:expr),* $(,)? ] $(, $($tail:tt)*)?) => { - { - if let $let_pat = $if_expr { - $($crate::cmd!(@ $command, $arg);)* - } - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, if let $let_pat:pat = $if_expr:expr => $arg:expr $(, $($tail:tt)*)?) => { - { - if let $let_pat = $if_expr { - $crate::cmd!(@ $command, $arg); - } - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, if $if_expr:expr => [ $($arg:expr),* $(,)?] $(, $($tail:tt)*)?) => { - { - if $if_expr { - $($crate::cmd!(@ $command, $arg);)* - } - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, if $if_expr:expr => $arg:expr $(, $($tail:tt)*)?) => { - { - if $if_expr { - $crate::cmd!(@ $command, $arg); - } - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, |$cmd_ref:ident|? $op:block $(, $($tail:tt)*)?) => { - { - let op_fn = |$cmd_ref: &mut ::std::process::Command| -> Result<()> { - $op - Ok(()) - }; - op_fn(&mut $command)?; - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, |$cmd_ref:ident| $op:block $(, $($tail:tt)*)?) => { - { - let op_fn = |$cmd_ref: &mut ::std::process::Command| $op; - op_fn(&mut $command); - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, $key:expr => $value:expr $(, $($tail:tt)*)?) => { - { - $command.env($key, $value); - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, current_dir = $dir:expr $(, $($tail:tt)*)?) => { - { - $command.current_dir($dir); - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, stdin = $pipe:expr $(, $($tail:tt)*)?) => { - { - $command.stdin($pipe); - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, stdout = $pipe:expr $(, $($tail:tt)*)?) => { - { - $command.stdout($pipe); - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, stderr = $pipe:expr $(, $($tail:tt)*)?) => { - { - $command.stderr($pipe); - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; - (@ $command:ident, $arg:expr $(, $($tail:tt)*)?) => { - { - $command.arg($arg); - $($crate::cmd!(@ $command, $($tail)*);)* - } - }; -} - /// Easily create a `String`. #[macro_export] macro_rules! string {