Fix typos in translatable strings for v2.21.0
[gitweb.git] / remote-curl.c
index 595447b16eb8b175f481b1c8b6d0704d4fa3d650..bb7421023ba584d59592124aa6f3ff2028bc5356 100644 (file)
@@ -5,7 +5,7 @@
 #include "strbuf.h"
 #include "walker.h"
 #include "http.h"
-#include "exec_cmd.h"
+#include "exec-cmd.h"
 #include "run-command.h"
 #include "pkt-line.h"
 #include "string-list.h"
@@ -15,6 +15,7 @@
 #include "sha1-array.h"
 #include "send-pack.h"
 #include "protocol.h"
+#include "quote.h"
 
 static struct remote *remote;
 /* always ends with a trailing slash */
@@ -26,6 +27,7 @@ struct options {
        char *deepen_since;
        struct string_list deepen_not;
        struct string_list push_options;
+       char *filter;
        unsigned progress : 1,
                check_self_contained_and_connected : 1,
                cloning : 1,
@@ -35,7 +37,9 @@ struct options {
                thin : 1,
                /* One of the SEND_PACK_PUSH_CERT_* constants. */
                push_cert : 2,
-               deepen_relative : 1;
+               deepen_relative : 1,
+               from_promisor : 1,
+               no_dependents : 1;
 };
 static struct options options;
 static struct string_list cas_options = STRING_LIST_INIT_DUP;
@@ -144,7 +148,15 @@ static int set_option(const char *name, const char *value)
                        return -1;
                return 0;
        } else if (!strcmp(name, "push-option")) {
-               string_list_append(&options.push_options, value);
+               if (*value != '"')
+                       string_list_append(&options.push_options, value);
+               else {
+                       struct strbuf unquoted = STRBUF_INIT;
+                       if (unquote_c_style(&unquoted, value, NULL) < 0)
+                               die("invalid quoting in push-option value");
+                       string_list_append_nodup(&options.push_options,
+                                                strbuf_detach(&unquoted, NULL));
+               }
                return 0;
 
 #if LIBCURL_VERSION_NUM >= 0x070a08
@@ -159,6 +171,15 @@ static int set_option(const char *name, const char *value)
                        return -1;
                return 0;
 #endif /* LIBCURL_VERSION_NUM >= 0x070a08 */
+       } else if (!strcmp(name, "from-promisor")) {
+               options.from_promisor = 1;
+               return 0;
+       } else if (!strcmp(name, "no-dependents")) {
+               options.no_dependents = 1;
+               return 0;
+       } else if (!strcmp(name, "filter")) {
+               options.filter = xstrdup(value);
+               return 0;
        } else {
                return 1 /* unsupported */;
        }
