Merge branch 'db/vcs-helper'
authorJunio C Hamano <gitster@pobox.com>
Sun, 13 Sep 2009 08:31:55 +0000 (01:31 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 13 Sep 2009 08:31:55 +0000 (01:31 -0700)
* db/vcs-helper:
  Makefile: remove remnant of separate http/https/ftp helpers
  Use a clearer style to issue commands to remote helpers
  Make the "traditionally-supported" URLs a special case
  Makefile: install hardlinks for git-remote-<scheme> supported by libcurl if possible
  Makefile: do not link three copies of git-remote-* programs
  Makefile: git-http-fetch does not need expat
  http-fetch: Fix Makefile dependancies
  Add transport native helper executables to .gitignore
  git-http-fetch: not a builtin
  Use an external program to implement fetching with curl
  Add support for external programs for handling native fetches

1  2 
.gitignore
Makefile
git.c
transport.c
transport.h

diff --combined .gitignore
@@@ -104,8 -104,8 +104,9 @@@ git-receive-pac
  git-reflog
  git-relink
  git-remote
+ git-remote-curl
  git-repack
 +git-replace
  git-repo-config
  git-request-pull
  git-rerere
diff --combined Makefile
+++ b/Makefile
@@@ -16,7 -16,7 +16,7 @@@ all:
  # when attempting to read from an fopen'ed directory.
  #
  # Define NO_OPENSSL environment variable if you do not have OpenSSL.
 -# This also implies MOZILLA_SHA1.
 +# This also implies BLK_SHA1.
  #
  # Define NO_CURL if you do not have libcurl installed.  git-http-pull and
  # git-http-push are not built, and you cannot use http:// and https://
  # specify your own (or DarwinPort's) include directories and
  # library directories by defining CFLAGS and LDFLAGS appropriately.
  #
 +# Define BLK_SHA1 environment variable if you want the C version
 +# of the SHA1 that assumes you can do unaligned 32-bit loads and
 +# have a fast htonl() function.
 +#
  # Define PPC_SHA1 environment variable when running make to make use of
  # a bundled SHA1 routine optimized for PowerPC.
  #
 -# Define ARM_SHA1 environment variable when running make to make use of
 -# a bundled SHA1 routine optimized for ARM.
 -#
 -# Define MOZILLA_SHA1 environment variable when running make to make use of
 -# a bundled SHA1 routine coming from Mozilla. It is GPL'd and should be fast
 -# on non-x86 architectures (e.g. PowerPC), while the OpenSSL version (default
 -# choice) has very fast version optimized for i586.
 +# Define NEEDS_CRYPTO_WITH_SSL if you need -lcrypto when using -lssl (Darwin).
  #
 -# Define NEEDS_SSL_WITH_CRYPTO if you need -lcrypto with -lssl (Darwin).
 +# Define NEEDS_SSL_WITH_CRYPTO if you need -lssl when using -lcrypto (Darwin).
  #
  # Define NEEDS_LIBICONV if linking with libc is not enough (Darwin).
  #
@@@ -359,6 -361,7 +359,6 @@@ PROGRAMS += git-patch-id$
  PROGRAMS += git-shell$X
  PROGRAMS += git-show-index$X
  PROGRAMS += git-unpack-file$X
 -PROGRAMS += git-update-server-info$X
  PROGRAMS += git-upload-pack$X
  PROGRAMS += git-var$X
  
@@@ -380,7 -383,8 +380,8 @@@ BUILT_INS += git-stage$
  BUILT_INS += git-status$X
  BUILT_INS += git-whatchanged$X
  
- # what 'all' will build and 'install' will install, in gitexecdir
+ # what 'all' will build and 'install' will install in gitexecdir,
+ # excluding programs for built-in commands
  ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
  
  # what 'all' will build but not install in gitexecdir
@@@ -529,7 -533,6 +530,7 @@@ LIB_OBJS += read-cache.
  LIB_OBJS += reflog-walk.o
  LIB_OBJS += refs.o
  LIB_OBJS += remote.o
 +LIB_OBJS += replace_object.o
  LIB_OBJS += rerere.o
  LIB_OBJS += revision.o
  LIB_OBJS += run-command.o
@@@ -547,6 -550,7 +548,7 @@@ LIB_OBJS += symlinks.
  LIB_OBJS += tag.o
  LIB_OBJS += trace.o
  LIB_OBJS += transport.o
+ LIB_OBJS += transport-helper.o
  LIB_OBJS += tree-diff.o
  LIB_OBJS += tree.o
  LIB_OBJS += tree-walk.o
@@@ -619,7 -623,6 +621,7 @@@ BUILTIN_OBJS += builtin-read-tree.
  BUILTIN_OBJS += builtin-receive-pack.o
  BUILTIN_OBJS += builtin-reflog.o
  BUILTIN_OBJS += builtin-remote.o
 +BUILTIN_OBJS += builtin-replace.o
  BUILTIN_OBJS += builtin-rerere.o
  BUILTIN_OBJS += builtin-reset.o
  BUILTIN_OBJS += builtin-rev-list.o
@@@ -637,7 -640,6 +639,7 @@@ BUILTIN_OBJS += builtin-tar-tree.
  BUILTIN_OBJS += builtin-unpack-objects.o
  BUILTIN_OBJS += builtin-update-index.o
  BUILTIN_OBJS += builtin-update-ref.o
 +BUILTIN_OBJS += builtin-update-server-info.o
  BUILTIN_OBJS += builtin-upload-archive.o
  BUILTIN_OBJS += builtin-verify-pack.o
  BUILTIN_OBJS += builtin-verify-tag.o
@@@ -706,7 -708,6 +708,7 @@@ ifeq ($(uname_S),SCO_SV
        TAR = gtar
  endif
  ifeq ($(uname_S),Darwin)
 +      NEEDS_CRYPTO_WITH_SSL = YesPlease
        NEEDS_SSL_WITH_CRYPTO = YesPlease
        NEEDS_LIBICONV = YesPlease
        ifeq ($(shell expr "$(uname_R)" : '[15678]\.'),2)
@@@ -752,6 -753,9 +754,6 @@@ ifeq ($(uname_S),SunOS
                NO_C99_FORMAT = YesPlease
                NO_STRTOUMAX = YesPlease
        endif
 -      ifdef NO_IPV6
 -              NEEDS_RESOLV = YesPlease
 -      endif
        INSTALL = /usr/ucb/install
        TAR = gtar
        BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ -DHAVE_ALLOCA_H
@@@ -920,6 -924,10 +922,6 @@@ els
        NO_PTHREADS = YesPlease
  endif
  endif
 -ifneq (,$(findstring arm,$(uname_M)))
 -      ARM_SHA1 = YesPlease
 -      NO_MKSTEMPS = YesPlease
 -endif
  
  -include config.mak.autogen
  -include config.mak
@@@ -973,9 -981,7 +975,7 @@@ els
        else
                CURL_LIBCURL = -lcurl
        endif
-       BUILTIN_OBJS += builtin-http-fetch.o
-       EXTLIBS += $(CURL_LIBCURL)
-       LIB_OBJS += http.o http-walker.o
+       PROGRAMS += git-remote-curl$X git-http-fetch$X
        curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
        ifeq "$(curl_check)" "070908"
                ifndef NO_EXPAT
@@@ -1010,12 -1016,9 +1010,12 @@@ ifndef NO_OPENSS
        else
                OPENSSL_LINK =
        endif
 +      ifdef NEEDS_CRYPTO_WITH_SSL
 +              OPENSSL_LINK += -lcrypto
 +      endif
  else
        BASIC_CFLAGS += -DNO_OPENSSL
 -      MOZILLA_SHA1 = 1
 +      BLK_SHA1 = 1
        OPENSSL_LIBSSL =
  endif
  ifdef NEEDS_SSL_WITH_CRYPTO
@@@ -1164,18 -1167,23 +1164,18 @@@ ifdef NO_DEFLATE_BOUN
        BASIC_CFLAGS += -DNO_DEFLATE_BOUND
  endif
  
 +ifdef BLK_SHA1
 +      SHA1_HEADER = "block-sha1/sha1.h"
 +      LIB_OBJS += block-sha1/sha1.o
 +else
  ifdef PPC_SHA1
        SHA1_HEADER = "ppc/sha1.h"
        LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o
 -else
 -ifdef ARM_SHA1
 -      SHA1_HEADER = "arm/sha1.h"
 -      LIB_OBJS += arm/sha1.o arm/sha1_arm.o
 -else
 -ifdef MOZILLA_SHA1
 -      SHA1_HEADER = "mozilla-sha1/sha1.h"
 -      LIB_OBJS += mozilla-sha1/sha1.o
  else
        SHA1_HEADER = <openssl/sha.h>
        EXTLIBS += $(LIB_4_CRYPTO)
  endif
  endif
 -endif
  ifdef NO_PERL_MAKEMAKER
        export NO_PERL_MAKEMAKER
  endif
@@@ -1249,6 -1257,7 +1249,7 @@@ ifndef 
        QUIET_LINK     = @echo '   ' LINK $@;
        QUIET_BUILT_IN = @echo '   ' BUILTIN $@;
        QUIET_GEN      = @echo '   ' GEN $@;
+       QUIET_LNCP     = @echo '   ' LN/CP $@;
        QUIET_SUBDIR0  = +@subdir=
        QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
                         $(MAKE) $(PRINT_DIR) -C $$subdir
@@@ -1476,12 -1485,21 +1477,21 @@@ git-imap-send$X: imap-send.o $(GITLIBS
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
  
- http.o http-walker.o http-push.o transport.o: http.h
+ http.o http-walker.o http-push.o: http.h
  
+ http.o http-walker.o: $(LIB_H)
+ git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)
+       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+               $(LIBS) $(CURL_LIBCURL)
  git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
  
+ git-remote-curl$X: remote-curl.o http.o http-walker.o $(GITLIBS)
+       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+               $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
  $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
  $(patsubst git-%$X,%.o,$(PROGRAMS)) git.o: $(LIB_H) $(wildcard */*.h)
  builtin-revert.o wt-status.o: wt-status.h
diff --combined git.c
--- 1/git.c
--- 2/git.c
+++ b/git.c
@@@ -5,10 -5,7 +5,10 @@@
  #include "run-command.h"
  
  const char git_usage_string[] =
 -      "git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
 +      "git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n"
 +      "           [-p|--paginate|--no-pager]\n"
 +      "           [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n"
 +      "           [--help] COMMAND [ARGS]";
  
  const char git_more_info_string[] =
        "See 'git help COMMAND' for more information on a specific command.";
@@@ -312,9 -309,6 +312,6 @@@ static void handle_internal_command(in
                { "get-tar-commit-id", cmd_get_tar_commit_id },
                { "grep", cmd_grep, RUN_SETUP | USE_PAGER },
                { "help", cmd_help },
- #ifndef NO_CURL
-               { "http-fetch", cmd_http_fetch, RUN_SETUP },
- #endif
                { "init", cmd_init_db },
                { "init-db", cmd_init_db },
                { "log", cmd_log, RUN_SETUP | USE_PAGER },
                { "receive-pack", cmd_receive_pack },
                { "reflog", cmd_reflog, RUN_SETUP },
                { "remote", cmd_remote, RUN_SETUP },
 +              { "replace", cmd_replace, RUN_SETUP },
                { "repo-config", cmd_config },
                { "rerere", cmd_rerere, RUN_SETUP },
                { "reset", cmd_reset, RUN_SETUP },
                { "unpack-objects", cmd_unpack_objects, RUN_SETUP },
                { "update-index", cmd_update_index, RUN_SETUP },
                { "update-ref", cmd_update_ref, RUN_SETUP },
 +              { "update-server-info", cmd_update_server_info, RUN_SETUP },
                { "upload-archive", cmd_upload_archive },
                { "verify-tag", cmd_verify_tag, RUN_SETUP },
                { "version", cmd_version },
@@@ -421,9 -413,13 +418,9 @@@ static void execv_dashed_external(cons
         * if we fail because the command is not found, it is
         * OK to return. Otherwise, we just pass along the status code.
         */
 -      status = run_command_v_opt(argv, 0);
 -      if (status != -ERR_RUN_COMMAND_EXEC) {
 -              if (IS_RUN_COMMAND_ERR(status))
 -                      die("unable to run '%s'", argv[0]);
 -              exit(-status);
 -      }
 -      errno = ENOENT; /* as if we called execvp */
 +      status = run_command_v_opt(argv, RUN_SILENT_EXEC_FAILURE);
 +      if (status >= 0 || errno != ENOENT)
 +              exit(status);
  
        argv[0] = tmp;
  
diff --combined transport.c
@@@ -1,9 -1,6 +1,6 @@@
  #include "cache.h"
  #include "transport.h"
  #include "run-command.h"
- #ifndef NO_CURL
- #include "http.h"
- #endif
  #include "pkt-line.h"
  #include "fetch-pack.h"
  #include "send-pack.h"
@@@ -352,50 -349,12 +349,11 @@@ static int rsync_transport_push(struct 
        return result;
  }
  
- /* Generic functions for using commit walkers */
- #ifndef NO_CURL /* http fetch is the only user */
- static int fetch_objs_via_walker(struct transport *transport,
-                                int nr_objs, const struct ref **to_fetch)
- {
-       char *dest = xstrdup(transport->url);
-       struct walker *walker = transport->data;
-       char **objs = xmalloc(nr_objs * sizeof(*objs));
-       int i;
-       walker->get_all = 1;
-       walker->get_tree = 1;
-       walker->get_history = 1;
-       walker->get_verbosely = transport->verbose >= 0;
-       walker->get_recover = 0;
-       for (i = 0; i < nr_objs; i++)
-               objs[i] = xstrdup(sha1_to_hex(to_fetch[i]->old_sha1));
-       if (walker_fetch(walker, nr_objs, objs, NULL, NULL))
-               die("Fetch failed.");
-       for (i = 0; i < nr_objs; i++)
-               free(objs[i]);
-       free(objs);
-       free(dest);
-       return 0;
- }
- #endif /* NO_CURL */
- static int disconnect_walker(struct transport *transport)
- {
-       struct walker *walker = transport->data;
-       if (walker)
-               walker_free(walker);
-       return 0;
- }
  #ifndef NO_CURL
  static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
  {
        const char **argv;
        int argc;
 -      int err;
  
        if (flags & TRANSPORT_PUSH_MIRROR)
                return error("http transport does not support mirror mode");
        while (refspec_nr--)
                argv[argc++] = *refspec++;
        argv[argc] = NULL;
 -      err = run_command_v_opt(argv, RUN_GIT_CMD);
 -      switch (err) {
 -      case -ERR_RUN_COMMAND_FORK:
 -              error("unable to fork for %s", argv[0]);
 -      case -ERR_RUN_COMMAND_EXEC:
 -              error("unable to exec %s", argv[0]);
 -              break;
 -      case -ERR_RUN_COMMAND_WAITPID:
 -      case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
 -      case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
 -      case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
 -              error("%s died with strange error", argv[0]);
 -      }
 -      return !!err;
 +      return !!run_command_v_opt(argv, RUN_GIT_CMD);
  }
  
- static struct ref *get_refs_via_curl(struct transport *transport, int for_push)
- {
-       struct strbuf buffer = STRBUF_INIT;
-       char *data, *start, *mid;
-       char *ref_name;
-       char *refs_url;
-       int i = 0;
-       int http_ret;
-       struct ref *refs = NULL;
-       struct ref *ref = NULL;
-       struct ref *last_ref = NULL;
-       struct walker *walker;
-       if (for_push)
-               return NULL;
-       if (!transport->data)
-               transport->data = get_http_walker(transport->url,
-                                               transport->remote);
-       walker = transport->data;
-       refs_url = xmalloc(strlen(transport->url) + 11);
-       sprintf(refs_url, "%s/info/refs", transport->url);
-       http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);
-       switch (http_ret) {
-       case HTTP_OK:
-               break;
-       case HTTP_MISSING_TARGET:
-               die("%s not found: did you run git update-server-info on the"
-                   " server?", refs_url);
-       default:
-               http_error(refs_url, http_ret);
-               die("HTTP request failed");
-       }
-       data = buffer.buf;
-       start = NULL;
-       mid = data;
-       while (i < buffer.len) {
-               if (!start)
-                       start = &data[i];
-               if (data[i] == '\t')
-                       mid = &data[i];
-               if (data[i] == '\n') {
-                       data[i] = 0;
-                       ref_name = mid + 1;
-                       ref = xmalloc(sizeof(struct ref) +
-                                     strlen(ref_name) + 1);
-                       memset(ref, 0, sizeof(struct ref));
-                       strcpy(ref->name, ref_name);
-                       get_sha1_hex(start, ref->old_sha1);
-                       if (!refs)
-                               refs = ref;
-                       if (last_ref)
-                               last_ref->next = ref;
-                       last_ref = ref;
-                       start = NULL;
-               }
-               i++;
-       }
-       strbuf_release(&buffer);
-       ref = alloc_ref("HEAD");
-       if (!walker->fetch_ref(walker, ref) &&
-           !resolve_remote_symref(ref, refs)) {
-               ref->next = refs;
-               refs = ref;
-       } else {
-               free(ref);
-       }
-       strbuf_release(&buffer);
-       free(refs_url);
-       return refs;
- }
- static int fetch_objs_via_curl(struct transport *transport,
-                                int nr_objs, const struct ref **to_fetch)
- {
-       if (!transport->data)
-               transport->data = get_http_walker(transport->url,
-                                               transport->remote);
-       return fetch_objs_via_walker(transport, nr_objs, to_fetch);
- }
  #endif
  
  struct bundle_transport_data {
@@@ -667,21 -549,6 +535,21 @@@ static int fetch_refs_via_pack(struct t
        return (refs ? 0 : -1);
  }
  
 +static int push_had_errors(struct ref *ref)
 +{
 +      for (; ref; ref = ref->next) {
 +              switch (ref->status) {
 +              case REF_STATUS_NONE:
 +              case REF_STATUS_UPTODATE:
 +              case REF_STATUS_OK:
 +                      break;
 +              default:
 +                      return 1;
 +              }
 +      }
 +      return 0;
 +}
 +
  static int refs_pushed(struct ref *ref)
  {
        for (; ref; ref = ref->next) {
@@@ -821,7 -688,7 +689,7 @@@ static int print_one_push_status(struc
  }
  
  static void print_push_status(const char *dest, struct ref *refs,
 -                                                        int verbose, int porcelain)
 +                            int verbose, int porcelain, int * nonfastforward)
  {
        struct ref *ref;
        int n = 0;
                if (ref->status == REF_STATUS_OK)
                        n += print_one_push_status(ref, dest, n, porcelain);
  
 +      *nonfastforward = 0;
        for (ref = refs; ref; ref = ref->next) {
                if (ref->status != REF_STATUS_NONE &&
                    ref->status != REF_STATUS_UPTODATE &&
                    ref->status != REF_STATUS_OK)
                        n += print_one_push_status(ref, dest, n, porcelain);
 +              if (ref->status == REF_STATUS_REJECT_NONFASTFORWARD)
 +                      *nonfastforward = 1;
        }
  }
  
@@@ -896,7 -760,6 +764,7 @@@ static int git_transport_push(struct tr
        args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
        args.use_thin_pack = data->thin;
        args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
 +      args.quiet = !!(flags & TRANSPORT_PUSH_QUIET);
        args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
  
        ret = send_pack(&args, data->fd, data->conn, remote_refs,
@@@ -955,14 -818,12 +823,12 @@@ struct transport *transport_get(struct 
        } else if (!prefixcmp(url, "http://")
                || !prefixcmp(url, "https://")
                || !prefixcmp(url, "ftp://")) {
+               transport_helper_init(ret, "curl");
  #ifdef NO_CURL
                error("git was compiled without libcurl support.");
  #else
-               ret->get_refs_list = get_refs_via_curl;
-               ret->fetch = fetch_objs_via_curl;
                ret->push = curl_transport_push;
  #endif
-               ret->disconnect = disconnect_walker;
  
        } else if (is_local(url) && is_file(url)) {
                struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
@@@ -1002,8 -863,7 +868,8 @@@ int transport_set_option(struct transpo
  }
  
  int transport_push(struct transport *transport,
 -                 int refspec_nr, const char **refspec, int flags)
 +                 int refspec_nr, const char **refspec, int flags,
 +                 int * nonfastforward)
  {
        verify_remote_names(refspec_nr, refspec);
  
                struct ref *local_refs = get_local_heads();
                int match_flags = MATCH_REFS_NONE;
                int verbose = flags & TRANSPORT_PUSH_VERBOSE;
 +              int quiet = flags & TRANSPORT_PUSH_QUIET;
                int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
                int ret;
  
  
                ret = transport->push_refs(transport, remote_refs, flags);
  
 -              print_push_status(transport->url, remote_refs, verbose | porcelain, porcelain);
 +              if (!quiet || push_had_errors(remote_refs))
 +                      print_push_status(transport->url, remote_refs,
 +                                      verbose | porcelain, porcelain,
 +                                      nonfastforward);
  
                if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
                        struct ref *ref;
                                update_tracking_ref(transport->remote, ref, verbose);
                }
  
 -              if (!ret && !refs_pushed(remote_refs))
 +              if (!quiet && !ret && !refs_pushed(remote_refs))
                        fprintf(stderr, "Everything up-to-date\n");
                return ret;
        }
@@@ -1059,12 -915,11 +925,12 @@@ const struct ref *transport_get_remote_
  int transport_fetch_refs(struct transport *transport, const struct ref *refs)
  {
        int rc;
 -      int nr_heads = 0, nr_alloc = 0;
 +      int nr_heads = 0, nr_alloc = 0, nr_refs = 0;
        const struct ref **heads = NULL;
        const struct ref *rm;
  
        for (rm = refs; rm; rm = rm->next) {
 +              nr_refs++;
                if (rm->peer_ref &&
                    !hashcmp(rm->peer_ref->old_sha1, rm->old_sha1))
                        continue;
                heads[nr_heads++] = rm;
        }
  
 +      if (!nr_heads) {
 +              /*
 +               * When deepening of a shallow repository is requested,
 +               * then local and remote refs are likely to still be equal.
 +               * Just feed them all to the fetch method in that case.
 +               * This condition shouldn't be met in a non-deepening fetch
 +               * (see builtin-fetch.c:quickfetch()).
 +               */
 +              heads = xmalloc(nr_refs * sizeof(*heads));
 +              for (rm = refs; rm; rm = rm->next)
 +                      heads[nr_heads++] = rm;
 +      }
 +
        rc = transport->fetch(transport, nr_heads, heads);
        free(heads);
        return rc;
diff --combined transport.h
@@@ -36,7 -36,6 +36,7 @@@ struct transport 
  #define TRANSPORT_PUSH_MIRROR 8
  #define TRANSPORT_PUSH_VERBOSE 16
  #define TRANSPORT_PUSH_PORCELAIN 32
 +#define TRANSPORT_PUSH_QUIET 64
  
  /* Returns a transport suitable for the url */
  struct transport *transport_get(struct remote *, const char *);
@@@ -69,8 -68,7 +69,8 @@@ int transport_set_option(struct transpo
                         const char *value);
  
  int transport_push(struct transport *connection,
 -                 int refspec_nr, const char **refspec, int flags);
 +                 int refspec_nr, const char **refspec, int flags,
 +                 int * nonfastforward);
  
  const struct ref *transport_get_remote_refs(struct transport *transport);
  
@@@ -79,4 -77,7 +79,7 @@@ void transport_unlock_pack(struct trans
  int transport_disconnect(struct transport *transport);
  char *transport_anonymize_url(const char *url);
  
+ /* Transport methods defined outside transport.c */
+ int transport_helper_init(struct transport *transport, const char *name);
  #endif