250
247
rev.properties[name[len(SVN_REVPROP_BZR_REVPROP_PREFIX):]] = value
250
class BzrSvnMapping(object):
254
251
"""Class that maps between Subversion and Bazaar semantics."""
255
252
experimental = False
256
253
_warned_experimental = False
258
255
def __init__(self):
259
if self.experimental and not BzrSvnMapping._warned_experimental:
256
if (version_info[3] == 'exp' or self.experimental) and not BzrSvnMapping._warned_experimental:
260
257
from bzrlib.trace import warning
261
258
warning("using experimental bzr-svn mappings; output may change between revisions")
262
259
BzrSvnMapping._warned_experimental = True
262
def from_repository(cls, repository, _hinted_branch_path=None):
265
266
def supports_roundtripping(cls):
266
267
"""Whether this mapping supports roundtripping.
430
443
return "".join(["%s\t%s\n" % (urllib.quote(path), fileids[path]) for path in sorted(fileids.keys())])
433
class BzrSvnMappingv3(BzrSvnMapping):
434
"""The third version of the mappings as used in the 0.4.x series.
438
upgrade_suffix = "-svn3"
439
revid_prefix = "svn-v3-"
441
def __init__(self, scheme):
442
BzrSvnMapping.__init__(self)
444
assert not isinstance(scheme, str)
447
return "%s(%r)" % (self.__class__.__name__, self.scheme)
449
def generate_file_id(self, uuid, revnum, branch, inv_path):
450
assert isinstance(uuid, str)
451
assert isinstance(revnum, int)
452
assert isinstance(branch, str)
453
assert isinstance(inv_path, unicode)
454
inv_path = inv_path.encode("utf-8")
455
ret = "%d@%s:%s:%s" % (revnum, uuid, escape_svn_path(branch), escape_svn_path(inv_path))
457
ret = "%d@%s:%s;%s" % (revnum, uuid,
458
escape_svn_path(branch),
459
sha.new(inv_path).hexdigest())
460
assert isinstance(ret, str)
461
return osutils.safe_file_id(ret)
464
def supports_roundtripping():
468
def _parse_revision_id(cls, revid):
469
assert isinstance(revid, str)
471
if not revid.startswith(cls.revid_prefix):
472
raise InvalidRevisionId(revid, "")
475
(version, uuid, branch_path, srevnum) = revid.split(":")
477
raise InvalidRevisionId(revid, "")
479
scheme = version[len(cls.revid_prefix):]
481
branch_path = unescape_svn_path(branch_path)
483
return (uuid, branch_path, int(srevnum), scheme)
486
def parse_revision_id(cls, revid):
487
(uuid, branch_path, srevnum, scheme) = cls._parse_revision_id(revid)
488
# Some older versions of bzr-svn 0.4 did not always set a branching
489
# scheme but set "undefined" instead.
490
if scheme == "undefined":
491
scheme = guess_scheme_from_branch_path(branch_path)
493
scheme = BranchingScheme.find_scheme(scheme)
495
return (uuid, branch_path, srevnum, cls(scheme))
497
def is_branch(self, branch_path):
498
return (self.scheme.is_branch(branch_path) or
499
self.scheme.is_tag(branch_path))
501
def is_tag(self, tag_path):
502
return self.scheme.is_tag(tag_path)
505
def _generate_revision_id(cls, uuid, revnum, path, scheme):
506
assert isinstance(revnum, int)
507
assert isinstance(path, str)
509
assert revnum > 0 or path == "", \
510
"Trying to generate revid for (%r,%r)" % (path, revnum)
511
return "%s%s:%s:%s:%d" % (cls.revid_prefix, scheme, uuid, \
512
escape_svn_path(path.strip("/")), revnum)
514
def generate_revision_id(self, uuid, revnum, path):
515
return self._generate_revision_id(uuid, revnum, path, self.scheme)
517
def unprefix(self, branch_path, repos_path):
518
(bp, np) = self.scheme.unprefix(repos_path)
519
assert branch_path == bp
522
def __eq__(self, other):
523
return type(self) == type(other) and self.scheme == other.scheme
526
class BzrSvnMappingFileProps:
446
class BzrSvnMappingFileProps(object):
528
448
def supports_custom_fileprops(cls):
529
449
"""Whether this mapping can be used with custom file properties."""
714
638
return type(self) == type(other)
717
class BzrSvnMappingv3Hybrid(BzrSvnMappingv3):
718
def __init__(self, scheme):
719
BzrSvnMappingv3.__init__(self, scheme)
720
self.revprops = BzrSvnMappingv3RevProps(scheme)
721
self.fileprops = BzrSvnMappingv3FileProps(scheme)
723
def get_rhs_parents(self, branch_path, svn_revprops, fileprops):
724
if svn_revprops.has_key(SVN_REVPROP_BZR_MAPPING_VERSION):
725
return self.revprops.get_rhs_parents(branch_path, svn_revprops, fileprops)
727
return self.fileprops.get_rhs_parents(branch_path, svn_revprops, fileprops)
729
def get_revision_id(self, branch_path, revprops, fileprops):
730
if revprops.has_key(SVN_REVPROP_BZR_MAPPING_VERSION):
731
return self.revprops.get_revision_id(branch_path, revprops, fileprops)
733
return self.fileprops.get_revision_id(branch_path, revprops, fileprops)
735
def import_fileid_map(self, svn_revprops, fileprops):
736
if svn_revprops.has_key(SVN_REVPROP_BZR_MAPPING_VERSION):
737
return self.revprops.import_fileid_map(svn_revprops, fileprops)
739
return self.fileprops.import_fileid_map(svn_revprops, fileprops)
741
def export_revision(self, branch_root, timestamp, timezone, committer, revprops, revision_id, revno,
743
(_, fileprops) = self.fileprops.export_revision(branch_root, timestamp, timezone, committer,
744
revprops, revision_id, revno, merges, fileprops)
745
(revprops, _) = self.revprops.export_revision(branch_root, timestamp, timezone, committer,
746
revprops, revision_id, revno, merges, fileprops)
747
return (revprops, fileprops)
749
def export_fileid_map(self, fileids, revprops, fileprops):
750
self.fileprops.export_fileid_map(fileids, revprops, fileprops)
751
self.revprops.export_fileid_map(fileids, revprops, fileprops)
753
def import_revision(self, svn_revprops, fileprops, rev):
754
self.fileprops.import_revision(svn_revprops, fileprops, rev)
755
self.revprops.import_revision(svn_revprops, fileprops, rev)
757
641
class BzrSvnMappingRegistry(registry.Registry):
758
642
"""Registry for the various Bzr<->Svn mappings."""
759
643
def register(self, key, factory, help):
770
654
This method must be called once and only once.
772
registry.Registry.register(self, 'default', self.get(key),
656
self._set_default_key(key)
658
def get_default(self):
659
"""Convenience function for obtaining the default mapping to use."""
660
return self.get(self._get_default_key())
775
662
mapping_registry = BzrSvnMappingRegistry()
776
663
mapping_registry.register('v1', BzrSvnMappingv1,
777
664
'Original bzr-svn mapping format')
778
665
mapping_registry.register('v2', BzrSvnMappingv2,
780
mapping_registry.register('v3-revprops', BzrSvnMappingv3RevProps,
781
'Third format with revision properties')
782
mapping_registry.register('v3-fileprops', BzrSvnMappingv3FileProps,
783
'Third format with file properties')
784
mapping_registry.register('v3-hybrid', BzrSvnMappingv3Hybrid,
785
'Hybrid third format')
786
mapping_registry.register('v3', BzrSvnMappingv3FileProps,
787
'Default third format')
667
mapping_registry.register_lazy('v3-revprops', 'bzrlib.plugins.svn.mapping3',
668
'BzrSvnMappingv3RevProps',
669
'Third format with revision properties')
670
mapping_registry.register_lazy('v3-fileprops', 'bzrlib.plugins.svn.mapping3',
671
'BzrSvnMappingv3FileProps',
672
'Third format with file properties')
673
mapping_registry.register_lazy('v3-hybrid', 'bzrlib.plugins.svn.mapping3',
674
'BzrSvnMappingv3Hybrid', 'Hybrid third format')
675
mapping_registry.register_lazy('v3', 'bzrlib.plugins.svn.mapping3',
676
'BzrSvnMappingv3FileProps',
677
'Default third format')
788
678
mapping_registry.register('v4', BzrSvnMappingv4,
790
680
mapping_registry.set_default('v3-fileprops')
793
682
def parse_revision_id(revid):
794
683
"""Try to parse a Subversion revision id.