1/*
2 * Copyright (C) 2005 Junio C Hamano
3 */
4#include "cache.h"
5#include "diff.h"
6#include "diffcore.h"
7
8static char **order;
9static int order_cnt;
10
11static void prepare_order(const char *orderfile)
12{
13 int fd, cnt, pass;
14 void *map;
15 char *cp, *endp;
16 struct stat st;
17 size_t sz;
18
19 if (order)
20 return;
21
22 fd = open(orderfile, O_RDONLY);
23 if (fd < 0)
24 return;
25 if (fstat(fd, &st)) {
26 close(fd);
27 return;
28 }
29 sz = xsize_t(st.st_size);
30 map = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
31 close(fd);
32 if (map == MAP_FAILED)
33 return;
34 endp = (char *) map + sz;
35 for (pass = 0; pass < 2; pass++) {
36 cnt = 0;
37 cp = map;
38 while (cp < endp) {
39 char *ep;
40 for (ep = cp; ep < endp && *ep != '\n'; ep++)
41 ;
42 /* cp to ep has one line */
43 if (*cp == '\n' || *cp == '#')
44 ; /* comment */
45 else if (pass == 0)
46 cnt++;
47 else {
48 if (*ep == '\n') {
49 *ep = 0;
50 order[cnt] = cp;
51 }
52 else {
53 order[cnt] = xmalloc(ep-cp+1);
54 memcpy(order[cnt], cp, ep-cp);
55 order[cnt][ep-cp] = 0;
56 }
57 cnt++;
58 }
59 if (ep < endp)
60 ep++;
61 cp = ep;
62 }
63 if (pass == 0) {
64 order_cnt = cnt;
65 order = xmalloc(sizeof(*order) * cnt);
66 }
67 }
68}
69
70struct pair_order {
71 struct diff_filepair *pair;
72 int orig_order;
73 int order;
74};
75
76static int match_order(const char *path)
77{
78 int i;
79 char p[PATH_MAX];
80
81 for (i = 0; i < order_cnt; i++) {
82 strcpy(p, path);
83 while (p[0]) {
84 char *cp;
85 if (!fnmatch(order[i], p, 0))
86 return i;
87 cp = strrchr(p, '/');
88 if (!cp)
89 break;
90 *cp = 0;
91 }
92 }
93 return order_cnt;
94}
95
96static int compare_pair_order(const void *a_, const void *b_)
97{
98 struct pair_order const *a, *b;
99 a = (struct pair_order const *)a_;
100 b = (struct pair_order const *)b_;
101 if (a->order != b->order)
102 return a->order - b->order;
103 return a->orig_order - b->orig_order;
104}
105
106void diffcore_order(const char *orderfile)
107{
108 struct diff_queue_struct *q = &diff_queued_diff;
109 struct pair_order *o;
110 int i;
111
112 if (!q->nr)
113 return;
114
115 o = xmalloc(sizeof(*o) * q->nr);
116 prepare_order(orderfile);
117 for (i = 0; i < q->nr; i++) {
118 o[i].pair = q->queue[i];
119 o[i].orig_order = i;
120 o[i].order = match_order(o[i].pair->two->path);
121 }
122 qsort(o, q->nr, sizeof(*o), compare_pair_order);
123 for (i = 0; i < q->nr; i++)
124 q->queue[i] = o[i].pair;
125 free(o);
126 return;
127}