test: do not LoadModule log_config_module unconditionally
[gitweb.git] / http-push.c
index 5b230380ccd33d8b04f8dfce24050237ae9206ad..30d2d340418f7f40b77823b1b58b307985347bdf 100644 (file)
@@ -9,11 +9,13 @@
 #include "revision.h"
 #include "exec_cmd.h"
 #include "remote.h"
+#include "list-objects.h"
+#include "sigchain.h"
 
 #include <expat.h>
 
 static const char http_push_usage[] =
-"git-http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n";
+"git http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n";
 
 #ifndef XML_STATUS_OK
 enum XML_Status {
@@ -86,6 +88,7 @@ static struct object_list *objects;
 struct repo
 {
        char *url;
+       char *path;
        int path_len;
        int has_info_refs;
        int can_update_info_refs;
@@ -125,7 +128,7 @@ struct transfer_request
        char errorstr[CURL_ERROR_SIZE];
        long http_code;
        unsigned char real_sha1[20];
-       SHA_CTX c;
+       git_SHA_CTX c;
        z_stream stream;
        int zret;
        int rename;
@@ -150,6 +153,7 @@ struct remote_lock
        char *url;
        char *owner;
        char *token;
+       char tmpfile_suffix[41];
        time_t start_time;
        long timeout;
        int refreshing;
@@ -175,6 +179,47 @@ struct remote_ls_ctx
        struct remote_ls_ctx *parent;
 };
 
+/* get_dav_token_headers options */
+enum dav_header_flag {
+       DAV_HEADER_IF = (1u << 0),
+       DAV_HEADER_LOCK = (1u << 1),
+       DAV_HEADER_TIMEOUT = (1u << 2)
+};
+
+static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options)
+{
+       struct strbuf buf = STRBUF_INIT;
+       struct curl_slist *dav_headers = NULL;
+
+       if (options & DAV_HEADER_IF) {
+               strbuf_addf(&buf, "If: (<%s>)", lock->token);
+               dav_headers = curl_slist_append(dav_headers, buf.buf);
+               strbuf_reset(&buf);
+       }
+       if (options & DAV_HEADER_LOCK) {
+               strbuf_addf(&buf, "Lock-Token: <%s>", lock->token);
+               dav_headers = curl_slist_append(dav_headers, buf.buf);
+               strbuf_reset(&buf);
+       }
+       if (options & DAV_HEADER_TIMEOUT) {
+               strbuf_addf(&buf, "Timeout: Second-%ld", lock->timeout);
+               dav_headers = curl_slist_append(dav_headers, buf.buf);
+               strbuf_reset(&buf);
+       }
+       strbuf_release(&buf);
+
+       return dav_headers;
+}
+
+static void append_remote_object_url(struct strbuf *buf, const char *url,
+                                    const char *hex,
+                                    int only_two_digit_prefix)
+{
+       strbuf_addf(buf, "%sobjects/%.*s/", url, 2, hex);
+       if (!only_two_digit_prefix)
+               strbuf_addf(buf, "%s", hex+2);
+}
+
 static void finish_request(struct transfer_request *request);
 static void release_request(struct transfer_request *request);
 
@@ -187,6 +232,15 @@ static void process_response(void *callback_data)
 }
 
 #ifdef USE_CURL_MULTI
