Merge 0.4.
authorJelmer Vernooij <jelmer@samba.org>
Tue, 29 Jan 2008 00:19:22 +0000 (01:19 +0100)
committerJelmer Vernooij <jelmer@samba.org>
Tue, 29 Jan 2008 00:19:22 +0000 (01:19 +0100)
1  2 
NEWS
__init__.py
commit.py
config.py
fetch.py
mapping.py
repository.py
tests/test_commit.py
tests/test_config.py

diff --cc NEWS
index e0b88e4397c316de05070538f760d7f6971a35b6,5345440efca7532d0065d7f037adad5941b6c837..c335b7097aa026e40e5b498f3b7fd903d401854a
--- 1/NEWS
--- 2/NEWS
+++ b/NEWS
@@@ -1,5 -1,11 +1,13 @@@
  bzr-svn 0.4.7 UNRELEASED
+  
+   FEATURES
+    * Implement Repository.find_branches(). (#178108)
+    * Warn about location when initializing Subversion repository cache.
++   * Set revision properties when possible.
 +
    BUGS
  
     * Fix opening unicode file names during fetch. (#162368)
diff --cc __init__.py
Simple merge
diff --cc commit.py
index 99b1f406ca8e3681612eb0812ca52dfd9edf9b8d,a4b1d9091c9bc5b724aade94698848a6e6ab9445..36ba031c7c98bc52d4ae071d878281bb56472133
+++ b/commit.py
@@@ -30,16 -30,11 +30,18 @@@ from bzrlib.trace import mutte
  from copy import deepcopy
  from cStringIO import StringIO
  from errors import ChangesRootLHSHistory, MissingPrefix, RevpropChangeFailed
- from repository import (SVN_PROP_BZR_ANCESTRY, SVN_PROP_BZR_FILEIDS,
-                         SVN_PROP_SVK_MERGE, SVN_PROP_BZR_REVISION_INFO, 
-                         SVN_PROP_BZR_REVISION_ID, revision_id_to_svk_feature,
++from repository import (SVN_PROP_SVK_MERGE, revision_id_to_svk_feature,
 +                        generate_revision_metadata, SvnRepositoryFormat, 
-                         SvnRepository, MAPPING_VERSION,
-                         SVN_REVPROP_BZR_COMMITTER, SVN_REVPROP_BZR_FILEIDS,
-                         SVN_REVPROP_BZR_MERGE, SVN_REVPROP_BZR_REVISION_ID,
-                         SVN_REVPROP_BZR_REVPROP_PREFIX, SVN_REVPROP_BZR_ROOT,
-                         SVN_REVPROP_BZR_TIMESTAMP, SVN_REVPROP_BZR_MAPPING_VERSION,
-                         format_highres_date)
++                        SvnRepository, format_highres_date)
+ from mapping import (SVN_PROP_BZR_ANCESTRY, SVN_PROP_BZR_FILEIDS,
 -                     SVN_PROP_BZR_REVISION_INFO, 
 -                     SVN_PROP_BZR_REVISION_ID)
++                     SVN_PROP_BZR_REVISION_INFO, SVN_PROP_BZR_REVISION_ID, 
++                     SVN_REVPROP_BZR_COMMITTER, SVN_REVPROP_BZR_FILEIDS,
++                     SVN_REVPROP_BZR_MERGE, SVN_REVPROP_BZR_REVISION_ID,
++                     SVN_REVPROP_BZR_REVPROP_PREFIX, SVN_REVPROP_BZR_ROOT,
++                     SVN_REVPROP_BZR_TIMESTAMP, SVN_REVPROP_BZR_MAPPING_VERSION,
++                     MAPPING_VERSION)
+ from repository import (revision_id_to_svk_feature, generate_revision_metadata, 
+                         SvnRepositoryFormat, SvnRepository, SVN_PROP_SVK_MERGE)
  import urllib
  
  
diff --cc config.py
index e4841ceec1145540831c51291ed07f5d742e479f,e16c81503466238f1979f9b4a2d29ac213011371..b98ae9bc83aff8ffe778923ed7a1b6d8a8cf44da
+++ b/config.py
@@@ -63,25 -64,19 +64,35 @@@ class SvnRepositoryConfig(IniBasedConfi
          """
          schemename = self._get_user_option("branching-scheme", use_global=False)
          if schemename is not None:
-             return BranchingScheme.find_scheme(schemename)
+             return BranchingScheme.find_scheme(schemename.encode('ascii'))
          return None
  
 +    def get_set_revprops(self):
 +        """Check whether or not bzr-svn should attempt to store Bazaar
 +        revision properties in Subversion revision properties during commit."""
 +        try:
 +            return self._get_parser().get_bool(self.uuid, "set-revprops")
 +        except KeyError:
 +            return None
 +
 +    def get_supports_change_revprop(self):
 +        """Check whether or not the repository supports changing existing 
 +        revision properties."""
 +        try:
 +            return self._get_parser().get_bool(self.uuid, "supports-change-revprop")
 +        except KeyError:
 +            return None
 +
+     def branching_scheme_is_mandatory(self):
+         """Check whether or not the branching scheme for this repository 
+         is mandatory.
+         """
+         mandatory = self._get_user_option("branching-scheme-mandatory", 
+                                            use_global=False)
+         if mandatory is not None:
+             return bool(mandatory)
+         return False
      def get_override_svn_revprops(self):
          """Check whether or not bzr-svn should attempt to override Subversion revision 
          properties after committing."""
diff --cc fetch.py
index 233e8c4543ded631b2f0404ae45e6219d2292544,5a41577252de655c007f0b3aba0c67c94a13a69e..68f86c654b5f428d61b73704843f1a79c6d8f2dd
+++ b/fetch.py
@@@ -30,14 -30,13 +30,14 @@@ import svn.cor
  
  from bzrlib.plugins.svn.errors import InvalidFileName
  from fileids import generate_file_id
- from repository import (SvnRepository, SVN_PROP_BZR_ANCESTRY, 
-                 SVN_PROP_SVK_MERGE, SVN_PROP_BZR_MERGE,
-                 SVN_PROP_BZR_PREFIX, SVN_PROP_BZR_REVISION_INFO, 
-                 SVN_PROP_BZR_BRANCHING_SCHEME, SVN_PROP_BZR_REVISION_ID,
-                 SVN_REVPROP_BZR_MAPPING_VERSION, MAPPING_VERSION,
-                 SVN_PROP_BZR_FILEIDS, SvnRepositoryFormat, 
-                 parse_revision_metadata, parse_merge_property,
-                 revision_parse_svn_revprops)
+ 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)
++                     SVN_PROP_BZR_FILEIDS, SVN_REVPROP_BZR_MAPPING_VERSION, 
++                     MAPPING_VERSION)
+ from repository import (SvnRepository, SvnRepositoryFormat, 
+                         parse_revision_metadata, parse_merge_property, 
 -                        SVN_PROP_SVK_MERGE)
++                        SVN_PROP_SVK_MERGE, revision_parse_svn_revprops)
  from tree import apply_txdelta_handler
  
  
diff --cc mapping.py
index 0000000000000000000000000000000000000000,a46fe6fdf9b05633eeb73878a7af863d93e551ef..765c336ea5829cb93732f57dfcfe4d520f1b2cf0
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,193 +1,195 @@@
+ # 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 3 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, see <http://www.gnu.org/licenses/>.
+ from bzrlib import errors, osutils, registry
+ import sha
+ import urllib
+ MAPPING_VERSION = 3
+ SVN_PROP_BZR_PREFIX = 'bzr:'
+ SVN_PROP_BZR_ANCESTRY = 'bzr:ancestry:v%d-' % MAPPING_VERSION
+ SVN_PROP_BZR_FILEIDS = 'bzr:file-ids'
+ SVN_PROP_BZR_MERGE = 'bzr:merge'
+ SVN_PROP_BZR_REVISION_INFO = 'bzr:revision-info'
+ SVN_PROP_BZR_REVISION_ID = 'bzr:revision-id:v%d-' % MAPPING_VERSION
+ SVN_PROP_BZR_BRANCHING_SCHEME = 'bzr:branching-scheme'
+ SVN_REVPROP_BZR_COMMITTER = 'bzr:committer'
+ SVN_REVPROP_BZR_FILEIDS = 'bzr:file-ids'
++SVN_REVPROP_BZR_MAPPING_VERSION = 'bzr:mapping-version'
+ SVN_REVPROP_BZR_MERGE = 'bzr:merge'
+ SVN_REVPROP_BZR_REVISION_ID = 'bzr:revision-id'
+ SVN_REVPROP_BZR_REVPROP_PREFIX = 'bzr:revprop:'
+ SVN_REVPROP_BZR_ROOT = 'bzr:root'
+ SVN_REVPROP_BZR_SCHEME = 'bzr:scheme'
+ SVN_REVPROP_BZR_SIGNATURE = 'bzr:gpg-signature'
++SVN_REVPROP_BZR_TIMESTAMP = 'bzr:timestamp'
+ def escape_svn_path(x):
+     """Escape a Subversion path for use in a revision identifier.
+     :param x: Path
+     :return: Escaped path
+     """
+     assert isinstance(x, str)
+     return urllib.quote(x, "")
+ unescape_svn_path = urllib.unquote
+ class BzrSvnMapping:
+     """Class that maps between Subversion and Bazaar semantics."""
+     @staticmethod
+     def parse_revision_id(revid):
+         """Parse an existing Subversion-based revision id.
+         :param revid: The revision id.
+         :raises: InvalidRevisionId
+         :return: Tuple with uuid, branch path, revision number and scheme.
+         """
+         raise NotImplementedError(self.parse_revision_id)
+     def generate_revision_id(uuid, revnum, path, scheme):
+         """Generate a unambiguous revision id. 
+         
+         :param uuid: UUID of the repository.
+         :param revnum: Subversion revision number.
+         :param path: Branch path.
+         :param scheme: Name of the branching scheme in use
+         :return: New revision id.
+         """
+         raise NotImplementedError(self.generate_revision_id)
+     @staticmethod
+     def generate_file_id(uuid, revnum, branch, inv_path):
+         """Create a file id identifying a Subversion file.
+         :param uuid: UUID of the repository
+         :param revnum: Revision number at which the file was introduced.
+         :param branch: Branch path of the branch in which the file was introduced.
+         :param inv_path: Original path of the file within the inventory
+         """
+         raise NotImplementedError(self.generate_file_id)
+ class BzrSvnMappingv1(BzrSvnMapping):
+     @staticmethod
+     def parse_revision_id(revid):
+         assert revid.startswith("svn-v1:")
+         revid = revid[len("svn-v1:"):]
+         at = revid.index("@")
+         fash = revid.rindex("-")
+         uuid = revid[at+1:fash]
+         branch_path = unescape_svn_path(revid[fash+1:])
+         revnum = int(revid[0:at])
+         assert revnum >= 0
+         return (uuid, branch_path, revnum, None)
+ class BzrSvnMappingv2(BzrSvnMapping):
+     @staticmethod
+     def parse_revision_id(revid):
+         assert revid.startswith("svn-v2:")
+         revid = revid[len("svn-v2:"):]
+         at = revid.index("@")
+         fash = revid.rindex("-")
+         uuid = revid[at+1:fash]
+         branch_path = unescape_svn_path(revid[fash+1:])
+         revnum = int(revid[0:at])
+         assert revnum >= 0
+         return (uuid, branch_path, revnum, None)
+ class BzrSvnMappingv3(BzrSvnMapping):
+     revid_prefix = "svn-v3-"
+     @classmethod
+     def parse_revision_id(cls, revid):
+         assert revid is not None
+         assert isinstance(revid, str)
+         if not revid.startswith(cls.revid_prefix):
+             raise errors.InvalidRevisionId(revid, "")
+         try:
+             (version, uuid, branch_path, srevnum) = revid.split(":")
+         except ValueError:
+             raise errors.InvalidRevisionId(revid, "")
+         scheme = version[len(cls.revid_prefix):]
+         if scheme == "undefined":
+             scheme = None
+         return (uuid, unescape_svn_path(branch_path), int(srevnum), scheme)
+     @classmethod
+     def generate_revision_id(cls, uuid, revnum, path, scheme):
+         assert isinstance(revnum, int)
+         assert isinstance(path, str)
+         assert revnum >= 0
+         assert revnum > 0 or path == "", \
+                 "Trying to generate revid for (%r,%r)" % (path, revnum)
+         return "%s%s:%s:%s:%d" % (cls.revid_prefix, scheme, uuid, \
+                        escape_svn_path(path.strip("/")), revnum)
+     @staticmethod
+     def generate_file_id(uuid, revnum, branch, inv_path):
+         assert isinstance(uuid, str)
+         assert isinstance(revnum, int)
+         assert isinstance(branch, str)
+         assert isinstance(inv_path, unicode)
+         inv_path = inv_path.encode("utf-8")
+         ret = "%d@%s:%s:%s" % (revnum, uuid, escape_svn_path(branch), escape_svn_path(inv_path))
+         if len(ret) > 150:
+             ret = "%d@%s:%s;%s" % (revnum, uuid, 
+                                 escape_svn_path(branch),
+                                 sha.new(inv_path).hexdigest())
+         assert isinstance(ret, str)
+         return osutils.safe_file_id(ret)
+ class BzrSvnMappingRegistry(registry.Registry):
+     def register(self, key, factory, help):
+         """Register a mapping between Bazaar and Subversion semantics.
+         The factory must be a callable that takes one parameter: the key.
+         It must produce an instance of BzrSvnMapping when called.
+         """
+         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.
+         """
+         registry.Registry.register(self, 'default', self.get(key), 
+             self.get_help(key))
+ mapping_registry = BzrSvnMappingRegistry()
+ mapping_registry.register('v1', BzrSvnMappingv1,
+         'Original bzr-svn mapping format')
+ mapping_registry.register('v2', BzrSvnMappingv2,
+         'Second format')
+ mapping_registry.register('v3', BzrSvnMappingv3,
+         'Third format')
+ mapping_registry.set_default('v3')
+ default_mapping = BzrSvnMappingv3
diff --cc repository.py
index d6f033e96525bfbba594b270b97ebc08cd7bc6c8,991aa68d8ac759d48b0d7dd0154972e9d7f3a742..45d6c8c11a80a37a95fb88f4404162099e361d28
@@@ -738,33 -714,24 +747,33 @@@ class SvnRepository(Repository)
          if revid is not None:
              return revid
  
 -        # Lookup the revision from the bzr:revision-id-vX property
 -        line = self.branchprop_list.get_property_diff(path, revnum, 
 -                SVN_PROP_BZR_REVISION_ID+str(scheme)).strip("\n")
 -        # Or generate it
 -        if line == "":
 -            revid = default_mapping.generate_revision_id(
 -                        self.uuid, revnum, path, scheme)
 +        # See if there is a bzr:revision-id revprop set
 +        revprops = self._log._get_transport().revprop_list(revnum)
 +        if revprops.has_key(SVN_REVPROP_BZR_MAPPING_VERSION):
 +            if revprops[SVN_REVPROP_BZR_ROOT] == path:
 +                revid = revprops[SVN_REVPROP_BZR_REVISION_ID]
 +            else:
 +                revid = generate_svn_revision_id(self.uuid, revnum, path, 
 +                                                 scheme)
          else:
 -            try:
 -                (bzr_revno, revid) = parse_revid_property(line)
 -                self.revmap.insert_revid(revid, path, revnum, revnum, 
 -                        scheme, bzr_revno)
 -            except errors.InvalidPropertyValue, e:
 -                mutter(str(e))
 -                revid = default_mapping.generate_revision_id(self.uuid, 
 -                            revnum, path, scheme)
 -                self.revmap.insert_revid(revid, path, revnum, revnum, 
 -                        scheme)
 +            # Lookup the revision from the bzr:revision-id-vX property
 +            line = self.branchprop_list.get_property_diff(path, revnum, 
 +                    SVN_PROP_BZR_REVISION_ID+str(scheme)).strip("\n")
 +            # Or generate it
 +            if line == "":
-                 revid = generate_svn_revision_id(self.uuid, revnum, path, 
-                                                  scheme)
++                revid = default_mapping.generate_revision_id(
++                            self.uuid, revnum, path, scheme)
 +            else:
 +                try:
 +                    (bzr_revno, revid) = parse_revid_property(line)
 +                    self.revmap.insert_revid(revid, path, revnum, revnum, 
 +                            scheme, bzr_revno)
 +                except errors.InvalidPropertyValue, e:
 +                    mutter(str(e))
-                     revid = generate_svn_revision_id(self.uuid, revnum, path, 
-                                                      scheme)
-         self.revmap.insert_revid(revid, path, revnum, revnum, 
-                 scheme)
++                    revid = default_mapping.generate_revision_id(self.uuid, 
++                                revnum, path, scheme)
++                    self.revmap.insert_revid(revid, path, revnum, revnum, 
++                            scheme)
  
          return revid
  
Simple merge
Simple merge