git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 2/3] git-submodule: fix subcommand parser

From
Junio C Hamano <gitster@pobox.com>
Date
Jan 15, 2008, 11:19 UTC
Message-ID
<7vve5ve3ov.fsf_-_@gitster.siamese.dyndns.org>
In-Reply-To
<7vzlv7flb5.fsf@gitster.siamese.dyndns.org>

The subcommand parser of "git submodule" made its subcommand names reserved words. As a consequence, a command like this:

    $ git submodule add init update

which is meant to add a submodule called 'init' at path 'update' was misinterpreted as a request to invoke more than one mutually incompatible subcommands and incorrectly rejected.

This patch fixes the issue by stopping the subcommand parsing at the first subcommand word, to allow the sample command line above to work as expected.

It also introduces the usual -- option disambiguator, so that a submodule at path '-foo' can be updated with

    $ git submodule update -- -foo
without triggering an "unrecognized option -foo" error.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 * And this is the second part to fix the real issue.
 git-submodule.sh |  157 ++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 116 insertions(+), 41 deletions(-)
diff --git a/git-submodule.sh b/git-submodule.sh
index 3c104e3..a6aaf40 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -9,11 +9,8 @@ OPTIONS_SPEC=
 . git-sh-setup
 require_work_tree
 
-add=
+command=
 branch=
-init=
-update=
-status=
 quiet=
 cached=
 
@@ -123,6 +120,32 @@ module_clone()
 #
 cmd_add()
 {
+	# parse $args after "submodule ... add".
+	while test $# -ne 0
+	do
+		case "$1" in
+		-b | --branch)
+			case "$2" in '') usage ;; esac
+			branch=$2
+			shift
+			;;
+		-q|--quiet)
+			quiet=1
+			;;
+		--)
+			shift
+			break
+			;;
+		-*)
+			usage
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+
 	repo=$1
 	path=$2
 
@@ -176,6 +199,27 @@ cmd_add()
 #
 cmd_init()
 {
+	# parse $args after "submodule ... init".
+	while test $# -ne 0
+	do
+		case "$1" in
+		-q|--quiet)
+			quiet=1
+			;;
+		--)
+			shift
+			break
+			;;
+		-*)
+			usage
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+
 	git ls-files --stage -- "$@" | grep -e '^160000 ' |
 	while read mode sha1 stage path
 	do
@@ -209,6 +253,27 @@ cmd_init()
 #
 cmd_update()
 {
+	# parse $args after "submodule ... update".
+	while test $# -ne 0
+	do
+		case "$1" in
+		-q|--quiet)
+			quiet=1
+			;;
+		--)
+			shift
+			break
+			;;
+		-*)
+			usage
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+
 	git ls-files --stage -- "$@" | grep -e '^160000 ' |
 	while read mode sha1 stage path
 	do
@@ -268,6 +333,30 @@ set_name_rev () {
 #
 cmd_status()
 {
+	# parse $args after "submodule ... status".
+	while test $# -ne 0
+	do
+		case "$1" in
+		-q|--quiet)
+			quiet=1
+			;;
+		--cached)
+			cached=1
+			;;
+		--)
+			shift
+			break
+			;;
+		-*)
+			usage
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+
 	git ls-files --stage -- "$@" | grep -e '^160000 ' |
 	while read mode sha1 stage path
 	do
@@ -293,20 +382,17 @@ cmd_status()
 	done
 }
 
-while test $# != 0
+# This loop parses the command line arguments to find the
+# subcommand name to dispatch.  Parsing of the subcommand specific
+# options are primarily done by the subcommand implementations.
+# Subcommand specific options such as --branch and --cached are
+# parsed here as well, for backward compatibility.
+
+while test $# != 0 && test -z "$command"
 do
 	case "$1" in
-	add)
-		add=1
-		;;
-	init)
-		init=1
-		;;
-	update)
-		update=1
-		;;
-	status)
-		status=1
+	add | init | update | status)
+		command=$1
 		;;
 	-q|--quiet)
 		quiet=1
@@ -335,30 +421,19 @@ do
 	shift
 done
 
-case "$add,$branch" in
-1,*)
-	;;
-,)
-	;;
-,*)
+# No command word defaults to "status"
+test -n "$command" || command=status
+
+# "-b branch" is accepted only by "add"
+if test -n "$branch" && test "$command" != add
+then
 	usage
-	;;
-esac
-
-case "$add,$init,$update,$status,$cached" in
-1,,,,)
-	cmd_add "$@"
-	;;
-,1,,,)
-	cmd_init "$@"
-	;;
-,,1,,)
-	cmd_update "$@"
-	;;
-,,,*,*)
-	cmd_status "$@"
-	;;
-*)
+fi
+
+# "--cached" is accepted only by "status"
+if test -n "$cached" && test "$command" != status
+then
 	usage
-	;;
-esac
+fi
+
+"cmd_$command" "$@"
-- 
1.5.4.rc3.11.g4e67
Previous: Junio C HamanoNext: Junio C Hamano
Message 6 of 7 in “- git submodule subcommand parsing modified.”
  1. - git submodule subcommand parsing modified.imyousuf@gmail.com, Jan 14, 2008
  2. Junio C HamanoJan 15, 2008
  3. 1/3 git-submodule: rename shell functions for consistencyJunio C Hamano, Jan 15, 2008
  4. Imran M YousufJan 16, 2008
  5. Junio C HamanoJan 16, 2008
  6. 2/3 git-submodule: fix subcommand parserJunio C Hamano, Jan 15, 2008
  7. 3/3 git-submodule: add test for the subcommand parser fixJunio C Hamano, Jan 15, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.