git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] - git submodule subcommand parsing modified.
@ 2008-01-14  3:22 imyousuf
  2008-01-15 10:13 ` Junio C Hamano
  0 siblings, 1 reply; 7+ messages in thread
From: imyousuf @ 2008-01-14  3:22 UTC (permalink / raw)
  To: git; +Cc: gitster, Imran M Yousuf

From: Imran M Yousuf <imyousuf@smartitengineering.com>

- manual page of git-submodule and usage mentioned in git-subcommand.sh
were not same, thus synchronized them. In doing so also had to change the
way the subcommands were parsed.

- Previous version did not allow commands such as
	git-submodule add init update
as the command parser incorrectly made subcommand names reserve.
Thus refusing them to be used as parameters to subcommands. As a result it
was impossible to add a submodule whose (symbolic) name is "init" and that
resides at path "update" was refused. For more details the following case
can be considered -

mkdir g; mkdir f; cd g/
touch g.txt; echo "sample text for g.txt" >> ./g.txt; git-init;
git-add g.txt; git-commit -a -m "First commit on g"
cd ../f/; ln -s ../g/ init
git-init; git-submodule add init update;
git-commit -a -m "With module update"
mkdir ../test; cd ../test
git-clone ../f/; cd f
git-submodule init update; git-submodule update update
cd ../..; rm -rf ./f/ ./test/ ./g/

This patch fixes this issue and allows it as well.

- Status currently is implemented to show list only but later
implementation might change and list and status could coexists. Thus
status module is introduced. The module is also used to parse its
arguments

- Subcommands will also parse their own commands; thus enabling command
specific arguments to be passed after the command. For example,
	git-submodule -q add -b master module_a
	git-submodule -q status -c
It is to be noted that -q or --quiet is specified before the subcommand
since it is for the submodule command in general rather than the
subcommand. It is mention worthy that backward compatibility exists and
thus commands like git submodule --cached status will also work as expected

- Subcommands that currently do not take any arguments (init and update)
has a case which is introduced just to ensure that no argument is
deliberately sent as the first argument and also to serve the purpose of
providing a future extension point for its arguments.

- Though ther was short and long version for quiet (-q or --quiet and
branch (-b or --branch) but there was no short version for cached. Thus
it is now introduced (-c or --cached).

- Added 3 specific messages for usage error related to branch and cached

- Simplified subcommand action invocation by simply invoking the action if
all conditions are fulfilled. Excepting for parsing command line arguments
case statements are avoided and instead more direct if statement is
introduced.
---
 git-submodule.sh |  158 +++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 114 insertions(+), 44 deletions(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index ad9fe62..22e7e5f 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -4,18 +4,23 @@
 #
 # Copyright (c) 2007 Lars Hjemli
 
-USAGE='[--quiet] [--cached] [add <repo> [-b branch]|status|init|update] [--] [<path>...]'
+# Synopsis of this commands are as follows
+# git-submodule [-q|--quiet] add [-b|--branch branch] <repository> [<path>]
+# git-submodule [-q|--quiet] [status] [-c|--cached] [--] [<path>...]
+# git-submodule [-q|--quiet] init [--] [<path>...]
+# git-submodule [-q|--quiet] update [--] [<path>...]
+USAGE='[-q|--quiet] [[[add [-b|--branch branch] <repo>]|[[[status [-c|--cached]]|init|update] [--]]]  [<path>...]]'
 OPTIONS_SPEC=
 . git-sh-setup
 require_work_tree
 
+MODULES_LIST='modules_list'
+
 add=
 branch=
-init=
-update=
-status=
 quiet=
 cached=
+command=
 
 #
 # print stuff on stdout unless -q was specified
@@ -114,6 +119,17 @@ module_clone()
 	die "Clone of '$url' into submodule path '$path' failed"
 }
 
+# Parses the branch name and exits if not present
+parse_branch_name()
+{
+	branch="$1"; 
+	if test -z "$branch"
+	then
+		echo Branch name must me specified	
+		usage
+	fi
+}
+
 #
 # Add a new submodule to the working tree, .gitmodules and the index
 #
@@ -123,6 +139,16 @@ module_clone()
 #
 module_add()
 {
+	case "$1" in
+		-b|--branch)
+			shift
+			parse_branch_name "$@" &&
+			shift
+			;;
+		-*)
+			usage
+			;;
+	esac
 	repo=$1
 	path=$2
 
@@ -176,6 +202,14 @@ module_add()
 #
 modules_init()
 {
+	# Added here to ensure that no argument is passed to be treated as
+	# parameter to the sub command. This will be used to parse any 
+	# to the subcommand
+	case "$1" in
+		-*)
+			usage
+			;;
+	esac
 	git ls-files --stage -- "$@" | grep -e '^160000 ' |
 	while read mode sha1 stage path
 	do
@@ -209,6 +243,14 @@ modules_init()
 #
 modules_update()
 {
+	# Added here to ensure that no argument is passed to be treated as
+	# parameter to the sub command. This will be used to parse any 
+	# to the subcommand
+	case "$1" in
+		-*)
+			usage
+			;;
+	esac
 	git ls-files --stage -- "$@" | grep -e '^160000 ' |
 	while read mode sha1 stage path
 	do
@@ -293,36 +335,69 @@ modules_list()
 	done
 }
 
+# Delgates to modules_list after parsing its arguments
+modules_status()
+{
+	case "$1" in
+		-c|--cached)
+			shift
+			cached=1
+			;;
+		-*)
+			usage
+			;;
+	esac
+	"$MODULES_LIST" "$@"
+}
+
+# If there is '--' as the first argument simply ignores it and thus shifts
+check_for_terminator()
+{
+	if test -n "$1" && test "$1" = "--"
+	then
+		shift
+	fi
+}
+
+
+
+# Command synopsis clearly shows that all arguments after
+# subcommand are arguments to the command itself. Thus
+# there lies no command that has configuration argument
+# after the mention of the subcommand. Thus once the
+# subcommand is found and the separator ('--') is ignored
+# rest can be safely sent the subcommand action
+# It is to be noted that pre-subcommand arguments are parsed
+# just to have backward compatibility.
 while test $# != 0
 do
 	case "$1" in
 	add)
 		add=1
+		command="module_$1"
+		shift
+		break
 		;;
-	init)
-		init=1
-		;;
-	update)
-		update=1
-		;;
-	status)
-		status=1
+	init|update|status)
+		command="modules_$1"
+		shift
+		check_for_terminator "$1"
+		break
 		;;
 	-q|--quiet)
 		quiet=1
 		;;
 	-b|--branch)
-		case "$2" in
-		'')
-			usage
-			;;
-		esac
-		branch="$2"; shift
+		shift
+		parse_branch_name "$@"
 		;;
-	--cached)
+	-c|--cached)
 		cached=1
 		;;
 	--)
+		# It is shifted so that it is not passed
+		# as an argument to the default subcommand
+		shift
 		break
 		;;
 	-*)
@@ -335,30 +410,25 @@ do
 	shift
 done
 
-case "$add,$branch" in
-1,*)
-	;;
-,)
-	;;
-,*)
+# Throws usage error if branch is not used with add command
+if test -n "$branch" &&
+   test -z "$add"
+then
+	echo Branch can not be specified without add subcommand
 	usage
-	;;
-esac
-
-case "$add,$init,$update,$status,$cached" in
-1,,,,)
-	module_add "$@"
-	;;
-,1,,,)
-	modules_init "$@"
-	;;
-,,1,,)
-	modules_update "$@"
-	;;
-,,,*,*)
-	modules_list "$@"
-	;;
-*)
+fi
+
+# If no command is specified then default command
+# is - git submodule status
+test -z "$command" && command="modules_status"
+
+# Throws usage if --cached is used by other than status, init or update
+# that is used with add command
+if test -n "$cached" &&
+   test "$command" != "modules_status"
+then
+	echo Cached can only be used with the status subcommand
 	usage
-	;;
-esac
+fi
+
+"$command" "$@"
-- 
1.5.3.7

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] - git submodule subcommand parsing modified.
  2008-01-14  3:22 [PATCH] - git submodule subcommand parsing modified imyousuf
@ 2008-01-15 10:13 ` Junio C Hamano
  2008-01-15 11:18   ` [PATCH 1/3] git-submodule: rename shell functions for consistency Junio C Hamano
                     ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Junio C Hamano @ 2008-01-15 10:13 UTC (permalink / raw)
  To: imyousuf; +Cc: git, Imran M Yousuf

imyousuf@gmail.com writes:

> From: Imran M Yousuf <imyousuf@smartitengineering.com>
>
> - manual page of git-submodule and usage mentioned in git-subcommand.sh
> were not same, thus synchronized them. In doing so also had to change the
> way the subcommands were parsed.
>
> - Previous version did not allow commands such as
> 	git-submodule add init update
> as the command parser incorrectly made subcommand names reserve.
> Thus refusing them to be used as parameters to subcommands. As a result it
> was impossible to add a submodule whose (symbolic) name is "init" and that
> resides at path "update" was refused. For more details the following case
> can be considered -
>
> mkdir g; mkdir f; cd g/
> touch g.txt; echo "sample text for g.txt" >> ./g.txt; git-init;
> git-add g.txt; git-commit -a -m "First commit on g"
> cd ../f/; ln -s ../g/ init
> git-init; git-submodule add init update;
> git-commit -a -m "With module update"
> mkdir ../test; cd ../test
> git-clone ../f/; cd f
> git-submodule init update; git-submodule update update
> cd ../..; rm -rf ./f/ ./test/ ./g/

 - I'd drop everything after "For more details...".  If you feel
   that the part before "For more details" cannot be understood
   without that thick and solid sample script, perhaps that
   description needs to be rewritten to make it easier to
   understand (personally I do not see it as hard to understand,
   modulo grammatical errors).

> This patch fixes this issue and allows it as well.

 - "it" in this sentence can easily be mistaken as referring to
   "this issue".  I'd suggest dropping "and allows...".

> - Status currently is implemented to show list only but later
> implementation might change and list and status could coexists. Thus
> status module is introduced. The module is also used to parse its
> arguments

 - That is probably better in a separate patch, if the purpose
   of the patch is about straightening out the command parser to
   fix existing issues.  Generally it is a good idea to have
   fixes and enhancement as separate patches.

> - Subcommands will also parse their own commands; thus enabling command
> specific arguments to be passed after the command. For example,
> 	git-submodule -q add -b master module_a
> 	git-submodule -q status -c
> It is to be noted that -q or --quiet is specified before the subcommand
> since it is for the submodule command in general rather than the
> subcommand. It is mention worthy that backward compatibility exists and
> thus commands like git submodule --cached status will also work as expected

 - I have a mild distaste against commands that expect the users
   to intimately know what option is command wide and what
   option is subcommand specific.  IOW it is not very nice to
   accept "git submodule -q status" and reject "git submodule
   status -q".

> - Subcommands that currently do not take any arguments (init and update)
> has a case which is introduced just to ensure that no argument is
> deliberately sent as the first argument and also to serve the purpose of
> providing a future extension point for its arguments.

 - As far as I understand what they do, they both do take
   paths arguments to name specific modules, so the above
   sentence is bogus.  Maybe you meant rejecting non-existent
   options, and I'd agree with the intent if that is the case
   (but your implementation around -- is bogus).

> - Though ther was short and long version for quiet (-q or --quiet and
> branch (-b or --branch) but there was no short version for cached. Thus
> it is now introduced (-c or --cached).
>
> - Added 3 specific messages for usage error related to branch and cached
>
> - Simplified subcommand action invocation by simply invoking the action if
> all conditions are fulfilled. Excepting for parsing command line arguments
> case statements are avoided and instead more direct if statement is
> introduced.
> ---

 - Lacks sign-off.

 - The message felt very hard to read.  Perhaps it is just that
   these unindented sentences in bullet-list, together with the
   two displayed command line that are not separated from the
   rest of the text with a blank line, hurts the eyes.

 - Perhaps the patch tries to do too many things.  For example,
   introduction of -c does not have to belong here.  nor
   "status" which currently is the same as "list".  Maybe that
   is why the description needs to talk about too many things,
   which in turn could be the reason why I find the above
   message very hard to read.

> diff --git a/git-submodule.sh b/git-submodule.sh
> index ad9fe62..22e7e5f 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -4,18 +4,23 @@
>  #
>  # Copyright (c) 2007 Lars Hjemli
>  
> -USAGE='[--quiet] [--cached] [add <repo> [-b branch]|status|init|update] [--] [<path>...]'
> +# Synopsis of this commands are as follows
> +# git-submodule [-q|--quiet] add [-b|--branch branch] <repository> [<path>]
> +# git-submodule [-q|--quiet] [status] [-c|--cached] [--] [<path>...]
> +# git-submodule [-q|--quiet] init [--] [<path>...]
> +# git-submodule [-q|--quiet] update [--] [<path>...]
> +USAGE='[-q|--quiet] [[[add [-b|--branch branch] <repo>]|[[[status [-c|--cached]]|init|update] [--]]]  [<path>...]]'
>  OPTIONS_SPEC=
>  . git-sh-setup
>  require_work_tree
>  
> +MODULES_LIST='modules_list'
> +

 - What's the purpose of this variable?  If you are planning to
   change the default command by changing the value of this
   variable, then the variable is not about MODULES_LIST, but
   about DEFAULT_COMMAND or something, and should be named as
   such.

>  add=
>  branch=
> -init=
> -update=
> -status=
>  quiet=
>  cached=
> +command=
>  
>  #
>  # print stuff on stdout unless -q was specified
> @@ -114,6 +119,17 @@ module_clone()
>  	die "Clone of '$url' into submodule path '$path' failed"
>  }
>  
> +# Parses the branch name and exits if not present
> +parse_branch_name()
> +{
> +	branch="$1"; 
> +	if test -z "$branch"
> +	then
> +		echo Branch name must me specified	
> +		usage
> +	fi

 - Shouldn't the message go to stderr?

 - If we use "usage", that already tells the user -b is followed
   by branch.  Is the extra message needed in the first place?
   If this patch is about "fixing", perhaps you should not be
   mixing this kind of unnecessary changes in it.

> +}
> +
>  #
>  # Add a new submodule to the working tree, .gitmodules and the index
>  #
> @@ -123,6 +139,16 @@ module_clone()
>  #
>  module_add()
>  {
> +	case "$1" in
> +		-b|--branch)
> +			shift
> +			parse_branch_name "$@" &&
> +			shift
> +			;;
> +		-*)
> +			usage
> +			;;
> +	esac

 - Style.  Please align case arms with "case/esac", like other
   scripts (and the original version of this script) do.  I.e.

	case "$1" in
        -b|--branch)
                ...
	esac

   This comment applies to other parts of the patch as well.

>  	repo=$1
>  	path=$2
>  
> @@ -176,6 +202,14 @@ module_add()
>  #
>  modules_init()
>  {
> +	# Added here to ensure that no argument is passed to be treated as
> +	# parameter to the sub command. This will be used to parse any 
> +	# to the subcommand
> +	case "$1" in
> +		-*)
> +			usage
> +			;;
> +	esac

 - If I understand correctly, "git submodule init" takes paths
   to submodules as arguments.  Are you disallowing paths that
   begin with '-', even though the body of the command (ls-files
   piped to while loop) is written in such a way that is
   perfectly capable of handling such a path?

>  	git ls-files --stage -- "$@" | grep -e '^160000 ' |
>  	while read mode sha1 stage path
>  	do
> @@ -209,6 +243,14 @@ modules_init()
>  #
>  modules_update()
>  {
> +	# Added here to ensure that no argument is passed to be treated as
> +	# parameter to the sub command. This will be used to parse any 
> +	# to the subcommand
> +	case "$1" in
> +		-*)
> +			usage
> +			;;
> +	esac

 - The same comment as modules_init() above applies here.

>  	git ls-files --stage -- "$@" | grep -e '^160000 ' |
>  	while read mode sha1 stage path
>  	do
> @@ -293,36 +335,69 @@ modules_list()
>  	done
>  }
>  
> +# Delgates to modules_list after parsing its arguments

 - That's "delegates", but typically when we write a sentence
   without the subject like this in the comment, we use the
   imperative mood, so "Delegate to modules_list after ..."
   would be more appropriate.

> +modules_status()
> +{
> +	case "$1" in
> +		-c|--cached)
> +			shift
> +			cached=1
> +			;;
> +		-*)
> +			usage
> +			;;
> +	esac
> +	"$MODULES_LIST" "$@"
> +}

 - The same comment as modules_init() above applies here.

> +# If there is '--' as the first argument simply ignores it and thus shifts
> +check_for_terminator()
> +{
> +	if test -n "$1" && test "$1" = "--"
> +	then
> +		shift
> +	fi
> +}

 - That 'test -n "$1" && test "$1" = "--"' feels stupid; if "$1"
   is equal to "--", it certainly will be -n (i.e. not empty).
   Perhaps 'test $# -ge 1 && test "$1" = "--"' or even just
   'test "$1" = "--"'.

 - I do not think the 'shift' does anything useful.  It does not
   shift the positional parameters of the caller of this shell
   function, and would be a noop from the caller's point of
   view.  It only shifts the positional parameters inside this
   function (study e.g. "2.9.5 Function Definition Command",
   http://www.opengroup.org/onlinepubs/000095399/utilities/xcu_chap02.html).

> +# Command synopsis clearly shows that all arguments after
> +# subcommand are arguments to the command itself. Thus
> +# there lies no command that has configuration argument
> +# after the mention of the subcommand. Thus once the
> +# subcommand is found and the separator ('--') is ignored
> +# rest can be safely sent the subcommand action

 - That's a valid justification but I think it is enough to say
   what it does (i.e. "Arguments after the subcommand name are
   given to the subcommand").  How you arrived to that design
   decision (i.e. your justification based on the synopsis) does
   not belong here.  It could however be part of the commit log
   message.

 - I do not agree with the (attempted) stripping of -- you talk
   about here (that is done in the loop below).

> +# It is to be noted that pre-subcommand arguments are parsed
> +# just to have backward compatibility.

 - Because we might want to deprecate and remove forms like "-b
   branch add" later, this is a good comment to have here.  It
   makes it clear that these oddballs are purely for backward
   compatibility.

>  while test $# != 0
>  do
>  	case "$1" in
>  	add)
>  		add=1
> +		command="module_$1"
> +		shift
> +		break
>  		;;
> -	init)
> -		init=1
> -		;;
> -	update)
> -		update=1
> -		;;
> -	status)
> -		status=1
> +	init|update|status)
> +		command="modules_$1"
> +		shift
> +		check_for_terminator "$1"
> +		break
>  		;;

 - Aside from my earlier comment that the code would become
   simpler if you consistently renamed the shell functions to
   module_$foo (or cmd_$foo) so that the dispatcher can follow a
   simple rule "subcommand $foo is handled by shell function
   cmd_$foo", which you seem to have ignored, and also aside
   from that your check_for_terminator does not do what you seem
   to have intended (see above), I think this handling of -- is
   wrong.  By stripping -- here, you are making the following
   two behave exactly the same:

   $ git submodule update -- $other_args
   $ git submodule update    $other_args

   The whole point of -- is so that you can tell the command
   that the argument at the beginning of $other_args that
   happens to begin with a dash is _not_ an option but is a
   literal path (or whatever).  Think of the case in which you
   had '-foo' and 'bar' in place of $other_args above.  The
   first one tells the command to update two modules ('-foo' and
   'bar'), the second one tells the command to update 'bar'
   module but the update operation needs to be done with -foo
   option (whatever that option means to 'update' command).

   By checking and shifting -- out, you are making it impossible
   for the implementation of the command (i.e. your
   "modules_update") to tell which case it is dealing with.

>  	-q|--quiet)
>  		quiet=1
>  		;;
>  	-b|--branch)
> -		case "$2" in
> -		'')
> -			usage
> -			;;
> -		esac
> -		branch="$2"; shift
> +		shift
> +		parse_branch_name "$@"
>  		;;
> -	--cached)
> +	-c|--cached)
>  		cached=1
>  		;;
>  	--)
> +		# It is shifted so that it is not passed
> +		# as an argument to the default subcommand
> +		shift
>  		break
>  		;;
>  	-*)
> @@ -335,30 +410,25 @@ do
>  	shift
>  done
>  
> -case "$add,$branch" in
> -1,*)
> -	;;
> -,)
> -	;;
> -,*)
> +# Throws usage error if branch is not used with add command
> +if test -n "$branch" &&
> +   test -z "$add"
> +then
> +	echo Branch can not be specified without add subcommand
>  	usage
> -	;;
> -esac
> -
> -case "$add,$init,$update,$status,$cached" in
> -1,,,,)
> -	module_add "$@"
> -	;;
> -,1,,,)
> -	modules_init "$@"
> -	;;
> -,,1,,)
> -	modules_update "$@"
> -	;;
> -,,,*,*)
> -	modules_list "$@"
> -	;;
> -*)
> +fi
> +
> +# If no command is specified then default command
> +# is - git submodule status
> +test -z "$command" && command="modules_status"
> +
> +# Throws usage if --cached is used by other than status, init or update
> +# that is used with add command
> +if test -n "$cached" &&
> +   test "$command" != "modules_status"
> +then
> +	echo Cached can only be used with the status subcommand
>  	usage
> -	;;
> -esac
> +fi
> +
> +"$command" "$@"
> -- 
> 1.5.3.7

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] git-submodule: rename shell functions for consistency
  2008-01-15 10:13 ` Junio C Hamano
