/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_foreign.py

  • Committer: John Arbash Meinel
  • Date: 2009-12-22 16:28:47 UTC
  • mto: This revision was merged to the branch mainline in revision 4922.
  • Revision ID: john@arbash-meinel.com-20091222162847-tvnsc69to4l4uf5r
Implement a permute_for_extension helper.

Use it for all of the 'simple' extension permutations.
It basically permutes all tests in the current module, by setting TestCase.module.
Which works well for most of our extension tests. Some had more advanced
handling of permutations (extra permutations, custom vars, etc.)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2008 Canonical Ltd
 
2
#
 
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.
 
7
#
 
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.
 
12
#
 
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
 
 
18
"""Tests for foreign VCS utility code."""
 
19
 
 
20
 
 
21
from bzrlib import (
 
22
    branch,
 
23
    bzrdir,
 
24
    errors,
 
25
    foreign,
 
26
    lockable_files,
 
27
    lockdir,
 
28
    revision,
 
29
    tests,
 
30
    trace,
 
31
    )
 
32
 
 
33
# This is the dummy foreign revision control system, used 
 
34
# mainly here in the testsuite to test the foreign VCS infrastructure.
 
35
# It is basically standard Bazaar with some minor modifications to 
 
36
# make it "foreign". 
 
37
 
38
# It has the following differences to "regular" Bazaar:
 
39
# - The control directory is named ".dummy", not ".bzr".
 
40
# - The revision ids are tuples, not strings.
 
41
# - Doesn't support more than one parent natively
 
42
 
 
43
 
 
44
class DummyForeignVcsMapping(foreign.VcsMapping):
 
45
    """A simple mapping for the dummy Foreign VCS, for use with testing."""
 
46
 
 
47
    def __eq__(self, other):
 
48
        return type(self) == type(other)
 
49
 
 
50
    def revision_id_bzr_to_foreign(self, bzr_revid):
 
51
        return tuple(bzr_revid[len("dummy-v1:"):].split("-")), self
 
52
 
 
53
    def revision_id_foreign_to_bzr(self, foreign_revid):
 
54
        return "dummy-v1:%s-%s-%s" % foreign_revid
 
55
 
 
56
 
 
57
class DummyForeignVcsMappingRegistry(foreign.VcsMappingRegistry):
 
58
 
 
59
    def revision_id_bzr_to_foreign(self, revid):
 
60
        if not revid.startswith("dummy-"):
 
61
            raise errors.InvalidRevisionId(revid, None)
 
62
        mapping_version = revid[len("dummy-"):len("dummy-vx")]
 
63
        mapping = self.get(mapping_version)
 
64
        return mapping.revision_id_bzr_to_foreign(revid)
 
65
 
 
66
 
 
67
class DummyForeignVcs(foreign.ForeignVcs):
 
68
    """A dummy Foreign VCS, for use with testing.
 
69
 
 
70
    It has revision ids that are a tuple with three strings.
 
71
    """
 
72
 
 
73
    def __init__(self):
 
74
        self.mapping_registry = DummyForeignVcsMappingRegistry()
 
75
        self.mapping_registry.register("v1", DummyForeignVcsMapping(self),
 
76
                                       "Version 1")
 
77
        self.abbreviation = "dummy"
 
78
 
 
79
    def show_foreign_revid(self, foreign_revid):
 
80
        return { "dummy ding": "%s/%s\\%s" % foreign_revid }
 
81
 
 
82
    def serialize_foreign_revid(self, foreign_revid):
 
83
        return "%s|%s|%s" % foreign_revid
 
84
 
 
85
 
 
86
class DummyForeignVcsBranch(branch.BzrBranch6,foreign.ForeignBranch):
 
87
    """A Dummy VCS Branch."""
 
88
 
 
89
    def __init__(self, _format, _control_files, a_bzrdir, *args, **kwargs):
 
90
        self._format = _format
 
91
        self._base = a_bzrdir.transport.base
 
92
        self._ignore_fallbacks = False
 
93
        foreign.ForeignBranch.__init__(self, 
 
94
            DummyForeignVcsMapping(DummyForeignVcs()))
 
95
        branch.BzrBranch6.__init__(self, _format, _control_files, a_bzrdir, 
 
96
            *args, **kwargs)
 
97
 
 
98
 
 
99
class InterToDummyVcsBranch(branch.GenericInterBranch,
 
100
                            foreign.InterToForeignBranch):
 
101
 
 
102
    @staticmethod
 
103
    def is_compatible(source, target):
 
104
        return isinstance(target, DummyForeignVcsBranch)
 
