/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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
16
2819.2.5 by Andrew Bennetts
Make reconcile abort gracefully if the revision index has bad parents.
17
"""Tests for reconciliation of repositories."""
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
18
19
20
import bzrlib
21
import bzrlib.errors as errors
2745.6.43 by Andrew Bennetts
Tidy imports, docstrings, comments and variable names.
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
2819.2.5 by Andrew Bennetts
Make reconcile abort gracefully if the revision index has bad parents.
24
from bzrlib.repofmt.knitrepo import RepositoryFormatKnit
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
25
from bzrlib.revision import Revision
2819.2.5 by Andrew Bennetts
Make reconcile abort gracefully if the revision index has bad parents.
26
from bzrlib.tests import TestSkipped, TestNotApplicable
3689.1.1 by John Arbash Meinel
Rename repository_implementations tests into per_repository tests
27
from bzrlib.tests.per_repository.helpers import (
2819.2.5 by Andrew Bennetts
Make reconcile abort gracefully if the revision index has bad parents.
28
    TestCaseWithBrokenRevisionIndex,
29
    )
3689.1.1 by John Arbash Meinel
Rename repository_implementations tests into per_repository tests
30
from bzrlib.tests.per_repository import (
2745.6.32 by Andrew Bennetts
Some testing notes, test reorganisation, XXX comments and some failing tests.
31
    TestCaseWithRepository,
32
    )
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
33
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.
34
from bzrlib.uncommit import uncommit
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
35
36
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
37
class TestReconcile(TestCaseWithRepository):
38
39
    def checkUnreconciled(self, d, reconciler):
40
        """Check that d did not get reconciled."""
41
        # nothing should have been fixed yet:
42
        self.assertEqual(0, reconciler.inconsistent_parents)
43
        # and no garbage inventories
44
        self.assertEqual(0, reconciler.garbage_inventories)
45
        self.checkNoBackupInventory(d)
46
47
    def checkNoBackupInventory(self, aBzrDir):
48
        """Check that there is no backup inventory in aBzrDir."""
49
        repo = aBzrDir.open_repository()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
50
        # Remote repository, and possibly others, do not have
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
51
        # _transport.
52
        if getattr(repo, '_transport', None) is not None:
53
            for path in repo._transport.list_dir('.'):
54
                self.assertFalse('inventory.backup' in path)
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
55
56
57
class TestsNeedingReweave(TestReconcile):
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
58
59
    def setUp(self):
1570.1.8 by Robert Collins
Only reconcile if doing so will perform gc or correct ancestry.
60
        super(TestsNeedingReweave, self).setUp()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
61
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
62
        t = get_transport(self.get_url())
63
        # 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.
64
        repo = self.make_repository('inventory_without_revision')
2592.3.38 by Robert Collins
All experimental format tests passing again.
65
        repo.lock_write()
66
        repo.start_write_group()
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
67
        inv = Inventory(revision_id='missing')
68
        inv.root.revision = 'missing'
2592.3.119 by Robert Collins
Merge some test fixes from Martin.
69
        repo.add_inventory('missing', inv, [])
2592.3.38 by Robert Collins
All experimental format tests passing again.
70
        repo.commit_write_group()
71
        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.
72
2951.1.3 by Robert Collins
Partial support for native reconcile with packs.
73
        def add_commit(repo, revision_id, parent_ids):
74
            repo.lock_write()
75
            repo.start_write_group()
76
            inv = Inventory(revision_id=revision_id)
77
            inv.root.revision = revision_id
78
            root_id = inv.root.file_id
79
            sha1 = repo.add_inventory(revision_id, inv, parent_ids)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
80
            repo.texts.add_lines((root_id, revision_id), [], [])
2951.1.3 by Robert Collins
Partial support for native reconcile with packs.
81
            rev = bzrlib.revision.Revision(timestamp=0,
82
                                           timezone=None,
83
                                           committer="Foo Bar <foo@example.com>",
84
                                           message="Message",
85
                                           inventory_sha1=sha1,
86
                                           revision_id=revision_id)
87
            rev.parent_ids = parent_ids
88
            repo.add_revision(revision_id, rev)
89
            repo.commit_write_group()
90
            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.
91
        # an empty inventory with no revision for testing with.
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
92
        # this is referenced by 'references_missing' to let us test
93
        # that all the cached data is correctly converted into ghost links
94
        # 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.
95
        repo = self.make_repository('inventory_without_revision_and_ghost')
2592.3.38 by Robert Collins
All experimental format tests passing again.
96
        repo.lock_write()
97
        repo.start_write_group()
