Skip to content

Commit 220f071

Browse files
committed
Evaluate only once, and then only realise
1 parent f973cb5 commit 220f071

File tree

1 file changed

+47
-9
lines changed

1 file changed

+47
-9
lines changed

src/push.rs

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,24 @@
33
// SPDX-License-Identifier: MPL-2.0
44

55
use log::{debug, info};
6+
use std::collections::HashMap;
67
use std::path::Path;
78
use std::process::Stdio;
89
use thiserror::Error;
910
use tokio::process::Command;
1011

1112
#[derive(Error, Debug)]
1213
pub enum PushProfileError {
14+
#[error("Failed to run Nix show-derivation command: {0}")]
15+
ShowDerivationError(std::io::Error),
16+
#[error("Nix show-derivation command resulted in a bad exit code: {0:?}")]
17+
ShowDerivationExitError(Option<i32>),
18+
#[error("Nix show-derivation command output contained an invalid UTF-8 sequence: {0}")]
19+
ShowDerivationUtf8Error(std::str::Utf8Error),
20+
#[error("Failed to parse the output of nix show-derivation: {0}")]
21+
ShowDerivationParseError(serde_json::Error),
22+
#[error("Nix show-derivation output is empty")]
23+
ShowDerivationEmpty,
1324
#[error("Failed to run Nix build command: {0}")]
1425
BuildError(std::io::Error),
1526
#[error("Nix build command resulted in a bad exit code: {0:?}")]
@@ -44,6 +55,39 @@ pub struct PushProfileData<'a> {
4455
}
4556

4657
pub async fn push_profile(data: PushProfileData<'_>) -> Result<(), PushProfileError> {
58+
debug!(
59+
"Finding the deriver of store path for {}",
60+
&data.deploy_data.profile.profile_settings.path
61+
);
62+
63+
// `nix-store --query --deriver` doesn't work on invalid paths, so we parse output of show-derivation :(
64+
let mut show_derivation_command = Command::new("nix");
65+
66+
show_derivation_command
67+
.arg("show-derivation")
68+
.arg(&data.deploy_data.profile.profile_settings.path);
69+
70+
let show_derivation_output = show_derivation_command
71+
.output()
72+
.await
73+
.map_err(PushProfileError::ShowDerivationError)?;
74+
75+
match show_derivation_output.status.code() {
76+
Some(0) => (),
77+
a => return Err(PushProfileError::ShowDerivationExitError(a)),
78+
};
79+
80+
let derivation_info: HashMap<&str, serde_json::value::Value> = serde_json::from_str(
81+
std::str::from_utf8(&show_derivation_output.stdout)
82+
.map_err(PushProfileError::ShowDerivationUtf8Error)?,
83+
)
84+
.map_err(PushProfileError::ShowDerivationParseError)?;
85+
86+
let derivation_name = derivation_info
87+
.keys()
88+
.next()
89+
.ok_or(PushProfileError::ShowDerivationEmpty)?;
90+
4791
info!(
4892
"Building profile `{}` for node `{}`",
4993
data.deploy_data.profile_name, data.deploy_data.node_name
@@ -56,15 +100,9 @@ pub async fn push_profile(data: PushProfileData<'_>) -> Result<(), PushProfileEr
56100
};
57101

58102
if data.supports_flakes {
59-
build_command.arg("build").arg(format!(
60-
"{}#deploy.nodes.\"{}\".profiles.\"{}\".path",
61-
data.repo, data.deploy_data.node_name, data.deploy_data.profile_name
62-
))
103+
build_command.arg("build").arg(derivation_name)
63104
} else {
64-
build_command.arg(&data.repo).arg("-A").arg(format!(
65-
"deploy.nodes.\"{}\".profiles.\"{}\".path",
66-
data.deploy_data.node_name, data.deploy_data.profile_name
67-
))
105+
build_command.arg(derivation_name)
68106
};
69107

70108
match (data.keep_result, data.supports_flakes) {
@@ -142,7 +180,7 @@ pub async fn push_profile(data: PushProfileData<'_>) -> Result<(), PushProfileEr
142180
};
143181
}
144182

145-
debug!(
183+
info!(
146184
"Copying profile `{}` to node `{}`",
147185
data.deploy_data.profile_name, data.deploy_data.node_name
148186
);

0 commit comments

Comments
 (0)