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