@@ -3,7 +3,7 @@ use std::path::Path;
3
3
/// Common knowledge about the worktree that is needed across most interactions with the work tree
4
4
#[ cfg_attr( feature = "serde1" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
5
5
#[ derive( PartialEq , Eq , Debug , Hash , Ord , PartialOrd , Clone , Copy ) ]
6
- pub struct Context {
6
+ pub struct Capabilities {
7
7
/// If true, the filesystem will store paths as decomposed unicode, i.e. `ä` becomes `"a\u{308}"`, which means that
8
8
/// we have to turn these forms back from decomposed to precomposed unicode before storing it in the index or generally
9
9
/// using it. This also applies to input received from the command-line, so callers may have to be aware of this and
@@ -15,29 +15,50 @@ pub struct Context {
15
15
pub ignore_case : bool ,
16
16
/// If true, we assume the the executable bit is honored as part of the files mode. If false, we assume the file system
17
17
/// ignores the executable bit, hence it will be reported as 'off' even though we just tried to set it to be on.
18
- pub file_mode : bool ,
18
+ pub executable_bit : bool ,
19
19
/// If true, the file system supports symbolic links and we should try to create them. Otherwise symbolic links will be checked
20
20
/// out as files which contain the link as text.
21
21
pub symlink : bool ,
22
22
}
23
23
24
- impl Context {
24
+ impl Capabilities {
25
25
/// try to determine all values in this context by probing them in the given `git_dir`, which
26
26
/// should be on the file system the git repository is located on.
27
27
/// `git_dir` is a typical git repository, expected to be populated with the typical files like `config`.
28
28
///
29
29
/// All errors are ignored and interpreted on top of the default for the platform the binary is compiled for.
30
- pub fn probe ( git_dir : impl AsRef < std :: path :: Path > ) -> Self {
30
+ pub fn probe ( git_dir : impl AsRef < Path > ) -> Self {
31
31
let root = git_dir. as_ref ( ) ;
32
- let ctx = Context :: default ( ) ;
33
- Context {
32
+ let ctx = Capabilities :: default ( ) ;
33
+ Capabilities {
34
34
symlink : Self :: probe_symlink ( root) . unwrap_or ( ctx. symlink ) ,
35
35
ignore_case : Self :: probe_ignore_case ( root) . unwrap_or ( ctx. ignore_case ) ,
36
36
precompose_unicode : Self :: probe_precompose_unicode ( root) . unwrap_or ( ctx. precompose_unicode ) ,
37
- .. ctx
37
+ executable_bit : Self :: probe_file_mode ( root ) . unwrap_or ( ctx. executable_bit ) ,
38
38
}
39
39
}
40
40
41
+ #[ cfg( unix) ]
42
+ fn probe_file_mode ( root : & Path ) -> std:: io:: Result < bool > {
43
+ use std:: os:: unix:: fs:: { MetadataExt , OpenOptionsExt } ;
44
+
45
+ // test it exactly as we typically create executable files, not using chmod.
46
+ let test_path = root. join ( "_test_executable_bit" ) ;
47
+ let res = std:: fs:: OpenOptions :: new ( )
48
+ . create_new ( true )
49
+ . write ( true )
50
+ . mode ( 0o777 )
51
+ . open ( & test_path)
52
+ . and_then ( |f| f. metadata ( ) . map ( |m| m. mode ( ) & 0o100 == 0o100 ) ) ;
53
+ std:: fs:: remove_file ( test_path) ?;
54
+ res
55
+ }
56
+
57
+ #[ cfg( not( unix) ) ]
58
+ fn probe_file_mode ( root : & Path ) -> std:: io:: Result < bool > {
59
+ Ok ( false )
60
+ }
61
+
41
62
fn probe_ignore_case ( git_dir : & Path ) -> std:: io:: Result < bool > {
42
63
std:: fs:: metadata ( git_dir. join ( "cOnFiG" ) ) . map ( |_| true ) . or_else ( |err| {
43
64
if err. kind ( ) == std:: io:: ErrorKind :: NotFound {
@@ -84,36 +105,36 @@ impl Context {
84
105
}
85
106
86
107
#[ cfg( windows) ]
87
- impl Default for Context {
108
+ impl Default for Capabilities {
88
109
fn default ( ) -> Self {
89
- Context {
110
+ Capabilities {
90
111
precompose_unicode : false ,
91
112
ignore_case : true ,
92
- file_mode : false ,
113
+ executable_bit : false ,
93
114
symlink : false ,
94
115
}
95
116
}
96
117
}
97
118
98
119
#[ cfg( target_os = "macos" ) ]
99
- impl Default for Context {
120
+ impl Default for Capabilities {
100
121
fn default ( ) -> Self {
101
- Context {
122
+ Capabilities {
102
123
precompose_unicode : true ,
103
124
ignore_case : true ,
104
- file_mode : true ,
125
+ executable_bit : true ,
105
126
symlink : true ,
106
127
}
107
128
}
108
129
}
109
130
110
131
#[ cfg( all( unix, not( target_os = "macos" ) ) ) ]
111
- impl Default for Context {
132
+ impl Default for Capabilities {
112
133
fn default ( ) -> Self {
113
- Context {
134
+ Capabilities {
114
135
precompose_unicode : false ,
115
136
ignore_case : false ,
116
- file_mode : true ,
137
+ executable_bit : true ,
117
138
symlink : true ,
118
139
}
119
140
}
0 commit comments