1
# Copyright (C) 2006 by Canonical Ltd
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.
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.
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
17
"""Tests for reconiliation of repositories."""
21
import bzrlib.errors as errors
22
from bzrlib.reconcile import reconcile, Reconciler, RepoReconciler
23
from bzrlib.revision import Revision
24
from bzrlib.tests.repository_implementations.test_repository import TestCaseWithRepository
25
from bzrlib.transport import get_transport
26
from bzrlib.tree import EmptyTree
27
from bzrlib.workingtree import WorkingTree
30
class TestsNeedingReweave(TestCaseWithRepository):
33
super(TestsNeedingReweave, self).setUp()
35
t = get_transport(self.get_url())
36
# an empty inventory with no revision for testing with.
37
# this is referenced by 'references_missing' to let us test
38
# that all the cached data is correctly converted into ghost links
39
# and the referenced inventory still cleaned.
40
repo = self.make_repository('inventory_without_revision')
41
inv = EmptyTree().inventory
42
repo.add_inventory('missing', inv, [])
43
sha1 = repo.add_inventory('references_missing', inv, ['missing'])
44
rev = Revision(timestamp=0,
46
committer="Foo Bar <foo@example.com>",
49
revision_id='references_missing')
50
rev.parent_ids = ['missing']
51
repo.add_revision('references_missing', rev)
53
# a inventory with no parents and the revision has parents..
55
repo = self.make_repository('inventory_one_ghost')
56
sha1 = repo.add_inventory('ghost', inv, [])
57
rev = Revision(timestamp=0,
59
committer="Foo Bar <foo@example.com>",
63
rev.parent_ids = ['the_ghost']
64
repo.add_revision('ghost', rev)
66
# a inventory with a ghost that can be corrected now.
67
t.copy_tree('inventory_one_ghost', 'inventory_ghost_present')
68
repo = bzrlib.repository.Repository.open('inventory_ghost_present')
69
sha1 = repo.add_inventory('the_ghost', inv, [])
70
rev = Revision(timestamp=0,
72
committer="Foo Bar <foo@example.com>",
75
revision_id='the_ghost')
77
repo.add_revision('the_ghost', rev)
79
def test_reweave_empty(self):
80
self.make_repository('empty')
81
d = bzrlib.bzrdir.BzrDir.open('empty')
82
# calling on a empty repository should do nothing
83
reconciler = RepoReconciler(d.find_repository())
84
reconciler.reconcile()
85
# no inconsistent parents should have been found
86
self.assertEqual(0, reconciler.inconsistent_parents)
87
# and no garbage inventories
88
self.assertEqual(0, reconciler.garbage_inventories)
89
# and no backup weave should have been needed/made.
90
repo = d.open_repository()
91
self.assertRaises(errors.NoSuchFile,
92
repo.control_weaves.get_weave,
94
repo.get_transaction())
96
def test_reweave_inventory_without_revision_reconcile(self):
97
# smoke test for the all in one ui tool
98
d = bzrlib.bzrdir.BzrDir.open('inventory_without_revision')
100
# now the backup should have it but not the current inventory
101
repo = d.open_repository()
102
backup = repo.control_weaves.get_weave('inventory.backup',
103
repo.get_transaction())
104
self.assertTrue('missing' in backup.versions())
105
self.assertRaises(errors.RevisionNotPresent,
106
repo.get_inventory, 'missing')
108
def test_reweave_inventory_without_revision_reconciler(self):
109
# smoke test for the all in one Reconciler class,
110
# other tests use the lower level RepoReconciler.
111
d = bzrlib.bzrdir.BzrDir.open('inventory_without_revision')
112
reconciler = Reconciler(d)
113
reconciler.reconcile()
114
# no inconsistent parents should have been found
115
self.assertEqual(1, reconciler.inconsistent_parents)
116
# and one garbage inventories
117
self.assertEqual(1, reconciler.garbage_inventories)
118
# now the backup should have it but not the current inventory
119
repo = d.open_repository()
120
backup = repo.control_weaves.get_weave('inventory.backup',
121
repo.get_transaction())
122
self.assertTrue('missing' in backup.versions())
123
self.assertRaises(errors.RevisionNotPresent,
124
repo.get_inventory, 'missing')
126
def test_reweave_inventory_without_revision(self):
127
# actual low level test.
128
d = bzrlib.bzrdir.BzrDir.open('inventory_without_revision')
129
reconciler = RepoReconciler(d.open_repository())
130
reconciler.reconcile()
131
# no inconsistent parents should have been found
132
self.assertEqual(1, reconciler.inconsistent_parents)
133
# and one garbage inventories
134
self.assertEqual(1, reconciler.garbage_inventories)
135
# now the backup should have it but not the current inventory
136
repo = d.open_repository()
137
backup = repo.control_weaves.get_weave('inventory.backup',
138
repo.get_transaction())
139
self.assertTrue('missing' in backup.versions())
140
self.assertRaises(errors.RevisionNotPresent,
141
repo.get_inventory, 'missing')
142
# and the parent list for 'references_missing' should have that
143
# revision a ghost now.
144
self.assertEqual([None, 'references_missing'],
145
repo.get_ancestry('references_missing'))
147
def test_reweave_inventory_preserves_a_revision_with_ghosts(self):
148
d = bzrlib.bzrdir.BzrDir.open('inventory_one_ghost')
149
reconciler = RepoReconciler(d.open_repository())
150
reconciler.reconcile()
151
# no inconsistent parents should have been found:
152
# the lack of a parent for ghost is normal
153
self.assertEqual(0, reconciler.inconsistent_parents)
154
# and one garbage inventories
155
self.assertEqual(0, reconciler.garbage_inventories)
156
# now the current inventory should still have 'ghost'
157
repo = d.open_repository()
158
repo.get_inventory('ghost')
159
self.assertEqual([None, 'ghost'], repo.get_ancestry('ghost'))
161
def test_reweave_inventory_fixes_ancestryfor_a_present_ghost(self):
162
d = bzrlib.bzrdir.BzrDir.open('inventory_ghost_present')
163
repo = d.open_repository()
164
self.assertEqual([None, 'ghost'], repo.get_ancestry('ghost'))
165
reconciler = RepoReconciler(repo)
166
reconciler.reconcile()
167
# one inconsistent parents should have been found : the
168
# available but not reference parent for ghost.
169
self.assertEqual(1, reconciler.inconsistent_parents)
170
# and no garbage inventories
171
self.assertEqual(0, reconciler.garbage_inventories)
172
# now the current inventory should still have 'ghost'
173
repo = d.open_repository()
174
repo.get_inventory('ghost')
175
repo.get_inventory('the_ghost')
176
self.assertEqual([None, 'the_ghost', 'ghost'], repo.get_ancestry('ghost'))
177
self.assertEqual([None, 'the_ghost'], repo.get_ancestry('the_ghost'))