Rev 3860: (mbp, for jelmer) add Foreign base classes in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Nov 27 03:18:43 GMT 2008


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 3860
revision-id: pqm at pqm.ubuntu.com-20081127031840-o1i61l3vf2yin615
parent: pqm at pqm.ubuntu.com-20081127023840-5jizeni4af1cyu8g
parent: jelmer at samba.org-20081125030814-90fce65a9h7ffmmb
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2008-11-27 03:18:40 +0000
message:
  (mbp, for jelmer) add Foreign base classes
added:
  bzrlib/foreign.py              foreign.py-20081112170002-olsxmandkk8qyfuq-1
  bzrlib/tests/test_foreign.py   test_foreign.py-20081125004048-ywb901edgp9lluxo-1
modified:
  bzrlib/log.py                  log.py-20050505065812-c40ce11702fe5fb1
  bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
    ------------------------------------------------------------
    revno: 3830.4.6
    revision-id: jelmer at samba.org-20081125030814-90fce65a9h7ffmmb
    parent: jelmer at samba.org-20081125030514-3f04fj0z1mjyq2e9
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: foreign
    timestamp: Tue 2008-11-25 04:08:14 +0100
    message:
      Remove dpush() implementation for now.
    modified:
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/foreign.py              foreign.py-20081112170002-olsxmandkk8qyfuq-1
    ------------------------------------------------------------
    revno: 3830.4.5
    revision-id: jelmer at samba.org-20081125030514-3f04fj0z1mjyq2e9
    parent: jelmer at samba.org-20081125003753-4v0wwkd66npqzd00
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: foreign
    timestamp: Tue 2008-11-25 04:05:14 +0100
    message:
      add tests for VCS infrastructure classes.
    added:
      bzrlib/tests/test_foreign.py   test_foreign.py-20081125004048-ywb901edgp9lluxo-1
    modified:
      bzrlib/foreign.py              foreign.py-20081112170002-olsxmandkk8qyfuq-1
      bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
    ------------------------------------------------------------
    revno: 3830.4.4
    revision-id: jelmer at samba.org-20081125003753-4v0wwkd66npqzd00
    parent: jelmer at samba.org-20081125002158-jlkj0eknb37w6hh4
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: foreign
    timestamp: Tue 2008-11-25 01:37:53 +0100
    message:
      make inventory_sha1 default to an empty string.
    modified:
      bzrlib/foreign.py              foreign.py-20081112170002-olsxmandkk8qyfuq-1
    ------------------------------------------------------------
    revno: 3830.4.3
    revision-id: jelmer at samba.org-20081125002158-jlkj0eknb37w6hh4
    parent: jelmer at samba.org-20081125002137-6q4s7237x8azx264
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: foreign
    timestamp: Tue 2008-11-25 01:21:58 +0100
    message:
      Register dpush command.
    modified:
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
    ------------------------------------------------------------
    revno: 3830.4.2
    revision-id: jelmer at samba.org-20081125002137-6q4s7237x8azx264
    parent: jelmer at samba.org-20081112170508-csgg471lebld71rl
    parent: pqm at pqm.ubuntu.com-20081121221932-44m8c85k5ri8h5hg
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: foreign
    timestamp: Tue 2008-11-25 01:21:37 +0100
    message:
      Merge bzr.dev
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/__init__.py             __init__.py-20050309040759-33e65acf91bbcd5d
      bzrlib/_readdir_pyx.pyx        readdir.pyx-20060609152855-rm6v321vuaqyh9tu-1
      bzrlib/btree_index.py          index.py-20080624222253-p0x5f92uyh5hw734-7
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/commit.py               commit.py-20050511101309-79ec1a0168e0e825
      bzrlib/fetch.py                fetch.py-20050818234941-26fea6105696365d
      bzrlib/index.py                index.py-20070712131115-lolkarso50vjr64s-1
      bzrlib/knit.py                 knit.py-20051212171256-f056ac8f0fbe1bd9
      bzrlib/lockable_files.py       control_files.py-20051111201905-bb88546e799d669f
      bzrlib/option.py               option.py-20051014052914-661fb36e76e7362f
      bzrlib/plugin.py               plugin.py-20050622060424-829b654519533d69
      bzrlib/plugins/launchpad/account.py account.py-20071011033320-50y6vfftywf4yllw-1
      bzrlib/plugins/launchpad/lp_directory.py lp_indirect.py-20070126012204-de5rugwlt22c7u7e-1
      bzrlib/plugins/launchpad/test_account.py test_account.py-20071011033320-50y6vfftywf4yllw-2
      bzrlib/python-compat.h         pythoncompat.h-20080924041409-9kvi0fgtuuqp743j-1
      bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
      bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
      bzrlib/repofmt/weaverepo.py    presplitout.py-20070125045333-wfav3tsh73oxu3zk-1
      bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
      bzrlib/shelf_ui.py             shelver.py-20081005210102-33worgzwrtdw0yrm-1
      bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
      bzrlib/tests/branch_implementations/test_stacking.py test_stacking.py-20080214020755-msjlkb7urobwly0f-1
      bzrlib/tests/interrepository_implementations/test_fetch.py test_fetch.py-20080425213627-j60cjh782ufm83ry-1
      bzrlib/tests/per_repository/test_write_group.py test_write_group.py-20070716105516-89n34xtogq5frn0m-1
      bzrlib/tests/test_btree_index.py test_index.py-20080624222253-p0x5f92uyh5hw734-13
      bzrlib/tests/test_knit.py      test_knit.py-20051212171302-95d4c00dd5f11f2b
      bzrlib/tests/test_pack_repository.py test_pack_repository-20080801043947-eaw0e6h2gu75kwmy-1
      bzrlib/tests/test_permissions.py test_permissions.py-20051215004520-ccf475789c80e80c
      bzrlib/tests/test_plugins.py   plugins.py-20050622075746-32002b55e5e943e9
      bzrlib/tests/test_remote.py    test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
      bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
      bzrlib/tests/test_revision.py  testrevision.py-20050804210559-46f5e1eb67b01289
      bzrlib/tests/test_shelf_ui.py  test_shelf_ui.py-20081027155203-wtcuazg85wp9u4fv-1
      bzrlib/transport/remote.py     ssh.py-20060608202016-c25gvf1ob7ypbus6-1
      bzrlib/versionedfile.py        versionedfile.py-20060222045106-5039c71ee3b65490
      bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
      bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
    ------------------------------------------------------------
    revno: 3830.4.1
    revision-id: jelmer at samba.org-20081112170508-csgg471lebld71rl
    parent: pqm at pqm.ubuntu.com-20081111045205-junyogmq9uajfg6z
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: foreign
    timestamp: Wed 2008-11-12 18:05:08 +0100
    message:
      Add base classes for foreign branches.
    added:
      bzrlib/foreign.py              foreign.py-20081112170002-olsxmandkk8qyfuq-1
    modified:
      bzrlib/log.py                  log.py-20050505065812-c40ce11702fe5fb1
