/brz/remove-bazaar

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