Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merge branch 'jk/maint-null-in-trees'

We do not want a link to 0{40} object stored anywhere in our objects.

* jk/maint-null-in-trees:
  fsck: detect null sha1 in tree entries
  do not write null sha1s to on-disk index
  diff: do not use null sha1 as a sentinel value
  • Loading branch information...
commit 3b753148b636be9dc821feebf85cd7f1739b07a1 2 parents b9148c3 + c479d14
Junio C Hamano authored August 27, 2012
2  builtin.h
@@ -43,7 +43,7 @@ extern int check_pager_config(const char *cmd);
43 43
 struct diff_options;
44 44
 extern void setup_diff_pager(struct diff_options *);
45 45
 
46  
-extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, char **buf, unsigned long *buf_size);
  46
+extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, int sha1_valid, char **buf, unsigned long *buf_size);
47 47
 
48 48
 extern int cmd_add(int argc, const char **argv, const char *prefix);
49 49
 extern int cmd_annotate(int argc, const char **argv, const char *prefix);
9  builtin/blame.c
@@ -110,6 +110,7 @@ static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, long ctxlen,
110 110
 int textconv_object(const char *path,
111 111
 		    unsigned mode,
112 112
 		    const unsigned char *sha1,
  113
+		    int sha1_valid,
113 114
 		    char **buf,
114 115
 		    unsigned long *buf_size)
115 116
 {
@@ -117,7 +118,7 @@ int textconv_object(const char *path,
117 118
 	struct userdiff_driver *textconv;
118 119
 
119 120
 	df = alloc_filespec(path);
120  
-	fill_filespec(df, sha1, mode);
  121
+	fill_filespec(df, sha1, sha1_valid, mode);
121 122
 	textconv = get_textconv(df);
122 123
 	if (!textconv) {
123 124
 		free_filespec(df);
@@ -142,7 +143,7 @@ static void fill_origin_blob(struct diff_options *opt,
142 143
 
143 144
 		num_read_blob++;
144 145
 		if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
145  
-		    textconv_object(o->path, o->mode, o->blob_sha1, &file->ptr, &file_size))
  146
+		    textconv_object(o->path, o->mode, o->blob_sha1, 1, &file->ptr, &file_size))
146 147
 			;
147 148
 		else
148 149
 			file->ptr = read_sha1_file(o->blob_sha1, &type, &file_size);
@@ -2120,7 +2121,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
2120 2121
 		switch (st.st_mode & S_IFMT) {
2121 2122
 		case S_IFREG:
2122 2123
 			if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&
2123  
-			    textconv_object(read_from, mode, null_sha1, &buf_ptr, &buf_len))
  2124
+			    textconv_object(read_from, mode, null_sha1, 0, &buf_ptr, &buf_len))
2124 2125
 				strbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1);
2125 2126
 			else if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
2126 2127
 				die_errno("cannot open or read '%s'", read_from);
@@ -2513,7 +2514,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
2513 2514
 			die("no such path %s in %s", path, final_commit_name);
2514 2515
 
