diff options
Diffstat (limited to 'third_party/git/diffcore-order.c')
-rw-r--r-- | third_party/git/diffcore-order.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/third_party/git/diffcore-order.c b/third_party/git/diffcore-order.c new file mode 100644 index 000000000000..19e73311f9cd --- /dev/null +++ b/third_party/git/diffcore-order.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2005 Junio C Hamano + */ +#include "cache.h" +#include "diff.h" +#include "diffcore.h" + +static char **order; +static int order_cnt; + +static void prepare_order(const char *orderfile) +{ + int cnt, pass; + struct strbuf sb = STRBUF_INIT; + void *map; + char *cp, *endp; + ssize_t sz; + + if (order) + return; + + sz = strbuf_read_file(&sb, orderfile, 0); + if (sz < 0) + die_errno(_("failed to read orderfile '%s'"), orderfile); + map = strbuf_detach(&sb, NULL); + endp = (char *) map + sz; + + for (pass = 0; pass < 2; pass++) { + cnt = 0; + cp = map; + while (cp < endp) { + char *ep; + for (ep = cp; ep < endp && *ep != '\n'; ep++) + ; + /* cp to ep has one line */ + if (*cp == '\n' || *cp == '#') + ; /* comment */ + else if (pass == 0) + cnt++; + else { + if (*ep == '\n') { + *ep = 0; + order[cnt] = cp; + } else { + order[cnt] = xmemdupz(cp, ep - cp); + } + cnt++; + } + if (ep < endp) + ep++; + cp = ep; + } + if (pass == 0) { + order_cnt = cnt; + ALLOC_ARRAY(order, cnt); + } + } +} + +static int match_order(const char *path) +{ + int i; + static struct strbuf p = STRBUF_INIT; + + for (i = 0; i < order_cnt; i++) { + strbuf_reset(&p); + strbuf_addstr(&p, path); + while (p.buf[0]) { + char *cp; + if (!wildmatch(order[i], p.buf, 0)) + return i; + cp = strrchr(p.buf, '/'); + if (!cp) + break; + *cp = 0; + } + } + return order_cnt; +} + +static int compare_objs_order(const void *a_, const void *b_) +{ + struct obj_order const *a, *b; + a = (struct obj_order const *)a_; + b = (struct obj_order const *)b_; + if (a->order != b->order) + return a->order - b->order; + return a->orig_order - b->orig_order; +} + +void order_objects(const char *orderfile, obj_path_fn_t obj_path, + struct obj_order *objs, int nr) +{ + int i; + + if (!nr) + return; + + prepare_order(orderfile); + for (i = 0; i < nr; i++) { + objs[i].orig_order = i; + objs[i].order = match_order(obj_path(objs[i].obj)); + } + QSORT(objs, nr, compare_objs_order); +} + +static const char *pair_pathtwo(void *obj) +{ + struct diff_filepair *pair = (struct diff_filepair *)obj; + + return pair->two->path; +} + +void diffcore_order(const char *orderfile) +{ + struct diff_queue_struct *q = &diff_queued_diff; + struct obj_order *o; + int i; + + if (!q->nr) + return; + + ALLOC_ARRAY(o, q->nr); + for (i = 0; i < q->nr; i++) + o[i].obj = q->queue[i]; + order_objects(orderfile, pair_pathtwo, o, q->nr); + for (i = 0; i < q->nr; i++) + q->queue[i] = o[i].obj; + free(o); + return; +} |