Merge branch 'jk/drop-rsync-transport'
authorJunio C Hamano <gitster@pobox.com>
Wed, 17 Feb 2016 18:13:28 +0000 (10:13 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 17 Feb 2016 18:13:28 +0000 (10:13 -0800)
It turns out "git clone" over rsync transport has been broken when
the source repository has packed references for a long time, and
nobody noticed nor complained about it.

* jk/drop-rsync-transport:
transport: drop support for git-over-rsync

1  2 
Documentation/config.txt
Documentation/git-clone.txt
Documentation/git.txt
t/t5510-fetch.sh
transport.c
diff --combined Documentation/config.txt
index 27f02be35ed2aebedab93281814b1f4e0fea4f35,d2e41c9bd918b44291d6b9472373136beede7929..0a08638bcda1cdfa7d2d8114e39d727c7611d009
@@@ -308,15 -308,6 +308,15 @@@ core.trustctime:
        crawlers and some backup systems).
        See linkgit:git-update-index[1]. True by default.
  
 +core.untrackedCache::
 +      Determines what to do about the untracked cache feature of the
 +      index. It will be kept, if this variable is unset or set to
 +      `keep`. It will automatically be added if set to `true`. And
 +      it will automatically be removed, if set to `false`. Before
 +      setting it to `true`, you should check that mtime is working
 +      properly on your system.
 +      See linkgit:git-update-index[1]. `keep` by default.
 +
  core.checkStat::
        Determines which stat fields to match between the index
        and work tree. The user can set this to 'default' or
@@@ -879,8 -870,6 +879,8 @@@ When preserve, also pass `--preserve-me
  so that locally committed merge commits will not be flattened
  by running 'git pull'.
  +
 +When the value is `interactive`, the rebase is run in interactive mode.
 ++
  *NOTE*: this is a possibly dangerous operation; do *not* use
  it unless you understand the implications (see linkgit:git-rebase[1]
  for details).
@@@ -1254,10 -1243,6 +1254,10 @@@ format.coverLetter:
        format-patch is invoked, but in addition can be set to "auto", to
        generate a cover-letter only when there's more than one patch.
  
 +format.outputDirectory::
 +      Set a custom directory to store the resulting files instead of the
 +      current working directory.
 +
  filter.<driver>.clean::
        The command which is used to convert the content of a worktree
        file to a blob upon checkin.  See linkgit:gitattributes[5] for
@@@ -1465,14 -1450,6 +1465,14 @@@ grep.extendedRegexp:
        option is ignored when the 'grep.patternType' option is set to a value
        other than 'default'.
  
 +grep.threads::
 +      Number of grep worker threads to use.
 +      See `grep.threads` in linkgit:git-grep[1] for more information.
 +
 +grep.fallbackToNoIndex::
 +      If set to true, fall back to git grep --no-index if git grep
 +      is executed outside of a git repository.  Defaults to false.
 +
  gpg.program::
        Use this custom program instead of "gpg" found on $PATH when
        making or verifying a PGP signature. The program must support the
@@@ -1619,34 -1596,9 +1619,34 @@@ help.htmlPath:
  
  http.proxy::
        Override the HTTP proxy, normally configured using the 'http_proxy',
 -      'https_proxy', and 'all_proxy' environment variables (see
 -      `curl(1)`).  This can be overridden on a per-remote basis; see
 -      remote.<name>.proxy
 +      'https_proxy', and 'all_proxy' environment variables (see `curl(1)`). In
 +      addition to the syntax understood by curl, it is possible to specify a
 +      proxy string with a user name but no password, in which case git will
 +      attempt to acquire one in the same way it does for other credentials. See
 +      linkgit:gitcredentials[7] for more information. The syntax thus is
 +      '[protocol://][user[:password]@]proxyhost[:port]'. This can be overridden
 +      on a per-remote basis; see remote.<name>.proxy
 +
 +http.proxyAuthMethod::
 +      Set the method with which to authenticate against the HTTP proxy. This
 +      only takes effect if the configured proxy string contains a user name part
 +      (i.e. is of the form 'user@host' or 'user@host:port'). This can be
 +      overridden on a per-remote basis; see `remote.<name>.proxyAuthMethod`.
 +      Both can be overridden by the 'GIT_HTTP_PROXY_AUTHMETHOD' environment
 +      variable.  Possible values are:
 ++
 +--
 +* `anyauth` - Automatically pick a suitable authentication method. It is
 +  assumed that the proxy answers an unauthenticated request with a 407
 +  status code and one or more Proxy-authenticate headers with supported
 +  authentication methods. This is the default.
 +* `basic` - HTTP Basic authentication
 +* `digest` - HTTP Digest authentication; this prevents the password from being
 +  transmitted to the proxy in clear text
 +* `negotiate` - GSS-Negotiate authentication (compare the --negotiate option
 +  of `curl(1)`)
 +* `ntlm` - NTLM authentication (compare the --ntlm option of `curl(1)`)
 +--
  
  http.cookieFile::
        File containing previously stored cookie lines which should be used
@@@ -2122,7 -2074,7 +2122,7 @@@ pack.indexVersion:
        larger than 2 GB.
  +
  If you have an old Git that does not understand the version 2 `*.idx` file,
- cloning or fetching over a non native protocol (e.g. "http" and "rsync")
+ cloning or fetching over a non native protocol (e.g. "http")
  that will copy both `*.pack` file and corresponding `*.idx` file from the
  other side may give you a repository that cannot be accessed with your
  older version of Git. If the `*.pack` file is smaller than 2 GB, however,
@@@ -2197,8 -2149,6 +2197,8 @@@ When preserve, also pass `--preserve-me
  so that locally committed merge commits will not be flattened
  by running 'git pull'.
  +
 +When the value is `interactive`, the rebase is run in interactive mode.
 ++
  *NOTE*: this is a possibly dangerous operation; do *not* use
  it unless you understand the implications (see linkgit:git-rebase[1]
  for details).