2515 2516
 		if (DIFF_OPT_TST(&sb.revs->diffopt, ALLOW_TEXTCONV) &&
2516  
-		    textconv_object(path, o->mode, o->blob_sha1, (char **) &sb.final_buf,
  2517
+		    textconv_object(path, o->mode, o->blob_sha1, 1, (char **) &sb.final_buf,
2517 2518
 				    &sb.final_buf_size))
2518 2519
 			;
2519 2520
 		else
2  builtin/cat-file.c
@@ -146,7 +146,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
146 146
 			die("git cat-file --textconv %s: <object> must be <sha1:path>",
147 147
 			    obj_name);
148 148
 
149  
-		if (!textconv_object(obj_context.path, obj_context.mode, sha1, &buf, &size))
  149
+		if (!textconv_object(obj_context.path, obj_context.mode, sha1, 1, &buf, &size))
150 150
 			die("git cat-file --textconv: unable to run textconv on %s",
151 151
 			    obj_name);
152 152
 		break;
8  builtin/diff.c
@@ -29,6 +29,8 @@ static void stuff_change(struct diff_options *opt,
29 29
 			 unsigned old_mode, unsigned new_mode,
30 30
 			 const unsigned char *old_sha1,
31 31
 			 const unsigned char *new_sha1,
  32
+			 int old_sha1_valid,
  33
+			 int new_sha1_valid,
32 34
 			 const char *old_name,
33 35
 			 const char *new_name)
34 36
 {
@@ -54,8 +56,8 @@ static void stuff_change(struct diff_options *opt,
54 56
 
55 57
 	one = alloc_filespec(old_name);
56 58
 	two = alloc_filespec(new_name);
57  
-	fill_filespec(one, old_sha1, old_mode);
58  
-	fill_filespec(two, new_sha1, new_mode);
  59
+	fill_filespec(one, old_sha1, old_sha1_valid, old_mode);
  60
+	fill_filespec(two, new_sha1, new_sha1_valid, new_mode);
59 61
 
60 62
 	diff_queue(&diff_queued_diff, one, two);
61 63
 }
@@ -84,6 +86,7 @@ static int builtin_diff_b_f(struct rev_info *revs,
84 86
 	stuff_change(&revs->diffopt,
85 87
 		     blob[0].mode, canon_mode(st.st_mode),
86 88
 		     blob[0].sha1, null_sha1,
  89
+		     1, 0,
87 90
 		     path, path);
88 91
 	diffcore_std(&revs->diffopt);
89 92
 	diff_flush(&revs->diffopt);
@@ -108,6 +111,7 @@ static int builtin_diff_blobs(struct rev_info *revs,
108 111
 	stuff_change(&revs->diffopt,
109 112
 		     blob[0].mode, blob[1].mode,
110 113
 		     blob[0].sha1, blob[1].sha1,
  114
+		     1, 1,
111 115
 		     blob[0].name, blob[1].name);
112 116
 	diffcore_std(&revs->diffopt);
113 117
 	diff_flush(&revs->diffopt);
4  combine-diff.c
@@ -111,7 +111,7 @@ static char *grab_blob(const unsigned char *sha1, unsigned int mode,
111 111
 		return xcalloc(1, 1);
112 112
 	} else if (textconv) {
113 113
 		struct diff_filespec *df = alloc_filespec(path);
114  
-		fill_filespec(df, sha1, mode);
  114
+		fill_filespec(df, sha1, 1, mode);
115 115
 		*size = fill_textconv(textconv, df, &blob);
116 116
 		free_filespec(df);
117 117
 	} else {
@@ -823,7 +823,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
823 823
 						   &result_size, NULL, NULL);
824 824
 		} else if (textconv) {
825 825
 			struct diff_filespec *df = alloc_filespec(elem->path);
826  
-			fill_filespec(df, null_sha1, st.st_mode);
  826
+			fill_filespec(df, null_sha1, 0, st.st_mode);
827 827
 			result_size = fill_textconv(textconv, df, &result);
828 828
 			free_filespec(df);
829 829
 		} else if (0 <= (fd = open(elem->path, O_RDONLY))) {
20  diff-lib.c
@@ -206,7 +206,8 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
206 206
 			if (silent_on_removed)
207 207
 				continue;
208 208
 			diff_addremove(&revs->diffopt, '-', ce->ce_mode,
209  
-				       ce->sha1, ce->name, 0);
  209
+				       ce->sha1, !is_null_sha1(ce->sha1),
  210
+				       ce->name, 0);
210 211
 			continue;
211 212
 		}
212 213
 		changed = match_stat_with_submodule(&revs->diffopt, ce, &st,
@@ -220,6 +221,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
220 221
 		newmode = ce_mode_from_stat(ce, st.st_mode);
221 222
 		diff_change(&revs->diffopt, oldmode, newmode,
222 223
 			    ce->sha1, (changed ? null_sha1 : ce->sha1),
  224
+			    !is_null_sha1(ce->sha1), (changed ? 0 : !is_null_sha1(ce->sha1)),
223 225
 			    ce->name, 0, dirty_submodule);
224 226
 
225 227
 	}
@@ -236,11 +238,12 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
236 238
 static void diff_index_show_file(struct rev_info *revs,
237 239
 				 const char *prefix,
238 240
 				 struct cache_entry *ce,
239  
-				 const unsigned char *sha1, unsigned int mode,
  241
+				 const unsigned char *sha1, int sha1_valid,
  242
+				 unsigned int mode,
240 243
 				 unsigned dirty_submodule)
241 244
 {
242 245
 	diff_addremove(&revs->diffopt, prefix[0], mode,
243  
-		       sha1, ce->name, dirty_submodule);
  246
+		       sha1, sha1_valid, ce->name, dirty_submodule);
244 247
 }
245 248
 
246 249
 static int get_stat_data(struct cache_entry *ce,
@@ -295,7 +298,7 @@ static void show_new_file(struct rev_info *revs,
295 298
 	    &dirty_submodule, &revs->diffopt) < 0)
296 299
 		return;
297 300
 
298  
-	diff_index_show_file(revs, "+", new, sha1, mode, dirty_submodule);
  301
+	diff_index_show_file(revs, "+", new, sha1, !is_null_sha1(sha1), mode, dirty_submodule);
299 302
 }