+
+static char *get_remote_object_url(const char *url, const char *hex,
+                                  int only_two_digit_prefix)
+{
+       struct strbuf buf = STRBUF_INIT;
+       append_remote_object_url(&buf, url, hex, only_two_digit_prefix);
+       return strbuf_detach(&buf, NULL);
+}
+
 static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
                               void *data)
 {
@@ -207,8 +261,8 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
        do {
                request->stream.next_out = expn;
                request->stream.avail_out = sizeof(expn);
-               request->zret = inflate(&request->stream, Z_SYNC_FLUSH);
-               SHA1_Update(&request->c, expn,
+               request->zret = git_inflate(&request->stream, Z_SYNC_FLUSH);
+               git_SHA1_Update(&request->c, expn,
                            sizeof(expn) - request->stream.avail_out);
        } while (request->stream.avail_in && request->zret == Z_OK);
        data_received++;
@@ -221,7 +275,6 @@ static void start_fetch_loose(struct transfer_request *request)
        char *filename;
        char prevfile[PATH_MAX];
        char *url;
-       char *posn;
        int prevlocal;
        unsigned char prev_buf[PREV_BUF_SIZE];
        ssize_t prev_read = 0;
@@ -267,21 +320,12 @@ static void start_fetch_loose(struct transfer_request *request)
 
        memset(&request->stream, 0, sizeof(request->stream));
 
-       inflateInit(&request->stream);
+       git_inflate_init(&request->stream);
 
-       SHA1_Init(&request->c);
+       git_SHA1_Init(&request->c);
 
-       url = xmalloc(strlen(remote->url) + 50);
-       request->url = xmalloc(strlen(remote->url) + 50);
-       strcpy(url, remote->url);
-       posn = url + strlen(remote->url);
-       strcpy(posn, "objects/");
-       posn += 8;
-       memcpy(posn, hex, 2);
-       posn += 2;
-       *(posn++) = '/';
-       strcpy(posn, hex + 2);
-       strcpy(request->url, url);
+       url = get_remote_object_url(remote->url, hex, 0);
+       request->url = xstrdup(url);
 
        /* If a previous temp file is present, process what was already
           fetched. */
@@ -308,8 +352,8 @@ static void start_fetch_loose(struct transfer_request *request)
           file; also rewind to the beginning of the local file. */
        if (prev_read == -1) {
                memset(&request->stream, 0, sizeof(request->stream));
-               inflateInit(&request->stream);
-               SHA1_Init(&request->c);
+               git_inflate_init(&request->stream);
+               git_SHA1_Init(&request->c);
                if (prev_posn>0) {
                        prev_posn = 0;
                        lseek(request->local_fileno, 0, SEEK_SET);
@@ -354,16 +398,8 @@ static void start_mkcol(struct transfer_request *request)
 {
        char *hex = sha1_to_hex(request->obj->sha1);
        struct active_request_slot *slot;
-       char *posn;
 
-       request->url = xmalloc(strlen(remote->url) + 13);
-       strcpy(request->url, remote->url);
-       posn = request->url + strlen(remote->url);
-       strcpy(posn, "objects/");
-       posn += 8;
-       memcpy(posn, hex, 2);
-       posn += 2;
-       strcpy(posn, "/");
+       request->url = get_remote_object_url(remote->url, hex, 1);
 
        slot = get_active_slot();
        slot->callback_func = process_response;
@@ -478,7 +514,7 @@ static void start_put(struct transfer_request *request)
 {
        char *hex = sha1_to_hex(request->obj->sha1);
        struct active_request_slot *slot;
-       char *posn;
+       struct strbuf buf = STRBUF_INIT;
        enum object_type type;
        char hdr[50];
        void *unpacked;
@@ -517,21 +553,13 @@ static void start_put(struct transfer_request *request)
 
        request->buffer.buf.len = stream.total_out;
 
-       request->url = xmalloc(strlen(remote->url) +
-                              strlen(request->lock->token) + 51);
-       strcpy(request->url, remote->url);
-       posn = request->url + strlen(remote->url);
-       strcpy(posn, "objects/");
-       posn += 8;
-       memcpy(posn, hex, 2);
-       posn += 2;
-       *(posn++) = '/';
-       strcpy(posn, hex + 2);
-       request->dest = xmalloc(strlen(request->url) + 14);
-       sprintf(request->dest, "Destination: %s", request->url);
-       posn += 38;
-       *(posn++) = '_';
-       strcpy(posn, request->lock->token);
+       strbuf_addstr(&buf, "Destination: ");
+       append_remote_object_url(&buf, remote->url, hex, 0);
+       request->dest = strbuf_detach(&buf, NULL);
+
+       append_remote_object_url(&buf, remote->url, hex, 0);
+       strbuf_add(&buf, request->lock->tmpfile_suffix, 41);
+       request->url = strbuf_detach(&buf, NULL);
 
        slot = get_active_slot();
        slot->callback_func = process_response;
@@ -586,18 +614,12 @@ static int refresh_lock(struct remote_lock *lock)
 {
        struct active_request_slot *slot;
        struct slot_results results;
-       char *if_header;
-       char timeout_header[25];
-       struct curl_slist *dav_headers = NULL;
+       struct curl_slist *dav_headers;
        int rc = 0;
 
        lock->refreshing = 1;
 
-       if_header = xmalloc(strlen(lock->token) + 25);
-       sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
-       sprintf(timeout_header, "Timeout: Second-%ld", lock->timeout);
-       dav_headers = curl_slist_append(dav_headers, if_header);
-       dav_headers = curl_slist_append(dav_headers, timeout_header);
+       dav_headers = get_dav_token_headers(lock, DAV_HEADER_IF | DAV_HEADER_TIMEOUT);
 
        slot = get_active_slot();
        slot->results = &results;
@@ -620,7 +642,6 @@ static int refresh_lock(struct remote_lock *lock)
 
        lock->refreshing = 0;
        curl_slist_free_all(dav_headers);
-       free(if_header);
 
        return rc;
 }
@@ -740,8 +761,8 @@ static void finish_request(struct transfer_request *request)
                        if (request->http_code == 416)
                                fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
 
-                       inflateEnd(&request->stream);
-                       SHA1_Final(request->real_sha1, &request->c);
+                       git_inflate_end(&request->stream);
+                       git_SHA1_Final(request->real_sha1, &request->c);
                        if (request->zret != Z_STREAM_END) {
                                unlink(request->tmpfile);
                        } else if (hashcmp(request->obj->sha1, request->real_sha1)) {
@@ -782,7 +803,7 @@ static void finish_request(struct transfer_request *request)
                                        lst = &((*lst)->next);
                                *lst = (*lst)->next;
 
-                               if (!verify_pack(target, 0))
+                               if (!verify_pack(target))
                                        install_packed_git(target);
                                else
                                        remote->can_update_info_refs = 0;
@@ -1109,6 +1130,8 @@ static void handle_lockprop_ctx(struct xml_ctx *ctx, int tag_closed)
 static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
 {
        struct remote_lock *lock = (struct remote_lock *)ctx->userData;
+       git_SHA_CTX sha_ctx;
+       unsigned char lock_token_sha1[20];
 
        if (tag_closed && ctx->cdata) {
                if (!strcmp(ctx->name, DAV_ACTIVELOCK_OWNER)) {
@@ -1119,10 +1142,15 @@ static void handle_new_lock_ctx(struct xml_ctx *ctx, int tag_closed)
                                lock->timeout =
                                        strtol(ctx->cdata + 7, NULL, 10);
                } else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
-                       if (!prefixcmp(ctx->cdata, "opaquelocktoken:")) {
-                               lock->token = xmalloc(strlen(ctx->cdata) - 15);
-                               strcpy(lock->token, ctx->cdata + 16);
-                       }
+                       lock->token = xmalloc(strlen(ctx->cdata) + 1);
+                       strcpy(lock->token, ctx->cdata);
+
+                       git_SHA1_Init(&sha_ctx);
+                       git_SHA1_Update(&sha_ctx, lock->token, strlen(lock->token));
+                       git_SHA1_Final(lock_token_sha1, &sha_ctx);
+
+                       lock->tmpfile_suffix[0] = '_';
+                       memcpy(lock->tmpfile_suffix + 1, sha1_to_hex(lock_token_sha1), 40);
                }
        }
 }
@@ -1201,7 +1229,8 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
        /* Make sure leading directories exist for the remote ref */
        ep = strchr(url + strlen(remote->url) + 1, '/');
        while (ep) {
-               *ep = 0;
+               char saved_character = ep[1];
+               ep[1] = '\0';
                slot = get_active_slot();
                slot->results = &results;
                curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
@@ -1223,7 +1252,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
                        free(url);
                        return NULL;
                }
-               *ep = '/';
+               ep[1] = saved_character;
                ep = strchr(ep + 1, '/');
        }
 
@@ -1302,14 +1331,10 @@ static int unlock_remote(struct remote_lock *lock)
        struct active_request_slot *slot;
        struct slot_results results;
        struct remote_lock *prev = remote->locks;
-       char *lock_token_header;
-       struct curl_slist *dav_headers = NULL;
+       struct curl_slist *dav_headers;
        int rc = 0;
 
-       lock_token_header = xmalloc(strlen(lock->token) + 31);
-       sprintf(lock_token_header, "Lock-Token: <opaquelocktoken:%s>",
-               lock->token);
-       dav_headers = curl_slist_append(dav_headers, lock_token_header);
+       dav_headers = get_dav_token_headers(lock, DAV_HEADER_LOCK);
 
        slot = get_active_slot();
        slot->results = &results;
@@ -1330,7 +1355,6 @@ static int unlock_remote(struct remote_lock *lock)
        }
 
        curl_slist_free_all(dav_headers);
-       free(lock_token_header);
 
        if (remote->locks == lock) {
                remote->locks = lock->next;
@@ -1349,6 +1373,24 @@ static int unlock_remote(struct remote_lock *lock)
        return rc;
 }
 
+static void remove_locks(void)
+{
+       struct remote_lock *lock = remote->locks;
+
+       fprintf(stderr, "Removing remote locks...\n");
+       while (lock) {
+               unlock_remote(lock);
+               lock = lock->next;
+       }
+}
+
+static void remove_locks_on_signal(int signo)
+{
+       remove_locks();
+       sigchain_pop(signo);
+       raise(signo);
+}
+
 static void remote_ls(const char *path, int flags,
                      void (*userFunc)(struct remote_ls_ctx *ls),
                      void *userData);
@@ -1407,9 +1449,17 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
                                ls->userFunc(ls);
                        }
                } else if (!strcmp(ctx->name, DAV_PROPFIND_NAME) && ctx->cdata) {
-                       ls->dentry_name = xmalloc(strlen(ctx->cdata) -
-                                                 remote->path_len + 1);
-                       strcpy(ls->dentry_name, ctx->cdata + remote->path_len);
+                       char *path = ctx->cdata;
+                       if (*ctx->cdata == 'h') {
+                               path = strstr(path, "//");
+                               if (path) {
+                                       path = strchr(path+2, '/');
+                               }
+                       }
+                       if (path) {
+                               path += remote->path_len;
+                               ls->dentry_name = xstrdup(path);
+                       }
                } else if (!strcmp(ctx->name, DAV_PROPFIND_COLLECTION)) {
                        ls->dentry_flags |= IS_DIR;
                }
@@ -1420,6 +1470,12 @@ static void handle_remote_ls_ctx(struct xml_ctx *ctx, int tag_closed)
        }
 }
 
