[PATCH] Added recurse command to git submodule

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Added a recurse command to git-submodule. Using this recurse command
any git command (for example, git-status, git-diff, git-checkout) can
be performed from the top level to all its submodules at any depth; if
the module has not been initialized and updated (that is git sumodule
init and git submodule update) the script will take care of that too.

I needed this feature especially for diff, status and pull; as I am
working on a multi module maven project with each module having
separate repository due to architecture and future extensibility.

Following is the diff with git-submdoule version 1.5.3.7. I also
attached the diff and the modified file in the attachment.

diff --git a/git-submodule b/git-submodule
index b91d626..e819152 100755
--- a/git-submodule
+++ b/git-submodule
@@ -1,10 +1,11 @@
 #!/bin/sh
 #
 # git-submodules.sh: add, init, update or list git submodules
+# or recurse any git command over the submodules recursively.
 #
 # Copyright (c) 2007 Lars Hjemli

-USAGE='[--quiet] [--cached] [add <repo> [-b
branch]|status|init|update] [--] [<path>...]'
+USAGE='[[--quiet] [--cached] [add <repo> [-b
branch]|status|init|update] [--] [<path>...]|[recurse [-v] command
arguments ...]]'
 . git-sh-setup
 require_work_tree

@@ -251,6 +252,78 @@ modules_list()
 	done
 }

+# Simply checks whether the submodule is initialized
+# or not. If not initialized it does so.
+initializeSubModule() {
+	if [ ! -d "$1"/.git ]; then
+		if [ $recurse_verbose -eq 1 ]; then
+			echo Initializing and updating "$1"
+		fi
+		git-submodule init "$1"; git-submodule update "$1"
+	fi
+}
+
+# This actually traverses the module; checks
+# whether the module is initialized or not.
+# if not initialized, then done so and then the
+# intended command is evaluated. Then it
+# recursively goes into it modules.
+traverseModule() {
+	current_dir=`pwd`
+	dir_path="$current_dir:$dir_path"
+	initializeSubModule "$1"
+        cd "$1"
+	if [ $recurse_verbose -eq 1 ]; then
+		echo Working in mod $1 @ `pwd` with $2
+	fi
+        eval "$2"
+	if [ -f .gitmodules ]; then
+                for mod_path in `grep "path =" .gitmodules | awk
'{print $3}'`; do
+                        traverseModule "$mod_path" "$2"
+                done
+        fi
+	old_dir=$(echo $dir_path | cut -d':' -f1-1)
+	length_old_dir=`expr "$old_dir" : '.*'`
+	cd $old_dir
+	index=$(echo "$length_old_dir+2" | bc)
+	dir_path=`echo $dir_path $index | awk '{print substr($1, $2)}'`
+}
+
+# Propagates or recurses over all the submodules at any
+# depth with any git command, e.g. git-clone, git-status,
+# git-commit etc., with the arguments supplied exactly as
+# it would have been supplied to the command otherwise.
+# This actually starts the recursive propagation
+propagate() {
+	project_home=`pwd`
+	echo Project Home: $project_home
+	if [ -d $project_home/.git/ ]; then
+		git_command=$1
+		shift
+		command_arguments=""
+		for arg in "$@"; do
+			if [ `expr index "$arg" ' '` -gt 0 ]; then
+				arg="\"$arg\""
+			fi
+			command_arguments="$command_arguments $arg"
+		done
+		if [ $recurse_verbose -eq 1 ]; then
+			echo GIT Command git-$git_command with arguments\($#\) "$command_arguments"
+		fi
+		main_command="git-$git_command $command_arguments"
+		eval $main_command
+		if [ -f .gitmodules ]; then
+			for mod_path in `grep "path =" .gitmodules | awk '{print $3}'`; do
+				traverseModule $mod_path "$main_command"
+			done
+		fi
+	else
+		echo $project_home not a git repo thus exiting
+		exit
+	fi
+}
+
+recurse_verbose=0
 while test $# != 0
 do
 	case "$1" in
@@ -286,6 +359,17 @@ do
 	-*)
 		usage
 		;;
+	recurse)
+		recurse=1
+		case "$2" in
+			-v)
+				recurse_verbose=1
+				shift
+				;;
+		esac
+		shift
+		break
+		;;
 	*)
 		break
 		;;
@@ -303,17 +387,21 @@ case "$add,$branch" in
 	;;
 esac

-case "$add,$init,$update,$status,$cached" in
-1,,,,)
+
+case "$add,$init,$update,$recurse,$status,$cached" in
+1,,,,,)
 	module_add "$@"
 	;;
-,1,,,)
+,1,,,,)
 	modules_init "$@"
 	;;
