Skip to content

Commit 08f704f

Browse files
committed
toposort: rename "lifo" field
The primary invariant of sort_in_topological_order() is that a parent commit is not emitted until all children of it are. When traversing a forked history like this with "git log C E": A----B----C \ D----E we ensure that A is emitted after all of B, C, D, and E are done, B has to wait until C is done, and D has to wait until E is done. In some applications, however, we would further want to control how these child commits B, C, D and E on two parallel ancestry chains are shown. Most of the time, we would want to see C and B emitted together, and then E and D, and finally A (i.e. the --topo-order output). The "lifo" parameter of the sort_in_topological_order() function is used to control this behaviour. We start the traversal by knowing two commits, C and E. While keeping in mind that we also need to inspect E later, we pick C first to inspect, and we notice and record that B needs to be inspected. By structuring the "work to be done" set as a LIFO stack, we ensure that B is inspected next, before other in-flight commits we had known that we will need to inspect, e.g. E. When showing in --date-order, we would want to see commits ordered by timestamps, i.e. show C, E, B and D in this order before showing A, possibly mixing commits from two parallel histories together. When "lifo" parameter is set to false, the function keeps the "work to be done" set sorted in the date order to realize this semantics. After inspecting C, we add B to the "work to be done" set, but the next commit we inspect from the set is E which is newer than B. The name "lifo", however, is too strongly tied to the way how the function implements its behaviour, and does not describe what the behaviour _means_. Replace this field with an enum rev_sort_order, with two possible values: REV_SORT_IN_GRAPH_ORDER and REV_SORT_BY_COMMIT_DATE, and update the existing code. The mechanical replacement rule is: "lifo == 0" is equivalent to "sort_order == REV_SORT_BY_COMMIT_DATE" "lifo == 1" is equivalent to "sort_order == REV_SORT_IN_GRAPH_ORDER" Signed-off-by: Junio C Hamano <[email protected]>
1 parent a84b794 commit 08f704f

File tree

6 files changed

+38
-20
lines changed

6 files changed

+38
-20
lines changed

builtin/log.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ static void log_show_early(struct rev_info *revs, struct commit_list *list)
205205
int i = revs->early_output;
206206
int show_header = 1;
207207

208-
sort_in_topological_order(&list, revs->lifo);
208+
sort_in_topological_order(&list, revs->sort_order);
209209
while (list && i) {
210210
struct commit *commit = list->item;
211211
switch (simplify_commit(revs, commit)) {

builtin/show-branch.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
631631
int num_rev, i, extra = 0;
632632
int all_heads = 0, all_remotes = 0;
633633
int all_mask, all_revs;
634-
int lifo = 1;
634+
enum rev_sort_order sort_order = REV_SORT_IN_GRAPH_ORDER;
635635
char head[128];
636636
const char *head_p;
637637
int head_len;
@@ -666,15 +666,17 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
666666
N_("show possible merge bases")),
667667
OPT_BOOLEAN(0, "independent", &independent,
668668
N_("show refs unreachable from any other ref")),
669-
OPT_BOOLEAN(0, "topo-order", &lifo,
670-
N_("show commits in topological order")),
669+
OPT_SET_INT(0, "topo-order", &sort_order,
670+
N_("show commits in topological order"),
671+
REV_SORT_IN_GRAPH_ORDER),
671672
OPT_BOOLEAN(0, "topics", &topics,
672673
N_("show only commits not on the first branch")),
673674
OPT_SET_INT(0, "sparse", &dense,
674675
N_("show merges reachable from only one tip"), 0),
675-
OPT_SET_INT(0, "date-order", &lifo,
676+
OPT_SET_INT(0, "date-order", &sort_order,
676677
N_("show commits where no parent comes before its "
677-
"children"), 0),
678+
"children"),
679+
REV_SORT_BY_COMMIT_DATE),
678680
{ OPTION_CALLBACK, 'g', "reflog", &reflog_base, N_("<n>[,<base>]"),
679681
N_("show <n> most recent ref-log entries starting at "
680682
"base"),
@@ -901,7 +903,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
901903
exit(0);
902904

903905
/* Sort topologically */
904-
sort_in_topological_order(&seen, lifo);
906+
sort_in_topological_order(&seen, sort_order);
905907

906908
/* Give names to commits */
907909
if (!sha1_name && !no_name)

commit.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ define_commit_slab(indegree_slab, int);
512512
/*
513513
* Performs an in-place topological sort on the list supplied.
514514
*/
515-
void sort_in_topological_order(struct commit_list ** list, int lifo)
515+
void sort_in_topological_order(struct commit_list ** list, enum rev_sort_order sort_order)
516516
{
517517
struct commit_list *next, *orig = *list;
518518
struct commit_list *work, **insert;
@@ -561,7 +561,7 @@ void sort_in_topological_order(struct commit_list ** list, int lifo)
561561
}
562562

563563
/* process the list in topological order */
564-
if (!lifo)
564+
if (sort_order != REV_SORT_IN_GRAPH_ORDER)
565565
commit_list_sort_by_date(&work);
566566

567567
pptr = list;
@@ -588,10 +588,14 @@ void sort_in_topological_order(struct commit_list ** list, int lifo)
588588
* guaranteeing topological order.
589589
*/
590590
if (--(*pi) == 1) {
591-
if (!lifo)
591+
switch (sort_order) {
592+
case REV_SORT_BY_COMMIT_DATE:
592593
commit_list_insert_by_date(parent, &work);
593-
else
594+
break;
595+
default: /* REV_SORT_IN_GRAPH_ORDER */
594596
commit_list_insert(parent, &work);
597+
break;
598+
}
595599
}
596600
}
597601
/*

commit.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,15 +139,23 @@ struct commit *pop_commit(struct commit_list **stack);
139139
void clear_commit_marks(struct commit *commit, unsigned int mark);
140140
void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark);
141141

142+
143+
enum rev_sort_order {
144+
REV_SORT_IN_GRAPH_ORDER = 0,
145+
REV_SORT_BY_COMMIT_DATE
146+
};
147+
142148
/*
143149
* Performs an in-place topological sort of list supplied.
144150
*
145151
* invariant of resulting list is:
146152
* a reachable from b => ord(b) < ord(a)
147-
* in addition, when lifo == 0, commits on parallel tracks are
148-
* sorted in the dates order.
153+
* sort_order further specifies:
154+
* REV_SORT_IN_GRAPH_ORDER: try to show a commit on a single-parent
155+
* chain together.
156+
* REV_SORT_BY_COMMIT_DATE: show eligible commits in committer-date order.
149157
*/
150-
void sort_in_topological_order(struct commit_list ** list, int lifo);
158+
void sort_in_topological_order(struct commit_list **, enum rev_sort_order);
151159

