Sorry for the inconvenience, but please ignore this patch as it was not generated with -n and version number :(. - best regards, Imran On Mon, May 5, 2008 at 2:44 PM, <imyousuf@xxxxxxxxx> wrote: > From: Imran M Yousuf <imyousuf@xxxxxxxxxxxxxxxxxxxxxx> > > The purpose of the recurse command in the git submodule is to recurse > a command in its submodule. For example if one wants to do a diff on its > project with submodules at once, one can simply do > git-submodule recurse diff HEAD > and would see the diff for all the modules it contains. > > The recurse commands behavior can be customized with several arguments > that it accepts. The synopsis for the recurse command is: > > git-submodule recurse [-q|--quiet] [-e|--exit-after-error] > [-d|--depth <recursion depth>] [-b|--breadth-first] > <git command> [<arguments> ...] > > There are commands that can fail for a certain submodule but succeed for > others; if one wants to stop execution once the top level module's execution > fails, one can specify [-e|--exit-after-error]. It will ensure that once > execution of git <command> fails in the top level module it will not recurse > into its submodules. > > If the project has submodule hierarchy upto n depth and we want to restrict > recursion to (n-p) depth; we can use the [-d|--depth <recursion depth>] option. > Value has to be greater than 0 and command will at least recurse into the first > depth. If depth is specified to p than all depths <= p will be recursed over. > > While discussion on the recurse command one thing which was put forward > in several occassions is that there might be scenario where a command should be > executed over the child module before the parent module. > > For such scenario [-b|--breadth-first] option can be used; one use case > in particular presented as an example is git commit; where almost everybody > mentioned that they prefer to commit the child module before the parent and > default will enable just that. > > E.g. p -> a, b, c, e; a ->d is a module structure. If the following command is > used, > > git submodule recurse commit -a > > it will execute git commit -a in the following sequence - d, a, b, c, e, p. > > Now if one want to instead go in a breadth first manner then one can > specify -b option. E.g. if the above command is - > > git submodule recurse -b commit -a > > it will execute git commit -a in the following sequence - p, a, d, b, c, e. > > Signed-off-by: Imran M Yousuf <imyousuf@xxxxxxxxxxxxxxxxxxxxxx> > --- > git-submodule.sh | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 files changed, 130 insertions(+), 2 deletions(-) > > diff --git a/git-submodule.sh b/git-submodule.sh > index a5ee2e5..8161d51 100755 > --- a/git-submodule.sh > +++ b/git-submodule.sh > @@ -11,7 +11,8 @@ Use $0 -h for more details" > LONG_USAGE="$0 add [-q|--quiet] [-b|--branch branch] <repository> [<path>] > $0 [status] [-q|--quiet] [-c|--cached] [--] [<path>...] > $0 init|update [-q|--quiet] [--] [<path>...] > -$0 summary [--cached] [-n|--summary-limit <n>] [<commit>]" > +$0 summary [--cached] [-n|--summary-limit <n>] [<commit>] > +$0 recurse [-q|--quiet] [-e|--exit-after-error] [-d|--depth <recursion depth>] [-b|--breadth-first] <git command> [<args> ...]" > OPTIONS_SPEC= > . git-sh-setup > require_work_tree > @@ -20,6 +21,10 @@ command= > branch= > quiet= > cached= > +depth=0 > +current_depth=0 > +depth_first=1 > +on_error= > > # > # print stuff on stdout unless -q was specified > @@ -580,6 +585,129 @@ cmd_status() > done > } > > +# Check whether the submodule is initialized or not > +initialize_sub_module() > +{ > + if test ! -d "$1"/.git > + then > + say "Submodule $1 is not initialized and skipped" > + return 1 > + # Returns true if submodule is already initialized > + elif test -d "$1"/.git > + then > + return 0 > + fi > +} > + > +# This function simply checks whether the depth is traverseable in terms of > +# depth and if so then it sequentially traverses its submodules > +traverse_submodules() > +{ > + # If current depth is the range specified than it will continue > + # else return with success > + if test "$depth" -gt 0 && > + test "$current_depth" -ge "$depth" > + then > + return 0; > + fi > + # If submodules exists than it will traverse over them > + if test -f .gitmodules > + then > + # Incrementing the depth for the next level of submodules > + current_depth=$(($current_depth + 1)) > + for mod_path in `sed -n -e 's/path = //p' .gitmodules`; do > + traverse_module "$mod_path" "$@" > + done > + # Decremented the depth to bring it back to the depth of > + # the current submodule > + current_depth=$(($current_depth - 1)) > + fi > +} > + > +# This actually traverses a submodule; checks whether the its initialized > +# or not, does nothing if not initialized. > +traverse_module() > +{ > + # Will work in the submodule if and only if its initialized > + initialize_sub_module "$1" && > + ( > + submod_path="$1" > + shift > + cd "$submod_path" > + # If depth-first is specified in that case submodules are > + # are traversed before executing the command on this submodule > + test -n "$depth_first" && traverse_submodules "$@" > + # pwd is mentioned in order to enable the ser to distinguish > + # between same name modules, e.g. a/lib and b/lib. > + say "git submodule recurse $submod_path $*" > + git "$@" > + # if exit on error is specifed than script will exit if any > + # command fails. As there is no transaction there will be > + # no rollback either > + # TODO - If possible facilitate transaction > + if test "$?" -ne 0 && test -n "$on_error" > + then > + die "FAILED: git submodule $submod_path $*" > + fi > + # If depth-first is not specified in that case submodules are > + # are traversed after executing the command on this submodule > + test -z "$depth_first" && traverse_submodules "$@" > + ) > +} > + > +# 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. > +cmd_recurse() { > + while : > + do > + case "$1" in > + -q|--quiet) > + quiet=1 > + ;; > + -d|--depth) > + shift > + if test -z "$1" > + then > + echo "No <recursion depth> specified" > + usage > + # Arithmatic operation will give an error if depth is not number > + # thus chose to check intergerness with regular expression. > + # $1 is underquoted becuase the expr is in quotation > + elif test "$(expr $1 : '[1-9][0-9]*')" -eq "$(expr $1 : '.*')" > + then > + depth="$1" > + else > + echo "<recursion depth> not an integer" > + usage > + fi > + ;; > + -b|--breadth-first) > + depth_first= > + ;; > + -e|--exit-after-error) > + on_error=1 > + ;; > + -*) > + usage > + ;; > + *) > + break > + ;; > + esac > + shift > + done > + test "$#" -le 0 && die "No git command specified" > + project_home="$(pwd)" > + if test -d "$project_home"/.git/ > + then > + traverse_module . "$@" > + else > + die "$project_home not a git repo thus exiting" > + fi > +} > + > # 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. > @@ -589,7 +717,7 @@ cmd_status() > while test $# != 0 && test -z "$command" > do > case "$1" in > - add | init | update | status | summary) > + add | init | update | status | summary |recurse) > command=$1 > ;; > -q|--quiet) > -- > 1.5.4.2 > > -- Imran M Yousuf Entrepreneur & Software Engineer Smart IT Engineering Dhaka, Bangladesh Email: imran@xxxxxxxxxxxxxxxxxxxxxx Mobile: +880-1711402557 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html