submodule: rewrite module_list shell function in C

Most of the submodule operations work on a set of submodules.
Calculating and using this set is usually done via:

       module_list "$@" | {
           while read mode sha1 stage sm_path
           do
                # the actual operation
           done
       }

Currently the function `module_list` is implemented in the
git-submodule.sh as a shell script wrapping a perl script.
The rewrite is in C, such that it is faster and can later be
easily adapted when other functions are rewritten in C.

git-submodule.sh, similar to the builtin commands, will navigate
to the top-most directory of the repository and keep the
subdirectory as a variable. As the helper is called from
within the git-submodule.sh script, we are already navigated
to the root level, but the path arguments are still relative
to the subdirectory we were in when calling git-submodule.sh.
That's why there is a `--prefix` option pointing to an alternative
path which to anchor relative path arguments.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Stefan Beller
2015-09-02 14:42:24 -07:00
committed by Junio C Hamano
parent 5a1ba6b48a
commit 74703a1e4d
6 changed files with 138 additions and 48 deletions

View File

@ -145,48 +145,6 @@ relative_path ()
echo "$result$target"
}
#
# Get submodule info for registered submodules
# $@ = path to limit submodule list
#
module_list()
{
eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
(
git ls-files -z --error-unmatch --stage -- "$@" ||
echo "unmatched pathspec exists"
) |
@@PERL@@ -e '
my %unmerged = ();
my ($null_sha1) = ("0" x 40);
my @out = ();
my $unmatched = 0;
$/ = "\0";
while (<STDIN>) {
if (/^unmatched pathspec/) {
$unmatched = 1;
next;
}
chomp;
my ($mode, $sha1, $stage, $path) =
/^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
next unless $mode eq "160000";
if ($stage ne "0") {
if (!$unmerged{$path}++) {
push @out, "$mode $null_sha1 U\t$path\n";
}
next;
}
push @out, "$_\n";
}
if ($unmatched) {
print "#unmatched\n";
} else {
print for (@out);
}
'
}
die_if_unmatched ()
{
if test "$1" = "#unmatched"
@ -532,7 +490,7 @@ cmd_foreach()
# command in the subshell (and a recursive call to this function)
exec 3<&0
module_list |
git submodule--helper list --prefix "$wt_prefix"|
while read mode sha1 stage sm_path
do
die_if_unmatched "$mode"
@ -592,7 +550,7 @@ cmd_init()
shift
done
module_list "$@" |
git submodule--helper list --prefix "$wt_prefix" "$@" |
while read mode sha1 stage sm_path
do
die_if_unmatched "$mode"
@ -674,7 +632,7 @@ cmd_deinit()
die "$(eval_gettext "Use '.' if you really want to deinitialize all submodules")"
fi
module_list "$@" |
git submodule--helper list --prefix "$wt_prefix" "$@" |
while read mode sha1 stage sm_path
do
die_if_unmatched "$mode"
@ -790,7 +748,7 @@ cmd_update()
fi
cloned_modules=
module_list "$@" | {
git submodule--helper list --prefix "$wt_prefix" "$@" | {
err=
while read mode sha1 stage sm_path
do
@ -1222,7 +1180,7 @@ cmd_status()
shift
done
module_list "$@" |
git submodule--helper list --prefix "$wt_prefix" "$@" |
while read mode sha1 stage sm_path
do
die_if_unmatched "$mode"
@ -1299,7 +1257,7 @@ cmd_sync()
esac
done
cd_to_toplevel
module_list "$@" |
git submodule--helper list --prefix "$wt_prefix" "$@" |
while read mode sha1 stage sm_path
do
die_if_unmatched "$mode"