Remove a CURLOPT_HTTPHEADER (un)setting
[gitweb.git] / http-push.c
index 724720c562ab6da2b02e91b69f5365bc7bfee4f4..176bb29fab011500e882d6fd6a3ed467b853bb18 100644 (file)
@@ -1,7 +1,6 @@
 #include "cache.h"
 #include "commit.h"
 #include "pack.h"
-#include "fetch.h"
 #include "tag.h"
 #include "blob.h"
 #include "http.h"
@@ -9,11 +8,12 @@
 #include "diff.h"
 #include "revision.h"
 #include "exec_cmd.h"
+#include "remote.h"
 
 #include <expat.h>
 
 static const char http_push_usage[] =
-"git-http-push [--all] [--force] [--verbose] <remote> [<head>...]\n";
+"git-http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n";
 
 #ifndef XML_STATUS_OK
 enum XML_Status {
@@ -75,11 +75,11 @@ static int aborted;
 static signed char remote_dir_exists[256];
 
 static struct curl_slist *no_pragma_header;
-static struct curl_slist *default_headers;
 
 static int push_verbosely;
-static int push_all;
+static int push_all = MATCH_REFS_NONE;
 static int force_all;
+static int dry_run;
 
 static struct object_list *objects;
 
@@ -312,7 +312,7 @@ static void start_fetch_loose(struct transfer_request *request)
                SHA1_Init(&request->c);
                if (prev_posn>0) {
                        prev_posn = 0;
-                       lseek(request->local_fileno, SEEK_SET, 0);
+                       lseek(request->local_fileno, 0, SEEK_SET);
                        ftruncate(request->local_fileno, 0);
                }
        }
@@ -432,7 +432,7 @@ static void start_fetch_packed(struct transfer_request *request)
        packfile = fopen(request->tmpfile, "a");
        if (!packfile) {
                fprintf(stderr, "Unable to open local file %s for pack",
-                       filename);
+                       request->tmpfile);
                remote->can_update_info_refs = 0;
                free(url);
                return;
@@ -517,7 +517,7 @@ static void start_put(struct transfer_request *request)
        request->buffer.size = stream.total_out;
        request->buffer.posn = 0;
 
-       request->url = xmalloc(strlen(remote->url) + 
+       request->url = xmalloc(strlen(remote->url) +
                               strlen(request->lock->token) + 51);
        strcpy(request->url, remote->url);
        posn = request->url + strlen(remote->url);
@@ -794,38 +794,27 @@ static void finish_request(struct transfer_request *request)
 }
 
 #ifdef USE_CURL_MULTI
-void fill_active_slots(void)
+static int fill_active_slot(void *unused)
 {
        struct transfer_request *request = request_queue_head;
-       struct transfer_request *next;
-       struct active_request_slot *slot = active_queue_head;
-       int num_transfers;
 
        if (aborted)
-               return;
+               return 0;
 
-       while (active_requests < max_requests && request != NULL) {
-               next = request->next;
+       for (request = request_queue_head; request; request = request->next) {
                if (request->state == NEED_FETCH) {
                        start_fetch_loose(request);
+                       return 1;
                } else if (pushing && request->state == NEED_PUSH) {
                        if (remote_dir_exists[request->obj->sha1[0]] == 1) {
                                start_put(request);
                        } else {
                                start_mkcol(request);
                        }
-                       curl_multi_perform(curlm, &num_transfers);
-               }
-               request = next;
-       }
-
-       while (slot != NULL) {
-               if (!slot->in_use && slot->curl != NULL) {
-                       curl_easy_cleanup(slot->curl);
-                       slot->curl = NULL;
+                       return 1;
                }
-               slot = slot->next;
        }
+       return 0;
 }
 #endif
 
@@ -935,11 +924,14 @@ static int fetch_index(unsigned char *sha1)
                                     hex);
                }
        } else {
+               free(url);
                return error("Unable to start request");
        }
 
-       if (has_pack_index(sha1))
+       if (has_pack_index(sha1)) {
+               free(url);
                return 0;
+       }
 
        if (push_verbosely)
                fprintf(stderr, "Getting index for pack %s\n", hex);
@@ -949,9 +941,11 @@ static int fetch_index(unsigned char *sha1)
        filename = sha1_pack_index_name(sha1);
        snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
        indexfile = fopen(tmpfile, "a");
-       if (!indexfile)
+       if (!indexfile) {
+               free(url);
                return error("Unable to open local file %s for pack index",
-                            filename);
+                            tmpfile);
+       }
 
        slot = get_active_slot();
        slot->results = &results;
@@ -1145,16 +1139,19 @@ int fetch_ref(char *ref, unsigned char *sha1)
        curl_easy_setopt(slot->curl, CURLOPT_URL, url);
        if (start_active_slot(slot)) {
                run_active_slot(slot);
+               free(url);
                if (results.curl_result != CURLE_OK)
                        return error("Couldn't get %s for %s\n%s",
                                     url, ref, curl_errorstr);
        } else {
+               free(url);
                return error("Unable to start request");
        }
 
