/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2006 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tests for reconiliation of repositories."""
18
19
20
import bzrlib
21
import bzrlib.errors as errors
1731.1.1 by Aaron Bentley
Make root entry an InventoryDirectory, make EmptyTree really empty
22
from bzrlib.inventory import Inventory
1594.2.7 by Robert Collins
Add versionedfile.fix_parents api for correcting data post hoc.
23
from bzrlib.reconcile import reconcile, Reconciler
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
24
from bzrlib.revision import Revision
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
25
from bzrlib.tests import TestSkipped
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
26
from bzrlib.tests.repository_implementations.test_repository import TestCaseWithRepository
27
from bzrlib.transport import get_transport
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
28
from bzrlib.uncommit import uncommit
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
29
from bzrlib.workingtree import WorkingTree
30
31
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
32
class TestReconcile(TestCaseWithRepository):
33
34
    def checkUnreconciled(self, d, reconciler):
35
        """Check that d did not get reconciled."""
36
        # nothing should have been fixed yet:
37
        self.assertEqual(0, reconciler.inconsistent_parents)
38
        # and no garbage inventories
39
        self.assertEqual(0, reconciler.garbage_inventories)
40
        self.checkNoBackupInventory(d)
41
42
    def checkNoBackupInventory(self, aBzrDir):
43
        """Check that there is no backup inventory in aBzrDir."""
44
        repo = aBzrDir.open_repository()
45
        self.assertRaises(errors.NoSuchFile,
46
                          repo.control_weaves.get_weave,
47
                          'inventory.backup',
48
                          repo.get_transaction())
49
50
51
class TestsNeedingReweave(TestReconcile):
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
52
53
    def setUp(self):
1570.1.8 by Robert Collins
Only reconcile if doing so will perform gc or correct ancestry.
54
        super(TestsNeedingReweave, self).setUp()
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
55
        
56
        t = get_transport(self.get_url())
57
        # an empty inventory with no revision for testing with.
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
58
        repo = self.make_repository('inventory_without_revision')
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
59
        repo.lock_write()
60
        repo.start_write_group()
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
61
        inv = Inventory(revision_id='missing')
62
        inv.root.revision = 'missing'
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
63
        repo.add_inventory('missing', inv, [])
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
64
        repo.commit_write_group()
65
        repo.unlock()
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
66
67
        # an empty inventory with no revision for testing with.
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
68
        # this is referenced by 'references_missing' to let us test
69
        # that all the cached data is correctly converted into ghost links
70
        # and the referenced inventory still cleaned.
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
71
        repo = self.make_repository('inventory_without_revision_and_ghost')
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
72
        repo.lock_write()
73
        repo.start_write_group()
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
74
        repo.add_inventory('missing', inv, [])
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
75
        inv = Inventory(revision_id='references_missing')
76
        inv.root.revision = 'references_missing'
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
77
        sha1 = repo.add_inventory('references_missing', inv, ['missing'])
78
        rev = Revision(timestamp=0,
79
                       timezone=None,
80
                       committer="Foo Bar <foo@example.com>",
81
                       message="Message",
82
                       inventory_sha1=sha1,
83
                       revision_id='references_missing')
84
        rev.parent_ids = ['missing']
85
        repo.add_revision('references_missing', rev)
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
86
        repo.commit_write_group()
87
        repo.unlock()
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
88
89
        # a inventory with no parents and the revision has parents..
90
        # i.e. a ghost.
1570.1.8 by Robert Collins
Only reconcile if doing so will perform gc or correct ancestry.
91
        repo = self.make_repository('inventory_one_ghost')
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
92
        repo.lock_write()
93
        repo.start_write_group()
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
94
        inv = Inventory(revision_id='ghost')
95
        inv.root.revision = 'ghost'
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
96
        sha1 = repo.add_inventory('ghost', inv, [])
97
        rev = Revision(timestamp=0,
98
                       timezone=None,
99
                       committer="Foo Bar <foo@example.com>",
100
                       message="Message",
101
                       inventory_sha1=sha1,
102
                       revision_id='ghost')
103
        rev.parent_ids = ['the_ghost']
104
        repo.add_revision('ghost', rev)
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
105
        repo.commit_write_group()
106
        repo.unlock()
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
107
         
108
        # a inventory with a ghost that can be corrected now.
109
        t.copy_tree('inventory_one_ghost', 'inventory_ghost_present')
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
110
        bzrdir_url = self.get_url('inventory_ghost_present')
111
        bzrdir = bzrlib.bzrdir.BzrDir.open(bzrdir_url)
112
        repo = bzrdir.open_repository()
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
113
        repo.lock_write()
114
        repo.start_write_group()
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
115
        inv = Inventory(revision_id='the_ghost')
116
        inv.root.revision = 'the_ghost'
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
117
        sha1 = repo.add_inventory('the_ghost', inv, [])
118
        rev = Revision(timestamp=0,
119
                       timezone=None,
120
                       committer="Foo Bar <foo@example.com>",
121
                       message="Message",
122
                       inventory_sha1=sha1,
123
                       revision_id='the_ghost')
124
        rev.parent_ids = []
125
        repo.add_revision('the_ghost', rev)
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
126
        repo.commit_write_group()
127
        repo.unlock()
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
128
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
129
    def checkEmptyReconcile(self, **kwargs):
130
        """Check a reconcile on an empty repository."""
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
131
        self.make_repository('empty')
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
132
        d = bzrlib.bzrdir.BzrDir.open(self.get_url('empty'))
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
133
        # calling on a empty repository should do nothing
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
134
        reconciler = d.find_repository().reconcile(**kwargs)
1570.1.8 by Robert Collins
Only reconcile if doing so will perform gc or correct ancestry.
135
        # no inconsistent parents should have been found
136
        self.assertEqual(0, reconciler.inconsistent_parents)
137
        # and no garbage inventories
138
        self.assertEqual(0, reconciler.garbage_inventories)
139
        # and no backup weave should have been needed/made.
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
140
        self.checkNoBackupInventory(d)
141
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
142
    def test_reconcile_empty(self):
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
143
        # in an empty repo, theres nothing to do.
144
        self.checkEmptyReconcile()
145
2671.4.2 by Robert Collins
Review feedback.
146
    def test_repo_has_reconcile_does_inventory_gc_attribute(self):
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
147
        repo = self.make_repository('repo')
2671.4.2 by Robert Collins
Review feedback.
148
        self.assertNotEqual(None, repo._reconcile_does_inventory_gc)
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
149
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
150
    def test_reconcile_empty_thorough(self):
151
        # reconcile should accept thorough=True
152
        self.checkEmptyReconcile(thorough=True)
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
153
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
154
    def test_convenience_reconcile_inventory_without_revision_reconcile(self):
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
155
        # smoke test for the all in one ui tool
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
156
        bzrdir_url = self.get_url('inventory_without_revision')
157
        bzrdir = bzrlib.bzrdir.BzrDir.open(bzrdir_url)
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
158
        repo = bzrdir.open_repository()
2671.4.2 by Robert Collins
Review feedback.
159
        if not repo._reconcile_does_inventory_gc:
160
            raise TestSkipped('Irrelevant test')
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
161
        reconcile(bzrdir)
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
162
        # now the backup should have it but not the current inventory
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
163
        repo = bzrdir.open_repository()
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
164
        self.check_missing_was_removed(repo)
165
166
    def test_reweave_inventory_without_revision(self):
167
        # an excess inventory on its own is only reconciled by using thorough
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
168
        d_url = self.get_url('inventory_without_revision')
169
        d = bzrlib.bzrdir.BzrDir.open(d_url)
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
170
        repo = d.open_repository()
2671.4.2 by Robert Collins
Review feedback.
171
        if not repo._reconcile_does_inventory_gc:
172
            raise TestSkipped('Irrelevant test')
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
173
        self.checkUnreconciled(d, repo.reconcile())
174
        reconciler = repo.reconcile(thorough=True)
175
        # no bad parents
176
        self.assertEqual(0, reconciler.inconsistent_parents)
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
177
        # and one garbage inventory
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
178
        self.assertEqual(1, reconciler.garbage_inventories)
179
        self.check_missing_was_removed(repo)
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
180
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
181
    def check_thorough_reweave_missing_revision(self, aBzrDir, reconcile,
182
            **kwargs):
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
183
        # actual low level test.
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
184
        repo = aBzrDir.open_repository()
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
185
        if ([None, 'missing', 'references_missing']
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
186
            != repo.get_ancestry('references_missing')):
187
            # the repo handles ghosts without corruption, so reconcile has
2671.4.3 by Robert Collins
Reformat comment to be more presentable.
188
            # nothing to do here. Specifically, this test has the inventory
189
            # 'missing' present and the revision 'missing' missing, so clearly
190
            # 'missing' cannot be reported in the present ancestry -> missing
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
191
            # is something that can be filled as a ghost.
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
192
            expected_inconsistent_parents = 0
193
        else:
194
            expected_inconsistent_parents = 1
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
195
        reconciler = reconcile(**kwargs)
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
196
        # some number of inconsistent parents should have been found
197
        self.assertEqual(expected_inconsistent_parents,
198
                         reconciler.inconsistent_parents)
1570.1.8 by Robert Collins
Only reconcile if doing so will perform gc or correct ancestry.
199
        # and one garbage inventories
200
        self.assertEqual(1, reconciler.garbage_inventories)
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
201
        # now the backup should have it but not the current inventory
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
202
        repo = aBzrDir.open_repository()
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
203
        self.check_missing_was_removed(repo)
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
204
        # and the parent list for 'references_missing' should have that
205
        # revision a ghost now.
206
        self.assertEqual([None, 'references_missing'],
207
                         repo.get_ancestry('references_missing'))
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
208
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
209
    def check_missing_was_removed(self, repo):
210
        backup = repo.control_weaves.get_weave('inventory.backup',
211
                                               repo.get_transaction())
212
        self.assertTrue('missing' in backup.versions())
213
        self.assertRaises(errors.RevisionNotPresent,
214
                          repo.get_inventory, 'missing')
215
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
216
    def test_reweave_inventory_without_revision_reconciler(self):
217
        # smoke test for the all in one Reconciler class,
218
        # other tests use the lower level repo.reconcile()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
219
        d_url = self.get_url('inventory_without_revision_and_ghost')
220
        d = bzrlib.bzrdir.BzrDir.open(d_url)
2671.4.2 by Robert Collins
Review feedback.
221
        if not d.open_repository()._reconcile_does_inventory_gc:
222
            raise TestSkipped('Irrelevant test')
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
223
        def reconcile():
224
            reconciler = Reconciler(d)
225
            reconciler.reconcile()
226
            return reconciler
227
        self.check_thorough_reweave_missing_revision(d, reconcile)
228
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
229
    def test_reweave_inventory_without_revision_and_ghost(self):
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
230
        # actual low level test.
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
231
        d_url = self.get_url('inventory_without_revision_and_ghost')
232
        d = bzrlib.bzrdir.BzrDir.open(d_url)
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
233
        repo = d.open_repository()
2671.4.2 by Robert Collins
Review feedback.
234
        if not repo._reconcile_does_inventory_gc:
235
            raise TestSkipped('Irrelevant test')
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
236
        # nothing should have been altered yet : inventories without
237
        # revisions are not data loss incurring for current format
238
        self.check_thorough_reweave_missing_revision(d, repo.reconcile,
239
            thorough=True)
240
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
241
    def test_reweave_inventory_preserves_a_revision_with_ghosts(self):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
242
        d = bzrlib.bzrdir.BzrDir.open(self.get_url('inventory_one_ghost'))
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
243
        reconciler = d.open_repository().reconcile(thorough=True)
1570.1.8 by Robert Collins
Only reconcile if doing so will perform gc or correct ancestry.
244
        # no inconsistent parents should have been found: 
245
        # the lack of a parent for ghost is normal
246
        self.assertEqual(0, reconciler.inconsistent_parents)
247
        # and one garbage inventories
248
        self.assertEqual(0, reconciler.garbage_inventories)
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
249
        # now the current inventory should still have 'ghost'
250
        repo = d.open_repository()
251
        repo.get_inventory('ghost')
252
        self.assertEqual([None, 'ghost'], repo.get_ancestry('ghost'))
253
        
254
    def test_reweave_inventory_fixes_ancestryfor_a_present_ghost(self):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
255
        d = bzrlib.bzrdir.BzrDir.open(self.get_url('inventory_ghost_present'))
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
256
        repo = d.open_repository()
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
257
        ghost_ancestry = repo.get_ancestry('ghost')
258
        if ghost_ancestry == [None, 'the_ghost', 'ghost']:
259
            # the repo handles ghosts without corruption, so reconcile has
260
            # nothing to do
261
            return
262
        self.assertEqual([None, 'ghost'], ghost_ancestry)
1594.2.7 by Robert Collins
Add versionedfile.fix_parents api for correcting data post hoc.
263
        reconciler = repo.reconcile()
1692.1.3 by Robert Collins
Finish the reconcile tweak: filled in ghosts are a data loss issue and need to be checked during fast reconciles.
264
        # this is a data corrupting error, so a normal reconcile should fix it.
1570.1.8 by Robert Collins
Only reconcile if doing so will perform gc or correct ancestry.
265
        # one inconsistent parents should have been found : the
266
        # available but not reference parent for ghost.
267
        self.assertEqual(1, reconciler.inconsistent_parents)
268
        # and no garbage inventories
269
        self.assertEqual(0, reconciler.garbage_inventories)
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
270
        # now the current inventory should still have 'ghost'
271
        repo = d.open_repository()
272
        repo.get_inventory('ghost')
273
        repo.get_inventory('the_ghost')
274
        self.assertEqual([None, 'the_ghost', 'ghost'], repo.get_ancestry('ghost'))
275
        self.assertEqual([None, 'the_ghost'], repo.get_ancestry('the_ghost'))
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
276
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
277
278
class TestReconcileWithIncorrectRevisionCache(TestReconcile):
279
    """Ancestry data gets cached in knits and weaves should be reconcilable.