@ 2008-01-15 11:18   ` Junio C Hamano
  2008-01-16  2:26     ` Imran M Yousuf
  2008-01-15 11:19   ` [PATCH 2/3] git-submodule: fix subcommand parser Junio C Hamano
  2008-01-15 11:20   ` [PATCH 3/3] git-submodule: add test for the subcommand parser fix Junio C Hamano
  2 siblings, 1 reply; 7+ messages in thread
From: Junio C Hamano @ 2008-01-15 11:18 UTC (permalink / raw)
  To: imyousuf; +Cc: git, Imran M Yousuf

This renames the shell functions used in git-submodule that
implement top-level subcommands.  The rule is that the
subcommand $foo is implemented by cmd_$foo function.

A noteworthy change is that modules_list() is now known as
cmd_status().  There is no "submodule list" command.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 * We could probably do something like this.  This first part is
   about making the command dispatcher maintainable.

   Note that I haven't seriously tested this series.  This and
   the next one are primarily to illustrate what I think the fix
   you are trying should look like.

 git-submodule.sh |   20 ++++++++++----------
 1 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/git-submodule.sh b/git-submodule.sh
index ad9fe62..3c104e3 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -86,9 +86,9 @@ module_name()
 #
 # Clone a submodule
 #
-# Prior to calling, modules_update checks that a possibly existing
+# Prior to calling, cmd_update checks that a possibly existing
 # path is not a git repository.