300 303
 
301 304
 static int show_modified(struct rev_info *revs,
@@ -312,7 +315,7 @@ static int show_modified(struct rev_info *revs,
312 315
 			  &dirty_submodule, &revs->diffopt) < 0) {
313 316
 		if (report_missing)
314 317
 			diff_index_show_file(revs, "-", old,
315  
-					     old->sha1, old->ce_mode, 0);
  318
+					     old->sha1, 1, old->ce_mode, 0);
316 319
 		return -1;
317 320
 	}
318 321
 
@@ -347,7 +350,8 @@ static int show_modified(struct rev_info *revs,
347 350
 		return 0;
348 351
 
349 352
 	diff_change(&revs->diffopt, oldmode, mode,
350  
-		    old->sha1, sha1, old->name, 0, dirty_submodule);
  353
+		    old->sha1, sha1, 1, !is_null_sha1(sha1),
  354
+		    old->name, 0, dirty_submodule);
351 355
 	return 0;
352 356
 }
353 357
 
@@ -380,7 +384,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
380 384
 		struct diff_filepair *pair;
381 385
 		pair = diff_unmerge(&revs->diffopt, idx->name);
382 386
 		if (tree)
383  
-			fill_filespec(pair->one, tree->sha1, tree->ce_mode);
  387
+			fill_filespec(pair->one, tree->sha1, 1, tree->ce_mode);
384 388
 		return;
385 389
 	}
386 390
 
@@ -396,7 +400,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
396 400
 	 * Something removed from the tree?
397 401
 	 */
398 402
 	if (!idx) {
399  
-		diff_index_show_file(revs, "-", tree, tree->sha1, tree->ce_mode, 0);
  403
+		diff_index_show_file(revs, "-", tree, tree->sha1, 1, tree->ce_mode, 0);
400 404
 		return;
401 405
 	}
402 406
 
2  diff-no-index.c
@@ -82,7 +82,7 @@ static struct diff_filespec *noindex_filespec(const char *name, int mode)
82 82
 	if (!name)
83 83
 		name = "/dev/null";
84 84
 	s = alloc_filespec(name);
85  
-	fill_filespec(s, null_sha1, mode);
  85
+	fill_filespec(s, null_sha1, 0, mode);
86 86
 	if (name == file_from_standard_input)
87 87
 		populate_from_stdin(s);
88 88
 	return s;
16  diff.c
@@ -2541,12 +2541,12 @@ void free_filespec(struct diff_filespec *spec)
2541 2541
 }
2542 2542
 
2543 2543
 void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
2544  
-		   unsigned short mode)
  2544
+		   int sha1_valid, unsigned short mode)
2545 2545
 {
2546 2546
 	if (mode) {
2547 2547
 		spec->mode = canon_mode(mode);
2548 2548
 		hashcpy(spec->sha1, sha1);
2549  
-		spec->sha1_valid = !is_null_sha1(sha1);
  2549
+		spec->sha1_valid = sha1_valid;
2550 2550
 	}
2551 2551
 }
2552 2552
 