-,,1,,)
+,,1,,,)
 	modules_update "$@"
 	;;
-,,,*,*)
+,,,1,,)
+	propagate "$@"
+	;;
+,,,,*,*)
 	modules_list "$@"
 	;;
 *)

-- 
Imran M Yousuf
diff --git a/git-submodule b/git-submodule
index b91d626..e819152 100755
--- a/git-submodule
+++ b/git-submodule
@@ -1,10 +1,11 @@
 #!/bin/sh
 #
 # git-submodules.sh: add, init, update or list git submodules
+# or recurse any git command over the submodules recursively.
 #
 # Copyright (c) 2007 Lars Hjemli
 
-USAGE='[--quiet] [--cached] [add <repo> [-b branch]|status|init|update] [--] [<path>...]'
+USAGE='[[--quiet] [--cached] [add <repo> [-b branch]|status|init|update] [--] [<path>...]|[recurse [-v] command arguments ...]]'
 . git-sh-setup
 require_work_tree
 
@@ -251,6 +252,78 @@ modules_list()
 	done
 }
 
+# Simply checks whether the submodule is initialized
+# or not. If not initialized it does so.
+initializeSubModule() {
+	if [ ! -d "$1"/.git ]; then
+		if [ $recurse_verbose -eq 1 ]; then
+			echo Initializing and updating "$1"
+		fi
+		git-submodule init "$1"; git-submodule update "$1"
+	fi
+}
+
+# This actually traverses the module; checks
+# whether the module is initialized or not.
+# if not initialized, then done so and then the
+# intended command is evaluated. Then it
+# recursively goes into it modules.
+traverseModule() {
+	current_dir=`pwd`
+	dir_path="$current_dir:$dir_path"
+	initializeSubModule "$1"
+        cd "$1"
+	if [ $recurse_verbose -eq 1 ]; then
+		echo Working in mod $1 @ `pwd` with $2
+	fi
+        eval "$2"
+	if [ -f .gitmodules ]; then
+                for mod_path in `grep "path =" .gitmodules | awk '{print $3}'`; do
+                        traverseModule "$mod_path" "$2"
+                done
+        fi
+	old_dir=$(echo $dir_path | cut -d':' -f1-1)
+	length_old_dir=`expr "$old_dir" : '.*'`
+	cd $old_dir
+	index=$(echo "$length_old_dir+2" | bc)
+	dir_path=`echo $dir_path $index | awk '{print substr($1, $2)}'`
+}
+
+# Propagates or recurses over all the submodules at any 
+# depth with any git command, e.g. git-clone, git-status,
+# git-commit etc., with the arguments supplied exactly as
+# it would have been supplied to the command otherwise.
+# This actually starts the recursive propagation
+propagate() {
+	project_home=`pwd`
+	echo Project Home: $project_home
+	if [ -d $project_home/.git/ ]; then
+		git_command=$1
+		shift
+		command_arguments=""
+		for arg in "$@"; do
+			if [ `expr index "$arg" ' '` -gt 0 ]; then
+				arg="\"$arg\""
+			fi 
+			command_arguments="$command_arguments $arg"
+		done
+		if [ $recurse_verbose -eq 1 ]; then
+			echo GIT Command git-$git_command with arguments\($#\) "$command_arguments"
+		fi
+		main_command="git-$git_command $command_arguments"
+		eval $main_command
+		if [ -f .gitmodules ]; then
+			for mod_path in `grep "path =" .gitmodules | awk '{print $3}'`; do
+				traverseModule $mod_path "$main_command"
+			done
+		fi
+	else
+		echo $project_home not a git repo thus exiting
+		exit
+	fi
+}
+
+recurse_verbose=0
 while test $# != 0
 do
 	case "$1" in
@@ -286,6 +359,17 @@ do
 	-*)
 		usage
 		;;
+	recurse)
+		recurse=1
+		case "$2" in
+			-v)
+				recurse_verbose=1
+				shift
+				;;
+		esac
+		shift
+		break
+		;;
 	*)
 		break
 		;;
@@ -303,17 +387,21 @@ case "$add,$branch" in
 	;;
 esac
 
-case "$add,$init,$update,$status,$cached" in
-1,,,,)
+
+case "$add,$init,$update,$recurse,$status,$cached" in
+1,,,,,)
 	module_add "$@"
 	;;
-,1,,,)
+,1,,,,)
 	modules_init "$@"
 	;;
-,,1,,)
+,,1,,,)
 	modules_update "$@"
 	;;
-,,,*,*)
+,,,1,,)
+	propagate "$@"
+	;;
+,,,,*,*)
 	modules_list "$@"
 	;;
 *)

Attachment: git-submodule
Description: Binary data


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux