Skip to content

Commit 3c7d614

Browse files
committed
fix: wrap hooks with sh on Windows
1 parent fd8a489 commit 3c7d614

File tree

1 file changed

+53
-4
lines changed

1 file changed

+53
-4
lines changed

src/hook.rs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,17 @@ pub(crate) fn run_pre_commit_hook(repo: &gix::Repository, use_editor: bool) -> R
6565
return Ok(false);
6666
};
6767

68-
let workdir = repo
69-
.work_dir()
70-
.expect("should not get this far with a bare repo");
68+
let work_dir = repo.work_dir().expect("not a bare repo");
7169

7270
let mut hook_command = std::process::Command::new(hook_path);
71+
hook_command.current_dir(work_dir);
7372
if !use_editor {
7473
hook_command.env("GIT_EDITOR", ":");
7574
}
7675

76+
let mut hook_command = make_sh_command_on_windows(hook_command);
77+
7778
let status = hook_command
78-
.current_dir(workdir)
7979
.stdin(std::process::Stdio::null())
8080
.status()
8181
.with_context(|| format!("`{hook_name}` hook"))?;
@@ -128,6 +128,8 @@ pub(crate) fn run_commit_msg_hook<'repo>(
128128

129129
hook_command.arg(temp_msg.filename());
130130

131+
let mut hook_command = make_sh_command_on_windows(hook_command);
132+
131133
let status = hook_command
132134
.status()
133135
.with_context(|| format!("`{hook_name}` hook"))?;
@@ -207,3 +209,50 @@ fn is_executable(meta: &std::fs::Metadata) -> bool {
207209
fn is_executable(_meta: &std::fs::Metadata) -> bool {
208210
true
209211
}
212+
213+
#[cfg(not(windows))]
214+
fn make_sh_command_on_windows(command: std::process::Command) -> std::process::Command {
215+
command
216+
}
217+
218+
#[cfg(windows)]
219+
fn make_sh_command_on_windows(command: std::process::Command) -> std::process::Command {
220+
let hook_path = command
221+
.get_program()
222+
.to_str()
223+
.expect("path to hook is valid UTF-8");
224+
assert!(!hook_path.contains('"'));
225+
assert!(!hook_path.contains('\''));
226+
227+
let mut command_str = String::new();
228+
command_str.push('"');
229+
command_str.push_str(hook_path);
230+
command_str.push('"');
231+
for arg in command.get_args() {
232+
let arg = arg.to_str().expect("hook args are valid UTF-8");
233+
assert!(!arg.contains('"'));
234+
assert!(!arg.contains('\''));
235+
command_str.push(' ');
236+
command_str.push('"');
237+
command_str.push_str(arg);
238+
command_str.push('"');
239+
}
240+
241+
let mut sh_command = std::process::Command::new("sh");
242+
sh_command.arg("-c");
243+
sh_command.arg(command_str);
244+
245+
for (k, opt_v) in command.get_envs() {
246+
if let Some(v) = opt_v {
247+
sh_command.env(k, v);
248+
} else {
249+
sh_command.env_remove(k);
250+
}
251+
}
252+
253+
if let Some(cur_dir) = command.get_current_dir() {
254+
sh_command.current_dir(cur_dir);
255+
}
256+
257+
sh_command
258+
}

0 commit comments

Comments
 (0)