diffcore-order.con commit Add test for correct coloring of git log --decoration (5671028)
   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                                } else {
  52                                        order[cnt] = xmemdupz(cp, ep - cp);
  53                                }
  54                                cnt++;
  55                        }
  56                        if (ep < endp)
  57                                ep++;
  58                        cp = ep;
  59                }
  60                if (pass == 0) {
  61                        order_cnt = cnt;
  62                        order = xmalloc(sizeof(*order) * cnt);
  63                }
  64        }
  65}
  66
  67struct pair_order {
  68        struct diff_filepair *pair;
  69        int orig_order;
  70        int order;
  71};
  72
  73static int match_order(const char *path)
  74{
  75        int i;
  76        char p[PATH_MAX];
  77
  78        for (i = 0; i < order_cnt; i++) {
  79                strcpy(p, path);
  80                while (p[0]) {
  81                        char *cp;
  82                        if (!fnmatch(order[i], p, 0))
  83                                return i;
  84                        cp = strrchr(p, '/');
  85                        if (!cp)
  86                                break;
  87                        *cp = 0;
  88                }
  89        }
  90        return order_cnt;
  91}
  92
  93static int compare_pair_order(const void *a_, const void *b_)
  94{
  95        struct pair_order const *a, *b;
  96        a = (struct pair_order const *)a_;
  97        b = (struct pair_order const *)b_;
  98        if (a->order != b->order)
  99                return a->order - b->order;
 100        return a->orig_order - b->orig_order;
 101}
 102
 103void diffcore_order(const char *orderfile)
 104{
 105        struct diff_queue_struct *q = &diff_queued_diff;
 106        struct pair_order *o;
 107        int i;
 108
 109        if (!q->nr)
 110                return;
 111
 112        o = xmalloc(sizeof(*o) * q->nr);
 113        prepare_order(orderfile);
 114        for (i = 0; i < q->nr; i++) {
 115                o[i].pair = q->queue[i];
 116                o[i].orig_order = i;
 117                o[i].order = match_order(o[i].pair->two->path);
 118        }
 119        qsort(o, q->nr, sizeof(*o), compare_pair_order);
 120        for (i = 0; i < q->nr; i++)
 121                q->queue[i] = o[i].pair;
 122        free(o);
 123        return;
 124}