105
 
 
106
    def lossy_push(self, stop_revision=None):
 
107
        result = branch.BranchPushResult()
 
108
        result.source_branch = self.source
 
109
        result.target_branch = self.target
 
110
        result.old_revno, result.old_revid = self.target.last_revision_info()
 
111
        self.source.lock_read()
 
112
        try:
 
113
            # This just handles simple cases, but that's good enough for tests
 
114
            my_history = self.target.revision_history()
 
115
            their_history = self.source.revision_history()
 
116
            if their_history[:min(len(my_history), len(their_history))] != my_history:
 
117
                raise errors.DivergedBranches(self.target, self.source)
 
118
            todo = their_history[len(my_history):]
 
119
            revidmap = {}
 
120
            for revid in todo:
 
121
                rev = self.source.repository.get_revision(revid)
 
122
                tree = self.source.repository.revision_tree(revid)
 
123
                def get_file_with_stat(file_id, path=None):
 
124
                    return (tree.get_file(file_id), None)
 
125
                tree.get_file_with_stat = get_file_with_stat
 
126
                new_revid = self.target.mapping.revision_id_foreign_to_bzr(
 
127
                    (str(rev.timestamp), str(rev.timezone), 
 
128
                        str(self.target.revno())))
 
129
                parent_revno, parent_revid= self.target.last_revision_info()
 
130
                if parent_revid == revision.NULL_REVISION:
 
131
                    parent_revids = []
 
132
                else:
 
133
                    parent_revids = [parent_revid]
 
134
                builder = self.target.get_commit_builder(parent_revids, 
 
135
                        self.target.get_config(), rev.timestamp,
 
136
                        rev.timezone, rev.committer, rev.properties,
 
137
                        new_revid)
 
138
                try:
 
139
                    for path, ie in tree.inventory.iter_entries():
 
140
                        new_ie = ie.copy()
 
141
                        new_ie.revision = None
 
142
                        builder.record_entry_contents(new_ie, 
 
143
                            [self.target.repository.revision_tree(parent_revid).inventory],
 
144
                            path, tree, 
 
145
                            (ie.kind, ie.text_size, ie.executable, ie.text_sha1))
 
146
                    builder.finish_inventory()
 
147
                except:
 
148
                    builder.abort()
 
149
                    raise
 
150
                revidmap[revid] = builder.commit(rev.message)
 
151
                self.target.set_last_revision_info(parent_revno+1, 
 
152
                    revidmap[revid])
 
153
                trace.mutter('lossily pushed revision %s -> %s', 
 
154
                    revid, revidmap[revid])
 
155
        finally:
 
156
            self.source.unlock()
 
157
        result.new_revno, result.new_revid = self.target.last_revision_info()
 
158
        result.revidmap = revidmap
 
159
        return result
 
160
 
 
161
 
 
162
class DummyForeignVcsBranchFormat(branch.BzrBranchFormat6):
 
163
 
 
164
    def get_format_string(self):
 
165
        return "Branch for Testing"
 
166
 
 
167
    def __init__(self):
 
168
        super(DummyForeignVcsBranchFormat, self).__init__()
 
169
        self._matchingbzrdir = DummyForeignVcsDirFormat()
 
170
 
 
171
    def open(self, a_bzrdir, _found=False):
 
172
        if not _found:
 
173
            raise NotImplementedError
 
174
        try:
 
175
            transport = a_bzrdir.get_branch_transport(None)
 
176
            control_files = lockable_files.LockableFiles(transport, 'lock',
 
177
                                                         lockdir.LockDir)
 
178
            return DummyForeignVcsBranch(_format=self,
 
179
                              _control_files=control_files,
 
180
                              a_bzrdir=a_bzrdir,
 
181
                              _repository=a_bzrdir.find_repository())
 
182
        except errors.NoSuchFile:
 
183
            raise errors.NotBranchError(path=transport.base)
 
184
 
 
185
 
 
186
class DummyForeignVcsDirFormat(bzrdir.BzrDirMetaFormat1):
 
187
    """BzrDirFormat for the dummy foreign VCS."""
 
188
 
 
189
    @classmethod
 
190
    def get_format_string(cls):
 
191
        return "A Dummy VCS Dir"
 
192
 
 
193
    @classmethod
 
194
    def get_format_description(cls):
 
195
        return "A Dummy VCS Dir"
 
196
 
 
197
    @classmethod
 
198
    def is_supported(cls):
 
199
        return True
 
200
 
 
201
    def get_branch_format(self):
 
202
        return DummyForeignVcsBranchFormat()
 
203
 
 
204
    @classmethod
 
205
    def probe_transport(klass, transport):
 