@@@ -2457,11 -2407,6 +2457,11 @@@ remote.<name>.proxy:
        the proxy to use for that remote.  Set to the empty string to
        disable proxying for that remote.
  
 +remote.<name>.proxyAuthMethod::
 +      For remotes that require curl (http, https and ftp), the method to use for
 +      authenticating against the proxy in use (probably set in
 +      `remote.<name>.proxy`). See `http.proxyAuthMethod`.
 +
  remote.<name>.fetch::
        The default set of "refspec" for linkgit:git-fetch[1]. See
        linkgit:git-fetch[1].
index 789b668f7732957d71f42f98d361abd0b34305a7,35bcc14484399e5a5c4cb4f299227cab76f6fe7a..b7c467a001ad47de0bebd8c985df769fe4e63adc
@@@ -115,8 -115,7 +115,7 @@@ objects from the source repository int
  --quiet::
  -q::
        Operate quietly.  Progress is not reported to the standard
-       error stream. This flag is also passed to the `rsync'
-       command when given.
+       error stream.
  
  --verbose::
  -v::
  
  --depth <depth>::
        Create a 'shallow' clone with a history truncated to the
 -      specified number of revisions.
 +      specified number of commits. Implies `--single-branch` unless
 +      `--no-single-branch` is given to fetch the histories near the
 +      tips of all branches.
  
  --[no-]single-branch::
        Clone only the history leading to the tip of a single branch,
        either specified by the `--branch` option or the primary
 -      branch remote's `HEAD` points at. When creating a shallow
 -      clone with the `--depth` option, this is the default, unless
 -      `--no-single-branch` is given to fetch the histories near the
 -      tips of all branches.
 +      branch remote's `HEAD` points at.
        Further fetches into the resulting repository will only update the
        remote-tracking branch for the branch this option was used for the
        initial cloning.  If the HEAD at the remote did not point at any
diff --combined Documentation/git.txt
index d987ad20c90a05932733c09812324c3d176ebbbe,6524f4ae4ebbf87ccbc6269521883ca189bed70a..a48c1e802413713122f2f9e4f9dc410950163aef
@@@ -43,10 -43,9 +43,10 @@@ unreleased) version of Git, that is ava
  branch of the `git.git` repository.
  Documentation for older releases are available here:
  
 -* link:v2.7.0/git.html[documentation for release 2.7]
 +* link:v2.7.1/git.html[documentation for release 2.7.1]
  
  * release notes for
 +  link:RelNotes/2.7.1.txt[2.7.1],
    link:RelNotes/2.7.0.txt[2.7].
  
  * link:v2.6.5/git.html[documentation for release 2.6.5]
@@@ -1124,8 -1123,6 +1124,6 @@@ of clones and fetches
          - `ssh`: git over ssh (including `host:path` syntax,
            `git+ssh://`, etc).
  
