git / diffcore-order.c

/*
 * 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 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 = (char *) 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;
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.