t0020-crlf.sh: use the $( ... ) construct for command substitution
[gitweb.git] / transport-helper.c
index 673b7c214f981cf158a8790b7278e37611c700fa..86e1679c1e0e1e58ebe5297f4c5f48ca1a1f6418 100644 (file)
@@ -190,7 +190,7 @@ static struct child_process *get_helper(struct transport *transport)
                        data->export = 1;
                else if (!strcmp(capname, "check-connectivity"))
                        data->check_connectivity = 1;
-               else if (!data->refspecs && !prefixcmp(capname, "refspec ")) {
+               else if (!data->refspecs && starts_with(capname, "refspec ")) {
                        ALLOC_GROW(refspecs,
                                   refspec_nr + 1,
                                   refspec_alloc);
@@ -199,17 +199,17 @@ static struct child_process *get_helper(struct transport *transport)
                        data->connect = 1;
                } else if (!strcmp(capname, "signed-tags")) {
                        data->signed_tags = 1;
-               } else if (!prefixcmp(capname, "export-marks ")) {
+               } else if (starts_with(capname, "export-marks ")) {
                        struct strbuf arg = STRBUF_INIT;
                        strbuf_addstr(&arg, "--export-marks=");
                        strbuf_addstr(&arg, capname + strlen("export-marks "));
                        data->export_marks = strbuf_detach(&arg, NULL);
-               } else if (!prefixcmp(capname, "import-marks")) {
+               } else if (starts_with(capname, "import-marks")) {
                        struct strbuf arg = STRBUF_INIT;
                        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")) {
+               } else if (starts_with(capname, "no-private-update")) {
                        data->no_private_update = 1;
                } else if (mandatory) {
                        die("Unknown mandatory capability %s. This remote "
@@ -311,7 +311,7 @@ static int set_helper_option(struct transport *transport,
 
        if (!strcmp(buf.buf, "ok"))
                ret = 0;
-       else if (!prefixcmp(buf.buf, "error")) {
+       else if (starts_with(buf.buf, "error")) {
                ret = -1;
        } else if (!strcmp(buf.buf, "unsupported"))
                ret = 1;
@@ -360,6 +360,12 @@ static int fetch_with_fetch(struct transport *transport,
            data->transport_options.check_self_contained_and_connected)
                set_helper_option(transport, "check-connectivity", "true");
 
+       if (transport->cloning)
+               set_helper_option(transport, "cloning", "true");
+
+       if (data->transport_options.update_shallow)
+               set_helper_option(transport, "update-shallow", "true");
+
        for (i = 0; i < nr_heads; i++) {
                const struct ref *posn = to_fetch[i];
                if (posn->status & REF_STATUS_UPTODATE)
@@ -375,7 +381,7 @@ static int fetch_with_fetch(struct transport *transport,
        while (1) {
                recvline(data, &buf);
 
-               if (!prefixcmp(buf.buf, "lock ")) {
+               if (starts_with(buf.buf, "lock ")) {
                        const char *name = buf.buf + 5;
                        if (transport->pack_lockfile)
                                warning("%s also locked %s", data->name, name);
@@ -644,12 +650,12 @@ static int push_update_ref_status(struct strbuf *buf,
                                   struct ref *remote_refs)
 {
        char *refname, *msg;
-       int status;
+       int status, forced = 0;
 
-       if (!prefixcmp(buf->buf, "ok ")) {
+       if (starts_with(buf->buf, "ok ")) {
                status = REF_STATUS_OK;
                refname = buf->buf + 3;
-       } else if (!prefixcmp(buf->buf, "error ")) {
+       } else if (starts_with(buf->buf, "error ")) {
                status = REF_STATUS_REMOTE_REJECT;
                refname = buf->buf + 6;
        } else
@@ -702,6 +708,11 @@ static int push_update_ref_status(struct strbuf *buf,
                        free(msg);
                        msg = NULL;
                }
+               else if (!strcmp(msg, "forced update")) {
+                       forced = 1;
+                       free(msg);
+                       msg = NULL;
+               }
        }
 
        if (*ref)
@@ -723,12 +734,14 @@ static int push_update_ref_status(struct strbuf *buf,
        }
 
        (*ref)->status = status;
+       (*ref)->forced_update |= forced;
        (*ref)->remote_status = msg;
        return !(status == REF_STATUS_OK);
 }
 
 static void push_update_refs_status(struct helper_data *data,
-                                   struct ref *remote_refs)
+                                   struct ref *remote_refs,
+                                   int flags)
 {
        struct strbuf buf = STRBUF_INIT;
        struct ref *ref = remote_refs;
@@ -742,7 +755,7 @@ static void push_update_refs_status(struct helper_data *data,
                if (push_update_ref_status(&buf, &ref, remote_refs))
                        continue;
 
-               if (!data->refspecs || data->no_private_update)
+               if (flags & TRANSPORT_PUSH_DRY_RUN || !data->refspecs || data->no_private_update)
                        continue;
 
                /* propagate back the update to the remote namespace */
@@ -833,7 +846,7 @@ static int push_refs_with_push(struct transport *transport,
        sendline(data, &buf);
        strbuf_release(&buf);
 
-       push_update_refs_status(data, remote_refs);
+       push_update_refs_status(data, remote_refs, flags);
        return 0;
 }
 
@@ -854,6 +867,11 @@ static int push_refs_with_export(struct transport *transport,
                        die("helper %s does not support dry-run", data->name);
        }
 
+       if (flags & TRANSPORT_PUSH_FORCE) {
+               if (set_helper_option(transport, "force", "true") != 0)
+                       warning("helper %s does not support 'force'", data->name);
+       }
+
        helper = get_helper(transport);
 
        write_constant(helper->in, "export\n");
@@ -875,9 +893,6 @@ static int push_refs_with_export(struct transport *transport,
                }
                free(private);
 
-               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");
@@ -890,7 +905,7 @@ static int push_refs_with_export(struct transport *transport,
 
        if (finish_command(&exporter))
                die("Error while running fast-export");
-       push_update_refs_status(data, remote_refs);
+       push_update_refs_status(data, remote_refs, flags);
        return 0;
 }
 
@@ -1129,9 +1144,8 @@ static int udt_do_write(struct unidirectional_transfer *t)
                return 0;       /* Nothing to write. */
 
        transfer_debug("%s is writable", t->dest_name);
-       bytes = write(t->dest, t->buf, t->bufuse);
-       if (bytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN &&
-               errno != EINTR) {
+       bytes = xwrite(t->dest, t->buf, t->bufuse);
+       if (bytes < 0 && errno != EWOULDBLOCK) {
                error("write(%s) failed: %s", t->dest_name, strerror(errno));
                return -1;
        } else if (bytes > 0) {