-         - `rsync`: git over rsync
          - `http`: git over http, both "smart http" and "dumb http".
            Note that this does _not_ include `https`; if you want both,
            you should specify both as `http:https`.
diff --combined t/t5510-fetch.sh
index 9203a6507fa8df75ef187c129f750921caf19951,c3838786c51eb6419e5b3322d18ecba5824e970d..0c10c856a96072a1b0c37530a9f5c8605d8833b5
@@@ -7,7 -7,7 +7,7 @@@ test_description='Per branch config var
  
  . ./test-lib.sh
  
 -D=`pwd`
 +D=$(pwd)
  
  test_bundle_object_count () {
        git verify-pack -v "$1" >verify.out &&
@@@ -64,8 -64,8 +64,8 @@@ test_expect_success "fetch test" 
        cd two &&
        git fetch &&
        test -f .git/refs/heads/one &&
 -      mine=`git rev-parse refs/heads/one` &&
 -      his=`cd ../one && git rev-parse refs/heads/master` &&
 +      mine=$(git rev-parse refs/heads/one) &&
 +      his=$(cd ../one && git rev-parse refs/heads/master) &&
        test "z$mine" = "z$his"
  '
  
@@@ -75,8 -75,8 +75,8 @@@ test_expect_success "fetch test for-mer
        git fetch &&
        test -f .git/refs/heads/two &&
        test -f .git/refs/heads/one &&
 -      master_in_two=`cd ../two && git rev-parse master` &&
 -      one_in_two=`cd ../two && git rev-parse one` &&
 +      master_in_two=$(cd ../two && git rev-parse master) &&
 +      one_in_two=$(cd ../two && git rev-parse one) &&
        {
                echo "$one_in_two       "
                echo "$master_in_two    not-for-merge"
@@@ -314,42 -314,6 +314,6 @@@ test_expect_success 'bundle should be a
  
  '
  
- ! rsync --help > /dev/null 2> /dev/null &&
- say 'Skipping rsync tests because rsync was not found' || {
- test_expect_success 'fetch via rsync' '
-       git pack-refs &&
-       mkdir rsynced &&
-       (cd rsynced &&
-        git init --bare &&
-        git fetch "rsync:../.git" master:refs/heads/master &&
-        git gc --prune &&
-        test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
-        git fsck --full)
- '
- test_expect_success 'push via rsync' '
-       mkdir rsynced2 &&
-       (cd rsynced2 &&
-        git init) &&
-       (cd rsynced &&
-        git push "rsync:../rsynced2/.git" master) &&
-       (cd rsynced2 &&
-        git gc --prune &&
-        test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
-        git fsck --full)
- '
- test_expect_success 'push via rsync' '
-       mkdir rsynced3 &&
-       (cd rsynced3 &&
-        git init) &&
-       git push --all "rsync:rsynced3/.git" &&
-       (cd rsynced3 &&
-        test $(git rev-parse master) = $(cd .. && git rev-parse master) &&
-        git fsck --full)
- '
- }
  test_expect_success 'fetch with a non-applying branch.<name>.merge' '
        git config branch.master.remote yeti &&
        git config branch.master.merge refs/heads/bigfoot &&
@@@ -708,17 -672,4 +672,17 @@@ test_expect_success 'fetching a one-lev
        )
  '
  
 +test_expect_success 'fetching with auto-gc does not lock up' '
 +      write_script askyesno <<-\EOF &&
 +      echo "$*" &&
 +      false
 +      EOF
 +      git clone "file://$D" auto-gc &&
 +      test_commit test2 &&
 +      cd auto-gc &&
 +      git config gc.autoPackLimit 1 &&
 +      GIT_ASK_YESNO="$D/askyesno" git fetch >fetch.out 2>&1 &&
 +      ! grep "Should I try again" fetch.out
 +'
 +
  test_done
diff --combined transport.c
index 9ae71849d622d088a90bfcab81f9053fccfe79ac,9da4e89fd9a80f1c50d9712182ed0c8afda7528e..c92f8ae7054e3340cf1a40c3f74c70b7aab7303a
  #include "sha1-array.h"
  #include "sigchain.h"
  
- /* rsync support */
- /*
-  * We copy packed-refs and refs/ into a temporary file, then read the
-  * loose refs recursively (sorting whenever possible), and then inserting
-  * those packed refs that are not yet in the list (not validating, but
-  * assuming that the file is sorted).
-  *
-  * Appears refactoring this from refs.c is too cumbersome.
-  */
- static int str_cmp(const void *a, const void *b)
- {
-       const char *s1 = a;
-       const char *s2 = b;
-       return strcmp(s1, s2);
- }
- /* path->buf + name_offset is expected to point to "refs/" */
- static int read_loose_refs(struct strbuf *path, int name_offset,
-               struct ref **tail)
- {
-       DIR *dir = opendir(path->buf);
-       struct dirent *de;
-       struct {
-               char **entries;
-               int nr, alloc;
-       } list;
-       int i, pathlen;
-       if (!dir)
-               return -1;
-       memset (&list, 0, sizeof(list));
-       while ((de = readdir(dir))) {
-               if (is_dot_or_dotdot(de->d_name))
-                       continue;
-               ALLOC_GROW(list.entries, list.nr + 1, list.alloc);
-               list.entries[list.nr++] = xstrdup(de->d_name);
-       }
-       closedir(dir);
-       /* sort the list */
-       qsort(list.entries, list.nr, sizeof(char *), str_cmp);
-       pathlen = path->len;
-       strbuf_addch(path, '/');
-       for (i = 0; i < list.nr; i++, strbuf_setlen(path, pathlen + 1)) {
-               strbuf_addstr(path, list.entries[i]);
-               if (read_loose_refs(path, name_offset, tail)) {
-                       int fd = open(path->buf, O_RDONLY);
-                       char buffer[40];
-                       struct ref *next;
-                       if (fd < 0)
-                               continue;
-                       next = alloc_ref(path->buf + name_offset);
-                       if (read_in_full(fd, buffer, 40) != 40 ||
-                                       get_oid_hex(buffer, &next->old_oid)) {
-                               close(fd);
-                               free(next);
-                               continue;
-                       }
-                       close(fd);
-                       (*tail)->next = next;
-                       *tail = next;
-               }
-       }
-       strbuf_setlen(path, pathlen);
-       for (i = 0; i < list.nr; i++)
-               free(list.entries[i]);
-       free(list.entries);
-       return 0;
- }
- /* insert the packed refs for which no loose refs were found */
- static void insert_packed_refs(const char *packed_refs, struct ref **list)
- {
-       FILE *f = fopen(packed_refs, "r");
-       static char buffer[PATH_MAX];
-       if (!f)
-               return;
-       for (;;) {
-               int cmp = 0; /* assigned before used */
-               int len;
-               if (!fgets(buffer, sizeof(buffer), f)) {
-                       fclose(f);
-                       return;
-               }
-               if (!isxdigit(buffer[0]))
-                       continue;
-               len = strlen(buffer);
-               if (len && buffer[len - 1] == '\n')
-                       buffer[--len] = '\0';
-               if (len < 41)
-                       continue;
-               while ((*list)->next &&
-                               (cmp = strcmp(buffer + 41,
-                                     (*list)->next->name)) > 0)
-                       list = &(*list)->next;
-               if (!(*list)->next || cmp < 0) {
-                       struct ref *next = alloc_ref(buffer + 41);
-                       buffer[40] = '\0';
-                       if (get_oid_hex(buffer, &next->old_oid)) {
-                               warning ("invalid SHA-1: %s", buffer);
-                               free(next);
-                               continue;
-                       }
-                       next->next = (*list)->next;
-                       (*list)->next = next;
-                       list = &(*list)->next;
-               }
-       }
- }
  static void set_upstreams(struct transport *transport, struct ref *refs,
        int pretend)
  {
        }
  }
  
