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 blockmaint
						commit
						9883ec2c73
					
				| 
						 | 
				
			
			@ -2123,6 +2123,35 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
 | 
			
		|||
#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 +2159,7 @@ static int add_ref_tag(const char *path, const struct object_id *oid, int flag,
 | 
			
		|||
	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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,58 +25,94 @@ test_expect_success setup '
 | 
			
		|||
	} >obj-list
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
rm -rf clone.git
 | 
			
		||||
test_expect_success 'pack without --include-tag' '
 | 
			
		||||
	packname_1=$(git pack-objects \
 | 
			
		||||
	packname=$(git pack-objects \
 | 
			
		||||
		--window=0 \
 | 
			
		||||
		test-1 <obj-list)
 | 
			
		||||
		test-no-include <obj-list)
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'unpack objects' '
 | 
			
		||||
	(
 | 
			
		||||
		GIT_DIR=clone.git &&
 | 
			
		||||
		export GIT_DIR &&
 | 
			
		||||
		git init &&
 | 
			
		||||
		git unpack-objects -n <test-1-${packname_1}.pack &&
 | 
			
		||||
		git unpack-objects <test-1-${packname_1}.pack
 | 
			
		||||
	)
 | 
			
		||||
	rm -rf clone.git &&
 | 
			
		||||
	git init clone.git &&
 | 
			
		||||
	git -C clone.git unpack-objects <test-no-include-${packname}.pack
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'check unpacked result (have commit, no tag)' '
 | 
			
		||||
	git rev-list --objects $commit >list.expect &&
 | 
			
		||||
	(
 | 
			
		||||
		test_must_fail env GIT_DIR=clone.git git cat-file -e $tag &&
 | 
			
		||||
		git rev-list --objects $commit
 | 
			
		||||
	) >list.actual &&
 | 
			
		||||
	test_must_fail git -C clone.git cat-file -e $tag &&
 | 
			
		||||
	git -C clone.git rev-list --objects $commit >list.actual &&
 | 
			
		||||
	test_cmp list.expect list.actual
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
rm -rf clone.git
 | 
			
		||||
test_expect_success 'pack with --include-tag' '
 | 
			
		||||
	packname_1=$(git pack-objects \
 | 
			
		||||
	packname=$(git pack-objects \
 | 
			
		||||
		--window=0 \
 | 
			
		||||
		--include-tag \
 | 
			
		||||
		test-2 <obj-list)
 | 
			
		||||
		test-include <obj-list)
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'unpack objects' '
 | 
			
		||||
	(
 | 
			
		||||
		GIT_DIR=clone.git &&
 | 
			
		||||
		export GIT_DIR &&
 | 
			
		||||
		git init &&
 | 
			
		||||
		git unpack-objects -n <test-2-${packname_1}.pack &&
 | 
			
		||||
		git unpack-objects <test-2-${packname_1}.pack
 | 
			
		||||
	)
 | 
			
		||||
	rm -rf clone.git &&
 | 
			
		||||
	git init clone.git &&
 | 
			
		||||
	git -C clone.git unpack-objects <test-include-${packname}.pack
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'check unpacked result (have commit, have tag)' '
 | 
			
		||||
	git rev-list --objects mytag >list.expect &&
 | 
			
		||||
	(
 | 
			
		||||
		GIT_DIR=clone.git &&
 | 
			
		||||
		export GIT_DIR &&
 | 
			
		||||
		git rev-list --objects $tag
 | 
			
		||||
	) >list.actual &&
 | 
			
		||||
	git -C clone.git rev-list --objects $tag >list.actual &&
 | 
			
		||||
	test_cmp list.expect list.actual
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
# A tag of a tag, where the "inner" tag is not otherwise
 | 
			
		||||
# reachable, and a full peel points to a commit reachable from HEAD.
 | 
			
		||||
test_expect_success 'create hidden inner tag' '
 | 
			
		||||
	test_commit commit &&
 | 
			
		||||
	git tag -m inner inner HEAD &&
 | 
			
		||||
	git tag -m outer outer inner &&
 | 
			
		||||
	git tag -d inner
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'pack explicit outer tag' '
 | 
			
		||||
	packname=$(
 | 
			
		||||
		{
 | 
			
		||||
			echo HEAD &&
 | 
			
		||||
			echo outer
 | 
			
		||||
		} |
 | 
			
		||||
		git pack-objects --revs test-hidden-explicit
 | 
			
		||||
	)
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'unpack objects' '
 | 
			
		||||
	rm -rf clone.git &&
 | 
			
		||||
	git init clone.git &&
 | 
			
		||||
	git -C clone.git unpack-objects <test-hidden-explicit-${packname}.pack
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'check unpacked result (have all objects)' '
 | 
			
		||||
	git -C clone.git rev-list --objects $(git rev-parse outer HEAD)
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'pack implied outer tag' '
 | 
			
		||||
	packname=$(
 | 
			
		||||
		echo HEAD |
 | 
			
		||||
		git pack-objects --revs --include-tag test-hidden-implied
 | 
			
		||||
	)
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'unpack objects' '
 | 
			
		||||
	rm -rf clone.git &&
 | 
			
		||||
	git init clone.git &&
 | 
			
		||||
	git -C clone.git unpack-objects <test-hidden-implied-${packname}.pack
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'check unpacked result (have all objects)' '
 | 
			
		||||
	git -C clone.git rev-list --objects $(git rev-parse outer HEAD)
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_expect_success 'single-branch clone can transfer tag' '
 | 
			
		||||
	rm -rf clone.git &&
 | 
			
		||||
	git clone --no-local --single-branch -b master . clone.git &&
 | 
			
		||||
	git -C clone.git fsck
 | 
			
		||||
'
 | 
			
		||||
 | 
			
		||||
test_done
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue