From 16094885ca94f72abc28a915f9aa4021e203a16d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Thu, 5 Dec 2013 20:02:50 +0700 Subject: [PATCH] smart-http: support shallow fetch/clone MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- Documentation/gitremote-helpers.txt | 7 +++++++ builtin/fetch-pack.c | 16 +++++++++++++--- remote-curl.c | 32 ++++++++++++++++++++++++++++---- t/t5537-fetch-shallow.sh | 27 +++++++++++++++++++++++++++ transport-helper.c | 6 ++++++ upload-pack.c | 2 -- 6 files changed, 81 insertions(+), 9 deletions(-) diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt index f1f4ca9727..c2908db763 100644 --- a/Documentation/gitremote-helpers.txt +++ b/Documentation/gitremote-helpers.txt @@ -437,6 +437,13 @@ set by Git if the remote helper has the 'option' capability. 'option check-connectivity' \{'true'|'false'\}:: Request the helper to check connectivity of a clone. +'option cloning \{'true'|'false'\}:: + Notify the helper this is a clone request (i.e. the current + repository is guaranteed empty). + +'option update-shallow \{'true'|'false'\}:: + Allow to extend .git/shallow if the new refs require it. + SEE ALSO -------- linkgit:git-remote[1] diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index aa6e5967e7..81fae380e8 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -3,6 +3,7 @@ #include "fetch-pack.h" #include "remote.h" #include "connect.h" +#include "sha1-array.h" static const char fetch_pack_usage[] = "git fetch-pack [--all] [--stdin] [--quiet|-q] [--keep|-k] [--thin] " @@ -46,6 +47,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) char **pack_lockfile_ptr = NULL; struct child_process *conn; struct fetch_pack_args args; + struct sha1_array shallow = SHA1_ARRAY_INIT; packet_trace_identity("fetch-pack"); @@ -113,6 +115,14 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) args.check_self_contained_and_connected = 1; continue; } + if (!strcmp("--cloning", arg)) { + args.cloning = 1; + continue; + } + if (!strcmp("--update-shallow", arg)) { + args.update_shallow = 1; + continue; + } usage(fetch_pack_usage); } @@ -157,10 +167,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) args.verbose ? CONNECT_VERBOSE : 0); } - get_remote_heads(fd[0], NULL, 0, &ref, 0, NULL, NULL); + get_remote_heads(fd[0], NULL, 0, &ref, 0, NULL, &shallow); - ref = fetch_pack(&args, fd, conn, ref, dest, - sought, nr_sought, NULL, pack_lockfile_ptr); + ref = fetch_pack(&args, fd, conn, ref, dest, sought, nr_sought, + &shallow, pack_lockfile_ptr); if (pack_lockfile) { printf("lock %s\n", pack_lockfile); fflush(stdout); diff --git a/remote-curl.c b/remote-curl.c index 25d67308c3..d1fc163e5e 100644 --- a/remote-curl.c +++ b/remote-curl.c @@ -10,6 +10,7 @@ #include "sideband.h" #include "argv-array.h" #include "credential.h" +#include "sha1-array.h" static struct remote *remote; /* always ends with a trailing slash */ @@ -20,6 +21,8 @@ struct options { unsigned long depth; unsigned progress : 1, check_self_contained_and_connected : 1, + cloning : 1, + update_shallow : 1, followtags : 1, dry_run : 1, thin : 1; @@ -87,8 +90,23 @@ static int set_option(const char *name, const char *value) string_list_append(&cas_options, val.buf); strbuf_release(&val); return 0; - } - else { + } else if (!strcmp(name, "cloning")) { + if (!strcmp(value, "true")) + options.cloning = 1; + else if (!strcmp(value, "false")) + options.cloning = 0; + else + return -1; + return 0; + } else if (!strcmp(name, "update-shallow")) { + if (!strcmp(value, "true")) + options.update_shallow = 1; + else if (!strcmp(value, "false")) + options.update_shallow = 0; + else + return -1; + return 0; + } else { return 1 /* unsupported */; } } @@ -99,6 +117,7 @@ struct discovery { char *buf; size_t len; struct ref *refs; + struct sha1_array shallow; unsigned proto_git : 1; }; static struct discovery *last_discovery; @@ -107,7 +126,7 @@ static struct ref *parse_git_refs(struct discovery *heads, int for_push) { struct ref *list = NULL; get_remote_heads(-1, heads->buf, heads->len, &list, - for_push ? REF_NORMAL : 0, NULL, NULL); + for_push ? REF_NORMAL : 0, NULL, &heads->shallow); return list; } @@ -168,6 +187,7 @@ static void free_discovery(struct discovery *d) if (d) { if (d == last_discovery) last_discovery = NULL; + free(d->shallow.sha1); free(d->buf_alloc); free_refs(d->refs); free(d); @@ -688,7 +708,7 @@ static int fetch_git(struct discovery *heads, struct strbuf preamble = STRBUF_INIT; char *depth_arg = NULL; int argc = 0, i, err; - const char *argv[16]; + const char *argv[17]; argv[argc++] = "fetch-pack"; argv[argc++] = "--stateless-rpc"; @@ -704,6 +724,10 @@ static int fetch_git(struct discovery *heads, } if (options.check_self_contained_and_connected) argv[argc++] = "--check-self-contained-and-connected"; + if (options.cloning) + argv[argc++] = "--cloning"; + if (options.update_shallow) + argv[argc++] = "--update-shallow"; if (!options.progress) argv[argc++] = "--no-progress"; if (options.depth) { diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh index 3ae9092f5c..79ce47287b 100755 --- a/t/t5537-fetch-shallow.sh +++ b/t/t5537-fetch-shallow.sh @@ -173,4 +173,31 @@ EOF ) ' +if test -n "$NO_CURL" -o -z "$GIT_TEST_HTTPD"; then + say 'skipping remaining tests, git built without http support' + test_done +fi + +LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5536'} +. "$TEST_DIRECTORY"/lib-httpd.sh +start_httpd + +test_expect_success 'clone http repository' ' + git clone --bare --no-local shallow "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + git clone $HTTPD_URL/smart/repo.git clone && + ( + cd clone && + git fsck && + git log --format=%s origin/master >actual && + cat <expect && +6 +5 +4 +3 +EOF + test_cmp expect actual + ) +' + +stop_httpd test_done diff --git a/transport-helper.c b/transport-helper.c index 673b7c214f..e2b4203159 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -360,6 +360,12 @@ static int fetch_with_fetch(struct transport *transport, data->transport_options.check_self_contained_and_connected) set_helper_option(transport, "check-connectivity", "true"); + if (transport->cloning) + set_helper_option(transport, "cloning", "true"); + + if (data->transport_options.update_shallow) + set_helper_option(transport, "update-shallow", "true"); + for (i = 0; i < nr_heads; i++) { const struct ref *posn = to_fetch[i]; if (posn->status & REF_STATUS_UPTODATE) diff --git a/upload-pack.c b/upload-pack.c index 28269c7462..2d022978a8 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -836,8 +836,6 @@ int main(int argc, char **argv) if (!enter_repo(dir, strict)) die("'%s' does not appear to be a git repository", dir); - if (is_repository_shallow() && stateless_rpc) - die("attempt to push into a shallow repository"); git_config(upload_pack_config, NULL); upload_pack(); -- 2.11.4.GIT