From 97560564c9e024d7095639cd2fc0b426aadb37a4 Mon Sep 17 00:00:00 2001 From: Stephan Dilly Date: Thu, 25 Jun 2020 08:14:43 +0200 Subject: [PATCH] run hooks from workdir and not from current dir (closes #151) --- CHANGELOG.md | 1 + asyncgit/src/sync/hooks.rs | 92 ++++++++++++++++++++++++++++++++++---- 2 files changed, 84 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41bfe004..389a0dd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - clearer help headers ([#131](https://github.com/extrawurst/gitui/issues/131)) - diisplay non-utf8 commit messages at least partially ([#150](https://github.com/extrawurst/gitui/issues/150)) +- hooks ignored when running `gitui` in subfolder of workdir ([#151](https://github.com/extrawurst/gitui/issues/151)) ## [0.7.0] - 2020-06-15 diff --git a/asyncgit/src/sync/hooks.rs b/asyncgit/src/sync/hooks.rs index d0eb36d0..d217b175 100644 --- a/asyncgit/src/sync/hooks.rs +++ b/asyncgit/src/sync/hooks.rs @@ -1,4 +1,5 @@ -use crate::error::Result; +use super::utils::{repo, work_dir}; +use crate::error::{Error, Result}; use scopetime::scope_time; use std::{ fs::File, @@ -22,13 +23,15 @@ pub fn hooks_commit_msg( ) -> Result { scope_time!("hooks_commit_msg"); - if hook_runable(repo_path, HOOK_COMMIT_MSG) { - let temp_file = - Path::new(repo_path).join(HOOK_COMMIT_MSG_TEMP_FILE); + let work_dir = work_dir_as_string(repo_path)?; + + if hook_runable(work_dir.as_str(), HOOK_COMMIT_MSG) { + let temp_file = Path::new(work_dir.as_str()) + .join(HOOK_COMMIT_MSG_TEMP_FILE); File::create(&temp_file)?.write_all(msg.as_bytes())?; let res = run_hook( - repo_path, + work_dir.as_str(), HOOK_COMMIT_MSG, &[HOOK_COMMIT_MSG_TEMP_FILE], ); @@ -47,13 +50,28 @@ pub fn hooks_commit_msg( pub fn hooks_post_commit(repo_path: &str) -> Result { scope_time!("hooks_post_commit"); - if hook_runable(repo_path, HOOK_POST_COMMIT) { - Ok(run_hook(repo_path, HOOK_POST_COMMIT, &[])) + let work_dir = work_dir_as_string(repo_path)?; + let work_dir_str = work_dir.as_str(); + + if hook_runable(work_dir_str, HOOK_POST_COMMIT) { + Ok(run_hook(work_dir_str, HOOK_POST_COMMIT, &[])) } else { Ok(HookResult::Ok) } } +fn work_dir_as_string(repo_path: &str) -> Result { + let repo = repo(repo_path)?; + work_dir(&repo) + .to_str() + .map(|s| s.to_string()) + .ok_or_else(|| { + Error::Generic( + "workdir contains invalid utf8".to_string(), + ) + }) +} + fn hook_runable(path: &str, hook: &str) -> bool { let path = Path::new(path); let path = path.join(hook); @@ -126,7 +144,7 @@ fn is_executable(_: PathBuf) -> bool { mod tests { use super::*; use crate::sync::tests::repo_init; - use std::fs::File; + use std::fs::{self, File}; #[test] fn test_smoke() { @@ -182,7 +200,7 @@ exit 0 } #[test] - fn test_hooks_commit_msg() { + fn test_hooks_commit_msg_reject() { let (_td, repo) = repo_init().unwrap(); let root = repo.path().parent().unwrap(); let repo_path = root.as_os_str().to_str().unwrap(); @@ -207,6 +225,37 @@ exit 1 assert_eq!(msg, String::from("msg\n")); } + #[test] + fn test_hooks_commit_msg_reject_in_subfolder() { + let (_td, repo) = repo_init().unwrap(); + let root = repo.path().parent().unwrap(); + // let repo_path = root.as_os_str().to_str().unwrap(); + + let hook = b" +#!/bin/sh +echo 'msg' > $1 +echo 'rejected' +exit 1 + "; + + create_hook(root, HOOK_COMMIT_MSG, hook); + + let subfolder = root.join("foo/"); + fs::create_dir_all(&subfolder).unwrap(); + + let mut msg = String::from("test"); + let res = + hooks_commit_msg(subfolder.to_str().unwrap(), &mut msg) + .unwrap(); + + assert_eq!( + res, + HookResult::NotOk(String::from("rejected\n")) + ); + + assert_eq!(msg, String::from("msg\n")); + } + #[test] fn test_commit_msg_no_block_but_alter() { let (_td, repo) = repo_init().unwrap(); @@ -227,4 +276,29 @@ exit 0 assert_eq!(res, HookResult::Ok); assert_eq!(msg, String::from("msg\n")); } + + #[test] + fn test_post_commit_hook_reject_in_subfolder() { + let (_td, repo) = repo_init().unwrap(); + let root = repo.path().parent().unwrap(); + + let hook = b" +#!/bin/sh +echo 'rejected' +exit 1 + "; + + create_hook(root, HOOK_POST_COMMIT, hook); + + let subfolder = root.join("foo/"); + fs::create_dir_all(&subfolder).unwrap(); + + let res = + hooks_post_commit(subfolder.to_str().unwrap()).unwrap(); + + assert_eq!( + res, + HookResult::NotOk(String::from("rejected\n")) + ); + } }