GIT submodule checker script

A small script to check git repositories in workspace and their submodules. Checks if all submodules have same remote and there is a tag in the submodule for the containing project.

#!/bin/sh

function checkSubmodules() {
	echo "Checking submodules..."

	local PHC="\033[44;1;37m" # project title color
	local THC="\033[44;1;37m" # tag title color
	local RHC="\033[44;1;37m" # remote title color
	local PC="\033[1;34m" # project color
	local MC="\033[0;32m" # module color
	local TC="\033[1;33m" # tag color
	local RC="\033[1;36m" # remote color
	local EC="\033[1;31m" # error color
	local HC="\033[1;37m" # highlight color
	local NC="\033[0m" # no color

	pl=0
	tl=0
	rl=0
	for directory in $(ls); do
		if [ -d $directory ] && [ $(expr length $directory) -gt $pl ]; then
			pl=$(expr length $directory)
		fi
		if [ -d $directory ] && [ -d $directory/.git ]; then
			cd $directory

			tag=$(git remote -v | grep -E "^origin.*\(fetch\)$" | sed -r 's/origin\t[a-z]+:\/\/([^@]+@)?[^\/]+\/(.*)(\.git|[^\.][^g][^i][^t]) \(fetch\)/\2/')
			if [ ! -z "$tag" ] && [ $(expr length $tag) -gt $tl ]; then
				tl=$(expr length $tag)
			fi

			remote=$(git remote -v | grep -E "^origin.*\(fetch\)$" | sed -r 's/origin\t([a-z]+:\/\/([^@]+@)?[^\/]+)\/.*(\.git|[^\.][^g][^i][^t]) \(fetch\)/\1/')
			if [ ! -z "$remote" ] && [ $(expr length $remote) -gt $rl ]; then
				rl=$(expr length $remote)
			fi

			cd ..
		fi
	done

	printf "${PHC}%-${pl}s${NC} ${THC}%-${tl}s${NC} ${RHC}%-${rl}s${NC}\n" "    PROJECT / SUBMODULE" "    TAG" "    REMOTE"

	for directory in $(ls); do
		if [ -d $directory ] && [ ! -d $directory/.git ]; then
			echo -e "${PC}${directory}${NC} is not a GIT repository."
		elif [ -d $directory ]; then
			cd $directory
			tag=""
			remote=""
			while [ -z "$tag" ]; do
				tag=$(git remote -v | grep -E "^origin.*\(fetch\)$" | sed -r 's/origin\t[a-z]+:\/\/([^@]+@)?[^\/]+\/(.*)(\.git|[^\.][^g][^i][^t]) \(fetch\)/\2/')
				remote=$(git remote -v | grep -E "^origin.*\(fetch\)$" | sed -r 's/origin\t([a-z]+:\/\/([^@]+@)?[^\/]+)\/.*(\.git|[^\.][^g][^i][^t]) \(fetch\)/\1/')
				if [ -z "$tag" ]; then
					echo -e "${EC}Could not detect tag for ${PC}${directory}${EC} project!${NC}" >&2
					response="";
					while [ "$response" != "c" ]; do
						read -p "  what next? (${HC}C${NC})ontinue, (${HC}S${NC})hell, (${HC}Q${NC})uit" -n1 response

						if [ "$response" = "q" ]; then
							exit 1
						elif [ "$response" = "s" ]; then
							$SHELL
						fi
					done
				fi
			done

			printf "${PC}%-${pl}s${NC} ${TC}%-${tl}s${NC} ${RC}%-${rl}s${NC}\n" $directory $tag $remote

			IFS="
	"
			for submodule in $(git submodule); do
				if echo $submodule | grep -E "^\-.*"; then
					subname=$(echo $submodule | sed -r 's/\-[0-9a-f]{40}\ ([^\ ]+)/\1/')
					git submodule init $subname
					git submodule update $subname
				fi
			done

			sl=$(expr $pl - 4)
			tagdesc=""
			for submodule in $(git submodule); do
				if echo $submodule | grep -E "^.[0-9a-f]{40}\ ([^\ ]+)\ \((.*)\)" > /dev/null; then
					parts=$(echo $submodule | sed -r 's/.[0-9a-f]{40}\ ([^\ ]+)\ \((.*)\)/\1 \2/')
					subdir=$(echo $parts | cut -d" " -f1)
					pardir=$(echo $subdir | sed -r 's/[^\/]+/../g')
					subtag=$(echo $parts | cut -d" " -f2)

					cd $subdir

					subrem=$(git remote -v | grep -E "^origin.*\(fetch\)$" | sed -r 's/origin\t([a-z]+:\/\/[^@]+@[^\/]+)\/.*(\.git)?.*/\1/')

					printf "  - ${MC}%-${sl}s${NC} ${TC}%-${tl}s${NC} ${RC}%-${rl}s${NC}\n" $subdir $subtag $subrem

					if [ "$subrem" != "$remote" ]; then
						echo -e "    Remote of the containing ${PC}${directory}${NC} project (${RC}${remote}${NC}) differs from remote of the ${MC}${subdir}${NC} submodule (${RC}${subrem}${NC})!" >&2
						$SHELL
					fi

					if [ "$subtag" != "$tag" ]; then
						echo -e "    Tag ${TC}${tag}${NC} does not match ${MC}${subdir}${NC} submodule tag (${TC}${subtag}${NC})."
						while [ -z $tagdesc ]; do
							read -p "    Enter the description of the ${TC}${tag}${NC} tag: " tagdesc
						done
						git fetch
						git tag -fa $tag -m "$tagdesc"
						git push --tags
						git lp
					fi
					cd $pardir
				else
					echo -e "${EC}  Wrong submodule ${MC}${submodule}${EC}!${NC}" >&2
					response="";
					while [ "$response" != "c" ]; do
						read -p "  What next? (${HC}C${NC})ontinue, (${HC}S${NC})hell, (${HC}Q${NC})uit" -n1 response;
						if [ "$response" = "q" ]; then
							exit 1
						elif [ "$response" = "s" ]; then
							$SHELL
						fi
					done
				fi
			done
			cd ..
		fi
	done
}

checkSubmodules

Leave a Reply

Your email address will not be published. Required fields are marked *