From 47e6a32ba356ac11de64d56bd733b040c2e5e4a5 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 14 Feb 2026 19:20:52 -0500 Subject: [PATCH] Run nix build. --- example_config.toml | 2 +- src/command/build/runner.rs | 33 ++++++++++++++++----- src/config/root.rs | 8 ++--- src/config/target.rs | 43 +++++++++++++++++++++++---- src/main.rs | 1 + src/nix_util/high_level.rs | 58 +++++++++++++++++++++++++++++++++++++ src/nix_util/mod.rs | 2 ++ 7 files changed, 130 insertions(+), 17 deletions(-) create mode 100644 src/nix_util/high_level.rs create mode 100644 src/nix_util/mod.rs diff --git a/example_config.toml b/example_config.toml index e752a45..88ca3bf 100644 --- a/example_config.toml +++ b/example_config.toml @@ -1,4 +1,4 @@ -# work_directory = "/home/nixworker/persist/nix_builder" +# repo_directory = "/home/nixworker/persist/nix_builder" [[targets]] name = "odo" diff --git a/src/command/build/runner.rs b/src/command/build/runner.rs index 702651a..f03e266 100644 --- a/src/command/build/runner.rs +++ b/src/command/build/runner.rs @@ -6,6 +6,7 @@ use crate::fs_util::assert_directory; use crate::fs_util::is_git_repo; use crate::git_util::git_force_into_state; use crate::git_util::git_init_at_rev; +use crate::nix_util::nixos_build_target; pub(crate) async fn run_build(args: BuildArgs) -> Result<(), CustomError> { println!("{:?}", args); @@ -23,6 +24,7 @@ pub(crate) async fn run_build(args: BuildArgs) -> Result<(), CustomError> { }; prepare_flake_repo(&config, target_config).await?; + build_target(&config, target_config).await?; } Ok(()) @@ -32,17 +34,17 @@ async fn prepare_flake_repo( config_root: &Config, target_config: &TargetConfig, ) -> Result<(), CustomError> { - let flake_directory = target_config.get_flake_directory(config_root)?; + let repo_directory = target_config.get_repo_directory(config_root)?; assert_directory!( - &flake_directory, - "Creating flake directory {}", - (&flake_directory).to_string_lossy() + &repo_directory, + "Creating repo directory {}", + (&repo_directory).to_string_lossy() ); - if is_git_repo(&flake_directory).await? { + if is_git_repo(&repo_directory).await? { // Clean up the existing clone git_force_into_state( - &flake_directory, + &repo_directory, target_config.get_branch()?, "origin", target_config.get_repo()?, @@ -51,7 +53,7 @@ async fn prepare_flake_repo( .await?; } else { git_init_at_rev( - &flake_directory, + &repo_directory, target_config.get_branch()?, target_config.get_repo()?, target_config.get_revision()?, @@ -60,3 +62,20 @@ async fn prepare_flake_repo( } Ok(()) } + +async fn build_target( + config_root: &Config, + target_config: &TargetConfig, +) -> Result<(), CustomError> { + let flake_directory = target_config.get_flake_directory(config_root)?; + let build_directory = target_config.get_build_directory(config_root)?; + assert_directory!( + &build_directory, + "Creating build directory {}", + (&build_directory).to_string_lossy() + ); + + nixos_build_target(build_directory, flake_directory, target_config.get_attr()?).await?; + + Ok(()) +} diff --git a/src/config/root.rs b/src/config/root.rs index 565b646..0b19f29 100644 --- a/src/config/root.rs +++ b/src/config/root.rs @@ -15,7 +15,7 @@ use super::TargetConfig; pub(crate) struct Config { #[serde(skip)] config_path: Option, - work_directory: Option, + output_directory: Option, targets: Vec, } @@ -63,9 +63,9 @@ impl Config { Ok(target_config) } - pub(crate) fn get_work_directory(&self) -> Result, CustomError> { - let maybe_work_directory = self.work_directory.as_deref().map(Cow::Borrowed); - if let Some(work_dir) = maybe_work_directory { + pub(crate) fn get_output_directory(&self) -> Result, CustomError> { + let maybe_repo_directory = self.output_directory.as_deref().map(Cow::Borrowed); + if let Some(work_dir) = maybe_repo_directory { return Ok(work_dir); } let current_dir: PathBuf = std::env::current_dir()?; diff --git a/src/config/target.rs b/src/config/target.rs index 07c4ffa..44cd348 100644 --- a/src/config/target.rs +++ b/src/config/target.rs @@ -24,7 +24,7 @@ pub(crate) struct TargetConfig { pub(super) path: Option, #[serde(default)] - pub(super) attr: Option, + pub(super) attr: String, #[serde(default)] pub(super) update: Option, @@ -34,26 +34,44 @@ pub(crate) struct TargetConfig { } impl TargetConfig { + /// The root directory for this specific build target. pub(crate) fn get_target_directory<'target, 'root>( &'target self, config_root: &'root Config, ) -> Result, CustomError> { - let work_directory = config_root.get_work_directory()?; - Ok(Cow::Owned(work_directory.join(&self.name))) + let repo_directory = config_root.get_output_directory()?; + Ok(Cow::Owned(repo_directory.join(&self.name))) } - pub(crate) fn get_flake_directory<'target, 'root>( + /// The root of the checkout of the git repository. + pub(crate) fn get_repo_directory<'target, 'root>( &'target self, config_root: &'root Config, ) -> Result, CustomError> { let target_directory = self.get_target_directory(config_root)?; - Ok(Cow::Owned(target_directory.join("flake"))) + Ok(Cow::Owned(target_directory.join("repo"))) } + /// The directory that contains flake.nix. + pub(crate) fn get_flake_directory<'target, 'root>( + &'target self, + config_root: &'root Config, + ) -> Result, CustomError> { + let repo_directory = self.get_repo_directory(config_root)?; + let subpath = self.path.as_deref(); + if let Some(subpath) = subpath { + Ok(Cow::Owned(repo_directory.join(subpath))) + } else { + Ok(repo_directory) + } + } + + /// The URL to the upstream git repository. pub(crate) fn get_repo(&'_ self) -> Result<&String, CustomError> { Ok(&self.repo) } + /// The git branch name to track. pub(crate) fn get_branch(&'_ self) -> Result, CustomError> { if let Some(b) = &self.branch { Ok(Cow::Borrowed(b)) @@ -62,7 +80,22 @@ impl TargetConfig { } } + /// If we want to pin to a specific revision, this is the reference to that commit. pub(crate) fn get_revision(&self) -> Result<&Option, CustomError> { Ok(&self.revision) } + + /// The folder where nixos-rebuild is invoked and the outputs are linked. + pub(crate) fn get_build_directory<'target, 'root>( + &'target self, + config_root: &'root Config, + ) -> Result, CustomError> { + let target_directory = self.get_target_directory(config_root)?; + Ok(Cow::Owned(target_directory.join("build"))) + } + + /// The flake output attribute to build (the part after '#' in the build command). + pub(crate) fn get_attr(&'_ self) -> Result<&String, CustomError> { + Ok(&self.attr) + } } diff --git a/src/main.rs b/src/main.rs index 4ea65eb..41507cf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,6 +16,7 @@ mod error; mod fs_util; mod git_util; mod init_tracing; +mod nix_util; fn main() -> Result { let rt = tokio::runtime::Runtime::new()?; diff --git a/src/nix_util/high_level.rs b/src/nix_util/high_level.rs new file mode 100644 index 0000000..e872a37 --- /dev/null +++ b/src/nix_util/high_level.rs @@ -0,0 +1,58 @@ +use std::ffi::OsStr; +use std::ffi::OsString; +use std::path::Path; + +use tokio::process::Command; + +use crate::error::CustomError; + +pub(crate) async fn nixos_build_target( + build_path: B, + flake_path: F, + attr: A, +) -> Result<(), CustomError> +where + B: AsRef, + F: AsRef, + A: AsRef, +{ + let reference = { + let path = AsRef::::as_ref(flake_path.as_ref()); + let attr = attr.as_ref(); + let mut reference = OsString::with_capacity(path.len() + attr.len() + 1); + reference.push(path); + reference.push("#"); + reference.push(attr); + reference + }; + + // nixos-rebuild build --show-trace --sudo --max-jobs "$JOBS" --flake "$DIR/../../#odo" --log-format internal-json -v "${@}" + let mut command = Command::new("nixos-rebuild"); + command.current_dir(build_path); + command.args(&[ + "build", + "--show-trace", + "--sudo", + "--max-jobs", + "1", + "--log-format", + "internal-json", + "-v", + ]); + command.arg("--flake"); + command.arg(reference); + command.kill_on_drop(true); + + let mut child = command.spawn()?; + let status = child.wait().await?; + if !status.success() { + return Err("Nixos rebuild failed.".into()); + } + + // tokio::spawn(async move { + // let status = child.wait().await.expect("mpv encountered an error"); + // println!("mpv status was: {}", status); + // }); + + Ok(()) +} diff --git a/src/nix_util/mod.rs b/src/nix_util/mod.rs new file mode 100644 index 0000000..9c12d6c --- /dev/null +++ b/src/nix_util/mod.rs @@ -0,0 +1,2 @@ +mod high_level; +pub(crate) use high_level::*;