=== added file 'bzrlib/foreign.py'
--- a/bzrlib/foreign.py	1970-01-01 00:00:00 +0000
+++ b/bzrlib/foreign.py	2008-11-25 03:08:14 +0000
@@ -0,0 +1,176 @@
+# Copyright (C) 2008 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+"""Foreign branch utilities."""
+
+from bzrlib.branch import Branch
+from bzrlib.commands import Command, Option
+from bzrlib.revision import Revision
+from bzrlib.lazy_import import lazy_import
+lazy_import(globals(), """
+from bzrlib import (
+    errors,
+    registry,
+    )
+""")
+
+class VcsMapping(object):
+    """Describes the mapping between the semantics of Bazaar and a foreign vcs.
+
+    """
+    # Whether this is an experimental mapping that is still open to changes.
+    experimental = False
+
+    # Whether this mapping supports exporting and importing all bzr semantics.
+    roundtripping = False
+
+    # Prefix used when importing native foreign revisions (not roundtripped) 
+    # using this mapping.
+    revid_prefix = None
+
+    def revision_id_bzr_to_foreign(self, bzr_revid):
+        """Parse a bzr revision id and convert it to a foreign revid.
+
+        :param bzr_revid: The bzr revision id (a string).
+        :return: A foreign revision id, can be any sort of object.
+        """
+        raise NotImplementedError(self.revision_id_bzr_to_foreign)
+
+    def revision_id_foreign_to_bzr(self, foreign_revid):
+        """Parse a foreign revision id and convert it to a bzr revid.
+
+        :param foreign_revid: Foreign revision id, can be any sort of object.
+        :return: A bzr revision id.
+        """
+        raise NotImplementedError(self.revision_id_foreign_to_bzr)
+
+    def show_foreign_revid(self, foreign_revid):
+        """Prepare a foreign revision id for formatting using bzr log.
+        
+        :param foreign_revid: Foreign revision id.
+        :return: Dictionary mapping string keys to string values.
+        """
+        # TODO: This could be on ForeignVcs instead
+        return { }
+
+
+class VcsMappingRegistry(registry.Registry):
+    """Registry for Bazaar<->foreign VCS mappings.
+    
+    There should be one instance of this registry for every foreign VCS.
+    """
+
+    def register(self, key, factory, help):
+        """Register a mapping between Bazaar and foreign VCS semantics.
+
+        The factory must be a callable that takes one parameter: the key.
+        It must produce an instance of VcsMapping when called.
+        """
+        if ":" in key:
+            raise ValueError("mapping name can not contain colon (:)")
+        registry.Registry.register(self, key, factory, help)
+
+    def set_default(self, key):
+        """Set the 'default' key to be a clone of the supplied key.
+
+        This method must be called once and only once.
+        """
+        self._set_default_key(key)
+
+    def get_default(self):
+        """Convenience function for obtaining the default mapping to use."""
+        return self.get(self._get_default_key())
+
+    def revision_id_bzr_to_foreign(self, revid):
+        """Convert a bzr revision id to a foreign revid."""
+        raise NotImplementedError(self.revision_id_bzr_to_foreign)
+
+
+class ForeignRevision(Revision):
+    """A Revision from a Foreign repository. Remembers 
+    information about foreign revision id and mapping.
+
+    """
+
+    def __init__(self, foreign_revid, mapping, *args, **kwargs):
+        if not "inventory_sha1" in kwargs:
+            kwargs["inventory_sha1"] = ""
+        super(ForeignRevision, self).__init__(*args, **kwargs)
+        self.foreign_revid = foreign_revid
+        self.mapping = mapping
+
+
+def show_foreign_properties(rev):
+    """Custom log displayer for foreign revision identifiers.
+
+    :param rev: Revision object.
+    """
+    # Revision comes directly from a foreign repository
+    if isinstance(rev, ForeignRevision):
+        return rev.mapping.show_foreign_revid(rev.foreign_revid)
+
+    # Revision was once imported from a foreign repository
+    try:
+        foreign_revid, mapping = \
+            foreign_vcs_registry.parse_revision_id(rev.revision_id)
+    except errors.InvalidRevisionId:
+        return {}
+
+    return mapping.show_foreign_revid(foreign_revid)
+
+
+class ForeignVcs(object):
+    """A foreign version control system."""
+
+    def __init__(self, mapping_registry):
+        self.mapping_registry = mapping_registry
+
+
+class ForeignVcsRegistry(registry.Registry):
+    """Registry for Foreign VCSes.
+
+    There should be one entry per foreign VCS. Example entries would be 
+    "git", "svn", "hg", "darcs", etc.
+    
+    """
+
+    def register(self, key, foreign_vcs, help):
+        """Register a foreign VCS.
+
+        :param key: Prefix of the foreign VCS in revision ids
+        :param foreign_vcs: ForeignVCS instance
+        :param help: Description of the foreign VCS
+        """
+        if ":" in key or "-" in key:
+            raise ValueError("vcs name can not contain : or -")
+        registry.Registry.register(self, key, foreign_vcs, help)
+
+    def parse_revision_id(self, revid):
+        """Parse a bzr revision and return the matching mapping and foreign 
+        revid.
+        
+        :param revid: The bzr revision id
+        :return: tuple with foreign revid and vcs mapping
+        """
+        if not "-" in revid:
+            raise errors.InvalidRevisionId(revid, None)
+        try:
+            foreign_vcs = self.get(revid.split("-")[0])
+        except KeyError:
+            raise errors.InvalidRevisionId(revid, None)
+        return foreign_vcs.mapping_registry.revision_id_bzr_to_foreign(revid)
+
+
+foreign_vcs_registry = ForeignVcsRegistry()

