Merge branch 'jc/fetch'
authorJunio C Hamano <junkio@cox.net>
Wed, 14 Mar 2007 08:40:19 +0000 (01:40 -0700)
committerJunio C Hamano <junkio@cox.net>
Wed, 14 Mar 2007 08:40:19 +0000 (01:40 -0700)
* jc/fetch:
.gitignore: add git-fetch--tool
builtin-fetch--tool: fix reflog notes.
git-fetch: retire update-local-ref which is not used anymore.
builtin-fetch--tool: make sure not to overstep ls-remote-result buffer.
fetch--tool: fix uninitialized buffer when reading from stdin
builtin-fetch--tool: adjust to updated sha1_object_info().
git-fetch--tool takes flags before the subcommand.
Use stdin reflist passing in git-fetch.sh
Use stdin reflist passing in parse-remote
Allow fetch--tool to read from stdin
git-fetch: rewrite expand_ref_wildcard in C
git-fetch: rewrite another shell loop in C
git-fetch: move more code into C.
git-fetch--tool: start rewriting parts of git-fetch in C.
git-fetch: split fetch_main into fetch_dumb and fetch_native

1  2 
.gitignore
Makefile
builtin.h
git-fetch.sh
git.c
diff --combined .gitignore
index 27797d1491938a9ca6b1f6dbd52d20e3388b0bed,847f40a54e1a2df4c21a17dbd21959655281188b..e8d2731ee5d7b3ad58bd0bebfe1ae87bed140615
@@@ -13,7 -13,6 +13,7 @@@ git-archiv
  git-bisect
  git-blame
  git-branch
 +git-bundle
  git-cat-file
  git-check-ref-format
  git-checkout
@@@ -38,6 -37,7 +38,7 @@@ git-diff-tre
  git-describe
  git-fast-import
  git-fetch
+ git-fetch--tool
  git-fetch-pack
  git-findtags
  git-fmt-merge-msg
@@@ -75,7 -75,6 +76,7 @@@ git-merge-our
  git-merge-recursive
  git-merge-resolve
  git-merge-stupid
 +git-mergetool
  git-mktag
  git-mktree
  git-name-rev
diff --combined Makefile
index 45fe3663a5e8323967f7bf7cfc1e7f69a5cb0631,9f20f842215364744809b03ab5bfa9506931e94a..dc024d45c143359e2e647990f37d927a59267cc0
+++ b/Makefile
@@@ -1,8 -1,6 +1,8 @@@
  # The default target of this Makefile is...
  all::
  
 +# Define V=1 to have a more verbose compile.
 +#
  # Define NO_OPENSSL environment variable if you do not have OpenSSL.
  # This also implies MOZILLA_SHA1.
  #
@@@ -91,9 -89,6 +91,9 @@@
  #
  # Define NO_ICONV if your libc does not properly support iconv.
  #
 +# Define OLD_ICONV if your library has an old iconv(), where the second
 +# (input buffer pointer) parameter is declared with type (const char **).
 +#
  # Define NO_R_TO_GCC if your gcc does not like "-R/path/lib" that
  # tells runtime paths to dynamic libraries; "-Wl,-rpath=/path/lib"
  # is used instead.
@@@ -179,10 -174,10 +179,10 @@@ SCRIPT_SH = 
        git-clean.sh git-clone.sh git-commit.sh \
        git-fetch.sh git-gc.sh \
        git-ls-remote.sh \
 -      git-merge-one-file.sh git-parse-remote.sh \
 +      git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \
        git-pull.sh git-rebase.sh \
        git-repack.sh git-request-pull.sh git-reset.sh \
 -      git-revert.sh git-sh-setup.sh \
 +      git-sh-setup.sh \
        git-tag.sh git-verify-tag.sh \
        git-applymbox.sh git-applypatch.sh git-am.sh \
        git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
@@@ -198,7 -193,7 +198,7 @@@ SCRIPT_PERL = 
  
  SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
          $(patsubst %.perl,%,$(SCRIPT_PERL)) \
 -        git-cherry-pick git-status git-instaweb
 +        git-status git-instaweb
  
  # ... and all the rest that could be moved out of bindir to gitexecdir
  PROGRAMS = \
