From af5323e0274fad058f13949b89a9191a7bef7e38 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 30 May 2005 00:09:07 -0700 Subject: [PATCH] [PATCH] Add -O option to diff-* brothers. A new diffcore filter diffcore-order is introduced. This takes a text file each of whose line is a shell glob pattern. Patches that match a glob pattern on an earlier line in the file are output before patches that match a later line, and patches that do not match any glob pattern are output last. A typical orderfile for git project probably should look like this: README Makefile Documentation *.h *.c Signed-off-by: Junio C Hamano Signed-off-by: Linus Torvalds --- Documentation/git-diff-cache.txt | 6 +- Documentation/git-diff-files.txt | 6 +- Documentation/git-diff-tree.txt | 6 +- Makefile | 3 +- diff-cache.c | 8 +- diff-files.c | 6 +- diff-tree.c | 8 +- diff.c | 5 +- diff.h | 7 +- diffcore-order.c | 122 +++++++++++++++++++++++++++++++ 10 files changed, 167 insertions(+), 10 deletions(-) create mode 100644 diffcore-order.c diff --git a/Documentation/git-diff-cache.txt b/Documentation/git-diff-cache.txt index 10cbc9ff9..9c7832f6e 100644 --- a/Documentation/git-diff-cache.txt +++ b/Documentation/git-diff-cache.txt @@ -9,7 +9,7 @@ git-diff-cache - Compares content and mode of blobs between the cache and reposi SYNOPSIS -------- -'git-diff-cache' [-p] [-r] [-z] [-m] [-B] [-M] [-R] [-C] [-S] [--pickaxe-all] [--cached] [...] +'git-diff-cache' [-p] [-r] [-z] [-m] [-B] [-M] [-R] [-C] [-O] [-S] [--pickaxe-all] [--cached] [...] DESCRIPTION ----------- @@ -52,6 +52,10 @@ OPTIONS changeset, not just the files that contains the change in . +-O:: + Output the patch in the order specified in the + , which has one shell glob pattern per line. + -R:: Output diff in reverse. diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.txt index ba257e8fb..8439355b0 100644 --- a/Documentation/git-diff-files.txt +++ b/Documentation/git-diff-files.txt @@ -9,7 +9,7 @@ git-diff-files - Compares files in the working tree and the cache SYNOPSIS -------- -'git-diff-files' [-p] [-q] [-r] [-z] [-B] [-M] [-C] [-R] [-S] [--pickaxe-all] [...] +'git-diff-files' [-p] [-q] [-r] [-z] [-B] [-M] [-C] [-R] [-O] [-S] [--pickaxe-all] [...] DESCRIPTION ----------- @@ -46,6 +46,10 @@ OPTIONS changeset, not just the files that contains the change in . +-O:: + Output the patch in the order specified in the + , which has one shell glob pattern per line. + -r:: This flag does not mean anything. It is there only to match git-diff-tree. Unlike git-diff-tree, git-diff-files always looks diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt index f23694919..9e038856e 100644 --- a/Documentation/git-diff-tree.txt +++ b/Documentation/git-diff-tree.txt @@ -9,7 +9,7 @@ git-diff-tree - Compares the content and mode of blobs found via two tree object SYNOPSIS -------- -'git-diff-tree' [-p] [-r] [-z] [--stdin] [-B] [-M] [-R] [-C] [-S] [--pickaxe-all] [-m] [-s] [-v] [-t] []\* +'git-diff-tree' [-p] [-r] [-z] [--stdin] [-B] [-M] [-R] [-C] [-O] [-S] [--pickaxe-all] [-m] [-s] [-v] [-t] []\* DESCRIPTION ----------- @@ -53,6 +53,10 @@ OPTIONS changeset, not just the files that contains the change in . +-O:: + Output the patch in the order specified in the + , which has one shell glob pattern per line. + -r:: recurse diff --git a/Makefile b/Makefile index ba75d6732..a320a8814 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ LIB_OBJS += strbuf.o LIB_H += diff.h count-delta.h LIB_OBJS += diff.o diffcore-rename.o diffcore-pickaxe.o diffcore-pathspec.o \ - count-delta.o diffcore-break.o + count-delta.o diffcore-break.o diffcore-order.o LIB_OBJS += gitenv.o @@ -132,6 +132,7 @@ diffcore-rename.o : $(LIB_H) diffcore.h diffcore-pathspec.o : $(LIB_H) diffcore.h diffcore-pickaxe.o : $(LIB_H) diffcore.h diffcore-break.o : $(LIB_H) diffcore.h +diffcore-order.o : $(LIB_H) diffcore.h test: all $(MAKE) -C t/ all diff --git a/diff-cache.c b/diff-cache.c index 7d067a8f4..2aaf16a39 100644 --- a/diff-cache.c +++ b/diff-cache.c @@ -10,6 +10,7 @@ static int diff_score_opt = 0; static const char *pickaxe = NULL; static int pickaxe_opts = 0; static int diff_break_opt = -1; +static const char *orderfile = NULL; /* A file entry went away or appeared */ static void show_file(const char *prefix, struct cache_entry *ce, unsigned char *sha1, unsigned int mode) @@ -215,6 +216,10 @@ int main(int argc, const char **argv) pickaxe = arg + 2; continue; } + if (!strncmp(arg, "-O", 2)) { + orderfile = arg + 2; + continue; + } if (!strcmp(arg, "--pickaxe-all")) { pickaxe_opts = DIFF_PICKAXE_ALL; continue; @@ -249,7 +254,8 @@ int main(int argc, const char **argv) diffcore_std(pathspec ? : NULL, detect_rename, diff_score_opt, pickaxe, pickaxe_opts, - diff_break_opt); + diff_break_opt, + orderfile); diff_flush(diff_output_format, 1); return ret; } diff --git a/diff-files.c b/diff-files.c index b840b35d1..f3a79e5c0 100644 --- a/diff-files.c +++ b/diff-files.c @@ -16,6 +16,7 @@ static int diff_score_opt = 0; static const char *pickaxe = NULL; static int pickaxe_opts = 0; static int diff_break_opt = -1; +static const char *orderfile = NULL; static int silent = 0; static void show_unmerge(const char *path) @@ -56,6 +57,8 @@ int main(int argc, const char **argv) diff_setup_opt |= DIFF_SETUP_REVERSE; else if (!strncmp(argv[1], "-S", 2)) pickaxe = argv[1] + 2; + else if (!strncmp(argv[1], "-O", 2)) + orderfile = argv[1] + 2; else if (!strcmp(argv[1], "--pickaxe-all")) pickaxe_opts = DIFF_PICKAXE_ALL; else if (!strncmp(argv[1], "-B", 2)) @@ -122,7 +125,8 @@ int main(int argc, const char **argv) diffcore_std((1 < argc) ? argv + 1 : NULL, detect_rename, diff_score_opt, pickaxe, pickaxe_opts, - diff_break_opt); + diff_break_opt, + orderfile); diff_flush(diff_output_format, 1); return 0; } diff --git a/diff-tree.c b/diff-tree.c index c33f54a2d..ec2c07817 100644 --- a/diff-tree.c +++ b/diff-tree.c @@ -15,6 +15,7 @@ static int diff_score_opt = 0; static const char *pickaxe = NULL; static int pickaxe_opts = 0; static int diff_break_opt = -1; +static const char *orderfile = NULL; static const char *header = NULL; static const char *header_prefix = ""; @@ -265,7 +266,8 @@ static int call_diff_flush(void) diffcore_std(0, detect_rename, diff_score_opt, pickaxe, pickaxe_opts, - diff_break_opt); + diff_break_opt, + orderfile); if (diff_queue_is_empty()) { diff_flush(DIFF_FORMAT_NO_OUTPUT, 0); return 0; @@ -511,6 +513,10 @@ int main(int argc, const char **argv) pickaxe = arg + 2; continue; } + if (!strncmp(arg, "-O", 2)) { + orderfile = arg + 2; + continue; + } if (!strcmp(arg, "--pickaxe-all")) { pickaxe_opts = DIFF_PICKAXE_ALL; continue; diff --git a/diff.c b/diff.c index 38a1babd5..d5881c777 100644 --- a/diff.c +++ b/diff.c @@ -888,7 +888,8 @@ void diff_flush(int diff_output_style, int resolve_rename_copy) void diffcore_std(const char **paths, int detect_rename, int rename_score, const char *pickaxe, int pickaxe_opts, - int break_opt) + int break_opt, + const char *orderfile) { if (paths && paths[0]) diffcore_pathspec(paths); @@ -898,6 +899,8 @@ void diffcore_std(const char **paths, diffcore_rename(detect_rename, rename_score); if (pickaxe) diffcore_pickaxe(pickaxe, pickaxe_opts); + if (orderfile) + diffcore_order(orderfile); } void diff_addremove(int addremove, unsigned mode, diff --git a/diff.h b/diff.h index ef0dfe287..0f1ed5877 100644 --- a/diff.h +++ b/diff.h @@ -43,12 +43,15 @@ extern void diffcore_pickaxe(const char *needle, int opts); extern void diffcore_pathspec(const char **pathspec); -extern void diffcore_break(int); +extern void diffcore_order(const char *orderfile); + +extern void diffcore_break(int max_score); extern void diffcore_std(const char **paths, int detect_rename, int rename_score, const char *pickaxe, int pickaxe_opts, - int break_opt); + int break_opt, + const char *orderfile); extern int diff_queue_is_empty(void); diff --git a/diffcore-order.c b/diffcore-order.c new file mode 100644 index 000000000..a03862c1c --- /dev/null +++ b/diffcore-order.c @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2005 Junio C Hamano + */ +#include "cache.h" +#include "diff.h" +#include "diffcore.h" +#include + +static char **order; +static int order_cnt; + +static void prepare_order(const char *orderfile) +{ + int fd, cnt, pass; + void *map; + char *cp, *endp; + struct stat st; + + if (order) + return; + + fd = open(orderfile, O_RDONLY); + if (fd < 0) + return; + if (fstat(fd, &st)) { + close(fd); + return; + } + map = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + close(fd); + if (-1 == (int)(long)map) + return; + endp = map + st.st_size; + for (pass = 0; pass < 2; pass++) { + cnt = 0; + cp = map; + while (cp < endp) { + char *ep; + for (ep = cp; ep < endp && *ep != '\n'; ep++) + ; + /* cp to ep has one line */ + if (*cp == '\n' || *cp == '#') + ; /* comment */ + else if (pass == 0) + cnt++; + else { + if (*ep == '\n') { + *ep = 0; + order[cnt] = cp; + } + else { + order[cnt] = xmalloc(ep-cp+1); + memcpy(order[cnt], cp, ep-cp); + order[cnt][ep-cp] = 0; + } + cnt++; + } + if (ep < endp) + ep++; + cp = ep; + } + if (pass == 0) { + order_cnt = cnt; + order = xmalloc(sizeof(*order) * cnt); + } + } +} + +struct pair_order { + struct diff_filepair *pair; + int orig_order; + int order; +}; + +static int match_order(const char *path) +{ + int i; + char p[PATH_MAX]; + + for (i = 0; i < order_cnt; i++) { + strcpy(p, path); + while (p[0]) { + char *cp; + if (!fnmatch(order[i], p, 0)) + return i; + cp = strrchr(p, '/'); + if (!cp) + break; + *cp = 0; + } + } + return order_cnt; +} + +static int compare_pair_order(const void *a_, const void *b_) +{ + struct pair_order const *a, *b; + a = (struct pair_order const *)a_; + b = (struct pair_order const *)b_; + if (a->order != b->order) + return a->order - b->order; + return a->orig_order - b->orig_order; +} + +void diffcore_order(const char *orderfile) +{ + struct diff_queue_struct *q = &diff_queued_diff; + struct pair_order *o = xmalloc(sizeof(*o) * q->nr); + int i; + + prepare_order(orderfile); + for (i = 0; i < q->nr; i++) { + o[i].pair = q->queue[i]; + o[i].orig_order = i; + o[i].order = match_order(o[i].pair->two->path); + } + qsort(o, q->nr, sizeof(*o), compare_pair_order); + for (i = 0; i < q->nr; i++) + q->queue[i] = o[i].pair; + free(o); + return; +} -- 2.30.2