diff options
Diffstat (limited to 'combine-diff.c')
-rw-r--r-- | combine-diff.c | 90 |
1 files changed, 82 insertions, 8 deletions
diff --git a/combine-diff.c b/combine-diff.c index be67cfcd4..214014dc6 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -702,9 +702,8 @@ static void show_combined_header(struct combine_diff_path *elem, int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV; const char *a_prefix = opt->a_prefix ? opt->a_prefix : "a/"; const char *b_prefix = opt->b_prefix ? opt->b_prefix : "b/"; - int use_color = DIFF_OPT_TST(opt, COLOR_DIFF); - const char *c_meta = diff_get_color(use_color, DIFF_METAINFO); - const char *c_reset = diff_get_color(use_color, DIFF_RESET); + const char *c_meta = diff_get_color_opt(opt, DIFF_METAINFO); + const char *c_reset = diff_get_color_opt(opt, DIFF_RESET); const char *abb; int added = 0; int deleted = 0; @@ -768,7 +767,8 @@ 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, struct rev_info *rev) + int dense, int working_tree_file, + struct rev_info *rev) { struct diff_options *opt = &rev->diffopt; unsigned long result_size, cnt, lno; @@ -777,7 +777,6 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, struct sline *sline; /* survived lines */ int mode_differs = 0; int i, show_hunks; - int working_tree_file = is_null_sha1(elem->sha1); mmfile_t result_file; struct userdiff_driver *userdiff; struct userdiff_driver *textconv = NULL; @@ -964,7 +963,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, show_combined_header(elem, num_parent, dense, rev, mode_differs, 1); dump_sline(sline, cnt, num_parent, - DIFF_OPT_TST(opt, COLOR_DIFF), result_deleted); + opt->use_color, result_deleted); } free(result); @@ -1028,6 +1027,12 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re write_name_quoted(p->path, stdout, line_termination); } +/* + * The result (p->elem) is from the working tree and their + * parents are typically from multiple stages during a merge + * (i.e. diff-files) or the state in HEAD and in the index + * (i.e. diff-index). + */ void show_combined_diff(struct combine_diff_path *p, int num_parent, int dense, @@ -1041,7 +1046,73 @@ 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, rev); + show_patch_diff(p, num_parent, dense, 1, 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, @@ -1103,13 +1174,16 @@ 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); for (p = paths; p; p = p->next) { if (p->len) show_patch_diff(p, num_parent, dense, - rev); + 0, rev); } } } |