Skip to content

Commit f2ce9fd

Browse files
Junio C HamanoLinus Torvalds
authored andcommitted
[PATCH] Add --diff-filter= output restriction to diff-* family.
This is a halfway between debugging aid and a helper to write an ultra-smart merge scripts. The new option takes a string that consists of a list of "status" letters, and limits the diff output to only those classes of changes, with two exceptions: - A broken pair (aka "complete rewrite"), does not match D (deleted) or N (created). Use B to look for them. - The letter "A" in the diff-filter string does not match anything itself, but causes the entire diff that contains selected patches to be output (this behaviour is similar to that of --pickaxe-all for the -S option). For example, $ git-rev-list HEAD | git-diff-tree --stdin -s -v -B -C --diff-filter=BCR shows a list of commits that have complete rewrite, copy, or rename. Signed-off-by: Junio C Hamano <junkio@cox.net> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
1 parent a7ca654 commit f2ce9fd

File tree

7 files changed

+108
-21
lines changed

7 files changed

+108
-21
lines changed

diff-cache.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ static const char *pickaxe = NULL;
1111
static int pickaxe_opts = 0;
1212
static int diff_break_opt = -1;
1313
static const char *orderfile = NULL;
14+
static const char *diff_filter = NULL;
1415

1516
/* A file entry went away or appeared */
1617
static void show_file(const char *prefix, struct cache_entry *ce, unsigned char *sha1, unsigned int mode)
@@ -224,6 +225,10 @@ int main(int argc, const char **argv)
224225
pickaxe = arg + 2;
225226
continue;
226227
}
228+
if (!strncmp(arg, "--diff-filter=", 14)) {
229+
diff_filter = arg + 14;
230+
continue;
231+
}
227232
if (!strncmp(arg, "-O", 2)) {
228233
orderfile = arg + 2;
229234
continue;
@@ -263,7 +268,7 @@ int main(int argc, const char **argv)
263268
detect_rename, diff_score_opt,
264269
pickaxe, pickaxe_opts,
265270
diff_break_opt,
266-
orderfile);
267-
diff_flush(diff_output_format, 1);
271+
orderfile, diff_filter);
272+
diff_flush(diff_output_format);
268273
return ret;
269274
}

diff-files.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ static const char *pickaxe = NULL;
1717
static int pickaxe_opts = 0;
1818
static int diff_break_opt = -1;
1919
static const char *orderfile = NULL;
20+
static const char *diff_filter = NULL;
2021
static int silent = 0;
2122

2223
static void show_unmerge(const char *path)
@@ -59,6 +60,8 @@ int main(int argc, const char **argv)
5960
pickaxe = argv[1] + 2;
6061
else if (!strncmp(argv[1], "-O", 2))
6162
orderfile = argv[1] + 2;
63+
else if (!strncmp(argv[1], "--diff-filter=", 14))
64+
diff_filter = argv[1] + 14;
6265
else if (!strcmp(argv[1], "--pickaxe-all"))
6366
pickaxe_opts = DIFF_PICKAXE_ALL;
6467
else if (!strncmp(argv[1], "-B", 2)) {
@@ -131,7 +134,7 @@ int main(int argc, const char **argv)
131134
detect_rename, diff_score_opt,
132135
pickaxe, pickaxe_opts,
133136
diff_break_opt,
134-
orderfile);
135-
diff_flush(diff_output_format, 1);
137+
orderfile, diff_filter);
138+
diff_flush(diff_output_format);
136139
return 0;
137140
}

diff-helper.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,16 @@
88
static const char *pickaxe = NULL;
99
static int pickaxe_opts = 0;
1010
static const char *orderfile = NULL;
11+
static const char *diff_filter = NULL;
1112
static int line_termination = '\n';
1213
static int inter_name_termination = '\t';
1314

1415
static void flush_them(int ac, const char **av)
1516
{
16-
diffcore_std(av + 1,
17-
0, 0, /* no renames */
18-
pickaxe, pickaxe_opts,
19-
-1, /* no breaks */
20-
orderfile);
21-
diff_flush(DIFF_FORMAT_PATCH, 0);
17+
diffcore_std_no_resolve(av + 1,
18+
pickaxe, pickaxe_opts,
19+
orderfile, diff_filter);
20+
diff_flush(DIFF_FORMAT_PATCH);
2221
}
2322