@@@ -225,7 -220,7 +225,7 @@@ EXTRA_PROGRAMS 
  BUILT_INS = \
        git-format-patch$X git-show$X git-whatchanged$X git-cherry$X \
        git-get-tar-commit-id$X git-init$X git-repo-config$X \
 -      git-fsck-objects$X \
 +      git-fsck-objects$X git-cherry-pick$X \
        $(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))
  
  # what 'all' will build and 'install' will install, in gitexecdir
@@@ -282,7 -277,6 +282,7 @@@ BUILTIN_OBJS = 
        builtin-archive.o \
        builtin-blame.o \
        builtin-branch.o \
 +      builtin-bundle.o \
        builtin-cat-file.o \
        builtin-checkout-index.o \
        builtin-check-ref-format.o \
        builtin-diff-files.o \
        builtin-diff-index.o \
        builtin-diff-tree.o \
+       builtin-fetch--tool.o \
        builtin-fmt-merge-msg.o \
        builtin-for-each-ref.o \
        builtin-fsck.o \
        builtin-rerere.o \
        builtin-rev-list.o \
        builtin-rev-parse.o \
 +      builtin-revert.o \
        builtin-rm.o \
        builtin-runstatus.o \
        builtin-shortlog.o \
@@@ -384,6 -378,7 +385,6 @@@ ifeq ($(uname_O),Cygwin
        NO_STRCASESTR = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NEEDS_LIBICONV = YesPlease
 -      NO_C99_FORMAT = YesPlease
        NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
        NO_TRUSTABLE_FILEMODE = UnfortunatelyYes
        # There are conflicting reports about this.
@@@ -581,10 -576,6 +582,10 @@@ ifdef NO_ICON
        BASIC_CFLAGS += -DNO_ICONV
  endif
  
 +ifdef OLD_ICONV
 +      BASIC_CFLAGS += -DOLD_ICONV
 +endif
 +
  ifdef PPC_SHA1
        SHA1_HEADER = "ppc/sha1.h"
        LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o
@@@ -606,31 -597,6 +607,31 @@@ ifdef NO_PERL_MAKEMAKE
        export NO_PERL_MAKEMAKER
  endif
  
 +QUIET_SUBDIR0  = $(MAKE) -C # space to separate -C and subdir
 +QUIET_SUBDIR1  =
 +
 +ifneq ($(findstring $(MAKEFLAGS),w),w)
 +PRINT_DIR = --no-print-directory
 +else # "make -w"
 +NO_SUBDIR = :
 +endif
 +
 +ifneq ($(findstring $(MAKEFLAGS),s),s)
 +ifndef V
 +      QUIET_CC       = @echo '   ' CC $@;
 +      QUIET_AR       = @echo '   ' AR $@;
 +      QUIET_LINK     = @echo '   ' LINK $@;
 +      QUIET_BUILT_IN = @echo '   ' BUILTIN $@;
 +      QUIET_GEN      = @echo '   ' GEN $@;
 +      QUIET_SUBDIR0  = @subdir=
 +      QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
 +                       $(MAKE) $(PRINT_DIR) -C $$subdir
 +      export V
 +      export QUIET_GEN
 +      export QUIET_BUILT_IN
 +endif
 +endif
 +
  # Shell quote (do not use $(call) to accommodate ancient setups);
  
  SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER))