+       if (buffer.posn != 41)
+               return 1;
         hex[40] = '\0';
-        get_sha1_hex(hex, sha1);
-        return 0;
+       return get_sha1_hex(hex, sha1);
 }
 
 static void one_remote_object(const char *hex)
@@ -1270,10 +1267,7 @@ xml_cdata(void *userData, const XML_Char *s, int len)
 {
        struct xml_ctx *ctx = (struct xml_ctx *)userData;
        free(ctx->cdata);
-       ctx->cdata = xmalloc(len + 1);
-       /* NB: 's' is not null-terminated, can not use strlcpy here */
-       memcpy(ctx->cdata, s, len);
-       ctx->cdata[len] = '\0';
+       ctx->cdata = xmemdupz(s, len);
 }
 
 static struct remote_lock *lock_remote(const char *path, long timeout)
@@ -1288,8 +1282,6 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
        char *ep;
        char timeout_header[25];
        struct remote_lock *lock = NULL;
-       XML_Parser parser = XML_ParserCreate(NULL);
-       enum XML_Status result;
        struct curl_slist *dav_headers = NULL;
        struct xml_ctx ctx;
 
@@ -1358,6 +1350,8 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
        if (start_active_slot(slot)) {
                run_active_slot(slot);
                if (results.curl_result == CURLE_OK) {
+                       XML_Parser parser = XML_ParserCreate(NULL);
+                       enum XML_Status result;
                        ctx.name = xcalloc(10, 1);
                        ctx.len = 0;
                        ctx.cdata = NULL;
@@ -1376,6 +1370,7 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
                                                XML_GetErrorCode(parser)));
                                lock->timeout = -1;
                        }
+                       XML_ParserFree(parser);
                }
        } else {
                fprintf(stderr, "Unable to start LOCK request\n");
@@ -1538,8 +1533,6 @@ static void remote_ls(const char *path, int flags,
        struct buffer out_buffer;
        char *in_data;
        char *out_data;
-       XML_Parser parser = XML_ParserCreate(NULL);
-       enum XML_Status result;
        struct curl_slist *dav_headers = NULL;
        struct xml_ctx ctx;
        struct remote_ls_ctx ls;
@@ -1582,6 +1575,8 @@ static void remote_ls(const char *path, int flags,
        if (start_active_slot(slot)) {
                run_active_slot(slot);
                if (results.curl_result == CURLE_OK) {
+                       XML_Parser parser = XML_ParserCreate(NULL);
+                       enum XML_Status result;
                        ctx.name = xcalloc(10, 1);
                        ctx.len = 0;
                        ctx.cdata = NULL;
@@ -1600,6 +1595,7 @@ static void remote_ls(const char *path, int flags,
                                        XML_ErrorString(
                                                XML_GetErrorCode(parser)));
                        }
+                       XML_ParserFree(parser);
                }
        } else {
                fprintf(stderr, "Unable to start PROPFIND request\n");
@@ -1633,8 +1629,6 @@ static int locking_available(void)
        struct buffer out_buffer;
        char *in_data;
        char *out_data;
-       XML_Parser parser = XML_ParserCreate(NULL);
-       enum XML_Status result;
        struct curl_slist *dav_headers = NULL;
        struct xml_ctx ctx;
        int lock_flags = 0;
@@ -1671,6 +1665,8 @@ static int locking_available(void)
        if (start_active_slot(slot)) {
                run_active_slot(slot);
                if (results.curl_result == CURLE_OK) {
+                       XML_Parser parser = XML_ParserCreate(NULL);
+                       enum XML_Status result;
                        ctx.name = xcalloc(10, 1);
                        ctx.len = 0;
                        ctx.cdata = NULL;
@@ -1689,6 +1685,7 @@ static int locking_available(void)
                                                XML_GetErrorCode(parser)));
                                lock_flags = 0;
                        }
+                       XML_ParserFree(parser);
                }
        } else {
                fprintf(stderr, "Unable to start PROPFIND request\n");
@@ -2117,6 +2114,7 @@ static int remote_exists(const char *path)
 
         if (start_active_slot(slot)) {
                run_active_slot(slot);
+               free(url);
                if (results.http_code == 404)
                        return 0;
                else if (results.curl_result == CURLE_OK)
@@ -2124,6 +2122,7 @@ static int remote_exists(const char *path)
                else
                        fprintf(stderr, "HEAD HTTP error %ld\n", results.http_code);
        } else {
+               free(url);
                fprintf(stderr, "Unable to start HEAD request\n");
        }
 
@@ -2171,9 +2170,7 @@ static void fetch_symref(const char *path, char **symref, unsigned char *sha1)
 
        /* If it's a symref, set the refname; otherwise try for a sha1 */
        if (!prefixcmp((char *)buffer.buffer, "ref: ")) {
-               *symref = xmalloc(buffer.posn - 5);
-               memcpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 6);
-               (*symref)[buffer.posn - 6] = '\0';
+               *symref = xmemdupz((char *)buffer.buffer + 5, buffer.posn - 6);
        } else {
                get_sha1_hex(buffer.buffer, sha1);
        }
