@@ -10,12 +10,16 @@ pub const DEFAULT_MANIFEST_FILE: &str = "spin.toml";
1010
1111/// Attempts to find a manifest. If a path is provided, that path is resolved
1212/// using `resolve_manifest_file_path`; otherwise, a directory search is carried out
13- /// using `search_upwards_for_manifest`. If a manifest is found, a boolean is
14- /// also returned indicating if it was the default: this can be used to
15- /// notify the user that a non-default manifest is being used.
16- pub fn find_manifest_file_path ( provided_path : Option < impl AsRef < Path > > ) -> Result < ( PathBuf , bool ) > {
13+ /// using `search_upwards_for_manifest`. If we had to search, and a manifest is found,
14+ /// a (non-zero) usize is returned indicating how far above the current directory it
15+ /// was found. (A usize of 0 indicates that the manifest was provided or found
16+ /// in the current directory.) This can be used to notify the user that a
17+ /// non-default manifest is being used.
18+ pub fn find_manifest_file_path (
19+ provided_path : Option < impl AsRef < Path > > ,
20+ ) -> Result < ( PathBuf , usize ) > {
1721 match provided_path {
18- Some ( provided_path) => resolve_manifest_file_path ( provided_path) . map ( |p| ( p, true ) ) ,
22+ Some ( provided_path) => resolve_manifest_file_path ( provided_path) . map ( |p| ( p, 0 ) ) ,
1923 None => search_upwards_for_manifest ( )
2024 . ok_or_else ( || anyhow ! ( "\" {}\" not found" , DEFAULT_MANIFEST_FILE ) ) ,
2125 }
@@ -52,25 +56,38 @@ pub fn resolve_manifest_file_path(provided_path: impl AsRef<Path>) -> Result<Pat
5256/// Starting from the current directory, searches upward through
5357/// the directory tree for a manifest (that is, a file with the default
5458/// manifest name `spin.toml`). If found, the path to the manifest
55- /// is returned, with a boolean flag indicating if the found path was
56- /// the default (i.e. `spin.toml` in the current directory).
59+ /// is returned, with a usize indicating how far above the current directory it
60+ /// was found. (A usize of 0 indicates that the manifest was provided or found
61+ /// in the current directory.) This can be used to notify the user that a
62+ /// non-default manifest is being used.
5763/// If no matching file is found, the function returns None.
58- pub fn search_upwards_for_manifest ( ) -> Option < ( PathBuf , bool ) > {
59- let mut inferred_dir = std:: env:: current_dir ( ) . unwrap ( ) ;
60- let mut is_default = true ;
64+ ///
65+ /// The search is abandoned if it reaches the root directory, or the
66+ /// root of a Git repository, without finding a 'spin.toml'.
67+ pub fn search_upwards_for_manifest ( ) -> Option < ( PathBuf , usize ) > {
68+ let candidate = PathBuf :: from ( DEFAULT_MANIFEST_FILE ) ;
69+
70+ if candidate. is_file ( ) {
71+ return Some ( ( candidate, 0 ) ) ;
72+ }
6173
62- loop {
63- let candidate = inferred_dir. join ( DEFAULT_MANIFEST_FILE ) ;
74+ for distance in 1 ..20 {
75+ let inferred_dir = PathBuf :: from ( "../" . repeat ( distance) ) ;
76+ if !inferred_dir. is_dir ( ) {
77+ return None ;
78+ }
6479
80+ let candidate = inferred_dir. join ( DEFAULT_MANIFEST_FILE ) ;
6581 if candidate. is_file ( ) {
66- return Some ( ( candidate, is_default ) ) ;
82+ return Some ( ( candidate, distance ) ) ;
6783 }
6884
69- is_default = false ;
70- let parent = inferred_dir. parent ( ) ?;
71-
72- inferred_dir = parent. to_owned ( ) ;
85+ if is_git_root ( & inferred_dir) {
86+ return None ;
87+ }
7388 }
89+
90+ None
7491}
7592
7693/// Resolves the parent directory of a path, returning an error if the path
@@ -86,6 +103,10 @@ pub fn parent_dir(path: impl AsRef<Path>) -> Result<PathBuf> {
86103 Ok ( parent. into ( ) )
87104}
88105
106+ fn is_git_root ( dir : & Path ) -> bool {
107+ dir. join ( ".git" ) . is_dir ( )
108+ }
109+
89110#[ cfg( test) ]
90111mod tests {
91112 use super :: * ;
0 commit comments