comparison hgext/convert/bzr.py @ 16060:f84dda152a55

convert/bzr: convert all branches (issue3229) (BC) Instead of opening the target bzr checkout as a single branch, we try to open it as a repository. This has the following effects: - All branches are now converted - bzr branch names are preserved. Previously, the selected branch was always converted as 'default'. Branches without a name or 'trunk' are mapped to 'default branch. - Lightweight checkouts are no longer supported. Maybe they can be, I did not try to fix that at all. Implementation notes: - This was a quick fix, I have no knowledge of bzr API besides browsing 2.0.3 sources. - The fix was only tested on OSX against bzr 2.4.2. - Tags discovery does not handle collisions. I have no idea how tags work in bzr so maybe such collisions are not possible.
author Patrick Mezard <pmezard@gmail.com>
date Thu, 02 Feb 2012 10:15:12 +0100
parents f5b6046f6ce8
children 915e06faa8f3
comparison
equal deleted inserted replaced
16059:f5b6046f6ce8 16060:f84dda152a55
21 from mercurial import util 21 from mercurial import util
22 from common import NoRepo, commit, converter_source 22 from common import NoRepo, commit, converter_source
23 23
24 try: 24 try:
25 # bazaar imports 25 # bazaar imports
26 from bzrlib import branch, revision, errors 26 from bzrlib import bzrdir, revision, errors
27 from bzrlib.revisionspec import RevisionSpec 27 from bzrlib.revisionspec import RevisionSpec
28 except ImportError: 28 except ImportError:
29 pass 29 pass
30 30
31 supportedkinds = ('file', 'symlink') 31 supportedkinds = ('file', 'symlink')
40 raise NoRepo(_('%s does not look like a Bazaar repository') 40 raise NoRepo(_('%s does not look like a Bazaar repository')
41 % path) 41 % path)
42 42
43 try: 43 try:
44 # access bzrlib stuff 44 # access bzrlib stuff
45 branch 45 bzrdir
46 except NameError: 46 except NameError:
47 raise NoRepo(_('Bazaar modules could not be loaded')) 47 raise NoRepo(_('Bazaar modules could not be loaded'))
48 48
49 path = os.path.abspath(path) 49 path = os.path.abspath(path)
50 self._checkrepotype(path) 50 self._checkrepotype(path)
51 self.branch = branch.Branch.open(path) 51 try:
52 self.sourcerepo = self.branch.repository 52 self.sourcerepo = bzrdir.BzrDir.open(path).open_repository()
53 except errors.NoRepositoryPresent:
54 raise NoRepo(_('%s does not look like a Bazaar repository')
55 % path)
53 self._parentids = {} 56 self._parentids = {}
54 57
55 def _checkrepotype(self, path): 58 def _checkrepotype(self, path):
56 # Lightweight checkouts detection is informational but probably 59 # Lightweight checkouts detection is informational but probably
57 # fragile at API level. It should not terminate the conversion. 60 # fragile at API level. It should not terminate the conversion.
88 def after(self): 91 def after(self):
89 self.sourcerepo.unlock() 92 self.sourcerepo.unlock()
90 93
91 def getheads(self): 94 def getheads(self):
92 if not self.rev: 95 if not self.rev:
93 return [self.branch.last_revision()] 96 heads = sorted([b.last_revision()
94 try: 97 for b in self.sourcerepo.find_branches()])
95 r = RevisionSpec.from_string(self.rev) 98 else:
96 info = r.in_history(self.branch) 99 revid = None
97 except errors.BzrError: 100 for branch in self.sourcerepo.find_branches():
98 raise util.Abort(_('%s is not a valid revision in current branch') 101 try:
99 % self.rev) 102 r = RevisionSpec.from_string(self.rev)
100 return [info.rev_id] 103 info = r.in_history(branch)
104 except errors.BzrError:
105 pass
106 revid = info.rev_id
107 if revid is None:
108 raise util.Abort(_('%s is not a valid revision') % self.rev)
109 heads = [revid]
110 return heads
101 111
102 def getfile(self, name, rev): 112 def getfile(self, name, rev):
103 revtree = self.sourcerepo.revision_tree(rev) 113 revtree = self.sourcerepo.revision_tree(rev)
104 fileid = revtree.path2id(name.decode(self.encoding or 'utf-8')) 114 fileid = revtree.path2id(name.decode(self.encoding or 'utf-8'))
105 kind = None 115 kind = None
138 self._parentids[version] = (revision.NULL_REVISION,) 148 self._parentids[version] = (revision.NULL_REVISION,)
139 else: 149 else:
140 parents = self._filterghosts(rev.parent_ids) 150 parents = self._filterghosts(rev.parent_ids)
141 self._parentids[version] = parents 151 self._parentids[version] = parents
142 152
153 branch = self.recode(rev.properties.get('branch-nick', u'default'))
154 if branch == 'trunk':
155 branch = 'default'
143 return commit(parents=parents, 156 return commit(parents=parents,
144 date='%d %d' % (rev.timestamp, -rev.timezone), 157 date='%d %d' % (rev.timestamp, -rev.timezone),
145 author=self.recode(rev.committer), 158 author=self.recode(rev.committer),
146 desc=self.recode(rev.message), 159 desc=self.recode(rev.message),
160 branch=branch,
147 rev=version) 161 rev=version)
148 162
149 def gettags(self): 163 def gettags(self):
150 if not self.branch.supports_tags():
151 return {}
152 tagdict = self.branch.tags.get_tag_dict()
153 bytetags = {} 164 bytetags = {}
154 for name, rev in tagdict.iteritems(): 165 for branch in self.sourcerepo.find_branches():
155 bytetags[self.recode(name)] = rev 166 if not branch.supports_tags():
167 return {}
168 tagdict = branch.tags.get_tag_dict()
169 for name, rev in tagdict.iteritems():
170 bytetags[self.recode(name)] = rev
156 return bytetags 171 return bytetags
157 172
158 def getchangedfiles(self, rev, i): 173 def getchangedfiles(self, rev, i):
159 self._modecache = {} 174 self._modecache = {}
160 curtree = self.sourcerepo.revision_tree(rev) 175 curtree = self.sourcerepo.revision_tree(rev)