Skip to content

Commit

Permalink
Merge branch 'jh/submodule-foreach'
Browse files Browse the repository at this point in the history
* jh/submodule-foreach:
  git clone: Add --recursive to automatically checkout (nested) submodules
  t7407: Use 'rev-parse --short' rather than bash's substring expansion notation
  git submodule status: Add --recursive to recurse into nested submodules
  git submodule update: Introduce --recursive to update nested submodules
  git submodule foreach: Add --recursive to recurse into nested submodules
  git submodule foreach: test access to submodule name as '$name'
  Add selftest for 'git submodule foreach'
  git submodule: Cleanup usage string and add option parsing to cmd_foreach()
  git submodule foreach: Provide access to submodule name, as '$name'

Conflicts:
	Documentation/git-submodule.txt
	git-submodule.sh
  • Loading branch information
Junio C Hamano committed Aug 27, 2009
2 parents ab36d06 + e7fed18 commit adc5423
Show file tree
Hide file tree
Showing 5 changed files with 346 additions and 14 deletions.
10 changes: 9 additions & 1 deletion Documentation/git-clone.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ SYNOPSIS
'git clone' [--template=<template_directory>]
[-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
[-o <name>] [-u <upload-pack>] [--reference <repository>]
[--depth <depth>] [--] <repository> [<directory>]
[--depth <depth>] [--recursive] [--] <repository> [<directory>]

DESCRIPTION
-----------
Expand Down Expand Up @@ -147,6 +147,14 @@ objects from the source repository into a pack in the cloned repository.
with a long history, and would want to send in fixes
as patches.

--recursive::
After the clone is created, initialize all submodules within,
using their default settings. This is equivalent to running
'git submodule update --init --recursive' immediately after
the clone is finished. This option is ignored if the cloned
repository does not have a worktree/checkout (i.e. if any of
`--no-checkout`/`-n`, `--bare`, or `--mirror` is given)

<repository>::
The (possibly remote) repository to clone from. See the
<<URLS,URLS>> section below for more information on specifying
Expand Down
23 changes: 19 additions & 4 deletions Documentation/git-submodule.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ SYNOPSIS
[verse]
'git submodule' [--quiet] add [-b branch]
[--reference <repository>] [--] <repository> <path>
'git submodule' [--quiet] status [--cached] [--] [<path>...]
'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
'git submodule' [--quiet] init [--] [<path>...]
'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
[--reference <repository>] [--merge] [--] [<path>...]
[--reference <repository>] [--merge] [--recursive] [--] [<path>...]
'git submodule' [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
'git submodule' [--quiet] foreach <command>
'git submodule' [--quiet] foreach [--recursive] <command>
'git submodule' [--quiet] sync [--] [<path>...]


Expand Down Expand Up @@ -100,6 +100,9 @@ status::
initialized and `+` if the currently checked out submodule commit
does not match the SHA-1 found in the index of the containing
repository. This command is the default command for 'git-submodule'.
+
If '--recursive' is specified, this command will recurse into nested
submodules, and show their status as well.

init::
Initialize the submodules, i.e. register each submodule name
Expand All @@ -122,6 +125,9 @@ update::
If the submodule is not yet initialized, and you just want to use the
setting as stored in .gitmodules, you can automatically initialize the
submodule with the --init option.
+
If '--recursive' is specified, this command will recurse into the
registered submodules, and update any nested submodules within.

summary::
Show commit summary between the given commit (defaults to HEAD) and
Expand All @@ -135,12 +141,15 @@ summary::

foreach::
Evaluates an arbitrary shell command in each checked out submodule.
The command has access to the variables $path and $sha1:
The command has access to the variables $name, $path and $sha1:
$name is the name of the relevant submodule section in .gitmodules,
$path is the name of the submodule directory relative to the
superproject, and $sha1 is the commit as recorded in the superproject.
Any submodules defined in the superproject but not checked out are
ignored by this command. Unless given --quiet, foreach prints the name
of each submodule before evaluating the command.
If --recursive is given, submodules are traversed recursively (i.e.
the given shell command is evaluated in nested submodules as well).
A non-zero return from the command in any submodule causes
the processing to terminate. This can be overridden by adding '|| :'
to the end of the command.
Expand Down Expand Up @@ -218,6 +227,12 @@ OPTIONS
*NOTE*: Do *not* use this option unless you have read the note
for linkgit:git-clone[1]'s --reference and --shared options carefully.

--recursive::
This option is only valid for foreach, update and status commands.
Traverse submodules recursively. The operation is performed not
only in the submodules of the current repo, but also
in any nested submodules inside those submodules (and so on).

<path>...::
Paths to submodule(s). When specified this will restrict the command
to only operate on the submodules found at the specified paths.
Expand Down
11 changes: 10 additions & 1 deletion builtin-clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static const char * const builtin_clone_usage[] = {
};

static int option_quiet, option_no_checkout, option_bare, option_mirror;
static int option_local, option_no_hardlinks, option_shared;
static int option_local, option_no_hardlinks, option_shared, option_recursive;
static char *option_template, *option_reference, *option_depth;
static char *option_origin = NULL;
static char *option_upload_pack = "git-upload-pack";
Expand All @@ -59,6 +59,8 @@ static struct option builtin_clone_options[] = {
"don't use local hardlinks, always copy"),
OPT_BOOLEAN('s', "shared", &option_shared,
"setup as shared repository"),
OPT_BOOLEAN(0, "recursive", &option_recursive,
"setup as shared repository"),
OPT_STRING(0, "template", &option_template, "path",
"path the template repository"),
OPT_STRING(0, "reference", &option_reference, "repo",
Expand All @@ -73,6 +75,10 @@ static struct option builtin_clone_options[] = {
OPT_END()
};

static const char *argv_submodule[] = {
"submodule", "update", "--init", "--recursive", NULL
};

static char *get_repo_path(const char *repo, int *is_bundle)
{
static char *suffix[] = { "/.git", ".git", "" };
Expand Down Expand Up @@ -608,6 +614,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)

err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1),
sha1_to_hex(remote_head->old_sha1), "1", NULL);

if (!err && option_recursive)
err = run_command_v_opt(argv_submodule, RUN_GIT_CMD);
}

