1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-10-30 13:57:54 +01:00
git/diffcore-order.c
Kirill Smelkov 1df4320fa2 diffcore-order: export generic ordering interface
diffcore_order() interface only accepts a queue of `struct
diff_filepair`.

In the next patches, we'll want to order `struct combine_diff_path`
by path, so let's first rework diffcore-order to also provide
generic low-level interface for ordering arbitrary objects, provided
they have path accessors.

The new interface is:

    - `struct obj_order`    for describing objects to ordering routine, and
    - order_objects()       for actually doing the ordering work.

Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-24 14:44:57 -08:00

131 lines
2.4 KiB
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 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;
order = xmalloc(sizeof(*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 (!fnmatch(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, sizeof(*objs), 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;
o = xmalloc(sizeof(*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;
}