-# Likewise, module_add checks that path does not exist at all,
+# Likewise, cmd_add checks that path does not exist at all,
 # since it is the location of a new submodule.
 #
 module_clone()
@@ -121,7 +121,7 @@ module_clone()
 #
 # optional branch is stored in global branch variable
 #
-module_add()
+cmd_add()
 {
 	repo=$1
 	path=$2
@@ -174,7 +174,7 @@ module_add()
 #
 # $@ = requested paths (default to all)
 #
-modules_init()
+cmd_init()
 {
 	git ls-files --stage -- "$@" | grep -e '^160000 ' |
 	while read mode sha1 stage path
@@ -207,7 +207,7 @@ modules_init()
 #
 # $@ = requested paths (default to all)
 #
-modules_update()
+cmd_update()
 {
 	git ls-files --stage -- "$@" | grep -e '^160000 ' |
 	while read mode sha1 stage path
@@ -266,7 +266,7 @@ set_name_rev () {
 #
 # $@ = requested paths (default to all)
 #
-modules_list()
+cmd_status()
 {
 	git ls-files --stage -- "$@" | grep -e '^160000 ' |
 	while read mode sha1 stage path
@@ -347,16 +347,16 @@ esac
 
 case "$add,$init,$update,$status,$cached" in
 1,,,,)
-	module_add "$@"
+	cmd_add "$@"
 	;;
 ,1,,,)
-	modules_init "$@"
+	cmd_init "$@"
 	;;
 ,,1,,)
-	modules_update "$@"
+	cmd_update "$@"
 	;;
 ,,,*,*)
-	modules_list "$@"
+	cmd_status "$@"
 	;;
 *)
 	usage
