@matheusbsbs / matheus-bagliano / commits / 34110cd4e3
Fork 0

Make 'unpack_trees()' have a separate source and destination index

We will always unpack into our own internal index, but we will take the source from wherever specified, and we will optionally write the result to a specified index (optionally, because not everybody even _wants_ any result: the index diffing really wants to just walk the tree and index in parallel). This ends up removing a fair number more lines than it adds, for the simple reason that we can now skip all the crud that tried to be oh-so-careful about maintaining our position in the index as we were traversing and modifying it. Since we don't actually modify the source index any more, we can just update the 'o->pos' pointer without worrying about whether an index entry got removed or replaced or added to. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Linus Torvalds committed Mar 6, 2008 at 18:12 UTC 34110cd4e394e3f92c01a4709689b384c34645d8
8 files changed +102 -153
builtin-checkout.c
+6 -3
@@ -160,7 +160,8 @@ static int reset_to_new(struct tree *tree, int quiet)
160 opts.merge = 1;
161 opts.fn = oneway_merge;
162 opts.verbose_update = !quiet;
163 - opts.index = &the_index;
163 + opts.src_index = &the_index;
164 + opts.dst_index = &the_index;
165 parse_tree(tree);
166 init_tree_desc(&tree_desc, tree->buffer, tree->size);
167 if (unpack_trees(1, &tree_desc, &opts))
@@ -180,7 +181,8 @@ static void reset_clean_to_new(struct tree *tree, int quiet)
181 opts.merge = 1;
182 opts.fn = oneway_merge;
183 opts.verbose_update = !quiet;
183 - opts.index = &the_index;
184 + opts.src_index = &the_index;
185 + opts.dst_index = &the_index;
186 parse_tree(tree);
187 init_tree_desc(&tree_desc, tree->buffer, tree->size);
188 if (unpack_trees(1, &tree_desc, &opts))
@@ -231,7 +233,8 @@ static int merge_working_tree(struct checkout_opts *opts,
233
234 memset(&topts, 0, sizeof(topts));
235 topts.head_idx = -1;
234 - topts.index = &the_index;
236 + topts.src_index = &the_index;
237 + topts.dst_index = &the_index;
238
239 refresh_cache(REFRESH_QUIET);
240
builtin-commit.c
+2 -1
@@ -198,7 +198,8 @@ static void create_base_index(void)
198 opts.head_idx = 1;
199 opts.index_only = 1;
200 opts.merge = 1;
201 - opts.index = &the_index;
201 + opts.src_index = &the_index;
202 + opts.dst_index = &the_index;
203
204 opts.fn = oneway_merge;
205 tree = parse_tree_indirect(head_sha1);
builtin-merge-recursive.c
+2 -1
@@ -213,7 +213,8 @@ static int git_merge_trees(int index_only,
213 opts.merge = 1;
214 opts.head_idx = 2;
215 opts.fn = threeway_merge;
216 - opts.index = &the_index;
216 + opts.src_index = &the_index;
217 + opts.dst_index = &the_index;
218
219 init_tree_desc_from_tree(t+0, common);
220 init_tree_desc_from_tree(t+1, head);
builtin-read-tree.c
+2 -22
@@ -102,7 +102,8 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
102
103 memset(&opts, 0, sizeof(opts));
104 opts.head_idx = -1;
105 - opts.index = &the_index;
105 + opts.src_index = &the_index;
106 + opts.dst_index = &the_index;
107
108 git_config(git_default_config);
109
@@ -221,27 +222,6 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
222 if ((opts.dir && !opts.update))
223 die("--exclude-per-directory is meaningless unless -u");
224
224 - if (opts.prefix) {
225 - int pfxlen = strlen(opts.prefix);
226 - int pos;
227 - if (opts.prefix[pfxlen-1] != '/')
228 - die("prefix must end with /");
229 - if (stage != 2)
230 - die("binding merge takes only one tree");
231 - pos = cache_name_pos(opts.prefix, pfxlen);
232 - if (0 <= pos)
233 - die("corrupt index file");
234 - pos = -pos-1;
235 - if (pos < active_nr &&
236 - !strncmp(active_cache[pos]->name, opts.prefix, pfxlen))
237 - die("subdirectory '%s' already exists.", opts.prefix);
238 - pos = cache_name_pos(opts.prefix, pfxlen-1);
239 - if (0 <= pos)
240 - die("file '%.*s' already exists.",
241 - pfxlen-1, opts.prefix);
242 - opts.pos = -1 - pos;
243 - }
244 -
225 if (opts.merge) {
226 if (stage < 2)
227 die("just how do you expect me to merge %d trees?", stage-1);
diff-lib.c
+8 -41
@@ -600,8 +600,7 @@ static void mark_merge_entries(void)
600 */
601 static void do_oneway_diff(struct unpack_trees_options *o,
602 struct cache_entry *idx,
603 - struct cache_entry *tree,
604 - int idx_pos, int idx_nr)
603 + struct cache_entry *tree)
604 {
605 struct rev_info *revs = o->unpack_data;
606 int match_missing, cached;
@@ -642,34 +641,6 @@ static void do_oneway_diff(struct unpack_trees_options *o,
641 show_modified(revs, tree, idx, 1, cached, match_missing);
642 }
643
645 -/*
646 - * Count how many index entries go with the first one
647 - */
648 -static inline int count_skip(const struct cache_entry *src, int pos)
649 -{
650 - int skip = 1;
651 -
652 - /* We can only have multiple entries if the first one is not stage-0 */
653 - if (ce_stage(src)) {
654 - struct cache_entry **p = active_cache + pos;
655 - int namelen = ce_namelen(src);
656 -
657 - for (;;) {
658 - const struct cache_entry *ce;
659 - pos++;
660 - if (pos >= active_nr)
661 - break;
662 - ce = *++p;
663 - if (ce_namelen(ce) != namelen)
664 - break;
665 - if (memcmp(ce->name, src->name, namelen))
666 - break;
667 - skip++;
668 - }
669 - }
670 - return skip;
671 -}
672 -
644 /*
645 * The unpack_trees() interface is designed for merging, so
646 * the different source entries are designed primarily for
@@ -685,18 +656,12 @@ static inline int count_skip(const struct cache_entry *src, int pos)
656 * the fairly complex unpack_trees() semantic requirements, including
657 * the skipping, the path matching, the type conflict cases etc.
658 */
688 -static int oneway_diff(struct cache_entry **src,
689 - struct unpack_trees_options *o,
690 - int index_pos)
659 +static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o)
660 {
692 - int skip = 0;
661 struct cache_entry *idx = src[0];
662 struct cache_entry *tree = src[1];
663 struct rev_info *revs = o->unpack_data;
664
697 - if (index_pos >= 0)
698 - skip = count_skip(idx, index_pos);
699 -
665 /*
666 * Unpack-trees generates a DF/conflict entry if
667 * there was a directory in the index and a tree
@@ -707,9 +672,9 @@ static int oneway_diff(struct cache_entry **src,
672 tree = NULL;
673
674 if (ce_path_match(idx ? idx : tree, revs->prune_data))
710 - do_oneway_diff(o, idx, tree, index_pos, skip);
675 + do_oneway_diff(o, idx, tree);
676
712 - return skip;
677 + return 0;
678 }
679
680 int run_diff_index(struct rev_info *revs, int cached)
@@ -734,7 +699,8 @@ int run_diff_index(struct rev_info *revs, int cached)
699 opts.merge = 1;
700 opts.fn = oneway_diff;
701 opts.unpack_data = revs;
737 - opts.index = &the_index;
702 + opts.src_index = &the_index;
703 + opts.dst_index = NULL;
704
705 init_tree_desc(&t, tree->buffer, tree->size);
706 if (unpack_trees(1, &t, &opts))
@@ -788,7 +754,8 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
754 opts.merge = 1;
755 opts.fn = oneway_diff;
756 opts.unpack_data = &revs;
791 - opts.index = &the_index;
757 + opts.src_index = &the_index;
758 + opts.dst_index = &the_index;
759
760 init_tree_desc(&t, tree->buffer, tree->size);
761 if (unpack_trees(1, &t, &opts))
t/t1005-read-tree-reset.sh
+1 -1
@@ -21,7 +21,7 @@ test_expect_success 'setup' '
21 git commit -m two
22 '
23
24 -test_expect_failure 'reset should work' '
24 +test_expect_success 'reset should work' '
25 git read-tree -u --reset HEAD^ &&
26 git ls-files >actual &&
27 diff -u expect actual
unpack-trees.c
+72 -77
@@ -8,10 +8,18 @@
8 #include "progress.h"
9 #include "refs.h"
10
11 -static inline void remove_entry(int remove, struct unpack_trees_options *o)
11 +static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
12 + unsigned int set, unsigned int clear)
13 {
13 - if (remove >= 0)
14 - remove_index_entry_at(o->index, remove);
14 + unsigned int size = ce_size(ce);
15 + struct cache_entry *new = xmalloc(size);
16 +
17 + clear |= CE_HASHED | CE_UNHASHED;
18 +
19 + memcpy(new, ce, size);
20 + new->next = NULL;
21 + new->ce_flags = (new->ce_flags & ~clear) | set;
22 + add_index_entry(&o->result, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE|ADD_CACHE_SKIP_DFCHECK);
23 }
24
25 /* Unlink the last component and attempt to remove leading
@@ -51,11 +59,12 @@ static void check_updates(struct unpack_trees_options *o)
59 unsigned cnt = 0, total = 0;
60 struct progress *progress = NULL;
61 char last_symlink[PATH_MAX];
62 + struct index_state *index = &o->result;
63 int i;
64
65 if (o->update && o->verbose_update) {
57 - for (total = cnt = 0; cnt < o->index->cache_nr; cnt++) {
58 - struct cache_entry *ce = o->index->cache[cnt];
66 + for (total = cnt = 0; cnt < index->cache_nr; cnt++) {
67 + struct cache_entry *ce = index->cache[cnt];
68 if (ce->ce_flags & (CE_UPDATE | CE_REMOVE))
69 total++;
70 }
@@ -66,15 +75,15 @@ static void check_updates(struct unpack_trees_options *o)
75 }
76
77 *last_symlink = '\0';
69 - for (i = 0; i < o->index->cache_nr; i++) {
70 - struct cache_entry *ce = o->index->cache[i];
78 + for (i = 0; i < index->cache_nr; i++) {
79 + struct cache_entry *ce = index->cache[i];
80
81 if (ce->ce_flags & (CE_UPDATE | CE_REMOVE))
82 display_progress(progress, ++cnt);
83 if (ce->ce_flags & CE_REMOVE) {
84 if (o->update)
85 unlink_entry(ce->name, last_symlink);
77 - remove_index_entry_at(o->index, i);
86 + remove_index_entry_at(&o->result, i);
87 i--;
88 continue;
89 }
@@ -89,28 +98,27 @@ static void check_updates(struct unpack_trees_options *o)
98 stop_progress(&progress);
99 }
100
92 -static inline int call_unpack_fn(struct cache_entry **src, struct unpack_trees_options *o, int remove)
101 +static inline int call_unpack_fn(struct cache_entry **src, struct unpack_trees_options *o)
102 {
94 - int ret = o->fn(src, o, remove);
95 - if (ret > 0) {
96 - o->pos += ret;
103 + int ret = o->fn(src, o);
104 + if (ret > 0)
105 ret = 0;
98 - }
106 return ret;
107 }
108
109 static int unpack_index_entry(struct cache_entry *ce, struct unpack_trees_options *o)
110 {
111 struct cache_entry *src[5] = { ce, };
112 +
113 + o->pos++;
114 if (ce_stage(ce)) {
115 if (o->skip_unmerged) {
107 - o->pos++;
108 - } else {
109 - remove_entry(o->pos, o);
116 + add_entry(o, ce, 0, 0);
117 + return 0;
118 }
119 return 0;
120 }
113 - return call_unpack_fn(src, o, o->pos);
121 + return call_unpack_fn(src, o);
122 }
123
124 int traverse_trees_recursive(int n, unsigned long dirmask, unsigned long df_conflicts, struct name_entry *names, struct traverse_info *info)
@@ -200,7 +208,7 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info, con
208 }
209
210 static int unpack_nondirectories(int n, unsigned long mask, unsigned long dirmask, struct cache_entry *src[5],
203 - const struct name_entry *names, const struct traverse_info *info, int remove)
211 + const struct name_entry *names, const struct traverse_info *info)
212 {
213 int i;
214 struct unpack_trees_options *o = info->data;
@@ -240,12 +248,11 @@ static int unpack_nondirectories(int n, unsigned long mask, unsigned long dirmas
248 }
249
250 if (o->merge)
243 - return call_unpack_fn(src, o, remove);
251 + return call_unpack_fn(src, o);
252
253 n += o->merge;
246 - remove_entry(remove, o);
254 for (i = 0; i < n; i++)
248 - add_index_entry(o->index, src[i], ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
255 + add_entry(o, src[i], 0, 0);
256 return 0;
257 }
258
@@ -253,7 +260,6 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
260 {
261 struct cache_entry *src[5] = { NULL, };
262 struct unpack_trees_options *o = info->data;
256 - int remove = -1;
263 const struct name_entry *p = names;
264
265 /* Find first entry with a real name (we could use "mask" too) */
@@ -262,8 +268,8 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
268
269 /* Are we supposed to look at the index too? */
270 if (o->merge) {
265 - while (o->pos < o->index->cache_nr) {
266 - struct cache_entry *ce = o->index->cache[o->pos];
271 + while (o->pos < o->src_index->cache_nr) {
272 + struct cache_entry *ce = o->src_index->cache[o->pos];
273 int cmp = compare_entry(ce, info, p);
274 if (cmp < 0) {
275 if (unpack_index_entry(ce, o) < 0)
@@ -271,24 +277,25 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
277 continue;
278 }
279 if (!cmp) {
280 + o->pos++;
281 if (ce_stage(ce)) {
282 /*
283 * If we skip unmerged index entries, we'll skip this
284 * entry *and* the tree entries associated with it!
285 */
279 - if (o->skip_unmerged)
286 + if (o->skip_unmerged) {
287 + add_entry(o, ce, 0, 0);
288 return mask;
281 - remove_entry(o->pos, o);
289 + }
290 continue;
291 }
292 src[0] = ce;
285 - remove = o->pos;
293 }
294 break;
295 }
296 }
297
291 - if (unpack_nondirectories(n, mask, dirmask, src, names, info, remove) < 0)
298 + if (unpack_nondirectories(n, mask, dirmask, src, names, info) < 0)
299 return -1;
300
301 /* Now handle any directories.. */
@@ -313,8 +320,6 @@ static int unpack_failed(struct unpack_trees_options *o, const char *message)
320 return error(message);
321 return -1;
322 }
316 - discard_index(o->index);
317 - read_index(o->index);
323 return -1;
324 }
325
@@ -330,6 +335,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
335 state.quiet = 1;
336 state.refresh_cache = 1;
337
338 + memset(&o->result, 0, sizeof(o->result));
339 o->merge_size = len;
340
341 if (!dfc)
@@ -350,8 +356,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
356
357 /* Any left-over entries in the index? */
358 if (o->merge) {
353 - while (o->pos < o->index->cache_nr) {
354 - struct cache_entry *ce = o->index->cache[o->pos];
359 + while (o->pos < o->src_index->cache_nr) {
360 + struct cache_entry *ce = o->src_index->cache[o->pos];
361 if (unpack_index_entry(ce, o) < 0)
362 return unpack_failed(o, NULL);
363 }
@@ -360,7 +366,10 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
366 if (o->trivial_merges_only && o->nontrivial_merge)
367 return unpack_failed(o, "Merge requires file-level merging");
368
369 + o->src_index = NULL;
370 check_updates(o);
371 + if (o->dst_index)
372 + *o->dst_index = o->result;
373 return 0;
374 }
375
@@ -396,7 +405,7 @@ static int verify_uptodate(struct cache_entry *ce,
405 return 0;
406
407 if (!lstat(ce->name, &st)) {
399 - unsigned changed = ie_match_stat(o->index, ce, &st, CE_MATCH_IGNORE_VALID);
408 + unsigned changed = ie_match_stat(o->src_index, ce, &st, CE_MATCH_IGNORE_VALID);
409 if (!changed)
410 return 0;
411 /*
@@ -419,7 +428,7 @@ static int verify_uptodate(struct cache_entry *ce,
428 static void invalidate_ce_path(struct cache_entry *ce, struct unpack_trees_options *o)
429 {
430 if (ce)
422 - cache_tree_invalidate_path(o->index->cache_tree, ce->name);
431 + cache_tree_invalidate_path(o->src_index->cache_tree, ce->name);
432 }
433
434 /*
@@ -464,12 +473,12 @@ static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,
473 * in that directory.
474 */
475 namelen = strlen(ce->name);
467 - pos = index_name_pos(o->index, ce->name, namelen);
476 + pos = index_name_pos(o->src_index, ce->name, namelen);
477 if (0 <= pos)
478 return cnt; /* we have it as nondirectory */
479 pos = -pos - 1;
471 - for (i = pos; i < o->index->cache_nr; i++) {
472 - struct cache_entry *ce = o->index->cache[i];
480 + for (i = pos; i < o->src_index->cache_nr; i++) {
481 + struct cache_entry *ce = o->src_index->cache[i];
482 int len = ce_namelen(ce);
483 if (len < namelen ||
484 strncmp(ce->name, ce->name, namelen) ||
@@ -481,7 +490,7 @@ static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,
490 if (!ce_stage(ce)) {
491 if (verify_uptodate(ce, o))
492 return -1;
484 - ce->ce_flags |= CE_REMOVE;
493 + add_entry(o, ce, CE_REMOVE, 0);
494 }
495 cnt++;
496 }
@@ -567,9 +576,9 @@ static int verify_absent(struct cache_entry *ce, const char *action,
576 * delete this path, which is in a subdirectory that
577 * is being replaced with a blob.
578 */
570 - cnt = index_name_pos(o->index, ce->name, strlen(ce->name));
579 + cnt = index_name_pos(&o->result, ce->name, strlen(ce->name));
580 if (0 <= cnt) {
572 - struct cache_entry *ce = o->index->cache[cnt];
581 + struct cache_entry *ce = o->result.cache[cnt];
582 if (ce->ce_flags & CE_REMOVE)
583 return 0;
584 }
@@ -584,7 +593,6 @@ static int verify_absent(struct cache_entry *ce, const char *action,
593 static int merged_entry(struct cache_entry *merge, struct cache_entry *old,
594 struct unpack_trees_options *o)
595 {
587 - merge->ce_flags |= CE_UPDATE;
596 if (old) {
597 /*
598 * See if we can re-use the old CE directly?
@@ -607,29 +615,29 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old,
615 invalidate_ce_path(merge, o);
616 }
617
610 - merge->ce_flags &= ~CE_STAGEMASK;
611 - add_index_entry(o->index, merge, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
618 + add_entry(o, merge, CE_UPDATE, CE_STAGEMASK);
619 return 1;
620 }
621
622 static int deleted_entry(struct cache_entry *ce, struct cache_entry *old,
623 struct unpack_trees_options *o)
624 {
618 - if (old) {
619 - if (verify_uptodate(old, o))
620 - return -1;
621 - } else
625 + /* Did it exist in the index? */
626 + if (!old) {
627 if (verify_absent(ce, "removed", o))
628 return -1;
624 - ce->ce_flags |= CE_REMOVE;
625 - add_index_entry(o->index, ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
629 + return 0;
630 + }
631 + if (verify_uptodate(old, o))
632 + return -1;
633 + add_entry(o, ce, CE_REMOVE, 0);
634 invalidate_ce_path(ce, o);
635 return 1;
636 }
637
638 static int keep_entry(struct cache_entry *ce, struct unpack_trees_options *o)
639 {
632 - add_index_entry(o->index, ce, ADD_CACHE_OK_TO_ADD);
640 + add_entry(o, ce, 0, 0);
641 return 1;
642 }
643
@@ -649,9 +657,7 @@ static void show_stage_entry(FILE *o,
657 }
658 #endif
659
652 -int threeway_merge(struct cache_entry **stages,
653 - struct unpack_trees_options *o,
654 - int remove)
660 +int threeway_merge(struct cache_entry **stages, struct unpack_trees_options *o)
661 {
662 struct cache_entry *index;
663 struct cache_entry *head;
@@ -728,10 +734,8 @@ int threeway_merge(struct cache_entry **stages,
734 }
735
736 /* #1 */
731 - if (!head && !remote && any_anc_missing) {
732 - remove_entry(remove, o);
737 + if (!head && !remote && any_anc_missing)
738 return 0;
734 - }
739
740 /* Under the new "aggressive" rule, we resolve mostly trivial
741 * cases that we historically had git-merge-one-file resolve.
@@ -763,10 +767,9 @@ int threeway_merge(struct cache_entry **stages,
767 if ((head_deleted && remote_deleted) ||
768 (head_deleted && remote && remote_match) ||
769 (remote_deleted && head && head_match)) {
766 - remove_entry(remove, o);
770 if (index)
771 return deleted_entry(index, index, o);
769 - else if (ce && !head_deleted) {
772 + if (ce && !head_deleted) {
773 if (verify_absent(ce, "removed", o))
774 return -1;
775 }
@@ -789,7 +792,6 @@ int threeway_merge(struct cache_entry **stages,
792 return -1;
793 }
794
792 - remove_entry(remove, o);
795 o->nontrivial_merge = 1;
796
797 /* #2, #3, #4, #6, #7, #9, #10, #11. */
@@ -824,9 +826,7 @@ int threeway_merge(struct cache_entry **stages,
826 * "carry forward" rule, please see <Documentation/git-read-tree.txt>.
827 *
828 */
827 -int twoway_merge(struct cache_entry **src,
828 - struct unpack_trees_options *o,
829 - int remove)
829 +int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o)
830 {
831 struct cache_entry *current = src[0];
832 struct cache_entry *oldtree = src[1];
@@ -854,7 +854,6 @@ int twoway_merge(struct cache_entry **src,
854 }
855 else if (oldtree && !newtree && same(current, oldtree)) {
856 /* 10 or 11 */
857 - remove_entry(remove, o);
857 return deleted_entry(oldtree, current, o);
858 }
859 else if (oldtree && newtree &&
@@ -864,7 +863,6 @@ int twoway_merge(struct cache_entry **src,
863 }
864 else {
865 /* all other failures */
867 - remove_entry(remove, o);
866 if (oldtree)
867 return o->gently ? -1 : reject_merge(oldtree);
868 if (current)
@@ -876,7 +874,6 @@ int twoway_merge(struct cache_entry **src,
874 }
875 else if (newtree)
876 return merged_entry(newtree, current, o);
879 - remove_entry(remove, o);
877 return deleted_entry(oldtree, current, o);
878 }
879
@@ -887,8 +884,7 @@ int twoway_merge(struct cache_entry **src,
884 * stage0 does not have anything there.
885 */
886 int bind_merge(struct cache_entry **src,
890 - struct unpack_trees_options *o,
891 - int remove)
887 + struct unpack_trees_options *o)
888 {
889 struct cache_entry *old = src[0];
890 struct cache_entry *a = src[1];
@@ -898,7 +894,7 @@ int bind_merge(struct cache_entry **src,
894 o->merge_size);
895 if (a && old)
896 return o->gently ? -1 :
901 - error("Entry '%s' overlaps. Cannot bind.", a->name);
897 + error("Entry '%s' overlaps with '%s'. Cannot bind.", a->name, old->name);
898 if (!a)
899 return keep_entry(old, o);
900 else
@@ -911,9 +907,7 @@ int bind_merge(struct cache_entry **src,
907 * The rule is:
908 * - take the stat information from stage0, take the data from stage1
909 */
914 -int oneway_merge(struct cache_entry **src,
915 - struct unpack_trees_options *o,
916 - int remove)
910 +int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
911 {
912 struct cache_entry *old = src[0];
913 struct cache_entry *a = src[1];
@@ -922,18 +916,19 @@ int oneway_merge(struct cache_entry **src,
916 return error("Cannot do a oneway merge of %d trees",
917 o->merge_size);
918
925 - if (!a) {
926 - remove_entry(remove, o);
919 + if (!a)
920 return deleted_entry(old, old, o);
928 - }
921 +
922 if (old && same(old, a)) {
923 + int update = 0;
924 if (o->reset) {
925 struct stat st;
926 if (lstat(old->name, &st) ||
933 - ie_match_stat(o->index, old, &st, CE_MATCH_IGNORE_VALID))
934 - old->ce_flags |= CE_UPDATE;
927 + ie_match_stat(o->src_index, old, &st, CE_MATCH_IGNORE_VALID))
928 + update |= CE_UPDATE;
929 }
936 - return keep_entry(old, o);
930 + add_entry(o, old, update, 0);
931 + return 0;
932 }
933 return merged_entry(a, old, o);
934 }
unpack-trees.h
+9 -7
@@ -4,8 +4,7 @@
4 struct unpack_trees_options;
5
6 typedef int (*merge_fn_t)(struct cache_entry **src,
7 - struct unpack_trees_options *options,
8 - int remove);
7 + struct unpack_trees_options *options);
8
9 struct unpack_trees_options {
10 int reset;
@@ -28,15 +27,18 @@ struct unpack_trees_options {
27
28 struct cache_entry *df_conflict_entry;
29 void *unpack_data;
31 - struct index_state *index;
30 +
31 + struct index_state *dst_index;
32 + const struct index_state *src_index;
33 + struct index_state result;
34 };
35
36 extern int unpack_trees(unsigned n, struct tree_desc *t,
37 struct unpack_trees_options *options);
38
37 -int threeway_merge(struct cache_entry **stages, struct unpack_trees_options *o, int);
38 -int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o, int);
39 -int bind_merge(struct cache_entry **src, struct unpack_trees_options *o, int);
40 -int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o, int);
39 +int threeway_merge(struct cache_entry **stages, struct unpack_trees_options *o);
40 +int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o);
41 +int bind_merge(struct cache_entry **src, struct unpack_trees_options *o);
42 +int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o);
43
44 #endif