@@ -2256,7 +2253,11 @@ static int delete_remote_branch(char *pattern, int force)
 
                /* Remote branch must be an ancestor of remote HEAD */
                if (!verify_merge_base(head_sha1, remote_ref->old_sha1)) {
-                       return error("The branch '%s' is not a strict subset of your current HEAD.\nIf you are sure you want to delete it, run:\n\t'git http-push -D %s %s'", remote_ref->name, remote->url, pattern);
+                       return error("The branch '%s' is not an ancestor "
+                                    "of your current HEAD.\n"
+                                    "If you are sure you want to delete it,"
+                                    " run:\n\t'git http-push -D %s %s'",
+                                    remote_ref->name, remote->url, pattern);
                }
        }
 
@@ -2311,13 +2312,17 @@ int main(int argc, char **argv)
 
                if (*arg == '-') {
                        if (!strcmp(arg, "--all")) {
-                               push_all = 1;
+                               push_all = MATCH_REFS_ALL;
                                continue;
                        }
                        if (!strcmp(arg, "--force")) {
                                force_all = 1;
                                continue;
                        }
+                       if (!strcmp(arg, "--dry-run")) {
+                               dry_run = 1;
+                               continue;
+                       }
                        if (!strcmp(arg, "--verbose")) {
                                push_verbosely = 1;
                                continue;
@@ -2358,11 +2363,6 @@ int main(int argc, char **argv)
        http_init();
 
        no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
-       default_headers = curl_slist_append(default_headers, "Range:");
-       default_headers = curl_slist_append(default_headers, "Destination:");
-       default_headers = curl_slist_append(default_headers, "If:");
-       default_headers = curl_slist_append(default_headers,
-                                           "Pragma: no-cache");
 
        /* Verify DAV compliance/lock support */
        if (!locking_available()) {
@@ -2400,7 +2400,7 @@ int main(int argc, char **argv)
        if (!remote_tail)
                remote_tail = &remote_refs;
        if (match_refs(local_refs, remote_refs, &remote_tail,
-                      nr_refspec, refspec, push_all))
+                      nr_refspec, (const char **) refspec, push_all))
                return -1;
        if (!remote_refs) {
                fprintf(stderr, "No refs in common and none specified; doing nothing.\n");
@@ -2428,16 +2428,17 @@ int main(int argc, char **argv)
                        if (!has_sha1_file(ref->old_sha1) ||
                            !ref_newer(ref->peer_ref->new_sha1,
                                       ref->old_sha1)) {
-                               /* We do not have the remote ref, or
+                               /*
+                                * We do not have the remote ref, or
                                 * we know that the remote ref is not
                                 * an ancestor of what we are trying to
                                 * push.  Either way this can be losing
                                 * commits at the remote end and likely
                                 * we were not up to date to begin with.
                                 */
-                               error("remote '%s' is not a strict "
-                                     "subset of local ref '%s'. "
-                                     "maybe you are not up-to-date and "
+                               error("remote '%s' is not an ancestor of\n"
+                                     "local '%s'.\n"
+                                     "Maybe you are not up-to-date and "
                                      "need to pull first?",
                                      ref->name,
                                      ref->peer_ref->name);
@@ -2459,7 +2460,8 @@ int main(int argc, char **argv)
                if (strcmp(ref->name, ref->peer_ref->name))
                        fprintf(stderr, " using '%s'", ref->peer_ref->name);
                fprintf(stderr, "\n  from %s\n  to   %s\n", old_hex, new_hex);
-
+               if (dry_run)
+                       continue;
 
                /* Lock remote branch ref */
                ref_lock = lock_remote(ref->name, LOCK_TIME);
@@ -2506,6 +2508,7 @@ int main(int argc, char **argv)
                                objects_to_send);
 #ifdef USE_CURL_MULTI
                fill_active_slots();
+               add_fill_function(NULL, fill_active_slot);
 #endif
                finish_all_active_slots();
 
@@ -2526,7 +2529,8 @@ int main(int argc, char **argv)
        if (remote->has_info_refs && new_refs) {
                if (info_ref_lock && remote->can_update_info_refs) {
                        fprintf(stderr, "Updating remote server info\n");
-                       update_remote_info_refs(info_ref_lock);
+                       if (!dry_run)
+                               update_remote_info_refs(info_ref_lock);
                } else {
                        fprintf(stderr, "Unable to update server info\n");
                }
@@ -2538,7 +2542,6 @@ int main(int argc, char **argv)
        free(remote);
 
        curl_slist_free_all(no_pragma_header);
-       curl_slist_free_all(default_headers);
 
        http_cleanup();