diffcore-order.con commit git-svn: fix show-ignore when not connected to the repository root (102a0a2)
   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
  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
  68struct pair_order {
  69        struct diff_filepair *pair;
  70        int orig_order;
  71        int order;
  72};
  73
  74static 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
  94static 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
 104void 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}