Re: [PATCH 04/11] Resumable clone: add prime-clone to remote-curl

2016-09-27 Thread Kevin Wern
On Mon, Sep 19, 2016 at 08:52:34PM +0700, Duy Nguyen wrote:
> 
> A brief overview for this service in
> Documentation/technical/http-protocol.txt (and maybe
> Documentation/gitremote-helpers.txt as well) would be great help. It's
> a bit hard to follow because at this point I don't know anything about
> the server side (and on top of that I was confused between http
> send/receive vs transport send/receive, but this is my fault).
> 

I figured I would miss something in this vein. So many things to cover!

Thanks again for reading.

- Kevin


Re: [PATCH 04/11] Resumable clone: add prime-clone to remote-curl

2016-09-19 Thread Duy Nguyen
On Fri, Sep 16, 2016 at 7:12 AM, Kevin Wern  wrote:
> +static void prime_clone(void)
> +{
> +   char *result, *result_full, *line;
> +   size_t result_len;
> +   int err = 0, one_successful = 0;
> +
> +   if (request_service("git-prime-clone", &result_full, &result,
> +   &result_len, HTTP_ERROR_GENTLE)) {
> +   while (line = packet_read_line_buf_gentle(&result, 
> &result_len,
> + NULL)) {
> +   char *space = strchr(line ,' ');
> +
> +   // We will eventually support multiple resources, so
> +   // always parse the whole message
> +   if (err)
> +   continue;
> +   if (!space || strchr(space + 1, ' ')) {
> +   if (options.verbosity > 1)
> +   fprintf(stderr, "prime clone "
> +   "protocol error: got '%s'\n",
> +   line);
> +   printf("error\n");
> +   err = 1;
> +   continue;
> +   }
> +
> +   one_successful = 1;
> +   printf("%s\n", line);

A brief overview for this service in
Documentation/technical/http-protocol.txt (and maybe
Documentation/gitremote-helpers.txt as well) would be great help. It's
a bit hard to follow because at this point I don't know anything about
the server side (and on top of that I was confused between http
send/receive vs transport send/receive, but this is my fault).

> +   }
> +   if (!one_successful && options.verbosity > 1)
> +   fprintf(stderr, "did not get required components for "
> +   "alternate resource\n");
> +   }
> +
> +   printf("\n");
> +   fflush(stdout);
> +   free(result_full);
> +}
-- 
Duy


[PATCH 04/11] Resumable clone: add prime-clone to remote-curl

2016-09-15 Thread Kevin Wern
Add function and interface to handle prime-clone input, extracting
and using duplicate functionality from discover_refs as function
request_service.

Because part of our goal is for prime_clone to recover from errors,
HTTP errors are only optionally printed to screen and never cause
death in this case.

Signed-off-by: Kevin Wern 
---
 remote-curl.c | 165 ++
 1 file changed, 121 insertions(+), 44 deletions(-)

diff --git a/remote-curl.c b/remote-curl.c
index 15e48e2..8ebb587 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -13,6 +13,8 @@
 #include "sha1-array.h"
 #include "send-pack.h"
 
+#define HTTP_ERROR_GENTLE (1u << 0)
+
 static struct remote *remote;
 /* always ends with a trailing slash */
 static struct strbuf url = STRBUF_INIT;
@@ -244,7 +246,31 @@ static int show_http_message(struct strbuf *type, struct 
strbuf *charset,
return 0;
 }
 
-static struct discovery *discover_refs(const char *service, int for_push)
+static char *http_handle_result(int http_return)
+{
+   struct strbuf error = STRBUF_INIT;
+
+   switch (http_return) {
+   case HTTP_OK:
+   return NULL;
+   case HTTP_MISSING_TARGET:
+   strbuf_addf(&error, "repository '%s' not found", url.buf);
+   break;
+   case HTTP_NOAUTH:
+   strbuf_addf(&error, "Authentication failed for '%s'",
+   url.buf);
+   break;
+   default:
+   strbuf_addf(&error, "unable to access '%s': %s", url.buf,
+   curl_errorstr);
+   break;
+   }
+
+   return strbuf_detach(&error, NULL);
+}
+
+static int request_service(char const *const service, char **buffer_full,
+   char **buffer_msg, size_t *buffer_len, int flags)
 {
struct strbuf exp = STRBUF_INIT;
struct strbuf type = STRBUF_INIT;
@@ -252,13 +278,9 @@ static struct discovery *discover_refs(const char 
*service, int for_push)
struct strbuf buffer = STRBUF_INIT;
struct strbuf refs_url = STRBUF_INIT;
struct strbuf effective_url = STRBUF_INIT;
-   struct discovery *last = last_discovery;
-   int http_ret, maybe_smart = 0;
-   struct http_get_options options;
-
-   if (last && !strcmp(service, last->service))
-   return last;
-   free_discovery(last);
+   int http_ret, maybe_smart = 0, ran_smart = 0;
+   struct http_get_options get_options;
+   const char *error_string;
 
strbuf_addf(&refs_url, "%sinfo/refs", url.buf);
if ((starts_with(url.buf, "http://";) || starts_with(url.buf, 
"https://";)) &&
@@ -271,45 +293,41 @@ static struct discovery *discover_refs(const char 
*service, int for_push)
strbuf_addf(&refs_url, "service=%s", service);
}
 
-   memset(&options, 0, sizeof(options));
-   options.content_type = &type;
-   options.charset = &charset;
-   options.effective_url = &effective_url;
-   options.base_url = &url;
-   options.no_cache = 1;
-   options.keep_error = 1;
-
-   http_ret = http_get_strbuf(refs_url.buf, &buffer, &options);
-   switch (http_ret) {
-   case HTTP_OK:
-   break;
-   case HTTP_MISSING_TARGET:
-   show_http_message(&type, &charset, &buffer);
-   die("repository '%s' not found", url.buf);
-   case HTTP_NOAUTH:
-   show_http_message(&type, &charset, &buffer);
-   die("Authentication failed for '%s'", url.buf);
-   default:
-   show_http_message(&type, &charset, &buffer);
-   die("unable to access '%s': %s", url.buf, curl_errorstr);
+   memset(&get_options, 0, sizeof(get_options));
+   get_options.content_type = &type;
+   get_options.charset = &charset;
+   get_options.effective_url = &effective_url;
+   get_options.base_url = &url;
+   get_options.no_cache = 1;
+   get_options.keep_error = 1;
+
+   http_ret = http_get_strbuf(refs_url.buf, &buffer, &get_options);
+   error_string = http_handle_result(http_ret);
+   if (error_string) {
+   if (!(flags & HTTP_ERROR_GENTLE)) {
+   show_http_message(&type, &charset, &buffer);
+   die("%s", error_string);
+   }
+   else if (options.verbosity > 1) {
+   show_http_message(&type, &charset, &buffer);
+   fprintf(stderr, "%s\n", error_string);
+   }
}
 
-   last= xcalloc(1, sizeof(*last_discovery));
-   last->service = service;
-   last->buf_alloc = strbuf_detach(&buffer, &last->len);
-   last->buf = last->buf_alloc;
+   *buffer_full = strbuf_detach(&buffer, buffer_len);
+   *buffer_msg = *buffer_full;
 
strbuf_addf(&exp, "application/x-%s-advertisement", service);
if (maybe_smart &&
-   (5 <= last->len && last->buf[4] == '#')