@@ -43,6 +43,9 @@ pub enum PushProfileError {
43
43
CopyExit ( Option < i32 > ) ,
44
44
#[ error( "The remote building option is not supported when using legacy nix" ) ]
45
45
RemoteBuildWithLegacyNix ,
46
+
47
+ #[ error( "Failed to run Nix path-info command: {0}" ) ]
48
+ PathInfo ( std:: io:: Error ) ,
46
49
}
47
50
48
51
pub struct PushProfileData < ' a > {
@@ -236,19 +239,45 @@ pub async fn build_profile(data: PushProfileData<'_>) -> Result<(), PushProfileE
236
239
)
237
240
. map_err ( PushProfileError :: ShowDerivationParse ) ?;
238
241
239
- let derivation_name = derivation_info
242
+ let & deriver = derivation_info
240
243
. keys ( )
241
244
. next ( )
242
245
. ok_or ( PushProfileError :: ShowDerivationEmpty ) ?;
243
246
247
+ // Since nix 2.15.0 'nix build <path>.drv' will build only the .drv file itself, not the
248
+ // derivation outputs, '^out' is used to refer to outputs explicitly
249
+ let new_deriver = & ( deriver. to_owned ( ) . to_string ( ) + "^out" ) ;
250
+
251
+ let path_info_output = Command :: new ( "nix" )
252
+ . arg ( "--experimental-features" ) . arg ( "nix-command" )
253
+ . arg ( "path-info" )
254
+ . arg ( & deriver)
255
+ . output ( ) . await
256
+ . map_err ( PushProfileError :: PathInfo ) ?;
257
+
258
+ let deriver = if std:: str:: from_utf8 ( & path_info_output. stdout ) . map ( |s| s. trim ( ) ) == Ok ( deriver) {
259
+ // In this case we're on 2.15.0 or newer, because 'nix path-infonix path-info <...>.drv'
260
+ // returns the same '<...>.drv' path.
261
+ // If 'nix path-info <...>.drv' returns a different path, then we're on pre 2.15.0 nix and
262
+ // derivation build result is already present in the /nix/store.
263
+ new_deriver
264
+ } else {
265
+ // If 'nix path-info <...>.drv' returns a different path, then we're on pre 2.15.0 nix and
266
+ // derivation build result is already present in the /nix/store.
267
+ //
268
+ // Alternatively, the result of the derivation build may not be yet present
269
+ // in the /nix/store. In this case, 'nix path-info' returns
270
+ // 'error: path '...' is not valid'.
271
+ deriver
272
+ } ;
244
273
if data. deploy_data . merged_settings . remote_build . unwrap_or ( false ) {
245
274
if !data. supports_flakes {
246
275
return Err ( PushProfileError :: RemoteBuildWithLegacyNix )
247
276
}
248
277
249
- build_profile_remotely ( & data, derivation_name ) . await ?;
278
+ build_profile_remotely ( & data, & deriver ) . await ?;
250
279
} else {
251
- build_profile_locally ( & data, derivation_name ) . await ?;
280
+ build_profile_locally ( & data, & deriver ) . await ?;
252
281
}
253
282
254
283
Ok ( ( ) )
0 commit comments