-- 
1.5.4.rc3.11.g4e67

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] git-submodule: fix subcommand parser
  2008-01-15 10:13 ` Junio C Hamano
  2008-01-15 11:18   ` [PATCH 1/3] git-submodule: rename shell functions for consistency Junio C Hamano
@ 2008-01-15 11:19   ` Junio C Hamano
  2008-01-15 11:20   ` [PATCH 3/3] git-submodule: add test for the subcommand parser fix Junio C Hamano
  2 siblings, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2008-01-15 11:19 UTC (permalink / raw)
  To: imyousuf; +Cc: git, Imran M Yousuf

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

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] git-submodule: add test for the subcommand parser fix
  2008-01-15 10:13 ` Junio C Hamano
  2008-01-15 11:18   ` [PATCH 1/3] git-submodule: rename shell functions for consistency Junio C Hamano
  2008-01-15 11:19   ` [PATCH 2/3] git-submodule: fix subcommand parser Junio C Hamano
@ 2008-01-15 11:20   ` Junio C Hamano
  2 siblings, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2008-01-15 11:20 UTC (permalink / raw)
  To: imyousuf; +Cc: git, Imran M Yousuf

This modifies the existing t7400 test to use 'init' as the
pathname that a submodule is bound to.  Without the earlier
subcommand parser fix, this fails.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/t7400-submodule-basic.sh |   56 ++++++++++++++++++++++----------------------
 1 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 4fe3a41..2ef85a8 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -13,11 +13,11 @@ subcommands of git-submodule.
 
 #
 # Test setup:
