Merge branch 'jc/topo-author-date-sort'
"git log" learned the "--author-date-order" option, with which the output is topologically sorted and commits in parallel histories are shown intermixed together based on the author timestamp. * jc/topo-author-date-sort: t6003: add --author-date-order test topology tests: teach a helper to set author dates as well t6003: add --date-order test topology tests: teach a helper to take abbreviated timestamps t/lib-t6000: style fixes log: --author-date-order sort-in-topological-order: use prio-queue prio-queue: priority queue of pointers to structs toposort: rename "lifo" field
This commit is contained in:
commit
534f0e0996
1
.gitignore
vendored
1
.gitignore
vendored
@ -191,6 +191,7 @@
|
||||
/test-mktemp
|
||||
/test-parse-options
|
||||
/test-path-utils
|
||||
/test-prio-queue
|
||||
/test-read-cache
|
||||
/test-regex
|
||||
/test-revision-walking
|
||||
|
@ -625,6 +625,10 @@ By default, the commits are shown in reverse chronological order.
|
||||
Show no parents before all of its children are shown, but
|
||||
otherwise show commits in the commit timestamp order.
|
||||
|
||||
--author-date-order::
|
||||
Show no parents before all of its children are shown, but
|
||||
otherwise show commits in the author timestamp order.
|
||||
|
||||
--topo-order::
|
||||
Show no parents before all of its children are shown, and
|
||||
avoid showing commits on multiple lines of history
|
||||
|
3
Makefile
3
Makefile
@ -569,6 +569,7 @@ TEST_PROGRAMS_NEED_X += test-mergesort
|
||||
TEST_PROGRAMS_NEED_X += test-mktemp
|
||||
TEST_PROGRAMS_NEED_X += test-parse-options
|
||||
TEST_PROGRAMS_NEED_X += test-path-utils
|
||||
TEST_PROGRAMS_NEED_X += test-prio-queue
|
||||
TEST_PROGRAMS_NEED_X += test-read-cache
|
||||
TEST_PROGRAMS_NEED_X += test-regex
|
||||
TEST_PROGRAMS_NEED_X += test-revision-walking
|
||||
@ -705,6 +706,7 @@ LIB_H += parse-options.h
|
||||
LIB_H += patch-ids.h
|
||||
LIB_H += pathspec.h
|
||||
LIB_H += pkt-line.h
|
||||
LIB_H += prio-queue.h
|
||||
LIB_H += progress.h
|
||||
LIB_H += prompt.h
|
||||
LIB_H += quote.h
|
||||
@ -846,6 +848,7 @@ LIB_OBJS += pathspec.o
|
||||
LIB_OBJS += pkt-line.o
|
||||
LIB_OBJS += preload-index.o
|
||||
LIB_OBJS += pretty.o
|
||||
LIB_OBJS += prio-queue.o
|
||||
LIB_OBJS += progress.o
|
||||
LIB_OBJS += prompt.o
|
||||
LIB_OBJS += quote.o
|
||||
|
@ -237,7 +237,7 @@ static void log_show_early(struct rev_info *revs, struct commit_list *list)
|
||||
int i = revs->early_output;
|
||||
int show_header = 1;
|
||||
|
||||
sort_in_topological_order(&list, revs->lifo);
|
||||
sort_in_topological_order(&list, revs->sort_order);
|
||||
while (list && i) {
|
||||
struct commit *commit = list->item;
|
||||
switch (simplify_commit(revs, commit)) {
|
||||
|
@ -630,7 +630,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
|
||||
int num_rev, i, extra = 0;
|
||||
int all_heads = 0, all_remotes = 0;
|
||||
int all_mask, all_revs;
|
||||
int lifo = 1;
|
||||
enum rev_sort_order sort_order = REV_SORT_IN_GRAPH_ORDER;
|
||||
char head[128];
|
||||
const char *head_p;
|
||||
int head_len;
|
||||
@ -665,15 +665,17 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
|
||||
N_("show possible merge bases")),
|
||||
OPT_BOOLEAN(0, "independent", &independent,
|
||||
N_("show refs unreachable from any other ref")),
|
||||
OPT_BOOLEAN(0, "topo-order", &lifo,
|
||||
N_("show commits in topological order")),
|
||||
OPT_SET_INT(0, "topo-order", &sort_order,
|
||||
N_("show commits in topological order"),
|
||||
REV_SORT_IN_GRAPH_ORDER),
|
||||
OPT_BOOLEAN(0, "topics", &topics,
|
||||
N_("show only commits not on the first branch")),
|
||||
OPT_SET_INT(0, "sparse", &dense,
|
||||
N_("show merges reachable from only one tip"), 0),
|
||||
OPT_SET_INT(0, "date-order", &lifo,
|
||||
OPT_SET_INT(0, "date-order", &sort_order,
|
||||
N_("show commits where no parent comes before its "
|
||||
"children"), 0),
|
||||
"children"),
|
||||
REV_SORT_BY_COMMIT_DATE),
|
||||
{ OPTION_CALLBACK, 'g', "reflog", &reflog_base, N_("<n>[,<base>]"),
|
||||
N_("show <n> most recent ref-log entries starting at "
|
||||
"base"),
|
||||
@ -900,7 +902,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
|
||||
exit(0);
|
||||
|
||||
/* Sort topologically */
|
||||
sort_in_topological_order(&seen, lifo);
|
||||
sort_in_topological_order(&seen, sort_order);
|
||||
|
||||
/* Give names to commits */
|
||||
if (!sha1_name && !no_name)
|
||||
|
145
commit.c
145
commit.c
@ -9,6 +9,7 @@
|
||||
#include "gpg-interface.h"
|
||||
#include "mergesort.h"
|
||||
#include "commit-slab.h"
|
||||
#include "prio-queue.h"
|
||||
|
||||
static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
|
||||
|
||||
@ -518,31 +519,124 @@ struct commit *pop_commit(struct commit_list **stack)
|
||||
/* count number of children that have not been emitted */
|
||||
define_commit_slab(indegree_slab, int);
|
||||
|
||||
/* record author-date for each commit object */
|
||||
define_commit_slab(author_date_slab, unsigned long);
|
||||
|
||||
static void record_author_date(struct author_date_slab *author_date,
|
||||
struct commit *commit)
|
||||
{
|
||||
const char *buf, *line_end;
|
||||
char *buffer = NULL;
|
||||
struct ident_split ident;
|
||||
char *date_end;
|
||||
unsigned long date;
|
||||
|
||||
if (!commit->buffer) {
|
||||
unsigned long size;
|
||||
enum object_type type;
|
||||
buffer = read_sha1_file(commit->object.sha1, &type, &size);
|
||||
if (!buffer)
|
||||
return;
|
||||
}
|
||||
|
||||
for (buf = commit->buffer ? commit->buffer : buffer;
|
||||
buf;
|
||||
buf = line_end + 1) {
|
||||
line_end = strchrnul(buf, '\n');
|
||||
if (prefixcmp(buf, "author ")) {
|
||||
if (!line_end[0] || line_end[1] == '\n')
|
||||
return; /* end of header */
|
||||
continue;
|
||||
}
|
||||
if (split_ident_line(&ident,
|
||||
buf + strlen("author "),
|
||||
line_end - (buf + strlen("author "))) ||
|
||||
!ident.date_begin || !ident.date_end)
|
||||
goto fail_exit; /* malformed "author" line */
|
||||
break;
|
||||
}
|
||||
|
||||
date = strtoul(ident.date_begin, &date_end, 10);
|
||||
if (date_end != ident.date_end)
|
||||
goto fail_exit; /* malformed date */
|
||||
*(author_date_slab_at(author_date, commit)) = date;
|
||||
|
||||
fail_exit:
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static int compare_commits_by_author_date(const void *a_, const void *b_,
|
||||
void *cb_data)
|
||||
{
|
||||
const struct commit *a = a_, *b = b_;
|
||||
struct author_date_slab *author_date = cb_data;
|
||||
unsigned long a_date = *(author_date_slab_at(author_date, a));
|
||||
unsigned long b_date = *(author_date_slab_at(author_date, b));
|
||||
|
||||
/* newer commits with larger date first */
|
||||
if (a_date < b_date)
|
||||
return 1;
|
||||
else if (a_date > b_date)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused)
|
||||
{
|
||||
const struct commit *a = a_, *b = b_;
|
||||
/* newer commits with larger date first */
|
||||
if (a->date < b->date)
|
||||
return 1;
|
||||
else if (a->date > b->date)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs an in-place topological sort on the list supplied.
|
||||
*/
|
||||
void sort_in_topological_order(struct commit_list ** list, int lifo)
|
||||
void sort_in_topological_order(struct commit_list **list, enum rev_sort_order sort_order)
|
||||
{
|
||||
struct commit_list *next, *orig = *list;
|
||||
struct commit_list *work, **insert;
|
||||
struct commit_list **pptr;
|
||||
struct indegree_slab indegree;
|
||||
struct prio_queue queue;
|
||||
struct commit *commit;
|
||||
struct author_date_slab author_date;
|
||||
|
||||
if (!orig)
|
||||
return;
|
||||
*list = NULL;
|
||||
|
||||
init_indegree_slab(&indegree);
|
||||
memset(&queue, '\0', sizeof(queue));
|
||||
|
||||
switch (sort_order) {
|
||||
default: /* REV_SORT_IN_GRAPH_ORDER */
|
||||
queue.compare = NULL;
|
||||
break;
|
||||
case REV_SORT_BY_COMMIT_DATE:
|
||||
queue.compare = compare_commits_by_commit_date;
|
||||
break;
|
||||
case REV_SORT_BY_AUTHOR_DATE:
|
||||
init_author_date_slab(&author_date);
|
||||
queue.compare = compare_commits_by_author_date;
|
||||
queue.cb_data = &author_date;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Mark them and clear the indegree */
|
||||
for (next = orig; next; next = next->next) {
|
||||
struct commit *commit = next->item;
|
||||
*(indegree_slab_at(&indegree, commit)) = 1;
|
||||
/* also record the author dates, if needed */
|
||||
if (sort_order == REV_SORT_BY_AUTHOR_DATE)
|
||||
record_author_date(&author_date, commit);
|
||||
}
|
||||
|
||||
/* update the indegree */
|
||||
for (next = orig; next; next = next->next) {
|
||||
struct commit_list * parents = next->item->parents;
|
||||
struct commit_list *parents = next->item->parents;
|
||||
while (parents) {
|
||||
struct commit *parent = parents->item;
|
||||
int *pi = indegree_slab_at(&indegree, parent);
|
||||
@ -560,30 +654,28 @@ void sort_in_topological_order(struct commit_list ** list, int lifo)
|
||||
*
|
||||
* the tips serve as a starting set for the work queue.
|
||||
*/
|
||||
work = NULL;
|
||||
insert = &work;
|
||||
for (next = orig; next; next = next->next) {
|
||||
struct commit *commit = next->item;
|
||||
|
||||
if (*(indegree_slab_at(&indegree, commit)) == 1)
|
||||
insert = &commit_list_insert(commit, insert)->next;
|
||||
prio_queue_put(&queue, commit);
|
||||
}
|
||||
|
||||
/* process the list in topological order */
|
||||
if (!lifo)
|
||||
commit_list_sort_by_date(&work);
|
||||
/*
|
||||
* This is unfortunate; the initial tips need to be shown
|
||||
* in the order given from the revision traversal machinery.
|
||||
*/
|
||||
if (sort_order == REV_SORT_IN_GRAPH_ORDER)
|
||||
prio_queue_reverse(&queue);
|
||||
|
||||
/* We no longer need the commit list */
|
||||
free_commit_list(orig);
|
||||
|
||||
pptr = list;
|
||||
*list = NULL;
|
||||
while (work) {
|
||||
struct commit *commit;
|
||||
struct commit_list *parents, *work_item;
|
||||
while ((commit = prio_queue_get(&queue)) != NULL) {
|
||||
struct commit_list *parents;
|
||||
|
||||
work_item = work;
|
||||
work = work_item->next;
|
||||
work_item->next = NULL;
|
||||
|
||||
commit = work_item->item;
|
||||
for (parents = commit->parents; parents ; parents = parents->next) {
|
||||
struct commit *parent = parents->item;
|
||||
int *pi = indegree_slab_at(&indegree, parent);
|
||||
@ -596,23 +688,22 @@ void sort_in_topological_order(struct commit_list ** list, int lifo)
|
||||
* when all their children have been emitted thereby
|
||||
* guaranteeing topological order.
|
||||
*/
|
||||
if (--(*pi) == 1) {
|
||||
if (!lifo)
|
||||
commit_list_insert_by_date(parent, &work);
|
||||
else
|
||||
commit_list_insert(parent, &work);
|
||||
}
|
||||
if (--(*pi) == 1)
|
||||
prio_queue_put(&queue, parent);
|
||||
}
|
||||
/*
|
||||
* work_item is a commit all of whose children
|
||||
* have already been emitted. we can emit it now.
|
||||
* all children of commit have already been
|
||||
* emitted. we can emit it now.
|
||||
*/
|
||||
*(indegree_slab_at(&indegree, commit)) = 0;
|
||||
*pptr = work_item;
|
||||
pptr = &work_item->next;
|
||||
|
||||
pptr = &commit_list_insert(commit, pptr)->next;
|
||||
}
|
||||
|
||||
clear_indegree_slab(&indegree);
|
||||
clear_prio_queue(&queue);
|
||||
if (sort_order == REV_SORT_BY_AUTHOR_DATE)
|
||||
clear_author_date_slab(&author_date);
|
||||
}
|
||||
|
||||
/* merge-base stuff */
|
||||
|
15
commit.h
15
commit.h
@ -142,15 +142,24 @@ void clear_commit_marks(struct commit *commit, unsigned int mark);
|
||||
void clear_commit_marks_many(int nr, struct commit **commit, unsigned int mark);
|
||||
void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark);
|
||||
|
||||
|
||||
enum rev_sort_order {
|
||||
REV_SORT_IN_GRAPH_ORDER = 0,
|
||||
REV_SORT_BY_COMMIT_DATE,
|
||||
REV_SORT_BY_AUTHOR_DATE
|
||||
};
|
||||
|
||||
/*
|
||||
* Performs an in-place topological sort of list supplied.
|
||||
*
|
||||
* invariant of resulting list is:
|
||||
* a reachable from b => ord(b) < ord(a)
|
||||
* in addition, when lifo == 0, commits on parallel tracks are
|
||||
* sorted in the dates order.
|
||||
* sort_order further specifies:
|
||||
* REV_SORT_IN_GRAPH_ORDER: try to show a commit on a single-parent
|
||||
* chain together.
|
||||
* REV_SORT_BY_COMMIT_DATE: show eligible commits in committer-date order.
|
||||
*/
|
||||
void sort_in_topological_order(struct commit_list ** list, int lifo);
|
||||
void sort_in_topological_order(struct commit_list **, enum rev_sort_order);
|
||||
|
||||
struct commit_graft {
|
||||
unsigned char sha1[20];
|
||||
|
84
prio-queue.c
Normal file
84
prio-queue.c
Normal file
@ -0,0 +1,84 @@
|
||||
#include "cache.h"
|
||||
#include "commit.h"
|
||||
#include "prio-queue.h"
|
||||
|
||||
void prio_queue_reverse(struct prio_queue *queue)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (queue->compare != NULL)
|
||||
die("BUG: prio_queue_reverse() on non-LIFO queue");
|
||||
for (i = 0; i <= (j = (queue->nr - 1) - i); i++) {
|
||||
struct commit *swap = queue->array[i];
|
||||
queue->array[i] = queue->array[j];
|
||||
queue->array[j] = swap;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_prio_queue(struct prio_queue *queue)
|
||||
{
|
||||
free(queue->array);
|
||||
queue->nr = 0;
|
||||
queue->alloc = 0;
|
||||
queue->array = NULL;
|
||||
}
|
||||
|
||||
void prio_queue_put(struct prio_queue *queue, void *thing)
|
||||
{
|
||||
prio_queue_compare_fn compare = queue->compare;
|
||||
int ix, parent;
|
||||
|
||||
/* Append at the end */
|
||||
ALLOC_GROW(queue->array, queue->nr + 1, queue->alloc);
|
||||
queue->array[queue->nr++] = thing;
|
||||
if (!compare)
|
||||
return; /* LIFO */
|
||||
|
||||
/* Bubble up the new one */
|
||||
for (ix = queue->nr - 1; ix; ix = parent) {
|
||||
parent = (ix - 1) / 2;
|
||||
if (compare(queue->array[parent], queue->array[ix],
|
||||
queue->cb_data) <= 0)
|
||||
break;
|
||||
|
||||
thing = queue->array[parent];
|
||||
queue->array[parent] = queue->array[ix];
|
||||
queue->array[ix] = thing;
|
||||
}
|
||||
}
|
||||
|
||||
void *prio_queue_get(struct prio_queue *queue)
|
||||
{
|
||||
void *result, *swap;
|
||||
int ix, child;
|
||||
prio_queue_compare_fn compare = queue->compare;
|
||||
|
||||
if (!queue->nr)
|
||||
return NULL;
|
||||
if (!compare)
|
||||
return queue->array[--queue->nr]; /* LIFO */
|
||||
|
||||
result = queue->array[0];
|
||||
if (!--queue->nr)
|
||||
return result;
|
||||
|
||||
queue->array[0] = queue->array[queue->nr];
|
||||
|
||||
/* Push down the one at the root */
|
||||
for (ix = 0; ix * 2 + 1 < queue->nr; ix = child) {
|
||||
child = ix * 2 + 1; /* left */
|
||||
if ((child + 1 < queue->nr) &&
|
||||
(compare(queue->array[child], queue->array[child + 1],
|
||||
queue->cb_data) >= 0))
|
||||
child++; /* use right child */
|
||||
|
||||
if (compare(queue->array[ix], queue->array[child],
|
||||
queue->cb_data) <= 0)
|
||||
break;
|
||||
|
||||
swap = queue->array[child];
|
||||
queue->array[child] = queue->array[ix];
|
||||
queue->array[ix] = swap;
|
||||
}
|
||||
return result;
|
||||
}
|
48
prio-queue.h
Normal file
48
prio-queue.h
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef PRIO_QUEUE_H
|
||||
#define PRIO_QUEUE_H
|
||||
|
||||
/*
|
||||
* A priority queue implementation, primarily for keeping track of
|
||||
* commits in the 'date-order' so that we process them from new to old
|
||||
* as they are discovered, but can be used to hold any pointer to
|
||||
* struct. The caller is responsible for supplying a function to
|
||||
* compare two "things".
|
||||
*
|
||||
* Alternatively, this data structure can also be used as a LIFO stack
|
||||
* by specifying NULL as the comparison function.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Compare two "things", one and two; the third parameter is cb_data
|
||||
* in the prio_queue structure. The result is returned as a sign of
|
||||
* the return value, being the same as the sign of the result of
|
||||
* subtracting "two" from "one" (i.e. negative if "one" sorts earlier
|
||||
* than "two").
|
||||
*/
|
||||
typedef int (*prio_queue_compare_fn)(const void *one, const void *two, void *cb_data);
|
||||
|
||||
struct prio_queue {
|
||||
prio_queue_compare_fn compare;
|
||||
void *cb_data;
|
||||
int alloc, nr;
|
||||
void **array;
|
||||
};
|
||||
|
||||
/*
|
||||
* Add the "thing" to the queue.
|
||||
*/
|
||||
extern void prio_queue_put(struct prio_queue *, void *thing);
|
||||
|
||||
/*
|
||||
* Extract the "thing" that compares the smallest out of the queue,
|
||||
* or NULL. If compare function is NULL, the queue acts as a LIFO
|
||||
* stack.
|
||||
*/
|
||||
extern void *prio_queue_get(struct prio_queue *);
|
||||
|
||||
extern void clear_prio_queue(struct prio_queue *);
|
||||
|
||||
/* Reverse the LIFO elements */
|
||||
extern void prio_queue_reverse(struct prio_queue *);
|
||||
|
||||
#endif /* PRIO_QUEUE_H */
|
13
revision.c
13
revision.c
@ -1296,7 +1296,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)
|
||||
DIFF_OPT_SET(&revs->pruning, QUICK);
|
||||
revs->pruning.add_remove = file_add_remove;
|
||||
revs->pruning.change = file_change;
|
||||
revs->lifo = 1;
|
||||
revs->sort_order = REV_SORT_IN_GRAPH_ORDER;
|
||||
revs->dense = 1;
|
||||
revs->prefix = prefix;
|
||||
revs->max_age = -1;
|
||||
@ -1638,7 +1638,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
|
||||
} else if (!strcmp(arg, "--merge")) {
|
||||
revs->show_merge = 1;
|
||||
} else if (!strcmp(arg, "--topo-order")) {
|
||||
revs->lifo = 1;
|
||||
revs->sort_order = REV_SORT_IN_GRAPH_ORDER;
|
||||
revs->topo_order = 1;
|
||||
} else if (!strcmp(arg, "--simplify-merges")) {
|
||||
revs->simplify_merges = 1;
|
||||
@ -1656,7 +1656,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
|
||||
revs->prune = 1;
|
||||
load_ref_decorations(DECORATE_SHORT_REFS);
|
||||
} else if (!strcmp(arg, "--date-order")) {
|
||||
revs->lifo = 0;
|
||||
revs->sort_order = REV_SORT_BY_COMMIT_DATE;
|
||||
revs->topo_order = 1;
|
||||
} else if (!strcmp(arg, "--author-date-order")) {
|
||||
revs->sort_order = REV_SORT_BY_AUTHOR_DATE;
|
||||
revs->topo_order = 1;
|
||||
} else if (!prefixcmp(arg, "--early-output")) {
|
||||
int count = 100;
|
||||
@ -2606,7 +2609,7 @@ int prepare_revision_walk(struct rev_info *revs)
|
||||
if (limit_list(revs) < 0)
|
||||
return -1;
|
||||
if (revs->topo_order)
|
||||
sort_in_topological_order(&revs->commits, revs->lifo);
|
||||
sort_in_topological_order(&revs->commits, revs->sort_order);
|
||||
if (revs->line_level_traverse)
|
||||
line_log_filter(revs);
|
||||
if (revs->simplify_merges)
|
||||
@ -2924,7 +2927,7 @@ static void create_boundary_commit_list(struct rev_info *revs)
|
||||
* If revs->topo_order is set, sort the boundary commits
|
||||
* in topological order
|
||||
*/
|
||||
sort_in_topological_order(&revs->commits, revs->lifo);
|
||||
sort_in_topological_order(&revs->commits, revs->sort_order);
|
||||
}
|
||||
|
||||
static struct commit *get_revision_internal(struct rev_info *revs)
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "parse-options.h"
|
||||
#include "grep.h"
|
||||
#include "notes.h"
|
||||
#include "commit.h"
|
||||
|
||||
#define SEEN (1u<<0)
|
||||
#define UNINTERESTING (1u<<1)
|
||||
@ -62,6 +63,10 @@ struct rev_info {
|
||||
const char *prefix;
|
||||
const char *def;
|
||||
struct pathspec prune_data;
|
||||
|
||||
/* topo-sort */
|
||||
enum rev_sort_order sort_order;
|
||||
|
||||
unsigned int early_output:1,
|
||||
ignore_missing:1;
|
||||
|
||||
@ -72,7 +77,6 @@ struct rev_info {
|
||||
show_all:1,
|
||||
remove_empty_trees:1,
|
||||
simplify_history:1,
|
||||
lifo:1,
|
||||
topo_order:1,
|
||||
simplify_merges:1,
|
||||
simplify_by_decoration:1,
|
||||
|
104
t/lib-t6000.sh
104
t/lib-t6000.sh
@ -1,55 +1,50 @@
|
||||
: included from 6002 and others
|
||||
|
||||
[ -d .git/refs/tags ] || mkdir -p .git/refs/tags
|
||||
mkdir -p .git/refs/tags
|
||||
|
||||
:> sed.script
|
||||
>sed.script
|
||||
|
||||
# Answer the sha1 has associated with the tag. The tag must exist in .git or .git/refs/tags
|
||||
tag()
|
||||
{
|
||||
# Answer the sha1 has associated with the tag. The tag must exist in .git/refs/tags
|
||||
tag () {
|
||||
_tag=$1
|
||||
[ -f .git/refs/tags/$_tag ] || error "tag: \"$_tag\" does not exist"
|
||||
cat .git/refs/tags/$_tag
|
||||
test -f ".git/refs/tags/$_tag" || error "tag: \"$_tag\" does not exist"
|
||||
cat ".git/refs/tags/$_tag"
|
||||
}
|
||||
|
||||
# Generate a commit using the text specified to make it unique and the tree
|
||||
# named by the tag specified.
|
||||
unique_commit()
|
||||
{
|
||||
unique_commit () {
|
||||
_text=$1
|
||||
_tree=$2
|
||||
_tree=$2
|
||||
shift 2
|
||||
echo $_text | git commit-tree $(tag $_tree) "$@"
|
||||
echo "$_text" | git commit-tree $(tag "$_tree") "$@"
|
||||
}
|
||||
|
||||
# Save the output of a command into the tag specified. Prepend
|
||||
# a substitution script for the tag onto the front of sed.script
|
||||
save_tag()
|
||||
{
|
||||
save_tag () {
|
||||
_tag=$1
|
||||
[ -n "$_tag" ] || error "usage: save_tag tag commit-args ..."
|
||||
test -n "$_tag" || error "usage: save_tag tag commit-args ..."
|
||||
shift 1
|
||||
"$@" >.git/refs/tags/$_tag
|
||||
"$@" >".git/refs/tags/$_tag"
|
||||
|
||||
echo "s/$(tag $_tag)/$_tag/g" > sed.script.tmp
|
||||
cat sed.script >> sed.script.tmp
|
||||
echo "s/$(tag $_tag)/$_tag/g" >sed.script.tmp
|
||||
cat sed.script >>sed.script.tmp
|
||||
rm sed.script
|
||||
mv sed.script.tmp sed.script
|
||||
}
|
||||
|
||||
# Replace unhelpful sha1 hashses with their symbolic equivalents
|
||||
entag()
|
||||
{
|
||||
entag () {
|
||||
sed -f sed.script
|
||||
}
|
||||
|
||||
# Execute a command after first saving, then setting the GIT_AUTHOR_EMAIL
|
||||
# tag to a specified value. Restore the original value on return.
|
||||
as_author()
|
||||
{
|
||||
as_author () {
|
||||
_author=$1
|
||||
shift 1
|
||||
_save=$GIT_AUTHOR_EMAIL
|
||||
_save=$GIT_AUTHOR_EMAIL
|
||||
|
||||
GIT_AUTHOR_EMAIL="$_author"
|
||||
export GIT_AUTHOR_EMAIL
|
||||
@ -63,45 +58,58 @@ as_author()
|
||||
fi
|
||||
}
|
||||
|
||||
commit_date()
|
||||
{
|
||||
_commit=$1
|
||||
git cat-file commit $_commit | sed -n "s/^committer .*> \([0-9]*\) .*/\1/p"
|
||||
commit_date () {
|
||||
_commit=$1
|
||||
git cat-file commit $_commit |
|
||||
sed -n "s/^committer .*> \([0-9]*\) .*/\1/p"
|
||||
}
|
||||
|
||||
on_committer_date()
|
||||
{
|
||||
_date=$1
|
||||
shift 1
|
||||
GIT_COMMITTER_DATE="$_date"
|
||||
export GIT_COMMITTER_DATE
|
||||
"$@"
|
||||
unset GIT_COMMITTER_DATE
|
||||
# Assign the value of fake date to a variable, but
|
||||
# allow fairly common "1971-08-16 00:00" to be omittd
|
||||
assign_fake_date () {
|
||||
case "$2" in
|
||||
??:??:??) eval "$1='1971-08-16 $2'" ;;
|
||||
??:??) eval "$1='1971-08-16 00:$2'" ;;
|
||||
??) eval "$1='1971-08-16 00:00:$2'" ;;
|
||||
*) eval "$1='$2'" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
on_committer_date () {
|
||||
assign_fake_date GIT_COMMITTER_DATE "$1"
|
||||
export GIT_COMMITTER_DATE
|
||||
shift 1
|
||||
"$@"
|
||||
}
|
||||
|
||||
on_dates () {
|
||||
assign_fake_date GIT_COMMITTER_DATE "$1"
|
||||
assign_fake_date GIT_AUTHOR_DATE "$2"
|
||||
export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
|
||||
shift 2
|
||||
"$@"
|
||||
}
|
||||
|
||||
# Execute a command and suppress any error output.
|
||||
hide_error()
|
||||
{
|
||||
hide_error () {
|
||||
"$@" 2>/dev/null
|
||||
}
|
||||
|
||||
check_output()
|
||||
{
|
||||
check_output () {
|
||||
_name=$1
|
||||
shift 1
|
||||
if eval "$*" | entag > $_name.actual
|
||||
if eval "$*" | entag >"$_name.actual"
|
||||
then
|
||||
test_cmp $_name.expected $_name.actual
|
||||
test_cmp "$_name.expected" "$_name.actual"
|
||||
else
|
||||
return 1;
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Turn a reasonable test description into a reasonable test name.
|
||||
# All alphanums translated into -'s which are then compressed and stripped
|
||||
# from front and back.
|
||||
name_from_description()
|
||||
{
|
||||
name_from_description () {
|
||||
perl -pe '
|
||||
s/[^A-Za-z0-9.]/-/g;
|
||||
s/-+/-/g;
|
||||
@ -119,9 +127,11 @@ name_from_description()
|
||||
test_output_expect_success()
|
||||
{
|
||||
_description=$1
|
||||
_test=$2
|
||||
[ $# -eq 2 ] || error "usage: test_output_expect_success description test <<EOF ... EOF"
|
||||
_name=$(echo $_description | name_from_description)
|
||||
cat > $_name.expected
|
||||
_test=$2
|
||||
test $# -eq 2 ||
|
||||
error "usage: test_output_expect_success description test <<EOF ... EOF"
|
||||
|
||||
_name=$(echo $_description | name_from_description)
|
||||
cat >"$_name.expected"
|
||||
test_expect_success "$_description" "check_output $_name \"$_test\""
|
||||
}
|
||||
|
50
t/t0009-prio-queue.sh
Executable file
50
t/t0009-prio-queue.sh
Executable file
@ -0,0 +1,50 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='basic tests for priority queue implementation'
|
||||
. ./test-lib.sh
|
||||
|
||||
cat >expect <<'EOF'
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
EOF
|
||||
test_expect_success 'basic ordering' '
|
||||
test-prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
2
|
||||
3
|
||||
4
|
||||
1
|
||||
5
|
||||
6
|
||||
EOF
|
||||
test_expect_success 'mixed put and get' '
|
||||
test-prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<'EOF'
|
||||
1
|
||||
2
|
||||
NULL
|
||||
1
|
||||
2
|
||||
NULL
|
||||
EOF
|
||||
test_expect_success 'notice empty queue' '
|
||||
test-prio-queue 1 2 get get get 1 2 get get get >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
@ -39,25 +39,25 @@ test_bisection_diff()
|
||||
date >path0
|
||||
git update-index --add path0
|
||||
save_tag tree git write-tree
|
||||
on_committer_date "1971-08-16 00:00:00" hide_error save_tag root unique_commit root tree
|
||||
on_committer_date "1971-08-16 00:00:01" save_tag l0 unique_commit l0 tree -p root
|
||||
on_committer_date "1971-08-16 00:00:02" save_tag l1 unique_commit l1 tree -p l0
|
||||
on_committer_date "1971-08-16 00:00:03" save_tag l2 unique_commit l2 tree -p l1
|
||||
on_committer_date "1971-08-16 00:00:04" save_tag a0 unique_commit a0 tree -p l2
|
||||
on_committer_date "1971-08-16 00:00:05" save_tag a1 unique_commit a1 tree -p a0
|
||||
on_committer_date "1971-08-16 00:00:06" save_tag b1 unique_commit b1 tree -p a0
|
||||
on_committer_date "1971-08-16 00:00:07" save_tag c1 unique_commit c1 tree -p b1
|
||||
on_committer_date "1971-08-16 00:00:08" save_tag b2 unique_commit b2 tree -p b1
|
||||
on_committer_date "1971-08-16 00:00:09" save_tag b3 unique_commit b2 tree -p b2
|
||||
on_committer_date "1971-08-16 00:00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
|
||||
on_committer_date "1971-08-16 00:00:11" save_tag c3 unique_commit c3 tree -p c2
|
||||
on_committer_date "1971-08-16 00:00:12" save_tag a2 unique_commit a2 tree -p a1
|
||||
on_committer_date "1971-08-16 00:00:13" save_tag a3 unique_commit a3 tree -p a2
|
||||
on_committer_date "1971-08-16 00:00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3
|
||||
on_committer_date "1971-08-16 00:00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3
|
||||
on_committer_date "1971-08-16 00:00:16" save_tag l3 unique_commit l3 tree -p a4
|
||||
on_committer_date "1971-08-16 00:00:17" save_tag l4 unique_commit l4 tree -p l3
|
||||
on_committer_date "1971-08-16 00:00:18" save_tag l5 unique_commit l5 tree -p l4
|
||||
on_committer_date "00:00" hide_error save_tag root unique_commit root tree
|
||||
on_committer_date "00:01" save_tag l0 unique_commit l0 tree -p root
|
||||
on_committer_date "00:02" save_tag l1 unique_commit l1 tree -p l0
|
||||
on_committer_date "00:03" save_tag l2 unique_commit l2 tree -p l1
|
||||
on_committer_date "00:04" save_tag a0 unique_commit a0 tree -p l2
|
||||
on_committer_date "00:05" save_tag a1 unique_commit a1 tree -p a0
|
||||
on_committer_date "00:06" save_tag b1 unique_commit b1 tree -p a0
|
||||
on_committer_date "00:07" save_tag c1 unique_commit c1 tree -p b1
|
||||
on_committer_date "00:08" save_tag b2 unique_commit b2 tree -p b1
|
||||
on_committer_date "00:09" save_tag b3 unique_commit b2 tree -p b2
|
||||
on_committer_date "00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
|
||||
on_committer_date "00:11" save_tag c3 unique_commit c3 tree -p c2
|
||||
on_committer_date "00:12" save_tag a2 unique_commit a2 tree -p a1
|
||||
on_committer_date "00:13" save_tag a3 unique_commit a3 tree -p a2
|
||||
on_committer_date "00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3
|
||||
on_committer_date "00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3
|
||||
on_committer_date "00:16" save_tag l3 unique_commit l3 tree -p a4
|
||||
on_committer_date "00:17" save_tag l4 unique_commit l4 tree -p l3
|
||||
on_committer_date "00:18" save_tag l5 unique_commit l5 tree -p l4
|
||||
git update-ref HEAD $(tag l5)
|
||||
|
||||
|
||||
@ -90,29 +90,29 @@ git update-ref HEAD $(tag l5)
|
||||
# F
|
||||
|
||||
|
||||
on_committer_date "1971-08-16 00:00:00" hide_error save_tag F unique_commit F tree
|
||||
on_committer_date "1971-08-16 00:00:01" save_tag e8 unique_commit e8 tree -p F
|
||||
on_committer_date "1971-08-16 00:00:02" save_tag e7 unique_commit e7 tree -p e8
|
||||
on_committer_date "1971-08-16 00:00:03" save_tag e6 unique_commit e6 tree -p e7
|
||||
on_committer_date "1971-08-16 00:00:04" save_tag e5 unique_commit e5 tree -p e6
|
||||
on_committer_date "1971-08-16 00:00:05" save_tag f4 unique_commit f4 tree -p F
|
||||
on_committer_date "1971-08-16 00:00:06" save_tag f3 unique_commit f3 tree -p f4
|
||||
on_committer_date "1971-08-16 00:00:07" save_tag f2 unique_commit f2 tree -p f3
|
||||
on_committer_date "1971-08-16 00:00:08" save_tag f1 unique_commit f1 tree -p f2
|
||||
on_committer_date "1971-08-16 00:00:09" save_tag e4 unique_commit e4 tree -p e5
|
||||
on_committer_date "1971-08-16 00:00:10" save_tag e3 unique_commit e3 tree -p e4
|
||||
on_committer_date "1971-08-16 00:00:11" save_tag e2 unique_commit e2 tree -p e3
|
||||
on_committer_date "1971-08-16 00:00:12" save_tag e1 unique_commit e1 tree -p e2
|
||||
on_committer_date "1971-08-16 00:00:13" save_tag E unique_commit E tree -p e1 -p f1
|
||||
on_committer_date "00:00" hide_error save_tag F unique_commit F tree
|
||||
on_committer_date "00:01" save_tag e8 unique_commit e8 tree -p F
|
||||
on_committer_date "00:02" save_tag e7 unique_commit e7 tree -p e8
|
||||
on_committer_date "00:03" save_tag e6 unique_commit e6 tree -p e7
|
||||
on_committer_date "00:04" save_tag e5 unique_commit e5 tree -p e6
|
||||
on_committer_date "00:05" save_tag f4 unique_commit f4 tree -p F
|
||||
on_committer_date "00:06" save_tag f3 unique_commit f3 tree -p f4
|
||||
on_committer_date "00:07" save_tag f2 unique_commit f2 tree -p f3
|
||||
on_committer_date "00:08" save_tag f1 unique_commit f1 tree -p f2
|
||||
on_committer_date "00:09" save_tag e4 unique_commit e4 tree -p e5
|
||||
on_committer_date "00:10" save_tag e3 unique_commit e3 tree -p e4
|
||||
on_committer_date "00:11" save_tag e2 unique_commit e2 tree -p e3
|
||||
on_committer_date "00:12" save_tag e1 unique_commit e1 tree -p e2
|
||||
on_committer_date "00:13" save_tag E unique_commit E tree -p e1 -p f1
|
||||
|
||||
on_committer_date "1971-08-16 00:00:00" hide_error save_tag U unique_commit U tree
|
||||
on_committer_date "1971-08-16 00:00:01" save_tag u0 unique_commit u0 tree -p U
|
||||
on_committer_date "1971-08-16 00:00:01" save_tag u1 unique_commit u1 tree -p u0
|
||||
on_committer_date "1971-08-16 00:00:02" save_tag u2 unique_commit u2 tree -p u0
|
||||
on_committer_date "1971-08-16 00:00:03" save_tag u3 unique_commit u3 tree -p u0
|
||||
on_committer_date "1971-08-16 00:00:04" save_tag u4 unique_commit u4 tree -p u0
|
||||
on_committer_date "1971-08-16 00:00:05" save_tag u5 unique_commit u5 tree -p u0
|
||||
on_committer_date "1971-08-16 00:00:06" save_tag V unique_commit V tree -p u1 -p u2 -p u3 -p u4 -p u5
|
||||
on_committer_date "00:00" hide_error save_tag U unique_commit U tree
|
||||
on_committer_date "00:01" save_tag u0 unique_commit u0 tree -p U
|
||||
on_committer_date "00:01" save_tag u1 unique_commit u1 tree -p u0
|
||||
on_committer_date "00:02" save_tag u2 unique_commit u2 tree -p u0
|
||||
on_committer_date "00:03" save_tag u3 unique_commit u3 tree -p u0
|
||||
on_committer_date "00:04" save_tag u4 unique_commit u4 tree -p u0
|
||||
on_committer_date "00:05" save_tag u5 unique_commit u5 tree -p u0
|
||||
on_committer_date "00:06" save_tag V unique_commit V tree -p u1 -p u2 -p u3 -p u4 -p u5
|
||||
|
||||
test_sequence()
|
||||
{
|
||||
|
@ -16,39 +16,34 @@ list_duplicates()
|
||||
date >path0
|
||||
git update-index --add path0
|
||||
save_tag tree git write-tree
|
||||
on_committer_date "1971-08-16 00:00:00" hide_error save_tag root unique_commit root tree
|
||||
on_committer_date "1971-08-16 00:00:01" save_tag l0 unique_commit l0 tree -p root
|
||||
on_committer_date "1971-08-16 00:00:02" save_tag l1 unique_commit l1 tree -p l0
|
||||
on_committer_date "1971-08-16 00:00:03" save_tag l2 unique_commit l2 tree -p l1
|
||||
on_committer_date "1971-08-16 00:00:04" save_tag a0 unique_commit a0 tree -p l2
|
||||
on_committer_date "1971-08-16 00:00:05" save_tag a1 unique_commit a1 tree -p a0
|
||||
on_committer_date "1971-08-16 00:00:06" save_tag b1 unique_commit b1 tree -p a0
|
||||
on_committer_date "1971-08-16 00:00:07" save_tag c1 unique_commit c1 tree -p b1
|
||||
on_committer_date "1971-08-16 00:00:08" as_author foobar@example.com save_tag b2 unique_commit b2 tree -p b1
|
||||
on_committer_date "1971-08-16 00:00:09" save_tag b3 unique_commit b3 tree -p b2
|
||||
on_committer_date "1971-08-16 00:00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
|
||||
on_committer_date "1971-08-16 00:00:11" save_tag c3 unique_commit c3 tree -p c2
|
||||
on_committer_date "1971-08-16 00:00:12" save_tag a2 unique_commit a2 tree -p a1
|
||||
on_committer_date "1971-08-16 00:00:13" save_tag a3 unique_commit a3 tree -p a2
|
||||
on_committer_date "1971-08-16 00:00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3
|
||||
on_committer_date "1971-08-16 00:00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3
|
||||
on_committer_date "1971-08-16 00:00:16" save_tag l3 unique_commit l3 tree -p a4
|
||||
on_committer_date "1971-08-16 00:00:17" save_tag l4 unique_commit l4 tree -p l3
|
||||
on_committer_date "1971-08-16 00:00:18" save_tag l5 unique_commit l5 tree -p l4
|
||||
on_committer_date "1971-08-16 00:00:19" save_tag m1 unique_commit m1 tree -p a4 -p c3
|
||||
on_committer_date "1971-08-16 00:00:20" save_tag m2 unique_commit m2 tree -p c3 -p a4
|
||||
on_committer_date "1971-08-16 00:00:21" hide_error save_tag alt_root unique_commit alt_root tree
|
||||
on_committer_date "1971-08-16 00:00:22" save_tag r0 unique_commit r0 tree -p alt_root
|
||||
on_committer_date "1971-08-16 00:00:23" save_tag r1 unique_commit r1 tree -p r0
|
||||
on_committer_date "1971-08-16 00:00:24" save_tag l5r1 unique_commit l5r1 tree -p l5 -p r1
|
||||
on_committer_date "1971-08-16 00:00:25" save_tag r1l5 unique_commit r1l5 tree -p r1 -p l5
|
||||
on_dates "00:00" "00:00" hide_error save_tag root unique_commit root tree
|
||||
on_dates "00:01" "00:01" save_tag l0 unique_commit l0 tree -p root
|
||||
on_dates "00:02" "00:02" save_tag l1 unique_commit l1 tree -p l0
|
||||
on_dates "00:03" "00:03" save_tag l2 unique_commit l2 tree -p l1
|
||||
on_dates "00:04" "00:04" save_tag a0 unique_commit a0 tree -p l2
|
||||
on_dates "00:05" "00:05" save_tag a1 unique_commit a1 tree -p a0
|
||||
on_dates "00:06" "00:06" save_tag b1 unique_commit b1 tree -p a0
|
||||
on_dates "00:07" "00:07" save_tag c1 unique_commit c1 tree -p b1
|
||||
on_dates "00:08" "00:08" as_author foobar@example.com save_tag b2 unique_commit b2 tree -p b1
|
||||
on_dates "00:09" "00:09" save_tag b3 unique_commit b3 tree -p b2
|
||||
on_dates "00:10" "00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
|
||||
on_dates "00:11" "00:11" save_tag c3 unique_commit c3 tree -p c2
|
||||
on_dates "00:12" "00:00" save_tag a2 unique_commit a2 tree -p a1
|
||||
on_dates "00:13" "00:01" save_tag a3 unique_commit a3 tree -p a2
|
||||
on_dates "00:14" "00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3
|
||||
on_dates "00:15" "00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3
|
||||
on_dates "00:16" "00:16" save_tag l3 unique_commit l3 tree -p a4
|
||||
on_dates "00:17" "00:17" save_tag l4 unique_commit l4 tree -p l3
|
||||
on_dates "00:18" "00:18" save_tag l5 unique_commit l5 tree -p l4
|
||||
on_dates "00:19" "00:19" save_tag m1 unique_commit m1 tree -p a4 -p c3
|
||||
on_dates "00:20" "00:20" save_tag m2 unique_commit m2 tree -p c3 -p a4
|
||||
on_dates "00:21" "00:21" hide_error save_tag alt_root unique_commit alt_root tree
|
||||
on_dates "00:22" "00:22" save_tag r0 unique_commit r0 tree -p alt_root
|
||||
on_dates "00:23" "00:23" save_tag r1 unique_commit r1 tree -p r0
|
||||
on_dates "00:24" "00:24" save_tag l5r1 unique_commit l5r1 tree -p l5 -p r1
|
||||
on_dates "00:25" "00:25" save_tag r1l5 unique_commit r1l5 tree -p r1 -p l5
|
||||
|
||||
|
||||
#
|
||||
# note: as of 20/6, it isn't possible to create duplicate parents, so this
|
||||
# can't be tested.
|
||||
#
|
||||
#on_committer_date "1971-08-16 00:00:20" save_tag m3 unique_commit m3 tree -p c3 -p a4 -p c3
|
||||
hide_error save_tag e1 as_author e@example.com unique_commit e1 tree
|
||||
save_tag e2 as_author e@example.com unique_commit e2 tree -p e1
|
||||
save_tag f1 as_author f@example.com unique_commit f1 tree -p e1
|
||||
@ -105,6 +100,50 @@ l0
|
||||
root
|
||||
EOF
|
||||
|
||||
test_output_expect_success 'simple date order' 'git rev-list --date-order HEAD' <<EOF
|
||||
l5
|
||||
l4
|
||||
l3
|
||||
a4
|
||||
b4
|
||||
a3
|
||||
a2
|
||||
c3
|
||||
c2
|
||||
b3
|
||||
b2
|
||||
c1
|
||||
b1
|
||||
a1
|
||||
a0
|
||||
l2
|
||||
l1
|
||||
l0
|
||||
root
|
||||
EOF
|
||||
|
||||
test_output_expect_success 'simple author-date order' 'git rev-list --author-date-order HEAD' <<EOF
|
||||
l5
|
||||
l4
|
||||
l3
|
||||
a4
|
||||
b4
|
||||
c3
|
||||
c2
|
||||
b3
|
||||
b2
|
||||
c1
|
||||
b1
|
||||
a3
|
||||
a2
|
||||
a1
|
||||
a0
|
||||
l2
|
||||
l1
|
||||
l0
|
||||
root
|
||||
EOF
|
||||
|
||||
test_output_expect_success 'two diamonds topo order (g6)' 'git rev-list --topo-order g4' <<EOF
|
||||
g4
|
||||
h2
|
||||
|
39
test-prio-queue.c
Normal file
39
test-prio-queue.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include "cache.h"
|
||||
#include "prio-queue.h"
|
||||
|
||||
static int intcmp(const void *va, const void *vb, void *data)
|
||||
{
|
||||
const int *a = va, *b = vb;
|
||||
return *a - *b;
|
||||
}
|
||||
|
||||
static void show(int *v)
|
||||
{
|
||||
if (!v)
|
||||
printf("NULL\n");
|
||||
else
|
||||
printf("%d\n", *v);
|
||||
free(v);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct prio_queue pq = { intcmp };
|
||||
|
||||
while (*++argv) {
|
||||
if (!strcmp(*argv, "get"))
|
||||
show(prio_queue_get(&pq));
|
||||
else if (!strcmp(*argv, "dump")) {
|
||||
int *v;
|
||||
while ((v = prio_queue_get(&pq)))
|
||||
show(v);
|
||||
}
|
||||
else {
|
||||
int *v = malloc(sizeof(*v));
|
||||
*v = atoi(*argv);
|
||||
prio_queue_put(&pq, v);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user