From: Kevin Wern <kevin.m.wern@gmail.com>
To: git@vger.kernel.org
Subject: [PATCH 04/11] Resumable clone: add prime-clone to remote-curl
Date: Thu, 15 Sep 2016 20:12:15 -0400 [thread overview]
Message-ID: <1473984742-12516-5-git-send-email-kevin.m.wern@gmail.com> (raw)
In-Reply-To: <1473984742-12516-1-git-send-email-kevin.m.wern@gmail.com>
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 <kevin.m.wern@gmail.com>
---
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] == '#') &&
- !strbuf_cmp(&exp, &type)) {
+ (5 <= *buffer_len && (*buffer_msg)[4] == '#') &&
+ !strbuf_cmp(&exp, &type) && http_ret == HTTP_OK) {
char *line;
/*
* smart HTTP response; validate that the service
* pkt-line matches our request.
*/
- line = packet_read_line_buf(&last->buf, &last->len, NULL);
+ line = packet_read_line_buf(buffer_msg, buffer_len, NULL);
strbuf_reset(&exp);
strbuf_addf(&exp, "# service=%s", service);
@@ -321,23 +339,80 @@ static struct discovery *discover_refs(const char *service, int for_push)
* 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))
+ while (packet_read_line_buf(buffer_msg, buffer_len, NULL))
;
- last->proto_git = 1;
+ ran_smart = 1;
}
- if (last->proto_git)
- last->refs = parse_git_refs(last, for_push);
- else
- last->refs = parse_info_refs(last);
-
strbuf_release(&refs_url);
strbuf_release(&exp);
strbuf_release(&type);
strbuf_release(&charset);
strbuf_release(&effective_url);
strbuf_release(&buffer);
+
+ return ran_smart;
+}
+
+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);
+ }
+ if (!one_successful && options.verbosity > 1)
+ fprintf(stderr, "did not get required components for "
+ "alternate resource\n");
+ }
+
+ printf("\n");
+ fflush(stdout);
+ free(result_full);
+}
+
+
+static struct discovery *discover_refs(const char *service, int for_push)
+{
+ struct discovery *last = last_discovery;
+
+ if (last && !strcmp(service, last->service))
+ return last;
+ free_discovery(last);
+
+ last= xcalloc(1, sizeof(*last_discovery));
+ last->service = service;
+ last->proto_git = request_service(service, &last->buf_alloc,
+ &last->buf, &last->len, 0);
+
+ if (last->proto_git)
+ last->refs = parse_git_refs(last, for_push);
+ else
+ last->refs = parse_info_refs(last);
+
last_discovery = last;
return last;
}
@@ -1030,7 +1105,8 @@ int main(int argc, const char **argv)
} else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) {
int for_push = !!strstr(buf.buf + 4, "for-push");
output_refs(get_refs(for_push));
-
+ } else if (!strcmp(buf.buf, "prime-clone")) {
+ prime_clone();
} else if (starts_with(buf.buf, "push ")) {
parse_push(&buf);
@@ -1056,6 +1132,7 @@ int main(int argc, const char **argv)
printf("fetch\n");
printf("option\n");
printf("push\n");
+ printf("prime-clone\n");
printf("check-connectivity\n");
printf("\n");
fflush(stdout);
--
2.7.4
next prev parent reply other threads:[~2016-09-16 0:12 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-16 0:12 [PATCH 00/11] Resumable clone Kevin Wern
2016-09-16 0:12 ` [PATCH 01/11] Resumable clone: create service git-prime-clone Kevin Wern
2016-09-16 20:53 ` Junio C Hamano
2016-09-28 4:40 ` Kevin Wern
2016-09-16 0:12 ` [PATCH 02/11] Resumable clone: add prime-clone endpoints Kevin Wern
2016-09-19 13:15 ` Duy Nguyen
2016-09-28 4:43 ` Kevin Wern
2016-09-16 0:12 ` [PATCH 03/11] pkt-line: create gentle packet_read_line functions Kevin Wern
2016-09-16 22:17 ` Junio C Hamano
2016-09-28 4:42 ` Kevin Wern
2016-09-16 0:12 ` Kevin Wern [this message]
2016-09-19 13:52 ` [PATCH 04/11] Resumable clone: add prime-clone to remote-curl Duy Nguyen
2016-09-28 6:45 ` Kevin Wern
2016-09-16 0:12 ` [PATCH 05/11] Resumable clone: add output parsing to connect.c Kevin Wern
2016-09-16 0:12 ` [PATCH 06/11] Resumable clone: implement transport_prime_clone Kevin Wern
2016-09-16 0:12 ` [PATCH 07/11] Resumable clone: add resumable download to http/curl Kevin Wern
2016-09-16 22:45 ` Junio C Hamano
2016-09-28 6:41 ` Kevin Wern
2016-09-16 0:12 ` [PATCH 08/11] Resumable clone: create transport_download_primer Kevin Wern
2016-09-16 0:12 ` [PATCH 09/11] path: add resumable marker Kevin Wern
2016-09-19 13:24 ` Duy Nguyen
2016-09-16 0:12 ` [PATCH 10/11] run command: add RUN_COMMAND_NO_STDOUT Kevin Wern
2016-09-16 23:07 ` Junio C Hamano
2016-09-18 19:22 ` Johannes Schindelin
2016-09-28 4:46 ` Kevin Wern
2016-09-28 17:54 ` Junio C Hamano
2016-09-28 18:06 ` Kevin Wern
2016-09-16 0:12 ` [PATCH 11/11] Resumable clone: implement primer logic in git-clone Kevin Wern
2016-09-16 23:32 ` Junio C Hamano
2016-09-28 5:49 ` Kevin Wern
2016-09-19 14:04 ` Duy Nguyen
2016-09-19 17:16 ` Junio C Hamano
2016-09-28 4:44 ` Kevin Wern
2016-09-16 20:47 ` [PATCH 00/11] Resumable clone Junio C Hamano
2016-09-27 21:51 ` Eric Wong
2016-09-27 22:07 ` Junio C Hamano
2016-09-28 17:32 ` Junio C Hamano
2016-09-28 18:22 ` Junio C Hamano
2016-09-28 20:46 ` Eric Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1473984742-12516-5-git-send-email-kevin.m.wern@gmail.com \
--to=kevin.m.wern@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).