-#  -create a repository in directory lib
+#  -create a repository in directory init
 #  -add a couple of files
-#  -add directory lib to 'superproject', this creates a DIRLINK entry
+#  -add directory init to 'superproject', this creates a DIRLINK entry
 #  -add a couple of regular files to enable testing of submodule filtering
-#  -mv lib subrepo
+#  -mv init subrepo
 #  -add an entry to .gitmodules for submodule 'example'
 #
 test_expect_success 'Prepare submodule testing' '
@@ -25,8 +25,8 @@ test_expect_success 'Prepare submodule testing' '
 	git-add t &&
 	git-commit -m "initial commit" &&
 	git branch initial HEAD &&
-	mkdir lib &&
-	cd lib &&
+	mkdir init &&
+	cd init &&
 	git init &&
 	echo a >a &&
 	git add a &&
@@ -41,10 +41,10 @@ test_expect_success 'Prepare submodule testing' '
 	cd .. &&
 	echo a >a &&
 	echo z >z &&
-	git add a lib z &&
+	git add a init z &&
 	git-commit -m "super commit 1" &&
-	mv lib .subrepo &&
-	GIT_CONFIG=.gitmodules git config submodule.example.url git://example.com/lib.git
+	mv init .subrepo &&
+	GIT_CONFIG=.gitmodules git config submodule.example.url git://example.com/init.git
 '
 
 test_expect_success 'status should fail for unmapped paths' '
