@@ -9,7 +9,9 @@ use anyhow::{anyhow, Context, Result};
9
9
use crate :: wrap:: Message ;
10
10
11
11
/// Find path to hook script given a hook name.
12
- fn get_hook_path ( repo : & gix:: Repository , hook_name : & str ) -> Result < PathBuf > {
12
+ ///
13
+ /// Returns None if the hook script is not found or is not executable.
14
+ fn get_hook_path ( repo : & gix:: Repository , hook_name : & str ) -> Result < Option < PathBuf > > {
13
15
let config = repo. config_snapshot ( ) ;
14
16
let hooks_path =
15
17
if let Some ( core_hooks_path) = config. trusted_path ( "core.hookspath" ) . transpose ( ) ? {
@@ -27,7 +29,20 @@ fn get_hook_path(repo: &gix::Repository, hook_name: &str) -> Result<PathBuf> {
27
29
// No core.hookspath, use default .git/hooks location
28
30
Cow :: Owned ( repo. common_dir ( ) . join ( "hooks" ) )
29
31
} ;
30
- Ok ( hooks_path. join ( hook_name) )
32
+ let hook_path = hooks_path. join ( hook_name) ;
33
+
34
+ let hook_meta = match std:: fs:: metadata ( & hook_path) {
35
+ Ok ( meta) => meta,
36
+ Err ( _) => return Ok ( None ) , // ignore missing hook
37
+ } ;
38
+
39
+ if !is_executable ( & hook_meta) {
40
+ return Ok ( None ) ;
41
+ }
42
+
43
+ let hook_path = gix:: path:: realpath ( hook_path) ?;
44
+
45
+ Ok ( Some ( hook_path) )
31
46
}
32
47
33
48
/// Run the git `pre-commit` hook script.
@@ -40,25 +55,17 @@ fn get_hook_path(repo: &gix::Repository, hook_name: &str) -> Result<PathBuf> {
40
55
/// existing, not being a file, or not being executable.
41
56
pub ( crate ) fn run_pre_commit_hook ( repo : & gix:: Repository , use_editor : bool ) -> Result < bool > {
42
57
let hook_name = "pre-commit" ;
43
- let hook_path = get_hook_path ( repo, hook_name) ?;
44
- let hook_meta = match std:: fs:: metadata ( & hook_path) {
45
- Ok ( meta) => meta,
46
- Err ( _) => return Ok ( false ) , // ignore missing hook
47
- } ;
48
-
49
- if !hook_meta. is_file ( ) {
50
- return Ok ( false ) ;
51
- }
52
-
53
- // Ignore non-executable hooks
54
- if !is_executable ( & hook_meta) {
58
+ let hook_path = if let Some ( hook_path) = get_hook_path ( repo, hook_name) ? {
59
+ hook_path
60
+ } else {
55
61
return Ok ( false ) ;
56
- }
62
+ } ;
57
63
58
- let mut hook_command = std:: process:: Command :: new ( gix:: path:: realpath ( hook_path) ?) ;
59
64
let workdir = repo
60
65
. work_dir ( )
61
66
. expect ( "should not get this far with a bare repo" ) ;
67
+
68
+ let mut hook_command = std:: process:: Command :: new ( hook_path) ;
62
69
if !use_editor {
63
70
hook_command. env ( "GIT_EDITOR" , ":" ) ;
64
71
}
@@ -95,20 +102,11 @@ pub(crate) fn run_commit_msg_hook<'repo>(
95
102
use_editor : bool ,
96
103
) -> Result < Message < ' repo > > {
97
104
let hook_name = "commit-msg" ;
98
- let hook_path = get_hook_path ( repo, hook_name) ?;
99
- let hook_meta = match std:: fs:: metadata ( & hook_path) {
100
- Ok ( meta) => meta,
101
- Err ( _) => return Ok ( message) , // ignore missing hook
102
- } ;
103
-
104
- if !hook_meta. is_file ( ) {
105
- return Ok ( message) ;
106
- }
107
-
108
- // Ignore non-executable hooks
109
- if !is_executable ( & hook_meta) {
105
+ let hook_path = if let Some ( hook_path) = get_hook_path ( repo, hook_name) ? {
106
+ hook_path
107
+ } else {
110
108
return Ok ( message) ;
111
- }
109
+ } ;
112
110
113
111
let mut msg_file = tempfile:: NamedTempFile :: new ( ) ?;
114
112
msg_file. write_all ( message. raw_bytes ( ) ) ?;
@@ -118,7 +116,7 @@ pub(crate) fn run_commit_msg_hook<'repo>(
118
116
119
117
// TODO: when git runs this hook, it only sets GIT_INDEX_FILE and sometimes
120
118
// GIT_EDITOR. So author and committer vars are not clearly required.
121
- let mut hook_command = std:: process:: Command :: new ( gix :: path :: realpath ( hook_path) ? ) ;
119
+ let mut hook_command = std:: process:: Command :: new ( hook_path) ;
122
120
hook_command. env ( "GIT_INDEX_FILE" , & index_path) ;
123
121
if !use_editor {
124
122
hook_command. env ( "GIT_EDITOR" , ":" ) ;
0 commit comments