@matheusbsbs / matheus-bagliano / commits / 498bcd3159
Fork 0

rev-list: fix --reverse interaction with --parents

--reverse did not interact well with --parents, as the included test case shows: in a history like A--B. \ \ `C--M--D the command git rev-list --reverse --parents --full-history HEAD erroneously lists D as having no parents at all. (Without --reverse, it correctly lists M.) This is caused by the machinery driving --reverse: it first grabs all commits through the normal routines, then runs them through the same routines again, effectively simplifying them twice. Fix this by moving the --reverse one level up, into get_revision(). This way we can cleanly grab all commits via the normal calls, then just pop them off the list one by one without interfering with get_revision_internal(). Signed-off-by: Thomas Rast <trast@student.ethz.ch> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Thomas Rast committed Aug 29, 2008 at 21:18 UTC 498bcd3159ae3711f2beea2ea497cdc09856ee79
3 files changed +60 -21
revision.c
+17 -21
@@ -1786,26 +1786,6 @@ static struct commit *get_revision_internal(struct rev_info *revs)
1786 return c;
1787 }
1788
1789 - if (revs->reverse) {
1790 - int limit = -1;
1791 -
1792 - if (0 <= revs->max_count) {
1793 - limit = revs->max_count;
1794 - if (0 < revs->skip_count)
1795 - limit += revs->skip_count;
1796 - }
1797 - l = NULL;
1798 - while ((c = get_revision_1(revs))) {
1799 - commit_list_insert(c, &l);
1800 - if ((0 < limit) && !--limit)
1801 - break;
1802 - }
1803 - revs->commits = l;
1804 - revs->reverse = 0;
1805 - revs->max_count = -1;
1806 - c = NULL;
1807 - }
1808 -
1789 /*
1790 * Now pick up what they want to give us
1791 */
@@ -1878,7 +1858,23 @@ static struct commit *get_revision_internal(struct rev_info *revs)
1858
1859 struct commit *get_revision(struct rev_info *revs)
1860 {
1881 - struct commit *c = get_revision_internal(revs);
1861 + struct commit *c;
1862 + struct commit_list *reversed;
1863 +
1864 + if (revs->reverse) {
1865 + reversed = NULL;
1866 + while ((c = get_revision_internal(revs))) {
1867 + commit_list_insert(c, &reversed);
1868 + }
1869 + revs->commits = reversed;
1870 + revs->reverse = 0;
1871 + revs->reverse_output_stage = 1;
1872 + }
1873 +
1874 + if (revs->reverse_output_stage)
1875 + return pop_commit(&revs->commits);
1876 +
1877 + c = get_revision_internal(revs);
1878 if (c && revs->graph)
1879 graph_update(revs->graph, c);
1880 return c;
revision.h
+1
@@ -53,6 +53,7 @@ struct rev_info {
53 rewrite_parents:1,
54 print_parents:1,
55 reverse:1,
56 + reverse_output_stage:1,
57 cherry_pick:1,
58 first_parent_only:1;
59
t/t6013-rev-list-reverse-parents.sh new
+42
@@ -0,0 +1,42 @@
1 +#!/bin/sh
2 +
3 +test_description='--reverse combines with --parents'
4 +
5 +. ./test-lib.sh
6 +
7 +
8 +commit () {
9 + test_tick &&
10 + echo $1 > foo &&
11 + git add foo &&
12 + git commit -m "$1"
13 +}
14 +
15 +test_expect_success 'set up --reverse example' '
16 + commit one &&
17 + git tag root &&
18 + commit two &&
19 + git checkout -b side HEAD^ &&
20 + commit three &&
21 + git checkout master &&
22 + git merge -s ours side &&
23 + commit five
24 + '
25 +
26 +test_expect_success '--reverse --parents --full-history combines correctly' '
27 + git rev-list --parents --full-history master -- foo |
28 + tac > expected &&
29 + git rev-list --reverse --parents --full-history master -- foo \
30 + > actual &&
31 + test_cmp actual expected
32 + '
33 +
34 +test_expect_success '--boundary does too' '
35 + git rev-list --boundary --parents --full-history master ^root -- foo |
36 + tac > expected &&
37 + git rev-list --boundary --reverse --parents --full-history \
38 + master ^root -- foo > actual &&
39 + test_cmp actual expected
40 + '
41 +
42 +test_done