From: Junio C Hamano Date: Mon, 25 Mar 2013 21:01:02 +0000 (-0700) Subject: Merge branch 'jk/peel-ref' X-Git-Tag: v1.8.3-rc0~173 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/62bd0c01057b1cc47f4710090da4c84511f3cc3d?ds=inline;hp=-c Merge branch 'jk/peel-ref' Recent optimization broke shallow clones. * jk/peel-ref: upload-pack: load non-tip "want" objects from disk upload-pack: make sure "want" objects are parsed upload-pack: drop lookup-before-parse optimization --- 62bd0c01057b1cc47f4710090da4c84511f3cc3d diff --combined t/t5500-fetch-pack.sh index 354d32c584,e202383e4f..d574085696 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@@ -130,25 -130,16 +130,25 @@@ test_expect_success 'single given branc test_must_fail git --git-dir=branch-a/.git rev-parse origin/B ' +test_expect_success 'clone shallow depth 1' ' + git clone --no-single-branch --depth 1 "file://$(pwd)/." shallow0 && + test "`git --git-dir=shallow0/.git rev-list --count HEAD`" = 1 +' + test_expect_success 'clone shallow' ' git clone --no-single-branch --depth 2 "file://$(pwd)/." shallow ' +test_expect_success 'clone shallow depth count' ' + test "`git --git-dir=shallow/.git rev-list --count HEAD`" = 2 +' + test_expect_success 'clone shallow object count' ' ( cd shallow && git count-objects -v ) > count.shallow && - grep "^in-pack: 18" count.shallow + grep "^in-pack: 12" count.shallow ' test_expect_success 'clone shallow object count (part 2)' ' @@@ -265,36 -256,12 +265,36 @@@ test_expect_success 'additional simple ) ' +test_expect_success 'clone shallow depth count' ' + test "`git --git-dir=shallow/.git rev-list --count HEAD`" = 11 +' + test_expect_success 'clone shallow object count' ' ( cd shallow && git count-objects -v ) > count.shallow && - grep "^count: 52" count.shallow + grep "^count: 55" count.shallow +' + +test_expect_success 'fetch --no-shallow on full repo' ' + test_must_fail git fetch --noshallow +' + +test_expect_success 'fetch --depth --no-shallow' ' + ( + cd shallow && + test_must_fail git fetch --depth=1 --noshallow + ) +' + +test_expect_success 'turn shallow to complete repository' ' + ( + cd shallow && + git fetch --unshallow && + ! test -f .git/shallow && + git fsck --full + ) ' test_expect_success 'clone shallow without --no-single-branch' ' @@@ -306,7 -273,7 +306,7 @@@ test_expect_success 'clone shallow obje cd shallow2 && git count-objects -v ) > count.shallow2 && - grep "^in-pack: 6" count.shallow2 + grep "^in-pack: 3" count.shallow2 ' test_expect_success 'clone shallow with --branch' ' @@@ -314,7 -281,7 +314,7 @@@ ' test_expect_success 'clone shallow object count' ' - echo "in-pack: 6" > count3.expected && + echo "in-pack: 3" > count3.expected && GIT_DIR=shallow3/.git git count-objects -v | grep "^in-pack" > count3.actual && test_cmp count3.expected count3.actual @@@ -343,7 -310,7 +343,7 @@@ EO GIT_DIR=shallow6/.git git tag -l >taglist.actual && test_cmp taglist.expected taglist.actual && - echo "in-pack: 7" > count6.expected && + echo "in-pack: 4" > count6.expected && GIT_DIR=shallow6/.git git count-objects -v | grep "^in-pack" > count6.actual && test_cmp count6.expected count6.actual @@@ -358,12 -325,21 +358,21 @@@ EO GIT_DIR=shallow7/.git git tag -l >taglist.actual && test_cmp taglist.expected taglist.actual && - echo "in-pack: 7" > count7.expected && + echo "in-pack: 4" > count7.expected && GIT_DIR=shallow7/.git git count-objects -v | grep "^in-pack" > count7.actual && test_cmp count7.expected count7.actual ' + test_expect_success 'clone shallow with packed refs' ' + git pack-refs --all && + git clone --depth 1 --branch A "file://$(pwd)/." shallow8 && + echo "in-pack: 4" > count8.expected && + GIT_DIR=shallow8/.git git count-objects -v | + grep "^in-pack" > count8.actual && + test_cmp count8.expected count8.actual + ' + test_expect_success 'setup tests for the --stdin parameter' ' for head in C D E F do @@@ -424,55 -400,10 +433,55 @@@ test_expect_success 'fetch mixed refs f test_expect_success 'test duplicate refs from stdin' ' ( cd client && - test_must_fail git fetch-pack --stdin --no-progress .. <../input.dup + git fetch-pack --stdin --no-progress .. <../input.dup ) >output && cut -d " " -f 2 actual && test_cmp expect actual ' +test_expect_success 'set up tests of missing reference' ' + cat >expect-error <<-\EOF + error: no such remote ref refs/heads/xyzzy + EOF +' + +test_expect_success 'test lonely missing ref' ' + ( + cd client && + test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy + ) >/dev/null 2>error-m && + test_cmp expect-error error-m +' + +test_expect_success 'test missing ref after existing' ' + ( + cd client && + test_must_fail git fetch-pack --no-progress .. refs/heads/A refs/heads/xyzzy + ) >/dev/null 2>error-em && + test_cmp expect-error error-em +' + +test_expect_success 'test missing ref before existing' ' + ( + cd client && + test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy refs/heads/A + ) >/dev/null 2>error-me && + test_cmp expect-error error-me +' + +test_expect_success 'test --all, --depth, and explicit head' ' + ( + cd client && + git fetch-pack --no-progress --all --depth=1 .. refs/heads/A + ) >out-adh 2>error-adh +' + +test_expect_success 'test --all, --depth, and explicit tag' ' + git tag OLDTAG refs/heads/B~5 && + ( + cd client && + git fetch-pack --no-progress --all --depth=1 .. refs/tags/OLDTAG + ) >out-adt 2>error-adt +' + test_done diff --combined upload-pack.c index 35605310d2,6152a98757..f5673ee4c2 --- a/upload-pack.c +++ b/upload-pack.c @@@ -12,7 -12,6 +12,7 @@@ #include "run-command.h" #include "sigchain.h" #include "version.h" +#include "string-list.h" static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=] "; @@@ -26,15 -25,13 +26,15 @@@ #define SHALLOW (1u << 16) #define NOT_SHALLOW (1u << 17) #define CLIENT_SHALLOW (1u << 18) +#define HIDDEN_REF (1u << 19) static unsigned long oldest_have; -static int multi_ack, nr_our_refs; +static int multi_ack; static int no_done; static int use_thin_pack, use_ofs_delta, use_include_tag; static int no_progress, daemon_mode; +static int allow_tip_sha1_in_want; static int shallow_nr; static struct object_array have_obj; static struct object_array want_obj; @@@ -142,6 -139,7 +142,6 @@@ static void create_pack_file(void { struct async rev_list; struct child_process pack_objects; - int create_full_pack = (nr_our_refs == want_obj.nr && !have_obj.nr); char data[8193], progress[128]; char abort_msg[] = "aborting due to possible repository " "corruption on the remote side."; @@@ -153,7 -151,9 +153,7 @@@ argv[arg++] = "pack-objects"; if (!shallow_nr) { argv[arg++] = "--revs"; - if (create_full_pack) - argv[arg++] = "--all"; - else if (use_thin_pack) + if (use_thin_pack) argv[arg++] = "--thin"; } @@@ -185,15 -185,15 +185,15 @@@ } else { FILE *pipe_fd = xfdopen(pack_objects.in, "w"); - if (!create_full_pack) { - int i; - for (i = 0; i < want_obj.nr; i++) - fprintf(pipe_fd, "%s\n", sha1_to_hex(want_obj.objects[i].item->sha1)); - fprintf(pipe_fd, "--not\n"); - for (i = 0; i < have_obj.nr; i++) - fprintf(pipe_fd, "%s\n", sha1_to_hex(have_obj.objects[i].item->sha1)); - } + int i; + for (i = 0; i < want_obj.nr; i++) + fprintf(pipe_fd, "%s\n", + sha1_to_hex(want_obj.objects[i].item->sha1)); + fprintf(pipe_fd, "--not\n"); + for (i = 0; i < have_obj.nr; i++) + fprintf(pipe_fd, "%s\n", + sha1_to_hex(have_obj.objects[i].item->sha1)); fprintf(pipe_fd, "\n"); fflush(pipe_fd); fclose(pipe_fd); @@@ -327,9 -327,7 +327,7 @@@ static int got_sha1(char *hex, unsigne if (!has_sha1_file(sha1)) return -1; - o = lookup_object(sha1); - if (!(o && o->parsed)) - o = parse_object(sha1); + o = parse_object(sha1); if (!o) die("oops (%s)", sha1_to_hex(sha1)); if (o->type == OBJ_COMMIT) { @@@ -489,12 -487,6 +487,12 @@@ static int get_common_commits(void } } +static int is_our_ref(struct object *o) +{ + return o->flags & + ((allow_tip_sha1_in_want ? HIDDEN_REF : 0) | OUR_REF); +} + static void check_non_tip(void) { static const char *argv[] = { @@@ -531,7 -523,7 +529,7 @@@ o = get_indexed_object(--i); if (!o) continue; - if (!(o->flags & OUR_REF)) + if (!is_our_ref(o)) continue; memcpy(namebuf + 1, sha1_to_hex(o->sha1), 40); if (write_in_full(cmd.in, namebuf, 42) < 0) @@@ -540,7 -532,7 +538,7 @@@ namebuf[40] = '\n'; for (i = 0; i < want_obj.nr; i++) { o = want_obj.objects[i].item; - if (o->flags & OUR_REF) + if (is_our_ref(o)) continue; memcpy(namebuf, sha1_to_hex(o->sha1), 40); if (write_in_full(cmd.in, namebuf, 41) < 0) @@@ -574,7 -566,7 +572,7 @@@ error /* Pick one of them (we know there at least is one) */ for (i = 0; i < want_obj.nr; i++) { o = want_obj.objects[i].item; - if (!(o->flags & OUR_REF)) + if (!is_our_ref(o)) die("git upload-pack: not our ref %s", sha1_to_hex(o->sha1)); } @@@ -609,8 -601,6 +607,8 @@@ static void receive_needs(void object = parse_object(sha1); if (!object) die("did not find object for %s", line); + if (object->type != OBJ_COMMIT) + die("invalid shallow object %s", sha1_to_hex(sha1)); object->flags |= CLIENT_SHALLOW; add_object_array(object, NULL, &shallows); continue; @@@ -648,13 -638,13 +646,13 @@@ if (parse_feature_request(features, "include-tag")) use_include_tag = 1; - o = lookup_object(sha1_buf); + o = parse_object(sha1_buf); if (!o) die("git upload-pack: not our ref %s", sha1_to_hex(sha1_buf)); if (!(o->flags & WANTED)) { o->flags |= WANTED; - if (!(o->flags & OUR_REF)) + if (!is_our_ref(o)) has_non_tip = 1; add_object_array(o, NULL, &want_obj); } @@@ -678,17 -668,10 +676,17 @@@ if (depth == 0 && shallows.nr == 0) return; if (depth > 0) { - struct commit_list *result, *backup; + struct commit_list *result = NULL, *backup = NULL; int i; - backup = result = get_shallow_commits(&want_obj, depth, - SHALLOW, NOT_SHALLOW); + if (depth == INFINITE_DEPTH) + for (i = 0; i < shallows.nr; i++) { + struct object *object = shallows.objects[i].item; + object->flags |= NOT_SHALLOW; + } + else + backup = result = + get_shallow_commits(&want_obj, depth, + SHALLOW, NOT_SHALLOW); while (result) { struct object *object = &result->item->object; if (!(object->flags & (CLIENT_SHALLOW|NOT_SHALLOW))) { @@@ -735,47 -718,45 +733,47 @@@ free(shallows.objects); } +/* return non-zero if the ref is hidden, otherwise 0 */ +static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data) +{ + struct object *o = lookup_unknown_object(sha1); + + if (ref_is_hidden(refname)) { + o->flags |= HIDDEN_REF; + return 1; + } + if (!o) + die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1)); + o->flags |= OUR_REF; + return 0; +} + static int send_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data) { static const char *capabilities = "multi_ack thin-pack side-band" " side-band-64k ofs-delta shallow no-progress" " include-tag multi_ack_detailed"; - struct object *o = lookup_unknown_object(sha1); const char *refname_nons = strip_namespace(refname); unsigned char peeled[20]; + if (mark_our_ref(refname, sha1, flag, cb_data)) + return 0; + if (capabilities) - packet_write(1, "%s %s%c%s%s agent=%s\n", + packet_write(1, "%s %s%c%s%s%s agent=%s\n", sha1_to_hex(sha1), refname_nons, 0, capabilities, + allow_tip_sha1_in_want ? " allow-tip-sha1-in-want" : "", stateless_rpc ? " no-done" : "", git_user_agent_sanitized()); else packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname_nons); capabilities = NULL; - if (!(o->flags & OUR_REF)) { - o->flags |= OUR_REF; - nr_our_refs++; - } if (!peel_ref(refname, peeled)) packet_write(1, "%s %s^{}\n", sha1_to_hex(peeled), refname_nons); return 0; } -static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data) -{ - struct object *o = parse_object(sha1); - if (!o) - die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1)); - if (!(o->flags & OUR_REF)) { - o->flags |= OUR_REF; - nr_our_refs++; - } - return 0; -} - static void upload_pack(void) { if (advertise_refs || !stateless_rpc) { @@@ -797,13 -778,6 +795,13 @@@ } } +static int upload_pack_config(const char *var, const char *value, void *unused) +{ + if (!strcmp("uploadpack.allowtipsha1inwant", var)) + allow_tip_sha1_in_want = git_config_bool(var, value); + return parse_hide_refs_config(var, value, "uploadpack"); +} + int main(int argc, char **argv) { char *dir; @@@ -855,7 -829,6 +853,7 @@@ die("'%s' does not appear to be a git repository", dir); if (is_repository_shallow()) die("attempt to fetch/clone from a shallow repository"); + git_config(upload_pack_config, NULL); if (getenv("GIT_DEBUG_SEND_PACK")) debug_fd = atoi(getenv("GIT_DEBUG_SEND_PACK")); upload_pack();