##// END OF EJS Templates
demandimport: convert ignored modules from bytes -> str in extensions...
Matt Harbison -
r50445:5f22c92d stable
parent child Browse files
Show More
@@ -1,337 +1,337 b''
1 1 # bzr.py - bzr support for the convert extension
2 2 #
3 3 # Copyright 2008, 2009 Marek Kubica <marek@xivilization.net> and others
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 # This module is for handling Breezy imports or `brz`, but it's also compatible
9 9 # with Bazaar or `bzr`, that was formerly known as Bazaar-NG;
10 10 # it cannot access `bar` repositories, but they were never used very much.
11 11
12 12 import os
13 13
14 14 from mercurial.i18n import _
15 15 from mercurial import (
16 16 demandimport,
17 17 error,
18 18 util,
19 19 )
20 20 from . import common
21 21
22 22
23 23 # these do not work with demandimport, blacklist
24 24 demandimport.IGNORES.update(
25 25 [
26 b'breezy.transactions',
27 b'breezy.urlutils',
28 b'ElementPath',
26 'breezy.transactions',
27 'breezy.urlutils',
28 'ElementPath',
29 29 ]
30 30 )
31 31
32 32 try:
33 33 # bazaar imports
34 34 import breezy.bzr.bzrdir
35 35 import breezy.errors
36 36 import breezy.revision
37 37 import breezy.revisionspec
38 38
39 39 bzrdir = breezy.bzr.bzrdir
40 40 errors = breezy.errors
41 41 revision = breezy.revision
42 42 revisionspec = breezy.revisionspec
43 43 revisionspec.RevisionSpec
44 44 except ImportError:
45 45 pass
46 46
47 47 supportedkinds = ('file', 'symlink')
48 48
49 49
50 50 class bzr_source(common.converter_source):
51 51 """Reads Bazaar repositories by using the Bazaar Python libraries"""
52 52
53 53 def __init__(self, ui, repotype, path, revs=None):
54 54 super(bzr_source, self).__init__(ui, repotype, path, revs=revs)
55 55
56 56 if not os.path.exists(os.path.join(path, b'.bzr')):
57 57 raise common.NoRepo(
58 58 _(b'%s does not look like a Bazaar repository') % path
59 59 )
60 60
61 61 try:
62 62 # access breezy stuff
63 63 bzrdir
64 64 except NameError:
65 65 raise common.NoRepo(_(b'Bazaar modules could not be loaded'))
66 66
67 67 path = util.abspath(path)
68 68 self._checkrepotype(path)
69 69 try:
70 70 bzr_dir = bzrdir.BzrDir.open(path.decode())
71 71 self.sourcerepo = bzr_dir.open_repository()
72 72 except errors.NoRepositoryPresent:
73 73 raise common.NoRepo(
74 74 _(b'%s does not look like a Bazaar repository') % path
75 75 )
76 76 self._parentids = {}
77 77 self._saverev = ui.configbool(b'convert', b'bzr.saverev')
78 78
79 79 def _checkrepotype(self, path):
80 80 # Lightweight checkouts detection is informational but probably
81 81 # fragile at API level. It should not terminate the conversion.
82 82 try:
83 83 dir = bzrdir.BzrDir.open_containing(path.decode())[0]
84 84 try:
85 85 tree = dir.open_workingtree(recommend_upgrade=False)
86 86 branch = tree.branch
87 87 except (errors.NoWorkingTree, errors.NotLocalUrl):
88 88 tree = None
89 89 branch = dir.open_branch()
90 90 if (
91 91 tree is not None
92 92 and tree.controldir.root_transport.base
93 93 != branch.controldir.root_transport.base
94 94 ):
95 95 self.ui.warn(
96 96 _(
97 97 b'warning: lightweight checkouts may cause '
98 98 b'conversion failures, try with a regular '
99 99 b'branch instead.\n'
100 100 )
101 101 )
102 102 except Exception:
103 103 self.ui.note(_(b'bzr source type could not be determined\n'))
104 104
105 105 def before(self):
106 106 """Before the conversion begins, acquire a read lock
107 107 for all the operations that might need it. Fortunately
108 108 read locks don't block other reads or writes to the
109 109 repository, so this shouldn't have any impact on the usage of
110 110 the source repository.
111 111
112 112 The alternative would be locking on every operation that
113 113 needs locks (there are currently two: getting the file and
114 114 getting the parent map) and releasing immediately after,
115 115 but this approach can take even 40% longer."""
116 116 self.sourcerepo.lock_read()
117 117
118 118 def after(self):
119 119 self.sourcerepo.unlock()
120 120
121 121 def _bzrbranches(self):
122 122 return self.sourcerepo.find_branches(using=True)
123 123
124 124 def getheads(self):
125 125 if not self.revs:
126 126 # Set using=True to avoid nested repositories (see issue3254)
127 127 heads = sorted([b.last_revision() for b in self._bzrbranches()])
128 128 else:
129 129 revid = None
130 130 for branch in self._bzrbranches():
131 131 try:
132 132 revspec = self.revs[0].decode()
133 133 r = revisionspec.RevisionSpec.from_string(revspec)
134 134 info = r.in_history(branch)
135 135 except errors.BzrError:
136 136 pass
137 137 revid = info.rev_id
138 138 if revid is None:
139 139 raise error.Abort(
140 140 _(b'%s is not a valid revision') % self.revs[0]
141 141 )
142 142 heads = [revid]
143 143 # Empty repositories return 'null:', which cannot be retrieved
144 144 heads = [h for h in heads if h != b'null:']
145 145 return heads
146 146
147 147 def getfile(self, name, rev):
148 148 name = name.decode()
149 149 revtree = self.sourcerepo.revision_tree(rev)
150 150
151 151 try:
152 152 kind = revtree.kind(name)
153 153 except breezy.errors.NoSuchFile:
154 154 return None, None
155 155 if kind not in supportedkinds:
156 156 # the file is not available anymore - was deleted
157 157 return None, None
158 158 mode = self._modecache[(name.encode(), rev)]
159 159 if kind == 'symlink':
160 160 target = revtree.get_symlink_target(name)
161 161 if target is None:
162 162 raise error.Abort(
163 163 _(b'%s.%s symlink has no target') % (name, rev)
164 164 )
165 165 return target.encode(), mode
166 166 else:
167 167 sio = revtree.get_file(name)
168 168 return sio.read(), mode
169 169
170 170 def getchanges(self, version, full):
171 171 if full:
172 172 raise error.Abort(_(b"convert from cvs does not support --full"))
173 173 self._modecache = {}
174 174 self._revtree = self.sourcerepo.revision_tree(version)
175 175 # get the parentids from the cache
176 176 parentids = self._parentids.pop(version)
177 177 # only diff against first parent id
178 178 prevtree = self.sourcerepo.revision_tree(parentids[0])
179 179 files, changes = self._gettreechanges(self._revtree, prevtree)
180 180 return files, changes, set()
181 181
182 182 def getcommit(self, version):
183 183 rev = self.sourcerepo.get_revision(version)
184 184 # populate parent id cache
185 185 if not rev.parent_ids:
186 186 parents = []
187 187 self._parentids[version] = (revision.NULL_REVISION,)
188 188 else:
189 189 parents = self._filterghosts(rev.parent_ids)
190 190 self._parentids[version] = parents
191 191
192 192 branch = rev.properties.get('branch-nick', 'default')
193 193 if branch == 'trunk':
194 194 branch = 'default'
195 195 return common.commit(
196 196 parents=parents,
197 197 date=b'%d %d' % (rev.timestamp, -rev.timezone),
198 198 author=self.recode(rev.committer),
199 199 desc=self.recode(rev.message),
200 200 branch=branch.encode('utf8'),
201 201 rev=version,
202 202 saverev=self._saverev,
203 203 )
204 204
205 205 def gettags(self):
206 206 bytetags = {}
207 207 for branch in self._bzrbranches():
208 208 if not branch.supports_tags():
209 209 return {}
210 210 tagdict = branch.tags.get_tag_dict()
211 211 for name, rev in tagdict.items():
212 212 bytetags[self.recode(name)] = rev
213 213 return bytetags
214 214
215 215 def getchangedfiles(self, rev, i):
216 216 self._modecache = {}
217 217 curtree = self.sourcerepo.revision_tree(rev)
218 218 if i is not None:
219 219 parentid = self._parentids[rev][i]
220 220 else:
221 221 # no parent id, get the empty revision
222 222 parentid = revision.NULL_REVISION
223 223
224 224 prevtree = self.sourcerepo.revision_tree(parentid)
225 225 changes = [e[0] for e in self._gettreechanges(curtree, prevtree)[0]]
226 226 return changes
227 227
228 228 def _gettreechanges(self, current, origin):
229 229 revid = current._revision_id
230 230 changes = []
231 231 renames = {}
232 232 seen = set()
233 233
234 234 # Fall back to the deprecated attribute for legacy installations.
235 235 try:
236 236 inventory = origin.root_inventory
237 237 except AttributeError:
238 238 inventory = origin.inventory
239 239
240 240 # Process the entries by reverse lexicographic name order to
241 241 # handle nested renames correctly, most specific first.
242 242
243 243 def key(c):
244 244 return c.path[0] or c.path[1] or ""
245 245
246 246 curchanges = sorted(
247 247 current.iter_changes(origin),
248 248 key=key,
249 249 reverse=True,
250 250 )
251 251 for change in curchanges:
252 252 paths = change.path
253 253 kind = change.kind
254 254 executable = change.executable
255 255 if paths[0] == u'' or paths[1] == u'':
256 256 # ignore changes to tree root
257 257 continue
258 258
259 259 # bazaar tracks directories, mercurial does not, so
260 260 # we have to rename the directory contents
261 261 if kind[1] == 'directory':
262 262 if kind[0] not in (None, 'directory'):
263 263 # Replacing 'something' with a directory, record it
264 264 # so it can be removed.
265 265 changes.append((self.recode(paths[0]), revid))
266 266
267 267 if kind[0] == 'directory' and None not in paths:
268 268 renaming = paths[0] != paths[1]
269 269 # neither an add nor an delete - a move
270 270 # rename all directory contents manually
271 271 subdir = inventory.path2id(paths[0])
272 272 # get all child-entries of the directory
273 273 for name, entry in inventory.iter_entries(subdir):
274 274 # hg does not track directory renames
275 275 if entry.kind == 'directory':
276 276 continue
277 277 frompath = self.recode(paths[0] + '/' + name)
278 278 if frompath in seen:
279 279 # Already handled by a more specific change entry
280 280 # This is important when you have:
281 281 # a => b
282 282 # a/c => a/c
283 283 # Here a/c must not be renamed into b/c
284 284 continue
285 285 seen.add(frompath)
286 286 if not renaming:
287 287 continue
288 288 topath = self.recode(paths[1] + '/' + name)
289 289 # register the files as changed
290 290 changes.append((frompath, revid))
291 291 changes.append((topath, revid))
292 292 # add to mode cache
293 293 mode = (
294 294 (entry.executable and b'x')
295 295 or (entry.kind == 'symlink' and b's')
296 296 or b''
297 297 )
298 298 self._modecache[(topath, revid)] = mode
299 299 # register the change as move
300 300 renames[topath] = frompath
301 301
302 302 # no further changes, go to the next change
303 303 continue
304 304
305 305 # we got unicode paths, need to convert them
306 306 path, topath = paths
307 307 if path is not None:
308 308 path = self.recode(path)
309 309 if topath is not None:
310 310 topath = self.recode(topath)
311 311 seen.add(path or topath)
312 312
313 313 if topath is None:
314 314 # file deleted
315 315 changes.append((path, revid))
316 316 continue
317 317
318 318 # renamed
319 319 if path and path != topath:
320 320 renames[topath] = path
321 321 changes.append((path, revid))
322 322
323 323 # populate the mode cache
324 324 kind, executable = [e[1] for e in (kind, executable)]
325 325 mode = (executable and b'x') or (kind == 'symlink' and b'l') or b''
326 326 self._modecache[(topath, revid)] = mode
327 327 changes.append((topath, revid))
328 328
329 329 return changes, renames
330 330
331 331 def _filterghosts(self, ids):
332 332 """Filters out ghost revisions which hg does not support, see
333 333 <http://bazaar-vcs.org/GhostRevision>
334 334 """
335 335 parentmap = self.sourcerepo.get_parent_map(ids)
336 336 parents = tuple([parent for parent in ids if parent in parentmap])
337 337 return parents
@@ -1,100 +1,100 b''
1 1 # highlight.py - highlight extension implementation file
2 2 #
3 3 # Copyright 2007-2009 Adam Hupp <adam@hupp.org> and others
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7 #
8 8 # The original module was split in an interface and an implementation
9 9 # file to defer pygments loading and speedup extension setup.
10 10
11 11
12 12 from mercurial import demandimport
13 13
14 demandimport.IGNORES.update([b'pkgutil', b'pkg_resources', b'__main__'])
14 demandimport.IGNORES.update(['pkgutil', 'pkg_resources', '__main__'])
15 15
16 16 from mercurial import (
17 17 encoding,
18 18 pycompat,
19 19 )
20 20
21 21 from mercurial.utils import stringutil
22 22
23 23 with demandimport.deactivated():
24 24 import pygments
25 25 import pygments.formatters
26 26 import pygments.lexers
27 27 import pygments.plugin
28 28 import pygments.util
29 29
30 30 for unused in pygments.plugin.find_plugin_lexers():
31 31 pass
32 32
33 33 highlight = pygments.highlight
34 34 ClassNotFound = pygments.util.ClassNotFound
35 35 guess_lexer = pygments.lexers.guess_lexer
36 36 guess_lexer_for_filename = pygments.lexers.guess_lexer_for_filename
37 37 TextLexer = pygments.lexers.TextLexer
38 38 HtmlFormatter = pygments.formatters.HtmlFormatter
39 39
40 40 SYNTAX_CSS = (
41 41 b'\n<link rel="stylesheet" href="{url}highlightcss" type="text/css" />'
42 42 )
43 43
44 44
45 45 def pygmentize(field, fctx, style, tmpl, guessfilenameonly=False):
46 46
47 47 # append a <link ...> to the syntax highlighting css
48 48 tmpl.load(b'header')
49 49 old_header = tmpl.cache[b'header']
50 50 if SYNTAX_CSS not in old_header:
51 51 new_header = old_header + SYNTAX_CSS
52 52 tmpl.cache[b'header'] = new_header
53 53
54 54 text = fctx.data()
55 55 if stringutil.binary(text):
56 56 return
57 57
58 58 # str.splitlines() != unicode.splitlines() because "reasons"
59 59 for c in b"\x0c", b"\x1c", b"\x1d", b"\x1e":
60 60 if c in text:
61 61 text = text.replace(c, b'')
62 62
63 63 # Pygments is best used with Unicode strings:
64 64 # <http://pygments.org/docs/unicode/>
65 65 text = text.decode(pycompat.sysstr(encoding.encoding), 'replace')
66 66
67 67 # To get multi-line strings right, we can't format line-by-line
68 68 try:
69 69 path = pycompat.sysstr(fctx.path())
70 70 lexer = guess_lexer_for_filename(path, text[:1024], stripnl=False)
71 71 except (ClassNotFound, ValueError):
72 72 # guess_lexer will return a lexer if *any* lexer matches. There is
73 73 # no way to specify a minimum match score. This can give a high rate of
74 74 # false positives on files with an unknown filename pattern.
75 75 if guessfilenameonly:
76 76 return
77 77
78 78 try:
79 79 lexer = guess_lexer(text[:1024], stripnl=False)
80 80 except (ClassNotFound, ValueError):
81 81 # Don't highlight unknown files
82 82 return
83 83
84 84 # Don't highlight text files
85 85 if isinstance(lexer, TextLexer):
86 86 return
87 87
88 88 formatter = HtmlFormatter(nowrap=True, style=pycompat.sysstr(style))
89 89
90 90 colorized = highlight(text, lexer, formatter)
91 91 coloriter = (
92 92 s.encode(pycompat.sysstr(encoding.encoding), 'replace')
93 93 for s in colorized.splitlines()
94 94 )
95 95
96 96 tmpl._filters[b'colorize'] = lambda x: next(coloriter)
97 97
98 98 oldl = tmpl.cache[field]
99 99 newl = oldl.replace(b'line|escape', b'line|colorize')
100 100 tmpl.cache[field] = newl
General Comments 0
You need to be logged in to leave comments. Login now