- static const char *rsync_url(const char *url)
- {
-       if (!starts_with(url, "rsync://"))
-               skip_prefix(url, "rsync:", &url);
-       return url;
- }
- static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
- {
-       struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
-       struct ref dummy = {NULL}, *tail = &dummy;
-       struct child_process rsync = CHILD_PROCESS_INIT;
-       const char *args[5];
-       int temp_dir_len;
-       if (for_push)
-               return NULL;
-       /* copy the refs to the temporary directory */
-       strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
-       if (!mkdtemp(temp_dir.buf))
-               die_errno ("Could not make temporary directory");
-       temp_dir_len = temp_dir.len;
-       strbuf_addstr(&buf, rsync_url(transport->url));
-       strbuf_addstr(&buf, "/refs");
-       rsync.argv = args;
-       rsync.stdout_to_stderr = 1;
-       args[0] = "rsync";
-       args[1] = (transport->verbose > 1) ? "-rv" : "-r";
-       args[2] = buf.buf;
-       args[3] = temp_dir.buf;
-       args[4] = NULL;
-       if (run_command(&rsync))
-               die ("Could not run rsync to get refs");
-       strbuf_reset(&buf);
-       strbuf_addstr(&buf, rsync_url(transport->url));
-       strbuf_addstr(&buf, "/packed-refs");
-       args[2] = buf.buf;
-       if (run_command(&rsync))
-               die ("Could not run rsync to get refs");
-       /* read the copied refs */
-       strbuf_addstr(&temp_dir, "/refs");
-       read_loose_refs(&temp_dir, temp_dir_len + 1, &tail);
-       strbuf_setlen(&temp_dir, temp_dir_len);
-       tail = &dummy;
-       strbuf_addstr(&temp_dir, "/packed-refs");
-       insert_packed_refs(temp_dir.buf, &tail);
-       strbuf_setlen(&temp_dir, temp_dir_len);
-       if (remove_dir_recursively(&temp_dir, 0))
-               warning ("Error removing temporary directory %s.",
-                               temp_dir.buf);
-       strbuf_release(&buf);
-       strbuf_release(&temp_dir);
-       return dummy.next;
- }
- static int fetch_objs_via_rsync(struct transport *transport,
-                               int nr_objs, struct ref **to_fetch)
- {
-       struct child_process rsync = CHILD_PROCESS_INIT;
-       rsync.stdout_to_stderr = 1;
-       argv_array_push(&rsync.args, "rsync");
-       argv_array_push(&rsync.args, (transport->verbose > 1) ? "-rv" : "-r");
-       argv_array_push(&rsync.args, "--ignore-existing");
-       argv_array_push(&rsync.args, "--exclude");
-       argv_array_push(&rsync.args, "info");
-       argv_array_pushf(&rsync.args, "%s/objects/", rsync_url(transport->url));
-       argv_array_push(&rsync.args, get_object_directory());
-       /* NEEDSWORK: handle one level of alternates */
-       return run_command(&rsync);
- }
- static int write_one_ref(const char *name, const struct object_id *oid,
-                        int flags, void *data)
- {
-       struct strbuf *buf = data;
-       int len = buf->len;
-       /* when called via for_each_ref(), flags is non-zero */
-       if (flags && !starts_with(name, "refs/heads/") &&
-                       !starts_with(name, "refs/tags/"))
-               return 0;
-       strbuf_addstr(buf, name);
-       if (safe_create_leading_directories(buf->buf) ||
-           write_file_gently(buf->buf, "%s", oid_to_hex(oid)))
-               return error("problems writing temporary file %s: %s",
-                            buf->buf, strerror(errno));
-       strbuf_setlen(buf, len);
-       return 0;
- }
- static int write_refs_to_temp_dir(struct strbuf *temp_dir,
-                                 int refspec_nr, const char **refspec)
- {
-       int i;
-       for (i = 0; i < refspec_nr; i++) {
-               struct object_id oid;
-               char *ref;
-               if (dwim_ref(refspec[i], strlen(refspec[i]), oid.hash, &ref) != 1)
-                       return error("Could not get ref %s", refspec[i]);
-               if (write_one_ref(ref, &oid, 0, temp_dir)) {
-                       free(ref);
-                       return -1;
-               }
-               free(ref);
-       }
-       return 0;
- }
- static int rsync_transport_push(struct transport *transport,
-               int refspec_nr, const char **refspec, int flags)
- {
-       struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
-       int result = 0, i;
-       struct child_process rsync = CHILD_PROCESS_INIT;
-       const char *args[10];
-       if (flags & TRANSPORT_PUSH_MIRROR)
-               return error("rsync transport does not support mirror mode");
-       /* first push the objects */
-       strbuf_addstr(&buf, rsync_url(transport->url));
-       strbuf_addch(&buf, '/');
-       rsync.argv = args;
-       rsync.stdout_to_stderr = 1;
-       i = 0;
-       args[i++] = "rsync";
-       args[i++] = "-a";
-       if (flags & TRANSPORT_PUSH_DRY_RUN)
-               args[i++] = "--dry-run";
-       if (transport->verbose > 1)
-               args[i++] = "-v";
-       args[i++] = "--ignore-existing";
-       args[i++] = "--exclude";
-       args[i++] = "info";
-       args[i++] = get_object_directory();
-       args[i++] = buf.buf;
-       args[i++] = NULL;
-       if (run_command(&rsync))
-               return error("Could not push objects to %s",
-                               rsync_url(transport->url));
-       /* copy the refs to the temporary directory; they could be packed. */
-       strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
-       if (!mkdtemp(temp_dir.buf))
-               die_errno ("Could not make temporary directory");
-       strbuf_addch(&temp_dir, '/');
-       if (flags & TRANSPORT_PUSH_ALL) {
-               if (for_each_ref(write_one_ref, &temp_dir))
-                       return -1;
-       } else if (write_refs_to_temp_dir(&temp_dir, refspec_nr, refspec))
-               return -1;
-       i = 2;
-       if (flags & TRANSPORT_PUSH_DRY_RUN)
-               args[i++] = "--dry-run";
-       if (!(flags & TRANSPORT_PUSH_FORCE))
-               args[i++] = "--ignore-existing";
-       args[i++] = temp_dir.buf;
-       args[i++] = rsync_url(transport->url);
-       args[i++] = NULL;
-       if (run_command(&rsync))
-               result = error("Could not push to %s",
-                               rsync_url(transport->url));
-       if (remove_dir_recursively(&temp_dir, 0))
-               warning ("Could not remove temporary directory %s.",
-                               temp_dir.buf);
-       strbuf_release(&buf);
-       strbuf_release(&temp_dir);
-       return result;
- }
  struct bundle_transport_data {
        int fd;
        struct bundle_header header;
@@@ -481,10 -155,9 +155,10 @@@ static int set_git_option(struct git_tr
        return 1;
  }
  
 -static int connect_setup(struct transport *transport, int for_push, int verbose)
 +static int connect_setup(struct transport *transport, int for_push)
  {
        struct git_transport_data *data = transport->data;
 +      int flags = transport->verbose > 0 ? CONNECT_VERBOSE : 0;
  
        if (data->conn)
                return 0;
        data->conn = git_connect(data->fd, transport->url,
                                 for_push ? data->options.receivepack :
                                 data->options.uploadpack,
 -                               verbose ? CONNECT_VERBOSE : 0);
 +                               flags);
  
        return 0;
  }