280
281
    This class tests that reconcile can correct invalid caches (such as after
282
    a reconcile).
283
    """
284
285
    def setUp(self):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
286
        self.reduceLockdirTimeout()
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
287
        super(TestReconcileWithIncorrectRevisionCache, self).setUp()
288
        
289
        t = get_transport(self.get_url())
290
        # we need a revision with two parents in the wrong order
291
        # which should trigger reinsertion.
292
        # and another with the first one correct but the other two not
293
        # which should not trigger reinsertion.
294
        # these need to be in different repositories so that we don't
295
        # trigger a reconcile based on the other case.
296
        # there is no api to construct a broken knit repository at
297
        # this point. if we ever encounter a bad graph in a knit repo
298
        # we should add a lower level api to allow constructing such cases.
299
        
300
        # first off the common logic:
301
        tree = self.make_branch_and_tree('wrong-first-parent')
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
302
        second_tree = self.make_branch_and_tree('reversed-secondary-parents')
303
        for t in [tree, second_tree]:
304
            t.commit('1', rev_id='1')
305
            uncommit(t.branch, tree=t)
306
            t.commit('2', rev_id='2')
307
            uncommit(t.branch, tree=t)
308
            t.commit('3', rev_id='3')
309
            uncommit(t.branch, tree=t)
310
        #second_tree = self.make_branch_and_tree('reversed-secondary-parents')
311
        #second_tree.pull(tree) # XXX won't copy the repo?
312
        repo_secondary = second_tree.branch.repository
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
313
314
        # now setup the wrong-first parent case
315
        repo = tree.branch.repository
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
316
        repo.lock_write()
317
        repo.start_write_group()
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
318
        inv = Inventory(revision_id='wrong-first-parent')
319
        inv.root.revision = 'wrong-first-parent'
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
320
        sha1 = repo.add_inventory('wrong-first-parent', inv, ['2', '1'])
321
        rev = Revision(timestamp=0,
322
                       timezone=None,
323
                       committer="Foo Bar <foo@example.com>",
324
                       message="Message",
325
                       inventory_sha1=sha1,
326
                       revision_id='wrong-first-parent')
327
        rev.parent_ids = ['1', '2']
328
        repo.add_revision('wrong-first-parent', rev)
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
329
        repo.commit_write_group()
330
        repo.unlock()
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
331
332
        # now setup the wrong-secondary parent case
333
        repo = repo_secondary
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
334
        repo.lock_write()
335
        repo.start_write_group()
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
336
        inv = Inventory(revision_id='wrong-secondary-parent')
337
        inv.root.revision = 'wrong-secondary-parent'
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
338
        sha1 = repo.add_inventory('wrong-secondary-parent', inv, ['1', '3', '2'])
339
        rev = Revision(timestamp=0,
340
                       timezone=None,
341
                       committer="Foo Bar <foo@example.com>",
342
                       message="Message",
343
                       inventory_sha1=sha1,
344
                       revision_id='wrong-secondary-parent')
345
        rev.parent_ids = ['1', '2', '3']
346
        repo.add_revision('wrong-secondary-parent', rev)
2617.6.4 by Robert Collins
Update tests with things that break when a repository requires write groups to be used.
347
        repo.commit_write_group()
348
        repo.unlock()
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
349
350
    def test_reconcile_wrong_order(self):
351
        # a wrong order in primary parents is optionally correctable
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
352
        t = get_transport(self.get_url()).clone('wrong-first-parent')
353
        d = bzrlib.bzrdir.BzrDir.open_from_transport(t)
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
354
        repo = d.open_repository()
355
        g = repo.get_revision_graph()
2625.8.1 by Robert Collins
LIBRARY API BREAKS:
356
        if tuple(g['wrong-first-parent']) == ('1', '2'):
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
357
            raise TestSkipped('wrong-first-parent is not setup for testing')
358
        self.checkUnreconciled(d, repo.reconcile())
359
        # nothing should have been altered yet : inventories without
360
        # revisions are not data loss incurring for current format
361
        reconciler = repo.reconcile(thorough=True)
362
        # these show up as inconsistent parents
363
        self.assertEqual(1, reconciler.inconsistent_parents)
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
364
        # and no garbage inventories
365
        self.assertEqual(0, reconciler.garbage_inventories)
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
366
        # and should have been fixed:
367
        g = repo.get_revision_graph()
2625.8.1 by Robert Collins
LIBRARY API BREAKS:
368
        self.assertEqual(('1', '2'), g['wrong-first-parent'])
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
369
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
370
    def test_reconcile_wrong_order_secondary_inventory(self):
371
        # a wrong order in the parents for inventories is ignored.
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
372
        t = get_transport(self.get_url()).clone('reversed-secondary-parents')
373
        d = bzrlib.bzrdir.BzrDir.open_from_transport(t)
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
374
        repo = d.open_repository()
375
        self.checkUnreconciled(d, repo.reconcile())
376
        self.checkUnreconciled(d, repo.reconcile(thorough=True))