From 0716528b368a09621a38b1a39ae84dc2b3f5ccff Mon Sep 17 00:00:00 2001
From: Kevin Lyda <kevin@ie.suberic.net>
Date: Thu, 17 Nov 2016 11:55:54 +0000
Subject: [PATCH] Make hooks work as advertised.

For vcsh commands that loop through repos, hooks were not
run correctly. Typically what would be run were:

  pre-looping-hook*
  .pre-looping-hook*
  [command run on repo r1, r2, r3 ... rN]
  post-looping-hook*
  rN.post-looping-hook

The new, more obvious behaviour is:

  pre-looping-hook*
  r1.pre-looping-hook*
  [command run on repo r1]
  r1.post-looping-hook
  [...]
  rN.pre-looping-hook*
  [command run on repo r1]
  rN.post-looping-hook
  post-looping-hook*

I was mainly concerned with the pull command, but I've made changes
in all "for VCSH_REPO_NAME" loops. This is my way of resolving
issue RichiH/vcsh#213, but as I note there are other options.
---
 vcsh | 41 +++++++++++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 10 deletions(-)

diff --git a/vcsh b/vcsh
index de1b419..fe6af47 100755
--- a/vcsh
+++ b/vcsh
@@ -185,16 +185,18 @@ clone() {
 }
 
 commit() {
-	hook pre-commit
+	global_hook pre-commit
 	for VCSH_REPO_NAME in $(list); do
 		echo "$VCSH_REPO_NAME: "
 		GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR
 		use
+                repo_hook pre-commit
 		git commit --untracked-files=no --quiet $@
+                repo_hook post-commit
 		VCSH_COMMAND_RETURN_CODE=$?
 		echo
 	done
-	hook post-commit
+	global_hook post-commit
 }
 
 delete() {
@@ -224,7 +226,7 @@ enter() {
 }
 
 foreach() {
-	hook pre-foreach
+	global_hook pre-foreach
 
 	# We default to prefixing `git` to all commands passed to foreach, but
 	# allow running in general context with -g
@@ -239,23 +241,38 @@ foreach() {
 		echo "$VCSH_REPO_NAME:"
 		GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR
 		use
+                repo_hook pre-foreach
 		$command_prefix "$@"
+                repo_hook post-foreach
 	done
-	hook post-foreach
+	global_hook post-foreach
 }
 
 git_dir_exists() {
 	[ -d "$GIT_DIR" ] || fatal "no repository found for '$VCSH_REPO_NAME'" 12
 }
 
-hook() {
-	for hook in "$VCSH_HOOK_D/$1"* "$VCSH_HOOK_D/$VCSH_REPO_NAME.$1"*; do
+global_hook() {
+	for hook in "$VCSH_HOOK_D/$1"*; do
+		[ -x "$hook" ] || continue
+		verbose "executing '$hook'"
+		"$hook"
+	done
+}
+
+repo_hook() {
+	for hook in "$VCSH_HOOK_D/$VCSH_REPO_NAME.$1"*; do
 		[ -x "$hook" ] || continue
 		verbose "executing '$hook'"
 		"$hook"
 	done
 }
 
+hook() {
+        global_hook "$1"
+        repo_hook "$1"
+}
+
 init() {
 	hook pre-init
 	[ ! -e "$GIT_DIR" ] || fatal "'$GIT_DIR' exists" 10
@@ -349,29 +366,33 @@ list_untracked_helper() {
 }
 
 pull() {
-	hook pre-pull
+	global_hook pre-pull
 	for VCSH_REPO_NAME in $(list); do
 		printf '%s: ' "$VCSH_REPO_NAME"
 		GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR
 		use
+                repo_hook pre-pull
 		git pull
+                repo_hook post-pull
 		VCSH_COMMAND_RETURN_CODE=$?
 		echo
 	done
-	hook post-pull
+	global_hook post-pull
 }
 
 push() {
-	hook pre-push
+	global_hook pre-push
 	for VCSH_REPO_NAME in $(list); do
 		printf '%s: ' "$VCSH_REPO_NAME"
 		GIT_DIR=$VCSH_REPO_D/$VCSH_REPO_NAME.git; export GIT_DIR
 		use
+                repo_hook pre-push
 		git push
+                repo_hook post-push
 		VCSH_COMMAND_RETURN_CODE=$?
 		echo
 	done
-	hook post-push
+	global_hook post-push
 }
 
 retire() {
-- 
GitLab