@@ -72,6 +72,25 @@ struct Outputs {
7272 out : String ,
7373}
7474
75+ fn is_target_for_packaging ( src_dir : PathBuf ) -> bool {
76+ let has_cargo = src_dir. join ( "Cargo.toml" ) . is_file ( ) ;
77+ let cargo_lock = File :: open ( src_dir. join ( "Cargo.lock" ) ) ;
78+ let has_cargo_lock = cargo_lock. is_ok ( ) ;
79+ let has_cmake = src_dir. join ( "CMakeLists.txt" ) . is_file ( ) ;
80+ let has_go = src_dir. join ( "go.mod" ) . is_file ( ) ;
81+ let has_meson = src_dir. join ( "meson.build" ) . is_file ( ) ;
82+ let pyproject_toml = src_dir. join ( "pyproject.toml" ) ;
83+ let has_pyproject = pyproject_toml. is_file ( ) ;
84+ let has_setuptools = src_dir. join ( "setup.py" ) . is_file ( ) ;
85+
86+ ( has_cargo && has_cargo_lock)
87+ || has_cmake
88+ || has_go
89+ || has_meson
90+ || has_pyproject
91+ || has_setuptools
92+ }
93+
7594#[ tokio:: main]
7695async fn main ( ) -> Result < ( ) > {
7796 run ( ) . await
@@ -394,7 +413,77 @@ async fn run() -> Result<()> {
394413 PathBuf :: from ( & src)
395414 } ;
396415
397- let mut choices = Vec :: new ( ) ;
416+ // Let's first find all subdirectories that are compatible with our supported recipes.
417+ let root_src_dir = src_dir. clone ( ) ;
418+ let mut open_subdirs = vec ! [ ( 0 , src_dir) ] ;
419+ let mut sourceroot_candidates = vec ! [ ] ;
420+ while !open_subdirs. is_empty ( ) {
421+ // If we call this, we have a non-empty vector.
422+ let ( depth, target_dir) = open_subdirs. pop ( ) . unwrap ( ) ;
423+ let subdirs = std:: fs:: read_dir ( & target_dir) . with_context ( || {
424+ format ! ( "failed to list subdirectories of {}" , target_dir. display( ) )
425+ } ) ?;
426+
427+ for maybe_subdir in subdirs {
428+ let subdir = maybe_subdir. context ( format ! (
429+ "unexpected io error while reading a subdirectory of {}" ,
430+ target_dir. to_string_lossy( )
431+ ) ) ?;
432+
433+ let subdir_path = subdir. path ( ) ;
434+
435+ // We want only subdirectories.
436+ if !subdir_path. is_dir ( ) {
437+ continue ;
438+ }
439+
440+ if is_target_for_packaging ( subdir_path) {
441+ sourceroot_candidates. push ( subdir. file_name ( ) ) ;
442+ }
443+
444+ // Recurse into that subdir.
445+ if depth < 3 {
446+ open_subdirs. push ( ( depth + 1 , subdir_path) ) ;
447+ }
448+ }
449+ }
450+
451+ editor. set_helper ( Some ( Prompter :: List (
452+ sourceroot_candidates
453+ . iter ( )
454+ . map ( |sr| {
455+ sr. strip_prefix ( & root_src_dir)
456+ . expect ( "Failed to strip the root source directory prefix" )
457+ . to_string_lossy ( )
458+ . to_string ( )
459+ } )
460+ . collect ( ) ,
461+ ) ) ) ;
462+ let choice = editor. readline ( & prompt ( "Which subdirectory should we use?" ) ) ?;
463+ //let Some(Prompter::List(_choices)) = editor.helper_mut() else {
464+ // unreachable!();
465+ //};
466+ let src_dir = choice
467+ . parse ( )
468+ . ok ( )
469+ . and_then ( |i : usize | sourceroot_candidates. get ( i) )
470+ . unwrap_or_else ( || & sourceroot_candidates[ 0 ] ) ;
471+ let source_root = if src_dir != & root_src_dir {
472+ Some ( src_dir)
473+ } else {
474+ None
475+ } ;
476+ let source_root_expr = match source_root {
477+ Some ( subdir) => format ! (
478+ "\n sourceRoot = \" source/{}\" ;" ,
479+ subdir
480+ . strip_prefix( & root_src_dir)
481+ . expect( "Failed to strip the root source directory prefix" )
482+ . to_string_lossy( )
483+ ) ,
484+ None => "" . to_string ( ) ,
485+ } ;
486+
398487 let has_cargo = src_dir. join ( "Cargo.toml" ) . is_file ( ) ;
399488 let cargo_lock = File :: open ( src_dir. join ( "Cargo.lock" ) ) ;
400489 let has_cargo_lock = cargo_lock. is_ok ( ) ;
@@ -405,6 +494,7 @@ async fn run() -> Result<()> {
405494 let has_pyproject = pyproject_toml. is_file ( ) ;
406495 let has_setuptools = src_dir. join ( "setup.py" ) . is_file ( ) ;
407496
497+ let mut choices = Vec :: new ( ) ;
408498 let rust_vendors = if has_cargo {
409499 if cargo_lock. map_or ( true , |file| {
410500 BufReader :: new ( file)
@@ -454,7 +544,6 @@ async fn run() -> Result<()> {
454544 }
455545
456546 choices. push ( BuildType :: MkDerivation { rust : None } ) ;
457-
458547 editor. set_helper ( Some ( Prompter :: Build ( choices) ) ) ;
459548 let choice = editor. readline ( & prompt ( "How should this package be built?" ) ) ?;
460549 let Some ( Prompter :: Build ( choices) ) = editor. helper_mut ( ) else {
@@ -564,7 +653,7 @@ async fn run() -> Result<()> {
564653 pname = {pname:?};
565654 version = {version:?};
566655
567- src = {src_expr};
656+ src = {src_expr};{source_root_expr}
568657
569658 vendorHash = {hash};
570659
@@ -653,7 +742,7 @@ async fn run() -> Result<()> {
653742 version = {version:?};
654743 format = "{format}";
655744
656- src = {src_expr};
745+ src = {src_expr};{source_root_expr}
657746
658747 "# ,
659748 if application {
@@ -712,7 +801,7 @@ async fn run() -> Result<()> {
712801 pname = {pname:?};
713802 version = {version:?};
714803
715- src = {src_expr};
804+ src = {src_expr};{source_root_expr}
716805
717806 cargoHash = "{hash}";
718807
@@ -742,7 +831,7 @@ async fn run() -> Result<()> {
742831 pname = "{pname}";
743832 version = "{version}";
744833
745- src = {src_expr};
834+ src = {src_expr};{source_root_expr}
746835
747836 cargoLock = "# ,
748837 ) ?;
@@ -762,6 +851,7 @@ async fn run() -> Result<()> {
762851 version = {version:?};
763852
764853 src = {src_expr};
854+ {source_root_expr}
765855
766856 "# ,
767857 ) ?;
@@ -791,7 +881,7 @@ async fn run() -> Result<()> {
791881 pname = {pname:?};
792882 version = {version:?};
793883
794- src = {src_expr};
884+ src = {src_expr};{source_root_expr}
795885
796886 cargoDeps = rustPlatform.fetchCargoTarball {{
797887 inherit src;
@@ -824,7 +914,7 @@ async fn run() -> Result<()> {
824914 pname = "{pname}";
825915 version = "{version}";
826916
827- src = {src_expr};
917+ src = {src_expr};{source_root_expr}
828918
829919 cargoDeps = rustPlatform.importCargoLock "# ,
830920 ) ?;
@@ -908,7 +998,7 @@ async fn run() -> Result<()> {
908998 }
909999
9101000 let mut desc = desc. trim_matches ( |c : char | !c. is_alphanumeric ( ) ) . to_owned ( ) ;
911- desc. get_mut ( 0 .. 1 ) . map ( str:: make_ascii_uppercase) ;
1001+ desc. get_mut ( 0 .. 1 ) . map ( str:: make_ascii_uppercase) ;
9121002 write ! ( out, " " ) ?;
9131003 writedoc ! (
9141004 out,
@@ -1022,5 +1112,5 @@ fn get_version(rev: &str) -> &str {
10221112}
10231113
10241114fn get_version_number ( rev : & str ) -> & str {
1025- & rev[ rev. find ( char:: is_numeric) . unwrap_or_default ( ) ..]
1115+ & rev[ rev. find ( char:: is_numeric) . unwrap_or_default ( ) ..]
10261116}
0 commit comments