2592.3.119 by Robert Collins
Merge some test fixes from Martin.
98
        repo.add_inventory('missing', inv, [])
2592.3.38 by Robert Collins
All experimental format tests passing again.
99
        repo.commit_write_group()
100
        repo.unlock()
2951.1.3 by Robert Collins
Partial support for native reconcile with packs.
101
        add_commit(repo, 'references_missing', ['missing'])
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
102
103
        # a inventory with no parents and the revision has parents..
104
        # i.e. a ghost.
1570.1.8 by Robert Collins
Only reconcile if doing so will perform gc or correct ancestry.
105
        repo = self.make_repository('inventory_one_ghost')
2951.1.3 by Robert Collins
Partial support for native reconcile with packs.
106
        add_commit(repo, 'ghost', ['the_ghost'])
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
107
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
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()
2951.1.3 by Robert Collins
Partial support for native reconcile with packs.
113
        add_commit(repo, 'the_ghost', [])
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
114
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
115
    def checkEmptyReconcile(self, **kwargs):
116
        """Check a reconcile on an empty repository."""
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
117
        self.make_repository('empty')
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
118
        d = bzrlib.bzrdir.BzrDir.open(self.get_url('empty'))
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
119
        # calling on a empty repository should do nothing
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
120
        reconciler = d.find_repository().reconcile(**kwargs)
1570.1.8 by Robert Collins
Only reconcile if doing so will perform gc or correct ancestry.
121
        # no inconsistent parents should have been found
122
        self.assertEqual(0, reconciler.inconsistent_parents)
123
        # and no garbage inventories
124
        self.assertEqual(0, reconciler.garbage_inventories)
125
        # 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
126
        self.checkNoBackupInventory(d)
127
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
128
    def test_reconcile_empty(self):
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
129
        # in an empty repo, theres nothing to do.
130
        self.checkEmptyReconcile()
131
2671.4.2 by Robert Collins
Review feedback.
132
    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``
133
        repo = self.make_repository('repo')
2671.4.2 by Robert Collins
Review feedback.
134
        self.assertNotEqual(None, repo._reconcile_does_inventory_gc)
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
135
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
136
    def test_reconcile_empty_thorough(self):
137
        # reconcile should accept thorough=True
138
        self.checkEmptyReconcile(thorough=True)
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
139
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.
140
    def test_convenience_reconcile_inventory_without_revision_reconcile(self):
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
141
        # 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.
142
        bzrdir_url = self.get_url('inventory_without_revision')
143
        bzrdir = bzrlib.bzrdir.BzrDir.open(bzrdir_url)
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
144
        repo = bzrdir.open_repository()
2671.4.2 by Robert Collins
Review feedback.
145
        if not repo._reconcile_does_inventory_gc:
146
            raise TestSkipped('Irrelevant test')
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
147
        reconcile(bzrdir)
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
148
        # 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.
149
        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.
150
        self.check_missing_was_removed(repo)
151
152
    def test_reweave_inventory_without_revision(self):
153
        # 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.
154
        d_url = self.get_url('inventory_without_revision')
155
        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.
156
        repo = d.open_repository()
2671.4.2 by Robert Collins
Review feedback.
157
        if not repo._reconcile_does_inventory_gc:
158
            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.
159
        self.checkUnreconciled(d, repo.reconcile())
160
        reconciler = repo.reconcile(thorough=True)
161
        # no bad parents
162
        self.assertEqual(0, reconciler.inconsistent_parents)
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
163
        # 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.
164
        self.assertEqual(1, reconciler.garbage_inventories)
165
        self.check_missing_was_removed(repo)
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
166
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
167
    def check_thorough_reweave_missing_revision(self, aBzrDir, reconcile,
168
            **kwargs):
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
169
        # actual low level test.
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
170
        repo = aBzrDir.open_repository()
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
171
        if ([None, 'missing', 'references_missing']
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
172
            != repo.get_ancestry('references_missing')):
173
            # the repo handles ghosts without corruption, so reconcile has
2671.4.3 by Robert Collins
Reformat comment to be more presentable.
174
            # nothing to do here. Specifically, this test has the inventory
175
            # 'missing' present and the revision 'missing' missing, so clearly
176
            # 'missing' cannot be reported in the present ancestry -> missing
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
177
            # 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.
178
            expected_inconsistent_parents = 0
179
        else:
180
            expected_inconsistent_parents = 1
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
181
        reconciler = reconcile(**kwargs)
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
182
        # some number of inconsistent parents should have been found
183
        self.assertEqual(expected_inconsistent_parents,
184
                         reconciler.inconsistent_parents)
