1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-09 07:56:11 +02:00

log: --author-date-order

Sometimes people would want to view the commits in parallel
histories in the order of author dates, not committer dates.

Teach "topo-order" sort machinery to do so, using a commit-info slab
to record the author dates of each commit, and prio-queue to sort
them.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Junio C Hamano 2013-06-07 10:35:54 -07:00
parent da24b1044f
commit 81c6b38b67
4 changed files with 83 additions and 1 deletions

View File

@ -617,6 +617,10 @@ By default, the commits are shown in reverse chronological order.
Show no parents before all of its children are shown, but Show no parents before all of its children are shown, but
otherwise show commits in the commit timestamp order. 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:: --topo-order::
Show no parents before all of its children are shown, and Show no parents before all of its children are shown, and
avoid showing commits on multiple lines of history avoid showing commits on multiple lines of history

View File

@ -510,6 +510,68 @@ struct commit *pop_commit(struct commit_list **stack)
/* count number of children that have not been emitted */ /* count number of children that have not been emitted */
define_commit_slab(indegree_slab, int); 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) static int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused)
{ {
const struct commit *a = a_, *b = b_; const struct commit *a = a_, *b = b_;
@ -531,6 +593,7 @@ void sort_in_topological_order(struct commit_list **list, enum rev_sort_order so
struct indegree_slab indegree; struct indegree_slab indegree;
struct prio_queue queue; struct prio_queue queue;
struct commit *commit; struct commit *commit;
struct author_date_slab author_date;
if (!orig) if (!orig)
return; return;
@ -538,6 +601,7 @@ void sort_in_topological_order(struct commit_list **list, enum rev_sort_order so
init_indegree_slab(&indegree); init_indegree_slab(&indegree);
memset(&queue, '\0', sizeof(queue)); memset(&queue, '\0', sizeof(queue));
switch (sort_order) { switch (sort_order) {
default: /* REV_SORT_IN_GRAPH_ORDER */ default: /* REV_SORT_IN_GRAPH_ORDER */
queue.compare = NULL; queue.compare = NULL;
@ -545,12 +609,20 @@ void sort_in_topological_order(struct commit_list **list, enum rev_sort_order so
case REV_SORT_BY_COMMIT_DATE: case REV_SORT_BY_COMMIT_DATE:
queue.compare = compare_commits_by_commit_date; queue.compare = compare_commits_by_commit_date;
break; 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 */ /* Mark them and clear the indegree */
for (next = orig; next; next = next->next) { for (next = orig; next; next = next->next) {
struct commit *commit = next->item; struct commit *commit = next->item;
*(indegree_slab_at(&indegree, commit)) = 1; *(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 */ /* update the indegree */
@ -621,6 +693,8 @@ void sort_in_topological_order(struct commit_list **list, enum rev_sort_order so
clear_indegree_slab(&indegree); clear_indegree_slab(&indegree);
clear_prio_queue(&queue); clear_prio_queue(&queue);
if (sort_order == REV_SORT_BY_AUTHOR_DATE)
clear_author_date_slab(&author_date);
} }
/* merge-base stuff */ /* merge-base stuff */

View File

@ -142,7 +142,8 @@ void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark);
enum rev_sort_order { enum rev_sort_order {
REV_SORT_IN_GRAPH_ORDER = 0, REV_SORT_IN_GRAPH_ORDER = 0,
REV_SORT_BY_COMMIT_DATE REV_SORT_BY_COMMIT_DATE,
REV_SORT_BY_AUTHOR_DATE
}; };
/* /*

View File

@ -1393,6 +1393,9 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
} else if (!strcmp(arg, "--date-order")) { } else if (!strcmp(arg, "--date-order")) {
revs->sort_order = REV_SORT_BY_COMMIT_DATE; revs->sort_order = REV_SORT_BY_COMMIT_DATE;
revs->topo_order = 1; 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")) { } else if (!prefixcmp(arg, "--early-output")) {
int count = 100; int count = 100;
switch (arg[14]) { switch (arg[14]) {