Mercurial > hg
comparison hgext/fastannotate/commands.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | 566daffc607d |
children | 687b865b95ad |
comparison
equal
deleted
inserted
replaced
43075:57875cf423c9 | 43076:2372284d9457 |
---|---|
29 ) | 29 ) |
30 | 30 |
31 cmdtable = {} | 31 cmdtable = {} |
32 command = registrar.command(cmdtable) | 32 command = registrar.command(cmdtable) |
33 | 33 |
34 | |
34 def _matchpaths(repo, rev, pats, opts, aopts=facontext.defaultopts): | 35 def _matchpaths(repo, rev, pats, opts, aopts=facontext.defaultopts): |
35 """generate paths matching given patterns""" | 36 """generate paths matching given patterns""" |
36 perfhack = repo.ui.configbool('fastannotate', 'perfhack') | 37 perfhack = repo.ui.configbool('fastannotate', 'perfhack') |
37 | 38 |
38 # disable perfhack if: | 39 # disable perfhack if: |
43 # cwd related to reporoot | 44 # cwd related to reporoot |
44 reporoot = os.path.dirname(repo.path) | 45 reporoot = os.path.dirname(repo.path) |
45 reldir = os.path.relpath(encoding.getcwd(), reporoot) | 46 reldir = os.path.relpath(encoding.getcwd(), reporoot) |
46 if reldir == '.': | 47 if reldir == '.': |
47 reldir = '' | 48 reldir = '' |
48 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) |
49 perfhack = False | 50 perfhack = False |
50 else: # b) | 51 else: # b) |
51 relpats = [os.path.relpath(p, reporoot) if os.path.isabs(p) else p | 52 relpats = [ |
52 for p in pats] | 53 os.path.relpath(p, reporoot) if os.path.isabs(p) else p |
54 for p in pats | |
55 ] | |
53 # disable perfhack on '..' since it allows escaping from the repo | 56 # disable perfhack on '..' since it allows escaping from the repo |
54 if any(('..' in f or | 57 if any( |
55 not os.path.isfile( | 58 ( |
56 facontext.pathhelper(repo, f, aopts).linelogpath)) | 59 '..' in f |
57 for f in relpats): | 60 or not os.path.isfile( |
61 facontext.pathhelper(repo, f, aopts).linelogpath | |
62 ) | |
63 ) | |
64 for f in relpats | |
65 ): | |
58 perfhack = False | 66 perfhack = False |
59 | 67 |
60 # perfhack: emit paths directory without checking with manifest | 68 # perfhack: emit paths directory without checking with manifest |
61 # this can be incorrect if the rev dos not have file. | 69 # this can be incorrect if the rev dos not have file. |
62 if perfhack: | 70 if perfhack: |
63 for p in relpats: | 71 for p in relpats: |
64 yield os.path.join(reldir, p) | 72 yield os.path.join(reldir, p) |
65 else: | 73 else: |
74 | |
66 def bad(x, y): | 75 def bad(x, y): |
67 raise error.Abort("%s: %s" % (x, y)) | 76 raise error.Abort("%s: %s" % (x, y)) |
77 | |
68 ctx = scmutil.revsingle(repo, rev) | 78 ctx = scmutil.revsingle(repo, rev) |
69 m = scmutil.match(ctx, pats, opts, badfn=bad) | 79 m = scmutil.match(ctx, pats, opts, badfn=bad) |
70 for p in ctx.walk(m): | 80 for p in ctx.walk(m): |
71 yield p | 81 yield p |
82 | |
72 | 83 |
73 fastannotatecommandargs = { | 84 fastannotatecommandargs = { |
74 r'options': [ | 85 r'options': [ |
75 ('r', 'rev', '.', _('annotate the specified revision'), _('REV')), | 86 ('r', 'rev', '.', _('annotate the specified revision'), _('REV')), |
76 ('u', 'user', None, _('list the author (long with -v)')), | 87 ('u', 'user', None, _('list the author (long with -v)')), |
77 ('f', 'file', None, _('list the filename')), | 88 ('f', 'file', None, _('list the filename')), |
78 ('d', 'date', None, _('list the date (short with -q)')), | 89 ('d', 'date', None, _('list the date (short with -q)')), |
79 ('n', 'number', None, _('list the revision number (default)')), | 90 ('n', 'number', None, _('list the revision number (default)')), |
80 ('c', 'changeset', None, _('list the changeset')), | 91 ('c', 'changeset', None, _('list the changeset')), |
81 ('l', 'line-number', None, _('show line number at the first ' | 92 ( |
82 'appearance')), | 93 'l', |
94 'line-number', | |
95 None, | |
96 _('show line number at the first ' 'appearance'), | |
97 ), | |
83 ('e', 'deleted', None, _('show deleted lines (slow) (EXPERIMENTAL)')), | 98 ('e', 'deleted', None, _('show deleted lines (slow) (EXPERIMENTAL)')), |
84 ('', 'no-content', None, _('do not show file content (EXPERIMENTAL)')), | 99 ('', 'no-content', None, _('do not show file content (EXPERIMENTAL)')), |
85 ('', 'no-follow', None, _("don't follow copies and renames")), | 100 ('', 'no-follow', None, _("don't follow copies and renames")), |
86 ('', 'linear', None, _('enforce linear history, ignore second parent ' | 101 ( |
87 'of merges (EXPERIMENTAL)')), | 102 '', |
103 'linear', | |
104 None, | |
105 _( | |
106 'enforce linear history, ignore second parent ' | |
107 'of merges (EXPERIMENTAL)' | |
108 ), | |
109 ), | |
88 ('', 'long-hash', None, _('show long changeset hash (EXPERIMENTAL)')), | 110 ('', 'long-hash', None, _('show long changeset hash (EXPERIMENTAL)')), |
89 ('', 'rebuild', None, _('rebuild cache even if it exists ' | 111 ( |
90 '(EXPERIMENTAL)')), | 112 '', |
91 ] + commands.diffwsopts + commands.walkopts + commands.formatteropts, | 113 'rebuild', |
114 None, | |
115 _('rebuild cache even if it exists ' '(EXPERIMENTAL)'), | |
116 ), | |
117 ] | |
118 + commands.diffwsopts | |
119 + commands.walkopts | |
120 + commands.formatteropts, | |
92 r'synopsis': _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'), | 121 r'synopsis': _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'), |
93 r'inferrepo': True, | 122 r'inferrepo': True, |
94 } | 123 } |
124 | |
95 | 125 |
96 def fastannotate(ui, repo, *pats, **opts): | 126 def fastannotate(ui, repo, *pats, **opts): |
97 """show changeset information by line for each file | 127 """show changeset information by line for each file |
98 | 128 |
99 List changes in files, showing the revision id responsible for each line. | 129 List changes in files, showing the revision id responsible for each line. |
134 opts = pycompat.byteskwargs(opts) | 164 opts = pycompat.byteskwargs(opts) |
135 | 165 |
136 rev = opts.get('rev', '.') | 166 rev = opts.get('rev', '.') |
137 rebuild = opts.get('rebuild', False) | 167 rebuild = opts.get('rebuild', False) |
138 | 168 |
139 diffopts = patch.difffeatureopts(ui, opts, section='annotate', | 169 diffopts = patch.difffeatureopts( |
140 whitespace=True) | 170 ui, opts, section='annotate', whitespace=True |
171 ) | |
141 aopts = facontext.annotateopts( | 172 aopts = facontext.annotateopts( |
142 diffopts=diffopts, | 173 diffopts=diffopts, |
143 followmerge=not opts.get('linear', False), | 174 followmerge=not opts.get('linear', False), |
144 followrename=not opts.get('no_follow', False)) | 175 followrename=not opts.get('no_follow', False), |
145 | 176 ) |
146 if not any(opts.get(s) | 177 |
147 for s in ['user', 'date', 'file', 'number', 'changeset']): | 178 if not any( |
179 opts.get(s) for s in ['user', 'date', 'file', 'number', 'changeset'] | |
180 ): | |
148 # default 'number' for compatibility. but fastannotate is more | 181 # default 'number' for compatibility. but fastannotate is more |
149 # efficient with "changeset", "line-number" and "no-content". | 182 # efficient with "changeset", "line-number" and "no-content". |
150 for name in ui.configlist('fastannotate', 'defaultformat', ['number']): | 183 for name in ui.configlist('fastannotate', 'defaultformat', ['number']): |
151 opts[name] = True | 184 opts[name] = True |
152 | 185 |
173 for path in paths: | 206 for path in paths: |
174 result = lines = existinglines = None | 207 result = lines = existinglines = None |
175 while True: | 208 while True: |
176 try: | 209 try: |
177 with facontext.annotatecontext(repo, path, aopts, rebuild) as a: | 210 with facontext.annotatecontext(repo, path, aopts, rebuild) as a: |
178 result = a.annotate(rev, master=master, showpath=showpath, | 211 result = a.annotate( |
179 showlines=(showlines and | 212 rev, |
180 not showdeleted)) | 213 master=master, |
214 showpath=showpath, | |
215 showlines=(showlines and not showdeleted), | |
216 ) | |
181 if showdeleted: | 217 if showdeleted: |
182 existinglines = set((l[0], l[1]) for l in result) | 218 existinglines = set((l[0], l[1]) for l in result) |
183 result = a.annotatealllines( | 219 result = a.annotatealllines( |
184 rev, showpath=showpath, showlines=showlines) | 220 rev, showpath=showpath, showlines=showlines |
221 ) | |
185 break | 222 break |
186 except (faerror.CannotReuseError, faerror.CorruptedFileError): | 223 except (faerror.CannotReuseError, faerror.CorruptedFileError): |
187 # happens if master moves backwards, or the file was deleted | 224 # happens if master moves backwards, or the file was deleted |
188 # and readded, or renamed to an existing name, or corrupted. | 225 # and readded, or renamed to an existing name, or corrupted. |
189 if rebuild: # give up since we have tried rebuild already | 226 if rebuild: # give up since we have tried rebuild already |
190 raise | 227 raise |
191 else: # try a second time rebuilding the cache (slow) | 228 else: # try a second time rebuilding the cache (slow) |
192 rebuild = True | 229 rebuild = True |
193 continue | 230 continue |
194 | 231 |
195 if showlines: | 232 if showlines: |
196 result, lines = result | 233 result, lines = result |
197 | 234 |
198 formatter.write(result, lines, existinglines=existinglines) | 235 formatter.write(result, lines, existinglines=existinglines) |
199 formatter.end() | 236 formatter.end() |
200 | 237 |
238 | |
201 _newopts = set() | 239 _newopts = set() |
202 _knownopts = {opt[1].replace('-', '_') for opt in | 240 _knownopts = { |
203 (fastannotatecommandargs[r'options'] + commands.globalopts)} | 241 opt[1].replace('-', '_') |
242 for opt in (fastannotatecommandargs[r'options'] + commands.globalopts) | |
243 } | |
244 | |
204 | 245 |
205 def _annotatewrapper(orig, ui, repo, *pats, **opts): | 246 def _annotatewrapper(orig, ui, repo, *pats, **opts): |
206 """used by wrapdefault""" | 247 """used by wrapdefault""" |
207 # we need this hack until the obsstore has 0.0 seconds perf impact | 248 # we need this hack until the obsstore has 0.0 seconds perf impact |
208 if ui.configbool('fastannotate', 'unfilteredrepo'): | 249 if ui.configbool('fastannotate', 'unfilteredrepo'): |
218 paths = list(_matchpaths(repo, rev, pats, pycompat.byteskwargs(opts))) | 259 paths = list(_matchpaths(repo, rev, pats, pycompat.byteskwargs(opts))) |
219 repo.prefetchfastannotate(paths) | 260 repo.prefetchfastannotate(paths) |
220 | 261 |
221 return orig(ui, repo, *pats, **opts) | 262 return orig(ui, repo, *pats, **opts) |
222 | 263 |
264 | |
223 def registercommand(): | 265 def registercommand(): |
224 """register the fastannotate command""" | 266 """register the fastannotate command""" |
225 name = 'fastannotate|fastblame|fa' | 267 name = 'fastannotate|fastblame|fa' |
226 command(name, helpbasic=True, **fastannotatecommandargs)(fastannotate) | 268 command(name, helpbasic=True, **fastannotatecommandargs)(fastannotate) |
227 | 269 |
270 | |
228 def wrapdefault(): | 271 def wrapdefault(): |
229 """wrap the default annotate command, to be aware of the protocol""" | 272 """wrap the default annotate command, to be aware of the protocol""" |
230 extensions.wrapcommand(commands.table, 'annotate', _annotatewrapper) | 273 extensions.wrapcommand(commands.table, 'annotate', _annotatewrapper) |
231 | 274 |
232 @command('debugbuildannotatecache', | 275 |
233 [('r', 'rev', '', _('build up to the specific revision'), _('REV')) | 276 @command( |
234 ] + commands.walkopts, | 277 'debugbuildannotatecache', |
235 _('[-r REV] FILE...')) | 278 [('r', 'rev', '', _('build up to the specific revision'), _('REV'))] |
279 + commands.walkopts, | |
280 _('[-r REV] FILE...'), | |
281 ) | |
236 def debugbuildannotatecache(ui, repo, *pats, **opts): | 282 def debugbuildannotatecache(ui, repo, *pats, **opts): |
237 """incrementally build fastannotate cache up to REV for specified files | 283 """incrementally build fastannotate cache up to REV for specified files |
238 | 284 |
239 If REV is not specified, use the config 'fastannotate.mainbranch'. | 285 If REV is not specified, use the config 'fastannotate.mainbranch'. |
240 | 286 |
245 options and lives in '.hg/fastannotate/default'. | 291 options and lives in '.hg/fastannotate/default'. |
246 """ | 292 """ |
247 opts = pycompat.byteskwargs(opts) | 293 opts = pycompat.byteskwargs(opts) |
248 rev = opts.get('REV') or ui.config('fastannotate', 'mainbranch') | 294 rev = opts.get('REV') or ui.config('fastannotate', 'mainbranch') |
249 if not rev: | 295 if not rev: |
250 raise error.Abort(_('you need to provide a revision'), | 296 raise error.Abort( |
251 hint=_('set fastannotate.mainbranch or use --rev')) | 297 _('you need to provide a revision'), |
298 hint=_('set fastannotate.mainbranch or use --rev'), | |
299 ) | |
252 if ui.configbool('fastannotate', 'unfilteredrepo'): | 300 if ui.configbool('fastannotate', 'unfilteredrepo'): |
253 repo = repo.unfiltered() | 301 repo = repo.unfiltered() |
254 ctx = scmutil.revsingle(repo, rev) | 302 ctx = scmutil.revsingle(repo, rev) |
255 m = scmutil.match(ctx, pats, opts) | 303 m = scmutil.match(ctx, pats, opts) |
256 paths = list(ctx.walk(m)) | 304 paths = list(ctx.walk(m)) |
270 continue | 318 continue |
271 actx.annotate(rev, rev) | 319 actx.annotate(rev, rev) |
272 except (faerror.CannotReuseError, faerror.CorruptedFileError): | 320 except (faerror.CannotReuseError, faerror.CorruptedFileError): |
273 # the cache is broken (could happen with renaming so the | 321 # the cache is broken (could happen with renaming so the |
274 # file history gets invalidated). rebuild and try again. | 322 # file history gets invalidated). rebuild and try again. |
275 ui.debug('fastannotate: %s: rebuilding broken cache\n' | 323 ui.debug( |
276 % path) | 324 'fastannotate: %s: rebuilding broken cache\n' % path |
325 ) | |
277 actx.rebuild() | 326 actx.rebuild() |
278 try: | 327 try: |
279 actx.annotate(rev, rev) | 328 actx.annotate(rev, rev) |
280 except Exception as ex: | 329 except Exception as ex: |
281 # possibly a bug, but should not stop us from building | 330 # possibly a bug, but should not stop us from building |
282 # cache for other files. | 331 # cache for other files. |
283 ui.warn(_('fastannotate: %s: failed to ' | 332 ui.warn( |
284 'build cache: %r\n') % (path, ex)) | 333 _( |
334 'fastannotate: %s: failed to ' | |
335 'build cache: %r\n' | |
336 ) | |
337 % (path, ex) | |
338 ) | |
285 progress.complete() | 339 progress.complete() |