Merge branch 'rs/commit-h-single-parent-cleanup' into next
[gitweb.git] / transport-helper.c
index db2f930c740348bbe55525a2e471857b6dc463f1..8f68d69a86bd919162b62514af0b1d1d55e204a1 100644 (file)
@@ -124,8 +124,9 @@ static struct child_process *get_helper(struct transport *transport)
        helper->git_cmd = 0;
        helper->silent_exec_failure = 1;
 
-       argv_array_pushf(&helper->env_array, "%s=%s", GIT_DIR_ENVIRONMENT,
-                        get_git_dir());
+       if (have_git_dir())
+               argv_array_pushf(&helper->env_array, "%s=%s",
+                                GIT_DIR_ENVIRONMENT, get_git_dir());
 
        code = start_command(helper);
        if (code < 0 && errno == ENOENT)
@@ -241,8 +242,7 @@ static int disconnect_helper(struct transport *transport)
                close(data->helper->out);
                fclose(data->out);
                res = finish_command(data->helper);
-               free(data->helper);
-               data->helper = NULL;
+               FREE_AND_NULL(data->helper);
        }
        return res;
 }
@@ -258,8 +258,51 @@ static const char *boolean_options[] = {
        TRANS_OPT_THIN,
        TRANS_OPT_KEEP,
        TRANS_OPT_FOLLOWTAGS,
+       TRANS_OPT_DEEPEN_RELATIVE
        };
 
+static int strbuf_set_helper_option(struct helper_data *data,
+                                   struct strbuf *buf)
+{
+       int ret;
+
+       sendline(data, buf);
+       if (recvline(data, buf))
+               exit(128);
+
+       if (!strcmp(buf->buf, "ok"))
+               ret = 0;
+       else if (starts_with(buf->buf, "error"))
+               ret = -1;
+       else if (!strcmp(buf->buf, "unsupported"))
+               ret = 1;
+       else {
+               warning("%s unexpectedly said: '%s'", data->name, buf->buf);
+               ret = 1;
+       }
+       return ret;
+}
+
+static int string_list_set_helper_option(struct helper_data *data,
+                                        const char *name,
+                                        struct string_list *list)
+{
+       struct strbuf buf = STRBUF_INIT;
+       int i, ret = 0;
+
+       for (i = 0; i < list->nr; i++) {
+               strbuf_addf(&buf, "option %s ", name);
+               quote_c_style(list->items[i].string, &buf, NULL, 0);
+               strbuf_addch(&buf, '\n');
+
+               if ((ret = strbuf_set_helper_option(data, &buf)))
+                       break;
+               strbuf_reset(&buf);
+       }
+       strbuf_release(&buf);
+       return ret;
+}
+
 static int set_helper_option(struct transport *transport,
                          const char *name, const char *value)
 {
@@ -272,6 +315,10 @@ static int set_helper_option(struct transport *transport,
        if (!data->option)
                return 1;
 
+       if (!strcmp(name, "deepen-not"))
+               return string_list_set_helper_option(data, name,
+                                                    (struct string_list *)value);
+
        for (i = 0; i < ARRAY_SIZE(unsupported_options); i++) {
                if (!strcmp(name, unsupported_options[i]))
                        return 1;
@@ -291,20 +338,7 @@ static int set_helper_option(struct transport *transport,
                quote_c_style(value, &buf, NULL, 0);
        strbuf_addch(&buf, '\n');
 
-       sendline(data, &buf);
-       if (recvline(data, &buf))
-               exit(128);
-
-       if (!strcmp(buf.buf, "ok"))
-               ret = 0;
-       else if (starts_with(buf.buf, "error")) {
-               ret = -1;
-       } else if (!strcmp(buf.buf, "unsupported"))
-               ret = 1;
-       else {
-               warning("%s unexpectedly said: '%s'", data->name, buf.buf);
-               ret = 1;
-       }
+       ret = strbuf_set_helper_option(data, &buf);
        strbuf_release(&buf);
        return ret;
 }
@@ -312,14 +346,11 @@ static int set_helper_option(struct transport *transport,
 static void standard_options(struct transport *t)
 {
        char buf[16];
-       int n;
        int v = t->verbose;
 
        set_helper_option(t, "progress", t->progress ? "true" : "false");
 
-       n = snprintf(buf, sizeof(buf), "%d", v + 1);
-       if (n >= sizeof(buf))
-               die("impossibly large verbosity value");
+       xsnprintf(buf, sizeof(buf), "%d", v + 1);
        set_helper_option(t, "verbosity", buf);
 
        switch (t->family) {
@@ -679,43 +710,35 @@ static int push_update_ref_status(struct strbuf *buf,
 
                if (!strcmp(msg, "no match")) {
                        status = REF_STATUS_NONE;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "up to date")) {
                        status = REF_STATUS_UPTODATE;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "non-fast forward")) {
                        status = REF_STATUS_REJECT_NONFASTFORWARD;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "already exists")) {
                        status = REF_STATUS_REJECT_ALREADY_EXISTS;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "fetch first")) {
                        status = REF_STATUS_REJECT_FETCH_FIRST;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "needs force")) {
                        status = REF_STATUS_REJECT_NEEDS_FORCE;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "stale info")) {
                        status = REF_STATUS_REJECT_STALE;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
                else if (!strcmp(msg, "forced update")) {
                        forced = 1;
-                       free(msg);
-                       msg = NULL;
+                       FREE_AND_NULL(msg);
                }
        }
 
@@ -792,6 +815,13 @@ static void set_common_push_options(struct transport *transport,
                if (set_helper_option(transport, TRANS_OPT_PUSH_CERT, "if-asked") != 0)
                        die("helper %s does not support --signed=if-asked", name);
        }
+
+       if (flags & TRANSPORT_PUSH_OPTIONS) {
+               struct string_list_item *item;
+               for_each_string_list_item(item, transport->push_options)
+                       if (set_helper_option(transport, "push-option", item->string) != 0)
+                               die("helper %s does not support 'push-option'", name);
+       }
 }
 
 static int push_refs_with_push(struct transport *transport,
@@ -897,7 +927,7 @@ static int push_refs_with_export(struct transport *transport,
                struct object_id oid;
 
                private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
-               if (private && !get_sha1(private, oid.hash)) {
+               if (private && !get_oid(private, &oid)) {
                        strbuf_addf(&buf, "^%s", private);
                        string_list_append(&revlist_args, strbuf_detach(&buf, NULL));
                        oidcpy(&ref->old_oid, &oid);