mirror of
https://github.com/facebook/sapling.git
synced 2024-10-09 16:31:02 +03:00
1c63f171b5
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
108 lines
3.6 KiB
Python
108 lines
3.6 KiB
Python
# Copyright 2016-present Facebook. All Rights Reserved.
|
|
#
|
|
# support: fastannotate support for hgweb, and filectx
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
from __future__ import absolute_import
|
|
|
|
from mercurial import (
|
|
context as hgcontext,
|
|
extensions,
|
|
hgweb,
|
|
patch,
|
|
util,
|
|
)
|
|
|
|
from . import context
|
|
|
|
class _lazyfctx(object):
|
|
"""delegates to fctx but do not construct fctx when unnecessary"""
|
|
|
|
def __init__(self, repo, node, path):
|
|
self._node = node
|
|
self._path = path
|
|
self._repo = repo
|
|
|
|
def node(self):
|
|
return self._node
|
|
|
|
def path(self):
|
|
return self._path
|
|
|
|
@util.propertycache
|
|
def _fctx(self):
|
|
return context.resolvefctx(self._repo, self._node, self._path)
|
|
|
|
def __getattr__(self, name):
|
|
return getattr(self._fctx, name)
|
|
|
|
def _convertoutputs(repo, annotated, contents):
|
|
"""convert fastannotate outputs to vanilla annotate format"""
|
|
# fastannotate returns: [(nodeid, linenum, path)], [linecontent]
|
|
# convert to what fctx.annotate returns: [((fctx, linenum), linecontent)]
|
|
results = []
|
|
fctxmap = {}
|
|
for i, (hsh, linenum, path) in enumerate(annotated):
|
|
if (hsh, path) not in fctxmap:
|
|
fctxmap[(hsh, path)] = _lazyfctx(repo, hsh, path)
|
|
# linenum: the user wants 1-based, we have 0-based.
|
|
results.append(((fctxmap[(hsh, path)], linenum + 1), contents[i]))
|
|
return results
|
|
|
|
def _doannotate(fctx, follow=True, diffopts=None, ui=None):
|
|
"""like the vanilla fctx.annotate, but do it via fastannotate, and make
|
|
the output format compatible with the vanilla fctx.annotate.
|
|
may raise Exception, and always return line numbers.
|
|
"""
|
|
repo = fctx._repo
|
|
if ui is None:
|
|
ui = repo.ui
|
|
path = fctx._path
|
|
|
|
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
|
|
|
|
aopts = context.annotateopts(diffopts=diffopts, followrename=follow)
|
|
annotated = contents = None
|
|
|
|
with context.annotatecontext(repo, path, aopts) as ac:
|
|
try:
|
|
annotated, contents = ac.annotate(fctx.rev(), master=master,
|
|
showpath=True, showlines=True)
|
|
except Exception:
|
|
ac.rebuild() # try rebuild once
|
|
ui.debug('fastannotate: %s: rebuilding broken cache\n' % path)
|
|
try:
|
|
annotated, contents = ac.annotate(fctx.rev(), master=master,
|
|
showpath=True, showlines=True)
|
|
except Exception:
|
|
raise
|
|
|
|
assert annotated and contents
|
|
return _convertoutputs(repo, annotated, contents)
|
|
|
|
def _hgwebannotate(orig, fctx, ui):
|
|
diffopts = patch.difffeatureopts(ui, untrusted=True,
|
|
section='annotate', whitespace=True)
|
|
return _doannotate(fctx, diffopts=diffopts, ui=ui)
|
|
|
|
def _fctxannotate(orig, self, follow=False, linenumber=False, diffopts=None):
|
|
try:
|
|
return _doannotate(self, follow, diffopts)
|
|
except Exception:
|
|
# fallback to the original method
|
|
return orig(self, follow, linenumber, diffopts)
|
|
|
|
def replacehgwebannotate():
|
|
extensions.wrapfunction(hgweb.webutil, 'annotate', _hgwebannotate)
|
|
|
|
def replacefctxannotate():
|
|
extensions.wrapfunction(hgcontext.basefilectx, 'annotate', _fctxannotate)
|