@@ -52,7 +52,7 @@ test_expect_success 'status should fail for unmapped paths' '
 	then
 		echo "[OOPS] submodule status succeeded"
 		false
-	elif ! GIT_CONFIG=.gitmodules git config submodule.example.path lib
+	elif ! GIT_CONFIG=.gitmodules git config submodule.example.path init
 	then
 		echo "[OOPS] git config failed to update .gitmodules"
 		false
@@ -71,7 +71,7 @@ test_expect_success 'status should initially be "missing"' '
 test_expect_success 'init should register submodule url in .git/config' '
 	git-submodule init &&
 	url=$(git config submodule.example.url) &&
-	if test "$url" != "git://example.com/lib.git"
+	if test "$url" != "git://example.com/init.git"
 	then
 		echo "[OOPS] init succeeded but submodule url is wrong"
 		false
@@ -83,41 +83,41 @@ test_expect_success 'init should register submodule url in .git/config' '
 '
 
 test_expect_success 'update should fail when path is used by a file' '
-	echo "hello" >lib &&
+	echo "hello" >init &&
 	if git-submodule update
 	then
 		echo "[OOPS] update should have failed"
 		false
-	elif test "$(cat lib)" != "hello"
+	elif test "$(cat init)" != "hello"
 	then
-		echo "[OOPS] update failed but lib file was molested"
+		echo "[OOPS] update failed but init file was molested"
 		false
 	else