2423
static const char *diff_helper_usage =
@@ -38,6 +37,10 @@ int main(int ac, const char **av) {
3837
}
3938
else if (!strcmp(av[1], "--pickaxe-all"))
4039
pickaxe_opts = DIFF_PICKAXE_ALL;
40+
else if (!strncmp(av[1], "--diff-filter=", 14))
41+
diff_filter = av[1] + 14;
42+
else if (!strncmp(av[1], "-O", 2))
43+
orderfile = av[1] + 2;
4144
else
4245
usage(diff_helper_usage);
4346
ac--; av++;

diff-stages.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ static const char *pickaxe = NULL;
1313
static int pickaxe_opts = 0;
1414
static int diff_break_opt = -1;
1515
static const char *orderfile = NULL;
16+
static const char *diff_filter = NULL;
1617

1718
static char *diff_stages_usage =
1819
"git-diff-stages [-p] [-r] [-z] [-M] [-C] [-R] [-S<string>] [-O<orderfile>] <stage1> <stage2> [<path>...]";
@@ -50,6 +51,8 @@ int main(int ac, const char **av)
5051
pickaxe = arg + 2;
5152
else if (!strncmp(arg, "-O", 2))
5253
orderfile = arg + 2;
54+
else if (!strncmp(arg, "--diff-filter=", 14))
55+
diff_filter = arg + 14;
5356
else if (!strcmp(arg, "--pickaxe-all"))
5457
pickaxe_opts = DIFF_PICKAXE_ALL;
5558
else
@@ -106,7 +109,8 @@ int main(int ac, const char **av)
106109
detect_rename, diff_score_opt,
107110
pickaxe, pickaxe_opts,
108111
diff_break_opt,
109-
orderfile);
110-
diff_flush(diff_output_format, 1);
112+
orderfile,
113+
diff_filter);
114+
diff_flush(diff_output_format);
111115
return 0;
112116
}

diff-tree.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ static const char *pickaxe = NULL;
1818
static int pickaxe_opts = 0;
1919
static int diff_break_opt = -1;
2020
static const char *orderfile = NULL;
21+
static const char *diff_filter = NULL;
2122
static const char *header = NULL;
2223
static const char *header_prefix = "";
2324
static enum cmit_fmt commit_format = CMIT_FMT_RAW;
@@ -272,9 +273,10 @@ static int call_diff_flush(void)
272273
detect_rename, diff_score_opt,
273274
pickaxe, pickaxe_opts,
274275
diff_break_opt,
275-
orderfile);
276+
orderfile,
277+
diff_filter);
276278
if (diff_queue_is_empty()) {
277-
diff_flush(DIFF_FORMAT_NO_OUTPUT, 0);
279+
diff_flush(DIFF_FORMAT_NO_OUTPUT);
278280
return 0;
279281
}
280282
if (header) {
@@ -285,7 +287,7 @@ static int call_diff_flush(void)
285287
printf(fmt, header, 0);
286288
header = NULL;
287289
}
288-
diff_flush(diff_output_format, 1);
290+
diff_flush(diff_output_format);
289291
return 1;
290292
}
291293

@@ -468,6 +470,10 @@ int main(int argc, const char **argv)
468470
orderfile = arg + 2;
469471
continue;
470472
}
473+
if (!strncmp(arg, "--diff-filter=", 14)) {
474+
diff_filter = arg + 14;
475+
continue;
476+
}
471477
if (!strcmp(arg, "--pickaxe-all")) {
472478
pickaxe_opts = DIFF_PICKAXE_ALL;
473479
continue;

diff.c

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -921,7 +921,7 @@ static void diff_resolve_rename_copy(void)
921921
diff_debug_queue("resolve-rename-copy done", q);
922922
}
923923