206
        """Return the .bzrdir style format present in a directory."""
 
207
        if not transport.has('.dummy'):
 
208
            raise errors.NotBranchError(path=transport.base)
 
209
        return klass()
 
210
 
 
211
    def initialize_on_transport(self, transport):
 
212
        """Initialize a new bzrdir in the base directory of a Transport."""
 
213
        # Since we don't have a .bzr directory, inherit the
 
214
        # mode from the root directory
 
215
        temp_control = lockable_files.LockableFiles(transport,
 
216
                            '', lockable_files.TransportLock)
 
217
        temp_control._transport.mkdir('.dummy',
 
218
                                      # FIXME: RBC 20060121 don't peek under
 
219
                                      # the covers
 
220
                                      mode=temp_control._dir_mode)
 
221
        del temp_control
 
222
        bzrdir_transport = transport.clone('.dummy')
 
223
        # NB: no need to escape relative paths that are url safe.
 
224
        control_files = lockable_files.LockableFiles(bzrdir_transport,
 
225
            self._lock_file_name, self._lock_class)
 
226
        control_files.create_lock()
 
227
        return self.open(transport, _found=True)
 
228
 
 
229
    def _open(self, transport):
 
230
        return DummyForeignVcsDir(transport, self)
 
231
 
 
232
 
 
233
class DummyForeignVcsDir(bzrdir.BzrDirMeta1):
 
234
 
 
235
    def __init__(self, _transport, _format):
 
236
        self._format = _format
 
237
        self.transport = _transport.clone('.dummy')
 
238
        self.root_transport = _transport
 
239
        self._mode_check_done = False
 
240
        self._control_files = lockable_files.LockableFiles(self.transport,
 
241
            "lock", lockable_files.TransportLock)
 
242
 
 
243
    def open_branch(self, ignore_fallbacks=True):
 
244
        return self._format.get_branch_format().open(self, _found=True)
 
245
 
 
246
    def cloning_metadir(self, stacked=False):
 
247
        """Produce a metadir suitable for cloning with."""
 
248
        return bzrdir.format_registry.make_bzrdir("default")
 
249
 
 
250
    def sprout(self, url, revision_id=None, force_new_repo=False,
 
251
               recurse='down', possible_transports=None,
 
252
               accelerator_tree=None, hardlink=False, stacked=False,
 
253
               source_branch=None):
 
254
        # dirstate doesn't cope with accelerator_trees well 
 
255
        # that have a different control dir
 
256
        return super(DummyForeignVcsDir, self).sprout(url=url, 
 
257
                revision_id=revision_id, force_new_repo=force_new_repo, 
 
258
                recurse=recurse, possible_transports=possible_transports, 
 
259
                hardlink=hardlink, stacked=stacked, source_branch=source_branch)
 
260
 
 
261
 
 
262
def register_dummy_foreign_for_test(testcase):
 
263
    bzrdir.BzrDirFormat.register_control_format(DummyForeignVcsDirFormat)
 
264
    testcase.addCleanup(bzrdir.BzrDirFormat.unregister_control_format,
 
265
                        DummyForeignVcsDirFormat)
 
266
    # We need to register the optimiser to make the dummy appears really
 
267
    # different from a regular bzr repository.
 
268
    branch.InterBranch.register_optimiser(InterToDummyVcsBranch)
 
269
    testcase.addCleanup(branch.InterBranch.unregister_optimiser,
 
270
                        InterToDummyVcsBranch)
 
271
 
 
272
 
 
273
class ForeignVcsRegistryTests(tests.TestCase):
 
274
    """Tests for the ForeignVcsRegistry class."""
 
275
 
 
276
    def test_parse_revision_id_no_dash(self):
 
277
        reg = foreign.ForeignVcsRegistry()
 
278
        self.assertRaises(errors.InvalidRevisionId,
 
279
                          reg.parse_revision_id, "invalid")
 
280
 
 
281
    def test_parse_revision_id_unknown_mapping(self):
 
282
        reg = foreign.ForeignVcsRegistry()
 
283
        self.assertRaises(errors.InvalidRevisionId,
 
284
                          reg.parse_revision_id, "unknown-foreignrevid")
 
285
 
 
286
    def test_parse_revision_id(self):
 
287
        reg = foreign.ForeignVcsRegistry()
 
288
        vcs = DummyForeignVcs()
 
289
        reg.register("dummy", vcs, "Dummy VCS")
 
290
        self.assertEquals((("some", "foreign", "revid"), DummyForeignVcsMapping(vcs)),
 
291
                          reg.parse_revision_id("dummy-v1:some-foreign-revid"))
 
