3
3
// SPDX-License-Identifier: MPL-2.0
4
4
5
5
use log:: { debug, info} ;
6
+ use std:: collections:: HashMap ;
6
7
use std:: path:: Path ;
7
8
use std:: process:: Stdio ;
8
9
use thiserror:: Error ;
9
10
use tokio:: process:: Command ;
10
11
11
12
#[ derive( Error , Debug ) ]
12
13
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 ,
13
24
#[ error( "Failed to run Nix build command: {0}" ) ]
14
25
BuildError ( std:: io:: Error ) ,
15
26
#[ error( "Nix build command resulted in a bad exit code: {0:?}" ) ]
@@ -44,6 +55,39 @@ pub struct PushProfileData<'a> {
44
55
}
45
56
46
57
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
+
47
91
info ! (
48
92
"Building profile `{}` for node `{}`" ,
49
93
data. deploy_data. profile_name, data. deploy_data. node_name
@@ -56,15 +100,9 @@ pub async fn push_profile(data: PushProfileData<'_>) -> Result<(), PushProfileEr
56
100
} ;
57
101
58
102
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)
63
104
} 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)
68
106
} ;
69
107
70
108
match ( data. keep_result , data. supports_flakes ) {
@@ -142,7 +180,7 @@ pub async fn push_profile(data: PushProfileData<'_>) -> Result<(), PushProfileEr
142
180
} ;
143
181
}
144
182
145
- debug ! (
183
+ info ! (
146
184
"Copying profile `{}` to node `{}`" ,
147
185
data. deploy_data. profile_name, data. deploy_data. node_name
148
186
) ;
0 commit comments