about summary refs log tree commit diff
path: root/submodules.sh
diff options
context:
space:
mode:
Diffstat (limited to 'submodules.sh')
-rwxr-xr-xsubmodules.sh181
1 files changed, 181 insertions, 0 deletions
diff --git a/submodules.sh b/submodules.sh
new file mode 100755
index 0000000..1d7b13f
--- /dev/null
+++ b/submodules.sh
@@ -0,0 +1,181 @@
+#!/bin/sh
+#
+# submodules.sh: init, update or list git submodules
+#
+# Copyright (C) 2006 Lars Hjemli
+#
+# Licensed under GNU General Public License v2
+#   (see COPYING for full license text)
+#
+
+
+usage="submodules.sh [-i | -u] [-q] [--cached] [path...]"
+init=
+update=
+quiet=
+cached=
+
+
+say()
+{
+	if test -z "$quiet"
+	then
+		echo -e "$@"
+	fi
+}
+
+
+die()
+{
+	echo >&2 -e "$@"
+	exit 1
+}
+
+
+
+#
+# Silently checkout specified submodule revision, return exit status of git-checkout
+#
+# $1 = local path
+# $2 = requested sha1
+#
+module_checkout()
+{
+	$(cd "$1" && git checkout "$2" 1>/dev/null 2>/dev/null)
+}
+
+
+#
+# Find all (requested) submodules, run clone + checkout on missing paths
+#
+# $@ = requested paths (default to all)
+#
+modules_init()
+{
+	git ls-files --stage -- $@ | grep -e '^160000 ' |
+	while read mode sha1 stage path
+	do
+		test -d "$path/.git" && continue
+
+		if test -d "$path"
+		then
+			rmdir "$path" 2>/dev/null ||
+			die "Directory '$path' exist, but not as a submodule"
+		fi
+
+		test -e "$path" && die "A file already exist at path '$path'"
+
+		url=$(sed -nre "s/^$path[ \t]+//p" .gitmodules)
+		test -z "$url" && die "No url found for $path in .gitmodules"
+
+		git clone "$url" "$path" || die "Clone of submodule '$path' failed"
+		module_checkout "$path" "$sha1" || die "Checkout of submodule '$path' failed"
+		say "Submodule '$path' initialized"
+	done
+}
+
+#
+# Checkout correct revision of each initialized submodule
+#
+# $@ = requested paths (default to all)
+#
+modules_update()
+{
+	git ls-files --stage -- $@ | grep -e '^160000 ' |
+	while read mode sha1 stage path
+	do
+		if ! test -d "$path/.git"
+		then
+			say "Submodule '$path' not initialized"
+			continue;
+		fi
+		subsha1=$(cd "$path" && git rev-parse --verify HEAD) ||
+		die "Unable to find current revision of submodule '$path'"
+		if test "$subsha1" != "$sha1"
+		then
+			module_checkout "$path" "$sha1" ||
+			die "Unable to checkout revision $sha1 of submodule '$path'"
+			say "Submodule '$path' reset to revision $sha1"
+		fi
+	done
+}
+
+#
+# List all registered submodules, prefixed with:
+#  - submodule not initialized
+#  + different version checked out
+#
+# If --cached was specified the revision in the index will be printed
+# instead of the currently checked out revision.
+#
+# $@ = requested paths (default to all)
+#
+modules_list()
+{
+	git ls-files --stage -- $@ | grep -e '^160000 ' |
+	while read mode sha1 stage path
+	do
+		if ! test -d "$path/.git"
+		then
+			say "-$sha1 $path"
+			continue;
+		fi
+		revname=$(cd "$path" && git describe $sha1)
+		if git diff-files --quiet -- "$path"
+		then
+			say " $sha1 $path\t($revname)"
+		else
+			if test -z "$cached"
+			then
+				sha1=$(cd "$path" && git rev-parse HEAD)
+				revname=$(cd "$path" && git describe HEAD)
+			fi
+			say "+$sha1 $path\t($revname)"
+		fi
+	done
+}
+
+
+while case "$#" in 0) break ;; esac
+do
+	case "$1" in
+	-i)
+		init=1
+		;;
+	-u)
+		update=1
+		;;
+	-q)
+		quiet=1
+		;;
+	--cached)
+		cached=1
+		;;
+	--)
+		break
+		;;
+	-*)
+		echo "Usage: $usage"
+		exit 1
+		;;
+	--*)
+		echo "Usage: $usage"
+		exit 1
+		;;
+	*)
+		break
+		;;
+	esac
+	shift
+done
+
+
+if test "$init" = "1"
+then
+	modules_init $@
+elif test "$update" = "1"
+then
+	modules_update $@
+else
+	modules_list $@
+fi