Merge branch 'js/remote-curl-i18n'
authorJunio C Hamano <gitster@pobox.com>
Tue, 16 Apr 2019 10:28:05 +0000 (19:28 +0900)
committerJunio C Hamano <gitster@pobox.com>
Tue, 16 Apr 2019 10:28:05 +0000 (19:28 +0900)
Error messages given from the http transport have been updated so
that they can be localized.

* js/remote-curl-i18n:
remote-curl: mark all error messages for translation

1  2 
remote-curl.c
diff --combined remote-curl.c
index 78f340f004e36bdfd84687f1ee803254b8fb8d43,06f091d86217765dbdaca10180e9e877b8a7c77c..8bba57270b00b72c7e70fe749880a29c1ddfea1f
@@@ -154,7 -154,7 +154,7 @@@ static int set_option(const char *name
                else {
                        struct strbuf unquoted = STRBUF_INIT;
                        if (unquote_c_style(&unquoted, value, NULL) < 0)
-                               die("invalid quoting in push-option value");
+                               die(_("invalid quoting in push-option value: '%s'"), value);
                        string_list_append_nodup(&options.push_options,
                                                 strbuf_detach(&unquoted, NULL));
                }
@@@ -205,8 -205,7 +205,8 @@@ static struct ref *parse_git_refs(struc
  
        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) {
@@@ -251,7 -250,7 +251,7 @@@ static struct ref *parse_info_refs(stru
                        mid = &data[i];
                if (data[i] == '\n') {
                        if (mid - start != 40)
-                               die("%sinfo/refs not valid: is this a git repository?",
+                               die(_("%sinfo/refs not valid: is this a git repository?"),
                                    transport_anonymize_url(url.buf));
                        data[i] = 0;
                        ref_name = mid + 1;
@@@ -332,63 -331,9 +332,63 @@@ static int get_protocol_http_header(enu
        return 0;
  }
  
-               die("invalid server response; expected service, got flush packet");
 +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; got '%s'", reader.line);
++              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;
        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) {
                break;
        case HTTP_MISSING_TARGET:
                show_http_message(&type, &charset, &buffer);
-               die("repository '%s' not found",
+               die(_("repository '%s' not found"),
                    transport_anonymize_url(url.buf));
        case HTTP_NOAUTH:
                show_http_message(&type, &charset, &buffer);
-               die("Authentication failed for '%s'",
+               die(_("Authentication failed for '%s'"),
                    transport_anonymize_url(url.buf));
        default:
                show_http_message(&type, &charset, &buffer);
-               die("unable to access '%s': %s",
+               die(_("unable to access '%s': %s"),
                    transport_anonymize_url(url.buf), curl_errorstr);
        }
  
        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);
 -              if (!line)
 -                      die(_("invalid server response; expected service, got flush packet"));
 -
 -              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);
                last->refs = parse_info_refs(last);
  
        strbuf_release(&refs_url);
 -      strbuf_release(&exp);
        strbuf_release(&type);
        strbuf_release(&charset);
        strbuf_release(&effective_url);
@@@ -512,6 -489,8 +512,6 @@@ static void output_refs(struct ref *ref
  
  struct rpc_state {
        const char *service_name;
 -      const char **argv;
 -      struct strbuf *stdin_preamble;
        char *service_url;
        char *hdr_content_type;
        char *hdr_accept;
        int in;
        int out;
        int any_written;
 -      struct strbuf result;
        unsigned gzip_request : 1;
        unsigned initial_buffer : 1;
 +
 +      /*
 +       * Whenever a pkt-line is read into buf, append the 4 characters
 +       * denoting its length before appending the payload.
 +       */
 +      unsigned write_line_lengths : 1;
 +
 +      /*
 +       * Used by rpc_out; initialize to 0. This is true if a flush has been
 +       * read, but the corresponding line length (if write_line_lengths is
 +       * true) and EOF have not been sent to libcurl. Since each flush marks
 +       * the end of a request, each flush must be completely sent before any
 +       * further reading occurs.
 +       */
 +      unsigned flush_read_but_not_sent : 1;
  };
  
-                               die("shouldn't have EOF when not gentle on EOF");
 +/*
 + * Appends the result of reading from rpc->out to the string represented by
 + * rpc->buf and rpc->len if there is enough space. Returns 1 if there was
 + * enough space, 0 otherwise.
 + *
 + * If rpc->write_line_lengths is true, appends the line length as a 4-byte
 + * hexadecimal string before appending the result described above.
 + *
 + * Writes the total number of bytes appended into appended.
 + */
 +static int rpc_read_from_out(struct rpc_state *rpc, int options,
 +                           size_t *appended,
 +                           enum packet_read_status *status) {
 +      size_t left;
 +      char *buf;
 +      int pktlen_raw;
 +
 +      if (rpc->write_line_lengths) {
 +              left = rpc->alloc - rpc->len - 4;
 +              buf = rpc->buf + rpc->len + 4;
 +      } else {
 +              left = rpc->alloc - rpc->len;
 +              buf = rpc->buf + rpc->len;
 +      }
 +
 +      if (left < LARGE_PACKET_MAX)
 +              return 0;
 +
 +      *status = packet_read_with_status(rpc->out, NULL, NULL, buf,
 +                      left, &pktlen_raw, options);
 +      if (*status != PACKET_READ_EOF) {
 +              *appended = pktlen_raw + (rpc->write_line_lengths ? 4 : 0);
 +              rpc->len += *appended;
 +      }
 +
 +      if (rpc->write_line_lengths) {
 +              switch (*status) {
 +              case PACKET_READ_EOF:
 +                      if (!(options & PACKET_READ_GENTLE_ON_EOF))
++                              die(_("shouldn't have EOF when not gentle on EOF"));
 +                      break;
 +              case PACKET_READ_NORMAL:
 +                      set_packet_header(buf - 4, *appended);
 +                      break;
 +              case PACKET_READ_DELIM:
 +                      memcpy(buf - 4, "0001", 4);
 +                      break;
 +              case PACKET_READ_FLUSH:
 +                      memcpy(buf - 4, "0000", 4);
 +                      break;
 +              }
 +      }
 +
 +      return 1;
 +}
 +
  static size_t rpc_out(void *ptr, size_t eltsize,
                size_t nmemb, void *buffer_)
  {
        size_t max = eltsize * nmemb;
        struct rpc_state *rpc = buffer_;
        size_t avail = rpc->len - rpc->pos;
 +      enum packet_read_status status;
  
        if (!avail) {
                rpc->initial_buffer = 0;
 -              avail = packet_read(rpc->out, NULL, NULL, rpc->buf, rpc->alloc, 0);
 -              if (!avail)
 -                      return 0;
 +              rpc->len = 0;
                rpc->pos = 0;
 -              rpc->len = avail;
 +              if (!rpc->flush_read_but_not_sent) {
 +                      if (!rpc_read_from_out(rpc, 0, &avail, &status))
 +                              BUG("The entire rpc->buf should be larger than LARGE_PACKET_MAX");
 +                      if (status == PACKET_READ_FLUSH)
 +                              rpc->flush_read_but_not_sent = 1;
 +              }
 +              /*
 +               * If flush_read_but_not_sent is true, we have already read one
 +               * full request but have not fully sent it + EOF, which is why
 +               * we need to refrain from reading.
 +               */
 +      }
 +      if (rpc->flush_read_but_not_sent) {
 +              if (!avail) {
 +                      /*
 +                       * The line length either does not need to be sent at
 +                       * all or has already been completely sent. Now we can
 +                       * return 0, indicating EOF, meaning that the flush has
 +                       * been fully sent.
 +                       */
 +                      rpc->flush_read_but_not_sent = 0;
 +                      return 0;
 +              }
 +              /*
 +               * If avail is non-zerp, the line length for the flush still
 +               * hasn't been fully sent. Proceed with sending the line
 +               * length.
 +               */
        }
  
        if (max < avail)
@@@ -661,7 -544,7 +661,7 @@@ static curlioerr rpc_ioctl(CURL *handle
                        rpc->pos = 0;
                        return CURLIOE_OK;
                }
-               error("unable to rewind rpc post data - try increasing http.postBuffer");
+               error(_("unable to rewind rpc post data - try increasing http.postBuffer"));
                return CURLIOE_FAILRESTART;
  
        default:
  }
  #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;
  }
  
@@@ -721,7 -588,7 +721,7 @@@ static int run_slot(struct active_reque
                                strbuf_addstr(&msg, curl_errorstr);
                        }
                }
-               error("RPC failed; %s", msg.buf);
+               error(_("RPC failed; %s"), msg.buf);
                strbuf_release(&msg);
        }
  
@@@ -757,19 -624,13 +757,19 @@@ static int probe_rpc(struct rpc_state *
        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");
+               die(_("cannot handle pushes this big"));
 -      return (curl_off_t) len;
 +      return (curl_off_t)size;
  }
  
 -static int post_rpc(struct rpc_state *rpc)
 +/*
 + * If flush_received is true, do not attempt to read any more; just use what's
 + * in rpc->buf.
 + */
 +static int post_rpc(struct rpc_state *rpc, int flush_received)
  {
        struct active_request_slot *slot;
        struct curl_slist *headers = http_copy_default_headers();
        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
         * chunked encoding mess.
         */
 -      while (1) {
 -              size_t left = rpc->alloc - rpc->len;
 -              char *buf = rpc->buf + rpc->len;
 -              int n;
 -
 -              if (left < LARGE_PACKET_MAX) {
 -                      large_request = 1;
 -                      use_gzip = 0;
 -                      break;
 +      if (!flush_received) {
 +              while (1) {
 +                      size_t n;
 +                      enum packet_read_status status;
 +
 +                      if (!rpc_read_from_out(rpc, 0, &n, &status)) {
 +                              large_request = 1;
 +                              use_gzip = 0;
 +                              break;
 +                      }
 +                      if (status == PACKET_READ_FLUSH)
 +                              break;
                }
 -
 -              n = packet_read(rpc->out, NULL, NULL, buf, left, 0);
 -              if (!n)
 -                      break;
 -              rpc->len += n;
        }
  
        if (large_request) {
@@@ -876,11 -738,11 +876,11 @@@ retry
  
                ret = git_deflate(&stream, Z_FINISH);
                if (ret != Z_STREAM_END)
-                       die("cannot deflate request; zlib deflate error %d", ret);
+                       die(_("cannot deflate request; zlib deflate error %d"), ret);
  
                ret = git_deflate_end_gently(&stream);
                if (ret != Z_OK)
-                       die("cannot deflate request; zlib end error %d", ret);
+                       die(_("cannot deflate request; zlib end error %d"), ret);
  
                gzip_size = stream.total_out;
  
  
        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;
        return err;
  }
  
 -static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
 +static int rpc_service(struct rpc_state *rpc, struct discovery *heads,
 +                     const char **client_argv, const struct strbuf *preamble,
 +                     struct strbuf *rpc_result)
  {
        const char *svc = rpc->service_name;
        struct strbuf buf = STRBUF_INIT;
 -      struct strbuf *preamble = rpc->stdin_preamble;
        struct child_process client = CHILD_PROCESS_INIT;
        int err = 0;
  
        client.in = -1;
        client.out = -1;
        client.git_cmd = 1;
 -      client.argv = rpc->argv;
 +      client.argv = client_argv;
        if (start_command(&client))
                exit(1);
 -      if (preamble)
 -              write_or_die(client.in, preamble->buf, preamble->len);
 +      write_or_die(client.in, preamble->buf, preamble->len);
        if (heads)
                write_or_die(client.in, heads->buf, heads->len);
  
        rpc->buf = xmalloc(rpc->alloc);
        rpc->in = client.in;
        rpc->out = client.out;
 -      strbuf_init(&rpc->result, 0);
  
        strbuf_addf(&buf, "%s%s", url.buf, svc);
        rpc->service_url = strbuf_detach(&buf, NULL);
                        break;
                rpc->pos = 0;
                rpc->len = n;
 -              err |= post_rpc(rpc);
 +              err |= post_rpc(rpc, 0);
        }
  
        close(client.in);
        client.in = -1;
        if (!err) {
 -              strbuf_read(&rpc->result, client.out, 0);
 +              strbuf_read(rpc_result, client.out, 0);
        } else {
                char buf[4096];
                for (;;)
@@@ -1011,7 -871,7 +1011,7 @@@ static int fetch_dumb(int nr_heads, str
  
        ALLOC_ARRAY(targets, nr_heads);
        if (options.depth || options.deepen_since)
-               die("dumb http transport does not support shallow capabilities");
+               die(_("dumb http transport does not support shallow capabilities"));
        for (i = 0; i < nr_heads; i++)
                targets[i] = xstrdup(oid_to_hex(&to_fetch[i]->old_oid));
  
                free(targets[i]);
        free(targets);
  
-       return ret ? error("fetch failed.") : 0;
+       return ret ? error(_("fetch failed.")) : 0;
  }
  
  static int fetch_git(struct discovery *heads,
        struct strbuf preamble = STRBUF_INIT;
        int i, err;
        struct argv_array args = ARGV_ARRAY_INIT;
 +      struct strbuf rpc_result = STRBUF_INIT;
  
        argv_array_pushl(&args, "fetch-pack", "--stateless-rpc",
                         "--stdin", "--lock-pack", NULL);
        for (i = 0; i < nr_heads; i++) {
                struct ref *ref = to_fetch[i];
                if (!*ref->name)
-                       die("cannot fetch by sha1 over smart http");
+                       die(_("cannot fetch by sha1 over smart http"));
                packet_buf_write(&preamble, "%s %s\n",
                                 oid_to_hex(&ref->old_oid), ref->name);
        }
  
        memset(&rpc, 0, sizeof(rpc));
        rpc.service_name = "git-upload-pack",
 -      rpc.argv = args.argv;
 -      rpc.stdin_preamble = &preamble;
        rpc.gzip_request = 1;
  
 -      err = rpc_service(&rpc, heads);
 -      if (rpc.result.len)
 -              write_or_die(1, rpc.result.buf, rpc.result.len);
 -      strbuf_release(&rpc.result);
 +      err = rpc_service(&rpc, heads, args.argv, &preamble, &rpc_result);
 +      if (rpc_result.len)
 +              write_or_die(1, rpc_result.buf, rpc_result.len);
 +      strbuf_release(&rpc_result);
        strbuf_release(&preamble);
        argv_array_clear(&args);
        return err;
@@@ -1116,13 -977,13 +1116,13 @@@ static void parse_fetch(struct strbuf *
                        struct object_id old_oid;
  
                        if (get_oid_hex(p, &old_oid))
-                               die("protocol error: expected sha/ref, got %s'", p);
+                               die(_("protocol error: expected sha/ref, got %s'"), p);
                        if (p[GIT_SHA1_HEXSZ] == ' ')
                                name = p + GIT_SHA1_HEXSZ + 1;
                        else if (!p[GIT_SHA1_HEXSZ])
                                name = "";
                        else
-                               die("protocol error: expected sha/ref, got %s'", p);
+                               die(_("protocol error: expected sha/ref, got %s'"), p);
  
                        ref = alloc_ref(name);
                        oidcpy(&ref->old_oid, &old_oid);
                        to_fetch[nr_heads++] = ref;
                }
                else
-                       die("http transport does not support %s", buf->buf);
+                       die(_("http transport does not support %s"), buf->buf);
  
                strbuf_reset(buf);
                if (strbuf_getline_lf(buf, stdin) == EOF)
@@@ -1170,7 -1031,7 +1170,7 @@@ static int push_dav(int nr_spec, char *
                argv_array_push(&child.args, specs[i]);
  
        if (run_command(&child))
-               die("git-http-push failed");
+               die(_("git-http-push failed"));
        return 0;
  }
  
@@@ -1181,7 -1042,6 +1181,7 @@@ static int push_git(struct discovery *h
        struct argv_array args;
        struct string_list_item *cas_option;
        struct strbuf preamble = STRBUF_INIT;
 +      struct strbuf rpc_result = STRBUF_INIT;
  
        argv_array_init(&args);
        argv_array_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status",
  
        memset(&rpc, 0, sizeof(rpc));
        rpc.service_name = "git-receive-pack",
 -      rpc.argv = args.argv;
 -      rpc.stdin_preamble = &preamble;
  
 -      err = rpc_service(&rpc, heads);
 -      if (rpc.result.len)
 -              write_or_die(1, rpc.result.buf, rpc.result.len);
 -      strbuf_release(&rpc.result);
 +      err = rpc_service(&rpc, heads, args.argv, &preamble, &rpc_result);
 +      if (rpc_result.len)
 +              write_or_die(1, rpc_result.buf, rpc_result.len);
 +      strbuf_release(&rpc_result);
        strbuf_release(&preamble);
        argv_array_clear(&args);
        return err;
@@@ -1248,7 -1110,7 +1248,7 @@@ static void parse_push(struct strbuf *b
                        specs[nr_spec++] = xstrdup(buf->buf + 5);
                }
                else
-                       die("http transport does not support %s", buf->buf);
+                       die(_("http transport does not support %s"), buf->buf);
  
                strbuf_reset(buf);
                if (strbuf_getline_lf(buf, stdin) == EOF)
        free(specs);
  }
  
 -/*
 - * Used to represent the state of a connection to an HTTP server when
 - * communicating using git's wire-protocol version 2.
 - */
 -struct proxy_state {
 -      char *service_name;
 -      char *service_url;
 -      struct curl_slist *headers;
 -      struct strbuf request_buffer;
 -      int in;
 -      int out;
 -      struct packet_reader reader;
 -      size_t pos;
 -      int seen_flush;
 -};
 -
 -static void proxy_state_init(struct proxy_state *p, const char *service_name,
 -                           enum protocol_version version)
 -{
 -      struct strbuf buf = STRBUF_INIT;
 -
 -      memset(p, 0, sizeof(*p));
 -      p->service_name = xstrdup(service_name);
 -
 -      p->in = 0;
 -      p->out = 1;
 -      strbuf_init(&p->request_buffer, 0);
 -
 -      strbuf_addf(&buf, "%s%s", url.buf, p->service_name);
 -      p->service_url = strbuf_detach(&buf, NULL);
 -
 -      p->headers = http_copy_default_headers();
 -
 -      strbuf_addf(&buf, "Content-Type: application/x-%s-request", p->service_name);
 -      p->headers = curl_slist_append(p->headers, buf.buf);
 -      strbuf_reset(&buf);
 -
 -      strbuf_addf(&buf, "Accept: application/x-%s-result", p->service_name);
 -      p->headers = curl_slist_append(p->headers, buf.buf);
 -      strbuf_reset(&buf);
 -
 -      p->headers = curl_slist_append(p->headers, "Transfer-Encoding: chunked");
 -
 -      /* Add the Git-Protocol header */
 -      if (get_protocol_http_header(version, &buf))
 -              p->headers = curl_slist_append(p->headers, buf.buf);
 -
 -      packet_reader_init(&p->reader, p->in, NULL, 0,
 -                         PACKET_READ_GENTLE_ON_EOF);
 -
 -      strbuf_release(&buf);
 -}
 -
 -static void proxy_state_clear(struct proxy_state *p)
 -{
 -      free(p->service_name);
 -      free(p->service_url);
 -      curl_slist_free_all(p->headers);
 -      strbuf_release(&p->request_buffer);
 -}
 -
 -/*
 - * CURLOPT_READFUNCTION callback function.
 - * Attempts to copy over a single packet-line at a time into the
 - * curl provided buffer.
 - */
 -static size_t proxy_in(char *buffer, size_t eltsize,
 -                     size_t nmemb, void *userdata)
 -{
 -      size_t max;
 -      struct proxy_state *p = userdata;
 -      size_t avail = p->request_buffer.len - p->pos;
 -
 -
 -      if (eltsize != 1)
 -              BUG("curl read callback called with size = %"PRIuMAX" != 1",
 -                  (uintmax_t)eltsize);
 -      max = nmemb;
 -
 -      if (!avail) {
 -              if (p->seen_flush) {
 -                      p->seen_flush = 0;
 -                      return 0;
 -              }
 -
 -              strbuf_reset(&p->request_buffer);
 -              switch (packet_reader_read(&p->reader)) {
 -              case PACKET_READ_EOF:
 -                      die(_("unexpected EOF when reading from parent process"));
 -              case PACKET_READ_NORMAL:
 -                      packet_buf_write_len(&p->request_buffer, p->reader.line,
 -                                           p->reader.pktlen);
 -                      break;
 -              case PACKET_READ_DELIM:
 -                      packet_buf_delim(&p->request_buffer);
 -                      break;
 -              case PACKET_READ_FLUSH:
 -                      packet_buf_flush(&p->request_buffer);
 -                      p->seen_flush = 1;
 -                      break;
 -              }
 -              p->pos = 0;
 -              avail = p->request_buffer.len;
 -      }
 -
 -      if (max < avail)
 -              avail = max;
 -      memcpy(buffer, p->request_buffer.buf + p->pos, avail);
 -      p->pos += avail;
 -      return avail;
 -}
 -
 -static size_t proxy_out(char *buffer, size_t eltsize,
 -                      size_t nmemb, void *userdata)
 -{
 -      size_t size;
 -      struct proxy_state *p = userdata;
 -
 -      if (eltsize != 1)
 -              BUG("curl read callback called with size = %"PRIuMAX" != 1",
 -                  (uintmax_t)eltsize);
 -      size = nmemb;
 -
 -      write_or_die(p->out, buffer, size);
 -      return size;
 -}
 -
 -/* Issues a request to the HTTP server configured in `p` */
 -static int proxy_request(struct proxy_state *p)
 -{
 -      struct active_request_slot *slot;
 -
 -      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);
 -      curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, p->headers);
 -
 -      /* Setup function to read request from client */
 -      curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, proxy_in);
 -      curl_easy_setopt(slot->curl, CURLOPT_READDATA, p);
 -
 -      /* Setup function to write server response to client */
 -      curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, proxy_out);
 -      curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, p);
 -
 -      if (run_slot(slot, NULL) != HTTP_OK)
 -              return -1;
 -
 -      return 0;
 -}
 -
  static int stateless_connect(const char *service_name)
  {
        struct discovery *discover;
 -      struct proxy_state p;
 +      struct rpc_state rpc;
 +      struct strbuf buf = STRBUF_INIT;
  
        /*
         * Run the info/refs request and see if the server supports protocol
                fflush(stdout);
        }
  
 -      proxy_state_init(&p, service_name, discover->version);
 +      rpc.service_name = service_name;
 +      rpc.service_url = xstrfmt("%s%s", url.buf, rpc.service_name);
 +      rpc.hdr_content_type = xstrfmt("Content-Type: application/x-%s-request", rpc.service_name);
 +      rpc.hdr_accept = xstrfmt("Accept: application/x-%s-result", rpc.service_name);
 +      if (get_protocol_http_header(discover->version, &buf)) {
 +              rpc.protocol_header = strbuf_detach(&buf, NULL);
 +      } else {
 +              rpc.protocol_header = NULL;
 +              strbuf_release(&buf);
 +      }
 +      rpc.buf = xmalloc(http_post_buffer);
 +      rpc.alloc = http_post_buffer;
 +      rpc.len = 0;
 +      rpc.pos = 0;
 +      rpc.in = 1;
 +      rpc.out = 0;
 +      rpc.any_written = 0;
 +      rpc.gzip_request = 1;
 +      rpc.initial_buffer = 0;
 +      rpc.write_line_lengths = 1;
 +      rpc.flush_read_but_not_sent = 0;
  
        /*
         * Dump the capability listing that we got from the server earlier
         * during the info/refs request.
         */
 -      write_or_die(p.out, discover->buf, discover->len);
 +      write_or_die(rpc.in, discover->buf, discover->len);
 +
 +      /* Until we see EOF keep sending POSTs */
 +      while (1) {
 +              size_t avail;
 +              enum packet_read_status status;
  
 -      /* Peek the next packet line.  Until we see EOF keep sending POSTs */
 -      while (packet_reader_peek(&p.reader) != PACKET_READ_EOF) {
 -              if (proxy_request(&p)) {
 +              if (!rpc_read_from_out(&rpc, PACKET_READ_GENTLE_ON_EOF, &avail,
 +                                     &status))
 +                      BUG("The entire rpc->buf should be larger than LARGE_PACKET_MAX");
 +              if (status == PACKET_READ_EOF)
 +                      break;
 +              if (post_rpc(&rpc, status == PACKET_READ_FLUSH))
                        /* We would have an err here */
                        break;
 -              }
 +              /* Reset the buffer for next request */
 +              rpc.len = 0;
        }
  
 -      proxy_state_clear(&p);
 +      free(rpc.service_url);
 +      free(rpc.hdr_content_type);
 +      free(rpc.hdr_accept);
 +      free(rpc.protocol_header);
 +      free(rpc.buf);
 +      strbuf_release(&buf);
 +
        return 0;
  }
  
@@@ -1356,7 -1336,7 +1356,7 @@@ int cmd_main(int argc, const char **arg
  
        setup_git_directory_gently(&nongit);
        if (argc < 2) {
-               error("remote-curl: usage: git remote-curl <remote> [<url>]");
+               error(_("remote-curl: usage: git remote-curl <remote> [<url>]"));
                return 1;
        }
  
        string_list_init(&options.deepen_not, 1);
        string_list_init(&options.push_options, 1);
  
 +      /*
 +       * Just report "remote-curl" here (folding all the various aliases
 +       * ("git-remote-http", "git-remote-https", and etc.) here since they
 +       * are all just copies of the same actual executable.
 +       */
 +      trace2_cmd_name("remote-curl");
 +
        remote = remote_get(argv[1]);
  
        if (argc > 2) {
  
                if (strbuf_getline_lf(&buf, stdin) == EOF) {
                        if (ferror(stdin))
-                               error("remote-curl: error reading command stream from git");
+                               error(_("remote-curl: error reading command stream from git"));
                        return 1;
                }
                if (buf.len == 0)
                        break;
                if (starts_with(buf.buf, "fetch ")) {
                        if (nongit)
-                               die("remote-curl: fetch attempted without a local repo");
+                               die(_("remote-curl: fetch attempted without a local repo"));
                        parse_fetch(&buf);
  
                } else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) {
                        if (!stateless_connect(arg))
                                break;
                } else {
-                       error("remote-curl: unknown command '%s' from git", buf.buf);
+                       error(_("remote-curl: unknown command '%s' from git"), buf.buf);
                        return 1;
                }
                strbuf_reset(&buf);