/*
 * Copyright (C) 2005 Junio C Hamano
 */
#include "cache.h"
#include "diff.h"
#include "diffcore.h"
#include <fnmatch.h>

static char **order;
static int order_cnt;

static void prepare_order(const char *orderfile)
{
	int fd, cnt, pass;
	void *map;
	char *cp, *endp;
	struct stat st;

	if (order)
		return;

	fd = open(orderfile, O_RDONLY);
	if (fd < 0)
		return;
	if (fstat(fd, &st)) {
		close(fd);
		return;
	}
	map = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
	close(fd);
	if (map == MAP_FAILED)
		return;
	endp = map + st.st_size;
	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] = xmalloc(ep-cp+1);
					memcpy(order[cnt], cp, ep-cp);
					order[cnt][ep-cp] = 0;
				}
				cnt++;
			}
			if (ep < endp)
				ep++;
			cp = ep;
		}
		if (pass == 0) {
			order_cnt = cnt;
			order = xmalloc(sizeof(*order) * cnt);
		}
	}
}

struct pair_order {
	struct diff_filepair *pair;
	int orig_order;
	int order;
};

static int match_order(const char *path)
{
	int i;
	char p[PATH_MAX];

	for (i = 0; i < order_cnt; i++) {
		strcpy(p, path);
		while (p[0]) {
			char *cp;
			if (!fnmatch(order[i], p, 0))
				return i;
			cp = strrchr(p, '/');
			if (!cp)
				break;
			*cp = 0;
		}
	}
	return order_cnt;
}

static int compare_pair_order(const void *a_, const void *b_)
{
	struct pair_order const *a, *b;
	a = (struct pair_order const *)a_;
	b = (struct pair_order const *)b_;
	if (a->order != b->order)
		return a->order - b->order;
	return a->orig_order - b->orig_order;
}

void diffcore_order(const char *orderfile)
{
	struct diff_queue_struct *q = &diff_queued_diff;
	struct pair_order *o;
	int i;

	if (!q->nr)
		return;

	o = xmalloc(sizeof(*o) * q->nr);
	prepare_order(orderfile);
	for (i = 0; i < q->nr; i++) {
		o[i].pair = q->queue[i];
		o[i].orig_order = i;
		o[i].order = match_order(o[i].pair->two->path);
	}
	qsort(o, q->nr, sizeof(*o), compare_pair_order);
	for (i = 0; i < q->nr; i++)
		q->queue[i] = o[i].pair;
	free(o);
	return;
}
