diffcore-order.con commit Merge branch 'jc/xstrfmt-null-with-prec-0' into maint (97d5165)
   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 cnt, pass;
  14        struct strbuf sb = STRBUF_INIT;
  15        void *map;
  16        char *cp, *endp;
  17        ssize_t sz;
  18
  19        if (order)
  20                return;
  21
  22        sz = strbuf_read_file(&sb, orderfile, 0);
  23        if (sz < 0)
  24                die_errno(_("failed to read orderfile '%s'"), orderfile);
  25        map = strbuf_detach(&sb, NULL);
  26        endp = (char *) map + sz;
  27
  28        for (pass = 0; pass < 2; pass++) {
  29                cnt = 0;
  30                cp = map;
  31                while (cp < endp) {
  32                        char *ep;
  33                        for (ep = cp; ep < endp && *ep != '\n'; ep++)
  34                                ;
  35                        /* cp to ep has one line */
  36                        if (*cp == '\n' || *cp == '#')
  37                                ; /* comment */
  38                        else if (pass == 0)
  39                                cnt++;
  40                        else {
  41                                if (*ep == '\n') {
  42                                        *ep = 0;
  43                                        order[cnt] = cp;
  44                                } else {
  45                                        order[cnt] = xmemdupz(cp, ep - cp);
  46                                }
  47                                cnt++;
  48                        }
  49                        if (ep < endp)
  50                                ep++;
  51                        cp = ep;
  52                }
  53                if (pass == 0) {
  54                        order_cnt = cnt;
  55                        ALLOC_ARRAY(order, cnt);
  56                }
  57        }
  58}
  59
  60static int match_order(const char *path)
  61{
  62        int i;
  63        static struct strbuf p = STRBUF_INIT;
  64
  65        for (i = 0; i < order_cnt; i++) {
  66                strbuf_reset(&p);
  67                strbuf_addstr(&p, path);
  68                while (p.buf[0]) {
  69                        char *cp;
  70                        if (!wildmatch(order[i], p.buf, 0, NULL))
  71                                return i;
  72                        cp = strrchr(p.buf, '/');
  73                        if (!cp)
  74                                break;
  75                        *cp = 0;
  76                }
  77        }
  78        return order_cnt;
  79}
  80
  81static int compare_objs_order(const void *a_, const void *b_)
  82{
  83        struct obj_order const *a, *b;
  84        a = (struct obj_order const *)a_;
  85        b = (struct obj_order const *)b_;
  86        if (a->order != b->order)
  87                return a->order - b->order;
  88        return a->orig_order - b->orig_order;
  89}
  90
  91void order_objects(const char *orderfile, obj_path_fn_t obj_path,
  92                   struct obj_order *objs, int nr)
  93{
  94        int i;
  95
  96        if (!nr)
  97                return;
  98
  99        prepare_order(orderfile);
 100        for (i = 0; i < nr; i++) {
 101                objs[i].orig_order = i;
 102                objs[i].order = match_order(obj_path(objs[i].obj));
 103        }
 104        qsort(objs, nr, sizeof(*objs), compare_objs_order);
 105}
 106
 107static const char *pair_pathtwo(void *obj)
 108{
 109        struct diff_filepair *pair = (struct diff_filepair *)obj;
 110
 111        return pair->two->path;
 112}
 113
 114void diffcore_order(const char *orderfile)
 115{
 116        struct diff_queue_struct *q = &diff_queued_diff;
 117        struct obj_order *o;
 118        int i;
 119
 120        if (!q->nr)
 121                return;
 122
 123        ALLOC_ARRAY(o, q->nr);
 124        for (i = 0; i < q->nr; i++)
 125                o[i].obj = q->queue[i];
 126        order_objects(orderfile, pair_pathtwo, o, q->nr);
 127        for (i = 0; i < q->nr; i++)
 128                q->queue[i] = o[i].obj;
 129        free(o);
 130        return;
 131}