From: Junio C Hamano Date: Mon, 9 Sep 2013 21:30:01 +0000 (-0700) Subject: Merge branch 'nd/clone-connectivity-shortcut' X-Git-Tag: v1.8.5-rc0~172 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/711b2769740637e228c8200927e96b31f2065d32?ds=inline;hp=-c Merge branch 'nd/clone-connectivity-shortcut' * nd/clone-connectivity-shortcut: smart http: use the same connectivity check on cloning --- 711b2769740637e228c8200927e96b31f2065d32 diff --combined Documentation/git-fetch-pack.txt index 1e71754347,461a632fb7..444b805d35 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@@ -10,9 -10,9 +10,9 @@@ SYNOPSI -------- [verse] 'git fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] - [--upload-pack=] - [--depth=] [--no-progress] - [-v] [:] [...] + [--upload-pack=] + [--depth=] [--no-progress] + [-v] [:] [...] DESCRIPTION ----------- @@@ -90,6 -90,10 +90,10 @@@ be in a separate packet, and the list m --no-progress:: Do not show the progress. + --check-self-contained-and-connected:: + Output "connectivity-ok" if the received pack is + self-contained and connected. + -v:: Run verbosely. diff --combined Documentation/gitremote-helpers.txt index 0827f69139,e33bd6a716..bc069c23df --- a/Documentation/gitremote-helpers.txt +++ b/Documentation/gitremote-helpers.txt @@@ -143,6 -143,10 +143,10 @@@ Supported commands: 'list', 'fetch' + Supported commands: 'list', 'import'. + 'check-connectivity':: + Can guarantee that when a clone is requested, the received + pack is self contained and is connected. + If a helper advertises 'connect', Git will use it if possible and fall back to another capability if the helper requests so when connecting (see the 'connect' command under COMMANDS). @@@ -159,11 -163,11 +163,11 @@@ Miscellaneous capabilitie carried out. 'refspec' :: - This modifies the 'import' capability, allowing the produced - fast-import stream to modify refs in a private namespace - instead of writing to refs/heads or refs/remotes directly. + For remote helpers that implement 'import' or 'export', this capability + allows the refs to be constrained to a private namespace, instead of + writing to refs/heads or refs/remotes directly. It is recommended that all importers providing the 'import' - capability use this. + capability use this. It's mandatory for 'export'. + A helper advertising the capability `refspec refs/heads/*:refs/svn/origin/branches/*` @@@ -174,8 -178,8 +178,8 @@@ ref This capability can be advertised multiple times. The first applicable refspec takes precedence. The left-hand of refspecs advertised with this capability must cover all refs reported by -the list command. If a helper does not need a specific 'refspec' -capability then it should advertise `refspec *:*`. +the list command. If no 'refspec' capability is advertised, +there is an implied `refspec *:*`. 'bidi-import':: This modifies the 'import' capability. @@@ -270,6 -274,9 +274,9 @@@ Optionally may output a 'lock ' l GIT_DIR/objects/pack which is keeping a pack until refs can be suitably updated. + + If option 'check-connectivity' is requested, the helper must output + 'connectivity-ok' if the clone is self-contained and connected. + + Supported if the helper has the "fetch" capability. 'push' +::: @@@ -416,6 -423,9 +423,9 @@@ set by Git if the remote helper has th must not rely on this option being set before connect request occurs. + 'option check-connectivity' \{'true'|'false'\}:: + Request the helper to check connectivity of a clone. + SEE ALSO -------- linkgit:git-remote[1] diff --combined remote-curl.c index 5b3ce9eed2,c3157e877b..6918668dc2 --- a/remote-curl.c +++ b/remote-curl.c @@@ -7,7 -7,6 +7,7 @@@ #include "run-command.h" #include "pkt-line.h" #include "sideband.h" +#include "argv-array.h" static struct remote *remote; static const char *url; /* always ends with a trailing slash */ @@@ -16,6 -15,7 +16,7 @@@ struct options int verbosity; unsigned long depth; unsigned progress : 1, + check_self_contained_and_connected : 1, followtags : 1, dry_run : 1, thin : 1; @@@ -67,6 -67,15 +68,15 @@@ static int set_option(const char *name return -1; return 0; } + else if (!strcmp(name, "check-connectivity")) { + if (!strcmp(value, "true")) + options.check_self_contained_and_connected = 1; + else if (!strcmp(value, "false")) + options.check_self_contained_and_connected = 0; + else + return -1; + return 0; + } else { return 1 /* unsupported */; } @@@ -654,7 -663,7 +664,7 @@@ static int fetch_git(struct discovery * struct strbuf preamble = STRBUF_INIT; char *depth_arg = NULL; int argc = 0, i, err; - const char *argv[15]; + const char *argv[16]; argv[argc++] = "fetch-pack"; argv[argc++] = "--stateless-rpc"; @@@ -668,6 -677,8 +678,8 @@@ argv[argc++] = "-v"; argv[argc++] = "-v"; } + if (options.check_self_contained_and_connected) + argv[argc++] = "--check-self-contained-and-connected"; if (!options.progress) argv[argc++] = "--no-progress"; if (options.depth) { @@@ -788,35 -799,36 +800,35 @@@ static int push_dav(int nr_spec, char * static int push_git(struct discovery *heads, int nr_spec, char **specs) { struct rpc_state rpc; - const char **argv; - int argc = 0, i, err; + int i, err; + struct argv_array args; + + argv_array_init(&args); + argv_array_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status", + NULL); - argv = xmalloc((10 + nr_spec) * sizeof(char*)); - argv[argc++] = "send-pack"; - argv[argc++] = "--stateless-rpc"; - argv[argc++] = "--helper-status"; if (options.thin) - argv[argc++] = "--thin"; + argv_array_push(&args, "--thin"); if (options.dry_run) - argv[argc++] = "--dry-run"; + argv_array_push(&args, "--dry-run"); if (options.verbosity == 0) - argv[argc++] = "--quiet"; + argv_array_push(&args, "--quiet"); else if (options.verbosity > 1) - argv[argc++] = "--verbose"; - argv[argc++] = options.progress ? "--progress" : "--no-progress"; - argv[argc++] = url; + argv_array_push(&args, "--verbose"); + argv_array_push(&args, options.progress ? "--progress" : "--no-progress"); + argv_array_push(&args, url); for (i = 0; i < nr_spec; i++) - argv[argc++] = specs[i]; - argv[argc++] = NULL; + argv_array_push(&args, specs[i]); memset(&rpc, 0, sizeof(rpc)); rpc.service_name = "git-receive-pack", - rpc.argv = argv; + rpc.argv = args.argv; err = rpc_service(&rpc, heads); if (rpc.result.len) write_or_die(1, rpc.result.buf, rpc.result.len); strbuf_release(&rpc.result); - free(argv); + argv_array_clear(&args); return err; } @@@ -939,6 -951,7 +951,7 @@@ int main(int argc, const char **argv printf("fetch\n"); printf("option\n"); printf("push\n"); + printf("check-connectivity\n"); printf("\n"); fflush(stdout); } else { diff --combined transport-helper.c index 63cabc37e3,fe1b7021d7..bec3b721fa --- a/transport-helper.c +++ b/transport-helper.c @@@ -11,7 -11,6 +11,7 @@@ #include "thread-utils.h" #include "sigchain.h" #include "argv-array.h" +#include "refs.h" static int debug; @@@ -27,6 -26,7 +27,7 @@@ struct helper_data push : 1, connect : 1, signed_tags : 1, + check_connectivity : 1, no_disconnect_req : 1; char *export_marks; char *import_marks; @@@ -48,7 -48,7 +49,7 @@@ static void sendline(struct helper_dat die_errno("Full write to remote helper failed"); } -static int recvline_fh(FILE *helper, struct strbuf *buffer) +static int recvline_fh(FILE *helper, struct strbuf *buffer, const char *name) { strbuf_reset(buffer); if (debug) @@@ -66,7 -66,7 +67,7 @@@ static int recvline(struct helper_data *helper, struct strbuf *buffer) { - return recvline_fh(helper->out, buffer); + return recvline_fh(helper->out, buffer, helper->name); } static void xchgline(struct helper_data *helper, struct strbuf *buffer) @@@ -186,6 -186,8 +187,8 @@@ static struct child_process *get_helper data->bidi_import = 1; else if (!strcmp(capname, "export")) data->export = 1; + else if (!strcmp(capname, "check-connectivity")) + data->check_connectivity = 1; else if (!data->refspecs && !prefixcmp(capname, "refspec ")) { ALLOC_GROW(refspecs, refspec_nr + 1, @@@ -218,8 -220,6 +221,8 @@@ for (i = 0; i < refspec_nr; i++) free((char *)refspecs[i]); free(refspecs); + } else if (data->import || data->bidi_import || data->export) { + warning("This remote helper should implement refspec capability."); } strbuf_release(&buf); if (debug) @@@ -349,6 -349,9 +352,9 @@@ static int fetch_with_fetch(struct tran struct strbuf buf = STRBUF_INIT; standard_options(transport); + if (data->check_connectivity && + data->transport_options.check_self_contained_and_connected) + set_helper_option(transport, "check-connectivity", "true"); for (i = 0; i < nr_heads; i++) { const struct ref *posn = to_fetch[i]; @@@ -372,6 -375,10 +378,10 @@@ else transport->pack_lockfile = xstrdup(name); } + else if (data->check_connectivity && + data->transport_options.check_self_contained_and_connected && + !strcmp(buf.buf, "connectivity-ok")) + data->transport_options.self_contained_and_connected = 1; else if (!buf.len) break; else @@@ -476,7 -483,7 +486,7 @@@ static int fetch_with_import(struct tra * were fetching. * * (If no "refspec" capability was specified, for historical - * reasons we default to *:*.) + * reasons we default to the equivalent of *:*.) * * Store the result in to_fetch[i].old_sha1. Callers such * as "git fetch" can use the value to write feedback to the @@@ -543,7 -550,7 +553,7 @@@ static int process_connect_service(stru goto exit; sendline(data, &cmdbuf); - recvline_fh(input, &cmdbuf); + recvline_fh(input, &cmdbuf, name); if (!strcmp(cmdbuf.buf, "")) { data->no_disconnect_req = 1; if (debug) @@@ -625,7 -632,7 +635,7 @@@ static int fetch(struct transport *tran return -1; } -static void push_update_ref_status(struct strbuf *buf, +static int push_update_ref_status(struct strbuf *buf, struct ref **ref, struct ref *remote_refs) { @@@ -691,7 -698,7 +701,7 @@@ *ref = find_ref_by_name(remote_refs, refname); if (!*ref) { warning("helper reported unexpected status of %s", refname); - return; + return 1; } if ((*ref)->status != REF_STATUS_NONE) { @@@ -700,12 -707,11 +710,12 @@@ * status reported by the remote helper if the latter is 'no match'. */ if (status == REF_STATUS_NONE) - return; + return 1; } (*ref)->status = status; (*ref)->remote_status = msg; + return !(status == REF_STATUS_OK); } static void push_update_refs_status(struct helper_data *data, @@@ -714,24 -720,11 +724,24 @@@ struct strbuf buf = STRBUF_INIT; struct ref *ref = remote_refs; for (;;) { + char *private; + recvline(data, &buf); if (!buf.len) break; - push_update_ref_status(&buf, &ref, remote_refs); + if (push_update_ref_status(&buf, &ref, remote_refs)) + continue; + + if (!data->refspecs) + continue; + + /* propagate back the update to the remote namespace */ + private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name); + if (!private) + continue; + update_ref("update by helper", private, ref->new_sha1, NULL, 0, 0); + free(private); } strbuf_release(&buf); } @@@ -806,14 -799,6 +816,14 @@@ static int push_refs_with_export(struc struct string_list revlist_args = STRING_LIST_INIT_NODUP; struct strbuf buf = STRBUF_INIT; + if (!data->refspecs) + die("remote-helper doesn't support push; refspec needed"); + + if (flags & TRANSPORT_PUSH_DRY_RUN) { + if (set_helper_option(transport, "dry-run", "true") != 0) + die("helper %s does not support dry-run", data->name); + } + helper = get_helper(transport); write_constant(helper->in, "export\n"); @@@ -824,9 -809,8 +834,9 @@@ char *private; unsigned char sha1[20]; - if (!data->refspecs) - continue; + if (ref->deletion) + die("remote-helpers do not support ref deletion"); + private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name); if (private && !get_sha1(private, sha1)) { strbuf_addf(&buf, "^%s", private); @@@ -835,14 -819,13 +845,14 @@@ } free(private); - if (ref->deletion) { + if (ref->deletion) die("remote-helpers do not support ref deletion"); - } - if (ref->peer_ref) + if (ref->peer_ref) { + if (strcmp(ref->peer_ref->name, ref->name)) + die("remote-helpers do not support old:new syntax"); string_list_append(&revlist_args, ref->peer_ref->name); - + } } if (get_exporter(transport, &exporter, &revlist_args)) @@@ -982,7 -965,6 +992,7 @@@ int transport_helper_init(struct transp #define PBUFFERSIZE 8192 /* Print bidirectional transfer loop debug message. */ +__attribute__((format (printf, 1, 2))) static void transfer_debug(const char *fmt, ...) { va_list args; @@@ -1068,7 -1050,7 +1078,7 @@@ static int udt_do_read(struct unidirect return -1; } else if (bytes == 0) { transfer_debug("%s EOF (with %i bytes in buffer)", - t->src_name, t->bufuse); + t->src_name, (int)t->bufuse); t->state = SSTATE_FLUSHING; } else if (bytes > 0) { t->bufuse += bytes; @@@ -1132,7 -1114,7 +1142,7 @@@ static void *udt_copy_task_routine(voi #ifndef NO_PTHREADS /* - * Join thread, with apporiate errors on failure. Name is name for the + * Join thread, with appropriate errors on failure. Name is name for the * thread (for error messages). Returns 0 on success, 1 on failure. */ static int tloop_join(pthread_t thread, const char *name) @@@ -1198,7 -1180,7 +1208,7 @@@ static void udt_kill_transfer(struct un } /* - * Join process, with apporiate errors on failure. Name is name for the + * Join process, with appropriate errors on failure. Name is name for the * process (for error messages). Returns 0 on success, 1 on failure. */ static int tloop_join(pid_t pid, const char *name)