string-list: use QSORT_S in string_list_sort()
[gitweb.git] / upload-pack.c
index d9e381f29126313aa7068478430dd5e3f704f9ef..7597ba3405e161d59608e18ec580946c60f9e6d2 100644 (file)
@@ -46,6 +46,8 @@ static int no_progress, daemon_mode;
 #define ALLOW_TIP_SHA1 01
 /* Allow request of a sha1 if it is reachable from a ref (possibly hidden ref). */
 #define ALLOW_REACHABLE_SHA1   02
+/* Allow request of any sha1. Implies ALLOW_TIP_SHA1 and ALLOW_REACHABLE_SHA1. */
+#define ALLOW_ANY_SHA1 07
 static unsigned int allow_unadvertised_object_request;
 static int shallow_nr;
 static struct object_array have_obj;
@@ -398,13 +400,13 @@ static int get_common_commits(void)
                        if (multi_ack == 2 && got_common
                            && !got_other && ok_to_give_up()) {
                                sent_ready = 1;
-                               packet_write(1, "ACK %s ready\n", last_hex);
+                               packet_write_fmt(1, "ACK %s ready\n", last_hex);
                        }
                        if (have_obj.nr == 0 || multi_ack)
-                               packet_write(1, "NAK\n");
+                               packet_write_fmt(1, "NAK\n");
 
                        if (no_done && sent_ready) {
-                               packet_write(1, "ACK %s\n", last_hex);
+                               packet_write_fmt(1, "ACK %s\n", last_hex);
                                return 0;
                        }
                        if (stateless_rpc)
@@ -421,20 +423,20 @@ static int get_common_commits(void)
                                        const char *hex = sha1_to_hex(sha1);
                                        if (multi_ack == 2) {
                                                sent_ready = 1;
-                                               packet_write(1, "ACK %s ready\n", hex);
+                                               packet_write_fmt(1, "ACK %s ready\n", hex);
                                        } else
-                                               packet_write(1, "ACK %s continue\n", hex);
+                                               packet_write_fmt(1, "ACK %s continue\n", hex);
                                }
                                break;
                        default:
                                got_common = 1;
                                memcpy(last_hex, sha1_to_hex(sha1), 41);
                                if (multi_ack == 2)
-                                       packet_write(1, "ACK %s common\n", last_hex);
+                                       packet_write_fmt(1, "ACK %s common\n", last_hex);
                                else if (multi_ack)
-                                       packet_write(1, "ACK %s continue\n", last_hex);
+                                       packet_write_fmt(1, "ACK %s continue\n", last_hex);
                                else if (have_obj.nr == 1)
-                                       packet_write(1, "ACK %s\n", last_hex);
+                                       packet_write_fmt(1, "ACK %s\n", last_hex);
                                break;
                        }
                        continue;
@@ -442,10 +444,10 @@ static int get_common_commits(void)
                if (!strcmp(line, "done")) {
                        if (have_obj.nr > 0) {
                                if (multi_ack)
-                                       packet_write(1, "ACK %s\n", last_hex);
+                                       packet_write_fmt(1, "ACK %s\n", last_hex);
                                return 0;
                        }
-                       packet_write(1, "NAK\n");
+                       packet_write_fmt(1, "NAK\n");
                        return -1;
                }
                die("git upload-pack: expected SHA1 list, got '%s'", line);
@@ -638,8 +640,8 @@ static void send_shallow(struct commit_list *result)
        while (result) {
                struct object *object = &result->item->object;
                if (!(object->flags & (CLIENT_SHALLOW|NOT_SHALLOW))) {
-                       packet_write(1, "shallow %s",
-                                    oid_to_hex(&object->oid));
+                       packet_write_fmt(1, "shallow %s",
+                                        oid_to_hex(&object->oid));
                        register_shallow(object->oid.hash);
                        shallow_nr++;
                }
@@ -655,8 +657,8 @@ static void send_unshallow(const struct object_array *shallows)
                struct object *object = shallows->objects[i].item;
                if (object->flags & NOT_SHALLOW) {
                        struct commit_list *parents;
-                       packet_write(1, "unshallow %s",
-                                    oid_to_hex(&object->oid));
+                       packet_write_fmt(1, "unshallow %s",
+                                        oid_to_hex(&object->oid));
                        object->flags &= ~CLIENT_SHALLOW;
                        /*
                         * We want to _register_ "object" as shallow, but we
@@ -825,7 +827,8 @@ static void receive_needs(void)
                            sha1_to_hex(sha1_buf));
                if (!(o->flags & WANTED)) {
                        o->flags |= WANTED;
-                       if (!is_our_ref(o))
+                       if (!((allow_unadvertised_object_request & ALLOW_ANY_SHA1) == ALLOW_ANY_SHA1
+                             || is_our_ref(o)))
                                has_non_tip = 1;
                        add_object_array(o, NULL, &want_obj);
                }
@@ -932,7 +935,7 @@ static int send_ref(const char *refname, const struct object_id *oid,
                struct strbuf symref_info = STRBUF_INIT;
 
                format_symref_info(&symref_info, cb_data);
-               packet_write(1, "%s %s%c%s%s%s%s%s agent=%s\n",
+               packet_write_fmt(1, "%s %s%c%s%s%s%s%s agent=%s\n",
                             oid_to_hex(oid), refname_nons,
                             0, capabilities,
                             (allow_unadvertised_object_request & ALLOW_TIP_SHA1) ?
@@ -944,11 +947,11 @@ static int send_ref(const char *refname, const struct object_id *oid,
                             git_user_agent_sanitized());
                strbuf_release(&symref_info);
        } else {
-               packet_write(1, "%s %s\n", oid_to_hex(oid), refname_nons);
+               packet_write_fmt(1, "%s %s\n", oid_to_hex(oid), refname_nons);
        }
        capabilities = NULL;
        if (!peel_ref(refname, peeled.hash))
-               packet_write(1, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
+               packet_write_fmt(1, "%s %s^{}\n", oid_to_hex(&peeled), refname_nons);
        return 0;
 }
 
@@ -1008,6 +1011,11 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
                        allow_unadvertised_object_request |= ALLOW_REACHABLE_SHA1;
                else
                        allow_unadvertised_object_request &= ~ALLOW_REACHABLE_SHA1;
+       } else if (!strcmp("uploadpack.allowanysha1inwant", var)) {
+               if (git_config_bool(var, value))
+                       allow_unadvertised_object_request |= ALLOW_ANY_SHA1;
+               else
+                       allow_unadvertised_object_request &= ~ALLOW_ANY_SHA1;
        } else if (!strcmp("uploadpack.keepalive", var)) {
                keepalive = git_config_int(var, value);
                if (!keepalive)