152160
struct commit_graft {
153161
unsigned char sha1[20];

revision.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,7 +1038,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)
10381038
DIFF_OPT_SET(&revs->pruning, QUICK);
10391039
revs->pruning.add_remove = file_add_remove;
10401040
revs->pruning.change = file_change;
1041-
revs->lifo = 1;
1041+
revs->sort_order = REV_SORT_IN_GRAPH_ORDER;
10421042
revs->dense = 1;
10431043
revs->prefix = prefix;
10441044
revs->max_age = -1;
@@ -1373,7 +1373,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
13731373
} else if (!strcmp(arg, "--merge")) {
13741374
revs->show_merge = 1;
13751375
} else if (!strcmp(arg, "--topo-order")) {
1376-
revs->lifo = 1;
1376+
revs->sort_order = REV_SORT_IN_GRAPH_ORDER;
13771377
revs->topo_order = 1;
13781378
} else if (!strcmp(arg, "--simplify-merges")) {
13791379
revs->simplify_merges = 1;
@@ -1391,7 +1391,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
13911391
revs->prune = 1;
13921392
load_ref_decorations(DECORATE_SHORT_REFS);
13931393
} else if (!strcmp(arg, "--date-order")) {
1394-
revs->lifo = 0;
1394+
revs->sort_order = REV_SORT_BY_COMMIT_DATE;
13951395
revs->topo_order = 1;
13961396
} else if (!prefixcmp(arg, "--early-output")) {
13971397
int count = 100;
@@ -2165,7 +2165,7 @@ int prepare_revision_walk(struct rev_info *revs)
21652165
if (limit_list(revs) < 0)
21662166
return -1;
21672167
if (revs->topo_order)
2168-
sort_in_topological_order(&revs->commits, revs->lifo);
2168+
sort_in_topological_order(&revs->commits, revs->sort_order);
21692169
if (revs->simplify_merges)
21702170
simplify_merges(revs);
21712171
if (revs->children.name)
@@ -2480,7 +2480,7 @@ static void create_boundary_commit_list(struct rev_info *revs)
24802480
* If revs->topo_order is set, sort the boundary commits
24812481
* in topological order
24822482
*/
2483-
sort_in_topological_order(&revs->commits, revs->lifo);
2483+
sort_in_topological_order(&revs->commits, revs->sort_order);
24842484
}
24852485

24862486
static struct commit *get_revision_internal(struct rev_info *revs)

revision.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "parse-options.h"
55
#include "grep.h"
66
#include "notes.h"
7+
#include "commit.h"
78

89
#define SEEN (1u<<0)
910
#define UNINTERESTING (1u<<1)
@@ -60,6 +61,10 @@ struct rev_info {
6061
const char *prefix;
6162
const char *def;
6263
struct pathspec prune_data;
64+
65+
/* topo-sort */
66+
enum rev_sort_order sort_order;
67+
6368
unsigned int early_output:1,
6469
ignore_missing:1;
6570

@@ -70,7 +75,6 @@ struct rev_info {
7075
show_all:1,
7176
remove_empty_trees:1,
7277
simplify_history:1,
73-
lifo:1,
7478
topo_order:1,
7579
simplify_merges:1,
7680
simplify_by_decoration:1,

0 commit comments

Comments
 (0)