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