Browse Source
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 <junkio@cox.net> Signed-off-by: Linus Torvalds <torvalds@osdl.org>maint
Junio C Hamano
20 years ago
committed by
Linus Torvalds
10 changed files with 167 additions and 10 deletions
@ -0,0 +1,122 @@
@@ -0,0 +1,122 @@
|
||||
/* |
||||
* Copyright (C) 2005 Junio C Hamano |
||||
*/ |
||||
#include "cache.h" |
||||
#include "diff.h" |
||||
#include "diffcore.h" |
||||
#include <fnmatch.h> |
||||
|
||||
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; |
||||
} |
Loading…
Reference in new issue