Rev 1013: Merge 0.4. in file:///data/jelmer/bzr-svn/pyrex/

Jelmer Vernooij jelmer at samba.org
Tue Mar 18 21:52:59 GMT 2008


At file:///data/jelmer/bzr-svn/pyrex/

------------------------------------------------------------
revno: 1013
revision-id:jelmer at samba.org-20080318215258-dcoi7wm4i4bioyoa
parent: jelmer at samba.org-20080318215041-vwt4yqbf90m5lksw
parent: jelmer at samba.org-20080318194550-jea4hwu2jqshsq9c
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: pyrex
timestamp: Tue 2008-03-18 22:52:58 +0100
message:
  Merge 0.4.
modified:
  Makefile                       makefile.other-20080311181537-5svhje3v1flh1n4f-1
  __init__.py                    __init__.py-20051008155114-eae558e6cf149e1d
  branch.py                      svnbranch.py-20051017135706-11c749eb0dab04a7
  errors.py                      errors.py-20061226172623-w1sbj8ynpo0eojqp-1
  fetch.py                       fetch.py-20060625004942-x2lfaib8ra707a8p-1
  tests/test_tree.py             test_tree.py-20070103204350-pr8nupes7e5sd2wr-1
  tree.py                        tree.py-20060624222557-dudlwqcmkf22lt2s-1
    ------------------------------------------------------------
    revno: 950.1.3
    revision-id:jelmer at samba.org-20080318194550-jea4hwu2jqshsq9c
    parent: jelmer at samba.org-20080316041437-dutaq8lj04m44pd5
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: 0.4
    timestamp: Tue 2008-03-18 20:45:50 +0100
    message:
      Cherrypick utility functions for svn:externals support.
    modified:
      branch.py                      svnbranch.py-20051017135706-11c749eb0dab04a7
      errors.py                      errors.py-20061226172623-w1sbj8ynpo0eojqp-1
      fetch.py                       fetch.py-20060625004942-x2lfaib8ra707a8p-1
      tests/test_tree.py             test_tree.py-20070103204350-pr8nupes7e5sd2wr-1
      tree.py                        tree.py-20060624222557-dudlwqcmkf22lt2s-1
    ------------------------------------------------------------
    revno: 950.1.2
    revision-id:jelmer at samba.org-20080316041437-dutaq8lj04m44pd5
    parent: jelmer at samba.org-20080315160050-9h1i4rm171xg4g6d
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: 0.4
    timestamp: Sun 2008-03-16 05:14:37 +0100
    message:
      Mark as only compatible with >= 1.3
    modified:
      __init__.py                    __init__.py-20051008155114-eae558e6cf149e1d
    ------------------------------------------------------------
    revno: 950.1.1
    revision-id:jelmer at samba.org-20080315160050-9h1i4rm171xg4g6d
    parent: jelmer at samba.org-20080312190525-6yyhiqt4f5t1kbhm
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: 0.4
    timestamp: Sat 2008-03-15 17:00:50 +0100
    message:
      Make it easier to run in a debugger.
    modified:
      Makefile                       makefile.other-20080311181537-5svhje3v1flh1n4f-1
=== modified file 'Makefile'
--- a/Makefile	2008-03-18 20:34:11 +0000
+++ b/Makefile	2008-03-18 21:52:58 +0000
@@ -31,7 +31,7 @@
 	ln -sf `pwd` $(TMP_PLUGINS_DIR)/svn
 
 check:: $(TMP_PLUGINS_DIR)/svn
-	LD_LIBRARY_PATH=/usr/local/lib BZR_PLUGIN_PATH=$(TMP_PLUGINS_DIR) $(DEBUGGER) $(PYTHON) $(BZR) selftest $(TEST_OPTIONS) $(TESTS)
+	BZR_PLUGIN_PATH=$(TMP_PLUGINS_DIR) $(DEBUGGER) $(PYTHON) $(BZR) selftest $(TEST_OPTIONS) $(TESTS)
 
 check-verbose::
 	$(MAKE) check TEST_OPTIONS=-v

=== modified file '__init__.py'
--- a/__init__.py	2008-03-14 00:47:07 +0000
+++ b/__init__.py	2008-03-18 21:52:58 +0000
@@ -39,7 +39,7 @@
     version_string = '%d.%d.%d%s%d' % version_info
 __version__ = version_string
 
