Mercurial > public > mercurial-scm > hg
comparison hgext/fastannotate/commands.py @ 43077:687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Done with
python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py')
black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**')
# skip-blame mass-reformatting only
Differential Revision: https://phab.mercurial-scm.org/D6972
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:48:39 -0400 |
parents | 2372284d9457 |
children | 4aa72cdf616f |
comparison
equal
deleted
inserted
replaced
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
32 command = registrar.command(cmdtable) | 32 command = registrar.command(cmdtable) |
33 | 33 |
34 | 34 |
35 def _matchpaths(repo, rev, pats, opts, aopts=facontext.defaultopts): | 35 def _matchpaths(repo, rev, pats, opts, aopts=facontext.defaultopts): |
36 """generate paths matching given patterns""" | 36 """generate paths matching given patterns""" |
37 perfhack = repo.ui.configbool('fastannotate', 'perfhack') | 37 perfhack = repo.ui.configbool(b'fastannotate', b'perfhack') |
38 | 38 |
39 # disable perfhack if: | 39 # disable perfhack if: |
40 # a) any walkopt is used | 40 # a) any walkopt is used |
41 # b) if we treat pats as plain file names, some of them do not have | 41 # b) if we treat pats as plain file names, some of them do not have |
42 # corresponding linelog files | 42 # corresponding linelog files |
43 if perfhack: | 43 if perfhack: |
44 # cwd related to reporoot | 44 # cwd related to reporoot |
45 reporoot = os.path.dirname(repo.path) | 45 reporoot = os.path.dirname(repo.path) |
46 reldir = os.path.relpath(encoding.getcwd(), reporoot) | 46 reldir = os.path.relpath(encoding.getcwd(), reporoot) |
47 if reldir == '.': | 47 if reldir == b'.': |
48 reldir = '' | 48 reldir = b'' |
49 if any(opts.get(o[1]) for o in commands.walkopts): # a) | 49 if any(opts.get(o[1]) for o in commands.walkopts): # a) |
50 perfhack = False | 50 perfhack = False |
51 else: # b) | 51 else: # b) |
52 relpats = [ | 52 relpats = [ |
53 os.path.relpath(p, reporoot) if os.path.isabs(p) else p | 53 os.path.relpath(p, reporoot) if os.path.isabs(p) else p |
54 for p in pats | 54 for p in pats |
55 ] | 55 ] |
56 # disable perfhack on '..' since it allows escaping from the repo | 56 # disable perfhack on '..' since it allows escaping from the repo |
57 if any( | 57 if any( |
58 ( | 58 ( |
59 '..' in f | 59 b'..' in f |
60 or not os.path.isfile( | 60 or not os.path.isfile( |
61 facontext.pathhelper(repo, f, aopts).linelogpath | 61 facontext.pathhelper(repo, f, aopts).linelogpath |
62 ) | 62 ) |
63 ) | 63 ) |
64 for f in relpats | 64 for f in relpats |
71 for p in relpats: | 71 for p in relpats: |
72 yield os.path.join(reldir, p) | 72 yield os.path.join(reldir, p) |
73 else: | 73 else: |
74 | 74 |
75 def bad(x, y): | 75 def bad(x, y): |
76 raise error.Abort("%s: %s" % (x, y)) | 76 raise error.Abort(b"%s: %s" % (x, y)) |
77 | 77 |
78 ctx = scmutil.revsingle(repo, rev) | 78 ctx = scmutil.revsingle(repo, rev) |
79 m = scmutil.match(ctx, pats, opts, badfn=bad) | 79 m = scmutil.match(ctx, pats, opts, badfn=bad) |
80 for p in ctx.walk(m): | 80 for p in ctx.walk(m): |
81 yield p | 81 yield p |
82 | 82 |
83 | 83 |
84 fastannotatecommandargs = { | 84 fastannotatecommandargs = { |
85 r'options': [ | 85 r'options': [ |
86 ('r', 'rev', '.', _('annotate the specified revision'), _('REV')), | 86 (b'r', b'rev', b'.', _(b'annotate the specified revision'), _(b'REV')), |
87 ('u', 'user', None, _('list the author (long with -v)')), | 87 (b'u', b'user', None, _(b'list the author (long with -v)')), |
88 ('f', 'file', None, _('list the filename')), | 88 (b'f', b'file', None, _(b'list the filename')), |
89 ('d', 'date', None, _('list the date (short with -q)')), | 89 (b'd', b'date', None, _(b'list the date (short with -q)')), |
90 ('n', 'number', None, _('list the revision number (default)')), | 90 (b'n', b'number', None, _(b'list the revision number (default)')), |
91 ('c', 'changeset', None, _('list the changeset')), | 91 (b'c', b'changeset', None, _(b'list the changeset')), |
92 ( | 92 ( |
93 'l', | 93 b'l', |
94 'line-number', | 94 b'line-number', |
95 None, | 95 None, |
96 _('show line number at the first ' 'appearance'), | 96 _(b'show line number at the first ' b'appearance'), |
97 ), | 97 ), |
98 ('e', 'deleted', None, _('show deleted lines (slow) (EXPERIMENTAL)')), | 98 ( |
99 ('', 'no-content', None, _('do not show file content (EXPERIMENTAL)')), | 99 b'e', |
100 ('', 'no-follow', None, _("don't follow copies and renames")), | 100 b'deleted', |
101 ( | 101 None, |
102 '', | 102 _(b'show deleted lines (slow) (EXPERIMENTAL)'), |
103 'linear', | 103 ), |
104 ( | |
105 b'', | |
106 b'no-content', | |
107 None, | |
108 _(b'do not show file content (EXPERIMENTAL)'), | |
109 ), | |
110 (b'', b'no-follow', None, _(b"don't follow copies and renames")), | |
111 ( | |
112 b'', | |
113 b'linear', | |
104 None, | 114 None, |
105 _( | 115 _( |
106 'enforce linear history, ignore second parent ' | 116 b'enforce linear history, ignore second parent ' |
107 'of merges (EXPERIMENTAL)' | 117 b'of merges (EXPERIMENTAL)' |
108 ), | 118 ), |
109 ), | 119 ), |
110 ('', 'long-hash', None, _('show long changeset hash (EXPERIMENTAL)')), | 120 ( |
111 ( | 121 b'', |
112 '', | 122 b'long-hash', |
113 'rebuild', | 123 None, |
114 None, | 124 _(b'show long changeset hash (EXPERIMENTAL)'), |
115 _('rebuild cache even if it exists ' '(EXPERIMENTAL)'), | 125 ), |
126 ( | |
127 b'', | |
128 b'rebuild', | |
129 None, | |
130 _(b'rebuild cache even if it exists ' b'(EXPERIMENTAL)'), | |
116 ), | 131 ), |
117 ] | 132 ] |
118 + commands.diffwsopts | 133 + commands.diffwsopts |
119 + commands.walkopts | 134 + commands.walkopts |
120 + commands.formatteropts, | 135 + commands.formatteropts, |
121 r'synopsis': _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'), | 136 r'synopsis': _(b'[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'), |
122 r'inferrepo': True, | 137 r'inferrepo': True, |
123 } | 138 } |
124 | 139 |
125 | 140 |
126 def fastannotate(ui, repo, *pats, **opts): | 141 def fastannotate(ui, repo, *pats, **opts): |
153 repo, avoid --linear, --no-follow, or any diff options. As the server | 168 repo, avoid --linear, --no-follow, or any diff options. As the server |
154 won't be able to populate annotate cache when non-default options | 169 won't be able to populate annotate cache when non-default options |
155 affecting results are used. | 170 affecting results are used. |
156 """ | 171 """ |
157 if not pats: | 172 if not pats: |
158 raise error.Abort(_('at least one filename or pattern is required')) | 173 raise error.Abort(_(b'at least one filename or pattern is required')) |
159 | 174 |
160 # performance hack: filtered repo can be slow. unfilter by default. | 175 # performance hack: filtered repo can be slow. unfilter by default. |
161 if ui.configbool('fastannotate', 'unfilteredrepo'): | 176 if ui.configbool(b'fastannotate', b'unfilteredrepo'): |
162 repo = repo.unfiltered() | 177 repo = repo.unfiltered() |
163 | 178 |
164 opts = pycompat.byteskwargs(opts) | 179 opts = pycompat.byteskwargs(opts) |
165 | 180 |
166 rev = opts.get('rev', '.') | 181 rev = opts.get(b'rev', b'.') |
167 rebuild = opts.get('rebuild', False) | 182 rebuild = opts.get(b'rebuild', False) |
168 | 183 |
169 diffopts = patch.difffeatureopts( | 184 diffopts = patch.difffeatureopts( |
170 ui, opts, section='annotate', whitespace=True | 185 ui, opts, section=b'annotate', whitespace=True |
171 ) | 186 ) |
172 aopts = facontext.annotateopts( | 187 aopts = facontext.annotateopts( |
173 diffopts=diffopts, | 188 diffopts=diffopts, |
174 followmerge=not opts.get('linear', False), | 189 followmerge=not opts.get(b'linear', False), |
175 followrename=not opts.get('no_follow', False), | 190 followrename=not opts.get(b'no_follow', False), |
176 ) | 191 ) |
177 | 192 |
178 if not any( | 193 if not any( |
179 opts.get(s) for s in ['user', 'date', 'file', 'number', 'changeset'] | 194 opts.get(s) |
195 for s in [b'user', b'date', b'file', b'number', b'changeset'] | |
180 ): | 196 ): |
181 # default 'number' for compatibility. but fastannotate is more | 197 # default 'number' for compatibility. but fastannotate is more |
182 # efficient with "changeset", "line-number" and "no-content". | 198 # efficient with "changeset", "line-number" and "no-content". |
183 for name in ui.configlist('fastannotate', 'defaultformat', ['number']): | 199 for name in ui.configlist( |
200 b'fastannotate', b'defaultformat', [b'number'] | |
201 ): | |
184 opts[name] = True | 202 opts[name] = True |
185 | 203 |
186 ui.pager('fastannotate') | 204 ui.pager(b'fastannotate') |
187 template = opts.get('template') | 205 template = opts.get(b'template') |
188 if template == 'json': | 206 if template == b'json': |
189 formatter = faformatter.jsonformatter(ui, repo, opts) | 207 formatter = faformatter.jsonformatter(ui, repo, opts) |
190 else: | 208 else: |
191 formatter = faformatter.defaultformatter(ui, repo, opts) | 209 formatter = faformatter.defaultformatter(ui, repo, opts) |
192 showdeleted = opts.get('deleted', False) | 210 showdeleted = opts.get(b'deleted', False) |
193 showlines = not bool(opts.get('no_content')) | 211 showlines = not bool(opts.get(b'no_content')) |
194 showpath = opts.get('file', False) | 212 showpath = opts.get(b'file', False) |
195 | 213 |
196 # find the head of the main (master) branch | 214 # find the head of the main (master) branch |
197 master = ui.config('fastannotate', 'mainbranch') or rev | 215 master = ui.config(b'fastannotate', b'mainbranch') or rev |
198 | 216 |
199 # paths will be used for prefetching and the real annotating | 217 # paths will be used for prefetching and the real annotating |
200 paths = list(_matchpaths(repo, rev, pats, opts, aopts)) | 218 paths = list(_matchpaths(repo, rev, pats, opts, aopts)) |
201 | 219 |
202 # for client, prefetch from the server | 220 # for client, prefetch from the server |
203 if util.safehasattr(repo, 'prefetchfastannotate'): | 221 if util.safehasattr(repo, b'prefetchfastannotate'): |
204 repo.prefetchfastannotate(paths) | 222 repo.prefetchfastannotate(paths) |
205 | 223 |
206 for path in paths: | 224 for path in paths: |
207 result = lines = existinglines = None | 225 result = lines = existinglines = None |
208 while True: | 226 while True: |
236 formatter.end() | 254 formatter.end() |
237 | 255 |
238 | 256 |
239 _newopts = set() | 257 _newopts = set() |
240 _knownopts = { | 258 _knownopts = { |
241 opt[1].replace('-', '_') | 259 opt[1].replace(b'-', b'_') |
242 for opt in (fastannotatecommandargs[r'options'] + commands.globalopts) | 260 for opt in (fastannotatecommandargs[r'options'] + commands.globalopts) |
243 } | 261 } |
244 | 262 |
245 | 263 |
246 def _annotatewrapper(orig, ui, repo, *pats, **opts): | 264 def _annotatewrapper(orig, ui, repo, *pats, **opts): |
247 """used by wrapdefault""" | 265 """used by wrapdefault""" |
248 # we need this hack until the obsstore has 0.0 seconds perf impact | 266 # we need this hack until the obsstore has 0.0 seconds perf impact |
249 if ui.configbool('fastannotate', 'unfilteredrepo'): | 267 if ui.configbool(b'fastannotate', b'unfilteredrepo'): |
250 repo = repo.unfiltered() | 268 repo = repo.unfiltered() |
251 | 269 |
252 # treat the file as text (skip the isbinary check) | 270 # treat the file as text (skip the isbinary check) |
253 if ui.configbool('fastannotate', 'forcetext'): | 271 if ui.configbool(b'fastannotate', b'forcetext'): |
254 opts[r'text'] = True | 272 opts[r'text'] = True |
255 | 273 |
256 # check if we need to do prefetch (client-side) | 274 # check if we need to do prefetch (client-side) |
257 rev = opts.get(r'rev') | 275 rev = opts.get(r'rev') |
258 if util.safehasattr(repo, 'prefetchfastannotate') and rev is not None: | 276 if util.safehasattr(repo, b'prefetchfastannotate') and rev is not None: |
259 paths = list(_matchpaths(repo, rev, pats, pycompat.byteskwargs(opts))) | 277 paths = list(_matchpaths(repo, rev, pats, pycompat.byteskwargs(opts))) |
260 repo.prefetchfastannotate(paths) | 278 repo.prefetchfastannotate(paths) |
261 | 279 |
262 return orig(ui, repo, *pats, **opts) | 280 return orig(ui, repo, *pats, **opts) |
263 | 281 |
264 | 282 |
265 def registercommand(): | 283 def registercommand(): |
266 """register the fastannotate command""" | 284 """register the fastannotate command""" |
267 name = 'fastannotate|fastblame|fa' | 285 name = b'fastannotate|fastblame|fa' |
268 command(name, helpbasic=True, **fastannotatecommandargs)(fastannotate) | 286 command(name, helpbasic=True, **fastannotatecommandargs)(fastannotate) |
269 | 287 |
270 | 288 |
271 def wrapdefault(): | 289 def wrapdefault(): |
272 """wrap the default annotate command, to be aware of the protocol""" | 290 """wrap the default annotate command, to be aware of the protocol""" |
273 extensions.wrapcommand(commands.table, 'annotate', _annotatewrapper) | 291 extensions.wrapcommand(commands.table, b'annotate', _annotatewrapper) |
274 | 292 |
275 | 293 |
276 @command( | 294 @command( |
277 'debugbuildannotatecache', | 295 b'debugbuildannotatecache', |
278 [('r', 'rev', '', _('build up to the specific revision'), _('REV'))] | 296 [(b'r', b'rev', b'', _(b'build up to the specific revision'), _(b'REV'))] |
279 + commands.walkopts, | 297 + commands.walkopts, |
280 _('[-r REV] FILE...'), | 298 _(b'[-r REV] FILE...'), |
281 ) | 299 ) |
282 def debugbuildannotatecache(ui, repo, *pats, **opts): | 300 def debugbuildannotatecache(ui, repo, *pats, **opts): |
283 """incrementally build fastannotate cache up to REV for specified files | 301 """incrementally build fastannotate cache up to REV for specified files |
284 | 302 |
285 If REV is not specified, use the config 'fastannotate.mainbranch'. | 303 If REV is not specified, use the config 'fastannotate.mainbranch'. |
289 | 307 |
290 The annotate cache will be built using the default diff and follow | 308 The annotate cache will be built using the default diff and follow |
291 options and lives in '.hg/fastannotate/default'. | 309 options and lives in '.hg/fastannotate/default'. |
292 """ | 310 """ |
293 opts = pycompat.byteskwargs(opts) | 311 opts = pycompat.byteskwargs(opts) |
294 rev = opts.get('REV') or ui.config('fastannotate', 'mainbranch') | 312 rev = opts.get(b'REV') or ui.config(b'fastannotate', b'mainbranch') |
295 if not rev: | 313 if not rev: |
296 raise error.Abort( | 314 raise error.Abort( |
297 _('you need to provide a revision'), | 315 _(b'you need to provide a revision'), |
298 hint=_('set fastannotate.mainbranch or use --rev'), | 316 hint=_(b'set fastannotate.mainbranch or use --rev'), |
299 ) | 317 ) |
300 if ui.configbool('fastannotate', 'unfilteredrepo'): | 318 if ui.configbool(b'fastannotate', b'unfilteredrepo'): |
301 repo = repo.unfiltered() | 319 repo = repo.unfiltered() |
302 ctx = scmutil.revsingle(repo, rev) | 320 ctx = scmutil.revsingle(repo, rev) |
303 m = scmutil.match(ctx, pats, opts) | 321 m = scmutil.match(ctx, pats, opts) |
304 paths = list(ctx.walk(m)) | 322 paths = list(ctx.walk(m)) |
305 if util.safehasattr(repo, 'prefetchfastannotate'): | 323 if util.safehasattr(repo, b'prefetchfastannotate'): |
306 # client | 324 # client |
307 if opts.get('REV'): | 325 if opts.get(b'REV'): |
308 raise error.Abort(_('--rev cannot be used for client')) | 326 raise error.Abort(_(b'--rev cannot be used for client')) |
309 repo.prefetchfastannotate(paths) | 327 repo.prefetchfastannotate(paths) |
310 else: | 328 else: |
311 # server, or full repo | 329 # server, or full repo |
312 progress = ui.makeprogress(_('building'), total=len(paths)) | 330 progress = ui.makeprogress(_(b'building'), total=len(paths)) |
313 for i, path in enumerate(paths): | 331 for i, path in enumerate(paths): |
314 progress.update(i) | 332 progress.update(i) |
315 with facontext.annotatecontext(repo, path) as actx: | 333 with facontext.annotatecontext(repo, path) as actx: |
316 try: | 334 try: |
317 if actx.isuptodate(rev): | 335 if actx.isuptodate(rev): |
319 actx.annotate(rev, rev) | 337 actx.annotate(rev, rev) |
320 except (faerror.CannotReuseError, faerror.CorruptedFileError): | 338 except (faerror.CannotReuseError, faerror.CorruptedFileError): |
321 # the cache is broken (could happen with renaming so the | 339 # the cache is broken (could happen with renaming so the |
322 # file history gets invalidated). rebuild and try again. | 340 # file history gets invalidated). rebuild and try again. |
323 ui.debug( | 341 ui.debug( |
324 'fastannotate: %s: rebuilding broken cache\n' % path | 342 b'fastannotate: %s: rebuilding broken cache\n' % path |
325 ) | 343 ) |
326 actx.rebuild() | 344 actx.rebuild() |
327 try: | 345 try: |
328 actx.annotate(rev, rev) | 346 actx.annotate(rev, rev) |
329 except Exception as ex: | 347 except Exception as ex: |
330 # possibly a bug, but should not stop us from building | 348 # possibly a bug, but should not stop us from building |
331 # cache for other files. | 349 # cache for other files. |
332 ui.warn( | 350 ui.warn( |
333 _( | 351 _( |
334 'fastannotate: %s: failed to ' | 352 b'fastannotate: %s: failed to ' |
335 'build cache: %r\n' | 353 b'build cache: %r\n' |
336 ) | 354 ) |
337 % (path, ex) | 355 % (path, ex) |
338 ) | 356 ) |
339 progress.complete() | 357 progress.complete() |