@@ -8,7 +8,6 @@ use fs_err::tokio as tokio_fs;
8
8
use miette:: { Context , IntoDiagnostic } ;
9
9
use pixi_build_backend:: {
10
10
protocol:: { Protocol , ProtocolInstantiator } ,
11
- source:: Source ,
12
11
tools:: RattlerBuild ,
13
12
utils:: TemporaryRenderedRecipe ,
14
13
} ;
@@ -196,9 +195,11 @@ impl Protocol for RattlerBuildBackend {
196
195
solved_packages. push ( conda) ;
197
196
}
198
197
198
+ let input_globs = Some ( Vec :: from ( [ "recipe.yaml" . to_string ( ) ] ) ) ;
199
+
199
200
Ok ( CondaMetadataResult {
200
201
packages : solved_packages,
201
- input_globs : Some ( input_globs ( & self . recipe_source , None ) ) ,
202
+ input_globs,
202
203
} )
203
204
}
204
205
@@ -318,9 +319,22 @@ impl Protocol for RattlerBuildBackend {
318
319
} )
319
320
. await ?;
320
321
322
+ let package_sources = output. finalized_sources . as_ref ( ) . map ( |package_sources| {
323
+ package_sources
324
+ . iter ( )
325
+ . filter_map ( |source| {
326
+ if let rattler_build:: recipe:: parser:: Source :: Path ( path_source) = source {
327
+ Some ( path_source. path . clone ( ) )
328
+ } else {
329
+ None
330
+ }
331
+ } )
332
+ . collect ( )
333
+ } ) ;
334
+
321
335
built. push ( CondaBuiltPackage {
322
336
output_file : build_path,
323
- input_globs : input_globs ( & self . recipe_source , output . finalized_sources . as_ref ( ) ) ,
337
+ input_globs : build_input_globs ( & self . recipe_source . path , package_sources ) ? ,
324
338
name : output. name ( ) . as_normalized ( ) . to_string ( ) ,
325
339
version : output. version ( ) . to_string ( ) ,
326
340
build : build_string. to_string ( ) ,
@@ -331,40 +345,55 @@ impl Protocol for RattlerBuildBackend {
331
345
}
332
346
}
333
347
334
- fn input_globs (
335
- source : & Source ,
336
- package_sources : Option < & Vec < rattler_build:: recipe:: parser:: Source > > ,
337
- ) -> Vec < String > {
338
- let mut input_globs = vec ! [ ] ;
339
- let parent = if source. path . is_file ( ) {
348
+ /// Returns the relative path from `base` to `input`, joined by "/".
349
+ pub fn relative_path_joined (
350
+ base : & std:: path:: Path ,
351
+ input : & std:: path:: Path ,
352
+ ) -> miette:: Result < String > {
353
+ let rel = pathdiff:: diff_paths ( input, base) . ok_or_else ( || {
354
+ miette:: miette!(
355
+ "could not compute relative path from '{:?}' to '{:?}'" ,
356
+ input,
357
+ base
358
+ )
359
+ } ) ?;
360
+ let joined = rel
361
+ . components ( )
362
+ . map ( |c| c. as_os_str ( ) . to_string_lossy ( ) )
363
+ . collect :: < Vec < _ > > ( )
364
+ . join ( "/" ) ;
365
+ Ok ( joined)
366
+ }
367
+
368
+ fn build_input_globs (
369
+ source : & Path ,
370
+ package_sources : Option < Vec < PathBuf > > ,
371
+ ) -> miette:: Result < Vec < String > > {
372
+ // Always add the current directory of the package to the globs
373
+ let mut input_globs = vec ! [ "*/**" . to_string( ) ] ;
374
+
375
+ // Get parent directory path
376
+ let parent = if source. is_file ( ) {
340
377
// use the parent path as glob
341
- if let Some ( parent) = source. path . parent ( ) {
342
- parent. to_path_buf ( )
343
- } else {
344
- source. path . clone ( )
345
- }
378
+ source. parent ( ) . unwrap_or ( source) . to_path_buf ( )
346
379
} else {
347
380
// use the source path as glob
348
- source. path . clone ( )
381
+ source. to_path_buf ( )
349
382
} ;
350
383
351
- // add the source path as glob
352
- input_globs. push ( format ! ( "{}/**" , parent. display( ) ) ) ;
353
-
384
+ // If there are sources add them to the globs as well
354
385
if let Some ( package_sources) = package_sources {
355
386
for source in package_sources {
356
- if let rattler_build:: recipe:: parser:: Source :: Path ( path_source) = source {
357
- // add the package source path as glob
358
- if path_source. path . is_dir ( ) {
359
- input_globs. push ( format ! ( "{}/**" , path_source. path. display( ) ) ) ;
360
- } else {
361
- input_globs. push ( path_source. path . display ( ) . to_string ( ) ) ;
362
- }
387
+ let source_glob = relative_path_joined ( & parent, & source) ?;
388
+ if source. is_dir ( ) {
389
+ input_globs. push ( format ! ( "{}/**" , source_glob) ) ;
390
+ } else {
391
+ input_globs. push ( source_glob) ;
363
392
}
364
393
}
365
394
}
366
395
367
- input_globs
396
+ Ok ( input_globs)
368
397
}
369
398
370
399
#[ async_trait:: async_trait]
@@ -590,4 +619,101 @@ mod tests {
590
619
recipe
591
620
) ;
592
621
}
622
+
623
+ #[ test]
624
+ fn test_relative_path_joined ( ) {
625
+ use std:: path:: Path ;
626
+ // Simple case
627
+ let base = Path :: new ( "/foo/bar" ) ;
628
+ let input = Path :: new ( "/foo/bar/baz/qux.txt" ) ;
629
+ assert_eq ! (
630
+ super :: relative_path_joined( base, input) . unwrap( ) ,
631
+ "baz/qux.txt"
632
+ ) ;
633
+ // Same path
634
+ let base = Path :: new ( "/foo/bar" ) ;
635
+ let input = Path :: new ( "/foo/bar" ) ;
636
+ assert_eq ! ( super :: relative_path_joined( base, input) . unwrap( ) , "" ) ;
637
+ // Input not under base
638
+ let base = Path :: new ( "/foo/bar" ) ;
639
+ let input = Path :: new ( "/foo/other" ) ;
640
+ assert_eq ! (
641
+ super :: relative_path_joined( base, input) . unwrap( ) ,
642
+ "../other"
643
+ ) ;
644
+ // Relative paths
645
+ let base = Path :: new ( "foo/bar" ) ;
646
+ let input = Path :: new ( "foo/bar/baz" ) ;
647
+ assert_eq ! ( super :: relative_path_joined( base, input) . unwrap( ) , "baz" ) ;
648
+ }
649
+
650
+ #[ test]
651
+ #[ cfg( windows) ]
652
+ fn test_relative_path_joined_windows ( ) {
653
+ use std:: path:: Path ;
654
+ let base = Path :: new ( r"C:\foo\bar" ) ;
655
+ let input = Path :: new ( r"C:\foo\bar\baz\qux.txt" ) ;
656
+ assert_eq ! (
657
+ super :: relative_path_joined( base, input) . unwrap( ) ,
658
+ "baz/qux.txt"
659
+ ) ;
660
+ let base = Path :: new ( r"C:\foo\bar" ) ;
661
+ let input = Path :: new ( r"C:\foo\bar" ) ;
662
+ assert_eq ! ( super :: relative_path_joined( base, input) . unwrap( ) , "" ) ;
663
+ let base = Path :: new ( r"C:\foo\bar" ) ;
664
+ let input = Path :: new ( r"C:\foo\other" ) ;
665
+ assert_eq ! (
666
+ super :: relative_path_joined( base, input) . unwrap( ) ,
667
+ "../other"
668
+ ) ;
669
+ }
670
+
671
+ #[ test]
672
+ fn test_build_input_globs_with_tempdirs ( ) {
673
+ use std:: fs;
674
+ use tempfile:: tempdir;
675
+
676
+ // Create a temp directory to act as the base
677
+ let base_dir = tempdir ( ) . unwrap ( ) ;
678
+ let base_path = base_dir. path ( ) ;
679
+
680
+ // Case 1: source is a file in the base dir
681
+ let recipe_path = base_path. join ( "recipe.yaml" ) ;
682
+ fs:: write ( & recipe_path, "fake" ) . unwrap ( ) ;
683
+ let globs = super :: build_input_globs ( & recipe_path, None ) . unwrap ( ) ;
684
+ assert_eq ! ( globs, vec![ "*/**" ] ) ;
685
+
686
+ // Case 2: source is a directory, with a file and a dir as package sources
687
+ let pkg_dir = base_path. join ( "pkg" ) ;
688
+ let pkg_file = pkg_dir. join ( "file.txt" ) ;
689
+ let pkg_subdir = pkg_dir. join ( "dir" ) ;
690
+ fs:: create_dir_all ( & pkg_subdir) . unwrap ( ) ;
691
+ fs:: write ( & pkg_file, "fake" ) . unwrap ( ) ;
692
+ let globs =
693
+ super :: build_input_globs ( base_path, Some ( vec ! [ pkg_file. clone( ) , pkg_subdir. clone( ) ] ) )
694
+ . unwrap ( ) ;
695
+ assert_eq ! ( globs, vec![ "*/**" , "pkg/file.txt" , "pkg/dir/**" ] ) ;
696
+ }
697
+
698
+ #[ test]
699
+ fn test_build_input_globs_two_folders_in_tempdir ( ) {
700
+ use std:: fs;
701
+ use tempfile:: tempdir;
702
+
703
+ // Create a temp directory
704
+ let temp = tempdir ( ) . unwrap ( ) ;
705
+ let temp_path = temp. path ( ) ;
706
+
707
+ // Create two folders: source_dir and package_source_dir
708
+ let source_dir = temp_path. join ( "source" ) ;
709
+ let package_source_dir = temp_path. join ( "pkgsrc" ) ;
710
+ fs:: create_dir_all ( & source_dir) . unwrap ( ) ;
711
+ fs:: create_dir_all ( & package_source_dir) . unwrap ( ) ;
712
+
713
+ // Call build_input_globs with source_dir as source, and package_source_dir as package source
714
+ let globs =
715
+ super :: build_input_globs ( & source_dir, Some ( vec ! [ package_source_dir. clone( ) ] ) ) . unwrap ( ) ;
716
+ // The relative path from source_dir to package_source_dir should be "../pkgsrc/**"
717
+ assert_eq ! ( globs, vec![ "*/**" , "../pkgsrc/**" ] ) ;
718
+ }
593
719
}
0 commit comments