From: Junio C Hamano Date: Thu, 15 Sep 2016 21:11:14 +0000 (-0700) Subject: Merge branch 'jk/pack-tag-of-tag' X-Git-Tag: v2.11.0-rc0~152 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/9883ec2c73e15dfe148d05ea078897cbe73e3480?hp=-c Merge branch 'jk/pack-tag-of-tag' "git pack-objects --include-tag" was taught that when we know that we are sending an object C, we want a tag B that directly points at C but also a tag A that points at the tag B. We used to miss the intermediate tag B in some cases. * jk/pack-tag-of-tag: pack-objects: walk tag chains for --include-tag t5305: simplify packname handling t5305: use "git -C" t5305: drop "dry-run" of unpack-objects t5305: move cleanup into test block --- 9883ec2c73e15dfe148d05ea078897cbe73e3480 diff --combined builtin/pack-objects.c index 4a63398960,ea5367e45d..0954375be9 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@@ -44,9 -44,7 +44,9 @@@ static int non_empty static int reuse_delta = 1, reuse_object = 1; static int keep_unreachable, unpack_unreachable, include_tag; static unsigned long unpack_unreachable_expiration; +static int pack_loose_unreachable; static int local; +static int have_non_local_packs; static int incremental; static int ignore_packed_keep; static int allow_ofs_delta; @@@ -979,23 -977,6 +979,23 @@@ static int want_object_in_pack(const un return 1; if (incremental) return 0; + + /* + * When asked to do --local (do not include an + * object that appears in a pack we borrow + * from elsewhere) or --honor-pack-keep (do not + * include an object that appears in a pack marked + * with .keep), we need to make sure no copy of this + * object come from in _any_ pack that causes us to + * omit it, and need to complete this loop. When + * neither option is in effect, we know the object + * we just found is going to be packed, so break + * out of the loop to return 1 now. + */ + if (!ignore_packed_keep && + (!local || !have_non_local_packs)) + break; + if (local && !p->pack_local) return 0; if (ignore_packed_keep && p->pack_local && p->pack_keep) @@@ -2123,6 -2104,35 +2123,35 @@@ static void ll_find_deltas(struct objec #define ll_find_deltas(l, s, w, d, p) find_deltas(l, &s, w, d, p) #endif + static void add_tag_chain(const struct object_id *oid) + { + struct tag *tag; + + /* + * We catch duplicates already in add_object_entry(), but we'd + * prefer to do this extra check to avoid having to parse the + * tag at all if we already know that it's being packed (e.g., if + * it was included via bitmaps, we would not have parsed it + * previously). + */ + if (packlist_find(&to_pack, oid->hash, NULL)) + return; + + tag = lookup_tag(oid->hash); + while (1) { + if (!tag || parse_tag(tag) || !tag->tagged) + die("unable to pack objects reachable from tag %s", + oid_to_hex(oid)); + + add_object_entry(tag->object.oid.hash, OBJ_TAG, NULL, 0); + + if (tag->tagged->type != OBJ_TAG) + return; + + tag = (struct tag *)tag->tagged; + } + } + static int add_ref_tag(const char *path, const struct object_id *oid, int flag, void *cb_data) { struct object_id peeled; @@@ -2130,7 -2140,7 +2159,7 @@@ if (starts_with(path, "refs/tags/") && /* is a tag? */ !peel_ref(path, peeled.hash) && /* peelable? */ packlist_find(&to_pack, peeled.hash, NULL)) /* object packed? */ - add_object_entry(oid->hash, OBJ_TAG, NULL, 0); + add_tag_chain(oid); return 0; } @@@ -2398,32 -2408,6 +2427,32 @@@ static void add_objects_in_unpacked_pac free(in_pack.array); } +static int add_loose_object(const unsigned char *sha1, const char *path, + void *data) +{ + enum object_type type = sha1_object_info(sha1, NULL); + + if (type < 0) { + warning("loose object at %s could not be examined", path); + return 0; + } + + add_object_entry(sha1, type, "", 0); + return 0; +} + +/* + * We actually don't even have to worry about reachability here. + * add_object_entry will weed out duplicates, so we just add every + * loose object we find. + */ +static void add_unreachable_loose_objects(void) +{ + for_each_loose_file_in_objdir(get_object_directory(), + add_loose_object, + NULL, NULL, NULL); +} + static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1) { static struct packed_git *last_found = (void *)1; @@@ -2593,8 -2577,6 +2622,8 @@@ static void get_object_list(int ac, con if (keep_unreachable) add_objects_in_unpacked_packs(&revs); + if (pack_loose_unreachable) + add_unreachable_loose_objects(); if (unpack_unreachable) loosen_unused_packed_objects(&revs); @@@ -2695,8 -2677,6 +2724,8 @@@ int cmd_pack_objects(int argc, const ch N_("include tag objects that refer to objects to be packed")), OPT_BOOL(0, "keep-unreachable", &keep_unreachable, N_("keep unreachable objects")), + OPT_BOOL(0, "pack-loose-unreachable", &pack_loose_unreachable, + N_("pack loose unreachable objects")), { OPTION_CALLBACK, 0, "unpack-unreachable", NULL, N_("time"), N_("unpack unreachable objects newer than