@@@ -502,7 -175,7 +176,7 @@@ static struct ref *get_refs_via_connect
        struct git_transport_data *data = transport->data;
        struct ref *refs;
  
 -      connect_setup(transport, for_push, 0);
 +      connect_setup(transport, for_push);
        get_remote_heads(data->fd[0], NULL, 0, &refs,
                         for_push ? REF_NORMAL : 0,
                         &data->extra_have,
@@@ -537,7 -210,7 +211,7 @@@ static int fetch_refs_via_pack(struct t
        args.update_shallow = data->options.update_shallow;
  
        if (!data->got_remote_heads) {
 -              connect_setup(transport, 0, 0);
 +              connect_setup(transport, 0);
                get_remote_heads(data->fd[0], NULL, 0, &refs_tmp, 0,
                                 NULL, &data->shallow);
                data->got_remote_heads = 1;
@@@ -813,7 -486,7 +487,7 @@@ static int git_transport_push(struct tr
  
        if (!data->got_remote_heads) {
                struct ref *tmp_refs;
 -              connect_setup(transport, 1, 0);
 +              connect_setup(transport, 1);
  
                get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL,
                                 NULL, &data->shallow);
@@@ -985,11 -658,7 +659,7 @@@ struct transport *transport_get(struct 
        if (helper) {
                transport_helper_init(ret, helper);
        } else if (starts_with(url, "rsync:")) {
-               transport_check_allowed("rsync");
-               ret->get_refs_list = get_refs_via_rsync;
-               ret->fetch = fetch_objs_via_rsync;
-               ret->push = rsync_transport_push;
-               ret->smart_options = NULL;
+               die("git-over-rsync is no longer supported");
        } else if (url_is_local_not_ssh(url) && is_file(url) && is_bundle(url, 1)) {
                struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
                transport_check_allowed("file");