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 <gitster@pobox.com>

Junio C Hamano committed Jun 6, 2013 at 16:07 UTC 08f704f294e4a3525b405c2cb1f4ee85e73fd92c
6 files changed +38 -20
builtin/log.c
+1 -1
@@ -205,7 +205,7 @@ static void log_show_early(struct rev_info *revs, struct commit_list *list)
205 int i = revs->early_output;
206 int show_header = 1;
207
208 - sort_in_topological_order(&list, revs->lifo);
208 + sort_in_topological_order(&list, revs->sort_order);
209 while (list && i) {
210 struct commit *commit = list->item;
211 switch (simplify_commit(revs, commit)) {
builtin/show-branch.c
+8 -6
@@ -631,7 +631,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
631 int num_rev, i, extra = 0;
632 int all_heads = 0, all_remotes = 0;
633 int all_mask, all_revs;
634 - int lifo = 1;
634 + enum rev_sort_order sort_order = REV_SORT_IN_GRAPH_ORDER;
635 char head[128];
636 const char *head_p;
637 int head_len;
@@ -666,15 +666,17 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
666 N_("show possible merge bases")),
667 OPT_BOOLEAN(0, "independent", &independent,
668 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),
672 OPT_BOOLEAN(0, "topics", &topics,
673 N_("show only commits not on the first branch")),
674 OPT_SET_INT(0, "sparse", &dense,
675 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,
677 N_("show commits where no parent comes before its "
677 - "children"), 0),
678 + "children"),
679 + REV_SORT_BY_COMMIT_DATE),
680 { OPTION_CALLBACK, 'g', "reflog", &reflog_base, N_("<n>[,<base>]"),
681 N_("show <n> most recent ref-log entries starting at "
682 "base"),
@@ -901,7 +903,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
903 exit(0);
904
905 /* Sort topologically */
904 - sort_in_topological_order(&seen, lifo);
906 + sort_in_topological_order(&seen, sort_order);
907
908 /* Give names to commits */
909 if (!sha1_name && !no_name)
commit.c
+8 -4
@@ -512,7 +512,7 @@ define_commit_slab(indegree_slab, int);
512 /*
513 * Performs an in-place topological sort on the list supplied.
514 */
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)
516 {
517 struct commit_list *next, *orig = *list;
518 struct commit_list *work, **insert;
@@ -561,7 +561,7 @@ void sort_in_topological_order(struct commit_list ** list, int lifo)
561 }
562
563 /* process the list in topological order */
564 - if (!lifo)
564 + if (sort_order != REV_SORT_IN_GRAPH_ORDER)
565 commit_list_sort_by_date(&work);
566
567 pptr = list;
@@ -588,10 +588,14 @@ void sort_in_topological_order(struct commit_list ** list, int lifo)
588 * guaranteeing topological order.
589 */
590 if (--(*pi) == 1) {
591 - if (!lifo)
591 + switch (sort_order) {
592 + case REV_SORT_BY_COMMIT_DATE:
593 commit_list_insert_by_date(parent, &work);
593 - else
594 + break;
595 + default: /* REV_SORT_IN_GRAPH_ORDER */
596 commit_list_insert(parent, &work);
597 + break;
598 + }
599 }
600 }
601 /*
commit.h
+11 -3
@@ -139,15 +139,23 @@ struct commit *pop_commit(struct commit_list **stack);
139 void clear_commit_marks(struct commit *commit, unsigned int mark);
140 void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark);
141
142 +
143 +enum rev_sort_order {
144 + REV_SORT_IN_GRAPH_ORDER = 0,
145 + REV_SORT_BY_COMMIT_DATE
146 +};
147 +
148 /*
149 * Performs an in-place topological sort of list supplied.
150 *
151 * invariant of resulting list is:
152 * 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.
157 */
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);
159
160 struct commit_graft {
161 unsigned char sha1[20];
revision.c
+5 -5
@@ -1038,7 +1038,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)
1038 DIFF_OPT_SET(&revs->pruning, QUICK);
1039 revs->pruning.add_remove = file_add_remove;
1040 revs->pruning.change = file_change;
1041 - revs->lifo = 1;
1041 + revs->sort_order = REV_SORT_IN_GRAPH_ORDER;
1042 revs->dense = 1;
1043 revs->prefix = prefix;
1044 revs->max_age = -1;
@@ -1373,7 +1373,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
1373 } else if (!strcmp(arg, "--merge")) {
1374 revs->show_merge = 1;
1375 } else if (!strcmp(arg, "--topo-order")) {
1376 - revs->lifo = 1;
1376 + revs->sort_order = REV_SORT_IN_GRAPH_ORDER;
1377 revs->topo_order = 1;
1378 } else if (!strcmp(arg, "--simplify-merges")) {
1379 revs->simplify_merges = 1;
@@ -1391,7 +1391,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
1391 revs->prune = 1;
1392 load_ref_decorations(DECORATE_SHORT_REFS);
1393 } else if (!strcmp(arg, "--date-order")) {
1394 - revs->lifo = 0;
1394 + revs->sort_order = REV_SORT_BY_COMMIT_DATE;
1395 revs->topo_order = 1;
1396 } else if (!prefixcmp(arg, "--early-output")) {
1397 int count = 100;
@@ -2165,7 +2165,7 @@ int prepare_revision_walk(struct rev_info *revs)
2165 if (limit_list(revs) < 0)
2166 return -1;
2167 if (revs->topo_order)
2168 - sort_in_topological_order(&revs->commits, revs->lifo);
2168 + sort_in_topological_order(&revs->commits, revs->sort_order);
2169 if (revs->simplify_merges)
2170 simplify_merges(revs);
2171 if (revs->children.name)
@@ -2480,7 +2480,7 @@ static void create_boundary_commit_list(struct rev_info *revs)
2480 * If revs->topo_order is set, sort the boundary commits
2481 * in topological order
2482 */
2483 - sort_in_topological_order(&revs->commits, revs->lifo);
2483 + sort_in_topological_order(&revs->commits, revs->sort_order);
2484 }
2485
2486 static struct commit *get_revision_internal(struct rev_info *revs)
revision.h
+5 -1
@@ -4,6 +4,7 @@
4 #include "parse-options.h"
5 #include "grep.h"
6 #include "notes.h"
7 +#include "commit.h"
8
9 #define SEEN (1u<<0)
10 #define UNINTERESTING (1u<<1)
@@ -60,6 +61,10 @@ struct rev_info {
61 const char *prefix;
62 const char *def;
63 struct pathspec prune_data;
64 +
65 + /* topo-sort */
66 + enum rev_sort_order sort_order;
67 +
68 unsigned int early_output:1,
69 ignore_missing:1;
70
@@ -70,7 +75,6 @@ struct rev_info {
75 show_all:1,
76 remove_empty_trees:1,
77 simplify_history:1,
73 - lifo:1,
78 topo_order:1,
79 simplify_merges:1,
80 simplify_by_decoration:1,