diff options
Diffstat (limited to 'combine-diff.c')
| -rw-r--r-- | combine-diff.c | 163 |
1 files changed, 129 insertions, 34 deletions
diff --git a/combine-diff.c b/combine-diff.c index ad7752ea6b..9228aebc16 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -10,7 +10,7 @@ #include "log-tree.h" #include "refs.h" #include "userdiff.h" -#include "sha1-array.h" +#include "oid-array.h" #include "revision.h" static int compare_paths(const struct combine_diff_path *one, @@ -23,11 +23,20 @@ static int compare_paths(const struct combine_diff_path *one, 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++) { @@ -50,6 +59,13 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, 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; } @@ -68,6 +84,10 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, 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; } @@ -81,6 +101,10 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, 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++; @@ -899,14 +923,13 @@ static void dump_quoted_path(const char *head, static void show_combined_header(struct combine_diff_path *elem, int num_parent, - int dense, struct rev_info *rev, const char *line_prefix, int mode_differs, int show_file_header) { struct diff_options *opt = &rev->diffopt; - int abbrev = opt->flags.full_index ? GIT_SHA1_HEXSZ : DEFAULT_ABBREV; + int abbrev = opt->flags.full_index ? the_hash_algo->hexsz : DEFAULT_ABBREV; const char *a_prefix = opt->a_prefix ? opt->a_prefix : "a/"; const char *b_prefix = opt->b_prefix ? opt->b_prefix : "b/"; const char *c_meta = diff_get_color_opt(opt, DIFF_METAINFO); @@ -915,6 +938,7 @@ static void show_combined_header(struct combine_diff_path *elem, int added = 0; int deleted = 0; int i; + int dense = rev->dense_combined_merges; if (rev->loginfo && !rev->no_commit_id) show_log(rev); @@ -960,12 +984,25 @@ static void show_combined_header(struct combine_diff_path *elem, 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); @@ -975,7 +1012,7 @@ static void show_combined_header(struct combine_diff_path *elem, } static void show_patch_diff(struct combine_diff_path *elem, int num_parent, - int dense, int working_tree_file, + int working_tree_file, struct rev_info *rev) { struct diff_options *opt = &rev->diffopt; @@ -996,7 +1033,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, if (!userdiff) userdiff = userdiff_find_by_name("default"); if (opt->flags.allow_textconv) - textconv = userdiff_get_textconv(userdiff); + textconv = userdiff_get_textconv(opt->repo, userdiff); /* Read the result of merge first */ if (!working_tree_file) @@ -1108,7 +1145,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, } } if (is_binary) { - show_combined_header(elem, num_parent, dense, rev, + show_combined_header(elem, num_parent, rev, line_prefix, mode_differs, 0); printf("Binary files differ\n"); free(result); @@ -1163,10 +1200,10 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, textconv, elem->path, opt->xdl_opts); } - show_hunks = make_hunks(sline, cnt, num_parent, dense); + show_hunks = make_hunks(sline, cnt, num_parent, rev->dense_combined_merges); if (show_hunks || mode_differs || working_tree_file) { - show_combined_header(elem, num_parent, dense, rev, + show_combined_header(elem, num_parent, rev, line_prefix, mode_differs, 1); dump_sline(sline, line_prefix, cnt, num_parent, opt->use_color, result_deleted); @@ -1227,6 +1264,15 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re 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); } @@ -1238,7 +1284,6 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re */ void show_combined_diff(struct combine_diff_path *p, int num_parent, - int dense, struct rev_info *rev) { struct diff_options *opt = &rev->diffopt; @@ -1248,7 +1293,7 @@ void show_combined_diff(struct combine_diff_path *p, DIFF_FORMAT_NAME_STATUS)) show_raw_diff(p, num_parent, rev); else if (opt->output_format & DIFF_FORMAT_PATCH) - show_patch_diff(p, num_parent, dense, 1, rev); + show_patch_diff(p, num_parent, 1, rev); } static void free_combined_pair(struct diff_filepair *pair) @@ -1321,10 +1366,20 @@ static const char *path_path(void *obj) 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; @@ -1342,15 +1397,15 @@ static struct combine_diff_path *find_paths_generic(const struct object_id *oid, * 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 && @@ -1395,10 +1450,45 @@ 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, - int dense, struct rev_info *rev) { struct diff_options *opt = &rev->diffopt; @@ -1450,28 +1540,31 @@ 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 * 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; 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. */ - 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; @@ -1515,8 +1608,7 @@ void diff_tree_combined(const struct object_id *oid, 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); @@ -1526,8 +1618,7 @@ void diff_tree_combined(const struct object_id *oid, printf("%s%c", diff_line_prefix(opt), opt->line_termination); for (p = paths; p; p = p->next) - show_patch_diff(p, num_parent, dense, - 0, rev); + show_patch_diff(p, num_parent, 0, rev); } } @@ -1535,13 +1626,17 @@ void diff_tree_combined(const struct object_id *oid, 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); } clear_pathspec(&diffopts.pathspec); } -void diff_tree_combined_merge(const struct commit *commit, int dense, +void diff_tree_combined_merge(const struct commit *commit, struct rev_info *rev) { struct commit_list *parent = get_saved_parents(rev, commit); @@ -1551,6 +1646,6 @@ void diff_tree_combined_merge(const struct commit *commit, int dense, oid_array_append(&parents, &parent->item->object.oid); parent = parent->next; } - diff_tree_combined(&commit->object.oid, &parents, dense, rev); + diff_tree_combined(&commit->object.oid, &parents, rev); oid_array_clear(&parents); } |
