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

2016-09-28 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", _full, ,
> +   _len, HTTP_ERROR_GENTLE)) {
> +   while (line = packet_read_line_buf_gentle(, 
> _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(, "repository '%s' not found", url.buf);
+   break;
+   case HTTP_NOAUTH:
+   strbuf_addf(, "Authentication failed for '%s'",
+   url.buf);
+   break;
+   default:
+   strbuf_addf(, "unable to access '%s': %s", url.buf,
+   curl_errorstr);
+   break;
+   }
+
+   return strbuf_detach(, 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(_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(_url, "service=%s", service);
}
 
-   memset(, 0, sizeof(options));
-   options.content_type = 
-   options.charset = 
-   options.effective_url = _url;
-   options.base_url = 
-   options.no_cache = 1;
-   options.keep_error = 1;
-
-   http_ret = http_get_strbuf(refs_url.buf, , );
-   switch (http_ret) {
-   case HTTP_OK:
-   break;
-   case HTTP_MISSING_TARGET:
-   show_http_message(, , );
-   die("repository '%s' not found", url.buf);
-   case HTTP_NOAUTH:
-   show_http_message(, , );
-   die("Authentication failed for '%s'", url.buf);
-   default:
-   show_http_message(, , );
-   die("unable to access '%s': %s", url.buf, curl_errorstr);
+   memset(_options, 0, sizeof(get_options));
+   get_options.content_type = 
+   get_options.charset = 
+   get_options.effective_url = _url;
+   get_options.base_url = 
+   get_options.no_cache = 1;
+   get_options.keep_error = 1;
+
+   http_ret = http_get_strbuf(refs_url.buf, , _options);
+   error_string = http_handle_result(http_ret);
+   if (error_string) {
+   if (!(flags & HTTP_ERROR_GENTLE)) {
+   show_http_message(, , );
+   die("%s", error_string);
+   }
+   else if (options.verbosity > 1) {
+   show_http_message(, , );
+   fprintf(stderr, "%s\n", error_string);
+   }
}
 
-   last= xcalloc(1, sizeof(*last_discovery));
-   last->service = service;
-   last->buf_alloc = strbuf_detach(, >len);
-   last->buf = last->buf_alloc;
+   *buffer_full = strbuf_detach(, buffer_len);
+   *buffer_msg = *buffer_full;
 
strbuf_addf(, "application/x-%s-advertisement", service);
if (maybe_smart &&
-   (5 <= last->len && last->buf[4] == '#') &&
-   !strbuf_cmp(, )) {
+   (5 <= *buffer_len && (*buffer_msg)[4] == '#') &&
+   !strbuf_cmp(, ) && http_ret == HTTP_OK) {
char *line;
 
/*
 * smart HTTP