=== modified file 'bzrlib/log.py'
--- a/bzrlib/log.py	2008-11-25 08:25:20 +0000
+++ b/bzrlib/log.py	2008-11-27 03:18:40 +0000
@@ -1005,6 +1005,10 @@
 
 
 properties_handler_registry = registry.Registry()
+properties_handler_registry.register_lazy("foreign",
+                                          "bzrlib.foreign",
+                                          "show_foreign_properties")
+
 
 # adapters which revision ids to log are filtered. When log is called, the
 # log_rev_iterator is adapted through each of these factory methods.

=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py	2008-11-15 19:41:37 +0000
+++ b/bzrlib/tests/__init__.py	2008-11-25 03:05:14 +0000
@@ -2805,6 +2805,7 @@
                    'bzrlib.tests.test_extract',
                    'bzrlib.tests.test_fetch',
                    'bzrlib.tests.test_ftp_transport',
+                   'bzrlib.tests.test_foreign',
                    'bzrlib.tests.test_generate_docs',
                    'bzrlib.tests.test_generate_ids',
                    'bzrlib.tests.test_globbing',

=== added file 'bzrlib/tests/test_foreign.py'
--- a/bzrlib/tests/test_foreign.py	1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/test_foreign.py	2008-11-25 03:05:14 +0000
@@ -0,0 +1,120 @@
+# Copyright (C) 2008 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+"""Tests for foreign VCS utility code."""
+
+from bzrlib import errors, foreign
+from bzrlib.revision import Revision
+from bzrlib.tests import TestCase
+
+
+class DummyForeignVcsMapping(foreign.VcsMapping):
+    """A simple mapping for the dummy Foreign VCS, for use with testing."""
+
+    def __eq__(self, other):
+        return type(self) == type(other)
+
+    def show_foreign_revid(self, foreign_revid):
+        return { "dummy ding": "%s/%s\\%s" % foreign_revid }
+
+    def revision_id_bzr_to_foreign(self, bzr_revid):
+        return tuple(bzr_revid[len("dummy-v1:"):].split("-")), self
+
+    def revision_id_foreign_to_bzr(self, foreign_revid):
+        return "dummy-v1:%s-%s-%s" % foreign_revid
+
+
+class DummyForeignVcsMappingRegistry(foreign.VcsMappingRegistry):
+
+    def revision_id_bzr_to_foreign(self, revid):
+        if not revid.startswith("dummy-"):
+            raise errors.InvalidRevisionId(revid, None)
+        mapping_version = revid[len("dummy-"):len("dummy-vx")]
+        mapping = self.get(mapping_version)
+        return mapping.revision_id_bzr_to_foreign(revid)
+
+
+class DummyForeignVcs(foreign.ForeignVcs):
+    """A dummy Foreign VCS, for use with testing.
+    
+    It has revision ids that are a tuple with three strings.
+    """
+
+    def __init__(self):
+        self.mapping_registry = DummyForeignVcsMappingRegistry()
+        self.mapping_registry.register("v1", DummyForeignVcsMapping(), 
+                                       "Version 1")
+
+
+class ForeignVcsRegistryTests(TestCase):
+
+    def test_parse_revision_id_no_dash(self):       
+        reg = foreign.ForeignVcsRegistry()
+        self.assertRaises(errors.InvalidRevisionId, 
+                          reg.parse_revision_id, "invalid")
+        
+    def test_parse_revision_id_unknown_mapping(self):       
+        reg = foreign.ForeignVcsRegistry()
+        self.assertRaises(errors.InvalidRevisionId, 
+                          reg.parse_revision_id, "unknown-foreignrevid")
+
+    def test_parse_revision_id(self):
+        reg = foreign.ForeignVcsRegistry()
+        reg.register("dummy", DummyForeignVcs(), "Dummy VCS")
+        self.assertEquals((("some", "foreign", "revid"), DummyForeignVcsMapping()),
+                          reg.parse_revision_id("dummy-v1:some-foreign-revid"))
+
+
+class ForeignRevisionTests(TestCase):
+    """Tests for the ForeignRevision class."""
+
+    def test_create(self):
+        mapp = DummyForeignVcsMapping()
+        rev = foreign.ForeignRevision(("a", "foreign", "revid"), 
+                                      mapp, "roundtripped-revid")
+        self.assertEquals("", rev.inventory_sha1)
+        self.assertEquals(("a", "foreign", "revid"), rev.foreign_revid)
+        self.assertEquals(mapp, rev.mapping)
+
+
+class ShowForeignPropertiesTests(TestCase):
+    """Tests for the show_foreign_properties() function."""
+
+    def setUp(self):
+        super(ShowForeignPropertiesTests, self).setUp()
+        foreign.foreign_vcs_registry.register("dummy", 
+            DummyForeignVcs(), "Dummy VCS")
+
+    def tearDown(self):
+        super(ShowForeignPropertiesTests, self).tearDown()
+        foreign.foreign_vcs_registry.remove("dummy")
+
+    def test_show_non_foreign(self):
+        """Test use with a native (non-foreign) bzr revision."""
+        self.assertEquals({}, foreign.show_foreign_properties(Revision("arevid")))
+
+    def test_show_imported(self):
+        rev = Revision("dummy-v1:my-foreign-revid")
+        self.assertEquals({ "dummy ding": "my/foreign\\revid" },
+                          foreign.show_foreign_properties(rev))
+
+    def test_show_direct(self):
+        rev = foreign.ForeignRevision(("some", "foreign", "revid"), 
+                                      DummyForeignVcsMapping(), 
+                                      "roundtrip-revid")
+        self.assertEquals({ "dummy ding": "some/foreign\\revid" },
+                          foreign.show_foreign_properties(rev))




More information about the bazaar-commits mailing list