diff options
Diffstat (limited to 'hgext/convert/bzr.py')
-rw-r--r-- | hgext/convert/bzr.py | 101 |
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 |