-COMPATIBLE_BZR_VERSIONS = [(0, 93), (1, 0), (1, 1), (1, 2)]
+COMPATIBLE_BZR_VERSIONS = [(1, 3)]
 
 def check_bzrlib_version(desired):
     """Check that bzrlib is compatible.

=== modified file 'branch.py'
--- a/branch.py	2008-03-18 21:50:41 +0000
+++ b/branch.py	2008-03-18 21:52:58 +0000
@@ -74,6 +74,7 @@
         self._revision_history_revnum = None
         self.mapping = self.repository.get_mapping()
         self._branch_path = branch_path.strip("/")
+        assert isinstance(self._branch_path, str)
         try:
             if self.repository.transport.check_path(branch_path.strip("/"), 
                 self.get_revnum()) != core.NODE_DIR:
@@ -129,11 +130,12 @@
         """
         return BranchCheckResult(self)
 
-    def _create_heavyweight_checkout(self, to_location, revision_id=None):
+    def _create_heavyweight_checkout(self, to_location, revision_id=None, hardlink=False):
         """Create a new heavyweight checkout of this branch.
 
         :param to_location: URL of location to create the new checkout in.
         :param revision_id: Revision that should be the tip of the checkout.
+        :param hardlink: Whether to hardlink
         :return: WorkingTree object of checkout.
         """
         checkout_branch = BzrDir.create_branch_convenience(
@@ -143,7 +145,7 @@
         # pull up to the specified revision_id to set the initial 
         # branch tip correctly, and seed it with history.
         checkout_branch.pull(self, stop_revision=revision_id)
-        return checkout.create_workingtree(revision_id)
+        return checkout.create_workingtree(revision_id, hardlink=hardlink)
 
     def lookup_revision_id(self, revid):
         """Look up the matching Subversion revision number on the mainline of 
@@ -180,12 +182,12 @@
         return wt
 
     def create_checkout(self, to_location, revision_id=None, lightweight=False,
-                        accelerator_tree=None):
+                        accelerator_tree=None, hardlink=False):
         """See Branch.create_checkout()."""
         if lightweight:
             return self._create_lightweight_checkout(to_location, revision_id)
         else:
-            return self._create_heavyweight_checkout(to_location, revision_id)
+            return self._create_heavyweight_checkout(to_location, revision_id, hardlink=hardlink)
 
     def generate_revision_id(self, revnum):
         """Generate a new revision id for a revision on this branch."""
@@ -228,6 +230,13 @@
         last_revid = self.last_revision()
         return self.revision_id_to_revno(last_revid), last_revid
 
+    def get_root_id(self, revnum=None):
+        if revnum is None:
+            tree = self.basis_tree()
+        else:
+            tree = self.repository.revision_tree(self.get_rev_id(revnum))
+        return tree.get_root_id()
+
     def revno(self):
         """See Branch.revno()."""
         return self.last_revision_info()[0]

=== modified file 'errors.py'
--- a/errors.py	2008-03-15 20:33:59 +0000
+++ b/errors.py	2008-03-18 21:52:58 +0000
@@ -24,6 +24,11 @@
 import core
 from bzrlib.plugins.svn import constants
 
+
+class InvalidExternalsDescription(BzrError):
+    _fmt = """Unable to parse externals description."""
+
+
 class NotSvnBranchPath(NotBranchError):
     """Error raised when a path was specified that did not exist."""
     _fmt = """%(path)s is not a valid Subversion branch path. 

=== modified file 'fetch.py'
--- a/fetch.py	2008-03-18 19:33:31 +0000
+++ b/fetch.py	2008-03-18 21:52:58 +0000
@@ -31,10 +31,12 @@
 from mapping import (SVN_PROP_BZR_ANCESTRY, SVN_PROP_BZR_MERGE, 
                      SVN_PROP_BZR_PREFIX, SVN_PROP_BZR_REVISION_INFO, 
                      SVN_PROP_BZR_BRANCHING_SCHEME, SVN_PROP_BZR_REVISION_ID,
-                     SVN_PROP_BZR_FILEIDS, parse_merge_property)
+                     SVN_PROP_BZR_FILEIDS, parse_merge_property,
+                     parse_revision_metadata)
 from repository import (SvnRepository, SvnRepositoryFormat)
 from svk import SVN_PROP_SVK_MERGE
 from delta import apply_txdelta_handler
+from tree import (parse_externals_description, inventory_add_external)
 
 
 def _escape_commit_message(message):
@@ -388,6 +390,8 @@
             pass
         elif name.startswith(constants.PROP_WC_PREFIX):
             pass
+        elif name == constants.PROP_EXTERNALS:
+            mutter('svn:externals property on file!')
         elif (name.startswith(constants.PROP_PREFIX) or
               name.startswith(SVN_PROP_BZR_PREFIX)):
             mutter('unsupported file property %r' % name)

