Skip to content

Commit

Permalink
fixup! [#260] Abstract some of the boilerplate
Browse files Browse the repository at this point in the history
  • Loading branch information
heitor-lassarote committed Jan 15, 2025
1 parent c87f4f8 commit b8ffefb
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 105 deletions.
24 changes: 14 additions & 10 deletions src/bin/activate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use signal_hook::{consts::signal::SIGHUP, iterator::Signals};
use clap::Clap;

use tokio::fs;
use tokio::process::Command;
use tokio::sync::mpsc;
use tokio::time::timeout;

Expand Down Expand Up @@ -175,23 +176,24 @@ pub enum DeactivateError {
pub async fn deactivate(profile_path: &str) -> Result<(), DeactivateError> {
warn!("De-activating due to error");

let mut nix_env_rollback_command = command::Command::new("nix-env");
let mut nix_env_rollback_command = Command::new("nix-env");
nix_env_rollback_command
.arg("-p")
.arg(&profile_path)
.arg("--rollback")
.arg("--rollback");
command::Command::new(nix_env_rollback_command)
.run()
.await
.map_err(DeactivateError::Rollback)?;

debug!("Listing generations");

let mut nix_env_list_generations_command = command::Command::new("nix-env");
let mut nix_env_list_generations_command = Command::new("nix-env");
nix_env_list_generations_command
.arg("-p")
.arg(&profile_path)
.arg("--list-generations");
let nix_env_list_generations_out = nix_env_list_generations_command
let nix_env_list_generations_out = command::Command::new(nix_env_list_generations_command)
.run()
.await
.map_err(DeactivateError::ListGen)?;
Expand All @@ -212,22 +214,24 @@ pub async fn deactivate(profile_path: &str) -> Result<(), DeactivateError> {
debug!("Removing generation entry {}", last_generation_line);
warn!("Removing generation by ID {}", last_generation_id);

let mut nix_env_delete_generation_command = command::Command::new("nix-env");
let mut nix_env_delete_generation_command = Command::new("nix-env");
nix_env_delete_generation_command
.arg("-p")
.arg(&profile_path)
.arg("--delete-generations")
.arg(last_generation_id)
.arg(last_generation_id);
command::Command::new(nix_env_delete_generation_command)
.run()
.await
.map_err(DeactivateError::DeleteGen)?;

info!("Attempting to re-activate the last generation");

let mut re_activate_command = command::Command::new(format!("{}/deploy-rs-activate", profile_path));
let mut re_activate_command = Command::new(format!("{}/deploy-rs-activate", profile_path));
re_activate_command
.env("PROFILE", &profile_path)
.current_dir(&profile_path)
.current_dir(&profile_path);
command::Command::new(re_activate_command)
.run()
.await
.map_err(DeactivateError::Reactivate)?;
Expand Down Expand Up @@ -421,7 +425,7 @@ pub async fn activate(
) -> Result<(), ActivateError> {
if !dry_activate {
info!("Activating profile");
let mut nix_env_set_command = command::Command::new("nix-env");
let mut nix_env_set_command = Command::new("nix-env");
nix_env_set_command
.arg("-p")
.arg(&profile_path)
Expand Down Expand Up @@ -454,7 +458,7 @@ pub async fn activate(
&profile_path
};

let mut activate_command = command::Command::new(format!("{}/deploy-rs-activate", activation_location));
let mut activate_command = Command::new(format!("{}/deploy-rs-activate", activation_location));
activate_command
.env("PROFILE", activation_location)
.env("DRY_ACTIVATE", if dry_activate { "1" } else { "0" })
Expand Down
17 changes: 9 additions & 8 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ async fn check_deployment(
info!("Running checks for flake in {}", repo);

let mut check_command = match supports_flakes {
true => command::Command::new("nix"),
false => command::Command::new("nix-build"),
true => Command::new("nix"),
false => Command::new("nix-build"),
};

if supports_flakes {
Expand All @@ -162,7 +162,7 @@ async fn check_deployment(

check_command.args(extra_build_args);

check_command.run().await.map_err(CheckDeploymentError::NixCheck)?;
command::Command::new(check_command).run().await.map_err(CheckDeploymentError::NixCheck)?;

Ok(())
}
Expand Down Expand Up @@ -199,9 +199,9 @@ async fn get_deployment_data(
info!("Evaluating flake in {}", flake.repo);

let mut eval_command = if supports_flakes {
command::Command::new("nix")
Command::new("nix")
} else {
command::Command::new("nix-instantiate")
Command::new("nix-instantiate")
};

if supports_flakes {
Expand Down Expand Up @@ -259,10 +259,11 @@ async fn get_deployment_data(
.arg(format!("let r = import {}/.; in if builtins.isFunction r then (r {{}}).deploy else r.deploy", flake.repo))
};

eval_command.args(extra_build_args);
eval_command
.args(extra_build_args)
.stdout(Stdio::null());

let build_output = eval_command
.stdout(Stdio::null())
let build_output = command::Command::new(eval_command)
.run()
.await
.map_err(GetDeploymentDataError::NixEval)?;
Expand Down
63 changes: 2 additions & 61 deletions src/command.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::ffi::OsStr;
use std::fmt;
use std::fmt::Debug;
use std::future::Future;
use thiserror::Error;
use tokio::process::Command as TokioCommand;

Expand Down Expand Up @@ -48,65 +46,8 @@ pub struct Command {
}

impl Command {
pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
Command {
command: TokioCommand::new(program),
}
}

pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
self.command.arg(arg);
self
}

pub fn args<I, S>(&mut self, args: I) -> &mut Command
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
self.command.args(args);
self
}

pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
where
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
self.command.env(key, val);
self
}

pub fn output(&mut self) -> impl Future<Output = tokio::io::Result<std::process::Output>> {
self.command.output()
}

pub fn current_dir<P: AsRef<std::path::Path>>(&mut self, dir: P) -> &mut Command {
self.command.current_dir(dir);
self
}

pub fn stdin<T: Into<std::process::Stdio>>(&mut self, cfg: T) -> &mut Command {
self.command.stdin(cfg);
self
}

pub fn stdout<T: Into<std::process::Stdio>>(&mut self, cfg: T) -> &mut Command {
self.command.stdout(cfg);
self
}

pub fn stderr<T: Into<std::process::Stdio>>(&mut self, cfg: T) -> &mut Command {
self.command.stderr(cfg);
self
}

pub fn spawn(&mut self) -> std::io::Result<tokio::process::Child> {
self.command.spawn()
}

pub fn status(&mut self) -> impl Future<Output = tokio::io::Result<std::process::ExitStatus>> {
self.command.status()
pub fn new(command: TokioCommand) -> Command {
Command { command }
}

pub async fn run<T: fmt::Debug + fmt::Display + HasCommandError>(
Expand Down
10 changes: 5 additions & 5 deletions src/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use log::{debug, info, trace};
use std::path::Path;
use thiserror::Error;
use tokio::io::AsyncWriteExt;
use tokio::{io::AsyncWriteExt, process::Command};

use crate::{command, DeployDataDefsError, DeployDefs, ProfileInfo};

Expand Down Expand Up @@ -282,7 +282,7 @@ pub async fn confirm_profile(
temp_path: &Path,
ssh_addr: &str,
) -> Result<(), ConfirmProfileError> {
let mut ssh_confirm_command = command::Command::new("ssh");
let mut ssh_confirm_command = Command::new("ssh");
ssh_confirm_command
.arg(ssh_addr)
.stdin(std::process::Stdio::piped());
Expand Down Expand Up @@ -424,7 +424,7 @@ pub async fn deploy_profile(

let ssh_addr = format!("{}@{}", deploy_defs.ssh_user, hostname);

let mut ssh_activate_command = command::Command::new("ssh");
let mut ssh_activate_command = Command::new("ssh");
ssh_activate_command
.arg(&ssh_addr)
.stdin(std::process::Stdio::piped());
Expand Down Expand Up @@ -509,7 +509,7 @@ pub async fn deploy_profile(

info!("Creating activation waiter");

let mut ssh_wait_command = command::Command::new("ssh");
let mut ssh_wait_command = Command::new("ssh");
ssh_wait_command
.arg(&ssh_addr)
.stdin(std::process::Stdio::piped());
Expand Down Expand Up @@ -631,7 +631,7 @@ pub async fn revoke(

let ssh_addr = format!("{}@{}", deploy_defs.ssh_user, hostname);

let mut ssh_activate_command = command::Command::new("ssh");
let mut ssh_activate_command = Command::new("ssh");
ssh_activate_command
.arg(&ssh_addr)
.stdin(std::process::Stdio::piped());
Expand Down
50 changes: 29 additions & 21 deletions src/push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::collections::HashMap;
use std::path::Path;
use std::process::Stdio;
use thiserror::Error;
use tokio::process::Command;

use crate::command;

Expand Down Expand Up @@ -104,9 +105,9 @@ pub async fn build_profile_locally(data: &PushProfileData<'_>, derivation_name:
);

let mut build_command = if data.supports_flakes {
command::Command::new("nix")
Command::new("nix")
} else {
command::Command::new("nix-build")
Command::new("nix-build")
};

if data.supports_flakes {
Expand All @@ -128,11 +129,12 @@ pub async fn build_profile_locally(data: &PushProfileData<'_>, derivation_name:
(false, true) => build_command.arg("--no-link"),
};

build_command.args(data.extra_build_args);

build_command
.args(data.extra_build_args)
// Logging should be in stderr, this just stops the store path from printing for no reason
.stdout(Stdio::null())
.stdout(Stdio::null());

command::Command::new(build_command)
.run()
.await
.map_err(PushProfileError::Build)?;
Expand Down Expand Up @@ -167,13 +169,14 @@ pub async fn build_profile_locally(data: &PushProfileData<'_>, derivation_name:
data.deploy_data.profile_name, data.deploy_data.node_name
);

let mut sign_command = command::Command::new("nix");
let mut sign_command = Command::new("nix");
sign_command
.arg("sign-paths")
.arg("-r")
.arg("-k")
.arg(local_key)
.arg(&data.deploy_data.profile.profile_settings.path)
.arg(&data.deploy_data.profile.profile_settings.path);
command::Command::new(sign_command)
.run()
.await
.map_err(PushProfileError::Sign)?;
Expand All @@ -198,31 +201,32 @@ pub async fn build_profile_remotely(data: &PushProfileData<'_>, derivation_name:


// copy the derivation to remote host so it can be built there
let mut copy_command = command::Command::new("nix");
let mut copy_command = Command::new("nix");
copy_command
.arg("copy")
.arg("-s") // fetch dependencies from substitures, not localhost
.arg("--to").arg(&store_address)
.arg("--derivation").arg(derivation_name)
.env("NIX_SSHOPTS", ssh_opts_str.clone())
.stdout(Stdio::null())
.stdout(Stdio::null());
command::Command::new(copy_command)
.run()
.await
.map_err(PushProfileError::Copy)?;

let mut build_command = command::Command::new("nix");
let mut build_command = Command::new("nix");
build_command
.arg("build").arg(derivation_name)
.arg("--eval-store").arg("auto")
.arg("--store").arg(&store_address)
.args(data.extra_build_args)
.env("NIX_SSHOPTS", ssh_opts_str.clone());
.env("NIX_SSHOPTS", ssh_opts_str.clone())
// Logging should be in stderr, this just stops the store path from printing for no reason
.stdout(Stdio::null());

debug!("build command: {:?}", build_command);

build_command
// Logging should be in stderr, this just stops the store path from printing for no reason
.stdout(Stdio::null())
command::Command::new(build_command)
.run()
.await
.map_err(PushProfileError::Build)?;
Expand All @@ -237,13 +241,13 @@ pub async fn build_profile(data: PushProfileData<'_>) -> Result<(), PushProfileE
);

// `nix-store --query --deriver` doesn't work on invalid paths, so we parse output of show-derivation :(
let mut show_derivation_command = command::Command::new("nix");
let mut show_derivation_command = Command::new("nix");

show_derivation_command
.arg("show-derivation")
.arg(&data.deploy_data.profile.profile_settings.path);

let show_derivation_output = show_derivation_command
let show_derivation_output = command::Command::new(show_derivation_command)
.run()
.await
.map_err(PushProfileError::ShowDerivation)?;
Expand Down Expand Up @@ -278,11 +282,14 @@ pub async fn build_profile(data: PushProfileData<'_>) -> Result<(), PushProfileE
deriver.to_owned()
};

let path_info_output = command::Command::new("nix")
let mut path_info_command = Command::new("nix");
path_info_command
.arg("--experimental-features").arg("nix-command")
.arg("path-info")
.arg(&deriver)
.run().await
.arg(&deriver);
let path_info_output = command::Command::new(path_info_command)
.run()
.await
.map_err(PushProfileError::PathInfo)?;

let deriver = if std::str::from_utf8(&path_info_output.stdout).map(|s| s.trim()) == Ok(deriver) {
Expand Down Expand Up @@ -332,7 +339,7 @@ pub async fn push_profile(data: PushProfileData<'_>) -> Result<(), PushProfileEr
data.deploy_data.profile_name, data.deploy_data.node_name
);

let mut copy_command = command::Command::new("nix");
let mut copy_command = Command::new("nix");
copy_command.arg("copy");

if data.deploy_data.merged_settings.fast_connection != Some(true) {
Expand All @@ -352,7 +359,8 @@ pub async fn push_profile(data: PushProfileData<'_>) -> Result<(), PushProfileEr
.arg("--to")
.arg(format!("ssh://{}@{}", data.deploy_defs.ssh_user, hostname))
.arg(&data.deploy_data.profile.profile_settings.path)
.env("NIX_SSHOPTS", ssh_opts_str)
.env("NIX_SSHOPTS", ssh_opts_str);
command::Command::new(copy_command)
.run()
.await
.map_err(PushProfileError::Copy)?;
Expand Down

0 comments on commit b8ffefb

Please sign in to comment.