@@ -4691,6 +4691,7 @@ static int is_submodule_ignored(const char *path, struct diff_options *options)
4691 4691
 void diff_addremove(struct diff_options *options,
4692 4692
 		    int addremove, unsigned mode,
4693 4693
 		    const unsigned char *sha1,
  4694
+		    int sha1_valid,
4694 4695
 		    const char *concatpath, unsigned dirty_submodule)
4695 4696
 {
4696 4697
 	struct diff_filespec *one, *two;
@@ -4722,9 +4723,9 @@ void diff_addremove(struct diff_options *options,
4722 4723
 	two = alloc_filespec(concatpath);
4723 4724
 
4724 4725
 	if (addremove != '+')
4725  
-		fill_filespec(one, sha1, mode);
  4726
+		fill_filespec(one, sha1, sha1_valid, mode);
4726 4727
 	if (addremove != '-') {
4727  
-		fill_filespec(two, sha1, mode);
  4728
+		fill_filespec(two, sha1, sha1_valid, mode);
4728 4729
 		two->dirty_submodule = dirty_submodule;
4729 4730
 	}
4730 4731
 
@@ -4737,6 +4738,7 @@ void diff_change(struct diff_options *options,
4737 4738
 		 unsigned old_mode, unsigned new_mode,
4738 4739
 		 const unsigned char *old_sha1,
4739 4740
 		 const unsigned char *new_sha1,
  4741
+		 int old_sha1_valid, int new_sha1_valid,
4740 4742
 		 const char *concatpath,
4741 4743
 		 unsigned old_dirty_submodule, unsigned new_dirty_submodule)
4742 4744
 {
@@ -4751,6 +4753,8 @@ void diff_change(struct diff_options *options,
4751 4753
 		const unsigned char *tmp_c;
4752 4754
 		tmp = old_mode; old_mode = new_mode; new_mode = tmp;
4753 4755
 		tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c;
  4756
+		tmp = old_sha1_valid; old_sha1_valid = new_sha1_valid;
  4757
+			new_sha1_valid = tmp;
4754 4758
 		tmp = old_dirty_submodule; old_dirty_submodule = new_dirty_submodule;
4755 4759
 			new_dirty_submodule = tmp;
4756 4760
 	}
@@ -4761,8 +4765,8 @@ void diff_change(struct diff_options *options,
4761 4765
 
4762 4766
 	one = alloc_filespec(concatpath);
4763 4767
 	two = alloc_filespec(concatpath);
4764  
-	fill_filespec(one, old_sha1, old_mode);
4765  
-	fill_filespec(two, new_sha1, new_mode);
  4768
+	fill_filespec(one, old_sha1, old_sha1_valid, old_mode);
  4769
+	fill_filespec(two, new_sha1, new_sha1_valid, new_mode);
4766 4770
 	one->dirty_submodule = old_dirty_submodule;
4767 4771
 	two->dirty_submodule = new_dirty_submodule;
4768 4772
 
5  diff.h
@@ -19,12 +19,14 @@ typedef void (*change_fn_t)(struct diff_options *options,
19 19
 		 unsigned old_mode, unsigned new_mode,
20 20
 		 const unsigned char *old_sha1,
21 21
 		 const unsigned char *new_sha1,
  22
+		 int old_sha1_valid, int new_sha1_valid,
22 23
 		 const char *fullpath,
23 24
 		 unsigned old_dirty_submodule, unsigned new_dirty_submodule);
24 25
 
25 26
 typedef void (*add_remove_fn_t)(struct diff_options *options,
26 27
 		    int addremove, unsigned mode,
27 28
 		    const unsigned char *sha1,
  29
+		    int sha1_valid,
28 30
 		    const char *fullpath, unsigned dirty_submodule);
29 31
 
30 32
 typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
@@ -214,12 +216,15 @@ extern void diff_addremove(struct diff_options *,
214 216
 			   int addremove,
215 217
 			   unsigned mode,
216 218
 			   const unsigned char *sha1,
  219
+			   int sha1_valid,
217 220
 			   const char *fullpath, unsigned dirty_submodule);
218 221
 
219 222
 extern void diff_change(struct diff_options *,
220 223
 			unsigned mode1, unsigned mode2,
221 224
 			const unsigned char *sha1,
222 225
 			const unsigned char *sha2,
  226
+			int sha1_valid,
  227
+			int sha2_valid,
223 228
 			const char *fullpath,
224 229
 			unsigned dirty_submodule1, unsigned dirty_submodule2);
225 230
 
2  diffcore-rename.c
@@ -48,7 +48,7 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two,
48 48
 		memmove(rename_dst + first + 1, rename_dst + first,
49 49
 			(rename_dst_nr - first - 1) * sizeof(*rename_dst));
50 50
 	rename_dst[first].two = alloc_filespec(two->path);
51  
-	fill_filespec(rename_dst[first].two, two->sha1, two->mode);
  51
+	fill_filespec(rename_dst[first].two, two->sha1, two->sha1_valid, two->mode);
52 52
 	rename_dst[first].pair = NULL;
53 53
 	return &(rename_dst[first]);
54 54
 }
2  diffcore.h
@@ -55,7 +55,7 @@ struct diff_filespec {
55 55
 extern struct diff_filespec *alloc_filespec(const char *);
56 56
 extern void free_filespec(struct diff_filespec *);
57 57
 extern void fill_filespec(struct diff_filespec *, const unsigned char *,
58  
-			  unsigned short);
  58
+			  int, unsigned short);
59 59
 
60 60
 extern int diff_populate_filespec(struct diff_filespec *, int);
61 61
 extern void diff_free_filespec_data(struct diff_filespec *);
8  fsck.c
@@ -139,6 +139,7 @@ static int verify_ordered(unsigned mode1, const char *name1, unsigned mode2, con
139 139
 static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
140 140
 {
141 141
 	int retval;
  142
+	int has_null_sha1 = 0;
142 143
 	int has_full_path = 0;
143 144
 	int has_empty_name = 0;
144 145
 	int has_zero_pad = 0;
@@ -157,9 +158,12 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
157 158
 	while (desc.size) {
158 159
 		unsigned mode;
159 160
 		const char *name;
  161
+		const unsigned char *sha1;
160 162
 
161  
-		tree_entry_extract(&desc, &name, &mode);
  163
+		sha1 = tree_entry_extract(&desc, &name, &mode);
162 164
 
  165
+		if (is_null_sha1(sha1))
  166
+			has_null_sha1 = 1;
163 167
 		if (strchr(name, '/'))
164 168
 			has_full_path = 1;
165 169
 		if (!*name)
@@ -207,6 +211,8 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
207 211
 	}
208 212
 
209 213
 	retval = 0;
  214
+	if (has_null_sha1)
  215
+		retval += error_func(&item->object, FSCK_WARN, "contains entries pointing to null sha1");
210 216
 	if (has_full_path)
211 217
 		retval += error_func(&item->object, FSCK_WARN, "contains full pathnames");
212 218
 	if (has_empty_name)
2  read-cache.c
@@ -1796,6 +1796,8 @@ int write_index(struct index_state *istate, int newfd)
1796 1796
 			continue;
1797 1797
 		if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce))
1798 1798
 			ce_smudge_racily_clean_entry(ce);
  1799
+		if (is_null_sha1(ce->sha1))
  1800
+			return error("cache entry has null sha1: %s", ce->name);
1799 1801
 		if (ce_write_entry(&c, newfd, ce, previous_name) < 0)
1800 1802
 			return -1;
1801 1803
 	}
2  revision.c
@@ -345,6 +345,7 @@ static int tree_difference = REV_TREE_SAME;
345 345
 static void file_add_remove(struct diff_options *options,
346 346
 		    int addremove, unsigned mode,
347 347
 		    const unsigned char *sha1,
  348
+		    int sha1_valid,
348 349
 		    const char *fullpath, unsigned dirty_submodule)
349 350
 {
350 351
 	int diff = addremove == '+' ? REV_TREE_NEW : REV_TREE_OLD;
@@ -358,6 +359,7 @@ static void file_change(struct diff_options *options,
358 359
 		 unsigned old_mode, unsigned new_mode,
359 360
 		 const unsigned char *old_sha1,
360 361
 		 const unsigned char *new_sha1,
  362
+		 int old_sha1_valid, int new_sha1_valid,
361 363
 		 const char *fullpath,
362 364
 		 unsigned old_dirty_submodule, unsigned new_dirty_submodule)
363 365
 {
26  t/t1450-fsck.sh
@@ -213,4 +213,30 @@ test_expect_success 'rev-list --verify-objects with bad sha1' '
213 213
 	grep -q "error: sha1 mismatch 63ffffffffffffffffffffffffffffffffffffff" out
214 214
 '
215 215
 
  216
+_bz='\0'
  217
+_bz5="$_bz$_bz$_bz$_bz$_bz"
  218
+_bz20="$_bz5$_bz5$_bz5$_bz5"
  219
+
  220
+test_expect_success 'fsck notices blob entry pointing to null sha1' '
  221
+	(git init null-blob &&
  222
+	 cd null-blob &&
  223
+	 sha=$(printf "100644 file$_bz$_bz20" |
  224
+	       git hash-object -w --stdin -t tree) &&
  225
+	  git fsck 2>out &&
  226
+	  cat out &&
  227
+	  grep "warning.*null sha1" out
  228
+	)
  229
+'
  230
+
  231
+test_expect_success 'fsck notices submodule entry pointing to null sha1' '
  232
+	(git init null-commit &&
  233
+	 cd null-commit &&
  234
+	 sha=$(printf "160000 submodule$_bz$_bz20" |
  235
+	       git hash-object -w --stdin -t tree) &&
  236
+	  git fsck 2>out &&
  237
+	  cat out &&
  238
+	  grep "warning.*null sha1" out
  239
+	)
  240
+'
  241
+
216 242
 test_done
19  t/t2107-update-index-basic.sh
@@ -29,4 +29,23 @@ test_expect_success 'update-index -h with corrupt index' '
29 29
 	grep "[Uu]sage: git update-index" broken/usage
30 30
 '
31 31
 
  32
+test_expect_success '--cacheinfo does not accept blob null sha1' '
  33
+	echo content >file &&
  34
+	git add file &&
  35
+	git rev-parse :file >expect &&
  36
+	test_must_fail git update-index --cacheinfo 100644 $_z40 file &&
  37
+	git rev-parse :file >actual &&
  38
+	test_cmp expect actual
  39
+'
  40
+
  41
+test_expect_success '--cacheinfo does not accept gitlink null sha1' '
  42
+	git init submodule &&
  43
+	(cd submodule && test_commit foo) &&
  44
+	git add submodule &&
  45
+	git rev-parse :submodule >expect &&
  46
+	test_must_fail git update-index --cacheinfo 160000 $_z40 submodule &&
  47
+	git rev-parse :submodule >actual &&
  48
+	test_cmp expect actual
  49
+'
  50
+
32 51
 test_done
83  t/t4054-diff-bogus-tree.sh
... ...
@@ -0,0 +1,83 @@
  1
+#!/bin/sh
  2
+
  3
+test_description='test diff with a bogus tree containing the null sha1'
  4
+. ./test-lib.sh
  5
+
  6
+empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904
  7
+
  8
+test_expect_success 'create bogus tree' '
  9
+	bogus_tree=$(
  10
+		printf "100644 fooQQQQQQQQQQQQQQQQQQQQQ" |
  11
+		q_to_nul |
  12
+		git hash-object -w --stdin -t tree
  13
+	)
  14
+'
  15
+
  16
+test_expect_success 'create tree with matching file' '
  17
+	echo bar >foo &&
  18
+	git add foo &&
  19
+	good_tree=$(git write-tree)
  20
+	blob=$(git rev-parse :foo)
  21
+'
  22
+
  23
+test_expect_success 'raw diff shows null sha1 (addition)' '
  24
+	echo ":000000 100644 $_z40 $_z40 A	foo" >expect &&
  25
+	git diff-tree $empty_tree $bogus_tree >actual &&
  26
+	test_cmp expect actual
  27
+'
  28
+
  29
+test_expect_success 'raw diff shows null sha1 (removal)' '
  30
+	echo ":100644 000000 $_z40 $_z40 D	foo" >expect &&
  31
+	git diff-tree $bogus_tree $empty_tree >actual &&
  32
+	test_cmp expect actual
  33
+'
  34
+
  35
+test_expect_success 'raw diff shows null sha1 (modification)' '
  36
+	echo ":100644 100644 $blob $_z40 M	foo" >expect &&
  37
+	git diff-tree $good_tree $bogus_tree >actual &&
  38
+	test_cmp expect actual
  39
+'
  40
+
  41
+test_expect_success 'raw diff shows null sha1 (other direction)' '
  42
+	echo ":100644 100644 $_z40 $blob M	foo" >expect &&
  43
+	git diff-tree $bogus_tree $good_tree >actual &&
  44
+	test_cmp expect actual
  45
+'
  46
+
  47
+test_expect_success 'raw diff shows null sha1 (reverse)' '
  48
+	echo ":100644 100644 $_z40 $blob M	foo" >expect &&
  49
+	git diff-tree -R $good_tree $bogus_tree >actual &&
  50
+	test_cmp expect actual
  51
+'
  52
+
  53
+test_expect_success 'raw diff shows null sha1 (index)' '
  54
+	echo ":100644 100644 $_z40 $blob M	foo" >expect &&
  55
+	git diff-index $bogus_tree >actual &&
  56
+	test_cmp expect actual
  57
+'
  58
+
  59
+test_expect_success 'patch fails due to bogus sha1 (addition)' '
  60
+	test_must_fail git diff-tree -p $empty_tree $bogus_tree
  61
+'
  62
+
  63
+test_expect_success 'patch fails due to bogus sha1 (removal)' '
  64
+	test_must_fail git diff-tree -p $bogus_tree $empty_tree
  65
+'
  66
+
  67
+test_expect_success 'patch fails due to bogus sha1 (modification)' '
  68
+	test_must_fail git diff-tree -p $good_tree $bogus_tree
  69
+'
  70
+
  71
+test_expect_success 'patch fails due to bogus sha1 (other direction)' '
  72
+	test_must_fail git diff-tree -p $bogus_tree $good_tree
  73
+'
  74
+
  75
+test_expect_success 'patch fails due to bogus sha1 (reverse)' '
  76
+	test_must_fail git diff-tree -R -p $good_tree $bogus_tree
  77
+'
  78
+
  79
+test_expect_success 'patch fails due to bogus sha1 (index)' '
  80
+	test_must_fail git diff-index -p $bogus_tree
  81
+'
  82
+
  83
+test_done
8  tree-diff.c
@@ -49,12 +49,12 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
49 49
 	if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) {
50 50
 		if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) {
51 51
 			opt->change(opt, mode1, mode2,
52  
-				    sha1, sha2, base->buf, 0, 0);
  52
+				    sha1, sha2, 1, 1, base->buf, 0, 0);
53 53
 		}
54 54
 		strbuf_addch(base, '/');
55 55
 		diff_tree_sha1(sha1, sha2, base->buf, opt);
56 56
 	} else {
57  
-		opt->change(opt, mode1, mode2, sha1, sha2, base->buf, 0, 0);
  57
+		opt->change(opt, mode1, mode2, sha1, sha2, 1, 1, base->buf, 0, 0);
58 58
 	}
59 59
 	strbuf_setlen(base, old_baselen);
60 60
 	return 0;
@@ -100,7 +100,7 @@ static void show_entry(struct diff_options *opt, const char *prefix,
100 100
 			die("corrupt tree sha %s", sha1_to_hex(sha1));
101 101
 
102 102
 		if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE))
103  
-			opt->add_remove(opt, *prefix, mode, sha1, base->buf, 0);
  103
+			opt->add_remove(opt, *prefix, mode, sha1, 1, base->buf, 0);
104 104
 
105 105
 		strbuf_addch(base, '/');
106 106
 
@@ -108,7 +108,7 @@ static void show_entry(struct diff_options *opt, const char *prefix,
108 108
 		show_tree(opt, prefix, &inner, base);
109 109
 		free(tree);
110 110
 	} else
111  
-		opt->add_remove(opt, prefix[0], mode, sha1, base->buf, 0);
  111
+		opt->add_remove(opt, prefix[0], mode, sha1, 1, base->buf, 0);
112 112
 
113 113
 	strbuf_setlen(base, old_baselen);
114 114
 }

0 notes on commit 3b75314

Please sign in to comment.
Something went wrong with that request. Please try again.