924-
void diff_flush(int diff_output_style, int resolve_rename_copy)
924+
void diff_flush(int diff_output_style)
925925
{
926926
struct diff_queue_struct *q = &diff_queued_diff;
927927
int i;
@@ -930,8 +930,6 @@ void diff_flush(int diff_output_style, int resolve_rename_copy)
930930

931931
if (diff_output_style == DIFF_FORMAT_MACHINE)
932932
line_termination = inter_name_termination = 0;
933-
if (resolve_rename_copy)
934-
diff_resolve_rename_copy();
935933

936934
for (i = 0; i < q->nr; i++) {
937935
struct diff_filepair *p = q->queue[i];
@@ -958,11 +956,58 @@ void diff_flush(int diff_output_style, int resolve_rename_copy)
958956
q->nr = q->alloc = 0;
959957
}
960958

959+
static void diffcore_apply_filter(const char *filter)
960+
{
961+
int i;
962+
struct diff_queue_struct *q = &diff_queued_diff;
963+
struct diff_queue_struct outq;
964+
outq.queue = NULL;
965+
outq.nr = outq.alloc = 0;
966+
967+
if (!filter)
968+
return;
969+
970+
if (strchr(filter, 'A')) {
971+
/* All-or-none */
972+
int found;
973+
for (i = found = 0; !found && i < q->nr; i++) {
974+
struct diff_filepair *p = q->queue[i];
975+
if ((p->broken_pair && strchr(filter, 'B')) ||
976+
(!p->broken_pair && strchr(filter, p->status)))
977+
found++;
978+
}
979+
if (found)
980+
return;
981+
982+
/* otherwise we will clear the whole queue
983+
* by copying the empty outq at the end of this
984+
* function, but first clear the current entries
985+
* in the queue.
986+
*/
987+
for (i = 0; i < q->nr; i++)
988+
diff_free_filepair(q->queue[i]);
989+
}
990+
else {
991+
/* Only the matching ones */
992+
for (i = 0; i < q->nr; i++) {
993+
struct diff_filepair *p = q->queue[i];
994+
if ((p->broken_pair && strchr(filter, 'B')) ||
995+
(!p->broken_pair && strchr(filter, p->status)))
996+
diff_q(&outq, p);
997+
else
998+
diff_free_filepair(p);
999+
}
1000+
}
1001+
free(q->queue);
1002+
*q = outq;
1003+
}
1004+
9611005
void diffcore_std(const char **paths,
9621006
int detect_rename, int rename_score,
9631007
const char *pickaxe, int pickaxe_opts,
9641008
int break_opt,
965-
const char *orderfile)
1009+
const char *orderfile,
1010+
const char *filter)
9661011
{
9671012
if (paths && paths[0])
9681013
diffcore_pathspec(paths);
@@ -976,6 +1021,23 @@ void diffcore_std(const char **paths,
9761021
diffcore_pickaxe(pickaxe, pickaxe_opts);
9771022
if (orderfile)
9781023
diffcore_order(orderfile);
1024+
diff_resolve_rename_copy();
1025+
diffcore_apply_filter(filter);
1026+
}
1027+
1028+
1029+
void diffcore_std_no_resolve(const char **paths,
1030+
const char *pickaxe, int pickaxe_opts,
1031+
const char *orderfile,
1032+
const char *filter)
1033+
{
1034+
if (paths && paths[0])
1035+
diffcore_pathspec(paths);
1036+
if (pickaxe)
1037+
diffcore_pickaxe(pickaxe, pickaxe_opts);
1038+
if (orderfile)
1039+
diffcore_order(orderfile);
1040+
diffcore_apply_filter(filter);
9791041
}
9801042

9811043
void diff_addremove(int addremove, unsigned mode,

diff.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ extern void diffcore_std(const char **paths,
4747
int detect_rename, int rename_score,
4848
const char *pickaxe, int pickaxe_opts,
4949
int break_opt,
50-
const char *orderfile);
50+
const char *orderfile, const char *filter);
51+
52+
extern void diffcore_std_no_resolve(const char **paths,
53+
const char *pickaxe, int pickaxe_opts,
54+
const char *orderfile, const char *filter);
5155

5256
extern int diff_queue_is_empty(void);
5357

@@ -56,6 +60,6 @@ extern int diff_queue_is_empty(void);
5660
#define DIFF_FORMAT_PATCH 2
5761
#define DIFF_FORMAT_NO_OUTPUT 3
5862

59-
extern void diff_flush(int output_style, int resolve_rename_copy);
63+
extern void diff_flush(int output_style);
6064

6165
#endif /* DIFF_H */

0 commit comments

Comments
 (0)