-		rm lib
+		rm init
 	fi
 '
 
 test_expect_success 'update should fail when path is used by a nonempty directory' '
-	mkdir lib &&
-	echo "hello" >lib/a &&
+	mkdir init &&
+	echo "hello" >init/a &&
 	if git-submodule update
 	then
 		echo "[OOPS] update should have failed"
 		false
-	elif test "$(cat lib/a)" != "hello"
+	elif test "$(cat init/a)" != "hello"
 	then
-		echo "[OOPS] update failed but lib/a was molested"
+		echo "[OOPS] update failed but init/a was molested"
 		false
 	else
-		rm lib/a
+		rm init/a
 	fi
 '
 
 test_expect_success 'update should work when path is an empty dir' '
-	rm -rf lib &&
-	mkdir lib &&
+	rm -rf init &&
+	mkdir init &&
 	git-submodule update &&
-	head=$(cd lib && git rev-parse HEAD) &&
+	head=$(cd init && git rev-parse HEAD) &&
 	if test -z "$head"
 	then
 		echo "[OOPS] Failed to obtain submodule head"
@@ -134,7 +134,7 @@ test_expect_success 'status should be "up-to-date" after update' '
 '
 
 test_expect_success 'status should be "modified" after submodule commit' '
-	cd lib &&
+	cd init &&
 	echo b >b &&
 	git add b &&
 	git-commit -m "submodule commit 2" &&
@@ -157,8 +157,8 @@ test_expect_success 'git diff should report the SHA1 of the new submodule commit
 '
 
 test_expect_success 'update should checkout rev1' '
-	git-submodule update &&
-	head=$(cd lib && git rev-parse HEAD) &&
+	git-submodule update init &&
+	head=$(cd init && git rev-parse HEAD) &&
 	if test -z "$head"
 	then
 		echo "[OOPS] submodule git rev-parse returned nothing"
@@ -182,13 +182,13 @@ test_expect_success 'checkout superproject with subproject already present' '
 test_expect_success 'apply submodule diff' '
 	git branch second &&
 	(
-		cd lib &&
+		cd init &&
 		echo s >s &&
 		git add s &&
 		git commit -m "change subproject"
 	) &&
-	git update-index --add lib &&
-	git-commit -m "change lib" &&
+	git update-index --add init &&
+	git-commit -m "change init" &&
 	git-format-patch -1 --stdout >P.diff &&
 	git checkout second &&
 	git apply --index P.diff &&
