Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

combine-diff: support format_callback

This teaches combine-diff machinery to feed a combined merge to a callback
function when DIFF_FORMAT_CALLBACK is specified.

So far, format callback functions are not used for anything but 2-way
diffs. A callback is given a diff_queue_struct, which is an array of
diff_filepair. As its name suggests, a diff_filepair is a _pair_ of
diff_filespec that represents a single preimage and a single postimage.

Since "diff -c" is to compare N parents with a single merge result and
filter out any paths whose result match one (or more) of the parent(s),
its output has to be able to represent N preimages and 1 postimage. For
this reason, a callback function that inspects a diff_filepair that
results from this new infrastructure can and is expected to view the
preimage side (i.e. pair->one) as an array of diff_filespec. Each element
in the array, except for the last one, is marked with "has_more_entries"
bit, so that the same callback function can be used for 2-way diffs and
combined diffs.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information...
commit 25e5e2bf85c8a2c2c8945935267539940c11020d 1 parent 0906f6e
@gitster gitster authored
Showing with 70 additions and 1 deletion.
  1. +69 −0 combine-diff.c
  2. +1 −1  diffcore.h
View
69 combine-diff.c
@@ -970,6 +970,72 @@ void show_combined_diff(struct combine_diff_path *p,
show_patch_diff(p, num_parent, dense, rev);
}
+static void free_combined_pair(struct diff_filepair *pair)
+{
+ free(pair->two);
+ free(pair);
+}
+
+/*
+ * A combine_diff_path expresses N parents on the LHS against 1 merge
+ * result. Synthesize a diff_filepair that has N entries on the "one"
+ * side and 1 entry on the "two" side.
+ *
+ * In the future, we might want to add more data to combine_diff_path
+ * so that we can fill fields we are ignoring (most notably, size) here,
+ * but currently nobody uses it, so this should suffice for now.
+ */
+static struct diff_filepair *combined_pair(struct combine_diff_path *p,
+ int num_parent)
+{
+ int i;
+ struct diff_filepair *pair;
+ struct diff_filespec *pool;
+
+ pair = xmalloc(sizeof(*pair));
+ pool = xcalloc(num_parent + 1, sizeof(struct diff_filespec));
+ pair->one = pool + 1;
+ pair->two = pool;
+
+ for (i = 0; i < num_parent; i++) {
+ pair->one[i].path = p->path;
+ pair->one[i].mode = p->parent[i].mode;
+ hashcpy(pair->one[i].sha1, p->parent[i].sha1);
+ pair->one[i].sha1_valid = !is_null_sha1(p->parent[i].sha1);
+ pair->one[i].has_more_entries = 1;
+ }
+ pair->one[num_parent - 1].has_more_entries = 0;
+
+ pair->two->path = p->path;
+ pair->two->mode = p->mode;
+ hashcpy(pair->two->sha1, p->sha1);
+ pair->two->sha1_valid = !is_null_sha1(p->sha1);
+ return pair;
+}
+
+static void handle_combined_callback(struct diff_options *opt,
+ struct combine_diff_path *paths,
+ int num_parent,
+ int num_paths)
+{
+ struct combine_diff_path *p;
+ struct diff_queue_struct q;
+ int i;
+
+ q.queue = xcalloc(num_paths, sizeof(struct diff_filepair *));
+ q.alloc = num_paths;
+ q.nr = num_paths;
+ for (i = 0, p = paths; p; p = p->next) {
+ if (!p->len)
+ continue;
+ q.queue[i++] = combined_pair(p, num_parent);
+ }
+ opt->format_callback(&q, opt, opt->format_callback_data);
+ for (i = 0; i < num_paths; i++)
+ free_combined_pair(q.queue[i]);
+ free(q.queue);
+}
+
void diff_tree_combined(const unsigned char *sha1,
const unsigned char parent[][20],
int num_parent,
@@ -1029,6 +1095,9 @@ void diff_tree_combined(const unsigned char *sha1,
else if (opt->output_format &
(DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT))
needsep = 1;
+ else if (opt->output_format & DIFF_FORMAT_CALLBACK)
+ handle_combined_callback(opt, paths, num_parent, num_paths);
+
if (opt->output_format & DIFF_FORMAT_PATCH) {
if (needsep)
putchar(opt->line_termination);
View
2  diffcore.h
@@ -45,7 +45,7 @@ struct diff_filespec {
unsigned dirty_submodule : 2; /* For submodules: its work tree is dirty */
#define DIRTY_SUBMODULE_UNTRACKED 1
#define DIRTY_SUBMODULE_MODIFIED 2
-
+ unsigned has_more_entries : 1; /* only appear in combined diff */
struct userdiff_driver *driver;
/* data should be considered "binary"; -1 means "don't know yet" */
int is_binary;
Please sign in to comment.
Something went wrong with that request. Please try again.