Merge branch 'sb/submodule-helper'
authorJunio C Hamano <gitster@pobox.com>
Mon, 5 Oct 2015 19:30:19 +0000 (12:30 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 5 Oct 2015 19:30:19 +0000 (12:30 -0700)
The infrastructure to rewrite "git submodule" in C is being built
incrementally.  Let's polish these early parts well enough and make
them graduate to 'next' and 'master', so that the more involved
follow-up can start cooking on a solid ground.

* sb/submodule-helper:
  submodule: rewrite `module_clone` shell function in C
  submodule: rewrite `module_name` shell function in C
  submodule: rewrite `module_list` shell function in C

1  2 
Makefile
builtin.h
git-submodule.sh
git.c

diff --combined Makefile
+++ b/Makefile
@@@ -467,6 -467,7 +467,6 @@@ TEST_PROGRAMS_NEED_X 
  # interactive shell sessions without exporting it.
  unexport CDPATH
  
 -SCRIPT_SH += git-am.sh
  SCRIPT_SH += git-bisect.sh
  SCRIPT_SH += git-difftool--helper.sh
  SCRIPT_SH += git-filter-branch.sh
@@@ -788,7 -789,6 +788,7 @@@ LIB_OBJS += submodule.
  LIB_OBJS += submodule-config.o
  LIB_OBJS += symlinks.o
  LIB_OBJS += tag.o
 +LIB_OBJS += tempfile.o
  LIB_OBJS += trace.o
  LIB_OBJS += trailer.o
  LIB_OBJS += transport.o
@@@ -815,7 -815,6 +815,7 @@@ LIB_OBJS += xdiff-interface.
  LIB_OBJS += zlib.o
  
  BUILTIN_OBJS += builtin/add.o
 +BUILTIN_OBJS += builtin/am.o
  BUILTIN_OBJS += builtin/annotate.o
  BUILTIN_OBJS += builtin/apply.o
  BUILTIN_OBJS += builtin/archive.o
@@@ -902,6 -901,7 +902,7 @@@ BUILTIN_OBJS += builtin/shortlog.
  BUILTIN_OBJS += builtin/show-branch.o
  BUILTIN_OBJS += builtin/show-ref.o
  BUILTIN_OBJS += builtin/stripspace.o
+ BUILTIN_OBJS += builtin/submodule--helper.o
  BUILTIN_OBJS += builtin/symbolic-ref.o
  BUILTIN_OBJS += builtin/tag.o
  BUILTIN_OBJS += builtin/unpack-file.o
@@@ -1700,10 -1700,10 +1701,10 @@@ $(BUILT_INS): git$
        ln -s $< $@ 2>/dev/null || \
        cp $< $@
  
 -common-cmds.h: generate-cmdlist.perl command-list.txt
 +common-cmds.h: generate-cmdlist.sh command-list.txt
  
  common-cmds.h: $(wildcard Documentation/git-*.txt)
 -      $(QUIET_GEN)$(PERL_PATH) generate-cmdlist.perl command-list.txt > $@+ && mv $@+ $@
 +      $(QUIET_GEN)$(SHELL_PATH) ./generate-cmdlist.sh command-list.txt >$@+ && mv $@+ $@
  
  SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
        $(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
diff --combined builtin.h
+++ b/builtin.h
@@@ -30,7 -30,6 +30,7 @@@ extern int textconv_object(const char *
  extern int is_builtin(const char *s);
  
  extern int cmd_add(int argc, const char **argv, const char *prefix);
 +extern int cmd_am(int argc, const char **argv, const char *prefix);
  extern int cmd_annotate(int argc, const char **argv, const char *prefix);
  extern int cmd_apply(int argc, const char **argv, const char *prefix);
  extern int cmd_archive(int argc, const char **argv, const char *prefix);
@@@ -120,6 -119,7 +120,7 @@@ extern int cmd_show(int argc, const cha
  extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
  extern int cmd_status(int argc, const char **argv, const char *prefix);
  extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
+ extern int cmd_submodule__helper(int argc, const char **argv, const char *prefix);
  extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
  extern int cmd_tag(int argc, const char **argv, const char *prefix);
  extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
diff --combined git-submodule.sh
@@@ -145,48 -145,6 +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"
@@@ -220,98 -178,6 +178,6 @@@ get_submodule_config () 
        printf '%s' "${value:-$default}"
  }
  
- #
- # Map submodule path to submodule name
- #
- # $1 = path
- #
- module_name()
- {
-       # Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
-       sm_path="$1"
-       re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
-       name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
-               sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
-       test -z "$name" &&
-       die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
-       printf '%s\n' "$name"
- }
- #
- # Clone a submodule
- #
- # $1 = submodule path
- # $2 = submodule name
- # $3 = URL to clone
- # $4 = reference repository to reuse (empty for independent)
- # $5 = depth argument for shallow clones (empty for deep)
- #
- # Prior to calling, cmd_update checks that a possibly existing
- # path is not a git repository.
- # Likewise, cmd_add checks that path does not exist at all,
- # since it is the location of a new submodule.
- #
- module_clone()
- {
-       sm_path=$1
-       name=$2
-       url=$3
-       reference="$4"
-       depth="$5"
-       quiet=
-       if test -n "$GIT_QUIET"
-       then
-               quiet=-q
-       fi
-       gitdir=
-       gitdir_base=
-       base_name=$(dirname "$name")
-       gitdir=$(git rev-parse --git-dir)
-       gitdir_base="$gitdir/modules/$base_name"
-       gitdir="$gitdir/modules/$name"
-       if test -d "$gitdir"
-       then
-               mkdir -p "$sm_path"
-               rm -f "$gitdir/index"
-       else
-               mkdir -p "$gitdir_base"
-               (
-                       clear_local_git_env
-                       git clone $quiet ${depth:+"$depth"} -n ${reference:+"$reference"} \
-                               --separate-git-dir "$gitdir" "$url" "$sm_path"
-               ) ||
-               die "$(eval_gettext "Clone of '\$url' into submodule path '\$sm_path' failed")"
-       fi
-       # We already are at the root of the work tree but cd_to_toplevel will
-       # resolve any symlinks that might be present in $PWD
-       a=$(cd_to_toplevel && cd "$gitdir" && pwd)/
-       b=$(cd_to_toplevel && cd "$sm_path" && pwd)/
-       # Remove all common leading directories after a sanity check
-       if test "${a#$b}" != "$a" || test "${b#$a}" != "$b"; then
-               die "$(eval_gettext "Gitdir '\$a' is part of the submodule path '\$b' or vice versa")"
-       fi
-       while test "${a%%/*}" = "${b%%/*}"
-       do
-               a=${a#*/}
-               b=${b#*/}
-       done
-       # Now chop off the trailing '/'s that were added in the beginning
-       a=${a%/}
-       b=${b%/}
-       # Turn each leading "*/" component into "../"
-       rel=$(printf '%s\n' "$b" | sed -e 's|[^/][^/]*|..|g')
-       printf '%s\n' "gitdir: $rel/$a" >"$sm_path/.git"
-       rel=$(printf '%s\n' "$a" | sed -e 's|[^/][^/]*|..|g')
-       (clear_local_git_env; cd "$sm_path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b")
- }
  isnumber()
  {
        n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
@@@ -472,7 -338,7 +338,7 @@@ Use -f if you really want to add it." >
                                echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
                        fi
                fi
-               module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" || exit
+               git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" "$reference" "$depth" || exit
                (
                        clear_local_git_env
                        cd "$sm_path" &&
@@@ -532,7 -398,7 +398,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"
                then
                        displaypath=$(relative_path "$sm_path")
                        say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
-                       name=$(module_name "$sm_path")
+                       name=$(git submodule--helper name "$sm_path")
                        (
                                prefix="$prefix$sm_path/"
                                clear_local_git_env
@@@ -592,11 -458,11 +458,11 @@@ 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"
-               name=$(module_name "$sm_path") || exit
+               name=$(git submodule--helper name "$sm_path") || exit
  
                displaypath=$(relative_path "$sm_path")
  
@@@ -674,11 -540,11 +540,11 @@@ 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"
-               name=$(module_name "$sm_path") || exit
+               name=$(git submodule--helper name "$sm_path") || exit
  
                displaypath=$(relative_path "$sm_path")
  
@@@ -790,7 -656,7 +656,7 @@@ cmd_update(
        fi
  
        cloned_modules=
-       module_list "$@" | {
+       git submodule--helper list --prefix "$wt_prefix" "$@" | {
        err=
        while read mode sha1 stage sm_path
        do
                        echo >&2 "Skipping unmerged submodule $prefix$sm_path"
                        continue
                fi
-               name=$(module_name "$sm_path") || exit
+               name=$(git submodule--helper name "$sm_path") || exit
                url=$(git config submodule."$name".url)
                branch=$(get_submodule_config "$name" branch master)
                if ! test -z "$update"
@@@ -834,7 -700,7 +700,7 @@@ Maybe you want to use 'update --init'?"
  
                if ! test -d "$sm_path"/.git && ! test -f "$sm_path"/.git
                then
-                       module_clone "$sm_path" "$name" "$url" "$reference" "$depth" || exit
+                       git submodule--helper clone ${GIT_QUIET:+--quiet} --prefix "$prefix" --path "$sm_path" --name "$name" --url "$url" "$reference" "$depth" || exit
                        cloned_modules="$cloned_modules;$name"
                        subsha1=
                else
                                ;;
                        !*)
                                command="${update_module#!}"
 -                              die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule  path '\$prefix\$sm_path'")"
 +                              die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$prefix\$sm_path'")"
                                say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': '\$command \$sha1'")"
                                must_die_on_failure=yes
                                ;;
@@@ -1064,7 -930,7 +930,7 @@@ cmd_summary() 
                        # Respect the ignore setting for --for-status.
                        if test -n "$for_status"
                        then
-                               name=$(module_name "$sm_path")
+                               name=$(git submodule--helper name "$sm_path")
                                ignore_config=$(get_submodule_config "$name" ignore none)
                                test $status != A && test $ignore_config = all && continue
                        fi
@@@ -1222,11 -1088,11 +1088,11 @@@ 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"
-               name=$(module_name "$sm_path") || exit
+               name=$(git submodule--helper name "$sm_path") || exit
                url=$(git config submodule."$name".url)
                displaypath=$(relative_path "$prefix$sm_path")
                if test "$stage" = U
@@@ -1299,11 -1165,11 +1165,11 @@@ 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"
-               name=$(module_name "$sm_path")
+               name=$(git submodule--helper name "$sm_path")
                url=$(git config -f .gitmodules --get submodule."$name".url)
  
                # Possibly a url relative to parent
diff --combined git.c
--- 1/git.c
--- 2/git.c
+++ b/git.c
@@@ -370,7 -370,6 +370,7 @@@ static int run_builtin(struct cmd_struc
  
  static struct cmd_struct commands[] = {
        { "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
 +      { "am", cmd_am, RUN_SETUP | NEED_WORK_TREE },
        { "annotate", cmd_annotate, RUN_SETUP },
        { "apply", cmd_apply, RUN_SETUP_GENTLY },
        { "archive", cmd_archive },
        { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
        { "init", cmd_init_db, NO_SETUP },
        { "init-db", cmd_init_db, NO_SETUP },
 -      { "interpret-trailers", cmd_interpret_trailers, RUN_SETUP },
 +      { "interpret-trailers", cmd_interpret_trailers, RUN_SETUP_GENTLY },
        { "log", cmd_log, RUN_SETUP },
        { "ls-files", cmd_ls_files, RUN_SETUP },
        { "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
        { "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
        { "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
        { "stripspace", cmd_stripspace },
+       { "submodule--helper", cmd_submodule__helper, RUN_SETUP },
        { "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
        { "tag", cmd_tag, RUN_SETUP },
        { "unpack-file", cmd_unpack_file, RUN_SETUP },