@@ -8,6 +8,12 @@ pub enum Error {
8
8
InaccessibleDirectory { path : PathBuf } ,
9
9
#[ error( "Could find a git repository in '{}' or in any of its parents" , . path. display( ) ) ]
10
10
NoGitRepository { path : PathBuf } ,
11
+ #[ error( "Could find a trusted git repository in '{}' or in any of its parents, candidate at '{}' discarded" , . path. display( ) , . candidate. display( ) ) ]
12
+ NoTrustedGitRepository {
13
+ path : PathBuf ,
14
+ candidate : PathBuf ,
15
+ required : git_sec:: Trust ,
16
+ } ,
11
17
#[ error( "Could not determine trust level for path '{}'." , . path. display( ) ) ]
12
18
CheckTrust {
13
19
path : PathBuf ,
@@ -37,6 +43,7 @@ impl Default for Options {
37
43
pub ( crate ) mod function {
38
44
use super :: { Error , Options } ;
39
45
use git_sec:: Trust ;
46
+ use std:: path:: PathBuf ;
40
47
use std:: {
41
48
borrow:: Cow ,
42
49
path:: { Component , Path } ,
@@ -57,23 +64,20 @@ pub(crate) mod function {
57
64
// us the parent directory. (`Path::parent` just strips off the last
58
65
// path component, which means it will not do what you expect when
59
66
// working with paths paths that contain '..'.)
60
- let directory = maybe_canonicalize ( directory. as_ref ( ) ) . map_err ( |_| Error :: InaccessibleDirectory {
61
- path : directory. as_ref ( ) . into ( ) ,
62
- } ) ?;
63
- if !directory. is_dir ( ) {
64
- return Err ( Error :: InaccessibleDirectory {
65
- path : directory. into_owned ( ) ,
66
- } ) ;
67
+ let directory = directory. as_ref ( ) ;
68
+ let dir = maybe_canonicalize ( directory) . map_err ( |_| Error :: InaccessibleDirectory { path : directory. into ( ) } ) ?;
69
+ let is_canonicalized = dir. as_ref ( ) != directory;
70
+ if !dir. is_dir ( ) {
71
+ return Err ( Error :: InaccessibleDirectory { path : dir. into_owned ( ) } ) ;
67
72
}
68
73
69
- let filter_by_trust =
70
- |x : & std:: path:: Path , kind : crate :: path:: Kind | -> Result < Option < ( crate :: Path , git_sec:: Trust ) > , Error > {
71
- let trust =
72
- git_sec:: Trust :: from_path_ownership ( x) . map_err ( |err| Error :: CheckTrust { path : x. into ( ) , err } ) ?;
73
- Ok ( ( trust >= required_trust) . then ( || ( crate :: Path :: from_dot_git_dir ( x, kind) , trust) ) )
74
- } ;
74
+ let filter_by_trust = |x : & std:: path:: Path | -> Result < Option < git_sec:: Trust > , Error > {
75
+ let trust =
76
+ git_sec:: Trust :: from_path_ownership ( x) . map_err ( |err| Error :: CheckTrust { path : x. into ( ) , err } ) ?;
77
+ Ok ( ( trust >= required_trust) . then ( || ( trust) ) )
78
+ } ;
75
79
76
- let mut cursor = directory . clone ( ) ;
80
+ let mut cursor = dir . clone ( ) ;
77
81
' outer: loop {
78
82
for append_dot_git in & [ false , true ] {
79
83
if * append_dot_git {
@@ -83,11 +87,38 @@ pub(crate) mod function {
83
87
}
84
88
}
85
89
if let Ok ( kind) = path:: is:: git ( & cursor) {
86
- match filter_by_trust ( & cursor, kind) ? {
87
- Some ( res) => break ' outer Ok ( res) ,
90
+ match filter_by_trust ( & cursor) ? {
91
+ Some ( trust) => {
92
+ // TODO: test this more
93
+ let path = if is_canonicalized {
94
+ match std:: env:: current_dir ( ) {
95
+ Ok ( cwd) => {
96
+ let short_path_components = cwd
97
+ . strip_prefix ( & cursor. parent ( ) . expect ( ".git appended" ) )
98
+ . expect ( "cwd is always within canonicalized candidate" )
99
+ . components ( )
100
+ . count ( ) ;
101
+ if short_path_components < cursor. components ( ) . count ( ) {
102
+ let mut p = PathBuf :: new ( ) ;
103
+ p. extend ( std:: iter:: repeat ( ".." ) . take ( short_path_components) ) ;
104
+ p. push ( ".git" ) ;
105
+ p
106
+ } else {
107
+ cursor. into_owned ( )
108
+ }
109
+ }
110
+ Err ( _) => cursor. into_owned ( ) ,
111
+ }
112
+ } else {
113
+ cursor. into_owned ( )
114
+ } ;
115
+ break ' outer Ok ( ( crate :: Path :: from_dot_git_dir ( path, kind) , trust) ) ;
116
+ }
88
117
None => {
89
- break ' outer Err ( Error :: NoGitRepository {
90
- path : directory. into_owned ( ) ,
118
+ break ' outer Err ( Error :: NoTrustedGitRepository {
119
+ path : dir. into_owned ( ) ,
120
+ candidate : cursor. into_owned ( ) ,
121
+ required : required_trust,
91
122
} )
92
123
}
93
124
}
@@ -100,11 +131,7 @@ pub(crate) mod function {
100
131
}
101
132
match cursor. parent ( ) {
102
133
Some ( parent) => cursor = parent. to_owned ( ) . into ( ) ,
103
- None => {
104
- break Err ( Error :: NoGitRepository {
105
- path : directory. into_owned ( ) ,
106
- } )
107
- }
134
+ None => break Err ( Error :: NoGitRepository { path : dir. into_owned ( ) } ) ,
108
135
}
109
136
}
110
137
}
0 commit comments