1use std::process::Command;23use crate::{command::CommandExt, host::Config, nix::SYSTEMS_ATTRIBUTE};4use anyhow::Result;5use clap::Clap;6use log::info;78#[derive(Clap)]9#[clap(group = clap::ArgGroup::new("target"))]10pub struct BuildSystems {11 12 #[clap(long)]13 builders: Option<String>,14 15 #[clap(long)]16 jobs: Option<usize>,17 18 #[clap(long)]19 fail_fast: bool,20 #[clap(long)]21 privileged_build: bool,22 #[clap(subcommand)]23 subcommand: Option<Subcommand>,24}2526#[derive(Clap)]27enum Subcommand {28 29 Test,30 31 Boot,32 33 Switch,34}35impl Subcommand {36 fn should_switch_profile(&self) -> bool {37 matches!(self, Self::Test | Self::Switch)38 }39 fn name(&self) -> &'static str {40 match self {41 Self::Test => "test",42 Self::Boot => "boot",43 Self::Switch => "switch",44 }45 }46}4748impl BuildSystems {49 pub fn run(self, config: &Config) -> Result<()> {50 println!("Build");51 52 let hosts = config.list_hosts()?;53 dbg!(&hosts);54 5556 for host in hosts.iter() {57 if config.should_skip(host) {58 continue;59 }60 info!("Building host {}", host);61 let built = {62 let dir = tempfile::tempdir()?;63 dir.path().to_owned()64 };6566 let mut nix_build = if self.privileged_build {67 let mut out = Command::new("sudo");68 out.arg("nix");69 out70 } else {71 Command::new("nix")72 };73 nix_build74 .args(&["build", "--impure", "--no-link", "--out-link"])75 .arg(&built)76 .arg(format!(77 "{}.{}.config.system.build.toplevel",78 SYSTEMS_ATTRIBUTE, host,79 ));80 8182 if let Some(builders) = &self.builders {83 println!("Using builders: {}", builders);84 nix_build.arg("--builders").arg(builders);85 }86 if let Some(jobs) = &self.jobs {87 nix_build.arg("--max-jobs");88 nix_build.arg(format!("{}", jobs));89 }90 if !self.fail_fast {91 nix_build.arg("--keep-going");92 }9394 nix_build.inherit_stdio().run()?;95 let built = std::fs::canonicalize(built)?;96 info!("Built closure: {:?}", built);97 if !config.is_local(host) {98 info!("Uploading system closure");99 Command::new("nix")100 .args(&["copy", "--to"])101 .arg(format!("ssh://root@{}", host))102 .arg(&built)103 .inherit_stdio()104 .run()?;105 }106 if let Some(subcommand) = &self.subcommand {107 if subcommand.should_switch_profile() {108 info!("Switching generation");109 dbg!(&mut config110 .command_on(host, "nix-env", true)111 .args(&["-p", "/nix/var/nix/profiles/system", "--set"])112 .arg(&built)113 .inherit_stdio())114 .run()?;115 }116 info!("Executing activation script");117 let mut switch_script = built.clone();118 switch_script.push("bin");119 switch_script.push("switch-to-configuration");120 info!("{:?}", switch_script);121 config122 .command_on(host, switch_script, true)123 .arg(subcommand.name())124 .inherit_stdio()125 .run()?;126 }127 }128 Ok(())129 }130}