@@ -183,7 +204,8 @@ static struct ref *parse_git_refs(struct discovery *heads, int for_push)
 
        packet_reader_init(&reader, -1, heads->buf, heads->len,
                           PACKET_READ_CHOMP_NEWLINE |
-                          PACKET_READ_GENTLE_ON_EOF);
+                          PACKET_READ_GENTLE_ON_EOF |
+                          PACKET_READ_DIE_ON_ERR_PACKET);
 
        heads->version = discover_version(&reader);
        switch (heads->version) {
@@ -309,9 +331,63 @@ static int get_protocol_http_header(enum protocol_version version,
        return 0;
 }
 
+static void check_smart_http(struct discovery *d, const char *service,
+                            struct strbuf *type)
+{
+       const char *p;
+       struct packet_reader reader;
+
+       /*
+        * If we don't see x-$service-advertisement, then it's not smart-http.
+        * But once we do, we commit to it and assume any other protocol
+        * violations are hard errors.
+        */
+       if (!skip_prefix(type->buf, "application/x-", &p) ||
+           !skip_prefix(p, service, &p) ||
+           strcmp(p, "-advertisement"))
+               return;
+
+       packet_reader_init(&reader, -1, d->buf, d->len,
+                          PACKET_READ_CHOMP_NEWLINE |
+                          PACKET_READ_DIE_ON_ERR_PACKET);
+       if (packet_reader_read(&reader) != PACKET_READ_NORMAL)
+               die("invalid server response; expected service, got flush packet");
+
+       if (skip_prefix(reader.line, "# service=", &p) && !strcmp(p, service)) {
+               /*
+                * The header can include additional metadata lines, up
+                * until a packet flush marker.  Ignore these now, but
+                * in the future we might start to scan them.
+                */
+               for (;;) {
+                       packet_reader_read(&reader);
+                       if (reader.pktlen <= 0) {
+                               break;
+                       }
+               }
+
+               /*
+                * v0 smart http; callers expect us to soak up the
+                * service and header packets
+                */
+               d->buf = reader.src_buffer;
+               d->len = reader.src_len;
+               d->proto_git = 1;
+
+       } else if (!strcmp(reader.line, "version 2")) {
+               /*
+                * v2 smart http; do not consume version packet, which will
+                * be handled elsewhere.
+                */
+               d->proto_git = 1;
+
+       } else {
+               die("invalid server response; got '%s'", reader.line);
+       }
+}
+
 static struct discovery *discover_refs(const char *service, int for_push)
 {
-       struct strbuf exp = STRBUF_INIT;
        struct strbuf type = STRBUF_INIT;
        struct strbuf charset = STRBUF_INIT;
        struct strbuf buffer = STRBUF_INIT;
@@ -359,7 +435,6 @@ static struct discovery *discover_refs(const char *service, int for_push)
        http_options.extra_headers = &extra_headers;
        http_options.initial_request = 1;
        http_options.no_cache = 1;
-       http_options.keep_error = 1;
 
        http_ret = http_get_strbuf(refs_url.buf, &buffer, &http_options);
        switch (http_ret) {
@@ -384,36 +459,8 @@ static struct discovery *discover_refs(const char *service, int for_push)
        last->buf_alloc = strbuf_detach(&buffer, &last->len);
        last->buf = last->buf_alloc;
 
-       strbuf_addf(&exp, "application/x-%s-advertisement", service);
-       if (maybe_smart &&
-           (5 <= last->len && last->buf[4] == '#') &&
-           !strbuf_cmp(&exp, &type)) {
-               char *line;
-
-               /*
-                * smart HTTP response; validate that the service
-                * pkt-line matches our request.
-                */
-               line = packet_read_line_buf(&last->buf, &last->len, NULL);
-
-               strbuf_reset(&exp);
-               strbuf_addf(&exp, "# service=%s", service);
-               if (strcmp(line, exp.buf))
-                       die("invalid server response; got '%s'", line);
-               strbuf_release(&exp);
-
-               /* The header can include additional metadata lines, up
-                * until a packet flush marker.  Ignore these now, but
-                * in the future we might start to scan them.
-                */
-               while (packet_read_line_buf(&last->buf, &last->len, NULL))
-                       ;
-
-               last->proto_git = 1;
-       } else if (maybe_smart &&
-                  last->len > 5 && starts_with(last->buf + 4, "version 2")) {
-               last->proto_git = 1;
-       }
+       if (maybe_smart)
+               check_smart_http(last, service, &type);
 
        if (last->proto_git)
                last->refs = parse_git_refs(last, for_push);
@@ -421,7 +468,6 @@ static struct discovery *discover_refs(const char *service, int for_push)
                last->refs = parse_info_refs(last);
 
        strbuf_release(&refs_url);
-       strbuf_release(&exp);
        strbuf_release(&type);
        strbuf_release(&charset);
        strbuf_release(&effective_url);
@@ -523,14 +569,30 @@ static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
 }
 #endif
 
+struct rpc_in_data {
+       struct rpc_state *rpc;
+       struct active_request_slot *slot;
+};
+
+/*
+ * A callback for CURLOPT_WRITEFUNCTION. The return value is the bytes consumed
+ * from ptr.
+ */
 static size_t rpc_in(char *ptr, size_t eltsize,
                size_t nmemb, void *buffer_)
 {
        size_t size = eltsize * nmemb;
-       struct rpc_state *rpc = buffer_;
+       struct rpc_in_data *data = buffer_;
+       long response_code;
+
+       if (curl_easy_getinfo(data->slot->curl, CURLINFO_RESPONSE_CODE,
+                             &response_code) != CURLE_OK)
+               return size;
+       if (response_code >= 300)
+               return size;
        if (size)
-               rpc->any_written = 1;
-       write_or_die(rpc->in, ptr, size);
+               data->rpc->any_written = 1;
+       write_or_die(data->rpc->in, ptr, size);
        return size;
 }
 
@@ -594,10 +656,12 @@ static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
        return err;
 }
 
-static curl_off_t xcurl_off_t(ssize_t len) {
-       if (len > maximum_signed_value_of_type(curl_off_t))
+static curl_off_t xcurl_off_t(size_t len)
+{
+       uintmax_t size = len;
+       if (size > maximum_signed_value_of_type(curl_off_t))
                die("cannot handle pushes this big");
-       return (curl_off_t) len;
+       return (curl_off_t)size;
 }
 
 static int post_rpc(struct rpc_state *rpc)
@@ -609,6 +673,7 @@ static int post_rpc(struct rpc_state *rpc)
        size_t gzip_size = 0;
        int err, large_request = 0;
        int needs_100_continue = 0;
+       struct rpc_in_data rpc_in_data;
 
        /* Try to load the entire request, if we can fit it into the
         * allocated buffer space we can use HTTP/1.0 and avoid the
@@ -661,7 +726,7 @@ static int post_rpc(struct rpc_state *rpc)
        curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
        curl_easy_setopt(slot->curl, CURLOPT_POST, 1);
        curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
-       curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip");
+       curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "");
 
        if (large_request) {
                /* The request body is large and the size cannot be predicted.
@@ -691,7 +756,7 @@ static int post_rpc(struct rpc_state *rpc)
 
        } else if (use_gzip && 1024 < rpc->len) {
                /* The client backend isn't giving us compressed data so
-                * we can try to deflate it ourselves, this may save on.
+                * we can try to deflate it ourselves, this may save on
                 * the transfer time.
                 */
                git_zstream stream;
@@ -741,7 +806,10 @@ static int post_rpc(struct rpc_state *rpc)
 
        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, rpc_in);
-       curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc);
+       rpc_in_data.rpc = rpc;
+       rpc_in_data.slot = slot;
+       curl_easy_setopt(slot->curl, CURLOPT_FILE, &rpc_in_data);
+       curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
 
 
        rpc->any_written = 0;
