Rev 950: Merge 0.4. in file:///data/jelmer/bzr-svn/revisionloader/

Jelmer Vernooij jelmer at samba.org
Tue Mar 18 19:54:31 GMT 2008


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

------------------------------------------------------------
revno: 950
revision-id:jelmer at samba.org-20080318195429-npub72gcqzs6xqfb
parent: jelmer at samba.org-20080312184954-ayb1gi3yjtqyjoez
parent: jelmer at samba.org-20080318194550-jea4hwu2jqshsq9c
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: revisionloader
timestamp: Tue 2008-03-18 20:54:29 +0100
message:
  Merge 0.4.
modified:
  Makefile                       makefile.other-20080311181537-5svhje3v1flh1n4f-1
  NEWS                           news-20061231030336-h9fhq245ie0de8bs-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: 948.1.5
    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: 948.1.4
    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: 948.1.3
    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
    ------------------------------------------------------------
    revno: 948.1.2
    revision-id:jelmer at samba.org-20080312190525-6yyhiqt4f5t1kbhm
    parent: jelmer at samba.org-20080312190508-qu9ahy02tzjogea6
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: 0.4
    timestamp: Wed 2008-03-12 20:05:25 +0100
    message:
      Deal with newer versions of bzr passing in unicode strings.
    modified:
      __init__.py                    __init__.py-20051008155114-eae558e6cf149e1d
    ------------------------------------------------------------
    revno: 948.1.1
    revision-id:jelmer at samba.org-20080312190508-qu9ahy02tzjogea6
    parent: jelmer at samba.org-20080312150357-87y32kta69anlqjg
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: 0.4
    timestamp: Wed 2008-03-12 20:05:08 +0100
    message:
      Add bug #
    modified:
      NEWS                           news-20061231030336-h9fhq245ie0de8bs-1
=== modified file 'Makefile'
--- a/Makefile	2008-03-11 18:16:09 +0000
+++ b/Makefile	2008-03-15 16:00:50 +0000
@@ -1,14 +1,20 @@
-BZR ?= bzr
+DEBUGGER ?= 
+BZR ?= $(shell which bzr)
+PYTHON ?= $(shell which python)
 SETUP ?= ./setup.py
 PYDOCTOR ?= pydoctor
-CTAGS = ?= ctags
+CTAGS ?= ctags
 PYLINT ?= pylint
+TESTS ?= svn
 
 all:: build
 
 build::
 	$(SETUP) build
 
+build-inplace::
+	$(SETUP) build_ext --inplace
+
 install::
 	$(SETUP) install
 
@@ -20,11 +26,11 @@
 $(TMP_PLUGINS_DIR):
 	mkdir -p $@
 
-$(TMP_PLUGINS_DIR)/svn: $(TMP_PLUGINS_DIR)
+$(TMP_PLUGINS_DIR)/svn: build-inplace $(TMP_PLUGINS_DIR)
 	ln -sf `pwd` $(TMP_PLUGINS_DIR)/svn
 
 check:: $(TMP_PLUGINS_DIR)/svn
-	BZR_PLUGIN_PATH=$(TMP_PLUGINS_DIR) $(BZR) selftest $(TEST_OPTIONS) svn
+	BZR_PLUGIN_PATH=$(TMP_PLUGINS_DIR) $(DEBUGGER) $(PYTHON) $(BZR) selftest $(TEST_OPTIONS) $(TESTS)
 
 check-verbose::
 	$(MAKE) check TEST_OPTIONS=-v
@@ -32,6 +38,9 @@
 check-one::
 	$(MAKE) check TEST_OPTIONS=--one
 
+show-plugins::
+	BZR_PLUGIN_PATH=$(TMP_PLUGINS_DIR) $(BZR) plugins
+
 lint::
 	$(PYLINT) -f parseable *.py */*.py
 

=== modified file 'NEWS'
--- a/NEWS	2008-03-12 15:03:57 +0000
+++ b/NEWS	2008-03-12 19:05:08 +0000
@@ -18,7 +18,7 @@
 
   BUG FIXES
 
-   * Fix compatibility with Bazaar 1.2.
+   * Fix compatibility with Bazaar 1.2. (#196002)
 
    * Don't provide find_repository() implementation. (#193814)
 

=== modified file '__init__.py'
--- a/__init__.py	2008-03-12 15:01:25 +0000
+++ b/__init__.py	2008-03-16 04:14:37 +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.
@@ -143,6 +143,8 @@
     
     :param schemename: Name of the scheme to retrieve.
     """
+    if isinstance(schemename, unicode):
+        schemename = schemename.encode("ascii")
     from scheme import BranchingScheme
     from bzrlib.errors import BzrCommandError
     

=== modified file 'branch.py'
--- a/branch.py	2008-02-04 03:21:32 +0000
+++ b/branch.py	2008-03-18 19:45:50 +0000
@@ -73,6 +73,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()) != svn.core.svn_node_dir:
@@ -128,11 +129,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(
@@ -142,7 +144,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 
@@ -183,12 +185,12 @@
         return WorkingTree.open(to_location)
 
     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."""
@@ -231,6 +233,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-12 15:01:25 +0000
+++ b/errors.py	2008-03-18 19:45:50 +0000
@@ -23,6 +23,11 @@
 import urllib
 import svn.core
 
+
+class InvalidExternalsDescription(BzrError):
+    _fmt = """Unable to parse externals description."""
+
+
 # APR define, not in svn.core
 SVN_ERR_UNKNOWN_HOSTNAME = 670002
 

=== modified file 'fetch.py'
--- a/fetch.py	2008-03-12 18:49:54 +0000
+++ b/fetch.py	2008-03-18 19:54:29 +0000
@@ -32,10 +32,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 tree import apply_txdelta_handler
+from tree import (apply_txdelta_handler, parse_externals_description, 
+                  inventory_add_external)
 
 
 def _escape_commit_message(message):
@@ -301,6 +303,8 @@
             self.is_symlink = (value != None)
         elif name == svn.core.SVN_PROP_ENTRY_COMMITTED_REV:
             self.last_file_rev = int(value)
+        elif name == svn.core.SVN_PROP_EXTERNALS:
+            mutter('svn:externals property on file!')
         elif name in (svn.core.SVN_PROP_ENTRY_COMMITTED_DATE,
                       svn.core.SVN_PROP_ENTRY_LAST_AUTHOR,
                       svn.core.SVN_PROP_ENTRY_LOCK_TOKEN,

=== 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-02-03 03:08:33 +0000
+++ b/tree.py	2008-03-18 19:45:50 +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,69 @@
 import svn.core, svn.wc, svn.delta
 from svn.core import Pool
 
+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)
+
+
 # Deal with Subversion 1.5 and the patched Subversion 1.4 (which are 
 # slightly different).
 
@@ -148,6 +213,8 @@
             self.is_executable = (value != None)
         elif name == svn.core.SVN_PROP_SPECIAL:
             self.is_symlink = (value != None)
+        elif name == svn.core.SVN_PROP_EXTERNALS:
+            mutter('%r property on file!' % name)
         elif name == svn.core.SVN_PROP_ENTRY_COMMITTED_REV:
             self.last_file_rev = int(value)
         elif name in (svn.core.SVN_PROP_ENTRY_COMMITTED_DATE,




More information about the bazaar-commits mailing list