diffcore-order.c 2.39 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
/*
 * 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)
{
13 14
	int cnt, pass;
	struct strbuf sb = STRBUF_INIT;
15 16
	void *map;
	char *cp, *endp;
17
	ssize_t sz;
18 19 20 21

	if (order)
		return;

22 23 24 25
	sz = strbuf_read_file(&sb, orderfile, 0);
	if (sz < 0)
		die_errno(_("failed to read orderfile '%s'"), orderfile);
	map = strbuf_detach(&sb, NULL);
26
	endp = (char *) map + sz;
27

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
	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;
44 45
				} else {
					order[cnt] = xmemdupz(cp, ep - cp);
46 47 48 49 50 51 52 53 54
				}
				cnt++;
			}
			if (ep < endp)
				ep++;
			cp = ep;
		}
		if (pass == 0) {
			order_cnt = cnt;
55
			ALLOC_ARRAY(order, cnt);
56 57 58 59 60 61 62
		}
	}
}

static int match_order(const char *path)
{
	int i;
63
	static struct strbuf p = STRBUF_INIT;
64 65

	for (i = 0; i < order_cnt; i++) {
66 67 68
		strbuf_reset(&p);
		strbuf_addstr(&p, path);
		while (p.buf[0]) {
69
			char *cp;
70
			if (!wildmatch(order[i], p.buf, 0))
71
				return i;
72
			cp = strrchr(p.buf, '/');
73 74 75 76 77 78 79 80
			if (!cp)
				break;
			*cp = 0;
		}
	}
	return order_cnt;
}

81
static int compare_objs_order(const void *a_, const void *b_)
82
{
83 84 85
	struct obj_order const *a, *b;
	a = (struct obj_order const *)a_;
	b = (struct obj_order const *)b_;
86 87 88 89 90
	if (a->order != b->order)
		return a->order - b->order;
	return a->orig_order - b->orig_order;
}

91 92 93 94 95 96 97 98 99 100 101 102 103
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));
	}
René Scharfe's avatar
René Scharfe committed
104
	QSORT(objs, nr, compare_objs_order);
105 106 107 108 109 110 111 112 113
}

static const char *pair_pathtwo(void *obj)
{
	struct diff_filepair *pair = (struct diff_filepair *)obj;

	return pair->two->path;
}

114 115 116
void diffcore_order(const char *orderfile)
{
	struct diff_queue_struct *q = &diff_queued_diff;
117
	struct obj_order *o;
118 119
	int i;

120 121 122
	if (!q->nr)
		return;

123
	ALLOC_ARRAY(o, q->nr);
124
	for (i = 0; i < q->nr; i++)
125 126 127 128
		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;
129 130 131
	free(o);
	return;
}