Merge lp:~jameinel/bzr/2.0rc2-419241-merge-sort into lp:bzr/2.0

Proposed by John A Meinel
Status: Merged
Merged at revision: not available
Proposed branch: lp:~jameinel/bzr/2.0rc2-419241-merge-sort
Merge into: lp:bzr/2.0
Diff against target: 160 lines
To merge this branch: bzr merge lp:~jameinel/bzr/2.0rc2-419241-merge-sort
Reviewer Review Type Date Requested Status
Vincent Ladeuil Approve
Review via email: mp+10755@code.launchpad.net
To post a comment you must log in.
Revision history for this message
John A Meinel (jameinel) wrote :

This fixes a bug in KnownGraph.merge_sort() when there is a ghost as a mainline parent.

The old code didn't notice because we always pruned ghosts when passing in the parent_map, but it seems nicer to have merge_sort handle them directly. (Means fewer calls to _strip_NULL_ghosts :).

This is part of a critical regression right now for stuff like 'bzr log' on branches with mainline ghosts.

The second (more critical) part is coming soon.

(The code is built on the 2.0 release branch so it can be merged there primarily.)

Revision history for this message
Vincent Ladeuil (vila) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2009-08-26 12:54:21 +0000
3+++ NEWS 2009-08-26 16:35:14 +0000
4@@ -6,6 +6,17 @@
5 .. contents:: List of Releases
6 :depth: 1
7
8+bzr 2.0rc2
9+##########
10+
11+Bug Fixes
12+*********
13+
14+* Fix a potential segmentation fault when doing 'log' of a branch that had
15+ ghosts in its mainline. (evaluating None as a tuple is bad.)
16+ (John Arbash Meinel, #419241)
17+
18+
19 bzr 2.0rc1
20 ##########
21
22
23=== modified file 'bzrlib/_known_graph_pyx.pyx'
24--- bzrlib/_known_graph_pyx.pyx 2009-08-18 21:41:08 +0000
25+++ bzrlib/_known_graph_pyx.pyx 2009-08-26 16:35:14 +0000
26@@ -443,7 +443,8 @@
27 self.completed = 0
28
29 def __repr__(self):
30- return '%s(depth:%s rev:%s,%s,%s first:%s seen:%s)' % (self.__class__.__name__,
31+ return '%s(%s depth:%s rev:%s,%s,%s first:%s seen:%s)' % (
32+ self.__class__.__name__, self.key,
33 self.merge_depth,
34 self._revno_first, self._revno_second, self._revno_last,
35 self.is_first_child, self.seen_by_child)
36@@ -497,7 +498,6 @@
37 if (tip_key is not None and tip_key != NULL_REVISION
38 and tip_key != (NULL_REVISION,)):
39 node = self.graph._nodes[tip_key]
40- self._get_ms_node(node)
41 self._push_node(node, 0)
42
43 cdef _MergeSortNode _get_ms_node(self, _KnownGraphNode node):
44@@ -518,10 +518,17 @@
45
46 ms_node = self._get_ms_node(node)
47 ms_node.merge_depth = merge_depth
48+ if node.parents is None:
49+ raise RuntimeError('ghost nodes should not be pushed'
50+ ' onto the stack: %s' % (node,))
51 if PyTuple_GET_SIZE(node.parents) > 0:
52 parent_node = _get_parent(node.parents, 0)
53 ms_node.left_parent = parent_node
54- ms_node.left_pending_parent = parent_node
55+ if parent_node.parents is None: # left-hand ghost
56+ ms_node.left_pending_parent = None
57+ ms_node.left_parent = None
58+ else:
59+ ms_node.left_pending_parent = parent_node
60 if PyTuple_GET_SIZE(node.parents) > 1:
61 ms_node.pending_parents = []
62 for pos from 1 <= pos < PyTuple_GET_SIZE(node.parents):
63
64=== modified file 'bzrlib/tests/test__known_graph.py'
65--- bzrlib/tests/test__known_graph.py 2009-08-18 21:41:08 +0000
66+++ bzrlib/tests/test__known_graph.py 2009-08-26 16:35:14 +0000
67@@ -731,6 +731,20 @@
68 ('A', 0, (1,), True),
69 ])
70
71+ def test_lefthand_ghost(self):
72+ # ghost
73+ # |
74+ # A
75+ # |
76+ # B
77+ self.assertSortAndIterate(
78+ {'A': ['ghost'],
79+ 'B': ['A'],
80+ }, 'B',
81+ [('B', 0, (2,), False),
82+ ('A', 0, (1,), True),
83+ ])
84+
85 def test_graph_cycle(self):
86 # merge_sort should fail with a simple error when a graph cycle is
87 # encountered.
88
89=== modified file 'bzrlib/tsort.py'
90--- bzrlib/tsort.py 2009-08-19 16:23:39 +0000
91+++ bzrlib/tsort.py 2009-08-26 16:35:14 +0000
92@@ -459,9 +459,15 @@
93 left_subtree_pushed_stack_append(False)
94 pending_parents_stack_append(list(parents))
95 # as we push it, check if it is the first child
96+ parent_info = None
97 if parents:
98 # node has parents, assign from the left most parent.
99- parent_info = revnos[parents[0]]
100+ try:
101+ parent_info = revnos[parents[0]]
102+ except KeyError:
103+ # Left-hand parent is a ghost, consider it not to exist
104+ pass
105+ if parent_info is not None:
106 first_child = parent_info[1]
107 parent_info[1] = False
108 else:
109@@ -495,9 +501,15 @@
110 pending_parents_stack_pop()
111
112 parents = original_graph[node_name]
113+ parent_revno = None
114 if parents:
115 # node has parents, assign from the left most parent.
116- parent_revno = revnos[parents[0]][0]
117+ try:
118+ parent_revno = revnos[parents[0]][0]
119+ except KeyError:
120+ # left-hand parent is a ghost, treat it as not existing
121+ pass
122+ if parent_revno is not None:
123 if not first_child:
124 # not the first child, make a new branch
125 base_revno = parent_revno[0]
126@@ -628,10 +640,15 @@
127 self._left_subtree_pushed_stack.append(False)
128 self._pending_parents_stack.append(list(parents))
129 # as we push it, figure out if this is the first child
130- parents = self._original_graph[node_name]
131+ parent_info = None
132 if parents:
133 # node has parents, assign from the left most parent.
134- parent_info = self._revnos[parents[0]]
135+ try:
136+ parent_info = self._revnos[parents[0]]
137+ except KeyError:
138+ # Left-hand parent is a ghost, consider it not to exist
139+ pass
140+ if parent_info is not None:
141 first_child = parent_info[1]
142 parent_info[1] = False
143 else:
144@@ -655,9 +672,15 @@
145 self._pending_parents_stack.pop()
146
147 parents = self._original_graph[node_name]
148+ parent_revno = None
149 if parents:
150 # node has parents, assign from the left most parent.
151- parent_revno = self._revnos[parents[0]][0]
152+ try:
153+ parent_revno = self._revnos[parents[0]][0]
154+ except KeyError:
155+ # left-hand parent is a ghost, treat it as not existing
156+ pass
157+ if parent_revno is not None:
158 if not first_child:
159 # not the first child, make a new branch
160 base_revno = parent_revno[0]

Subscribers

People subscribed via source and target branches