Skip to content

Commit 88f9f80

Browse files
committed
✨ Enhance Git hooks with improved execution environment
Enhance Git hooks with improved execution environment This playful plumbing upgrade makes Git hooks work more reliably by: - Executing hooks in repo's working directory instead of .git folder - Setting proper GIT_DIR and GIT_WORK_TREE environment variables - Adding detailed debug logging throughout hook execution process - Properly separating pre-commit and post-commit hook logic - Using Repository::discover instead of open for more reliable repo detection Now your hooks can dance around your repo with proper context!
1 parent e50fe97 commit 88f9f80

File tree

2 files changed

+72
-18
lines changed

2 files changed

+72
-18
lines changed

src/commit/service.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -168,21 +168,48 @@ impl IrisCommitService {
168168
Ok(generated_message)
169169
}
170170

171-
/// Perform a commit with the given message
171+
/// Performs a commit with the given message.
172172
///
173173
/// # Arguments
174174
///
175-
/// * `message` - The commit message to use
175+
/// * `message` - The commit message.
176176
///
177177
/// # Returns
178178
///
179-
/// A Result containing the `CommitResult` or an error
179+
/// A Result containing the `CommitResult` or an error.
180180
pub fn perform_commit(&self, message: &str) -> Result<CommitResult> {
181181
let processed_message = process_commit_message(message.to_string(), self.use_gitmoji);
182-
if self.verify {
183-
self.repo.commit_and_verify(&processed_message)
184-
} else {
185-
self.repo.commit(&processed_message)
182+
log_debug!("Performing commit with message: {}", processed_message);
183+
184+
if !self.verify {
185+
log_debug!("Skipping pre-commit hook (verify=false)");
186+
return self.repo.commit(&processed_message);
187+
}
188+
189+
// Execute pre-commit hook
190+
log_debug!("Executing pre-commit hook");
191+
if let Err(e) = self.repo.execute_hook("pre-commit") {
192+
log_debug!("Pre-commit hook failed: {}", e);
193+
return Err(e);
194+
}
195+
log_debug!("Pre-commit hook executed successfully");
196+
197+
// Perform the commit
198+
match self.repo.commit(&processed_message) {
199+
Ok(result) => {
200+
// Execute post-commit hook
201+
log_debug!("Executing post-commit hook");
202+
if let Err(e) = self.repo.execute_hook("post-commit") {
203+
log_debug!("Post-commit hook failed: {}", e);
204+
// We don't fail the commit if post-commit hook fails
205+
}
206+
log_debug!("Commit performed successfully");
207+
Ok(result)
208+
}
209+
Err(e) => {
210+
log_debug!("Commit failed: {}", e);
211+
Err(e)
212+
}
186213
}
187214
}
188215

src/git.rs

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -527,11 +527,27 @@ impl GitRepo {
527527
let hook_path = repo.path().join("hooks").join(hook_name);
528528

529529
if hook_path.exists() {
530-
let mut child = Command::new(&hook_path)
531-
.current_dir(repo.path())
530+
log_debug!("Executing hook: {}", hook_name);
531+
log_debug!("Hook path: {:?}", hook_path);
532+
533+
// Get the repository's working directory (top level)
534+
let repo_workdir = repo
535+
.workdir()
536+
.context("Repository has no working directory")?;
537+
log_debug!("Repository working directory: {:?}", repo_workdir);
538+
539+
// Create a command with the proper environment and working directory
540+
let mut command = Command::new(&hook_path);
541+
command
542+
.current_dir(repo_workdir) // Use the repository's working directory, not .git
543+
.env("GIT_DIR", repo.path()) // Set GIT_DIR to the .git directory
544+
.env("GIT_WORK_TREE", repo_workdir) // Set GIT_WORK_TREE to the working directory
532545
.stdout(Stdio::piped())
533-
.stderr(Stdio::piped())
534-
.spawn()?;
546+
.stderr(Stdio::piped());
547+
548+
log_debug!("Executing hook command: {:?}", command);
549+
550+
let mut child = command.spawn()?;
535551

536552
let stdout = child.stdout.take().context("Could not get stdout")?;
537553
let stderr = child.stderr.take().context("Could not get stderr")?;
@@ -554,6 +570,10 @@ impl GitRepo {
554570
status.code()
555571
));
556572
}
573+
574+
log_debug!("Hook '{}' executed successfully", hook_name);
575+
} else {
576+
log_debug!("Hook '{}' not found at {:?}", hook_name, hook_path);
557577
}
558578

559579
Ok(())
@@ -566,13 +586,20 @@ impl GitRepo {
566586
/// A Result containing a boolean indicating if inside a work tree or an error.
567587
pub fn is_inside_work_tree() -> Result<bool> {
568588
log_debug!("Checking if inside Git work tree");
569-
let repo = Repository::open(env::current_dir()?)?;
570-
if repo.is_bare() {
571-
log_debug!("Not inside Git work tree (bare repository)");
572-
Ok(false)
573-
} else {
574-
log_debug!("Inside Git work tree");
575-
Ok(true)
589+
match Repository::discover(env::current_dir()?) {
590+
Ok(repo) => {
591+
if repo.is_bare() {
592+
log_debug!("Not inside Git work tree (bare repository)");
593+
Ok(false)
594+
} else {
595+
log_debug!("Inside Git work tree");
596+
Ok(true)
597+
}
598+
}
599+
Err(e) => {
600+
log_debug!("Error discovering Git repository: {}", e);
601+
Err(anyhow!("Not in a Git repository: {}", e))
602+
}
576603
}
577604
}
578605

0 commit comments

Comments
 (0)