strbuf_release(&reflog_msg);
Expand Down
79 changes: 71 additions & 8 deletions git-submodule.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@
#
# Copyright (c) 2007 Lars Hjemli

USAGE="[--quiet] [--cached|--files] \
[add [-b branch] <repo> <path>]|[status|init|update [-i|--init] [-N|--no-fetch] [--rebase|--merge]|summary [-n|--summary-limit <n>] [<commit>]] \
[--] [<path>...]|[foreach <command>]|[sync [--] [<path>...]]"
dashless=$(basename "$0" | sed -e 's/-/ /')
USAGE="[--quiet] add [-b branch] [--reference <repository>] [--] <repository> <path>
or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
or: $dashless [--quiet] init [--] [<path>...]
or: $dashless [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
or: $dashless [--quiet] foreach [--recursive] <command>
or: $dashless [--quiet] sync [--] [<path>...]"
OPTIONS_SPEC=
. git-sh-setup
. git-parse-remote
Expand All @@ -19,6 +24,7 @@ cached=
files=
nofetch=
update=
prefix=

# Resolve relative url by appending to parent's url
resolve_relative_url ()
Expand Down Expand Up @@ -238,13 +244,43 @@ cmd_add()
#
cmd_foreach()
{
# parse $args after "submodule ... foreach".
while test $# -ne 0
do
case "$1" in
-q|--quiet)
GIT_QUIET=1
;;
--recursive)
recursive=1
;;
-*)
usage
;;
*)
break
;;
esac
shift
done

module_list |
while read mode sha1 stage path
do
if test -e "$path"/.git
then
say "Entering '$path'"
(cd "$path" && eval "$@") ||
say "Entering '$prefix$path'"
name=$(module_name "$path")
(
prefix="$prefix$path/"
unset GIT_DIR
cd "$path" &&
eval "$@" &&
if test -n "$recursive"
then
cmd_foreach "--recursive" "$@"
fi
) ||
die "Stopping at '$path'; script returned non-zero status."
fi
done
Expand Down Expand Up @@ -317,6 +353,7 @@ cmd_init()
cmd_update()
{
# parse $args after "submodule ... update".
orig_args="$@"
while test $# -ne 0
do
case "$1" in
Expand Down Expand Up @@ -349,6 +386,10 @@ cmd_update()
shift
update="merge"
;;
--recursive)
shift
recursive=1
;;
--)
shift
break
Expand Down Expand Up @@ -435,6 +476,12 @@ cmd_update()
die "Unable to $action '$sha1' in submodule path '$path'"
say "Submodule path '$path': $msg '$sha1'"
fi

if test -n "$recursive"
then
(unset GIT_DIR; cd "$path" && cmd_update $orig_args) ||
die "Failed to recurse into submodule path '$path'"
fi
done
}

Expand Down Expand Up @@ -656,6 +703,7 @@ cmd_summary() {
cmd_status()
{
# parse $args after "submodule ... status".
orig_args="$@"
while test $# -ne 0
do
case "$1" in
Expand All @@ -665,6 +713,9 @@ cmd_status()
--cached)
cached=1
;;
--recursive)
recursive=1
;;
--)
shift
break
Expand All @@ -684,22 +735,34 @@ cmd_status()
do
name=$(module_name "$path") || exit
url=$(git config submodule."$name".url)
displaypath="$prefix$path"
if test -z "$url" || ! test -d "$path"/.git -o -f "$path"/.git
then
say "-$sha1 $path"
say "-$sha1 $displaypath"
continue;
fi
set_name_rev "$path" "$sha1"
if git diff-files --quiet -- "$path"
then
say " $sha1 $path$revname"
say " $sha1 $displaypath$revname"
else
if test -z "$cached"
then
sha1=$(unset GIT_DIR; cd "$path" && git rev-parse --verify HEAD)
set_name_rev "$path" "$sha1"
fi
say "+$sha1 $path$revname"
say "+$sha1 $displaypath$revname"
fi

if test -n "$recursive"
then
(
prefix="$displaypath/"
unset GIT_DIR
cd "$path" &&
cmd_status $orig_args
) ||
die "Failed to recurse into submodule path '$path'"
fi
done
}
Expand Down
Loading

0 comments on commit adc5423

Please sign in to comment.