diff options
author | Max Kirillov <max@max630.net> | 2015-04-03 18:58:35 +0300 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-04-11 14:15:00 -0700 |
commit | 6f783955d110f3ea6e774489098ee1033f02bbc9 (patch) | |
tree | ad131aaa9937d48804535ab547f9158cf573e75e | |
parent | 0e5f2632fc6a31efd215349a3b774db0357d5018 (diff) | |
download | git-6f783955d110f3ea6e774489098ee1033f02bbc9.tar.gz |
diff --cc: relax too strict paths picking
For diff --cc, paths fitering used to select only paths which have
changed in all parents, while diffing itself output hunks which are
changed in as few as 2 parents.
Fix intersect_paths() to add paths which have at least 2 changed
parents. In this new functionality does not require special treatment of
first pass, because path can be added from any parent, not just the
first one.
Signed-off-by: Max Kirillov <max@max630.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | combine-diff.c | 56 | ||||
-rwxr-xr-x | t/t4059-diff-cc-not-affected-by-path-filtering.sh | 4 |
2 files changed, 41 insertions, 19 deletions
diff --git a/combine-diff.c b/combine-diff.c index 37881dd3c1..a20fa90ecb 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -26,6 +26,7 @@ static void insert_path(struct combine_diff_path **pos, const char* path, int n, int num_parent, struct diff_filepair *queue_item) { int len; + int parent_idx; struct combine_diff_path *p; len = strlen(path); @@ -42,43 +43,64 @@ static void insert_path(struct combine_diff_path **pos, const char* path, hashcpy(p->parent[n].sha1, queue_item->one->sha1); p->parent[n].mode = queue_item->one->mode; p->parent[n].status = queue_item->status; + for (parent_idx = 0; parent_idx < n; parent_idx++) { + hashcpy(p->parent[parent_idx].sha1, p->sha1); + p->parent[parent_idx].mode = p->mode; + p->parent[parent_idx].status = ' '; + } *pos = p; } +static int changed_parents(struct combine_diff_path *p, int n) +{ + int parent_idx; + int result = 0; + + for (parent_idx = 0; parent_idx < n; parent_idx++) { + if (p->parent[parent_idx].status != ' ') + result++; + } + + return result; +} + static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent) { struct diff_queue_struct *q = &diff_queued_diff; struct combine_diff_path *p, **tail = &curr; int i, cmp; - if (!n) { - for (i = 0; i < q->nr; i++) { - if (diff_unmodified_pair(q->queue[i])) - continue; - insert_path(tail, q->queue[i]->two->path, n, num_parent, q->queue[i]); - tail = &(*tail)->next; - } - return curr; - } - /* * paths in curr (linked list) and q->queue[] (array) are * both sorted in the tree order. */ i = 0; - while ((p = *tail) != NULL) { - cmp = ((i >= q->nr) - ? -1 : compare_paths(p, q->queue[i]->two)); + while ((p = *tail) != NULL || i < q->nr) { + cmp = (i >= q->nr) ? -1 + : (p == NULL) ? 1 + : compare_paths(p, q->queue[i]->two); if (cmp < 0) { - /* p->path not in q->queue[]; drop it */ - *tail = p->next; - free(p); + /* p->path not in q->queue[] */ + if (num_parent > 2 && 2 - changed_parents(p, n) <= num_parent - n - 1) { + /* still can get 2 changed parents */ + hashcpy(p->parent[n].sha1, p->sha1); + p->parent[n].mode = p->mode; + p->parent[n].status = ' '; + tail = &p->next; + } else { + *tail = p->next; + free(p); + } continue; } if (cmp > 0) { - /* q->queue[i] not in p->path; skip it */ + /* q->queue[i] not in p->path */ + if (1 <= num_parent - n - 1) { + insert_path(tail, q->queue[i]->two->path, n, num_parent, q->queue[i]); + tail = &(*tail)->next; + } i++; continue; } diff --git a/t/t4059-diff-cc-not-affected-by-path-filtering.sh b/t/t4059-diff-cc-not-affected-by-path-filtering.sh index 3e6e59b299..ab3dbd2f87 100755 --- a/t/t4059-diff-cc-not-affected-by-path-filtering.sh +++ b/t/t4059-diff-cc-not-affected-by-path-filtering.sh @@ -95,12 +95,12 @@ test_expect_success 'diff with mergebase shows discarded change from parent 1 in test -s actual ' -test_expect_failure 'diff with mergebase shows fully discarded file from parent 2' ' +test_expect_success 'diff with mergebase shows fully discarded file from parent 2' ' git diff --cc merge branch1 branch2 mergebase -- short/win1 >actual && test -s actual ' -test_expect_failure 'diff with mergebase shows fully discarded file from parent 1' ' +test_expect_success 'diff with mergebase shows fully discarded file from parent 1' ' git diff --cc merge branch1 branch2 mergebase -- short/win2 >actual && test -s actual ' |