Merge branch 'fc/transport-helper-no-refspec'
authorJunio C Hamano <gitster@pobox.com>
Thu, 6 Jun 2013 19:17:22 +0000 (12:17 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 6 Jun 2013 19:17:22 +0000 (12:17 -0700)
With "export" remote-helper protocol,

(1) a push that tries to update a remote ref whose name is
different from the pushing side does not work yet, and

(2) the helper may not know how to do --dry-run

Detect such problematic cases and disable them for now.

* fc/transport-helper-no-refspec:
transport-helper: check if the dry-run is supported
transport-helper: barf when user tries old:new

1  2 
transport-helper.c
diff --combined transport-helper.c
index 2f5ac3fbeefd65c61c9e9c89f97896f9dfac89c5,f08eff0ab6172e36ed6b3e4dafe73c776f5868d9..06c08a1786391e7a04fa566af0cf42c659ed8aa9
@@@ -11,7 -11,6 +11,7 @@@
  #include "thread-utils.h"
  #include "sigchain.h"
  #include "argv-array.h"
 +#include "refs.h"
  
  static int debug;
  
@@@ -48,7 -47,7 +48,7 @@@ static void sendline(struct helper_dat
                die_errno("Full write to remote helper failed");
  }
  
 -static int recvline_fh(FILE *helper, struct strbuf *buffer)
 +static int recvline_fh(FILE *helper, struct strbuf *buffer, const char *name)
  {
        strbuf_reset(buffer);
        if (debug)
@@@ -56,7 -55,7 +56,7 @@@
        if (strbuf_getline(buffer, helper, '\n') == EOF) {
                if (debug)
                        fprintf(stderr, "Debug: Remote helper quit.\n");
 -              exit(128);
 +              die("Reading from helper 'git-remote-%s' failed", name);
        }
  
        if (debug)
@@@ -66,7 -65,7 +66,7 @@@
  
  static int recvline(struct helper_data *helper, struct strbuf *buffer)
  {
 -      return recvline_fh(helper->out, buffer);
 +      return recvline_fh(helper->out, buffer, helper->name);
  }
  
  static void xchgline(struct helper_data *helper, struct strbuf *buffer)
@@@ -218,8 -217,6 +218,8 @@@ static struct child_process *get_helper
                for (i = 0; i < refspec_nr; i++)
                        free((char *)refspecs[i]);
                free(refspecs);
 +      } else if (data->import || data->bidi_import || data->export) {
 +              warning("This remote helper should implement refspec capability.");
        }
        strbuf_release(&buf);
        if (debug)
@@@ -476,7 -473,7 +476,7 @@@ static int fetch_with_import(struct tra
         * were fetching.
         *
         * (If no "refspec" capability was specified, for historical
 -       * reasons we default to *:*.)
 +       * reasons we default to the equivalent of *:*.)
         *
         * Store the result in to_fetch[i].old_sha1.  Callers such
         * as "git fetch" can use the value to write feedback to the
@@@ -543,7 -540,7 +543,7 @@@ static int process_connect_service(stru
                goto exit;
  
        sendline(data, &cmdbuf);
 -      recvline_fh(input, &cmdbuf);
 +      recvline_fh(input, &cmdbuf, name);
        if (!strcmp(cmdbuf.buf, "")) {
                data->no_disconnect_req = 1;
                if (debug)
@@@ -625,7 -622,7 +625,7 @@@ static int fetch(struct transport *tran
        return -1;
  }
  
 -static void push_update_ref_status(struct strbuf *buf,
 +static int push_update_ref_status(struct strbuf *buf,
                                   struct ref **ref,
                                   struct ref *remote_refs)
  {
                *ref = find_ref_by_name(remote_refs, refname);
        if (!*ref) {
                warning("helper reported unexpected status of %s", refname);
 -              return;
 +              return 1;
        }
  
        if ((*ref)->status != REF_STATUS_NONE) {
                 * status reported by the remote helper if the latter is 'no match'.
                 */
                if (status == REF_STATUS_NONE)
 -                      return;
 +                      return 1;
        }
  
        (*ref)->status = status;
        (*ref)->remote_status = msg;
 +      return !(status == REF_STATUS_OK);
  }
  
  static void push_update_refs_status(struct helper_data *data,
        struct strbuf buf = STRBUF_INIT;
        struct ref *ref = remote_refs;
        for (;;) {
 +              char *private;
 +
                recvline(data, &buf);
                if (!buf.len)
                        break;
  
 -              push_update_ref_status(&buf, &ref, remote_refs);
 +              if (push_update_ref_status(&buf, &ref, remote_refs))
 +                      continue;
 +
 +              if (!data->refspecs)
 +                      continue;
 +
 +              /* propagate back the update to the remote namespace */
 +              private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
 +              if (!private)
 +                      continue;
 +              update_ref("update by helper", private, ref->new_sha1, NULL, 0, 0);
 +              free(private);
        }
        strbuf_release(&buf);
  }
@@@ -806,9 -789,11 +806,14 @@@ static int push_refs_with_export(struc
        struct string_list revlist_args = STRING_LIST_INIT_NODUP;
        struct strbuf buf = STRBUF_INIT;
  
 +      if (!data->refspecs)
 +              die("remote-helper doesn't support push; refspec needed");
 +
+       if (flags & TRANSPORT_PUSH_DRY_RUN) {
+               if (set_helper_option(transport, "dry-run", "true") != 0)
+                       die("helper %s does not support dry-run", data->name);
+       }
        helper = get_helper(transport);
  
        write_constant(helper->in, "export\n");
                char *private;
                unsigned char sha1[20];
  
 -              if (!data->refspecs)
 -                      continue;
 +              if (ref->deletion)
 +                      die("remote-helpers do not support ref deletion");
 +
                private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
                if (private && !get_sha1(private, sha1)) {
                        strbuf_addf(&buf, "^%s", private);
                }
                free(private);
  
-               if (ref->peer_ref)
 -              if (ref->deletion) {
++              if (ref->deletion)
+                       die("remote-helpers do not support ref deletion");
 -              }
+               if (ref->peer_ref) {
+                       if (strcmp(ref->peer_ref->name, ref->name))
+                               die("remote-helpers do not support old:new syntax");
                        string_list_append(&revlist_args, ref->peer_ref->name);
+               }
        }
  
        if (get_exporter(transport, &exporter, &revlist_args))