=== modified file 'tests/test_tree.py'
--- a/tests/test_tree.py	2008-03-12 15:01:25 +0000
+++ b/tests/test_tree.py	2008-03-18 19:45:50 +0000
@@ -13,15 +13,20 @@
 # 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
-
 """Basis and revision tree tests."""
 
+from bzrlib.inventory import Inventory, TreeReference
 from bzrlib.osutils import has_symlinks
+from bzrlib.repository import Repository
+from bzrlib.revision import NULL_REVISION
+from bzrlib.tests import TestCase
 from bzrlib.workingtree import WorkingTree
 
-import os, sys
-
-from tree import SvnBasisTree
+import errors
+import os
+from tree import (SvnBasisTree, parse_externals_description, 
+                  inventory_add_external)
+import sys
 from tests import TestCaseWithSubversionRepository
 
 class TestBasisTree(TestCaseWithSubversionRepository):
@@ -91,3 +96,91 @@
         self.assertFalse(tree.inventory[tree.inventory.path2id("file")].executable)
         self.assertFalse(wt.inventory[wt.inventory.path2id("file")].executable)
 
+
+class TestExternalsParser(TestCase):
+    def test_parse_externals(self):
+        self.assertEqual({
+            'third-party/sounds': (None, "http://sounds.red-bean.com/repos"),
+            'third-party/skins': (None, "http://skins.red-bean.com/repositories/skinproj"),
+            'third-party/skins/toolkit': (21, "http://svn.red-bean.com/repos/skin-maker")},
+            parse_externals_description("http://example.com",
+"""third-party/sounds             http://sounds.red-bean.com/repos
+third-party/skins              http://skins.red-bean.com/repositories/skinproj
+third-party/skins/toolkit -r21 http://svn.red-bean.com/repos/skin-maker"""))
+
+    def test_parse_comment(self):
+        self.assertEqual({
+            'third-party/sounds': (None, "http://sounds.red-bean.com/repos")
+                },
+            parse_externals_description("http://example.com/",
+"""
+
+third-party/sounds             http://sounds.red-bean.com/repos
+#third-party/skins              http://skins.red-bean.com/repositories/skinproj
+#third-party/skins/toolkit -r21 http://svn.red-bean.com/repos/skin-maker"""))
+
+    def test_parse_relative(self):
+        self.assertEqual({
+            'third-party/sounds': (None, "http://example.com/branches/other"),
+                },
+            parse_externals_description("http://example.com/trunk",
+"third-party/sounds             ../branches/other"))
+
+    def test_parse_invalid_missing_url(self):
+        """No URL specified."""
+        self.assertRaises(errors.InvalidExternalsDescription, 
+            lambda: parse_externals_description("http://example.com/", "bla"))
+            
+    def test_parse_invalid_too_much_data(self):
+        """No URL specified."""
+        self.assertRaises(errors.InvalidExternalsDescription, 
+            lambda: parse_externals_description(None, "bla -R40 http://bla/"))
+ 
+
+class TestInventoryExternals(TestCaseWithSubversionRepository):
+    def test_add_nested_norev(self):
+        """Add a nested tree with no specific revision referenced."""
+        repos_url = self.make_client('d', 'dc')
+        repos = Repository.open(repos_url)
+        mapping = repos.get_mapping()
+        inv = Inventory(root_id='blabloe')
+        inventory_add_external(inv, 'blabloe', 'blie/bla', 
+                mapping.generate_revision_id(repos.uuid, 1, ""), 
+                None, repos_url)
+        self.assertEqual(TreeReference(
+            mapping.generate_file_id(repos.uuid, 0, "", u""),
+             'bla', inv.path2id('blie'), 
+             revision=mapping.generate_revision_id(repos.uuid, 1, "")), 
+             inv[inv.path2id('blie/bla')])
+
+    def test_add_simple_norev(self):
+        repos_url = self.make_client('d', 'dc')
+        repos = Repository.open(repos_url)
+        mapping = repos.get_mapping()
+        inv = Inventory(root_id='blabloe')
+        inventory_add_external(inv, 'blabloe', 'bla', 
+            mapping.generate_revision_id(repos.uuid, 1, ""), None, 
+            repos_url)
+
+        self.assertEqual(TreeReference(
+            mapping.generate_file_id(repos.uuid, 0, "", u""),
+             'bla', 'blabloe', 
+             revision=mapping.generate_revision_id(repos.uuid, 1, "")), 
+             inv[inv.path2id('bla')])
+
+    def test_add_simple_rev(self):
+        repos_url = self.make_client('d', 'dc')
+        repos = Repository.open(repos_url)
+        inv = Inventory(root_id='blabloe')
+        mapping = repos.get_mapping()
+        inventory_add_external(inv, 'blabloe', 'bla', 
+            mapping.generate_revision_id(repos.uuid, 1, ""), 0, repos_url)
+        expected_ie = TreeReference(mapping.generate_file_id(repos.uuid, 0, "", u""),
+            'bla', 'blabloe', 
+            revision=mapping.generate_revision_id(repos.uuid, 1, ""),
+            reference_revision=NULL_REVISION)
+        ie = inv[inv.path2id('bla')]
+        self.assertEqual(NULL_REVISION, ie.reference_revision)
+        self.assertEqual(mapping.generate_revision_id(repos.uuid, 1, ""), 
+                         ie.revision)
+        self.assertEqual(expected_ie, inv[inv.path2id('bla')])

