1111use std;
1212use std:: collections:: { BTreeMap , BTreeSet , HashMap } ;
1313use std:: fmt;
14+ use std:: fs:: File ;
1415use std:: hash:: Hash ;
16+ use std:: io:: { BufRead , BufReader } ;
1517use std:: path:: { Path , PathBuf } ;
1618use std:: str:: FromStr ;
1719
@@ -600,6 +602,10 @@ pub struct PartialSources {
600602 pub defines : Option < IndexMap < String , Option < String > > > ,
601603 /// The source file paths.
602604 pub files : Vec < PartialSourceFile > ,
605+ /// The list of external flists to include.
606+ pub external_flists : Option < Vec < String > > ,
607+ /// The absolute prefix for the external flists to include. Not intended to be user-modifiable.
608+ pub external_flist_prefix : Option < PathBuf > ,
603609 /// Unknown extra fields
604610 #[ serde( flatten) ]
605611 extra : HashMap < String , Value > ,
@@ -614,6 +620,8 @@ impl PartialSources {
614620 include_dirs : None ,
615621 defines : None ,
616622 files : Vec :: new ( ) ,
623+ external_flists : None ,
624+ external_flist_prefix : None ,
617625 extra : HashMap :: new ( ) ,
618626 }
619627 }
@@ -626,6 +634,11 @@ impl PrefixPaths for PartialSources {
626634 include_dirs : self . include_dirs . prefix_paths ( prefix) ?,
627635 defines : self . defines ,
628636 files : self . files . prefix_paths ( prefix) ?,
637+ external_flists : self . external_flists . prefix_paths ( prefix) ?,
638+ external_flist_prefix : match self . external_flist_prefix {
639+ Some ( _) => self . external_flist_prefix . prefix_paths ( prefix) ?,
640+ None => Some ( prefix. to_path_buf ( ) ) ,
641+ } ,
629642 extra : self . extra ,
630643 } )
631644 }
@@ -638,6 +651,8 @@ impl From<Vec<PartialSourceFile>> for PartialSources {
638651 include_dirs : None ,
639652 defines : None ,
640653 files : v,
654+ external_flists : None ,
655+ external_flist_prefix : None ,
641656 extra : HashMap :: new ( ) ,
642657 }
643658 }
@@ -647,9 +662,103 @@ impl Validate for PartialSources {
647662 type Output = Sources ;
648663 type Error = Error ;
649664 fn validate ( self , package_name : & str , pre_output : bool ) -> Result < Sources > {
665+ let external_flists: Result < Vec < _ > > = self
666+ . external_flists
667+ . clone ( )
668+ . unwrap_or_default ( )
669+ . iter ( )
670+ . map ( |path| env_path_from_string ( path. to_string ( ) ) )
671+ . collect ( ) ;
672+
673+ let external_flist_list: Result < Vec < Vec < String > > > = external_flists?
674+ . into_iter ( )
675+ . map ( |filename| {
676+ let file = File :: open ( & filename) . map_err ( |cause| {
677+ Error :: chain (
678+ format ! ( "Unable to open external flist file {:?}" , filename) ,
679+ cause,
680+ )
681+ } ) ?;
682+ let reader = BufReader :: new ( file) ;
683+ let lines: Vec < String > = reader
684+ . lines ( )
685+ . map ( |line| {
686+ line. map_err ( |cause| {
687+ Error :: chain (
688+ format ! ( "Error reading external flist file {:?}" , filename) ,
689+ cause,
690+ )
691+ } )
692+ } )
693+ . collect :: < Result < Vec < String > > > ( ) ?;
694+ Ok ( lines)
695+ } )
696+ . collect ( ) ;
697+
698+ let external_flist_groups: Result < Vec < PartialSourceFile > > = external_flist_list?
699+ . into_iter ( )
700+ . map ( |flist| {
701+ Ok ( PartialSourceFile :: Group ( Box :: new ( PartialSources {
702+ target : None ,
703+ include_dirs : Some (
704+ flist
705+ . clone ( )
706+ . into_iter ( )
707+ . filter_map ( |file| {
708+ if file. starts_with ( "+incdir+" ) {
709+ Some ( file. trim_start_matches ( "+incdir+" ) . to_string ( ) )
710+ } else {
711+ None
712+ }
713+ } )
714+ . map ( |dir| {
715+ dir. prefix_paths ( self . external_flist_prefix . as_ref ( ) . unwrap ( ) )
716+ } )
717+ . collect :: < Result < _ > > ( ) ?,
718+ ) ,
719+ defines : Some (
720+ flist
721+ . clone ( )
722+ . into_iter ( )
723+ . filter_map ( |file| {
724+ if let Some ( stripped) = file. strip_prefix ( "+define+" ) {
725+ if let Some ( eq_idx) = stripped. find ( "=" ) {
726+ Some ( (
727+ stripped[ ..eq_idx] . to_string ( ) ,
728+ Some ( stripped[ eq_idx + 1 ..] . to_string ( ) ) ,
729+ ) )
730+ } else {
731+ Some ( ( stripped. to_string ( ) , None ) )
732+ }
733+ } else {
734+ None
735+ }
736+ } )
737+ . collect ( ) ,
738+ ) ,
739+ files : flist
740+ . into_iter ( )
741+ . filter_map ( |file| {
742+ if file. starts_with ( "+" ) {
743+ None
744+ } else {
745+ // prefix path
746+ Some ( PartialSourceFile :: File ( file) )
747+ }
748+ } )
749+ . map ( |file| file. prefix_paths ( self . external_flist_prefix . as_ref ( ) . unwrap ( ) ) )
750+ . collect :: < Result < Vec < _ > > > ( ) ?,
751+ external_flists : None ,
752+ external_flist_prefix : None ,
753+ extra : HashMap :: new ( ) ,
754+ } ) ) )
755+ } )
756+ . collect ( ) ;
757+
650758 let post_env_files: Vec < PartialSourceFile > = self
651759 . files
652760 . into_iter ( )
761+ . chain ( external_flist_groups?. into_iter ( ) )
653762 . map ( |file| match file {
654763 PartialSourceFile :: File ( file) => {
655764 Ok ( PartialSourceFile :: File ( env_string_from_string ( file) ?) )
@@ -680,6 +789,7 @@ impl Validate for PartialSources {
680789 . iter ( )
681790 . map ( |path| env_path_from_string ( path. to_string ( ) ) )
682791 . collect ( ) ;
792+
683793 let defines = self . defines . unwrap_or_default ( ) ;
684794 let files: Result < Vec < _ > > = post_glob_files
685795 . into_iter ( )
0 commit comments