summaryrefslogtreecommitdiff
path: root/hgext/convert/bzr.py
diff options
context:
space:
mode:
Diffstat (limited to 'hgext/convert/bzr.py')
-rw-r--r--hgext/convert/bzr.py101
1 files changed, 38 insertions, 63 deletions
diff --git a/hgext/convert/bzr.py b/hgext/convert/bzr.py
index 5eef902..cc16258 100644
--- a/hgext/convert/bzr.py
+++ b/hgext/convert/bzr.py
@@ -23,7 +23,7 @@ from common import NoRepo, commit, converter_source
try:
# bazaar imports
- from bzrlib import bzrdir, revision, errors
+ from bzrlib import branch, revision, errors
from bzrlib.revisionspec import RevisionSpec
except ImportError:
pass
@@ -42,17 +42,14 @@ class bzr_source(converter_source):
try:
# access bzrlib stuff
- bzrdir
+ branch
except NameError:
raise NoRepo(_('Bazaar modules could not be loaded'))
path = os.path.abspath(path)
self._checkrepotype(path)
- try:
- self.sourcerepo = bzrdir.BzrDir.open(path).open_repository()
- except errors.NoRepositoryPresent:
- raise NoRepo(_('%s does not look like a Bazaar repository')
- % path)
+ self.branch = branch.Branch.open(path)
+ self.sourcerepo = self.branch.repository
self._parentids = {}
def _checkrepotype(self, path):
@@ -72,7 +69,7 @@ class bzr_source(converter_source):
self.ui.warn(_('warning: lightweight checkouts may cause '
'conversion failures, try with a regular '
'branch instead.\n'))
- except Exception:
+ except:
self.ui.note(_('bzr source type could not be determined\n'))
def before(self):
@@ -91,28 +88,16 @@ class bzr_source(converter_source):
def after(self):
self.sourcerepo.unlock()
- def _bzrbranches(self):
- return self.sourcerepo.find_branches(using=True)
-
def getheads(self):
if not self.rev:
- # Set using=True to avoid nested repositories (see issue3254)
- heads = sorted([b.last_revision() for b in self._bzrbranches()])
- else:
- revid = None
- for branch in self._bzrbranches():
- try:
- r = RevisionSpec.from_string(self.rev)
- info = r.in_history(branch)
- except errors.BzrError:
- pass
- revid = info.rev_id
- if revid is None:
- raise util.Abort(_('%s is not a valid revision') % self.rev)
- heads = [revid]
- # Empty repositories return 'null:', which cannot be retrieved
- heads = [h for h in heads if h != 'null:']
- return heads
+ return [self.branch.last_revision()]
+ try:
+ r = RevisionSpec.from_string(self.rev)
+ info = r.in_history(self.branch)
+ except errors.BzrError:
+ raise util.Abort(_('%s is not a valid revision in current branch')
+ % self.rev)
+ return [info.rev_id]
def getfile(self, name, rev):
revtree = self.sourcerepo.revision_tree(rev)
@@ -155,24 +140,20 @@ class bzr_source(converter_source):
parents = self._filterghosts(rev.parent_ids)
self._parentids[version] = parents
- branch = self.recode(rev.properties.get('branch-nick', u'default'))
- if branch == 'trunk':
- branch = 'default'
return commit(parents=parents,
date='%d %d' % (rev.timestamp, -rev.timezone),
author=self.recode(rev.committer),
+ # bzr returns bytestrings or unicode, depending on the content
desc=self.recode(rev.message),
- branch=branch,
rev=version)
def gettags(self):
+ if not self.branch.supports_tags():
+ return {}
+ tagdict = self.branch.tags.get_tag_dict()
bytetags = {}
- for branch in self._bzrbranches():
- if not branch.supports_tags():
- return {}
- tagdict = branch.tags.get_tag_dict()
- for name, rev in tagdict.iteritems():
- bytetags[self.recode(name)] = rev
+ for name, rev in tagdict.iteritems():
+ bytetags[self.recode(name)] = rev
return bytetags
def getchangedfiles(self, rev, i):
@@ -192,14 +173,8 @@ class bzr_source(converter_source):
revid = current._revision_id
changes = []
renames = {}
- seen = set()
- # Process the entries by reverse lexicographic name order to
- # handle nested renames correctly, most specific first.
- curchanges = sorted(current.iter_changes(origin),
- key=lambda c: c[1][0] or c[1][1],
- reverse=True)
for (fileid, paths, changed_content, versioned, parent, name,
- kind, executable) in curchanges:
+ kind, executable) in current.iter_changes(origin):
if paths[0] == u'' or paths[1] == u'':
# ignore changes to tree root
@@ -213,8 +188,7 @@ class bzr_source(converter_source):
# so it can be removed.
changes.append((self.recode(paths[0]), revid))
- if kind[0] == 'directory' and None not in paths:
- renaming = paths[0] != paths[1]
+ if None not in paths and paths[0] != paths[1]:
# neither an add nor an delete - a move
# rename all directory contents manually
subdir = origin.inventory.path2id(paths[0])
@@ -224,16 +198,6 @@ class bzr_source(converter_source):
if entry.kind == 'directory':
continue
frompath = self.recode(paths[0] + '/' + name)
- if frompath in seen:
- # Already handled by a more specific change entry
- # This is important when you have:
- # a => b
- # a/c => a/c
- # Here a/c must not be renamed into b/c
- continue
- seen.add(frompath)
- if not renaming:
- continue
topath = self.recode(paths[1] + '/' + name)
# register the files as changed
changes.append((frompath, revid))
@@ -250,12 +214,7 @@ class bzr_source(converter_source):
continue
# we got unicode paths, need to convert them
- path, topath = paths
- if path is not None:
- path = self.recode(path)
- if topath is not None:
- topath = self.recode(topath)
- seen.add(path or topath)
+ path, topath = [self.recode(part) for part in paths]
if topath is None:
# file deleted
@@ -283,3 +242,19 @@ class bzr_source(converter_source):
parentmap = self.sourcerepo.get_parent_map(ids)
parents = tuple([parent for parent in ids if parent in parentmap])
return parents
+
+ def recode(self, s, encoding=None):
+ """This version of recode tries to encode unicode to bytecode,
+ and preferably using the UTF-8 codec.
+ Other types than Unicode are silently returned, this is by
+ intention, e.g. the None-type is not going to be encoded but instead
+ just passed through
+ """
+ if not encoding:
+ encoding = self.encoding or 'utf-8'
+
+ if isinstance(s, unicode):
+ return s.encode(encoding)
+ else:
+ # leave it alone
+ return s