two->path, strlen(two->path), two->mode);
}
-static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)
+static int filename_changed(char status)
+{
+ return status == 'R' || status == 'C';
+}
+
+static struct combine_diff_path *intersect_paths(
+ struct combine_diff_path *curr,
+ int n,
+ int num_parent,
+ int combined_all_paths)
{
struct diff_queue_struct *q = &diff_queued_diff;
struct combine_diff_path *p, **tail = &curr;
- int i, cmp;
+ int i, j, cmp;
if (!n) {
for (i = 0; i < q->nr; i++) {
oidcpy(&p->parent[n].oid, &q->queue[i]->one->oid);
p->parent[n].mode = q->queue[i]->one->mode;
p->parent[n].status = q->queue[i]->status;
+
+ if (combined_all_paths &&
+ filename_changed(p->parent[n].status)) {
+ strbuf_init(&p->parent[n].path, 0);
+ strbuf_addstr(&p->parent[n].path,
+ q->queue[i]->one->path);
+ }
*tail = p;
tail = &p->next;
}
if (cmp < 0) {
/* p->path not in q->queue[]; drop it */
*tail = p->next;
+ for (j = 0; j < num_parent; j++)
+ if (combined_all_paths &&
+ filename_changed(p->parent[j].status))
+ strbuf_release(&p->parent[j].path);
free(p);
continue;
}
oidcpy(&p->parent[n].oid, &q->queue[i]->one->oid);
p->parent[n].mode = q->queue[i]->one->mode;
p->parent[n].status = q->queue[i]->status;
+ if (combined_all_paths &&
+ filename_changed(p->parent[n].status))
+ strbuf_addstr(&p->parent[n].path,
+ q->queue[i]->one->path);
tail = &p->next;
i++;
if (!show_file_header)
return;
- if (added)
- dump_quoted_path("--- ", "", "/dev/null",
- line_prefix, c_meta, c_reset);
- else
- dump_quoted_path("--- ", a_prefix, elem->path,
- line_prefix, c_meta, c_reset);
+ if (rev->combined_all_paths) {
+ for (i = 0; i < num_parent; i++) {
+ char *path = filename_changed(elem->parent[i].status)
+ ? elem->parent[i].path.buf : elem->path;
+ if (elem->parent[i].status == DIFF_STATUS_ADDED)
+ dump_quoted_path("--- ", "", "/dev/null",
+ line_prefix, c_meta, c_reset);
+ else
+ dump_quoted_path("--- ", a_prefix, path,
+ line_prefix, c_meta, c_reset);
+ }
+ } else {
+ if (added)
+ dump_quoted_path("--- ", "", "/dev/null",
+ line_prefix, c_meta, c_reset);
+ else
+ dump_quoted_path("--- ", a_prefix, elem->path,
+ line_prefix, c_meta, c_reset);
+ }
if (deleted)
dump_quoted_path("+++ ", "", "/dev/null",
line_prefix, c_meta, c_reset);
putchar(inter_name_termination);
}
+ for (i = 0; i < num_parent; i++)
+ if (rev->combined_all_paths) {
+ if (filename_changed(p->parent[i].status))
+ write_name_quoted(p->parent[i].path.buf, stdout,
+ inter_name_termination);
+ else
+ write_name_quoted(p->path, stdout,
+ inter_name_termination);
+ }
write_name_quoted(p->path, stdout, line_termination);
}
return path->path;
}
+/*
+ * Diff stat formats which we always compute solely against the first parent.
+ */
+#define STAT_FORMAT_MASK (DIFF_FORMAT_NUMSTAT \
+ | DIFF_FORMAT_SHORTSTAT \
+ | DIFF_FORMAT_SUMMARY \
+ | DIFF_FORMAT_DIRSTAT \
+ | DIFF_FORMAT_DIFFSTAT)
/* find set of paths that every parent touches */
static struct combine_diff_path *find_paths_generic(const struct object_id *oid,
- const struct oid_array *parents, struct diff_options *opt)
+ const struct oid_array *parents,
+ struct diff_options *opt,
+ int combined_all_paths)
{
struct combine_diff_path *paths = NULL;
int i, num_parent = parents->nr;
* show stat against the first parent even when doing
* combined diff.
*/
- int stat_opt = (output_format &
- (DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT));
+ int stat_opt = output_format & STAT_FORMAT_MASK;
if (i == 0 && stat_opt)
opt->output_format = stat_opt;
else
opt->output_format = DIFF_FORMAT_NO_OUTPUT;
diff_tree_oid(&parents->oid[i], oid, "", opt);
diffcore_std(opt);
- paths = intersect_paths(paths, i, num_parent);
+ paths = intersect_paths(paths, i, num_parent,
+ combined_all_paths);
/* if showing diff, show it in requested order */
if (opt->output_format != DIFF_FORMAT_NO_OUTPUT &&
* diff(sha1,parent_i) for all i to do the job, specifically
* for parent0.
*/
- paths = find_paths_generic(oid, parents, &diffopts);
+ paths = find_paths_generic(oid, parents, &diffopts,
+ rev->combined_all_paths);
}
else {
int stat_opt;
* show stat against the first parent even
* when doing combined diff.
*/
- stat_opt = (opt->output_format &
- (DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT));
+ stat_opt = opt->output_format & STAT_FORMAT_MASK;
if (stat_opt) {
diffopts.output_format = stat_opt;
show_raw_diff(p, num_parent, rev);
needsep = 1;
}
- else if (opt->output_format &
- (DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT))
+ else if (opt->output_format & STAT_FORMAT_MASK)
needsep = 1;
else if (opt->output_format & DIFF_FORMAT_CALLBACK)
handle_combined_callback(opt, paths, num_parent, num_paths);
while (paths) {
struct combine_diff_path *tmp = paths;
paths = paths->next;
+ for (i = 0; i < num_parent; i++)
+ if (rev->combined_all_paths &&
+ filename_changed(tmp->parent[i].status))
+ strbuf_release(&tmp->parent[i].path);
free(tmp);
}