Skip to content

Commit 55b9877

Browse files
author
Stephan Dilly
committed
use .git path instead of workdir finding hooks
fixes #1046
1 parent 12f3d97 commit 55b9877

File tree

1 file changed

+55
-34
lines changed

1 file changed

+55
-34
lines changed

asyncgit/src/sync/hooks.rs

Lines changed: 55 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
1-
use super::{repository::repo, utils::work_dir, RepoPath};
2-
use crate::error::{Error, Result};
1+
use super::{repository::repo, RepoPath};
2+
use crate::error::Result;
33
use scopetime::scope_time;
44
use std::{
55
fs::File,
66
io::{Read, Write},
7-
path::Path,
7+
path::{Path, PathBuf},
88
process::Command,
99
};
1010

11-
const HOOK_POST_COMMIT: &str = ".git/hooks/post-commit";
12-
const HOOK_PRE_COMMIT: &str = ".git/hooks/pre-commit";
13-
const HOOK_COMMIT_MSG: &str = ".git/hooks/commit-msg";
14-
const HOOK_COMMIT_MSG_TEMP_FILE: &str = ".git/COMMIT_EDITMSG";
11+
const HOOK_POST_COMMIT: &str = "hooks/post-commit";
12+
const HOOK_PRE_COMMIT: &str = "hooks/pre-commit";
13+
const HOOK_COMMIT_MSG: &str = "hooks/commit-msg";
14+
const HOOK_COMMIT_MSG_TEMP_FILE: &str = "COMMIT_EDITMSG";
1515

