diff options
author | Junio C Hamano <junkio@cox.net> | 2005-06-11 20:57:13 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-12 20:40:20 -0700 |
commit | f2ce9fde57513af026e0641073a6781a086251d5 (patch) | |
tree | 5a6e33c33717880fc6af64af378bb373bdf8e065 /diff.c | |
parent | a7ca65405c364e674cf4359b07ae959d4ece01ab (diff) | |
download | git-f2ce9fde57513af026e0641073a6781a086251d5.tar.gz git-f2ce9fde57513af026e0641073a6781a086251d5.tar.xz |
[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>
Diffstat (limited to 'diff.c')
-rw-r--r-- | diff.c | 70 |
1 files changed, 66 insertions, 4 deletions
@@ -921,7 +921,7 @@ static void diff_resolve_rename_copy(void) diff_debug_queue("resolve-rename-copy done", q); } -void diff_flush(int diff_output_style, int resolve_rename_copy) +void diff_flush(int diff_output_style) { struct diff_queue_struct *q = &diff_queued_diff; int i; @@ -930,8 +930,6 @@ void diff_flush(int diff_output_style, int resolve_rename_copy) if (diff_output_style == DIFF_FORMAT_MACHINE) line_termination = inter_name_termination = 0; - if (resolve_rename_copy) - diff_resolve_rename_copy(); for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; @@ -958,11 +956,58 @@ void diff_flush(int diff_output_style, int resolve_rename_copy) q->nr = q->alloc = 0; } +static void diffcore_apply_filter(const char *filter) +{ + int i; + struct diff_queue_struct *q = &diff_queued_diff; + struct diff_queue_struct outq; + outq.queue = NULL; + outq.nr = outq.alloc = 0; + + if (!filter) + return; + + if (strchr(filter, 'A')) { + /* All-or-none */ + int found; + for (i = found = 0; !found && i < q->nr; i++) { + struct diff_filepair *p = q->queue[i]; + if ((p->broken_pair && strchr(filter, 'B')) || + (!p->broken_pair && strchr(filter, p->status))) + found++; + } + if (found) + return; + + /* otherwise we will clear the whole queue + * by copying the empty outq at the end of this + * function, but first clear the current entries + * in the queue. + */ + for (i = 0; i < q->nr; i++) + diff_free_filepair(q->queue[i]); + } + else { + /* Only the matching ones */ + for (i = 0; i < q->nr; i++) { + struct diff_filepair *p = q->queue[i]; + if ((p->broken_pair && strchr(filter, 'B')) || + (!p->broken_pair && strchr(filter, p->status))) + diff_q(&outq, p); + else + diff_free_filepair(p); + } + } + free(q->queue); + *q = outq; +} + void diffcore_std(const char **paths, int detect_rename, int rename_score, const char *pickaxe, int pickaxe_opts, int break_opt, - const char *orderfile) + const char *orderfile, + const char *filter) { if (paths && paths[0]) diffcore_pathspec(paths); @@ -976,6 +1021,23 @@ void diffcore_std(const char **paths, diffcore_pickaxe(pickaxe, pickaxe_opts); if (orderfile) diffcore_order(orderfile); + diff_resolve_rename_copy(); + diffcore_apply_filter(filter); +} + + +void diffcore_std_no_resolve(const char **paths, + const char *pickaxe, int pickaxe_opts, + const char *orderfile, + const char *filter) +{ + if (paths && paths[0]) + diffcore_pathspec(paths); + if (pickaxe) + diffcore_pickaxe(pickaxe, pickaxe_opts); + if (orderfile) + diffcore_order(orderfile); + diffcore_apply_filter(filter); } void diff_addremove(int addremove, unsigned mode, |