fastannotate: prefetch cache from server in fctx mode

Summary:
Previously, all prefetching work is done by the "fastannotate" command and
we may replace the "annotate" command with "fastannotate" and we run into
issues dealing with command line option differences.

Now that we have the "fctx" mode, do not redirect "annotate" to
"fastannotate" but wrap "annotate" in a lightweight way so it's responsible
for downloading the annotate cache.

Test Plan: Added a new test case

Reviewers: #sourcecontrol, simonfar

Reviewed By: simonfar

Subscribers: mjpieters

Differential Revision: https://phabricator.intern.facebook.com/D4239607

Signature: t1:4239607:1480447754:a84268a9e64c678c1f275bc04c44a6f4138eafe6
This commit is contained in:
Jun Wu 2016-11-29 11:51:08 +00:00
parent a3dc8b960d
commit 1c63f171b5
4 changed files with 31 additions and 30 deletions

View File

@ -70,8 +70,7 @@ annotate cache greatly. Run "debugbuildlinkrevcache" before
# follow). do not affect "fastannotate" mode. (default: True)
forcefollow = True
# for "fastannotate" mode, use unfiltered repo for better performance. do
# not affect "fctx" mode.
# use unfiltered repo for better performance.
unfilteredrepo = True
# sacrifice correctness in some corner cases for performance. it does not
@ -120,6 +119,7 @@ def uisetup(ui):
elif name == 'fctx':
from . import support
support.replacefctxannotate()
commands.wrapdefault()
else:
raise hgerror.Abort(_('fastannotate: invalid mode: %s') % name)

View File

@ -196,40 +196,27 @@ _knownopts = set([opt[1].replace('-', '_') for opt in
(fastannotatecommandargs['options'] + commands.globalopts)])
def _annotatewrapper(orig, ui, repo, *pats, **opts):
"""use this in extensions.wrapcommand"""
nonemptyopts = set(k for k, v in opts.iteritems() if v)
unknownopts = nonemptyopts.difference(_knownopts)
if opts.get('template', '') not in ['json', '']:
# if -T is used, fastannotate only supports -Tjson
unknownopts.add('template')
if unknownopts:
ui.debug('fastannotate: option %r is not supported, falling back '
'to the original annotate\n' % list(unknownopts))
unsafeopts = _newopts.intersection(nonemptyopts)
if unsafeopts:
raise error.Abort(_('--%s cannot be used together with --%s')
% (list(unknownopts)[0].replace('_', '-'),
list(unsafeopts)[0].replace('_', '-')))
return orig(ui, repo, *pats, **opts)
return fastannotate(ui, repo, *pats, **opts)
"""used by wrapdefault"""
# we need this hack until the obsstore has 0.0 seconds perf impact
if ui.configbool('fastannotate', 'unfilteredrepo', True):
repo = repo.unfiltered()
def _appendoptions(origopts):
"""append our options to the original amend option list"""
for newopt in fastannotatecommandargs['options']:
if any([o[1] == newopt[1] for o in origopts]):
continue
origopts.append(newopt)
_newopts.add(newopt[1].replace('-', '_'))
# check if we need to do prefetch (client-side)
rev = opts.get('rev')
if util.safehasattr(repo, 'prefetchfastannotate') and rev is not None:
paths = list(_matchpaths(repo, rev, pats, opts, aopts=None))
repo.prefetchfastannotate(paths)
return orig(ui, repo, *pats, **opts)
def registercommand():
"""register the fastannotate command"""
name = '^fastannotate|fastblame|fa'
command(name, **fastannotatecommandargs)(fastannotate)
def replacedefault():
"""replace the default annotate command"""
entry = extensions.wrapcommand(commands.table, 'annotate', _annotatewrapper)
_appendoptions(entry[1])
def wrapdefault():
"""wrap the default annotate command, to be aware of the protocol"""
extensions.wrapcommand(commands.table, 'annotate', _annotatewrapper)
@command('debugbuildannotatecache',
[('r', 'rev', '', _('build up to the specific revision'), _('REV'))

View File

@ -61,7 +61,11 @@ def _doannotate(fctx, follow=True, diffopts=None, ui=None):
ui = repo.ui
path = fctx._path
master = ui.config('fastannotate', 'mainbranch') or 'default'
if util.safehasattr(repo, 'prefetchfastannotate'):
# client: do not update annotate cache on its own
master = None
else:
master = ui.config('fastannotate', 'mainbranch') or 'default'
if ui.configbool('fastannotate', 'forcefollow', True):
follow = True

View File

@ -119,6 +119,16 @@ the fastannotate cache is built in both repos, and they are the same
$ diff $p1/a.l $p2/a.l
$ diff $p1/a.m $p2/a.m
in the "fctx" mode with the "annotate" command, the client also downloads the
cache. but not in the (default) "fastannotate" mode.
$ rm $p1/a.l $p1/a.m
$ hg annotate a --debug | grep 'fastannotate: writing'
[1]
$ hg annotate a --config fastannotate.modes=fctx --debug | grep 'fastannotate: writing' | sort
fastannotate: writing 112 bytes to fastannotate/default/a.l
fastannotate: writing 94 bytes to fastannotate/default/a.m
the server would rebuild broken cache automatically
$ cp $p2/a.m $p2/a.m.bak