~bzr-pqm/bzr/bzr.dev

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