+/*
+ * NEEDSWORK: remote_ls() ignores info/refs on the remote side.  But it
+ * should _only_ heed the information from that file, instead of trying to
+ * determine the refs from the remote file system (badly: it does not even
+ * know about packed-refs).
+ */
 static void remote_ls(const char *path, int flags,
                      void (*userFunc)(struct remote_ls_ctx *ls),
                      void *userData)
@@ -1698,13 +1754,10 @@ static int update_remote(unsigned char *sha1, struct remote_lock *lock)
 {
        struct active_request_slot *slot;
        struct slot_results results;
-       char *if_header;
        struct buffer out_buffer = { STRBUF_INIT, 0 };
-       struct curl_slist *dav_headers = NULL;
+       struct curl_slist *dav_headers;
 
-       if_header = xmalloc(strlen(lock->token) + 25);
-       sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
-       dav_headers = curl_slist_append(dav_headers, if_header);
+       dav_headers = get_dav_token_headers(lock, DAV_HEADER_IF);
 
        strbuf_addf(&out_buffer.buf, "%s\n", sha1_to_hex(sha1));
 
@@ -1723,7 +1776,6 @@ static int update_remote(unsigned char *sha1, struct remote_lock *lock)
        if (start_active_slot(slot)) {
                run_active_slot(slot);
                strbuf_release(&out_buffer.buf);
-               free(if_header);
                if (results.curl_result != CURLE_OK) {
                        fprintf(stderr,
                                "PUT error: curl result=%d, HTTP code=%ld\n",
@@ -1733,7 +1785,6 @@ static int update_remote(unsigned char *sha1, struct remote_lock *lock)
                }
        } else {
                strbuf_release(&out_buffer.buf);
-               free(if_header);
                fprintf(stderr, "Unable to start PUT request\n");
                return 0;
        }
@@ -1759,15 +1810,15 @@ static int one_local_ref(const char *refname, const unsigned char *sha1, int fla
 static void one_remote_ref(char *refname)
 {
        struct ref *ref;
-       unsigned char remote_sha1[20];
        struct object *obj;
-       int len = strlen(refname) + 1;
 
-       if (http_fetch_ref(remote->url, refname + 5 /* "refs/" */,
-                          remote_sha1) != 0) {
+       ref = alloc_ref(refname);
+
+       if (http_fetch_ref(remote->url, ref) != 0) {
                fprintf(stderr,
                        "Unable to fetch ref %s from %s\n",
                        refname, remote->url);
+               free(ref);
                return;
        }
 
@@ -1775,18 +1826,15 @@ static void one_remote_ref(char *refname)
         * Fetch a copy of the object if it doesn't exist locally - it
         * may be required for updating server info later.
         */
-       if (remote->can_update_info_refs && !has_sha1_file(remote_sha1)) {
-               obj = lookup_unknown_object(remote_sha1);
+       if (remote->can_update_info_refs && !has_sha1_file(ref->old_sha1)) {
+               obj = lookup_unknown_object(ref->old_sha1);
                if (obj) {
                        fprintf(stderr, "  fetch %s for %s\n",
-                               sha1_to_hex(remote_sha1), refname);
+                               sha1_to_hex(ref->old_sha1), refname);
                        add_fetch_request(obj);
                }
        }
 
-       ref = xcalloc(1, sizeof(*ref) + len);
-       hashcpy(ref->old_sha1, remote_sha1);
-       memcpy(ref->name, refname, len);
        *remote_tail = ref;
        remote_tail = &ref->next;
 }
@@ -1863,61 +1911,39 @@ static int ref_newer(const unsigned char *new_sha1,
        return found;
 }
 
-static void mark_edge_parents_uninteresting(struct commit *commit)
-{
-       struct commit_list *parents;
-
-       for (parents = commit->parents; parents; parents = parents->next) {
-               struct commit *parent = parents->item;
-               if (!(parent->object.flags & UNINTERESTING))
-                       continue;
-               mark_tree_uninteresting(parent->tree);
-       }
-}
-
-static void mark_edges_uninteresting(struct commit_list *list)
-{
-       for ( ; list; list = list->next) {
-               struct commit *commit = list->item;
-
-               if (commit->object.flags & UNINTERESTING) {
-                       mark_tree_uninteresting(commit->tree);
-                       continue;
-               }
-               mark_edge_parents_uninteresting(commit);
-       }
-}
-
 static void add_remote_info_ref(struct remote_ls_ctx *ls)
 {
        struct strbuf *buf = (struct strbuf *)ls->userData;
-       unsigned char remote_sha1[20];
        struct object *o;
        int len;
        char *ref_info;
+       struct ref *ref;
 
-       if (http_fetch_ref(remote->url, ls->dentry_name + 5 /* "refs/" */,
-                          remote_sha1) != 0) {
+       ref = alloc_ref(ls->dentry_name);
+
+       if (http_fetch_ref(remote->url, ref) != 0) {
                fprintf(stderr,
                        "Unable to fetch ref %s from %s\n",
                        ls->dentry_name, remote->url);
                aborted = 1;
+               free(ref);
                return;
        }
 
-       o = parse_object(remote_sha1);
+       o = parse_object(ref->old_sha1);
        if (!o) {
                fprintf(stderr,
                        "Unable to parse object %s for remote ref %s\n",
-                       sha1_to_hex(remote_sha1), ls->dentry_name);
+                       sha1_to_hex(ref->old_sha1), ls->dentry_name);
                aborted = 1;
+               free(ref);
                return;
        }
 
        len = strlen(ls->dentry_name) + 42;
        ref_info = xcalloc(len + 1, 1);
        sprintf(ref_info, "%s   %s\n",
-               sha1_to_hex(remote_sha1), ls->dentry_name);
+               sha1_to_hex(ref->old_sha1), ls->dentry_name);
        fwrite_buffer(ref_info, 1, len, buf);
        free(ref_info);
 
@@ -1932,6 +1958,7 @@ static void add_remote_info_ref(struct remote_ls_ctx *ls)
                        free(ref_info);
                }
        }
+       free(ref);
 }
 
 static void update_remote_info_refs(struct remote_lock *lock)
@@ -1939,15 +1966,12 @@ static void update_remote_info_refs(struct remote_lock *lock)
        struct buffer buffer = { STRBUF_INIT, 0 };
        struct active_request_slot *slot;
        struct slot_results results;
-       char *if_header;
-       struct curl_slist *dav_headers = NULL;
+       struct curl_slist *dav_headers;
 
        remote_ls("refs/", (PROCESS_FILES | RECURSIVE),
                  add_remote_info_ref, &buffer.buf);
        if (!aborted) {
-               if_header = xmalloc(strlen(lock->token) + 25);
-               sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
-               dav_headers = curl_slist_append(dav_headers, if_header);
+               dav_headers = get_dav_token_headers(lock, DAV_HEADER_IF);
 
                slot = get_active_slot();
                slot->results = &results;
@@ -1969,7 +1993,6 @@ static void update_remote_info_refs(struct remote_lock *lock)
                                        results.curl_result, results.http_code);
                        }
                }