@@@ -665,43 -631,44 +666,43 @@@ ifneq (,$X
  endif
  
  all::
 -      $(MAKE) -C git-gui all
 -      $(MAKE) -C perl PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
 -      $(MAKE) -C templates
 +      $(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) all
 +      $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
 +      $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1)
  
  strip: $(PROGRAMS) git$X
        $(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
  
  git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS) GIT-CFLAGS
 -      $(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
 +      $(QUIET_LINK)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
                $(ALL_CFLAGS) -o $@ $(filter %.c,$^) \
                $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS)
  
  help.o: common-cmds.h
  
  $(BUILT_INS): git$X
 -      rm -f $@ && ln git$X $@
 +      $(QUIET_BUILT_IN)rm -f $@ && ln git$X $@
  
  common-cmds.h: Documentation/git-*.txt
 -      ./generate-cmdlist.sh > $@+
 -      mv $@+ $@
 +      $(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@
  
  $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
 -      rm -f $@ $@+
 +      $(QUIET_GEN)rm -f $@ $@+ && \
        sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
            -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
            -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
            -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
 -          $@.sh >$@+
 -      chmod +x $@+
 +          $@.sh >$@+ && \
 +      chmod +x $@+ && \
        mv $@+ $@
  
  $(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak
  
  perl/perl.mak: GIT-CFLAGS
 -      $(MAKE) -C perl PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F)
 +      $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F)
  
  $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl
 -      rm -f $@ $@+
 +      $(QUIET_GEN)rm -f $@ $@+ && \
        INSTLIBDIR=`$(MAKE) -C perl -s --no-print-directory instlibdir` && \
        sed -e '1{' \
            -e '        s|#!.*perl|#!$(PERL_PATH_SQ)|' \
            -e '}' \
            -e 's|@@INSTLIBDIR@@|'"$$INSTLIBDIR"'|g' \
            -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
 -          $@.perl >$@+
 -      chmod +x $@+
 -      mv $@+ $@
 -
 -git-cherry-pick: git-revert
 -      cp $< $@+
 +          $@.perl >$@+ && \
 +      chmod +x $@+ && \
        mv $@+ $@
  
  git-status: git-commit
 -      cp $< $@+
 -      mv $@+ $@
 +      $(QUIET_GEN)cp $< $@+ && mv $@+ $@
  
  gitweb/gitweb.cgi: gitweb/gitweb.perl
 -      rm -f $@ $@+
 +      $(QUIET_GEN)rm -f $@ $@+ && \
        sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \
            -e 's|++GIT_VERSION++|$(GIT_VERSION)|g' \
            -e 's|++GIT_BINDIR++|$(bindir)|g' \
            -e 's|++GITWEB_FAVICON++|$(GITWEB_FAVICON)|g' \
            -e 's|++GITWEB_SITE_HEADER++|$(GITWEB_SITE_HEADER)|g' \
            -e 's|++GITWEB_SITE_FOOTER++|$(GITWEB_SITE_FOOTER)|g' \
 -          $< >$@+
 -      chmod +x $@+
 +          $< >$@+ && \
 +      chmod +x $@+ && \
        mv $@+ $@
  
  git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css
 -      rm -f $@ $@+
 +      $(QUIET_GEN)rm -f $@ $@+ && \
        sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
            -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
            -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
            -e '/@@GITWEB_CGI@@/d' \
            -e '/@@GITWEB_CSS@@/r gitweb/gitweb.css' \
            -e '/@@GITWEB_CSS@@/d' \
 -          $@.sh > $@+
 -      chmod +x $@+
 +          $@.sh > $@+ && \
 +      chmod +x $@+ && \
        mv $@+ $@
  
  configure: configure.ac
 -      rm -f $@ $<+
 +      $(QUIET_GEN)rm -f $@ $<+ && \
        sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
 -          $< > $<+
 -      autoconf -o $@ $<+
 +          $< > $<+ && \
 +      autoconf -o $@ $<+ && \
        rm -f $<+
  
  # These can record GIT_VERSION