-- 
1.5.4.rc3.11.g4e67

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] git-submodule: rename shell functions for consistency
  2008-01-15 11:18   ` [PATCH 1/3] git-submodule: rename shell functions for consistency Junio C Hamano
@ 2008-01-16  2:26     ` Imran M Yousuf
  2008-01-16 20:08       ` Junio C Hamano
  0 siblings, 1 reply; 7+ messages in thread
From: Imran M Yousuf @ 2008-01-16  2:26 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Thanks Junio for showing how it should be done. Due to some
pre-scheduled appointment I was unavailable yesterday evening and thus
was neither able to reply nor resubmit the changes.

On Jan 15, 2008 5:18 PM, Junio C Hamano <gitster@pobox.com> wrote:
> This renames the shell functions used in git-submodule that
> implement top-level subcommands.  The rule is that the
> subcommand $foo is implemented by cmd_$foo function.
>
> A noteworthy change is that modules_list() is now known as
> cmd_status().  There is no "submodule list" command.
>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>
>  * We could probably do something like this.  This first part is
>    about making the command dispatcher maintainable.
>
>    Note that I haven't seriously tested this series.  This and
>    the next one are primarily to illustrate what I think the fix
>    you are trying should look like.
>
>  git-submodule.sh |   20 ++++++++++----------
>  1 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/git-submodule.sh b/git-submodule.sh
> index ad9fe62..3c104e3 100755
> --- a/git-submodule.sh
> +++ b/git-submodule.sh
> @@ -86,9 +86,9 @@ module_name()
>  #
>  # Clone a submodule
>  #
> -# Prior to calling, modules_update checks that a possibly existing
> +# Prior to calling, cmd_update checks that a possibly existing
>  # path is not a git repository.
> -# Likewise, module_add checks that path does not exist at all,
> +# Likewise, cmd_add checks that path does not exist at all,
>  # since it is the location of a new submodule.
>  #
>  module_clone()
> @@ -121,7 +121,7 @@ module_clone()
>  #
>  # optional branch is stored in global branch variable
>  #
> -module_add()
> +cmd_add()

After reading your reply I was about to suggest renaming module to cmd
but you have done it before I could propose or submit the patch.

>  {
>         repo=$1
>         path=$2
> @@ -174,7 +174,7 @@ module_add()
>  #
>  # $@ = requested paths (default to all)
>  #
> -modules_init()
> +cmd_init()
>  {
>         git ls-files --stage -- "$@" | grep -e '^160000 ' |
>         while read mode sha1 stage path
> @@ -207,7 +207,7 @@ modules_init()
>  #
>  # $@ = requested paths (default to all)
>  #
> -modules_update()
> +cmd_update()
>  {
>         git ls-files --stage -- "$@" | grep -e '^160000 ' |
>         while read mode sha1 stage path
> @@ -266,7 +266,7 @@ set_name_rev () {
>  #
>  # $@ = requested paths (default to all)
>  #
> -modules_list()
> +cmd_status()
>  {
>         git ls-files --stage -- "$@" | grep -e '^160000 ' |
>         while read mode sha1 stage path
> @@ -347,16 +347,16 @@ esac
>
>  case "$add,$init,$update,$status,$cached" in
>  1,,,,)
> -       module_add "$@"
> +       cmd_add "$@"
>         ;;
>  ,1,,,)
> -       modules_init "$@"
> +       cmd_init "$@"
>         ;;
>  ,,1,,)
> -       modules_update "$@"
> +       cmd_update "$@"
>         ;;
>  ,,,*,*)
> -       modules_list "$@"
> +       cmd_status "$@"
>         ;;
>  *)
>         usage
> --
> 1.5.4.rc3.11.g4e67
>
>



-- 
Imran M Yousuf

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] git-submodule: rename shell functions for consistency
  2008-01-16  2:26     ` Imran M Yousuf
@ 2008-01-16 20:08       ` Junio C Hamano
  0 siblings, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2008-01-16 20:08 UTC (permalink / raw)
  To: Imran M Yousuf; +Cc: Junio C Hamano, git

"Imran M Yousuf" <imyousuf@gmail.com> writes:

> Thanks Junio for showing how it should be done. Due to some
> pre-scheduled appointment I was unavailable yesterday evening and thus
> was neither able to reply nor resubmit the changes.

Well, I did not show how it _should_ be done.  That series was
merely an illustration of how I _think_ it should look like.  I
did not test it, I do not know if it introduced new bugs, and
most importantly I do not know if it fulfills what you intended
to achieve with your patch.

In other words, I just tried to turn the table around.  Instead
of me and others commenting on your patch saying "I do not like
this" piecemeal, now you have something you can comment on.  You
can say the whole range of things from "I tested this and it is
what I want", "I like the general concept but I found this and
that bug and here is a fix", to "This is much worse than what I
proposed and here is why."

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2008-01-16 20:09 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-14  3:22 [PATCH] - git submodule subcommand parsing modified imyousuf
2008-01-15 10:13 ` Junio C Hamano
2008-01-15 11:18   ` [PATCH 1/3] git-submodule: rename shell functions for consistency Junio C Hamano
2008-01-16  2:26     ` Imran M Yousuf
2008-01-16 20:08       ` Junio C Hamano
2008-01-15 11:19   ` [PATCH 2/3] git-submodule: fix subcommand parser Junio C Hamano
2008-01-15 11:20   ` [PATCH 3/3] git-submodule: add test for the subcommand parser fix Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).