292
 
 
293
 
 
294
class ForeignRevisionTests(tests.TestCase):
 
295
    """Tests for the ForeignRevision class."""
 
296
 
 
297
    def test_create(self):
 
298
        mapp = DummyForeignVcsMapping(DummyForeignVcs())
 
299
        rev = foreign.ForeignRevision(("a", "foreign", "revid"),
 
300
                                      mapp, "roundtripped-revid")
 
301
        self.assertEquals("", rev.inventory_sha1)
 
302
        self.assertEquals(("a", "foreign", "revid"), rev.foreign_revid)
 
303
        self.assertEquals(mapp, rev.mapping)
 
304
 
 
305
 
 
306
class WorkingTreeFileUpdateTests(tests.TestCaseWithTransport):
 
307
    """Tests for update_workingtree_fileids()."""
 
308
 
 
309
    def test_update_workingtree(self):
 
310
        wt = self.make_branch_and_tree('br1')
 
311
        self.build_tree_contents([('br1/bla', 'original contents\n')])
 
312
        wt.add('bla', 'bla-a')
 
313
        wt.commit('bla-a')
 
314
        root_id = wt.get_root_id()
 
315
        target = wt.bzrdir.sprout('br2').open_workingtree()
 
316
        target.unversion(['bla-a'])
 
317
        target.add('bla', 'bla-b')
 
318
        target.commit('bla-b')
 
319
        target_basis = target.basis_tree()
 
320
        target_basis.lock_read()
 
321
        self.addCleanup(target_basis.unlock)
 
322
        foreign.update_workingtree_fileids(wt, target_basis)
 
323
        wt.lock_read()
 
324
        try:
 
325
            self.assertEquals(set([root_id, "bla-b"]), set(wt.inventory))
 
326
        finally:
 
327
            wt.unlock()
 
328
 
 
329
 
 
330
class DummyForeignVcsTests(tests.TestCaseWithTransport):
 
331
    """Very basic test for DummyForeignVcs."""
 
332
 
 
333
    def setUp(self):
 
334
        super(DummyForeignVcsTests, self).setUp()
 
335
        register_dummy_foreign_for_test(self)
 
336
 
 
337
    def test_create(self):
 
338
        """Test we can create dummies."""
 
339
        self.make_branch_and_tree("d", format=DummyForeignVcsDirFormat())
 
340
        dir = bzrdir.BzrDir.open("d")
 
341
        self.assertEquals("A Dummy VCS Dir", dir._format.get_format_string())
 
342
        dir.open_repository()
 
343
        dir.open_branch()
 
344
        dir.open_workingtree()
 
345
 
 
346
    def test_sprout(self):
 
347
        """Test we can clone dummies and that the format is not preserved."""
 
348
        self.make_branch_and_tree("d", format=DummyForeignVcsDirFormat())
 
349
        dir = bzrdir.BzrDir.open("d")
 
350
        newdir = dir.sprout("e")
 
351
        self.assertNotEquals("A Dummy VCS Dir",
 
352
                             newdir._format.get_format_string())
 
353
 
 
354
    def test_lossy_push_empty(self):
 
355
        source_tree = self.make_branch_and_tree("source")
 
356
        target_tree = self.make_branch_and_tree("target", 
 
357
            format=DummyForeignVcsDirFormat())
 
358
        pushresult = source_tree.branch.lossy_push(target_tree.branch)
 
359
        self.assertEquals(revision.NULL_REVISION, pushresult.old_revid)
 
360
        self.assertEquals(revision.NULL_REVISION, pushresult.new_revid)
 
361
        self.assertEquals({}, pushresult.revidmap)
 
362
 
 
363
    def test_lossy_push_simple(self):
 
364
        source_tree = self.make_branch_and_tree("source")
 
365
        self.build_tree(['source/a', 'source/b'])
 
366
        source_tree.add(['a', 'b'])
 
367
        revid1 = source_tree.commit("msg")
 
368
        target_tree = self.make_branch_and_tree("target", 
 
369
            format=DummyForeignVcsDirFormat())
 
370
        target_tree.branch.lock_write()
 
371
        try:
 
372
            pushresult = source_tree.branch.lossy_push(target_tree.branch)
 
373
        finally:
 
374
            target_tree.branch.unlock()
 
375
        self.assertEquals(revision.NULL_REVISION, pushresult.old_revid)
 
376
        self.assertEquals({revid1:target_tree.branch.last_revision()}, 
 
377
                           pushresult.revidmap)
 
378
        self.assertEquals(pushresult.revidmap[revid1], pushresult.new_revid)