1570.1.8 by Robert Collins
Only reconcile if doing so will perform gc or correct ancestry.
185
        # and one garbage inventories
186
        self.assertEqual(1, reconciler.garbage_inventories)
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
187
        # 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
188
        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.
189
        self.check_missing_was_removed(repo)
1570.1.14 by Robert Collins
Enforce repository consistency during 'fetch' operations.
190
        # and the parent list for 'references_missing' should have that
191
        # revision a ghost now.
192
        self.assertEqual([None, 'references_missing'],
193
                         repo.get_ancestry('references_missing'))
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
194
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.
195
    def check_missing_was_removed(self, repo):
2951.1.3 by Robert Collins
Partial support for native reconcile with packs.
196
        if repo._reconcile_backsup_inventory:
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
197
            backed_up = False
198
            for path in repo._transport.list_dir('.'):
199
                if 'inventory.backup' in path:
200
                    backed_up = True
201
            self.assertTrue(backed_up)
202
            # Not clear how to do this at an interface level:
203
            # self.assertTrue('missing' in backup.versions())
204
        self.assertRaises(errors.NoSuchRevision, repo.get_inventory, '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.
205
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
206
    def test_reweave_inventory_without_revision_reconciler(self):
207
        # smoke test for the all in one Reconciler class,
208
        # other tests use the lower level repo.reconcile()
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
209
        d_url = self.get_url('inventory_without_revision_and_ghost')
210
        d = bzrlib.bzrdir.BzrDir.open(d_url)
2671.4.2 by Robert Collins
Review feedback.
211
        if not d.open_repository()._reconcile_does_inventory_gc:
212
            raise TestSkipped('Irrelevant test')
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
213
        def reconcile():
214
            reconciler = Reconciler(d)
215
            reconciler.reconcile()
216
            return reconciler
217
        self.check_thorough_reweave_missing_revision(d, reconcile)
218
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.
219
    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
220
        # actual low level test.
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
221
        d_url = self.get_url('inventory_without_revision_and_ghost')
222
        d = bzrlib.bzrdir.BzrDir.open(d_url)
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
223
        repo = d.open_repository()
2671.4.2 by Robert Collins
Review feedback.
224
        if not repo._reconcile_does_inventory_gc:
225
            raise TestSkipped('Irrelevant test')
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
226
        # nothing should have been altered yet : inventories without
227
        # revisions are not data loss incurring for current format
228
        self.check_thorough_reweave_missing_revision(d, repo.reconcile,
229
            thorough=True)
230
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
231
    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.
232
        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
233
        reconciler = d.open_repository().reconcile(thorough=True)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
234
        # no inconsistent parents should have been found:
1570.1.8 by Robert Collins
Only reconcile if doing so will perform gc or correct ancestry.
235
        # the lack of a parent for ghost is normal
236
        self.assertEqual(0, reconciler.inconsistent_parents)
237
        # and one garbage inventories
238
        self.assertEqual(0, reconciler.garbage_inventories)
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
239
        # now the current inventory should still have 'ghost'
240
        repo = d.open_repository()
241
        repo.get_inventory('ghost')
242
        self.assertEqual([None, 'ghost'], repo.get_ancestry('ghost'))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
243
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
244
    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.
245
        d = bzrlib.bzrdir.BzrDir.open(self.get_url('inventory_ghost_present'))
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
246
        repo = d.open_repository()
1594.2.9 by Robert Collins
Teach Knit repositories how to handle ghosts without corrupting at all.
247
        ghost_ancestry = repo.get_ancestry('ghost')
248
        if ghost_ancestry == [None, 'the_ghost', 'ghost']:
249
            # the repo handles ghosts without corruption, so reconcile has
250
            # nothing to do
251
            return
252
        self.assertEqual([None, 'ghost'], ghost_ancestry)
1594.2.7 by Robert Collins
Add versionedfile.fix_parents api for correcting data post hoc.
253
        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.
254
        # 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.
255
        # one inconsistent parents should have been found : the
256
        # available but not reference parent for ghost.
257
        self.assertEqual(1, reconciler.inconsistent_parents)
258
        # and no garbage inventories
259
        self.assertEqual(0, reconciler.garbage_inventories)
1570.1.2 by Robert Collins
Import bzrtools' 'fix' command as 'bzr reconcile.'
260
        # now the current inventory should still have 'ghost'
261
        repo = d.open_repository()
262
        repo.get_inventory('ghost')
263
        repo.get_inventory('the_ghost')
264
        self.assertEqual([None, 'the_ghost', 'ghost'], repo.get_ancestry('ghost'))
265
        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
266
4385.3.1 by Jelmer Vernooij
Reconcile can now deal with text revisions that originated in revisions that are ghosts.
267
    def test_text_from_ghost_revision(self):
268
        repo = self.make_repository('text-from-ghost')
269
        inv = Inventory(revision_id='final-revid')
270
        inv.root.revision = 'root-revid'
271
        ie = inv.add_path('bla', 'file', 'myfileid')
272
        ie.revision = 'ghostrevid'
273
        ie.text_size = 42
274
        ie.text_sha1 = "bee68c8acd989f5f1765b4660695275948bf5c00"
275
        rev = bzrlib.revision.Revision(timestamp=0,
276
                                       timezone=None,
277
                                       committer="Foo Bar <foo@example.com>",
278
                                       message="Message",
279
                                       revision_id='final-revid')
280
        repo.lock_write()
281
        try:
282
            repo.start_write_group()
283
            try:
284
                repo.add_revision('final-revid', rev, inv)
285
                try:
286
                    repo.texts.add_lines(('myfileid', 'ghostrevid'),
287
                        (('myfileid', 'ghost-text-parent'),),
288
                        ["line1\n", "line2\n"])
289
                except errors.RevisionNotPresent:
290
                    raise TestSkipped("text ghost parents not supported")
291
                if repo.supports_rich_root():
292
                    root_id = inv.root.file_id
293
                    repo.texts.add_lines((inv.root.file_id, inv.root.revision),
294
                        [], [])
295
            finally:
296
                repo.commit_write_group()
297
        finally:
298
            repo.unlock()
299
        repo.reconcile(thorough=True)
300
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
301
302
class TestReconcileWithIncorrectRevisionCache(TestReconcile):
303
    """Ancestry data gets cached in knits and weaves should be reconcilable.
304
305
    This class tests that reconcile can correct invalid caches (such as after
306
    a reconcile).
307
    """
308
309
    def setUp(self):
2018.14.1 by Andrew Bennetts
Update to current hpss branch? Fix lots of test failures.
310
        self.reduceLockdirTimeout()
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
311
        super(TestReconcileWithIncorrectRevisionCache, self).setUp()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
312
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
313
        t = get_transport(self.get_url())
314
        # we need a revision with two parents in the wrong order
315
        # which should trigger reinsertion.
316
        # and another with the first one correct but the other two not
317
        # which should not trigger reinsertion.
318
        # these need to be in different repositories so that we don't
319
        # trigger a reconcile based on the other case.
320
        # there is no api to construct a broken knit repository at
321
        # this point. if we ever encounter a bad graph in a knit repo
322
        # we should add a lower level api to allow constructing such cases.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
323
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
324
        # first off the common logic:
325
        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.
326
        second_tree = self.make_branch_and_tree('reversed-secondary-parents')
327
        for t in [tree, second_tree]:
328
            t.commit('1', rev_id='1')
329
            uncommit(t.branch, tree=t)
330
            t.commit('2', rev_id='2')
331
            uncommit(t.branch, tree=t)
332
            t.commit('3', rev_id='3')
333
            uncommit(t.branch, tree=t)
334
        #second_tree = self.make_branch_and_tree('reversed-secondary-parents')
335
        #second_tree.pull(tree) # XXX won't copy the repo?
336
        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.
337
338
        # now setup the wrong-first parent case
339
        repo = tree.branch.repository
2592.3.38 by Robert Collins
All experimental format tests passing again.
340
        repo.lock_write()
341
        repo.start_write_group()
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
342
        inv = Inventory(revision_id='wrong-first-parent')
343
        inv.root.revision = 'wrong-first-parent'
2592.3.119 by Robert Collins
Merge some test fixes from Martin.
344
        sha1 = repo.add_inventory('wrong-first-parent', inv, ['2', '1'])
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
345
        rev = Revision(timestamp=0,
346
                       timezone=None,
347
                       committer="Foo Bar <foo@example.com>",
348
                       message="Message",
349
                       inventory_sha1=sha1,
350
                       revision_id='wrong-first-parent')
351
        rev.parent_ids = ['1', '2']
352
        repo.add_revision('wrong-first-parent', rev)
2592.3.38 by Robert Collins
All experimental format tests passing again.
353
        repo.commit_write_group()
354
        repo.unlock()
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
355
356
        # now setup the wrong-secondary parent case
357
        repo = repo_secondary
2592.3.38 by Robert Collins
All experimental format tests passing again.
358
        repo.lock_write()
359
        repo.start_write_group()
1910.2.23 by Aaron Bentley
Fix up test cases that manually construct inventories
360
        inv = Inventory(revision_id='wrong-secondary-parent')
361
        inv.root.revision = 'wrong-secondary-parent'
2951.1.6 by Robert Collins
All check/reconcile tests passing now.
362
        if repo.supports_rich_root():
363
            root_id = inv.root.file_id
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
364
            repo.texts.add_lines((root_id, 'wrong-secondary-parent'), [], [])
2592.3.119 by Robert Collins
Merge some test fixes from Martin.
365
        sha1 = repo.add_inventory('wrong-secondary-parent', inv, ['1', '3', '2'])
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
366
        rev = Revision(timestamp=0,
367
                       timezone=None,
368
                       committer="Foo Bar <foo@example.com>",
369
                       message="Message",
370
                       inventory_sha1=sha1,
371
                       revision_id='wrong-secondary-parent')
372
        rev.parent_ids = ['1', '2', '3']
373
        repo.add_revision('wrong-secondary-parent', rev)
2592.3.38 by Robert Collins
All experimental format tests passing again.
374
        repo.commit_write_group()
375
        repo.unlock()
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
376
377
    def test_reconcile_wrong_order(self):
378
        # 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.
379
        t = get_transport(self.get_url()).clone('wrong-first-parent')
380
        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.
381
        repo = d.open_repository()
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
382
        repo.lock_read()
383
        try:
384
            g = repo.get_graph()
385
            if g.get_parent_map(['wrong-first-parent'])['wrong-first-parent'] \
386
                == ('1', '2'):
387
                raise TestSkipped('wrong-first-parent is not setup for testing')
388
        finally:
389
            repo.unlock()
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
390
        self.checkUnreconciled(d, repo.reconcile())
391
        # nothing should have been altered yet : inventories without
392
        # revisions are not data loss incurring for current format
393
        reconciler = repo.reconcile(thorough=True)
394
        # these show up as inconsistent parents
395
        self.assertEqual(1, reconciler.inconsistent_parents)
1692.1.1 by Robert Collins
* Repository.reconcile now takes a thorough keyword parameter to allow
396
        # and no garbage inventories
397
        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.
398
        # and should have been fixed:
3287.6.1 by Robert Collins
* ``VersionedFile.get_graph`` is deprecated, with no replacement method.
399
        repo.lock_read()
400
        self.addCleanup(repo.unlock)
401
        g = repo.get_graph()
402
        self.assertEqual(
403
            {'wrong-first-parent':('1', '2')},
404
            g.get_parent_map(['wrong-first-parent']))
1692.1.2 by Robert Collins
Teach reconcile to check the left-most parent is correct in the revision graph.
405
2671.4.1 by Robert Collins
* Add a new method ``bzrlib.repository.Repository.reconcile_actions``
406
    def test_reconcile_wrong_order_secondary_inventory(self):
407
        # 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.
408
        t = get_transport(self.get_url()).clone('reversed-secondary-parents')
409
        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.
410
        repo = d.open_repository()
411
        self.checkUnreconciled(d, repo.reconcile())
412
        self.checkUnreconciled(d, repo.reconcile(thorough=True))
2745.6.11 by Aaron Bentley
Fix knit file parents to follow parentage from revision/inventory XML
413
2819.2.5 by Andrew Bennetts
Make reconcile abort gracefully if the revision index has bad parents.
414
415
class TestBadRevisionParents(TestCaseWithBrokenRevisionIndex):
416
417
    def test_aborts_if_bad_parents_in_index(self):
418
        """Reconcile refuses to proceed if the revision index is wrong when
419
        checked against the revision texts, so that it does not generate broken
420
        data.
421
422
        Ideally reconcile would fix this, but until we implement that we just
423
        make sure we safely detect this problem.
424
        """
425
        repo = self.make_repo_with_extra_ghost_index()
426
        reconciler = repo.reconcile(thorough=True)
427
        self.assertTrue(reconciler.aborted,
428
            "reconcile should have aborted due to bad parents.")
429
430
    def test_does_not_abort_on_clean_repo(self):
431
        repo = self.make_repository('.')
432
        reconciler = repo.reconcile(thorough=True)
433
        self.assertFalse(reconciler.aborted,
434
            "reconcile should not have aborted on an unbroken repository.")
435
2951.2.8 by Robert Collins
Test that reconciling a repository can be done twice in a row.
436
437
class TestRepeatedReconcile(TestReconcile):
438
439
    def test_trivial_two_reconciles_no_error(self):
440
        tree = self.make_branch_and_tree('.')
441
        tree.commit('first post')
442
        tree.branch.repository.reconcile(thorough=True)
443
        tree.branch.repository.reconcile(thorough=True)