@@ -20,7 +20,23 @@ pub fn bare(git_dir_candidate: impl AsRef<Path>) -> bool {
20
20
/// * an objects directory
21
21
/// * a refs directory
22
22
pub fn git ( git_dir : impl AsRef < Path > ) -> Result < crate :: repository:: Kind , crate :: is_git:: Error > {
23
- let ( dot_git, common_dir, git_dir_is_linked_worktree) = match crate :: path:: from_gitdir_file ( git_dir. as_ref ( ) ) {
23
+ #[ derive( Eq , PartialEq ) ]
24
+ enum Kind {
25
+ MaybeRepo ,
26
+ LinkedWorkTreeDir ,
27
+ WorkTreeGitDir { work_dir : std:: path:: PathBuf } ,
28
+ }
29
+ #[ cfg( not( windows) ) ]
30
+ fn is_directory ( err : & std:: io:: Error ) -> bool {
31
+ err. raw_os_error ( ) == Some ( 21 )
32
+ }
33
+ // TODO: use ::IsDirectory as well when stabilized, but it's permission denied on windows
34
+ #[ cfg( windows) ]
35
+ fn is_directory ( err : & std:: io:: Error ) -> bool {
36
+ err. kind ( ) == std:: io:: ErrorKind :: PermissionDenied
37
+ }
38
+ let git_dir = git_dir. as_ref ( ) ;
39
+ let ( dot_git, common_dir, kind) = match crate :: path:: from_gitdir_file ( git_dir) {
24
40
Ok ( private_git_dir) => {
25
41
let common_dir = private_git_dir. join ( "commondir" ) ;
26
42
let common_dir = crate :: path:: from_plain_file ( & common_dir)
@@ -29,16 +45,31 @@ pub fn git(git_dir: impl AsRef<Path>) -> Result<crate::repository::Kind, crate::
29
45
} ) ?
30
46
. map_err ( |_| crate :: is_git:: Error :: MissingCommonDir { missing : common_dir } ) ?;
31
47
let common_dir = private_git_dir. join ( common_dir) ;
32
- ( Cow :: Owned ( private_git_dir) , Cow :: Owned ( common_dir) , true )
33
- }
34
- // TODO: use ::IsDirectory as well when stabilized, but it's permission denied on windows
35
- #[ cfg( not( windows) ) ]
36
- Err ( crate :: path:: from_gitdir_file:: Error :: Io ( err) ) if err. raw_os_error ( ) == Some ( 21 ) => {
37
- ( Cow :: Borrowed ( git_dir. as_ref ( ) ) , Cow :: Borrowed ( git_dir. as_ref ( ) ) , false )
48
+ (
49
+ Cow :: Owned ( private_git_dir) ,
50
+ Cow :: Owned ( common_dir) ,
51
+ Kind :: LinkedWorkTreeDir ,
52
+ )
38
53
}
39
- #[ cfg( windows) ]
40
- Err ( crate :: path:: from_gitdir_file:: Error :: Io ( err) ) if err. kind ( ) == std:: io:: ErrorKind :: PermissionDenied => {
41
- ( Cow :: Borrowed ( git_dir. as_ref ( ) ) , Cow :: Borrowed ( git_dir. as_ref ( ) ) , false )
54
+ Err ( crate :: path:: from_gitdir_file:: Error :: Io ( err) ) if is_directory ( & err) => {
55
+ let common_dir = git_dir. join ( "commondir" ) ;
56
+ match crate :: path:: from_plain_file ( common_dir)
57
+ . and_then ( Result :: ok)
58
+ . and_then ( |cd| {
59
+ crate :: path:: from_plain_file ( git_dir. join ( "gitdir" ) )
60
+ . and_then ( Result :: ok)
61
+ . map ( |worktree_gitfile| ( crate :: path:: without_dot_git_dir ( worktree_gitfile) , cd) )
62
+ } ) {
63
+ Some ( ( work_dir, common_dir) ) => {
64
+ let common_dir = git_dir. join ( common_dir) ;
65
+ (
66
+ Cow :: Borrowed ( git_dir) ,
67
+ Cow :: Owned ( common_dir) ,
68
+ Kind :: WorkTreeGitDir { work_dir } ,
69
+ )
70
+ }
71
+ None => ( Cow :: Borrowed ( git_dir) , Cow :: Borrowed ( git_dir) , Kind :: MaybeRepo ) ,
72
+ }
42
73
}
43
74
Err ( err) => return Err ( err. into ( ) ) ,
44
75
} ;
@@ -74,13 +105,17 @@ pub fn git(git_dir: impl AsRef<Path>) -> Result<crate::repository::Kind, crate::
74
105
}
75
106
}
76
107
77
- Ok ( if git_dir_is_linked_worktree {
78
- crate :: repository:: Kind :: WorkTree {
108
+ Ok ( match kind {
109
+ Kind :: LinkedWorkTreeDir => crate :: repository:: Kind :: WorkTree {
79
110
linked_git_dir : Some ( dot_git. into_owned ( ) ) ,
111
+ } ,
112
+ Kind :: WorkTreeGitDir { work_dir } => crate :: repository:: Kind :: WorkTreeGitDir { work_dir } ,
113
+ Kind :: MaybeRepo => {
114
+ if bare ( git_dir) {
115
+ crate :: repository:: Kind :: Bare
116
+ } else {
117
+ crate :: repository:: Kind :: WorkTree { linked_git_dir : None }
118
+ }
80
119
}
81
- } else if bare ( git_dir) {
82
- crate :: repository:: Kind :: Bare
83
- } else {
84
- crate :: repository:: Kind :: WorkTree { linked_git_dir : None }
85
120
} )
86
121
}
0 commit comments