@@@ -769,25 -741,25 +770,25 @@@ git$X git.spec 
        : GIT-VERSION-FILE
  
  %.o: %.c GIT-CFLAGS
 -      $(CC) -o $*.o -c $(ALL_CFLAGS) $<
 +      $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
  %.o: %.S
 -      $(CC) -o $*.o -c $(ALL_CFLAGS) $<
 +      $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $<
  
  exec_cmd.o: exec_cmd.c GIT-CFLAGS
 -      $(CC) -o $*.o -c $(ALL_CFLAGS) '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $<
 +      $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $<
  builtin-init-db.o: builtin-init-db.c GIT-CFLAGS
 -      $(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
 +      $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
  
  http.o: http.c GIT-CFLAGS
 -      $(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $<
 +      $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $<
  
  ifdef NO_EXPAT
  http-fetch.o: http-fetch.c http.h GIT-CFLAGS
 -      $(CC) -o $*.o -c $(ALL_CFLAGS) -DNO_EXPAT $<
 +      $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DNO_EXPAT $<
  endif
  
  git-%$X: %.o $(GITLIBS)
 -      $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
 +      $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
  
  ssh-pull.o: ssh-fetch.c
  ssh-push.o: ssh-upload.c
@@@ -801,19 -773,19 +802,19 @@@ git-imap-send$X: imap-send.o $(LIB_FILE
  
  http.o http-fetch.o http-push.o: http.h
  git-http-fetch$X: fetch.o http.o http-fetch.o $(GITLIBS)
 -      $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 +      $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
  
  git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
 -      $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 +      $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
  
 -$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
 +$(LIB_OBJS) $(BUILTIN_OBJS) fetch.o: $(LIB_H)
  $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
  $(DIFF_OBJS): diffcore.h
  
  $(LIB_FILE): $(LIB_OBJS)
 -      rm -f $@ && $(AR) rcs $@ $(LIB_OBJS)
 +      $(QUIET_AR)rm -f $@ && $(AR) rcs $@ $(LIB_OBJS)
  
  XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
        xdiff/xmerge.o
@@@ -821,7 -793,7 +822,7 @@@ $(XDIFF_OBJS): xdiff/xinclude.h xdiff/x
        xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h
  
  $(XDIFF_LIB): $(XDIFF_OBJS)
 -      rm -f $@ && $(AR) rcs $@ $(XDIFF_OBJS)
 +      $(QUIET_AR)rm -f $@ && $(AR) rcs $@ $(XDIFF_OBJS)
  
  
  perl/Makefile: perl/Git.pm perl/Makefile.PL GIT-CFLAGS
@@@ -931,7 -903,8 +932,7 @@@ dist: git.spec git-archiv
        $(TAR) rf $(GIT_TARNAME).tar \
                $(GIT_TARNAME)/git.spec \
                $(GIT_TARNAME)/version \
 -              $(GIT_TARNAME)/git-gui/version \
 -              $(GIT_TARNAME)/git-gui/credits
 +              $(GIT_TARNAME)/git-gui/version
        @rm -rf $(GIT_TARNAME)
        gzip -f -9 $(GIT_TARNAME).tar
  
diff --combined builtin.h
index c58d3e3445d0801ac3181e429365535b9ec11095,9a25b79f87ee1b1b6944ecd2030126c1aff88539..1cb64b7ecd60f71ca0fd0d4d47e93c5f3d05d9ce
+++ b/builtin.h
@@@ -19,12 -19,10 +19,12 @@@ extern int cmd_apply(int argc, const ch
  extern int cmd_archive(int argc, const char **argv, const char *prefix);
  extern int cmd_blame(int argc, const char **argv, const char *prefix);
  extern int cmd_branch(int argc, const char **argv, const char *prefix);
 +extern int cmd_bundle(int argc, const char **argv, const char *prefix);
  extern int cmd_cat_file(int argc, const char **argv, const char *prefix);
  extern int cmd_checkout_index(int argc, const char **argv, const char *prefix);
  extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
  extern int cmd_cherry(int argc, const char **argv, const char *prefix);
 +extern int cmd_cherry_pick(int argc, const char **argv, const char *prefix);
  extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);
  extern int cmd_count_objects(int argc, const char **argv, const char *prefix);
  extern int cmd_describe(int argc, const char **argv, const char *prefix);
@@@ -32,6 -30,7 +32,7 @@@ extern int cmd_diff_files(int argc, con
  extern int cmd_diff_index(int argc, const char **argv, const char *prefix);
  extern int cmd_diff(int argc, const char **argv, const char *prefix);
  extern int cmd_diff_tree(int argc, const char **argv, const char *prefix);
+ extern int cmd_fetch__tool(int argc, const char **argv, const char *prefix);
  extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix);
  extern int cmd_for_each_ref(int argc, const char **argv, const char *prefix);
  extern int cmd_format_patch(int argc, const char **argv, const char *prefix);
@@@ -61,7 -60,6 +62,7 @@@ extern int cmd_config(int argc, const c
  extern int cmd_rerere(int argc, const char **argv, const char *prefix);
  extern int cmd_rev_list(int argc, const char **argv, const char *prefix);
  extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
 +extern int cmd_revert(int argc, const char **argv, const char *prefix);
  extern int cmd_rm(int argc, const char **argv, const char *prefix);
  extern int cmd_runstatus(int argc, const char **argv, const char *prefix);
  extern int cmd_shortlog(int argc, const char **argv, const char *prefix);
diff --combined git-fetch.sh
index 5ae0d28cc09a0b3935262a542c9811b66eb5b85e,4a8d8d6ef73921ebd99ef68ffa097cd325453763..9d45dd266a8110a2d39fe29ffeb84aacb6053623
@@@ -24,8 -24,6 +24,8 @@@ update_head_ok
  exec=
  keep=
  shallow_depth=
 +no_progress=
 +test -t 1 || no_progress=--no-progress
  while case "$#" in 0) break ;; esac
  do
        case "$1" in
@@@ -109,133 -107,11 +109,11 @@@ ls_remote_result=$(git ls-remote $exec 
        die "Cannot get the repository state from $remote"
  
  append_fetch_head () {
-     head_="$1"
-     remote_="$2"
-     remote_name_="$3"
-     remote_nick_="$4"
-     local_name_="$5"
-     case "$6" in
-     t) not_for_merge_='not-for-merge' ;;
-     '') not_for_merge_= ;;
-     esac
-     # remote-nick is the URL given on the command line (or a shorthand)
-     # remote-name is the $GIT_DIR relative refs/ path we computed
-     # for this refspec.
-     # the $note_ variable will be fed to git-fmt-merge-msg for further
-     # processing.
-     case "$remote_name_" in
-     HEAD)
-       note_= ;;
-     refs/heads/*)
-       note_="$(expr "$remote_name_" : 'refs/heads/\(.*\)')"
-       note_="branch '$note_' of " ;;
-     refs/tags/*)
-       note_="$(expr "$remote_name_" : 'refs/tags/\(.*\)')"
-       note_="tag '$note_' of " ;;
-     refs/remotes/*)
-       note_="$(expr "$remote_name_" : 'refs/remotes/\(.*\)')"
-       note_="remote branch '$note_' of " ;;
-     *)
-       note_="$remote_name of " ;;
-     esac
-     remote_1_=$(expr "z$remote_" : 'z\(.*\)\.git/*$') &&
-       remote_="$remote_1_"
-     note_="$note_$remote_"
-     # 2.6.11-tree tag would not be happy to be fed to resolve.
-     if git-cat-file commit "$head_" >/dev/null 2>&1
-     then
-       headc_=$(git-rev-parse --verify "$head_^0") || exit
-       echo "$headc_   $not_for_merge_ $note_" >>"$GIT_DIR/FETCH_HEAD"
-     else
-       echo "$head_    not-for-merge   $note_" >>"$GIT_DIR/FETCH_HEAD"
-     fi
-     update_local_ref "$local_name_" "$head_" "$note_"
- }
- update_local_ref () {
-     # If we are storing the head locally make sure that it is
-     # a fast forward (aka "reverse push").
-     label_=$(git-cat-file -t $2)
-     newshort_=$(git-rev-parse --short $2)
-     if test -z "$1" ; then
-       [ "$verbose" ] && echo >&2 "* fetched $3"
-       [ "$verbose" ] && echo >&2 "  $label_: $newshort_"
-       return 0
-     fi
-     oldshort_=$(git show-ref --hash --abbrev "$1" 2>/dev/null)
-     case "$1" in
-     refs/tags/*)
-       # Tags need not be pointing at commits so there
-       # is no way to guarantee "fast-forward" anyway.
-       if test -n "$oldshort_"
-       then
-               if now_=$(git show-ref --hash "$1") && test "$now_" = "$2"
-               then
-                       [ "$verbose" ] && echo >&2 "* $1: same as $3"
-                       [ "$verbose" ] && echo >&2 "  $label_: $newshort_" ||:
-               else
-                       echo >&2 "* $1: updating with $3"
-                       echo >&2 "  $label_: $newshort_"
-                       git-update-ref -m "$GIT_REFLOG_ACTION: updating tag" "$1" "$2"
-               fi
-       else
-               echo >&2 "* $1: storing $3"
-               echo >&2 "  $label_: $newshort_"
-               git-update-ref -m "$GIT_REFLOG_ACTION: storing tag" "$1" "$2"
-       fi
-       ;;
-     refs/heads/* | refs/remotes/*)
-       # $1 is the ref being updated.
-       # $2 is the new value for the ref.
-       local=$(git-rev-parse --verify "$1^0" 2>/dev/null)
-       if test "$local"
-       then
-           # Require fast-forward.
-           mb=$(git-merge-base "$local" "$2") &&
-           case "$2,$mb" in
-           $local,*)
-               if test -n "$verbose"
-               then
-                       echo >&2 "* $1: same as $3"
-                       echo >&2 "  $label_: $newshort_"
-               fi
-               ;;
-           *,$local)
-               echo >&2 "* $1: fast forward to $3"
-               echo >&2 "  old..new: $oldshort_..$newshort_"
-               git-update-ref -m "$GIT_REFLOG_ACTION: fast-forward" "$1" "$2" "$local"
-               ;;
-           *)
-               false
-               ;;
-           esac || {
-               case ",$force,$single_force," in
-               *,t,*)
-                       echo >&2 "* $1: forcing update to non-fast forward $3"
-                       echo >&2 "  old...new: $oldshort_...$newshort_"
-                       git-update-ref -m "$GIT_REFLOG_ACTION: forced-update" "$1" "$2" "$local"
-                       ;;
-               *)
-                       echo >&2 "* $1: not updating to non-fast forward $3"
-                       echo >&2 "  old...new: $oldshort_...$newshort_"
-                       exit 1
-                       ;;
-               esac
-           }
-       else
-           echo >&2 "* $1: storing $3"
-           echo >&2 "  $label_: $newshort_"
-           git-update-ref -m "$GIT_REFLOG_ACTION: storing head" "$1" "$2"
-       fi
-       ;;
-     esac
+       flags=
+       test -n "$verbose" && flags="$flags -v"
+       test -n "$force" && flags="$flags -f"
+       GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION" \
+               git-fetch--tool $flags append-fetch-head "$@"
  }
  
  # updating the current HEAD with git-fetch in a bare
@@@ -279,7 -155,30 +157,38 @@@ the
        fi
  fi
  
- fetch_main () {
+ fetch_native () {
+   eval=$(echo "$1" | git-fetch--tool parse-reflist "-")
+   eval "$eval"
+     ( : subshell because we muck with IFS
+       IFS="   $LF"
+       (
 -        git-fetch-pack --thin $exec $keep $shallow_depth "$remote" $rref ||
++      if test -f "$remote" ; then
++          test -n "$shallow_depth" &&
++              die "shallow clone with bundle is not supported"
++          git-bundle unbundle "$remote" $rref ||
++          echo failed "$remote"
++      else
++        git-fetch-pack --thin $exec $keep $shallow_depth $no_progress \
++              "$remote" $rref ||
+         echo failed "$remote"
++      fi
+       ) |
+       (
+       flags=
+       test -n "$verbose" && flags="$flags -v"
+       test -n "$force" && flags="$flags -f"
+       GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION" \
+               git-fetch--tool $flags native-store \
+                       "$remote" "$remote_nick" "$refs"
+       )
+     ) || exit
+ }
+ fetch_dumb () {
    reflist="$1"
    refs=
    rref=
              rsync_slurped_objects=t
          }
          ;;
-       *)
-         # We will do git native transport with just one call later.
-         continue ;;
        esac
  
        append_fetch_head "$head" "$remote" \
  
    done
  
-   case "$remote" in
-   http://* | https://* | ftp://* | rsync://* )
-       ;; # we are already done.
-   *)
-     ( : subshell because we muck with IFS
-       IFS="   $LF"
-       (
-       if test -f "$remote" ; then
-           test -n "$shallow_depth" &&
-               die "shallow clone with bundle is not supported"
-           git-bundle unbundle "$remote" $rref ||
-           echo failed "$remote"
-       else
-         git-fetch-pack --thin $exec $keep $shallow_depth $no_progress \
-               "$remote" $rref ||
-         echo failed "$remote"
-       fi
-       ) |
-       (
-       trap '
-               if test -n "$keepfile" && test -f "$keepfile"
-               then
-                       rm -f "$keepfile"
-               fi
-       ' 0
-         keepfile=
-       while read sha1 remote_name
-       do
-         case "$sha1" in
-         failed)
-                 echo >&2 "Fetch failure: $remote"
-                 exit 1 ;;
-         # special line coming from index-pack with the pack name
-         pack)
-                 continue ;;
-         keep)
-                 keepfile="$GIT_OBJECT_DIRECTORY/pack/pack-$remote_name.keep"
-                 continue ;;
-         esac
-         found=
-         single_force=
-         for ref in $refs
-         do
-             case "$ref" in
-             +$remote_name:*)
-                 single_force=t
-                 not_for_merge=
-                 found="$ref"
-                 break ;;
-             .+$remote_name:*)
-                 single_force=t
-                 not_for_merge=t
-                 found="$ref"
-                 break ;;
-             .$remote_name:*)
-                 not_for_merge=t
-                 found="$ref"
-                 break ;;
-             $remote_name:*)
-                 not_for_merge=
-                 found="$ref"
-                 break ;;
-             esac
-         done
-         local_name=$(expr "z$found" : 'z[^:]*:\(.*\)')
-         append_fetch_head "$sha1" "$remote" \
-                 "$remote_name" "$remote_nick" "$local_name" \
-                 "$not_for_merge" || exit
-         done
-       )
-     ) || exit ;;
-   esac
+ }
  
+ fetch_main () {
+       case "$remote" in
+       http://* | https://* | ftp://* | rsync://* )
+               fetch_dumb "$@"
+               ;;
+       *)
+               fetch_native "$@"
+               ;;
+       esac
  }
  
  fetch_main "$reflist" || exit
diff --combined git.c
index fe2b74ab79619c425d7944c02a7f37c5e218bdef,2361b5fbbc4729c728159a7f2d79408a0ec1e8d6..dde4d07e8fbb830791417d422e4b9204373935e4
--- 1/git.c
--- 2/git.c
+++ b/git.c
@@@ -226,23 -226,22 +226,24 @@@ static void handle_internal_command(in
                { "add", cmd_add, RUN_SETUP | NOT_BARE },
                { "annotate", cmd_annotate, USE_PAGER },
                { "apply", cmd_apply },
 -              { "archive", cmd_archive },
 +              { "archive", cmd_archive, RUN_SETUP },
                { "blame", cmd_blame, RUN_SETUP },
                { "branch", cmd_branch, RUN_SETUP },
 +              { "bundle", cmd_bundle },
                { "cat-file", cmd_cat_file, RUN_SETUP },
                { "checkout-index", cmd_checkout_index, RUN_SETUP },
                { "check-ref-format", cmd_check_ref_format },
                { "cherry", cmd_cherry, RUN_SETUP },
 +              { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NOT_BARE },
                { "commit-tree", cmd_commit_tree, RUN_SETUP },
                { "config", cmd_config },
                { "count-objects", cmd_count_objects, RUN_SETUP },
                { "describe", cmd_describe, RUN_SETUP },
 -              { "diff", cmd_diff, RUN_SETUP | USE_PAGER },
 -              { "diff-files", cmd_diff_files, RUN_SETUP },
 +              { "diff", cmd_diff, USE_PAGER },
 +              { "diff-files", cmd_diff_files },
                { "diff-index", cmd_diff_index, RUN_SETUP },
                { "diff-tree", cmd_diff_tree, RUN_SETUP },
+               { "fetch--tool", cmd_fetch__tool, RUN_SETUP },
                { "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
                { "for-each-ref", cmd_for_each_ref, RUN_SETUP },
                { "format-patch", cmd_format_patch, RUN_SETUP },
                { "rerere", cmd_rerere, RUN_SETUP },
                { "rev-list", cmd_rev_list, RUN_SETUP },
                { "rev-parse", cmd_rev_parse, RUN_SETUP },
 +              { "revert", cmd_revert, RUN_SETUP | NOT_BARE },
                { "rm", cmd_rm, RUN_SETUP | NOT_BARE },
                { "runstatus", cmd_runstatus, RUN_SETUP | NOT_BARE },
                { "shortlog", cmd_shortlog, RUN_SETUP | USE_PAGER },