Merge 0.4.
[jelmer/subvertpy.git] / tree.py
diff --git a/tree.py b/tree.py
index 5960b55b638f1d93d49a210a203862f4d42cc60a..30edf1433b40c03e8550d0b24fbd8ca11d3f7658 100644 (file)
--- a/tree.py
+++ b/tree.py
@@ -1,8 +1,8 @@
-# Copyright (C) 2005-2006 Jelmer Vernooij <jelmer@samba.org>
+# Copyright (C) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
 
 # 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
+# the Free Software Foundation; either version 3 of the License, or
 # (at your option) any later version.
 
 # This program is distributed in the hope that it will be useful,
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 """Access to stored Subversion basis trees."""
 
-from bzrlib import urlutils
+from bzrlib import osutils, urlutils
 from bzrlib.branch import Branch
 from bzrlib.inventory import Inventory, InventoryDirectory, TreeReference
 
-from bzrlib import osutils, urlutils
+from bzrlib.revision import CURRENT_REVISION
 from bzrlib.trace import mutter
 from bzrlib.revisiontree import RevisionTree
 
@@ -28,10 +28,8 @@ import md5
 from cStringIO import StringIO
 import urllib
 
-import constants
-import core, wc
-from delta import apply_txdelta_handler
-import errors
+from bzrlib.plugins.svn.delta import apply_txdelta_handler
+from bzrlib.plugins.svn import core, errors, properties, wc
 
 def parse_externals_description(base_url, val):
     """Parse an svn:externals property value.
@@ -43,7 +41,6 @@ def parse_externals_description(base_url, val):
               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] == "#":
@@ -54,6 +51,10 @@ def parse_externals_description(base_url, val):
                 raise errors.InvalidExternalsDescription()
             ret[pts[0]] = (int(pts[1][2:]), urlutils.join(base_url, pts[2]))
         elif len(pts) == 2:
+            if pts[1].startswith("//"):
+                raise NotImplementedError("Relative to the scheme externals not yet supported")
+            if pts[1].startswith("^/"):
+                raise NotImplementedError("Relative to the repository root externals not yet supported")
             ret[pts[0]] = (None, urlutils.join(base_url, pts[1]))
         else:
             raise errors.InvalidExternalsDescription()
@@ -106,11 +107,15 @@ class SvnRevisionTree(RevisionTree):
         editor = TreeBuildEditor(self)
         self.file_data = {}
         root_repos = repository.transport.get_svn_repos_root()
-        reporter = repository.transport.do_switch(
-                self.revnum, True, 
+        conn = repository.transport.get_connection()
+        reporter = conn.do_switch(
+                self.revnum, "", True, 
                 urlutils.join(root_repos, self.branch_path), editor)
-        reporter.set_path("", 0, True)
-        reporter.finish()
+        try:
+            reporter.set_path("", 0, True)
+            reporter.finish()
+        finally:
+            repository.transport.add_connection(conn)
 
     def get_file_lines(self, file_id):
         return osutils.split_lines(self.file_data[file_id])
@@ -152,37 +157,18 @@ class DirectoryTreeEditor:
         return DirectoryTreeEditor(self.tree, file_id)
 
     def change_prop(self, name, value):
-        from mapping import (SVN_PROP_BZR_ANCESTRY, 
-                        SVN_PROP_BZR_PREFIX, SVN_PROP_BZR_REVISION_INFO, 
-                        SVN_PROP_BZR_FILEIDS, SVN_PROP_BZR_REVISION_ID,
-                        SVN_PROP_BZR_BRANCHING_SCHEME, SVN_PROP_BZR_MERGE)
-
-        if name.startswith(SVN_PROP_BZR_ANCESTRY):
-            if self.file_id != self.tree._inventory.root.file_id:
-                mutter('%r set on non-root dir!' % name)
-                return
-        elif name in (SVN_PROP_BZR_FILEIDS, SVN_PROP_BZR_BRANCHING_SCHEME):
-            if self.file_id != self.tree._inventory.root.file_id:
-                mutter('%r set on non-root dir!' % name)
-                return
-        elif name in (constants.PROP_ENTRY_COMMITTED_DATE,
-                      constants.PROP_ENTRY_COMMITTED_REV,
-                      constants.PROP_ENTRY_LAST_AUTHOR,
-                      constants.PROP_ENTRY_LOCK_TOKEN,
-                      constants.PROP_ENTRY_UUID,
-                      constants.PROP_EXECUTABLE,
-                      constants.PROP_IGNORE):
-            pass
-        elif name.startswith(constants.PROP_WC_PREFIX):
+        if name in (properties.PROP_ENTRY_COMMITTED_DATE,
+                      properties.PROP_ENTRY_COMMITTED_REV,
+                      properties.PROP_ENTRY_LAST_AUTHOR,
+                      properties.PROP_ENTRY_LOCK_TOKEN,
+                      properties.PROP_ENTRY_UUID,
+                      properties.PROP_EXECUTABLE,
+                      properties.PROP_IGNORE):
             pass
-        elif (name == SVN_PROP_BZR_REVISION_INFO or 
-              name.startswith(SVN_PROP_BZR_REVISION_ID)):
+        elif name.startswith(properties.PROP_WC_PREFIX):
             pass
-        elif name == SVN_PROP_BZR_MERGE:
-            pass
-        elif (name.startswith(constants.PROP_PREFIX) or
-              name.startswith(SVN_PROP_BZR_PREFIX)):
-            mutter('unsupported dir property %r' % name)
+        elif name.startswith(properties.PROP_PREFIX):
+            mutter('unsupported dir property %r', name)
 
     def add_file(self, path, copyfrom_path=None, copyfrom_revnum=-1):
         path = path.decode("utf-8")
@@ -203,25 +189,24 @@ class FileTreeEditor:
     def change_prop(self, name, value):
         from mapping import SVN_PROP_BZR_PREFIX
 
-        if name == constants.PROP_EXECUTABLE:
+        if name == properties.PROP_EXECUTABLE:
             self.is_executable = (value != None)
-        elif name == constants.PROP_SPECIAL:
+        elif name == properties.PROP_SPECIAL:
             self.is_symlink = (value != None)
-        elif name == constants.PROP_EXTERNALS:
-            mutter('%r property on file!' % name)
-        elif name == constants.PROP_ENTRY_COMMITTED_REV:
+        elif name == properties.PROP_EXTERNALS:
+            mutter('%r property on file!', name)
+        elif name == properties.PROP_ENTRY_COMMITTED_REV:
             self.last_file_rev = int(value)
-        elif name in (constants.PROP_ENTRY_COMMITTED_DATE,
-                      constants.PROP_ENTRY_LAST_AUTHOR,
-                      constants.PROP_ENTRY_LOCK_TOKEN,
-                      constants.PROP_ENTRY_UUID,
-                      constants.PROP_MIME_TYPE):
+        elif name in (properties.PROP_ENTRY_COMMITTED_DATE,
+                      properties.PROP_ENTRY_LAST_AUTHOR,
+                      properties.PROP_ENTRY_LOCK_TOKEN,
+                      properties.PROP_ENTRY_UUID,
+                      properties.PROP_MIME_TYPE):
             pass
-        elif name.startswith(constants.PROP_WC_PREFIX):
+        elif name.startswith(properties.PROP_WC_PREFIX):
             pass
-        elif (name.startswith(constants.PROP_PREFIX) or
-              name.startswith(SVN_PROP_BZR_PREFIX)):
-            mutter('unsupported file property %r' % name)
+        elif name.startswith(properties.PROP_PREFIX):
+            mutter('unsupported file property %r', name)
 
     def close(self, checksum=None):
         file_id, revision_id = self.tree.id_map[self.path]
@@ -275,7 +260,7 @@ class SvnBasisTree(RevisionTree):
 
         def add_file_to_inv(relpath, id, revid, adm):
             (delta_props, props) = adm.get_prop_diffs(self.workingtree.abspath(relpath))
-            if props.has_key(constants.PROP_SPECIAL):
+            if props.has_key(properties.PROP_SPECIAL):
                 ie = self._inventory.add_path(relpath, 'symlink', id)
                 ie.symlink_target = open(self._abspath(relpath)).read()[len("link "):]
                 ie.text_sha1 = None
@@ -287,7 +272,7 @@ class SvnBasisTree(RevisionTree):
                 data = osutils.fingerprint_file(open(self._abspath(relpath)))
                 ie.text_sha1 = data['sha1']
                 ie.text_size = data['size']
-                ie.executable = props.has_key(constants.PROP_EXECUTABLE)
+                ie.executable = props.has_key(properties.PROP_EXECUTABLE)
             ie.revision = revid
             return ie
 
@@ -296,7 +281,7 @@ class SvnBasisTree(RevisionTree):
             if entry.schedule in (wc.SCHEDULE_NORMAL, 
                                   wc.SCHEDULE_DELETE, 
                                   wc.SCHEDULE_REPLACE):
-                return self.id_map[workingtree.branch.unprefix(relpath)]
+                return self.id_map[workingtree.branch.unprefix(relpath.decode("utf-8"))]
             return (None, None)
 
         def add_dir_to_inv(relpath, adm, parent_id):
@@ -309,16 +294,19 @@ class SvnBasisTree(RevisionTree):
             # First handle directory itself
             ie = self._inventory.add_path(relpath, 'directory', id)
             ie.revision = revid
-            if relpath == "":
+            if relpath == u"":
                 self._inventory.revision_id = revid
 
-            for name in entries:
-                if name == "":
+            for name, entry in entries.items():
+                name = name.decode("utf-8")
+                if name == u"":
                     continue
 
+                assert isinstance(relpath, unicode)
+                assert isinstance(name, unicode)
+
                 subrelpath = os.path.join(relpath, name)
 
-                entry = entries[name]
                 assert entry
                 
                 if entry.kind == core.NODE_DIR:
@@ -336,14 +324,17 @@ class SvnBasisTree(RevisionTree):
 
         adm = workingtree._get_wc() 
         try:
-            add_dir_to_inv("", adm, None)
+            add_dir_to_inv(u"", adm, None)
         finally:
             adm.close()
 
     def _abspath(self, relpath):
-        return wc.get_pristine_copy_path(self.workingtree.abspath(relpath))
+        return wc.get_pristine_copy_path(self.workingtree.abspath(relpath).encode("utf-8"))
 
     def get_file_lines(self, file_id):
         base_copy = self._abspath(self.id2path(file_id))
         return osutils.split_lines(open(base_copy).read())
 
+    def annotate_iter(self, file_id,
+                      default_revision=CURRENT_REVISION):
+        raise NotImplementedError(self.annotate_iter)