@@ -846,9 +914,6 @@ static int fetch_dumb(int nr_heads, struct ref **to_fetch)
                targets[i] = xstrdup(oid_to_hex(&to_fetch[i]->old_oid));
 
        walker = get_http_walker(url.buf);
-       walker->get_all = 1;
-       walker->get_tree = 1;
-       walker->get_history = 1;
        walker->get_verbosely = options.verbosity >= 3;
        walker->get_recover = 0;
        ret = walker_fetch(walker, nr_heads, targets, NULL, NULL);
@@ -894,6 +959,12 @@ static int fetch_git(struct discovery *heads,
                                 options.deepen_not.items[i].string);
        if (options.deepen_relative && options.depth)
                argv_array_push(&args, "--deepen-relative");
+       if (options.from_promisor)
+               argv_array_push(&args, "--from-promisor");
+       if (options.no_dependents)
+               argv_array_push(&args, "--no-dependents");
+       if (options.filter)
+               argv_array_pushf(&args, "--filter=%s", options.filter);
        argv_array_push(&args, url.buf);
 
        for (i = 0; i < nr_heads; i++) {
@@ -1147,7 +1218,8 @@ static void proxy_state_init(struct proxy_state *p, const char *service_name,
                p->headers = curl_slist_append(p->headers, buf.buf);
 
        packet_reader_init(&p->reader, p->in, NULL, 0,
-                          PACKET_READ_GENTLE_ON_EOF);
+                          PACKET_READ_GENTLE_ON_EOF |
+                          PACKET_READ_DIE_ON_ERR_PACKET);
 
        strbuf_release(&buf);
 }
@@ -1233,6 +1305,7 @@ static int proxy_request(struct proxy_state *p)
 
        slot = get_active_slot();
 
+       curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "");
        curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
        curl_easy_setopt(slot->curl, CURLOPT_POST, 1);
        curl_easy_setopt(slot->curl, CURLOPT_URL, p->service_url);