summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--combine-diff.c43
-rwxr-xr-xt/t4064-diff-oidfind.sh55
2 files changed, 96 insertions, 2 deletions
diff --git a/combine-diff.c b/combine-diff.c
index 002e0e5438..23bca28746 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -1451,6 +1451,42 @@ static struct combine_diff_path *find_paths_multitree(
return paths_head.next;
}
+static int match_objfind(struct combine_diff_path *path,
+ int num_parent,
+ const struct oidset *set)
+{
+ int i;
+ if (oidset_contains(set, &path->oid))
+ return 1;
+ for (i = 0; i < num_parent; i++) {
+ if (oidset_contains(set, &path->parent[i].oid))
+ return 1;
+ }
+ return 0;
+}
+
+static struct combine_diff_path *combined_objfind(struct diff_options *opt,
+ struct combine_diff_path *paths,
+ int num_parent)
+{
+ struct combine_diff_path *ret = NULL, **tail = &ret;
+ struct combine_diff_path *p = paths;
+
+ while (p) {
+ struct combine_diff_path *next = p->next;
+
+ if (match_objfind(p, num_parent, opt->objfind)) {
+ p->next = NULL;
+ *tail = p;
+ tail = &p->next;
+ } else {
+ free(p);
+ }
+ p = next;
+ }
+
+ return ret;
+}
void diff_tree_combined(const struct object_id *oid,
const struct oid_array *parents,
@@ -1506,10 +1542,10 @@ void diff_tree_combined(const struct object_id *oid,
opt->flags.follow_renames ||
opt->break_opt != -1 ||
opt->detect_rename ||
- (opt->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK) ||
+ (opt->pickaxe_opts &
+ (DIFF_PICKAXE_KINDS_MASK & ~DIFF_PICKAXE_KIND_OBJFIND)) ||
opt->filter;
-
if (need_generic_pathscan) {
/*
* NOTE generic case also handles --stat, as it computes
@@ -1523,6 +1559,9 @@ void diff_tree_combined(const struct object_id *oid,
int stat_opt;
paths = find_paths_multitree(oid, parents, &diffopts);
+ if (opt->pickaxe_opts & DIFF_PICKAXE_KIND_OBJFIND)
+ paths = combined_objfind(opt, paths, num_parent);
+
/*
* show stat against the first parent even
* when doing combined diff.
diff --git a/t/t4064-diff-oidfind.sh b/t/t4064-diff-oidfind.sh
index 3bdf317af8..6d8c8986fc 100755
--- a/t/t4064-diff-oidfind.sh
+++ b/t/t4064-diff-oidfind.sh
@@ -65,4 +65,59 @@ test_expect_success 'find a submodule' '
test_cmp expect actual
'
+test_expect_success 'set up merge tests' '
+ test_commit base &&
+
+ git checkout -b boring base^ &&
+ echo boring >file &&
+ git add file &&
+ git commit -m boring &&
+
+ git checkout -b interesting base^ &&
+ echo interesting >file &&
+ git add file &&
+ git commit -m interesting &&
+
+ blob=$(git rev-parse interesting:file)
+'
+
+test_expect_success 'detect merge which introduces blob' '
+ git checkout -B merge base &&
+ git merge --no-commit boring &&
+ echo interesting >file &&
+ git commit -am "introduce blob" &&
+ git diff-tree --format=%s --find-object=$blob -c --name-status HEAD >actual &&
+ cat >expect <<-\EOF &&
+ introduce blob
+
+ AM file
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'detect merge which removes blob' '
+ git checkout -B merge interesting &&
+ git merge --no-commit base &&
+ echo boring >file &&
+ git commit -am "remove blob" &&
+ git diff-tree --format=%s --find-object=$blob -c --name-status HEAD >actual &&
+ cat >expect <<-\EOF &&
+ remove blob
+
+ MA file
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'do not detect merge that does not touch blob' '
+ git checkout -B merge interesting &&
+ git merge -m "untouched blob" base &&
+ git diff-tree --format=%s --find-object=$blob -c --name-status HEAD >actual &&
+ cat >expect <<-\EOF &&
+ untouched blob
+
+ EOF
+ test_cmp expect actual
+'
+
test_done