diff options
| author | Junio C Hamano <gitster@pobox.com> | 2011-08-28 21:18:47 -0700 | 
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2011-08-28 21:18:47 -0700 | 
| commit | 45792b64c1752d1b6736d0f49a8e4a003e458756 (patch) | |
| tree | 212efd8a613c7a820666a1eda1bb9eba1117d5ab | |
| parent | 0b98954975502f56f1de2a4cb0569f7e80fd44d0 (diff) | |
| parent | 8fb3ad76b1782a5439343b9601f73a9287a245cf (diff) | |
Merge branch 'di/fast-import-deltified-tree'
* di/fast-import-deltified-tree:
  fast-import: prevent producing bad delta
  fast-import: add a test for tree delta base corruption
| -rw-r--r-- | fast-import.c | 35 | ||||
| -rwxr-xr-x | t/t9300-fast-import.sh | 41 | 
2 files changed, 71 insertions, 5 deletions
| diff --git a/fast-import.c b/fast-import.c index 6d491b92fe..016d2456f6 100644 --- a/fast-import.c +++ b/fast-import.c @@ -170,6 +170,11 @@ Format of STDIN stream:  #define DEPTH_BITS 13  #define MAX_DEPTH ((1<<DEPTH_BITS)-1) +/* + * We abuse the setuid bit on directories to mean "do not delta". + */ +#define NO_DELTA S_ISUID +  struct object_entry {  	struct pack_idx_entry idx;  	struct object_entry *next; @@ -1416,8 +1421,9 @@ static void mktree(struct tree_content *t, int v, struct strbuf *b)  		struct tree_entry *e = t->entries[i];  		if (!e->versions[v].mode)  			continue; -		strbuf_addf(b, "%o %s%c", (unsigned int)e->versions[v].mode, -					e->name->str_dat, '\0'); +		strbuf_addf(b, "%o %s%c", +			(unsigned int)(e->versions[v].mode & ~NO_DELTA), +			e->name->str_dat, '\0');  		strbuf_add(b, e->versions[v].sha1, 20);  	}  } @@ -1427,7 +1433,7 @@ static void store_tree(struct tree_entry *root)  	struct tree_content *t = root->tree;  	unsigned int i, j, del;  	struct last_object lo = { STRBUF_INIT, 0, 0, /* no_swap */ 1 }; -	struct object_entry *le; +	struct object_entry *le = NULL;  	if (!is_null_sha1(root->versions[1].sha1))  		return; @@ -1437,7 +1443,8 @@ static void store_tree(struct tree_entry *root)  			store_tree(t->entries[i]);  	} -	le = find_object(root->versions[0].sha1); +	if (!(root->versions[0].mode & NO_DELTA)) +		le = find_object(root->versions[0].sha1);  	if (S_ISDIR(root->versions[0].mode) && le && le->pack_id == pack_id) {  		mktree(t, 0, &old_tree);  		lo.data = old_tree; @@ -1471,6 +1478,7 @@ static void tree_content_replace(  {  	if (!S_ISDIR(mode))  		die("Root cannot be a non-directory"); +	hashclr(root->versions[0].sha1);  	hashcpy(root->versions[1].sha1, sha1);  	if (root->tree)  		release_tree_content_recursive(root->tree); @@ -1515,6 +1523,23 @@ static int tree_content_set(  				if (e->tree)  					release_tree_content_recursive(e->tree);  				e->tree = subtree; + +				/* +				 * We need to leave e->versions[0].sha1 alone +				 * to avoid modifying the preimage tree used +				 * when writing out the parent directory. +				 * But after replacing the subdir with a +				 * completely different one, it's not a good +				 * delta base any more, and besides, we've +				 * thrown away the tree entries needed to +				 * make a delta against it. +				 * +				 * So let's just explicitly disable deltas +				 * for the subtree. +				 */ +				if (S_ISDIR(e->versions[0].mode)) +					e->versions[0].mode |= NO_DELTA; +  				hashclr(root->versions[1].sha1);  				return 1;  			} @@ -2938,7 +2963,7 @@ static void print_ls(int mode, const unsigned char *sha1, const char *path)  		/* mode SP type SP object_name TAB path LF */  		strbuf_reset(&line);  		strbuf_addf(&line, "%06o %s %s\t", -				mode, type, sha1_to_hex(sha1)); +				mode & ~NO_DELTA, type, sha1_to_hex(sha1));  		quote_c_style(path, &line, NULL, 0);  		strbuf_addch(&line, '\n');  	} diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 4ef7624646..dbe109963e 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -833,6 +833,47 @@ test_expect_success \  	 git diff-tree --abbrev --raw L^ L >output &&  	 test_cmp expect output' +cat >input <<INPUT_END +blob +mark :1 +data <<EOF +the data +EOF + +commit refs/heads/L2 +committer C O Mitter <committer@example.com> 1112912473 -0700 +data <<COMMIT +init L2 +COMMIT +M 644 :1 a/b/c +M 644 :1 a/b/d +M 644 :1 a/e/f + +commit refs/heads/L2 +committer C O Mitter <committer@example.com> 1112912473 -0700 +data <<COMMIT +update L2 +COMMIT +C a g +C a/e g/b +M 644 :1 g/b/h +INPUT_END + +cat <<EOF >expect +g/b/f +g/b/h +EOF + +test_expect_success \ +    'L: nested tree copy does not corrupt deltas' \ +	'git fast-import <input && +	git ls-tree L2 g/b/ >tmp && +	cat tmp | cut -f 2 >actual && +	test_cmp expect actual && +	git fsck `git rev-parse L2`' + +git update-ref -d refs/heads/L2 +  ###  ### series M  ### | 
