wireproto: separate commands tables for version 1 and 2 commands
We can't easily reuse existing command handlers for version 2
commands because the response types will be different. e.g. many
commands return nodes encoded as hex. Our new wire protocol is
binary safe, so we'll wish to encode nodes as binary.
We /could/ teach each command handler to look at the protocol
handler and change behavior based on the version in use. However,
this would make logic a bit unwieldy over time and would make
it harder to design a unified protocol handler interface. I think
it's better to create a clean break between version 1 and version 2
of commands on the server.
What I imagine happening is we will have separate @wireprotocommand
functions for each protocol generation. Those functions will parse the
request, dispatch to a common function to process it, then generate
the response in its own, transport-specific manner.
This commit establishes a separate table for tracking version 1
commands from version 2 commands. The HTTP server pieces have been
updated to use this new table.
Most commands are marked as both version 1 and version 2, so there is
little practical impact to this change.
A side-effect of this change is we now rely on transport registration
in wireprototypes.TRANSPORTS and certain properties of the protocol
interface. So a test had to be updated to conform.
Differential Revision: https://phab.mercurial-scm.org/D2982
"""test behavior of propertycache and unfiltered propertycache
The repoview overlay is quite complex. We test the behavior of
property cache of both localrepo and repoview to prevent
regression."""
from __future__ import absolute_import, print_function
import os
import subprocess
from mercurial import (
hg,
localrepo,
ui as uimod,
util,
)
# create some special property cache that trace they call
calllog = []
@util.propertycache
def testcachedfoobar(repo):
name = repo.filtername
if name is None:
name = ''
val = len(name)
calllog.append(val)
return val
unficalllog = []
@localrepo.unfilteredpropertycache
def testcachedunfifoobar(repo):
name = repo.filtername
if name is None:
name = ''
val = 100 + len(name)
unficalllog.append(val)
return val
#plug them on repo
localrepo.localrepository.testcachedfoobar = testcachedfoobar
localrepo.localrepository.testcachedunfifoobar = testcachedunfifoobar
# Create an empty repo and instantiate it. It is important to run
# these tests on the real object to detect regression.
repopath = os.path.join(os.environ['TESTTMP'], 'repo')
assert subprocess.call(['hg', 'init', repopath]) == 0
ui = uimod.ui.load()
repo = hg.repository(ui, path=repopath).unfiltered()
print('')
print('=== property cache ===')
print('')
print('calllog:', calllog)
print('cached value (unfiltered):',
vars(repo).get('testcachedfoobar', 'NOCACHE'))
print('')
print('= first access on unfiltered, should do a call')
print('access:', repo.testcachedfoobar)
print('calllog:', calllog)
print('cached value (unfiltered):',
vars(repo).get('testcachedfoobar', 'NOCACHE'))
print('')
print('= second access on unfiltered, should not do call')
print('access', repo.testcachedfoobar)
print('calllog:', calllog)
print('cached value (unfiltered):',
vars(repo).get('testcachedfoobar', 'NOCACHE'))
print('')
print('= first access on "visible" view, should do a call')
visibleview = repo.filtered('visible')
print('cached value ("visible" view):',
vars(visibleview).get('testcachedfoobar', 'NOCACHE'))
print('access:', visibleview.testcachedfoobar)
print('calllog:', calllog)
print('cached value (unfiltered):',
vars(repo).get('testcachedfoobar', 'NOCACHE'))
print('cached value ("visible" view):',
vars(visibleview).get('testcachedfoobar', 'NOCACHE'))
print('')
print('= second access on "visible view", should not do call')
print('access:', visibleview.testcachedfoobar)
print('calllog:', calllog)
print('cached value (unfiltered):',
vars(repo).get('testcachedfoobar', 'NOCACHE'))
print('cached value ("visible" view):',
vars(visibleview).get('testcachedfoobar', 'NOCACHE'))
print('')
print('= no effect on other view')
immutableview = repo.filtered('immutable')
print('cached value ("immutable" view):',
vars(immutableview).get('testcachedfoobar', 'NOCACHE'))
print('access:', immutableview.testcachedfoobar)
print('calllog:', calllog)
print('cached value (unfiltered):',
vars(repo).get('testcachedfoobar', 'NOCACHE'))
print('cached value ("visible" view):',
vars(visibleview).get('testcachedfoobar', 'NOCACHE'))
print('cached value ("immutable" view):',
vars(immutableview).get('testcachedfoobar', 'NOCACHE'))
# unfiltered property cache test
print('')
print('')
print('=== unfiltered property cache ===')
print('')
print('unficalllog:', unficalllog)
print('cached value (unfiltered): ',
vars(repo).get('testcachedunfifoobar', 'NOCACHE'))
print('cached value ("visible" view): ',
vars(visibleview).get('testcachedunfifoobar', 'NOCACHE'))
print('cached value ("immutable" view):',
vars(immutableview).get('testcachedunfifoobar', 'NOCACHE'))
print('')
print('= first access on unfiltered, should do a call')
print('access (unfiltered):', repo.testcachedunfifoobar)
print('unficalllog:', unficalllog)
print('cached value (unfiltered): ',
vars(repo).get('testcachedunfifoobar', 'NOCACHE'))
print('')
print('= second access on unfiltered, should not do call')
print('access (unfiltered):', repo.testcachedunfifoobar)
print('unficalllog:', unficalllog)
print('cached value (unfiltered): ',
vars(repo).get('testcachedunfifoobar', 'NOCACHE'))
print('')
print('= access on view should use the unfiltered cache')
print('access (unfiltered): ', repo.testcachedunfifoobar)
print('access ("visible" view): ', visibleview.testcachedunfifoobar)
print('access ("immutable" view):', immutableview.testcachedunfifoobar)
print('unficalllog:', unficalllog)
print('cached value (unfiltered): ',
vars(repo).get('testcachedunfifoobar', 'NOCACHE'))
print('cached value ("visible" view): ',
vars(visibleview).get('testcachedunfifoobar', 'NOCACHE'))
print('cached value ("immutable" view):',
vars(immutableview).get('testcachedunfifoobar', 'NOCACHE'))
print('')
print('= even if we clear the unfiltered cache')
del repo.__dict__['testcachedunfifoobar']
print('cached value (unfiltered): ',
vars(repo).get('testcachedunfifoobar', 'NOCACHE'))
print('cached value ("visible" view): ',
vars(visibleview).get('testcachedunfifoobar', 'NOCACHE'))
print('cached value ("immutable" view):',
vars(immutableview).get('testcachedunfifoobar', 'NOCACHE'))
print('unficalllog:', unficalllog)
print('access ("visible" view): ', visibleview.testcachedunfifoobar)
print('unficalllog:', unficalllog)
print('cached value (unfiltered): ',
vars(repo).get('testcachedunfifoobar', 'NOCACHE'))
print('cached value ("visible" view): ',
vars(visibleview).get('testcachedunfifoobar', 'NOCACHE'))
print('cached value ("immutable" view):',
vars(immutableview).get('testcachedunfifoobar', 'NOCACHE'))
print('access ("immutable" view):', immutableview.testcachedunfifoobar)
print('unficalllog:', unficalllog)
print('cached value (unfiltered): ',
vars(repo).get('testcachedunfifoobar', 'NOCACHE'))
print('cached value ("visible" view): ',
vars(visibleview).get('testcachedunfifoobar', 'NOCACHE'))
print('cached value ("immutable" view):',
vars(immutableview).get('testcachedunfifoobar', 'NOCACHE'))
print('access (unfiltered): ', repo.testcachedunfifoobar)
print('unficalllog:', unficalllog)
print('cached value (unfiltered): ',
vars(repo).get('testcachedunfifoobar', 'NOCACHE'))
print('cached value ("visible" view): ',
vars(visibleview).get('testcachedunfifoobar', 'NOCACHE'))
print('cached value ("immutable" view):',
vars(immutableview).get('testcachedunfifoobar', 'NOCACHE'))