-               free(if_header);
        }
        strbuf_release(&buffer.buf);
 }
@@ -2175,6 +2198,8 @@ int main(int argc, char **argv)
        struct ref *ref;
        char *rewritten_url = NULL;
 
+       git_extract_argv0_path(argv[0]);
+
        setup_git_directory();
 
        remote = xcalloc(sizeof(*remote), 1);
@@ -2213,10 +2238,11 @@ int main(int argc, char **argv)
                if (!remote->url) {
                        char *path = strstr(arg, "//");
                        remote->url = arg;
+                       remote->path_len = strlen(arg);
                        if (path) {
-                               path = strchr(path+2, '/');
-                               if (path)
-                                       remote->path_len = strlen(path);
+                               remote->path = strchr(path+2, '/');
+                               if (remote->path)
+                                       remote->path_len = strlen(remote->path);
                        }
                        continue;
                }
@@ -2242,11 +2268,12 @@ int main(int argc, char **argv)
        no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
 
        if (remote->url && remote->url[strlen(remote->url)-1] != '/') {
-               rewritten_url = malloc(strlen(remote->url)+2);
+               rewritten_url = xmalloc(strlen(remote->url)+2);
                strcpy(rewritten_url, remote->url);
                strcat(rewritten_url, "/");
+               remote->path = rewritten_url + (remote->path - remote->url);
+               remote->path_len++;
                remote->url = rewritten_url;
-               ++remote->path_len;
        }
 
        /* Verify DAV compliance/lock support */
@@ -2255,6 +2282,8 @@ int main(int argc, char **argv)
                goto cleanup;
        }
 
+       sigchain_push_common(remove_locks_on_signal);
+
        /* Check whether the remote has server info files */
        remote->can_update_info_refs = 0;
        remote->has_info_refs = remote_exists("info/refs");
@@ -2384,6 +2413,7 @@ int main(int argc, char **argv)
                }
                init_revisions(&revs, setup_git_directory());
                setup_revisions(commit_argc, commit_argv, &revs, NULL);
+               revs.edge_hint = 0; /* just in case */
                free(new_sha1_hex);
                if (old_sha1_hex) {
                        free(old_sha1_hex);
@@ -2394,7 +2424,7 @@ int main(int argc, char **argv)
                pushing = 0;
                if (prepare_revision_walk(&revs))
                        die("revision walk setup failed");
-               mark_edges_uninteresting(revs.commits);
+               mark_edges_uninteresting(revs.commits, &revs, NULL);
                objects_to_send = get_delta(&revs, ref_lock);
                finish_all_active_slots();