1616
/// this hook is documented here <https://git-scm.com/docs/githooks#_commit_msg>
1717
/// we use the same convention as other git clients to create a temp file containing
18-
/// the commit message at `.git/COMMIT_EDITMSG` and pass it's relative path as the only
18+
/// the commit message at `<.git|hooksPath>/COMMIT_EDITMSG` and pass it's relative path as the only
1919
/// parameter to the hook script.
2020
pub fn hooks_commit_msg(
2121
repo_path: &RepoPath,
2222
msg: &mut String,
2323
) -> Result<HookResult> {
2424
scope_time!("hooks_commit_msg");
2525

26-
let work_dir = work_dir_as_string(repo_path)?;
26+
let git_dir = git_dir_as_string(repo_path)?;
27+
let git_dir = git_dir.as_path();
2728

28-
if hook_runable(work_dir.as_str(), HOOK_COMMIT_MSG) {
29-
let temp_file = Path::new(work_dir.as_str())
30-
.join(HOOK_COMMIT_MSG_TEMP_FILE);
29+
if hook_runable(git_dir, HOOK_COMMIT_MSG) {
30+
let temp_file = git_dir.join(HOOK_COMMIT_MSG_TEMP_FILE);
3131
File::create(&temp_file)?.write_all(msg.as_bytes())?;
3232

3333
let res = run_hook(
34-
work_dir.as_str(),
34+
git_dir,
3535
HOOK_COMMIT_MSG,
3636
&[HOOK_COMMIT_MSG_TEMP_FILE],
3737
)?;
@@ -51,10 +51,11 @@ pub fn hooks_commit_msg(
5151
pub fn hooks_pre_commit(repo_path: &RepoPath) -> Result<HookResult> {
5252
scope_time!("hooks_pre_commit");
5353

54-
let work_dir = work_dir_as_string(repo_path)?;
54+
let git_dir = git_dir_as_string(repo_path)?;
55+
let git_dir = git_dir.as_path();
5556

56-
if hook_runable(work_dir.as_str(), HOOK_PRE_COMMIT) {
57-
Ok(run_hook(work_dir.as_str(), HOOK_PRE_COMMIT, &[])?)
57+
if hook_runable(git_dir, HOOK_PRE_COMMIT) {
58+
Ok(run_hook(git_dir, HOOK_PRE_COMMIT, &[])?)
5859
} else {
5960
Ok(HookResult::Ok)
6061
}
@@ -63,32 +64,23 @@ pub fn hooks_pre_commit(repo_path: &RepoPath) -> Result<HookResult> {
6364
pub fn hooks_post_commit(repo_path: &RepoPath) -> Result<HookResult> {
6465
scope_time!("hooks_post_commit");
6566

66-
let work_dir = work_dir_as_string(repo_path)?;
67-
let work_dir_str = work_dir.as_str();
67+
let git_dir = git_dir_as_string(repo_path)?;
68+
let git_dir = git_dir.as_path();
6869

69-
if hook_runable(work_dir_str, HOOK_POST_COMMIT) {
70-
Ok(run_hook(work_dir_str, HOOK_POST_COMMIT, &[])?)
70+
if hook_runable(git_dir, HOOK_POST_COMMIT) {
71+
Ok(run_hook(git_dir, HOOK_POST_COMMIT, &[])?)
7172
} else {
7273
Ok(HookResult::Ok)
7374
}
7475
}
7576

76-
fn work_dir_as_string(repo_path: &RepoPath) -> Result<String> {
77+
fn git_dir_as_string(repo_path: &RepoPath) -> Result<PathBuf> {
7778
let repo = repo(repo_path)?;
78-
work_dir(&repo)?
79-
.to_str()
80-
.map(std::string::ToString::to_string)
81-
.ok_or_else(|| {
82-
Error::Generic(
83-
"workdir contains invalid utf8".to_string(),
84-
)
85-
})
79+
Ok(repo.path().to_path_buf())
8680
}
8781

88-
fn hook_runable(path: &str, hook: &str) -> bool {
89-
let path = Path::new(path);
82+
fn hook_runable(path: &Path, hook: &str) -> bool {
9083
let path = path.join(hook);
91-
9284
path.exists() && is_executable(&path)
9385
}
9486

@@ -104,7 +96,7 @@ pub enum HookResult {
10496
/// this function calls hook scripts based on conventions documented here
10597
/// see <https://git-scm.com/docs/githooks>
10698
fn run_hook(
107-
path: &str,
99+
path: &Path,
108100
hook_script: &str,
109101
args: &[&str],
110102
) -> Result<HookResult> {
@@ -155,8 +147,10 @@ const fn is_executable(_: &Path) -> bool {
155147

156148
#[cfg(test)]
157149
mod tests {
150+
use tempfile::TempDir;
151+
158152
use super::*;
159-
use crate::sync::tests::repo_init;
153+
use crate::sync::tests::{repo_init, repo_init_bare};
160154
use std::fs::{self, File};
161155

162156
#[test]
@@ -177,6 +171,13 @@ mod tests {
177171
}
178172

179173
fn create_hook(path: &Path, hook_path: &str, hook_script: &[u8]) {
174+
let path = git_dir_as_string(
175+
&path.as_os_str().to_str().unwrap().into(),
176+
)
177+
.unwrap();
178+
let path = path.as_path();
179+
dbg!(&path);
180+
180181
File::create(&path.join(hook_path))
181182
.unwrap()
182183
.write_all(hook_script)
@@ -246,6 +247,26 @@ exit 1
246247
assert!(res != HookResult::Ok);
247248
}
248249

250+
#[test]
251+
fn test_pre_commit_fail_bare() {
252+
let (git_root, _repo) = repo_init_bare().unwrap();
253+
let workdir = TempDir::new().unwrap();
254+
let git_root = git_root.into_path();
255+
let repo_path = &RepoPath::Workdir {
256+
gitdir: git_root.to_path_buf(),
257+
workdir: workdir.into_path(),
258+
};
259+
260+
let hook = b"#!/bin/sh
261+
echo 'rejected'
262+
exit 1
263+
";
264+
265+
create_hook(git_root.as_path(), "hooks/pre-commit", hook);
266+
let res = hooks_pre_commit(repo_path).unwrap();
267+
assert!(res != HookResult::Ok);
268+
}
269+
249270
#[test]
250271
fn test_pre_commit_py() {
251272
let (_td, repo) = repo_init().unwrap();

0 commit comments

Comments
 (0)