Merge branch 'kk/tests-with-no-perl'
[gitweb.git] / transport-helper.c
index 45a35df66e09984c6db9fb86a35ece552a1cbcb1..b32e2d64dd344c3f8c4d5f42b6c48dd6bdb8d29f 100644 (file)
@@ -27,7 +27,9 @@ struct helper_data {
                push : 1,
                connect : 1,
                signed_tags : 1,
-               no_disconnect_req : 1;
+               check_connectivity : 1,
+               no_disconnect_req : 1,
+               no_private_update : 1;
        char *export_marks;
        char *import_marks;
        /* These go from remote name (as in "list") to private name */
@@ -186,6 +188,8 @@ static struct child_process *get_helper(struct transport *transport)
                        data->bidi_import = 1;
                else if (!strcmp(capname, "export"))
                        data->export = 1;
+               else if (!strcmp(capname, "check-connectivity"))
+                       data->check_connectivity = 1;
                else if (!data->refspecs && !prefixcmp(capname, "refspec ")) {
                        ALLOC_GROW(refspecs,
                                   refspec_nr + 1,
@@ -205,6 +209,8 @@ static struct child_process *get_helper(struct transport *transport)
                        strbuf_addstr(&arg, "--import-marks=");
                        strbuf_addstr(&arg, capname + strlen("import-marks "));
                        data->import_marks = strbuf_detach(&arg, NULL);
+               } else if (!prefixcmp(capname, "no-private-update")) {
+                       data->no_private_update = 1;
                } else if (mandatory) {
                        die("Unknown mandatory capability %s. This remote "
                            "helper probably needs newer version of Git.",
@@ -349,6 +355,9 @@ static int fetch_with_fetch(struct transport *transport,
        struct strbuf buf = STRBUF_INIT;
 
        standard_options(transport);
+       if (data->check_connectivity &&
+           data->transport_options.check_self_contained_and_connected)
+               set_helper_option(transport, "check-connectivity", "true");
 
        for (i = 0; i < nr_heads; i++) {
                const struct ref *posn = to_fetch[i];
@@ -372,6 +381,10 @@ static int fetch_with_fetch(struct transport *transport,
                        else
                                transport->pack_lockfile = xstrdup(name);
                }
+               else if (data->check_connectivity &&
+                        data->transport_options.check_self_contained_and_connected &&
+                        !strcmp(buf.buf, "connectivity-ok"))
+                       data->transport_options.self_contained_and_connected = 1;
                else if (!buf.len)
                        break;
                else
@@ -683,6 +696,11 @@ static int push_update_ref_status(struct strbuf *buf,
                        free(msg);
                        msg = NULL;
                }
+               else if (!strcmp(msg, "stale info")) {
+                       status = REF_STATUS_REJECT_STALE;
+                       free(msg);
+                       msg = NULL;
+               }
        }
 
        if (*ref)
@@ -723,7 +741,7 @@ static void push_update_refs_status(struct helper_data *data,
                if (push_update_ref_status(&buf, &ref, remote_refs))
                        continue;
 
-               if (!data->refspecs)
+               if (!data->refspecs || data->no_private_update)
                        continue;
 
                /* propagate back the update to the remote namespace */
@@ -737,13 +755,15 @@ static void push_update_refs_status(struct helper_data *data,
 }
 
 static int push_refs_with_push(struct transport *transport,
-               struct ref *remote_refs, int flags)
+                              struct ref *remote_refs, int flags)
 {
        int force_all = flags & TRANSPORT_PUSH_FORCE;
        int mirror = flags & TRANSPORT_PUSH_MIRROR;
        struct helper_data *data = transport->data;
        struct strbuf buf = STRBUF_INIT;
        struct ref *ref;
+       struct string_list cas_options = STRING_LIST_INIT_DUP;
+       struct string_list_item *cas_option;
 
        get_helper(transport);
        if (!data->push)
@@ -756,6 +776,7 @@ static int push_refs_with_push(struct transport *transport,
                /* Check for statuses set by set_ref_status_for_push() */
                switch (ref->status) {
                case REF_STATUS_REJECT_NONFASTFORWARD:
+               case REF_STATUS_REJECT_STALE:
                case REF_STATUS_REJECT_ALREADY_EXISTS:
                case REF_STATUS_UPTODATE:
                        continue;
@@ -778,11 +799,29 @@ static int push_refs_with_push(struct transport *transport,
                strbuf_addch(&buf, ':');
                strbuf_addstr(&buf, ref->name);
                strbuf_addch(&buf, '\n');
+
+               /*
+                * The "--force-with-lease" options without explicit
+                * values to expect have already been expanded into
+                * the ref->old_sha1_expect[] field; we can ignore
+                * transport->smart_options->cas altogether and instead
+                * can enumerate them from the refs.
+                */
+               if (ref->expect_old_sha1) {
+                       struct strbuf cas = STRBUF_INIT;
+                       strbuf_addf(&cas, "%s:%s",
+                                   ref->name, sha1_to_hex(ref->old_sha1_expect));
+                       string_list_append(&cas_options, strbuf_detach(&cas, NULL));
+               }
        }
-       if (buf.len == 0)
+       if (buf.len == 0) {
+               string_list_clear(&cas_options, 0);
                return 0;
+       }
 
        standard_options(transport);
+       for_each_string_list_item(cas_option, &cas_options)
+               set_helper_option(transport, "cas", cas_option->string);
 
        if (flags & TRANSPORT_PUSH_DRY_RUN) {
                if (set_helper_option(transport, "dry-run", "true") != 0)
@@ -1132,7 +1171,7 @@ static void *udt_copy_task_routine(void *udt)
 #ifndef NO_PTHREADS
 
 /*
- * Join thread, with apporiate errors on failure. Name is name for the
+ * Join thread, with appropriate errors on failure. Name is name for the
  * thread (for error messages). Returns 0 on success, 1 on failure.
  */
 static int tloop_join(pthread_t thread, const char *name)
@@ -1198,7 +1237,7 @@ static void udt_kill_transfer(struct unidirectional_transfer *t)
 }
 
 /*
- * Join process, with apporiate errors on failure. Name is name for the
+ * Join process, with appropriate errors on failure. Name is name for the
  * process (for error messages). Returns 0 on success, 1 on failure.
  */
 static int tloop_join(pid_t pid, const char *name)