=== modified file 'tree.py'
--- a/tree.py	2008-03-18 19:33:31 +0000
+++ b/tree.py	2008-03-18 21:52:58 +0000
@@ -15,7 +15,9 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 """Access to stored Subversion basis trees."""
 
-from bzrlib.inventory import Inventory
+from bzrlib import urlutils
+from bzrlib.branch import Branch
+from bzrlib.inventory import Inventory, InventoryDirectory, TreeReference
 
 from bzrlib import osutils, urlutils
 from bzrlib.trace import mutter
@@ -29,6 +31,68 @@
 import constants
 import core, wc
 from delta import apply_txdelta_handler
+import errors
+
+def parse_externals_description(base_url, val):
+    """Parse an svn:externals property value.
+
+    :param base_url: URL on which the property is set. Used for 
+        relative externals.
+
+    :returns: dictionary with local names as keys, (revnum, url)
+              as value. revnum is the revision number and is 
+              set to None if not applicable.
+    """
+    # TODO: Use svn.wc.parse_externals_description3 instead ?
+    ret = {}
+    for l in val.splitlines():
+        if l == "" or l[0] == "#":
+            continue
+        pts = l.rsplit(None, 2) 
+        if len(pts) == 3:
+            if not pts[1].startswith("-r"):
+                raise errors.InvalidExternalsDescription()
+            ret[pts[0]] = (int(pts[1][2:]), urlutils.join(base_url, pts[2]))
+        elif len(pts) == 2:
+            ret[pts[0]] = (None, urlutils.join(base_url, pts[1]))
+        else:
+            raise errors.InvalidExternalsDescription()
+    return ret
+
+
+def inventory_add_external(inv, parent_id, path, revid, ref_revnum, url):
+    """Add an svn:externals entry to an inventory as a tree-reference.
+    
+    :param inv: Inventory to add to.
+    :param parent_id: File id of directory the entry was set on.
+    :param path: Path of the entry, relative to entry with parent_id.
+    :param revid: Revision to store in newly created inventory entries.
+    :param ref_revnum: Referenced revision of tree that's being referenced, or 
+        None if no specific revision is being referenced.
+    :param url: URL of referenced tree.
+    """
+    assert ref_revnum is None or isinstance(ref_revnum, int)
+    assert revid is None or isinstance(revid, str)
+    (dir, name) = os.path.split(path)
+    parent = inv[parent_id]
+    if dir != "":
+        for part in dir.split("/"):
+            if parent.children.has_key(part):
+                parent = parent.children[part]
+            else:
+                # Implicitly add directory if it doesn't exist yet
+                # TODO: Generate a file id
+                parent = inv.add(InventoryDirectory('someid', part, 
+                                 parent_id=parent.file_id))
+                parent.revision = revid
+
+    reference_branch = Branch.open(url)
+    file_id = reference_branch.get_root_id()
+    ie = TreeReference(file_id, name, parent.file_id, revision=revid)
+    if ref_revnum is not None:
+        ie.reference_revision = reference_branch.get_rev_id(ref_revnum)
+    inv.add(ie)
+
 
 class SvnRevisionTree(RevisionTree):
     """A tree that existed in a historical Subversion revision."""
@@ -143,6 +207,8 @@
             self.is_executable = (value != None)
         elif name == constants.PROP_SPECIAL:
             self.is_symlink = (value != None)
+        elif name == svn.core.SVN_PROP_EXTERNALS:
+            mutter('%r property on file!' % name)
         elif name == constants.PROP_ENTRY_COMMITTED_REV:
             self.last_file_rev = int(value)
         elif name in (constants.PROP_ENTRY_COMMITTED_DATE,




More information about the bazaar-commits mailing list