diff-merges: let new options enable diff without -p

New options don't have any visible effect unless -p is either given or implied, as unlike -c/-cc we don't imply -p with --diff-merges. To fix this, this patch adds new functionality by letting new options enable output of diffs for merge commits only. Add 'merges_need_diff' field and set it whenever diff output for merges is enabled by any of the new options. Extend diff output logic accordingly, to output diffs for merges when 'merges_need_diff' is set even when no -p has been provided. Signed-off-by: Sergey Organov <sorganov@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Sergey Organov committed Dec 21, 2020 at 18:19 UTC a6d19ecc6b7715b50b0dced7e3d2923a8797df64
3 files changed +22 -9
diff-merges.c
+12 -5
@@ -10,6 +10,7 @@ static void suppress(struct rev_info *revs)
10 revs->dense_combined_merges = 0;
11 revs->combined_all_paths = 0;
12 revs->combined_imply_patch = 0;
13 + revs->merges_need_diff = 0;
14 }
15
16 static void set_separate(struct rev_info *revs)
@@ -51,9 +52,13 @@ static void set_dense_combined(struct rev_info *revs)
52
53 static void set_diff_merges(struct rev_info *revs, const char *optarg)
54 {
54 - if (!strcmp(optarg, "off") || !strcmp(optarg, "none"))
55 + if (!strcmp(optarg, "off") || !strcmp(optarg, "none")) {
56 suppress(revs);
56 - else if (!strcmp(optarg, "first-parent"))
57 + /* Return early to leave revs->merges_need_diff unset */
58 + return;
59 + }
60 +
61 + if (!strcmp(optarg, "first-parent"))
62 set_first_parent(revs);
63 else if (!strcmp(optarg, "separate"))
64 set_separate(revs);
@@ -63,6 +68,9 @@ static void set_diff_merges(struct rev_info *revs, const char *optarg)
68 set_dense_combined(revs);
69 else
70 die(_("unknown value for --diff-merges: %s"), optarg);
71 +
72 + /* The flag is cleared by set_xxx() functions, so don't move this up */
73 + revs->merges_need_diff = 1;
74 }
75
76 /*
@@ -129,10 +137,9 @@ void diff_merges_setup_revs(struct rev_info *revs)
137 revs->first_parent_merges = 0;
138 if (revs->combined_all_paths && !revs->combine_merges)
139 die("--combined-all-paths makes no sense without -c or --cc");
132 - if (revs->combine_merges)
140 + if (revs->combined_imply_patch)
141 revs->diff = 1;
134 - if (revs->combined_imply_patch) {
135 - /* Turn --cc/-c into -p --cc/-c when -p was not given */
142 + if (revs->combined_imply_patch || revs->merges_need_diff) {
143 if (!revs->diffopt.output_format)
144 revs->diffopt.output_format = DIFF_FORMAT_PATCH;
145 }
log-tree.c
+9 -4
@@ -899,15 +899,21 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
899 int showed_log;
900 struct commit_list *parents;
901 struct object_id *oid;
902 + int is_merge;
903 + int all_need_diff = opt->diff || opt->diffopt.flags.exit_with_status;
904
903 - if (!opt->diff && !opt->diffopt.flags.exit_with_status)
905 + if (!all_need_diff && !opt->merges_need_diff)
906 return 0;
907
908 parse_commit_or_die(commit);
909 oid = get_commit_tree_oid(commit);
910
909 - /* Root commit? */
911 parents = get_saved_parents(opt, commit);
912 + is_merge = parents && parents->next;
913 + if (!is_merge && !all_need_diff)
914 + return 0;
915 +
916 + /* Root commit? */
917 if (!parents) {
918 if (opt->show_root_diff) {
919 diff_root_tree_oid(oid, "", &opt->diffopt);
@@ -916,8 +922,7 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
922 return !opt->loginfo;
923 }
924
919 - /* More than one parent? */
920 - if (parents->next) {
925 + if (is_merge) {
926 if (opt->combine_merges)
927 return do_diff_combined(opt, commit);
928 if (opt->separate_merges) {
revision.h
+1
@@ -194,6 +194,7 @@ struct rev_info {
194 always_show_header:1,
195 /* Diff-merge flags */
196 explicit_diff_merges: 1,
197 + merges_need_diff: 1,
198 separate_merges: 1,
199 combine_merges:1,
200 combined_all_paths:1,