Re: [PATCH 7 of 7] hgweb: convert _siblings to a factory function of mappinggenerator

2018-04-14 Thread Anton Shestakov
On Sat, 14 Apr 2018 21:49:17 +0900
Yuya Nishihara  wrote:

> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1522594234 -32400
> #  Sun Apr 01 23:50:34 2018 +0900
> # Node ID fe959b32685068231cad8ef26387c7c16fe0961a
> # Parent  8e479b1d96bf94e81f76c78605c16b2864b219a5
> hgweb: convert _siblings to a factory function of mappinggenerator

Queued, thanks!
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3380: wireprotov2: establish a type for representing command response

2018-04-14 Thread indygreg (Gregory Szorc)
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  It will be desirable to have a higher-level type for representing
  command responses. This will allow us to do nicer things.
  
  For now, the instance encapsulates existing logic. It is still
  a bit primitive. But we're slowly making things better.
  
  Version 1 protocols have a wrapping layer that decodes the raw
  string data into a data structure and that data structure is
  sent to the future. Version 2 doesn't yet have this layer and
  the future is receiving the raw wire response. Hence why
  debugcommands needed to be taught about the response type.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3380

AFFECTED FILES
  mercurial/debugcommands.py
  mercurial/wireprotov2peer.py

CHANGE DETAILS

diff --git a/mercurial/wireprotov2peer.py b/mercurial/wireprotov2peer.py
--- a/mercurial/wireprotov2peer.py
+++ b/mercurial/wireprotov2peer.py
@@ -17,6 +17,26 @@
 wireprotoframing,
 )
 
+class commandresponse(object):
+"""Represents the response to a command request."""
+
+def __init__(self, requestid, command):
+self.requestid = requestid
+self.command = command
+
+self.cbor = False
+self.b = util.bytesio()
+
+def cborobjects(self):
+"""Obtain decoded CBOR objects from this response."""
+size = self.b.tell()
+self.b.seek(0)
+
+decoder = cbor.CBORDecoder(self.b)
+
+while self.b.tell() < size:
+yield decoder.decode()
+
 class clienthandler(object):
 """Object to handle higher-level client activities.
 
@@ -48,10 +68,7 @@
 rid = request.requestid
 self._requests[rid] = request
 self._futures[rid] = f
-self._responses[rid] = {
-'cbor': False,
-'b': util.bytesio(),
-}
+self._responses[rid] = commandresponse(rid, command)
 
 return iter(())
 
@@ -104,28 +121,13 @@
 response = self._responses[frame.requestid]
 
 if action == 'responsedata':
-response['b'].write(meta['data'])
+response.b.write(meta['data'])
 
 if meta['cbor']:
-response['cbor'] = True
+response.cbor = True
 
 if meta['eos']:
-if meta['cbor']:
-# If CBOR, decode every object.
-b = response['b']
-
-size = b.tell()
-b.seek(0)
-
-decoder = cbor.CBORDecoder(b)
-
-result = []
-while b.tell() < size:
-result.append(decoder.decode())
-else:
-result = [response['b'].getvalue()]
-
-self._futures[frame.requestid].set_result(result)
+self._futures[frame.requestid].set_result(response)
 
 del self._requests[frame.requestid]
 del self._futures[frame.requestid]
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -83,6 +83,7 @@
 vfs as vfsmod,
 wireprotoframing,
 wireprotoserver,
+wireprotov2peer,
 )
 from .utils import (
 dateutil,
@@ -3012,7 +3013,16 @@
 with peer.commandexecutor() as e:
 res = e.callcommand(command, args).result()
 
-ui.status(_('response: %s\n') % stringutil.pprint(res))
+if isinstance(res, wireprotov2peer.commandresponse):
+if res.cbor:
+val = list(res.cborobjects())
+else:
+val = [res.b.getvalue()]
+
+ui.status(_('response: %s\n') % stringutil.pprint(val))
+
+else:
+ui.status(_('response: %s\n') % stringutil.pprint(res))
 
 elif action == 'batchbegin':
 if batchedcommands is not None:



To: indygreg, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3387: wireprotov2: remove support for sending bytes response

2018-04-14 Thread indygreg (Gregory Szorc)
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  We recently declared that all responses must be CBOR. So remove
  support for sending a type that isn't CBOR data.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3387

AFFECTED FILES
  mercurial/wireprotov2server.py

CHANGE DETAILS

diff --git a/mercurial/wireprotov2server.py b/mercurial/wireprotov2server.py
--- a/mercurial/wireprotov2server.py
+++ b/mercurial/wireprotov2server.py
@@ -301,11 +301,7 @@
 res.status = b'200 OK'
 res.headers[b'Content-Type'] = FRAMINGTYPE
 
-if isinstance(rsp, wireprototypes.bytesresponse):
-action, meta = reactor.oncommandresponseready(outstream,
- command['requestid'],
- rsp.data)
-elif isinstance(rsp, wireprototypes.cborresponse):
+if isinstance(rsp, wireprototypes.cborresponse):
 encoded = cbor.dumps(rsp.value, canonical=True)
 action, meta = reactor.oncommandresponseready(outstream,
   command['requestid'],



To: indygreg, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3382: wireprotov2: define response data as CBOR

2018-04-14 Thread indygreg (Gregory Szorc)
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Previously, response data was defined as a stream of bytes. We had
  the option to declare it as CBOR using a frame flag.
  
  We've converged all wire protocol commands exposed on version 2 to
  CBOR. I think consistency is important. The overhead to encoding
  things with CBOR is minimal. Even a very large bytestring can be
  efficiently encoded using an indefinite length bytestring. Now,
  there are limitations with consumers not being able to efficiently
  stream large CBOR values. But these feel like solvable problems.
  
  This commit removes the "is CBOR" frame flag from command response
  frames and defines the frame as always consisting of a stream of
  CBOR values.
  
  The framing protocol media type has been bumped to reflect this
  BC change.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3382

AFFECTED FILES
  mercurial/debugcommands.py
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoframing.py
  mercurial/wireprotov2peer.py
  mercurial/wireprotov2server.py
  tests/test-http-api-httpv2.t
  tests/test-http-protocol.t
  tests/test-wireproto-command-branchmap.t
  tests/test-wireproto-command-capabilities.t
  tests/test-wireproto-command-heads.t
  tests/test-wireproto-command-known.t
  tests/test-wireproto-command-listkeys.t
  tests/test-wireproto-command-lookup.t
  tests/test-wireproto-command-pushkey.t
  tests/wireprotohelpers.sh

CHANGE DETAILS

diff --git a/tests/wireprotohelpers.sh b/tests/wireprotohelpers.sh
--- a/tests/wireprotohelpers.sh
+++ b/tests/wireprotohelpers.sh
@@ -1,5 +1,5 @@
 HTTPV2=exp-http-v2-0001
-MEDIATYPE=application/mercurial-exp-framing-0003
+MEDIATYPE=application/mercurial-exp-framing-0004
 
 sendhttpraw() {
   hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT/
@@ -26,16 +26,16 @@
 @wireproto.wireprotocommand('customreadonly', permission='pull',
 transportpolicy=wireproto.POLICY_V2_ONLY)
 def customreadonlyv2(repo, proto):
-return wireprototypes.bytesresponse(b'customreadonly bytes response')
+return wireprototypes.cborresponse(b'customreadonly bytes response')
 
 @wireproto.wireprotocommand('customreadwrite', permission='push')
 def customreadwrite(repo, proto):
 return wireprototypes.bytesresponse(b'customreadwrite bytes response')
 
 @wireproto.wireprotocommand('customreadwrite', permission='push',
 transportpolicy=wireproto.POLICY_V2_ONLY)
 def customreadwritev2(repo, proto):
-return wireprototypes.bytesresponse(b'customreadwrite bytes response')
+return wireprototypes.cborresponse(b'customreadwrite bytes response')
 EOF
 
 cat >> $HGRCPATH << EOF
diff --git a/tests/test-wireproto-command-pushkey.t 
b/tests/test-wireproto-command-pushkey.t
--- a/tests/test-wireproto-command-pushkey.t
+++ b/tests/test-wireproto-command-pushkey.t
@@ -32,8 +32,8 @@
   sending pushkey command
   s> *\r\n (glob)
   s> Accept-Encoding: identity\r\n
-  s> accept: application/mercurial-exp-framing-0003\r\n
-  s> content-type: application/mercurial-exp-framing-0003\r\n
+  s> accept: application/mercurial-exp-framing-0004\r\n
+  s> content-type: application/mercurial-exp-framing-0004\r\n
   s> content-length: 105\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> user-agent: Mercurial debugwireproto\r\n
@@ -43,14 +43,14 @@
   s> HTTP/1.1 200 OK\r\n
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
-  s> Content-Type: application/mercurial-exp-framing-0003\r\n
+  s> Content-Type: application/mercurial-exp-framing-0004\r\n
   s> Transfer-Encoding: chunked\r\n
   s> \r\n
   s> 9\r\n
-  s> *\x00\x01\x00\x02\x01F (glob)
+  s> \x01\x00\x00\x01\x00\x02\x01B
   s> \xf5
   s> \r\n
-  received frame(size=*; request=1; stream=2; streamflags=stream-begin; 
type=bytes-response; flags=eos|cbor) (glob)
+  received frame(size=1; request=1; stream=2; streamflags=stream-begin; 
type=bytes-response; flags=eos)
   s> 0\r\n
   s> \r\n
   response: True
@@ -63,8 +63,8 @@
   sending listkeys command
   s> POST /api/exp-http-v2-0001/ro/listkeys HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
-  s> accept: application/mercurial-exp-framing-0003\r\n
-  s> content-type: application/mercurial-exp-framing-0003\r\n
+  s> accept: application/mercurial-exp-framing-0004\r\n
+  s> content-type: application/mercurial-exp-framing-0004\r\n
   s> content-length: 49\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> user-agent: Mercurial debugwireproto\r\n
@@ -74,14 +74,14 @@
   s> HTTP/1.1 200 OK\r\n
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
-  s> Content-Type: application/mercurial-exp-framing-0003\r\n
+  s> Content-Type: application/mercurial-exp-framing-0004\r\n
   s> 

D3303: cborutil: implement support for streaming encoding, bytestring decoding

2018-04-14 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 8301.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3303?vs=8152=8301

REVISION DETAIL
  https://phab.mercurial-scm.org/D3303

AFFECTED FILES
  contrib/import-checker.py
  mercurial/utils/cborutil.py
  tests/test-cbor.py

CHANGE DETAILS

diff --git a/tests/test-cbor.py b/tests/test-cbor.py
new file mode 100644
--- /dev/null
+++ b/tests/test-cbor.py
@@ -0,0 +1,211 @@
+from __future__ import absolute_import
+
+import io
+import unittest
+
+from mercurial.thirdparty import (
+cbor,
+)
+from mercurial.utils import (
+cborutil,
+)
+
+def loadit(it):
+return cbor.loads(b''.join(it))
+
+class BytestringTests(unittest.TestCase):
+def testsimple(self):
+self.assertEqual(
+list(cborutil.streamencode(b'foobar')),
+[b'\x46', b'foobar'])
+
+self.assertEqual(
+loadit(cborutil.streamencode(b'foobar')),
+b'foobar')
+
+def testlong(self):
+source = b'x' * 1048576
+
+self.assertEqual(loadit(cborutil.streamencode(source)), source)
+
+def testfromiter(self):
+# This is the example from RFC 7049 Section 2.2.2.
+source = [b'\xaa\xbb\xcc\xdd', b'\xee\xff\x99']
+
+self.assertEqual(
+list(cborutil.streamencodebytestringfromiter(source)),
+[
+b'\x5f',
+b'\x44',
+b'\xaa\xbb\xcc\xdd',
+b'\x43',
+b'\xee\xff\x99',
+b'\xff',
+])
+
+self.assertEqual(
+loadit(cborutil.streamencodebytestringfromiter(source)),
+b''.join(source))
+
+def testfromiterlarge(self):
+source = [b'a' * 16, b'b' * 128, b'c' * 1024, b'd' * 1048576]
+
+self.assertEqual(
+loadit(cborutil.streamencodebytestringfromiter(source)),
+b''.join(source))
+
+def testindefinite(self):
+source = b'\x00\x01\x02\x03' + b'\xff' * 16384
+
+it = cborutil.streamencodeindefinitebytestring(source, chunksize=2)
+
+self.assertEqual(next(it), b'\x5f')
+self.assertEqual(next(it), b'\x42')
+self.assertEqual(next(it), b'\x00\x01')
+self.assertEqual(next(it), b'\x42')
+self.assertEqual(next(it), b'\x02\x03')
+self.assertEqual(next(it), b'\x42')
+self.assertEqual(next(it), b'\xff\xff')
+
+dest = b''.join(cborutil.streamencodeindefinitebytestring(
+source, chunksize=42))
+self.assertEqual(cbor.loads(dest), b''.join(source))
+
+def testreadtoiter(self):
+source = io.BytesIO(b'\x5f\x44\xaa\xbb\xcc\xdd\x43\xee\xff\x99\xff')
+
+it = cborutil.readindefinitebytestringtoiter(source)
+self.assertEqual(next(it), b'\xaa\xbb\xcc\xdd')
+self.assertEqual(next(it), b'\xee\xff\x99')
+
+with self.assertRaises(StopIteration):
+next(it)
+
+class IntTests(unittest.TestCase):
+def testsmall(self):
+self.assertEqual(list(cborutil.streamencode(0)), [b'\x00'])
+self.assertEqual(list(cborutil.streamencode(1)), [b'\x01'])
+self.assertEqual(list(cborutil.streamencode(2)), [b'\x02'])
+self.assertEqual(list(cborutil.streamencode(3)), [b'\x03'])
+self.assertEqual(list(cborutil.streamencode(4)), [b'\x04'])
+
+def testnegativesmall(self):
+self.assertEqual(list(cborutil.streamencode(-1)), [b'\x20'])
+self.assertEqual(list(cborutil.streamencode(-2)), [b'\x21'])
+self.assertEqual(list(cborutil.streamencode(-3)), [b'\x22'])
+self.assertEqual(list(cborutil.streamencode(-4)), [b'\x23'])
+self.assertEqual(list(cborutil.streamencode(-5)), [b'\x24'])
+
+def testrange(self):
+for i in range(-7, 7, 10):
+self.assertEqual(
+b''.join(cborutil.streamencode(i)),
+cbor.dumps(i))
+
+class ArrayTests(unittest.TestCase):
+def testempty(self):
+self.assertEqual(list(cborutil.streamencode([])), [b'\x80'])
+self.assertEqual(loadit(cborutil.streamencode([])), [])
+
+def testbasic(self):
+source = [b'foo', b'bar', 1, -10]
+
+self.assertEqual(list(cborutil.streamencode(source)), [
+b'\x84', b'\x43', b'foo', b'\x43', b'bar', b'\x01', b'\x29'])
+
+def testemptyfromiter(self):
+self.assertEqual(b''.join(cborutil.streamencodearrayfromiter([])),
+ b'\x9f\xff')
+
+def testfromiter1(self):
+source = [b'foo']
+
+self.assertEqual(list(cborutil.streamencodearrayfromiter(source)), [
+b'\x9f',
+b'\x43', b'foo',
+b'\xff',
+])
+
+
+dest = b''.join(cborutil.streamencodearrayfromiter(source))
+self.assertEqual(cbor.loads(dest), source)
+
+def testtuple(self):
+source = (b'foo', None, 42)
+
+self.assertEqual(cbor.loads(b''.join(cborutil.streamencode(source))),
+ 

D3377: hg: pass command intents to repo/peer creation (API)

2018-04-14 Thread indygreg (Gregory Szorc)
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The previous commit introduced a mechanism to declare command intents.
  This commit changes the repository and peer instantiation mechanism
  so the intents are passed down to each repository and peer type so
  they can do with them whatever they please.
  
  Currently, nobody does anything with any intent.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3377

AFFECTED FILES
  hgext/schemes.py
  mercurial/bundlerepo.py
  mercurial/dispatch.py
  mercurial/hg.py
  mercurial/httppeer.py
  mercurial/localrepo.py
  mercurial/sshpeer.py
  mercurial/statichttprepo.py
  mercurial/unionrepo.py

CHANGE DETAILS

diff --git a/mercurial/unionrepo.py b/mercurial/unionrepo.py
--- a/mercurial/unionrepo.py
+++ b/mercurial/unionrepo.py
@@ -231,7 +231,7 @@
 def getcwd(self):
 return pycompat.getcwd() # always outside the repo
 
-def instance(ui, path, create):
+def instance(ui, path, create, intents=None):
 if create:
 raise error.Abort(_('cannot create new union repository'))
 parentpath = ui.config("bundle", "mainreporoot")
diff --git a/mercurial/statichttprepo.py b/mercurial/statichttprepo.py
--- a/mercurial/statichttprepo.py
+++ b/mercurial/statichttprepo.py
@@ -215,7 +215,7 @@
 def _writecaches(self):
 pass # statichttprepository are read only
 
-def instance(ui, path, create):
+def instance(ui, path, create, intents=None):
 if create:
 raise error.Abort(_('cannot create new static-http repository'))
 return statichttprepository(ui, path[7:])
diff --git a/mercurial/sshpeer.py b/mercurial/sshpeer.py
--- a/mercurial/sshpeer.py
+++ b/mercurial/sshpeer.py
@@ -587,7 +587,7 @@
 raise error.RepoError(_('unknown version of SSH protocol: %s') %
   protoname)
 
-def instance(ui, path, create):
+def instance(ui, path, create, intents=None):
 """Create an SSH peer.
 
 The returned object conforms to the ``wireprotov1peer.wirepeer`` interface.
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -413,7 +413,7 @@
 'bisect.state',
 }
 
-def __init__(self, baseui, path, create=False):
+def __init__(self, baseui, path, create=False, intents=None):
 self.requirements = set()
 self.filtername = None
 # wvfs: rooted at the repository root, used to access the working copy
@@ -2332,8 +2332,9 @@
 assert name.startswith('journal')
 return os.path.join(base, name.replace('journal', 'undo', 1))
 
-def instance(ui, path, create):
-return localrepository(ui, util.urllocalpath(path), create)
+def instance(ui, path, create, intents=None):
+return localrepository(ui, util.urllocalpath(path), create,
+   intents=intents)
 
 def islocal(path):
 return True
diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py
--- a/mercurial/httppeer.py
+++ b/mercurial/httppeer.py
@@ -990,7 +990,7 @@
 return httppeer(ui, path, respurl, opener, requestbuilder,
 info['v1capabilities'])
 
-def instance(ui, path, create):
+def instance(ui, path, create, intents=None):
 if create:
 raise error.Abort(_('cannot create new http repository'))
 try:
diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -157,9 +157,10 @@
 # a list of (ui, repo) functions called for wire peer initialization
 wirepeersetupfuncs = []
 
-def _peerorrepo(ui, path, create=False, presetupfuncs=None):
+def _peerorrepo(ui, path, create=False, presetupfuncs=None,
+intents=None):
 """return a repository object for the specified path"""
-obj = _peerlookup(path).instance(ui, path, create)
+obj = _peerlookup(path).instance(ui, path, create, intents=intents)
 ui = getattr(obj, "ui", ui)
 for f in presetupfuncs or []:
 f(ui, obj)
@@ -172,19 +173,20 @@
 f(ui, obj)
 return obj
 
-def repository(ui, path='', create=False, presetupfuncs=None):
+def repository(ui, path='', create=False, presetupfuncs=None, intents=None):
 """return a repository object for the specified path"""
-peer = _peerorrepo(ui, path, create, presetupfuncs=presetupfuncs)
+peer = _peerorrepo(ui, path, create, presetupfuncs=presetupfuncs,
+   intents=intents)
 repo = peer.local()
 if not repo:
 raise error.Abort(_("repository '%s' is not local") %
  (path or peer.url()))
 return repo.filtered('visible')
 
-def peer(uiorrepo, opts, path, create=False):
+def peer(uiorrepo, opts, path, create=False, intents=None):
 '''return a repository peer for the specified path'''
 rui = remoteui(uiorrepo, opts)
-return _peerorrepo(rui, path, create).peer()
+return _peerorrepo(rui, path, create, 

D3384: wireprotov2: change frame type and name for command response

2018-04-14 Thread indygreg (Gregory Szorc)
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  There was hole at frame type value 3. And the frame is better
  named as a command response.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3384

AFFECTED FILES
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoframing.py
  mercurial/wireprotov2server.py
  tests/test-http-api-httpv2.t
  tests/test-http-protocol.t
  tests/test-wireproto-clientreactor.py
  tests/test-wireproto-command-branchmap.t
  tests/test-wireproto-command-capabilities.t
  tests/test-wireproto-command-heads.t
  tests/test-wireproto-command-known.t
  tests/test-wireproto-command-listkeys.t
  tests/test-wireproto-command-lookup.t
  tests/test-wireproto-command-pushkey.t
  tests/test-wireproto-serverreactor.py

CHANGE DETAILS

diff --git a/tests/test-wireproto-serverreactor.py 
b/tests/test-wireproto-serverreactor.py
--- a/tests/test-wireproto-serverreactor.py
+++ b/tests/test-wireproto-serverreactor.py
@@ -211,19 +211,19 @@
 results.append(self._sendsingleframe(
 reactor, ffs(b'1 1 stream-begin command-request new '
  b"cbor:{b'name': b'command'}")))
-result = reactor.onbytesresponseready(outstream, 1, b'response1')
+result = reactor.oncommandresponseready(outstream, 1, b'response1')
 self.assertaction(result, b'sendframes')
 list(result[1][b'framegen'])
 results.append(self._sendsingleframe(
 reactor, ffs(b'1 1 stream-begin command-request new '
  b"cbor:{b'name': b'command'}")))
-result = reactor.onbytesresponseready(outstream, 1, b'response2')
+result = reactor.oncommandresponseready(outstream, 1, b'response2')
 self.assertaction(result, b'sendframes')
 list(result[1][b'framegen'])
 results.append(self._sendsingleframe(
 reactor, ffs(b'1 1 stream-begin command-request new '
  b"cbor:{b'name': b'command'}")))
-result = reactor.onbytesresponseready(outstream, 1, b'response3')
+result = reactor.oncommandresponseready(outstream, 1, b'response3')
 self.assertaction(result, b'sendframes')
 list(result[1][b'framegen'])
 
@@ -347,10 +347,10 @@
 list(sendcommandframes(reactor, instream, 1, b'mycommand', {}))
 
 outstream = reactor.makeoutputstream()
-result = reactor.onbytesresponseready(outstream, 1, b'response')
+result = reactor.oncommandresponseready(outstream, 1, b'response')
 self.assertaction(result, b'sendframes')
 self.assertframesequal(result[1][b'framegen'], [
-b'1 2 stream-begin bytes-response eos response',
+b'1 2 stream-begin command-response eos response',
 ])
 
 def testmultiframeresponse(self):
@@ -363,11 +363,11 @@
 list(sendcommandframes(reactor, instream, 1, b'mycommand', {}))
 
 outstream = reactor.makeoutputstream()
-result = reactor.onbytesresponseready(outstream, 1, first + second)
+result = reactor.oncommandresponseready(outstream, 1, first + second)
 self.assertaction(result, b'sendframes')
 self.assertframesequal(result[1][b'framegen'], [
-b'1 2 stream-begin bytes-response continuation %s' % first,
-b'1 2 0 bytes-response eos %s' % second,
+b'1 2 stream-begin command-response continuation %s' % first,
+b'1 2 0 command-response eos %s' % second,
 ])
 
 def testapplicationerror(self):
@@ -392,12 +392,12 @@
 self.assertaction(results[0], b'runcommand')
 
 outstream = reactor.makeoutputstream()
-result = reactor.onbytesresponseready(outstream, 1, b'response')
+result = reactor.oncommandresponseready(outstream, 1, b'response')
 self.assertaction(result, b'noop')
 result = reactor.oninputeof()
 self.assertaction(result, b'sendframes')
 self.assertframesequal(result[1][b'framegen'], [
-b'1 2 stream-begin bytes-response eos response',
+b'1 2 stream-begin command-response eos response',
 ])
 
 def testmultiplecommanddeferresponse(self):
@@ -407,15 +407,15 @@
 list(sendcommandframes(reactor, instream, 3, b'command2', {}))
 
 outstream = reactor.makeoutputstream()
-result = reactor.onbytesresponseready(outstream, 1, b'response1')
+result = reactor.oncommandresponseready(outstream, 1, b'response1')
 self.assertaction(result, b'noop')
-result = reactor.onbytesresponseready(outstream, 3, b'response2')
+result = reactor.oncommandresponseready(outstream, 3, b'response2')
 self.assertaction(result, b'noop')
 result = reactor.oninputeof()
 self.assertaction(result, b'sendframes')
 self.assertframesequal(result[1][b'framegen'], [
-b'1 2 stream-begin 

D3383: wireprotov2: change frame type value for command data

2018-04-14 Thread indygreg (Gregory Szorc)
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  When we dropped the dedicated command argument frame type, this left
  a hole in our frame type numbering. Let's start plugging that hole.
  
  The command data frame is now type value 2 instead of 3.
  
  There was limited test fallout because a) we do a good job of using
  the constants to refer to frame types b) not many tests are sending
  command data frames.
  
  Bumping the media type will be performed in a later commit, once all
  type value adjustment has been performed.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3383

AFFECTED FILES
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoframing.py
  tests/test-wireproto-serverreactor.py

CHANGE DETAILS

diff --git a/tests/test-wireproto-serverreactor.py 
b/tests/test-wireproto-serverreactor.py
--- a/tests/test-wireproto-serverreactor.py
+++ b/tests/test-wireproto-serverreactor.py
@@ -185,7 +185,7 @@
 ffs(b'1 1 stream-begin command-data 0 ignored'))
 self.assertaction(result, b'error')
 self.assertEqual(result[1], {
-b'message': b'expected command request frame; got 3',
+b'message': b'expected command request frame; got 2',
 })
 
 def testunexpectedcommanddatareceiving(self):
diff --git a/mercurial/wireprotoframing.py b/mercurial/wireprotoframing.py
--- a/mercurial/wireprotoframing.py
+++ b/mercurial/wireprotoframing.py
@@ -42,7 +42,7 @@
 }
 
 FRAME_TYPE_COMMAND_REQUEST = 0x01
-FRAME_TYPE_COMMAND_DATA = 0x03
+FRAME_TYPE_COMMAND_DATA = 0x02
 FRAME_TYPE_BYTES_RESPONSE = 0x04
 FRAME_TYPE_ERROR_RESPONSE = 0x05
 FRAME_TYPE_TEXT_OUTPUT = 0x06
diff --git a/mercurial/help/internals/wireprotocol.txt 
b/mercurial/help/internals/wireprotocol.txt
--- a/mercurial/help/internals/wireprotocol.txt
+++ b/mercurial/help/internals/wireprotocol.txt
@@ -638,10 +638,10 @@
 ``0x01`` or ``0x02`` MUST be set to indicate this frame's role in
 a series of command request frames.
 
-If command data frames are to be sent, ``0x10`` MUST be set on ALL
+If command data frames are to be sent, ``0x08`` MUST be set on ALL
 command request frames.
 
-Command Data (``0x03``)
+Command Data (``0x02``)
 ---
 
 This frame contains raw data for a command.



To: indygreg, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3379: wireprotov2: move response handling out of httppeer

2018-04-14 Thread indygreg (Gregory Szorc)
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  And fix some bugs while we're here.
  
  The code for processing response data from the unified framing
  protocol is mostly peer agnostic. The peer-specific bits are the
  configuration of the client reactor and how I/O is performed. I
  initially implemented things in httppeer for expediency.
  
  This commit establishes a module for holding the peer API level
  code for the framing based protocol. Inside this module we have
  a class to help coordinate higher-level activities, such as managing
  response object.
  
  The client handler bits could be rolled into clientreactor. However,
  I want clientreactor to be sans I/O and I want it to only be
  concerned with protocol-level details, not higher-level concepts
  like how protocol events are converted into peer API concepts. I
  want clientreactor to receive a frame and then tell the caller what
  should probably be done about it. If we start putting things like
  future resolution into clientreactor, we'll constrain how the protocol
  can be used (e.g. by requiring futures).
  
  The new code is loosely based on what was in httppeer before. I
  changed things a bit around response handling. We now buffer the
  entire response "body" and then handle it as one atomic unit. This
  fixed a bug around decoding CBOR data that spanned multiple frames.
  I also fixed an off-by-one bug where we failed to read a single byte
  CBOR value at the end of the stream. That's why tests have changed.
  
  The new state of httppeer is much cleaner. It is largely agnostic
  about framing protocol implementation details. That's how it should
  be: the framing protocol is designed to be largely transport
  agnostic. We want peers merely putting bytes on the wire and telling
  the framing protocol where to read response data from.
  
  There's still a bit of work to be done here, especially for
  representing responses. But at least we're a step closer to having a
  higher-level peer interface that can be plugged into the SSH peer
  someday.
  
  I initially added this class to wireprotoframing. However, we'll
  eventually need version 2 specific functions to convert CBOR responses
  into data structures expected by the code calling commands. This
  needs to live somewhere. Since that code would be shared across peers,
  we need a common module. We have wireprotov1peer for the equivalent
  version 1 code. So I decided to establish wireprotov2peer.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3379

AFFECTED FILES
  mercurial/httppeer.py
  mercurial/wireprotov2peer.py
  tests/test-wireproto-command-known.t
  tests/test-wireproto-command-pushkey.t

CHANGE DETAILS

diff --git a/tests/test-wireproto-command-pushkey.t 
b/tests/test-wireproto-command-pushkey.t
--- a/tests/test-wireproto-command-pushkey.t
+++ b/tests/test-wireproto-command-pushkey.t
@@ -53,7 +53,7 @@
   received frame(size=*; request=1; stream=2; streamflags=stream-begin; 
type=bytes-response; flags=eos|cbor) (glob)
   s> 0\r\n
   s> \r\n
-  response: []
+  response: [True]
 
   $ sendhttpv2peer << EOF
   > command listkeys
diff --git a/tests/test-wireproto-command-known.t 
b/tests/test-wireproto-command-known.t
--- a/tests/test-wireproto-command-known.t
+++ b/tests/test-wireproto-command-known.t
@@ -50,7 +50,7 @@
   received frame(size=1; request=1; stream=2; streamflags=stream-begin; 
type=bytes-response; flags=eos|cbor)
   s> 0\r\n
   s> \r\n
-  response: []
+  response: [b'']
 
 Single known node works
 
diff --git a/mercurial/wireprotov2peer.py b/mercurial/wireprotov2peer.py
new file mode 100644
--- /dev/null
+++ b/mercurial/wireprotov2peer.py
@@ -0,0 +1,135 @@
+# wireprotov2peer.py - client side code for wire protocol version 2
+#
+# Copyright 2018 Gregory Szorc 
+#
+# 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 .i18n import _
+from .thirdparty import (
+cbor,
+)
+from . import (
+error,
+util,
+wireprotoframing,
+)
+
+class clienthandler(object):
+"""Object to handle higher-level client activities.
+
+The ``clientreactor`` is used to hold low-level state about the frame-based
+protocol, such as which requests and streams are active. This type is used
+for higher-level operations, such as reading frames from a socket, exposing
+and managing a higher-level primitive for representing command responses,
+etc. This class is what peers should probably use to bridge wire activity
+with the higher-level peer API.
+"""
+
+def __init__(self, ui, clientreactor):
+self._ui = ui
+self._reactor = clientreactor
+self._requests = {}
+self._futures = {}
+self._responses = {}
+
+def 

D3386: wireprotov2: change behavior of error frame

2018-04-14 Thread indygreg (Gregory Szorc)
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Now that we have a leading CBOR map in command response frames
  to indicate overall command result status, we don't need to use
  the error response frame to represent command errors. Instead,
  we can reserve it for protocol and server level errors. And for the
  special case of a command error that occurred after command response
  frames were emitted.
  
  The code for error handling still needs a ton of work. But we're
  slowly going in the right direction...

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3386

AFFECTED FILES
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoframing.py
  mercurial/wireprotov2server.py
  tests/test-wireproto-serverreactor.py

CHANGE DETAILS

diff --git a/tests/test-wireproto-serverreactor.py 
b/tests/test-wireproto-serverreactor.py
--- a/tests/test-wireproto-serverreactor.py
+++ b/tests/test-wireproto-serverreactor.py
@@ -373,16 +373,18 @@
 b'1 2 0 command-response eos %s' % second,
 ])
 
-def testapplicationerror(self):
+def testservererror(self):
 reactor = makereactor()
 instream = framing.stream(1)
 list(sendcommandframes(reactor, instream, 1, b'mycommand', {}))
 
 outstream = reactor.makeoutputstream()
-result = reactor.onapplicationerror(outstream, 1, b'some message')
+result = reactor.onservererror(outstream, 1, b'some message')
 self.assertaction(result, b'sendframes')
 self.assertframesequal(result[1][b'framegen'], [
-b'1 2 stream-begin error-response application some message',
+b"1 2 stream-begin error-response 0 "
+b"cbor:{b'type': b'server', "
+b"b'message': [{b'msg': b'some message'}]}",
 ])
 
 def test1commanddeferresponse(self):
diff --git a/mercurial/wireprotov2server.py b/mercurial/wireprotov2server.py
--- a/mercurial/wireprotov2server.py
+++ b/mercurial/wireprotov2server.py
@@ -311,7 +311,7 @@
   command['requestid'],
   encoded)
 else:
-action, meta = reactor.onapplicationerror(
+action, meta = reactor.onservererror(
 _('unhandled response type from wire proto command'))
 
 if action == 'sendframes':
diff --git a/mercurial/wireprotoframing.py b/mercurial/wireprotoframing.py
--- a/mercurial/wireprotoframing.py
+++ b/mercurial/wireprotoframing.py
@@ -87,20 +87,12 @@
 b'eos': FLAG_COMMAND_RESPONSE_EOS,
 }
 
-FLAG_ERROR_RESPONSE_PROTOCOL = 0x01
-FLAG_ERROR_RESPONSE_APPLICATION = 0x02
-
-FLAGS_ERROR_RESPONSE = {
-b'protocol': FLAG_ERROR_RESPONSE_PROTOCOL,
-b'application': FLAG_ERROR_RESPONSE_APPLICATION,
-}
-
 # Maps frame types to their available flags.
 FRAME_TYPE_FLAGS = {
 FRAME_TYPE_COMMAND_REQUEST: FLAGS_COMMAND_REQUEST,
 FRAME_TYPE_COMMAND_DATA: FLAGS_COMMAND_DATA,
 FRAME_TYPE_COMMAND_RESPONSE: FLAGS_COMMAND_RESPONSE,
-FRAME_TYPE_ERROR_RESPONSE: FLAGS_ERROR_RESPONSE,
+FRAME_TYPE_ERROR_RESPONSE: {},
 FRAME_TYPE_TEXT_OUTPUT: {},
 FRAME_TYPE_PROGRESS: {},
 FRAME_TYPE_STREAM_SETTINGS: {},
@@ -394,20 +386,19 @@
 if done:
 break
 
-def createerrorframe(stream, requestid, msg, protocol=False, 
application=False):
+def createerrorframe(stream, requestid, msg, errtype):
 # TODO properly handle frame size limits.
 assert len(msg) <= DEFAULT_MAX_FRAME_SIZE
 
-flags = 0
-if protocol:
-flags |= FLAG_ERROR_RESPONSE_PROTOCOL
-if application:
-flags |= FLAG_ERROR_RESPONSE_APPLICATION
+payload = cbor.dumps({
+b'type': errtype,
+b'message': [{b'msg': msg}],
+}, canonical=True)
 
 yield stream.makeframe(requestid=requestid,
typeid=FRAME_TYPE_ERROR_RESPONSE,
-   flags=flags,
-   payload=msg)
+   flags=0,
+   payload=payload)
 
 def createtextoutputframe(stream, requestid, atoms,
   maxframesize=DEFAULT_MAX_FRAME_SIZE):
@@ -664,12 +655,12 @@
 'framegen': makegen(),
 }
 
-def onapplicationerror(self, stream, requestid, msg):
+def onservererror(self, stream, requestid, msg):
 ensureserverstream(stream)
 
 return 'sendframes', {
 'framegen': createerrorframe(stream, requestid, msg,
- application=True),
+ errtype='server'),
 }
 
 def makeoutputstream(self):
@@ -1051,6 +1042,7 @@
 
 handlers = {
 FRAME_TYPE_COMMAND_RESPONSE: self._oncommandresponseframe,
+FRAME_TYPE_ERROR_RESPONSE: self._onerrorresponseframe,
 }
 
 meth = 

D3378: debugcommands: ability to suppress logging of handshake

2018-04-14 Thread indygreg (Gregory Szorc)
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The tests for calling wire protocol commands were getting quite
  verbose because they included the results of the capabilities
  request. Furthermore, it was annoying to have to update several
  tests every time the capabilities response changed.
  
  The only tests that really care about the low-level details of
  the capabilities requests are those testing the protocol
  handshake. And those are mostly not instantiating peer instances
  or are contained to limited files.
  
  This commit adds an option to `hg debugwireproto` to suppress logging
  of the handshake. The shell helper function to perform HTTP tests
  has been updated to use this by default. Lots of excessive test
  output has gone away.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3378

AFFECTED FILES
  mercurial/debugcommands.py
  tests/test-completion.t
  tests/test-http-api-httpv2.t
  tests/test-wireproto-command-branchmap.t
  tests/test-wireproto-command-capabilities.t
  tests/test-wireproto-command-heads.t
  tests/test-wireproto-command-known.t
  tests/test-wireproto-command-listkeys.t
  tests/test-wireproto-command-lookup.t
  tests/test-wireproto-command-pushkey.t
  tests/wireprotohelpers.sh

CHANGE DETAILS

diff --git a/tests/wireprotohelpers.sh b/tests/wireprotohelpers.sh
--- a/tests/wireprotohelpers.sh
+++ b/tests/wireprotohelpers.sh
@@ -6,6 +6,10 @@
 }
 
 sendhttpv2peer() {
+  hg --verbose debugwireproto --nologhandshake --peer http2 
http://$LOCALIP:$HGPORT/
+}
+
+sendhttpv2peerhandshake() {
   hg --verbose debugwireproto --peer http2 http://$LOCALIP:$HGPORT/
 }
 
diff --git a/tests/test-wireproto-command-pushkey.t 
b/tests/test-wireproto-command-pushkey.t
--- a/tests/test-wireproto-command-pushkey.t
+++ b/tests/test-wireproto-command-pushkey.t
@@ -29,23 +29,6 @@
   > new 426bada5c67598ca65036d57d9e4b64b0c1ce7a0
   > EOF
   creating http peer for wire protocol version 2
-  s> *\r\n (glob)
-  s> Accept-Encoding: identity\r\n
-  s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
-  s> x-hgproto-1: cbor\r\n
-  s> x-hgupgrade-1: exp-http-v2-0001\r\n
-  s> accept: application/mercurial-0.1\r\n
-  s> host: $LOCALIP:$HGPORT\r\n (glob)
-  s> user-agent: Mercurial debugwireproto\r\n
-  s> \r\n
-  s> makefile('rb', None)
-  s> HTTP/1.1 200 OK\r\n
-  s> Server: testing stub value\r\n
-  s> Date: $HTTP_DATE$\r\n
-  s> Content-Type: application/mercurial-cbor\r\n
-  s> Content-Length: *\r\n (glob)
-  s> \r\n
-  s> 
\xa3Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibNrawrepoformats\x82LgeneraldeltaHrevlogv1Qframingmediatypes\x81X/mercurial-exp-framing-0003GapibaseDapi/Nv1capabilitiesY\x01\xcabatch
 branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset 
compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 
httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey 
streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
   sending pushkey command
   s> *\r\n (glob)
   s> Accept-Encoding: identity\r\n
@@ -77,23 +60,6 @@
   > namespace bookmarks
   > EOF
   creating http peer for wire protocol version 2
-  s> GET /?cmd=capabilities HTTP/1.1\r\n
-  s> Accept-Encoding: identity\r\n
-  s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
-  s> x-hgproto-1: cbor\r\n
-  s> x-hgupgrade-1: exp-http-v2-0001\r\n
-  s> accept: application/mercurial-0.1\r\n
-  s> host: $LOCALIP:$HGPORT\r\n (glob)
-  s> user-agent: Mercurial debugwireproto\r\n
-  s> \r\n
-  s> makefile('rb', None)
-  s> HTTP/1.1 200 OK\r\n
-  s> Server: testing stub value\r\n
-  s> Date: $HTTP_DATE$\r\n
-  s> Content-Type: application/mercurial-cbor\r\n
-  s> Content-Length: *\r\n (glob)
-  s> \r\n
-  s> 
\xa3Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibNrawrepoformats\x82LgeneraldeltaHrevlogv1Qframingmediatypes\x81X/mercurial-exp-framing-0003GapibaseDapi/Nv1capabilitiesY\x01\xcabatch
 branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset 

D3388: wireprotov2: add support for more response types

2018-04-14 Thread indygreg (Gregory Szorc)
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This adds types to represent error and generator responses from
  server commands.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3388

AFFECTED FILES
  mercurial/wireprotoframing.py
  mercurial/wireprototypes.py
  mercurial/wireprotov2server.py

CHANGE DETAILS

diff --git a/mercurial/wireprotov2server.py b/mercurial/wireprotov2server.py
--- a/mercurial/wireprotov2server.py
+++ b/mercurial/wireprotov2server.py
@@ -306,6 +306,15 @@
 action, meta = reactor.oncommandresponseready(outstream,
   command['requestid'],
   encoded)
+elif isinstance(rsp, wireprototypes.v2streamingresponse):
+action, meta = reactor.oncommandresponsereadygen(outstream,
+ command['requestid'],
+ rsp.gen)
+elif isinstance(rsp, wireprototypes.v2errorresponse):
+action, meta = reactor.oncommanderror(outstream,
+  command['requestid'],
+  rsp.message,
+  rsp.args)
 else:
 action, meta = reactor.onservererror(
 _('unhandled response type from wire proto command'))
diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py
--- a/mercurial/wireprototypes.py
+++ b/mercurial/wireprototypes.py
@@ -106,6 +106,23 @@
 def __init__(self, v):
 self.value = v
 
+class v2errorresponse(object):
+"""Represents a command error for version 2 transports."""
+def __init__(self, message, args=None):
+self.message = message
+self.args = args
+
+class v2streamingresponse(object):
+"""A response whose data is supplied by a generator.
+
+The generator can either consist of data structures to CBOR
+encode or a stream of already-encoded bytes.
+"""
+def __init__(self, gen, compressible=True, iscbor=False):
+self.gen = gen
+self.compressible = compressible
+self.iscbor = iscbor
+
 # list of nodes encoding / decoding
 def decodelist(l, sep=' '):
 if l:
diff --git a/mercurial/wireprotoframing.py b/mercurial/wireprotoframing.py
--- a/mercurial/wireprotoframing.py
+++ b/mercurial/wireprotoframing.py
@@ -386,6 +386,56 @@
 if done:
 break
 
+def createbytesresponseframesfromgen(stream, requestid, gen,
+ maxframesize=DEFAULT_MAX_FRAME_SIZE):
+overall = cbor.dumps({b'status': b'ok'}, canonical=True)
+
+yield stream.makeframe(requestid=requestid,
+   typeid=FRAME_TYPE_COMMAND_RESPONSE,
+   flags=FLAG_COMMAND_RESPONSE_CONTINUATION,
+   payload=overall)
+
+cb = util.chunkbuffer(gen)
+
+flags = 0
+
+while True:
+chunk = cb.read(maxframesize)
+if not chunk:
+break
+
+yield stream.makeframe(requestid=requestid,
+   typeid=FRAME_TYPE_COMMAND_RESPONSE,
+   flags=flags,
+   payload=chunk)
+
+flags |= FLAG_COMMAND_RESPONSE_CONTINUATION
+
+flags ^= FLAG_COMMAND_RESPONSE_CONTINUATION
+flags |= FLAG_COMMAND_RESPONSE_EOS
+yield stream.makeframe(requestid=requestid,
+   typeid=FRAME_TYPE_COMMAND_RESPONSE,
+   flags=flags,
+   payload=b'')
+
+def createcommanderrorresponse(stream, requestid, message, args=None):
+m = {
+b'status': b'error',
+b'error': {
+b'message': message,
+}
+}
+
+if args:
+m[b'error'][b'args'] = args
+
+overall = cbor.dumps(m, canonical=True)
+
+yield stream.makeframe(requestid=requestid,
+   typeid=FRAME_TYPE_COMMAND_RESPONSE,
+   flags=FLAG_COMMAND_RESPONSE_EOS,
+   payload=overall)
+
 def createerrorframe(stream, requestid, msg, errtype):
 # TODO properly handle frame size limits.
 assert len(msg) <= DEFAULT_MAX_FRAME_SIZE
@@ -634,6 +684,19 @@
 'framegen': result,
 }
 
+def oncommandresponsereadygen(self, stream, requestid, gen):
+"""Signal that a bytes response is ready, with data as a generator."""
+ensureserverstream(stream)
+
+def sendframes():
+for frame in createbytesresponseframesfromgen(stream, requestid,
+  gen):
+yield frame
+
+self._activecommands.remove(requestid)
+
+return self._handlesendframes(sendframes())
+
 def oninputeof(self):
 

D3372: keepalive: add ** overlooked in 83250442dc81

2018-04-14 Thread durin42 (Augie Fackler)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG2177b499db6b: keepalive: add ** overlooked in 83250442dc81 
(authored by durin42, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3372?vs=8276=8287

REVISION DETAIL
  https://phab.mercurial-scm.org/D3372

AFFECTED FILES
  mercurial/keepalive.py

CHANGE DETAILS

diff --git a/mercurial/keepalive.py b/mercurial/keepalive.py
--- a/mercurial/keepalive.py
+++ b/mercurial/keepalive.py
@@ -326,16 +326,16 @@
 data = urllibcompat.getdata(req)
 h.putrequest(
 req.get_method(), urllibcompat.getselector(req),
-skipheaders)
+**skipheaders)
 if r'content-type' not in headers:
 h.putheader(r'Content-type',
 r'application/x-www-form-urlencoded')
 if r'content-length' not in headers:
 h.putheader(r'Content-length', r'%d' % len(data))
 else:
 h.putrequest(
 req.get_method(), urllibcompat.getselector(req),
-skipheaders)
+**skipheaders)
 except socket.error as err:
 raise urlerr.urlerror(err)
 for k, v in headers.items():



To: durin42, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 5 V2] test-lfs: add tests to force server error path coverage

2018-04-14 Thread Yuya Nishihara
On Sat, 14 Apr 2018 14:47:33 -0400, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison 
> # Date 1523119701 14400
> #  Sat Apr 07 12:48:21 2018 -0400
> # Node ID a83bc37bcf3da077f78bf3377b88b61d328bd4ce
> # Parent  9d509015742603624ef0df5497f0f205d8768ebf
> test-lfs: add tests to force server error path coverage

Queued, thanks.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2] templates: add whyunstable template keyword

2018-04-14 Thread Yuya Nishihara
On Sat, 14 Apr 2018 20:50:19 +0800, Anton Shestakov wrote:
> On Sat, 14 Apr 2018 21:03:23 +0900
> Yuya Nishihara  wrote:
> > > +def formatnode(ctx):
> > > +return ' %s (%s)' % (scmutil.formatchangeid(ctx), 
> > > ctx.phasestr())  
> > 
> > Nit: leading ' ' isn't nice when you join() the list.
> 
> I was trying to avoid something like '{if(divergentnodes, " ")}', but
> maybe it wouldn't be too bad. I'll come back to this tomorrow.

'{separate(' ', blah, blah, ...)}' could be used instead of if().
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] test-check-commit: don't run hg per commit

2018-04-14 Thread Augie Fackler

> On Apr 14, 2018, at 4:49 AM, Yuya Nishihara  wrote:
> 
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1523694452 -32400
> #  Sat Apr 14 17:27:32 2018 +0900
> # Node ID 34cde18a454484a1cf6e716a3325ca9282277d59
> # Parent  e743b8524d608684b5a947337c37b686cfc0ae5b
> test-check-commit: don't run hg per commit

Queued with enthusiasm, many thanks.

(This has been on my hit list for a while, and I never got around to it.)

> 
> We aren't stress testing CPU.
> 
>  $ time ./run-tests.py -l test-check-commit.t --timeout 600
>  (orig) 162.59s user 17.98s system 101% cpu 2:58.55 total
>  (new)  5.85s user 0.99s system 98% cpu 6.939 total
> 
> diff --git a/tests/test-check-commit.t b/tests/test-check-commit.t
> --- a/tests/test-check-commit.t
> +++ b/tests/test-check-commit.t
> @@ -8,15 +8,16 @@ Go back in the hg repo
> 
>   $ cd $TESTDIR/..
> 
> -  $ for node in `testrepohg log --rev 'not public() and ::. and not desc("# 
> no-check-commit")' --template '{node|short}\n'`; do
> -  >testrepohg export --git $node \
> -  >| contrib/check-commit > ${TESTTMP}/check-commit.out
> +  $ mkdir "$TESTTMP/p"
> +  $ testrepohg export --git -o "$TESTTMP/p/%n-%h" \
> +  > -r 'not public() and ::. and not desc("# no-check-commit")'
> +  $ for f in `ls "$TESTTMP/p"`; do
> +  >contrib/check-commit < "$TESTTMP/p/$f" > "$TESTTMP/check-commit.out"
>>   if [ $? -ne 0 ]; then
> +  >node="${f##*-}"
>>   echo "Revision $node does not comply with rules"
>>   echo '--'
>>   cat ${TESTTMP}/check-commit.out
>>   echo
>>  fi
>> done
> -
> -
> ___
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] test-check-commit: don't run hg per commit

2018-04-14 Thread Matt Harbison

On Sat, 14 Apr 2018 04:49:38 -0400, Yuya Nishihara  wrote:


# HG changeset patch
# User Yuya Nishihara 
# Date 1523694452 -32400
#  Sat Apr 14 17:27:32 2018 +0900
# Node ID 34cde18a454484a1cf6e716a3325ca9282277d59
# Parent  e743b8524d608684b5a947337c37b686cfc0ae5b
test-check-commit: don't run hg per commit

We aren't stress testing CPU.

  $ time ./run-tests.py -l test-check-commit.t --timeout 600
  (orig) 162.59s user 17.98s system 101% cpu 2:58.55 total
  (new)  5.85s user 0.99s system 98% cpu 6.939 total


+1

On my idle Windows laptop:

real17m40.978s
user0m0.045s
sys 0m0.062s

to:

real0m59.448s
user0m0.030s
sys 0m0.062s
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 5 V2] lfs: gracefully handle aborts on the server when corrupt blobs are detected

2018-04-14 Thread Matt Harbison
# HG changeset patch
# User Matt Harbison 
# Date 1519585633 18000
#  Sun Feb 25 14:07:13 2018 -0500
# Node ID 6645ae6f5e2a248f23ec05df1ff6f48f3377cc47
# Parent  414fdd730760f960aaa9b9e8cfb7853b543c8fca
lfs: gracefully handle aborts on the server when corrupt blobs are detected

The aborts weren't killing the server, but this seems cleaner.  I'm not sure if
it matters to handle the remaining IOError in the test like this, for
consistency.

The error code still feels wrong (especially if the client is trying to download
a corrupt blob) but I don't see anything better in the RFCs, and this is already
used elsewhere because the Batch API spec specifically mentioned this as a
"Validation Error".

diff --git a/hgext/lfs/blobstore.py b/hgext/lfs/blobstore.py
--- a/hgext/lfs/blobstore.py
+++ b/hgext/lfs/blobstore.py
@@ -152,7 +152,8 @@ class local(object):
 
 realoid = sha256.hexdigest()
 if realoid != oid:
-raise error.Abort(_('corrupt remote lfs object: %s') % oid)
+raise LfsCorruptionError(_('corrupt remote lfs object: %s')
+ % oid)
 
 self._linktousercache(oid)
 
@@ -526,8 +527,8 @@ def _deduplicate(pointers):
 def _verify(oid, content):
 realoid = hashlib.sha256(content).hexdigest()
 if realoid != oid:
-raise error.Abort(_('detected corrupt lfs object: %s') % oid,
-  hint=_('run hg verify'))
+raise LfsCorruptionError(_('detected corrupt lfs object: %s') % oid,
+ hint=_('run hg verify'))
 
 def remote(repo, remote=None):
 """remotestore factory. return a store in _storemap depending on config
@@ -573,3 +574,8 @@ def remote(repo, remote=None):
 
 class LfsRemoteError(error.RevlogError):
 pass
+
+class LfsCorruptionError(error.Abort):
+"""Raised when a corrupt blob is detected, aborting an operation
+
+It exists to allow specialized handling on the server side."""
diff --git a/hgext/lfs/wireprotolfsserver.py b/hgext/lfs/wireprotolfsserver.py
--- a/hgext/lfs/wireprotolfsserver.py
+++ b/hgext/lfs/wireprotolfsserver.py
@@ -20,6 +20,8 @@ from mercurial import (
 pycompat,
 )
 
+from . import blobstore
+
 HTTP_OK = hgwebcommon.HTTP_OK
 HTTP_CREATED = hgwebcommon.HTTP_CREATED
 HTTP_BAD_REQUEST = hgwebcommon.HTTP_BAD_REQUEST
@@ -276,13 +278,15 @@ def _processbasictransfer(repo, req, res
 #   Content-Length, but what happens if a client sends less than it
 #   says it will?
 
-# TODO: download() will abort if the checksum fails.  It should raise
-#   something checksum specific that can be caught here, and turned
-#   into an http code.
-localstore.download(oid, req.bodyfh)
+statusmessage = hgwebcommon.statusmessage
+try:
+localstore.download(oid, req.bodyfh)
+res.status = statusmessage(HTTP_OK if existed else HTTP_CREATED)
+except blobstore.LfsCorruptionError:
+_logexception(req)
 
-statusmessage = hgwebcommon.statusmessage
-res.status = statusmessage(HTTP_OK if existed else HTTP_CREATED)
+# XXX: Is this the right code?
+res.status = statusmessage(422, b'corrupt blob')
 
 # There's no payload here, but this is the header that lfs-test-server
 # sends back.  This eliminates some gratuitous test output 
conditionals.
@@ -296,9 +300,18 @@ def _processbasictransfer(repo, req, res
 res.status = hgwebcommon.statusmessage(HTTP_OK)
 res.headers[b'Content-Type'] = b'application/octet-stream'
 
-# TODO: figure out how to send back the file in chunks, instead of
-#   reading the whole thing.
-res.setbodybytes(localstore.read(oid))
+try:
+# TODO: figure out how to send back the file in chunks, instead of
+#   reading the whole thing.  (Also figure out how to send back
+#   an error status if an IOError occurs after a partial write
+#   in that case.  Here, everything is read before starting.)
+res.setbodybytes(localstore.read(oid))
+except blobstore.LfsCorruptionError:
+_logexception(req)
+
+# XXX: Is this the right code?
+res.status = hgwebcommon.statusmessage(422, b'corrupt blob')
+res.setbodybytes(b'')
 
 return True
 else:
diff --git a/tests/test-lfs-serve-access.t b/tests/test-lfs-serve-access.t
--- a/tests/test-lfs-serve-access.t
+++ b/tests/test-lfs-serve-access.t
@@ -236,7 +236,7 @@ Test a bad checksum sent by the client i
   $ hg -R client push http://localhost:$HGPORT1
   pushing to http://localhost:$HGPORT1/
   searching for changes
-  abort: HTTP error: HTTP Error 500: Internal Server Error 
(oid=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c, 
action=upload)!
+  abort: HTTP error: HTTP Error 422: corrupt 

[PATCH 3 of 5 V2] lfs: fix the inferred remote store path when using a --prefix

2018-04-14 Thread Matt Harbison
# HG changeset patch
# User Matt Harbison 
# Date 1523643390 14400
#  Fri Apr 13 14:16:30 2018 -0400
# Node ID 414fdd730760f960aaa9b9e8cfb7853b543c8fca
# Parent  f5420feae687abf2e16e8444c385bdac9eedfeab
lfs: fix the inferred remote store path when using a --prefix

This wasn't appending the '.git/info/lfs' path in this case.

diff --git a/hgext/lfs/blobstore.py b/hgext/lfs/blobstore.py
--- a/hgext/lfs/blobstore.py
+++ b/hgext/lfs/blobstore.py
@@ -561,7 +561,7 @@ def remote(repo, remote=None):
 if defaulturl.scheme in (b'http', b'https'):
 if defaulturl.path and defaulturl.path[:-1] != b'/':
 defaulturl.path += b'/'
-defaulturl.path = defaulturl.path or b'' + b'.git/info/lfs'
+defaulturl.path = (defaulturl.path or b'') + b'.git/info/lfs'
 
 url = util.url(bytes(defaulturl))
 repo.ui.note(_('lfs: assuming remote store: %s\n') % url)
diff --git a/tests/test-lfs-serve-access.t b/tests/test-lfs-serve-access.t
--- a/tests/test-lfs-serve-access.t
+++ b/tests/test-lfs-serve-access.t
@@ -73,8 +73,7 @@ Blob URIs are correct when --prefix is u
   >-A $TESTTMP/access.log -E $TESTTMP/errors.log
   $ cat hg.pid >> $DAEMON_PIDS
 
-  $ hg --config 
lfs.url=http://localhost:$HGPORT/subdir/mount/point/.git/info/lfs \
-  >clone --debug http://localhost:$HGPORT/subdir/mount/point cloned2
+  $ hg clone --debug http://localhost:$HGPORT/subdir/mount/point cloned2
   using http://localhost:$HGPORT/subdir/mount/point
   sending capabilities command
   query 1; heads
@@ -104,6 +103,7 @@ Blob URIs are correct when --prefix is u
   resolving manifests
branchmerge: False, force: False, partial: False
ancestor: , local: +, remote: 525251863cad
+  lfs: assuming remote store: 
http://localhost:$HGPORT/subdir/mount/point/.git/info/lfs
   Status: 200
   Content-Length: 371
   Content-Type: application/vnd.git-lfs+json
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 5 V2] test-lfs: add tests to force server error path coverage

2018-04-14 Thread Matt Harbison
# HG changeset patch
# User Matt Harbison 
# Date 1523119701 14400
#  Sat Apr 07 12:48:21 2018 -0400
# Node ID a83bc37bcf3da077f78bf3377b88b61d328bd4ce
# Parent  9d509015742603624ef0df5497f0f205d8768ebf
test-lfs: add tests to force server error path coverage

The tests are somewhat fragile in that the extension that forces the errors is
counting how many times some of the functions are being called, so it depends
heavily on the content of the repo.  Maybe we can do something clever like load
an extension on the client, and have it send over instructions in the HTTP
header how to fail.  (I'm trying to avoid killing and restarting the server,
because Windows seems to have issues with doing that a lot.)  But I'd rather fix
issues than polish tests before the freeze.

diff --git a/tests/test-lfs-serve-access.t b/tests/test-lfs-serve-access.t
--- a/tests/test-lfs-serve-access.t
+++ b/tests/test-lfs-serve-access.t
@@ -4,7 +4,6 @@
   > [extensions]
   > lfs=
   > [lfs]
-  > url=http://localhost:$HGPORT/.git/info/lfs
   > track=all()
   > [web]
   > push_ssl = False
@@ -149,3 +148,187 @@ Blob URIs are correct when --prefix is u
   $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=getbundle HTTP/1.1" 
200 - 
x-hgarg-1:bookmarks=1=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2=1==525251863cad618e55d483555f3d00a2ca99597e=bookmarks=1
 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "POST 
/subdir/mount/point/.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
   $LOCALIP - - [$LOGDATE$] "GET 
/subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e
 HTTP/1.1" 200 - (glob)
+
+  $ cat >> $TESTTMP/lfsstoreerror.py < import errno
+  > from hgext.lfs import blobstore
+  > 
+  > _numverifies = 0
+  > _readerr = True
+  > 
+  > def reposetup(ui, repo):
+  > # Nothing to do with a remote repo
+  > if not repo.local():
+  > return
+  > 
+  > store = repo.svfs.lfslocalblobstore
+  > class badstore(store.__class__):
+  > def download(self, oid, src):
+  > '''Called in the server to handle reading from the client in a
+  > PUT request.'''
+  > origread = src.read
+  > def _badread(nbytes):
+  > # Simulate bad data/checksum failure from the client
+  > return b'0' * len(origread(nbytes))
+  > src.read = _badread
+  > super(badstore, self).download(oid, src)
+  > 
+  > def _read(self, vfs, oid, verify):
+  > '''Called in the server to read data for a GET request, and 
then
+  > calls self._verify() on it before returning.'''
+  > global _readerr
+  > # One time simulation of a read error
+  > if _readerr:
+  > _readerr = False
+  > raise IOError(errno.EIO, '%s: I/O error' % oid)
+  > # Simulate corrupt content on client download
+  > blobstore._verify(oid, 'dummy content')
+  > 
+  > def verify(self, oid):
+  > '''Called in the server to populate the Batch API response,
+  > letting the client re-upload if the file is corrupt.'''
+  > # Fail verify in Batch API for one clone command and one push
+  > # command with an IOError.  Then let it through to access other
+  > # functions.  Checksum failure is tested elsewhere.
+  > global _numverifies
+  > _numverifies += 1
+  > if _numverifies <= 2:
+  > raise IOError(errno.EIO, '%s: I/O error' % oid)
+  > return super(badstore, self).verify(oid)
+  > 
+  > store.__class__ = badstore
+  > EOF
+
+  $ rm -rf `hg config lfs.usercache`
+  $ rm -f $TESTTMP/access.log $TESTTMP/errors.log
+  $ hg --config "lfs.usercache=$TESTTMP/servercache" \
+  >--config extensions.lfsstoreerror=$TESTTMP/lfsstoreerror.py \
+  >-R server serve -d \
+  >-p $HGPORT1 --pid-file=hg.pid -A $TESTTMP/access.log -E 
$TESTTMP/errors.log
+  $ cat hg.pid >> $DAEMON_PIDS
+
+Test an I/O error in localstore.verify() (Batch API) with GET
+
+  $ hg clone http://localhost:$HGPORT1 httpclone2
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  new changesets 525251863cad
+  updating to branch default
+  abort: LFS server error for "lfs.bin": Internal server error!
+  [255]
+
+Test an I/O error in localstore.verify() (Batch API) with PUT
+
+  $ echo foo > client/lfs.bin
+  $ hg -R client ci -m 'mod lfs'
+  $ 

[PATCH 5 of 5 V2] lfs: update the HTTP status codes in error cases

2018-04-14 Thread Matt Harbison
# HG changeset patch
# User Matt Harbison 
# Date 1523651553 14400
#  Fri Apr 13 16:32:33 2018 -0400
# Node ID 075edc6d6add061ac13578bc3301c581de347412
# Parent  6645ae6f5e2a248f23ec05df1ff6f48f3377cc47
lfs: update the HTTP status codes in error cases

I'm not bothering with validating PUT requests (for now), because the spec
doesn't explicitly call out a Content-Type (though the example transcript does
use the sensible 'application/octet-stream').

diff --git a/hgext/lfs/wireprotolfsserver.py b/hgext/lfs/wireprotolfsserver.py
--- a/hgext/lfs/wireprotolfsserver.py
+++ b/hgext/lfs/wireprotolfsserver.py
@@ -26,6 +26,9 @@ HTTP_OK = hgwebcommon.HTTP_OK
 HTTP_CREATED = hgwebcommon.HTTP_CREATED
 HTTP_BAD_REQUEST = hgwebcommon.HTTP_BAD_REQUEST
 HTTP_NOT_FOUND = hgwebcommon.HTTP_NOT_FOUND
+HTTP_METHOD_NOT_ALLOWED = hgwebcommon.HTTP_METHOD_NOT_ALLOWED
+HTTP_NOT_ACCEPTABLE = hgwebcommon.HTTP_NOT_ACCEPTABLE
+HTTP_UNSUPPORTED_MEDIA_TYPE = hgwebcommon.HTTP_UNSUPPORTED_MEDIA_TYPE
 
 def handlewsgirequest(orig, rctx, req, res, checkperm):
 """Wrap wireprotoserver.handlewsgirequest() to possibly process an LFS
@@ -105,12 +108,16 @@ def _processbatchrequest(repo, req, res)
 # "operation": "upload"
 #  }
 
-if (req.method != b'POST'
-or req.headers[b'Content-Type'] != b'application/vnd.git-lfs+json'
-or req.headers[b'Accept'] != b'application/vnd.git-lfs+json'):
-# TODO: figure out what the proper handling for a bad request to the
-#   Batch API is.
-_sethttperror(res, HTTP_BAD_REQUEST, b'Invalid Batch API request')
+if req.method != b'POST':
+_sethttperror(res, HTTP_METHOD_NOT_ALLOWED)
+return True
+
+if req.headers[b'Content-Type'] != b'application/vnd.git-lfs+json':
+_sethttperror(res, HTTP_UNSUPPORTED_MEDIA_TYPE)
+return True
+
+if req.headers[b'Accept'] != b'application/vnd.git-lfs+json':
+_sethttperror(res, HTTP_NOT_ACCEPTABLE)
 return True
 
 # XXX: specify an encoding?
@@ -315,6 +322,6 @@ def _processbasictransfer(repo, req, res
 
 return True
 else:
-_sethttperror(res, HTTP_BAD_REQUEST,
+_sethttperror(res, HTTP_METHOD_NOT_ALLOWED,
   message=b'Unsupported LFS transfer method: %s' % method)
 return True
diff --git a/mercurial/hgweb/common.py b/mercurial/hgweb/common.py
--- a/mercurial/hgweb/common.py
+++ b/mercurial/hgweb/common.py
@@ -30,6 +30,8 @@ HTTP_UNAUTHORIZED = 401
 HTTP_FORBIDDEN = 403
 HTTP_NOT_FOUND = 404
 HTTP_METHOD_NOT_ALLOWED = 405
+HTTP_NOT_ACCEPTABLE = 406
+HTTP_UNSUPPORTED_MEDIA_TYPE = 415
 HTTP_SERVER_ERROR = 500
 
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 5 V2] lfs: log information about Internal Server Errors reported in the Batch API

2018-04-14 Thread Matt Harbison
# HG changeset patch
# User Matt Harbison 
# Date 1523637594 14400
#  Fri Apr 13 12:39:54 2018 -0400
# Node ID f5420feae687abf2e16e8444c385bdac9eedfeab
# Parent  a83bc37bcf3da077f78bf3377b88b61d328bd4ce
lfs: log information about Internal Server Errors reported in the Batch API

Reporting a 500 and then not leaving any traces on the server seems like a
receipe for frustration.  There's similar log writing in hgweb.server.do_POST().
That doesn't write directly to the wsgi.errors object, so it doesn't seem worth
trying to refactor.

It does seem like earlier stack frames are missing for some reason.

diff --git a/hgext/lfs/wireprotolfsserver.py b/hgext/lfs/wireprotolfsserver.py
--- a/hgext/lfs/wireprotolfsserver.py
+++ b/hgext/lfs/wireprotolfsserver.py
@@ -10,6 +10,7 @@ from __future__ import absolute_import
 import datetime
 import errno
 import json
+import traceback
 
 from mercurial.hgweb import (
 common as hgwebcommon,
@@ -63,6 +64,19 @@ def _sethttperror(res, code, message=Non
 res.headers[b'Content-Type'] = b'text/plain; charset=utf-8'
 res.setbodybytes(b'')
 
+def _logexception(req):
+"""Write information about the current exception to wsgi.errors."""
+tb = pycompat.sysbytes(traceback.format_exc())
+errorlog = req.rawenv[r'wsgi.errors']
+
+uri = b''
+if req.apppath:
+uri += req.apppath
+uri += b'/' + req.dispatchpath
+
+errorlog.write(b"Exception happened while processing request '%s':\n%s" %
+   (uri, tb))
+
 def _processbatchrequest(repo, req, res):
 """Handle a request for the Batch API, which is the gateway to granting 
file
 access.
@@ -179,6 +193,8 @@ def _batchresponseobjects(req, objects, 
 verifies = store.verify(oid)
 except IOError as inst:
 if inst.errno != errno.ENOENT:
+_logexception(req)
+
 rsp['error'] = {
 'code': 500,
 'message': inst.strerror or 'Internal Server Server'
diff --git a/tests/test-lfs-serve-access.t b/tests/test-lfs-serve-access.t
--- a/tests/test-lfs-serve-access.t
+++ b/tests/test-lfs-serve-access.t
@@ -289,6 +289,18 @@ Test a checksum failure during the proce
   $LOCALIP - - [$LOGDATE$] "GET 
/.hg/lfs/objects/276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d
 HTTP/1.1" 500 - (glob)
 
   $ grep -v '  File "' $TESTTMP/errors.log
+  $LOCALIP - - [$ERRDATE$] HG error:  Exception happened while processing 
request '/.git/info/lfs/objects/batch': (glob)
+  $LOCALIP - - [$ERRDATE$] HG error:  Traceback (most recent call last): (glob)
+  $LOCALIP - - [$ERRDATE$] HG error:  verifies = store.verify(oid) (glob)
+  $LOCALIP - - [$ERRDATE$] HG error:  raise IOError(errno.EIO, '%s: I/O 
error' % oid) (glob)
+  $LOCALIP - - [$ERRDATE$] HG error:  IOError: [Errno 5] 
f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e: I/O error 
(glob)
+  $LOCALIP - - [$ERRDATE$] HG error:   (glob)
+  $LOCALIP - - [$ERRDATE$] HG error:  Exception happened while processing 
request '/.git/info/lfs/objects/batch': (glob)
+  $LOCALIP - - [$ERRDATE$] HG error:  Traceback (most recent call last): (glob)
+  $LOCALIP - - [$ERRDATE$] HG error:  verifies = store.verify(oid) (glob)
+  $LOCALIP - - [$ERRDATE$] HG error:  raise IOError(errno.EIO, '%s: I/O 
error' % oid) (glob)
+  $LOCALIP - - [$ERRDATE$] HG error:  IOError: [Errno 5] 
b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c: I/O error 
(glob)
+  $LOCALIP - - [$ERRDATE$] HG error:   (glob)
   $LOCALIP - - [$ERRDATE$] Exception happened during processing request 
'/.hg/lfs/objects/b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c':
 (glob)
   Traceback (most recent call last):
   self.do_write()
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 5] test-lfs: add tests to force server error path coverage

2018-04-14 Thread Matt Harbison

On Sat, 14 Apr 2018 03:28:49 -0400, Yuya Nishihara  wrote:


On Fri, 13 Apr 2018 18:04:33 -0400, Matt Harbison wrote:

# HG changeset patch
# User Matt Harbison 
# Date 1523119701 14400
#  Sat Apr 07 12:48:21 2018 -0400
# Node ID 1d394ac0efd4aa4f61f428fbac140fe57398f0b8
# Parent  bfdd20d22a86edc318493b4da84a1d7ff4ef98f2
test-lfs: add tests to force server error path coverage


The test failed on my machine. Can you take a look?


It crossed paths with 330ada7e8ea5.  Will resend.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] dispatch: add a whitelist map of commands to implicitly loaded extensions

2018-04-14 Thread Matt Harbison

On Sat, 14 Apr 2018 03:09:01 -0400, Yuya Nishihara  wrote:


On Fri, 13 Apr 2018 23:30:43 -0400, Matt Harbison wrote:

On Fri, 13 Apr 2018 15:10:45 -0400, Gregory Szorc
 wrote:
> What we may want instead is to key things off .hg/requires or a
> to-be-invented supplemental requirements-like file that declares soft
> features. localrepository.__init__ could then load trusted extensions  
at
> repo open time if a requirements/capability was present/requested.  
i.e.

> if
> you talk to an LFS server, write a semaphore somewhere into .hg/ and  
have

> something in core look for that and automatically load lfs if present.
> This would get you the "automatically enable LFS when talking to LFS
> servers"
> benefits.

Sounds promising.  One of the things the lfs extension is doing is  
writing

'[extensions]\nlfs=' to the repo's local hgrc file in a commit hook (it
should probably be handling transactions too).  So it would be nice if
this was baked into the core somehow (largefiles could use exactly the
same handling, and I'm assuming narrow will be similar).  It's also
manually adding to the requires file, since that doesn't seem to be
updated in exchange.

Assuming the semaphore is persistent, it could be beneficial to load
extensions indicated by it around the normal load time (e.g., largefiles
wraps the clone command and adds extra switches).

I'm not sure if this addresses Yuya's concern about long lived processes
though.


If the extensions to be loaded are bound to a repo, yes, that should be
fine. A well-designed extension should check the repo requirements. What
doesn't work in command server is to load extensions per-command basis.


While "bound to a repo" makes it sound like the extension would be  
isolated and could unload if the repo is GC'd, what I don't get is what  
that phrase means for all of the module functions that are wrapped.

___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D2880: bundle: add the possibility to bundle bookmarks (issue5792)

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz added inline comments.

INLINE COMMENTS

> lothiraldan wrote in test-bundle-bookmarks.t:37-63
> I have added such test and indeed this case is not handled right now. I'm not 
> aware of how Mercurial handle this case when exchanging bookmarks, I will 
> need to take a look at the code to find out.
> 
> What is the correct behavior here? Change the existing bookmark or the 
> bookmark from the bundle?

I think it should be the same thing as pulling from another repo. Try putting 
the same changes in another repo and pulling from it without giving the path a 
name (nothing in [paths] config). I haven't checked what suffix will be used on 
the divergent bookmark, but it probably makes sense to use the same here 
(perhaps it's just going to be "https://phab.mercurial-scm.org/D1@1; as I 
guessed before).

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D2880

To: lothiraldan, #hg-reviewers, indygreg
Cc: martinvonz, indygreg, pulkit, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 3] makefile: add Ubuntu Bionic docker targets (.deb and ppa)

2018-04-14 Thread Antonio Muci via Mercurial-devel
# HG changeset patch
# User Antonio Muci 
# Date 1523713197 -7200
#  Sat Apr 14 15:39:57 2018 +0200
# Node ID b29e5ecc90eef3af76eaaa4c21b992da66b8e444
# Parent  b5874ec21df592d83c3f97aa12ea33dfdb03e839
makefile: add Ubuntu Bionic docker targets (.deb and ppa)

Bionic Beaver is an LTS release, supported until 2023-04.

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -239,6 +239,12 @@ docker-ubuntu-artful: contrib/docker/ubu
 docker-ubuntu-artful-ppa: contrib/docker/ubuntu-artful
contrib/dockerdeb ubuntu artful --source-only
 
+docker-ubuntu-bionic: contrib/docker/ubuntu-bionic
+   contrib/dockerdeb ubuntu bionic
+
+docker-ubuntu-bionic-ppa: contrib/docker/ubuntu-bionic
+   contrib/dockerdeb ubuntu bionic --source-only
+
 fedora20:
mkdir -p packages/fedora20
contrib/buildrpm
@@ -308,6 +314,7 @@ linux-wheels-i686:
docker-ubuntu-trusty docker-ubuntu-trusty-ppa \
docker-ubuntu-xenial docker-ubuntu-xenial-ppa \
docker-ubuntu-artful docker-ubuntu-artful-ppa \
+   docker-ubuntu-bionic docker-ubuntu-bionic-ppa \
fedora20 docker-fedora20 \
fedora21 docker-fedora21 \
centos5 docker-centos5 \
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 3] makefile: reformat .PHONY targets

2018-04-14 Thread Antonio Muci via Mercurial-devel
# HG changeset patch
# User Antonio Muci 
# Date 1523723037 -7200
#  Sat Apr 14 18:23:57 2018 +0200
# Node ID b5874ec21df592d83c3f97aa12ea33dfdb03e839
# Parent  3c8463e542db60db1ad234ec80f39e290ed17658
makefile: reformat .PHONY targets

the list of make targets is likely to evolve over time.
This reformatting streamlines future patches.

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -302,10 +302,15 @@ linux-wheels-i686:
 .PHONY: help all local build doc cleanbutpackages clean install install-bin \
install-doc install-home install-home-bin install-home-doc \
dist dist-notests check tests check-code format-c update-pot \
-   osx deb ppa docker-debian-jessie docker-debian-stretch \
+   osx deb ppa \
+   docker-debian-jessie \
+   docker-debian-stretch \
docker-ubuntu-trusty docker-ubuntu-trusty-ppa \
docker-ubuntu-xenial docker-ubuntu-xenial-ppa \
docker-ubuntu-artful docker-ubuntu-artful-ppa \
-   fedora20 docker-fedora20 fedora21 docker-fedora21 \
-   centos5 docker-centos5 centos6 docker-centos6 centos7 docker-centos7 \
+   fedora20 docker-fedora20 \
+   fedora21 docker-fedora21 \
+   centos5 docker-centos5 \
+   centos6 docker-centos6 \
+   centos7 docker-centos7 \
linux-wheels
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 3] makefile: mkdir is not needed on templatized docker builds

2018-04-14 Thread Antonio Muci via Mercurial-devel
# HG changeset patch
# User Antonio Muci 
# Date 1523714275 -7200
#  Sat Apr 14 15:57:55 2018 +0200
# Node ID 3c8463e542db60db1ad234ec80f39e290ed17658
# Parent  1541e1a8e87de9bd6b869ed498ad8e9b93c59d4d
makefile: mkdir is not needed on templatized docker builds

this imitates e63dfbbdbd07 and is a small addition to 231690dba9b4 and
5c1283713293

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -213,11 +213,9 @@ contrib/docker/debian-%: contrib/docker/
sed "s/__CODENAME__/$*/" $< > $@
 
 docker-debian-jessie: contrib/docker/debian-jessie
-   mkdir -p packages/debian-jessie
contrib/dockerdeb debian jessie
 
 docker-debian-stretch: contrib/docker/debian-stretch
-   mkdir -p packages/debian-stretch
contrib/dockerdeb debian stretch
 
 contrib/docker/ubuntu-%: contrib/docker/ubuntu.template
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3371: scmutil: make shortesthexnodeidprefix() take a full binary nodeid

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8286.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3371?vs=8256=8286

REVISION DETAIL
  https://phab.mercurial-scm.org/D3371

AFFECTED FILES
  hgext/show.py
  mercurial/scmutil.py
  mercurial/templatefuncs.py
  tests/test-command-template.t

CHANGE DETAILS

diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -3900,6 +3900,21 @@
   $ hg log -r 'wdir()' -T '{node|shortest}\n'
   
 
+  $ hg log --template '{shortest("f")}\n' -l1
+  f
+
+  $ hg log --template 
'{shortest("0123456789012345678901234567890123456789")}\n' -l1
+  0123456789012345678901234567890123456789
+
+  $ hg log --template 
'{shortest("01234567890123456789012345678901234567890123456789")}\n' -l1
+  01234567890123456789012345678901234567890123456789
+
+  $ hg log --template '{shortest("not a hex string")}\n' -l1
+  not a hex string
+
+  $ hg log --template '{shortest("not a hex string, but it'\''s 40 bytes 
long")}\n' -l1
+  not a hex string, but it's 40 bytes long
+
   $ cd ..
 
 Test shortest(node) with the repo having short hash collision:
diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -26,6 +26,9 @@
 templateutil,
 util,
 )
+from .node import (
+bin,
+)
 from .utils import (
 dateutil,
 stringutil,
@@ -579,15 +582,29 @@
 # i18n: "shortest" is a keyword
 raise error.ParseError(_("shortest() expects one or two arguments"))
 
-node = evalstring(context, mapping, args[0])
+hexnode = evalstring(context, mapping, args[0])
 
 minlength = 4
 if len(args) > 1:
 minlength = evalinteger(context, mapping, args[1],
 # i18n: "shortest" is a keyword
 _("shortest() expects an integer minlength"))
 
 repo = context.resource(mapping, 'ctx')._repo
+if len(hexnode) > 40:
+return hexnode
+elif len(hexnode) == 40:
+try:
+node = bin(hexnode)
+except TypeError:
+return hexnode
+else:
+try:
+node = scmutil.resolvehexnodeidprefix(repo, hexnode)
+except (error.LookupError, error.WdirUnsupported):
+return hexnode
+if not node:
+return hexnode
 return scmutil.shortesthexnodeidprefix(repo, node, minlength)
 
 @templatefunc('strip(text[, chars])')
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -443,12 +443,12 @@
 repo.changelog.rev(node)  # make sure node isn't filtered
 return node
 
-def shortesthexnodeidprefix(repo, hexnode, minlength=1):
+def shortesthexnodeidprefix(repo, node, minlength=1):
 """Find the shortest unambiguous prefix that matches hexnode."""
 # _partialmatch() of filtered changelog could take O(len(repo)) time,
 # which would be unacceptably slow. so we look for hash collision in
 # unfiltered space, which means some hashes may be slightly longer.
-return repo.unfiltered().changelog.shortest(hexnode, minlength)
+return repo.unfiltered().changelog.shortest(hex(node), minlength)
 
 def isrevsymbol(repo, symbol):
 """Checks if a symbol exists in the repo.
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -29,7 +29,6 @@
 
 from mercurial.i18n import _
 from mercurial.node import (
-hex,
 nullrev,
 )
 from mercurial import (
@@ -448,8 +447,8 @@
 if not revs:
 return minlen
 cl = repo.changelog
-return max(len(scmutil.shortesthexnodeidprefix(repo, hex(cl.node(r)),
-   minlen)) for r in revs)
+return max(len(scmutil.shortesthexnodeidprefix(repo, cl.node(r), minlen))
+   for r in revs)
 
 # Adjust the docstring of the show command so it shows all registered views.
 # This is a bit hacky because it runs at the end of module load. When moved



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3309: scmutil: rename resolvepartialhexnodeid() to resolvehexnodeidprefix()

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8283.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3309?vs=8260=8283

REVISION DETAIL
  https://phab.mercurial-scm.org/D3309

AFFECTED FILES
  hgext/eol.py
  hgext/histedit.py
  mercurial/context.py
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -434,8 +434,8 @@
 hexfunc = short
 return '%d:%s' % (rev, hexfunc(node))
 
-def resolvepartialhexnodeid(repo, prefix):
-# Uses unfiltered repo because it's faster when then prefix is ambiguous/
+def resolvehexnodeidprefix(repo, prefix):
+# Uses unfiltered repo because it's faster when prefix is ambiguous/
 # This matches the "shortest" template function.
 node = repo.unfiltered().changelog._partialmatch(prefix)
 if node is None:
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -392,7 +392,7 @@
 #  * If you know that "x" is a branch or in some other namespace,
 #use the appropriate mechanism for that namespace
 #  * If you know that "x" is a hex nodeid prefix, use
-#repo[scmutil.resolvepartialhexnodeid(repo, x)]
+#repo[scmutil.resolvehexnodeidprefix(repo, x)]
 #  * If "x" is a string that can be any of the above, but you don't want
 #to allow general revsets (perhaps because "x" may come from a remote
 #user and the revset may be too costly), use scmutil.revsymbol(repo, x)
@@ -476,7 +476,7 @@
 except KeyError:
 pass
 
-self._node = scmutil.resolvepartialhexnodeid(repo, changeid)
+self._node = scmutil.resolvehexnodeidprefix(repo, changeid)
 if self._node is not None:
 self._rev = repo.changelog.rev(self._node)
 changectxdeprecwarn(repo)
diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -443,7 +443,7 @@
 """ Verifies semantic correctness of the rule"""
 repo = self.repo
 ha = node.hex(self.node)
-self.node = scmutil.resolvepartialhexnodeid(repo, ha)
+self.node = scmutil.resolvehexnodeidprefix(repo, ha)
 if self.node is None:
 raise error.ParseError(_('unknown changeset %s listed') % ha[:12])
 self._verifynodeconstraints(prev, expected, seen)
diff --git a/hgext/eol.py b/hgext/eol.py
--- a/hgext/eol.py
+++ b/hgext/eol.py
@@ -300,7 +300,7 @@
 hook = checkheadshook
 
 def preupdate(ui, repo, hooktype, parent1, parent2):
-p1node = scmutil.resolvepartialhexnodeid(repo, parent1)
+p1node = scmutil.resolvehexnodeidprefix(repo, parent1)
 repo.loadeol([p1node])
 return False
 



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3310: scmutil: use resolvehexnodeidprefix() from revsymbol()

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8284.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3310?vs=8261=8284

REVISION DETAIL
  https://phab.mercurial-scm.org/D3310

AFFECTED FILES
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -503,7 +503,7 @@
 except KeyError:
 pass
 
-node = repo.unfiltered().changelog._partialmatch(symbol)
+node = resolvehexnodeidprefix(repo, symbol)
 if node is not None:
 rev = repo.changelog.rev(node)
 return repo[rev]



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3370: scmutil: introduce shortesthexnodeidprefix()

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8285.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3370?vs=8262=8285

REVISION DETAIL
  https://phab.mercurial-scm.org/D3370

AFFECTED FILES
  hgext/show.py
  mercurial/scmutil.py
  mercurial/templatefuncs.py

CHANGE DETAILS

diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -590,8 +590,8 @@
 # _partialmatch() of filtered changelog could take O(len(repo)) time,
 # which would be unacceptably slow. so we look for hash collision in
 # unfiltered space, which means some hashes may be slightly longer.
-cl = context.resource(mapping, 'ctx')._repo.unfiltered().changelog
-return cl.shortest(node, minlength)
+repo = context.resource(mapping, 'ctx')._repo
+return scmutil.shortesthexnodeidprefix(repo.unfiltered(), node, minlength)
 
 @templatefunc('strip(text[, chars])')
 def strip(context, mapping, args):
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -443,6 +443,10 @@
 repo.changelog.rev(node)  # make sure node isn't filtered
 return node
 
+def shortesthexnodeidprefix(repo, hexnode, minlength=1):
+"""Find the shortest unambiguous prefix that matches hexnode."""
+return repo.changelog.shortest(hexnode, minlength)
+
 def isrevsymbol(repo, symbol):
 """Checks if a symbol exists in the repo.
 
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -45,6 +45,7 @@
 registrar,
 revset,
 revsetlang,
+scmutil,
 )
 
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' 
for
@@ -447,8 +448,10 @@
 if not revs:
 return minlen
 # don't use filtered repo because it's slow. see templater.shortest().
-cl = repo.unfiltered().changelog
-return max(len(cl.shortest(hex(cl.node(r)), minlen)) for r in revs)
+cl = repo.changelog
+return max(len(scmutil.shortesthexnodeidprefix(repo.unfiltered(),
+   hex(cl.node(r)),
+   minlen)) for r in revs)
 
 # Adjust the docstring of the show command so it shows all registered views.
 # This is a bit hacky because it runs at the end of module load. When moved



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3308: scmutil: document that isrevsymbol() raises on ambiguous node prefix

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8282.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3308?vs=8259=8282

REVISION DETAIL
  https://phab.mercurial-scm.org/D3308

AFFECTED FILES
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -444,6 +444,11 @@
 return node
 
 def isrevsymbol(repo, symbol):
+"""Checks if a symbol exists in the repo.
+
+   See revsymbol() for details. Raises error.LookupError if the symbol is 
an
+   ambiguous nodeid prefix.
+"""
 try:
 revsymbol(repo, symbol)
 return True



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3311: revset: use resolvehexnodeidprefix() in id() predicate (BC)

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz added a comment.


  In https://phab.mercurial-scm.org/D3311#53712, @yuja wrote:
  
  > I have vague memory that it was intentional. Since `rev()` and `id()` never
  >  error out on unknown identifier, it doesn't make sense to reject only
  >  ambiguous nodeid.
  
  
  I'm fine with dropping this patch. The rest of the stack doesn't depend on it 
anyway.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3311

To: martinvonz, #hg-reviewers, yuja
Cc: yuja, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3375: cleanup: polyfill assertRaisesRegex so we can avoid assertRaisesRegexp

2018-04-14 Thread durin42 (Augie Fackler)
durin42 updated this revision to Diff 8281.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3375?vs=8280=8281

REVISION DETAIL
  https://phab.mercurial-scm.org/D3375

AFFECTED FILES
  tests/test-simplekeyvaluefile.py
  tests/test-wireproto-clientreactor.py
  tests/test-wireproto-framing.py
  tests/test-wsgirequest.py

CHANGE DETAILS

diff --git a/tests/test-wsgirequest.py b/tests/test-wsgirequest.py
--- a/tests/test-wsgirequest.py
+++ b/tests/test-wsgirequest.py
@@ -196,21 +196,27 @@
 self.assertEqual(r.dispatchparts, [b'pathinfo'])
 self.assertEqual(r.dispatchpath, b'pathinfo')
 
+if not getattr(unittest.TestCase, 'assertRaisesRegex', False):
+# Python 3.7 deprecates the regex*p* version, but 2.7 lacks
+# the regex version.
+assertRaisesRegex = (# camelcase-required
+unittest.TestCase.assertRaisesRegexp)
+
 def testreponame(self):
 """repository path components get stripped from URL."""
 
-with self.assertRaisesRegexp(error.ProgrammingError,
+with self.assertRaisesRegex(error.ProgrammingError,
  b'reponame requires PATH_INFO'):
 parse(DEFAULT_ENV, reponame=b'repo')
 
-with self.assertRaisesRegexp(error.ProgrammingError,
+with self.assertRaisesRegex(error.ProgrammingError,
  b'PATH_INFO does not begin with repo '
  b'name'):
 parse(DEFAULT_ENV, reponame=b'repo', extra={
 r'PATH_INFO': r'/pathinfo',
 })
 
-with self.assertRaisesRegexp(error.ProgrammingError,
+with self.assertRaisesRegex(error.ProgrammingError,
  b'reponame prefix of PATH_INFO'):
 parse(DEFAULT_ENV, reponame=b'repo', extra={
 r'PATH_INFO': r'/repoextra/path',
diff --git a/tests/test-wireproto-framing.py b/tests/test-wireproto-framing.py
--- a/tests/test-wireproto-framing.py
+++ b/tests/test-wireproto-framing.py
@@ -103,19 +103,25 @@
 ffs(b'1 1 0 command-data eos %s' % data.getvalue()),
 ])
 
+if not getattr(unittest.TestCase, 'assertRaisesRegex', False):
+# Python 3.7 deprecates the regex*p* version, but 2.7 lacks
+# the regex version.
+assertRaisesRegex = (# camelcase-required
+unittest.TestCase.assertRaisesRegexp)
+
 def testtextoutputformattingstringtype(self):
 """Formatting string must be bytes."""
-with self.assertRaisesRegexp(ValueError, 'must use bytes formatting '):
+with self.assertRaisesRegex(ValueError, 'must use bytes formatting '):
 list(framing.createtextoutputframe(None, 1, [
 (b'foo'.decode('ascii'), [], [])]))
 
 def testtextoutputargumentbytes(self):
-with self.assertRaisesRegexp(ValueError, 'must use bytes for 
argument'):
+with self.assertRaisesRegex(ValueError, 'must use bytes for argument'):
 list(framing.createtextoutputframe(None, 1, [
 (b'foo', [b'foo'.decode('ascii')], [])]))
 
 def testtextoutputlabelbytes(self):
-with self.assertRaisesRegexp(ValueError, 'must use bytes for labels'):
+with self.assertRaisesRegex(ValueError, 'must use bytes for labels'):
 list(framing.createtextoutputframe(None, 1, [
 (b'foo', [], [b'foo'.decode('ascii')])]))
 
diff --git a/tests/test-wireproto-clientreactor.py 
b/tests/test-wireproto-clientreactor.py
--- a/tests/test-wireproto-clientreactor.py
+++ b/tests/test-wireproto-clientreactor.py
@@ -24,6 +24,13 @@
 
 class SingleSendTests(unittest.TestCase):
 """A reactor that can only send once rejects subsequent sends."""
+
+if not getattr(unittest.TestCase, 'assertRaisesRegex', False):
+# Python 3.7 deprecates the regex*p* version, but 2.7 lacks
+# the regex version.
+assertRaisesRegex = (# camelcase-required
+unittest.TestCase.assertRaisesRegexp)
+
 def testbasic(self):
 reactor = framing.clientreactor(hasmultiplesend=False, 
buffersends=True)
 
@@ -39,11 +46,11 @@
 
 self.assertEqual(request.state, b'sent')
 
-with self.assertRaisesRegexp(error.ProgrammingError,
+with self.assertRaisesRegex(error.ProgrammingError,
  'cannot issue new commands'):
 reactor.callcommand(b'foo', {})
 
-with self.assertRaisesRegexp(error.ProgrammingError,
+with self.assertRaisesRegex(error.ProgrammingError,
  'cannot issue new commands'):
 reactor.callcommand(b'foo', {})
 
@@ -77,6 +84,12 @@
 self.assertEqual(request.state, b'sent')
 
 class BadFrameRecvTests(unittest.TestCase):
+if not getattr(unittest.TestCase, 'assertRaisesRegex', False):
+# Python 3.7 deprecates the regex*p* version, but 2.7 lacks
+# the 

D3375: cleanup: polyfill assertRaisesRegex so we can avoid assertRaisesRegexp

2018-04-14 Thread durin42 (Augie Fackler)
durin42 created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The latter is deprecated on Python 3.7 and causes our tests to fail
  due to the warning.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3375

AFFECTED FILES
  tests/test-simplekeyvaluefile.py
  tests/test-wireproto-clientreactor.py
  tests/test-wireproto-framing.py
  tests/test-wsgirequest.py

CHANGE DETAILS

diff --git a/tests/test-wsgirequest.py b/tests/test-wsgirequest.py
--- a/tests/test-wsgirequest.py
+++ b/tests/test-wsgirequest.py
@@ -196,21 +196,26 @@
 self.assertEqual(r.dispatchparts, [b'pathinfo'])
 self.assertEqual(r.dispatchpath, b'pathinfo')
 
+if not getattr(unittest.TestCase, 'assertRaisesRegex', False):
+# Python 3.7 deprecates the regex*p* version, but 2.7 lacks
+# the regex version.
+assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
+
 def testreponame(self):
 """repository path components get stripped from URL."""
 
-with self.assertRaisesRegexp(error.ProgrammingError,
+with self.assertRaisesRegex(error.ProgrammingError,
  b'reponame requires PATH_INFO'):
 parse(DEFAULT_ENV, reponame=b'repo')
 
-with self.assertRaisesRegexp(error.ProgrammingError,
+with self.assertRaisesRegex(error.ProgrammingError,
  b'PATH_INFO does not begin with repo '
  b'name'):
 parse(DEFAULT_ENV, reponame=b'repo', extra={
 r'PATH_INFO': r'/pathinfo',
 })
 
-with self.assertRaisesRegexp(error.ProgrammingError,
+with self.assertRaisesRegex(error.ProgrammingError,
  b'reponame prefix of PATH_INFO'):
 parse(DEFAULT_ENV, reponame=b'repo', extra={
 r'PATH_INFO': r'/repoextra/path',
diff --git a/tests/test-wireproto-framing.py b/tests/test-wireproto-framing.py
--- a/tests/test-wireproto-framing.py
+++ b/tests/test-wireproto-framing.py
@@ -103,19 +103,24 @@
 ffs(b'1 1 0 command-data eos %s' % data.getvalue()),
 ])
 
+if not getattr(unittest.TestCase, 'assertRaisesRegex', False):
+# Python 3.7 deprecates the regex*p* version, but 2.7 lacks
+# the regex version.
+assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
+
 def testtextoutputformattingstringtype(self):
 """Formatting string must be bytes."""
-with self.assertRaisesRegexp(ValueError, 'must use bytes formatting '):
+with self.assertRaisesRegex(ValueError, 'must use bytes formatting '):
 list(framing.createtextoutputframe(None, 1, [
 (b'foo'.decode('ascii'), [], [])]))
 
 def testtextoutputargumentbytes(self):
-with self.assertRaisesRegexp(ValueError, 'must use bytes for 
argument'):
+with self.assertRaisesRegex(ValueError, 'must use bytes for argument'):
 list(framing.createtextoutputframe(None, 1, [
 (b'foo', [b'foo'.decode('ascii')], [])]))
 
 def testtextoutputlabelbytes(self):
-with self.assertRaisesRegexp(ValueError, 'must use bytes for labels'):
+with self.assertRaisesRegex(ValueError, 'must use bytes for labels'):
 list(framing.createtextoutputframe(None, 1, [
 (b'foo', [], [b'foo'.decode('ascii')])]))
 
diff --git a/tests/test-wireproto-clientreactor.py 
b/tests/test-wireproto-clientreactor.py
--- a/tests/test-wireproto-clientreactor.py
+++ b/tests/test-wireproto-clientreactor.py
@@ -24,6 +24,12 @@
 
 class SingleSendTests(unittest.TestCase):
 """A reactor that can only send once rejects subsequent sends."""
+
+if not getattr(unittest.TestCase, 'assertRaisesRegex', False):
+# Python 3.7 deprecates the regex*p* version, but 2.7 lacks
+# the regex version.
+assertRaisesRegex = unittest.TestCase.assertRaisesRegexp
+
 def testbasic(self):
 reactor = framing.clientreactor(hasmultiplesend=False, 
buffersends=True)
 
@@ -39,11 +45,11 @@
 
 self.assertEqual(request.state, b'sent')
 
-with self.assertRaisesRegexp(error.ProgrammingError,
+with self.assertRaisesRegex(error.ProgrammingError,
  'cannot issue new commands'):
 reactor.callcommand(b'foo', {})
 
-with self.assertRaisesRegexp(error.ProgrammingError,
+with self.assertRaisesRegex(error.ProgrammingError,
  'cannot issue new commands'):
 reactor.callcommand(b'foo', {})
 
@@ -77,6 +83,11 @@
 self.assertEqual(request.state, b'sent')
 
 class BadFrameRecvTests(unittest.TestCase):
+if not getattr(unittest.TestCase, 'assertRaisesRegex', False):
+# Python 3.7 deprecates the regex*p* version, but 2.7 lacks
+# the regex 

D3303: cborutil: implement support for streaming encoding, bytestring decoding

2018-04-14 Thread indygreg (Gregory Szorc)
indygreg added a comment.


  In https://phab.mercurial-scm.org/D3303#53422, @yuja wrote:
  
  > If it's just for date tuple, I have a patch to get rid of floating-point 
timestamps
  >  as our timestamps should be effectively ints.
  
  
  I believe that's the only place we use floats. Or at least the only place I 
saw it in test failures.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3303

To: indygreg, #hg-reviewers
Cc: yuja, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3373: tests: port test-hg-parseurl.py to unittest

2018-04-14 Thread durin42 (Augie Fackler)
durin42 created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3373

AFFECTED FILES
  tests/test-hg-parseurl.py
  tests/test-hg-parseurl.py.out

CHANGE DETAILS

diff --git a/tests/test-hg-parseurl.py.out b/tests/test-hg-parseurl.py.out
deleted file mode 100644
--- a/tests/test-hg-parseurl.py.out
+++ /dev/null
@@ -1,8 +0,0 @@
-http://example.com/no/anchor, branches: (None, [])
-http://example.com/an/anchor, branches: ('foo', [])
-http://example.com/no/anchor/branches, branches: (None, ['foo'])
-http://example.com/an/anchor/branches, branches: ('bar', ['foo'])
-http://example.com/an/anchor/branches-None, branches: ('foo', [])
-http://example.com/, branches: (None, [])
-http://example.com/, branches: (None, [])
-http://example.com/, branches: ('foo', [])
diff --git a/tests/test-hg-parseurl.py b/tests/test-hg-parseurl.py
--- a/tests/test-hg-parseurl.py
+++ b/tests/test-hg-parseurl.py
@@ -1,17 +1,34 @@
 from __future__ import absolute_import, print_function
 
+import unittest
+
 from mercurial import (
 hg,
 )
 
-def testparse(url, branch=[]):
-print('%s, branches: %r' % hg.parseurl(url, branch))
+class ParseRequestTests(unittest.TestCase):
+def testparse(self):
 
-testparse('http://example.com/no/anchor')
-testparse('http://example.com/an/anchor#foo')
-testparse('http://example.com/no/anchor/branches', branch=['foo'])
-testparse('http://example.com/an/anchor/branches#bar', branch=['foo'])
-testparse('http://example.com/an/anchor/branches-None#foo', branch=None)
-testparse('http://example.com/')
-testparse('http://example.com')
-testparse('http://example.com#foo')
+self.assertEqual(hg.parseurl('http://example.com/no/anchor'),
+ ('http://example.com/no/anchor', (None, [])))
+self.assertEqual(hg.parseurl('http://example.com/an/anchor#foo'),
+ ('http://example.com/an/anchor', ('foo', [])))
+self.assertEqual(
+hg.parseurl('http://example.com/no/anchor/branches', ['foo']),
+('http://example.com/no/anchor/branches', (None, ['foo'])))
+self.assertEqual(
+hg.parseurl('http://example.com/an/anchor/branches#bar', ['foo']),
+('http://example.com/an/anchor/branches', ('bar', ['foo'])))
+self.assertEqual(hg.parseurl(
+'http://example.com/an/anchor/branches-None#foo', None),
+('http://example.com/an/anchor/branches-None', ('foo', [])))
+self.assertEqual(hg.parseurl('http://example.com/'),
+ ('http://example.com/', (None, [])))
+self.assertEqual(hg.parseurl('http://example.com'),
+ ('http://example.com/', (None, [])))
+self.assertEqual(hg.parseurl('http://example.com#foo'),
+ ('http://example.com/', ('foo', [])))
+
+if __name__ == '__main__':
+import silenttestrunner
+silenttestrunner.main(__name__)



To: durin42, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3374: tests: add b prefixes to test-hg-parseurl.py

2018-04-14 Thread durin42 (Augie Fackler)
durin42 created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Now passes on Python 3.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3374

AFFECTED FILES
  tests/test-hg-parseurl.py

CHANGE DETAILS

diff --git a/tests/test-hg-parseurl.py b/tests/test-hg-parseurl.py
--- a/tests/test-hg-parseurl.py
+++ b/tests/test-hg-parseurl.py
@@ -9,25 +9,25 @@
 class ParseRequestTests(unittest.TestCase):
 def testparse(self):
 
-self.assertEqual(hg.parseurl('http://example.com/no/anchor'),
- ('http://example.com/no/anchor', (None, [])))
-self.assertEqual(hg.parseurl('http://example.com/an/anchor#foo'),
- ('http://example.com/an/anchor', ('foo', [])))
+self.assertEqual(hg.parseurl(b'http://example.com/no/anchor'),
+ (b'http://example.com/no/anchor', (None, [])))
+self.assertEqual(hg.parseurl(b'http://example.com/an/anchor#foo'),
+ (b'http://example.com/an/anchor', (b'foo', [])))
 self.assertEqual(
-hg.parseurl('http://example.com/no/anchor/branches', ['foo']),
-('http://example.com/no/anchor/branches', (None, ['foo'])))
+hg.parseurl(b'http://example.com/no/anchor/branches', [b'foo']),
+(b'http://example.com/no/anchor/branches', (None, [b'foo'])))
 self.assertEqual(
-hg.parseurl('http://example.com/an/anchor/branches#bar', ['foo']),
-('http://example.com/an/anchor/branches', ('bar', ['foo'])))
+hg.parseurl(b'http://example.com/an/anchor/branches#bar', 
[b'foo']),
+(b'http://example.com/an/anchor/branches', (b'bar', [b'foo'])))
 self.assertEqual(hg.parseurl(
-'http://example.com/an/anchor/branches-None#foo', None),
-('http://example.com/an/anchor/branches-None', ('foo', [])))
-self.assertEqual(hg.parseurl('http://example.com/'),
- ('http://example.com/', (None, [])))
-self.assertEqual(hg.parseurl('http://example.com'),
- ('http://example.com/', (None, [])))
-self.assertEqual(hg.parseurl('http://example.com#foo'),
- ('http://example.com/', ('foo', [])))
+b'http://example.com/an/anchor/branches-None#foo', None),
+(b'http://example.com/an/anchor/branches-None', (b'foo', [])))
+self.assertEqual(hg.parseurl(b'http://example.com/'),
+ (b'http://example.com/', (None, [])))
+self.assertEqual(hg.parseurl(b'http://example.com'),
+ (b'http://example.com/', (None, [])))
+self.assertEqual(hg.parseurl(b'http://example.com#foo'),
+ (b'http://example.com/', (b'foo', [])))
 
 if __name__ == '__main__':
 import silenttestrunner



To: durin42, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3367: hgwebdir: un-bytes the env dict before re-parsing env

2018-04-14 Thread durin42 (Augie Fackler)
durin42 updated this revision to Diff 8277.
Herald added a reviewer: pulkit.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3367?vs=8275=8277

REVISION DETAIL
  https://phab.mercurial-scm.org/D3367

AFFECTED FILES
  contrib/python3-whitelist
  mercurial/hgweb/hgwebdir_mod.py

CHANGE DETAILS

diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py
--- a/mercurial/hgweb/hgwebdir_mod.py
+++ b/mercurial/hgweb/hgwebdir_mod.py
@@ -422,8 +422,12 @@
 if real:
 # Re-parse the WSGI environment to take into account our
 # repository path component.
+uenv = req.rawenv
+if pycompat.ispy3:
+uenv = {k.decode('latin1'): v for k, v in
+uenv.iteritems()}
 req = requestmod.parserequestfromenv(
-req.rawenv, reponame=virtualrepo,
+uenv, reponame=virtualrepo,
 altbaseurl=self.ui.config('web', 'baseurl'))
 try:
 # ensure caller gets private copy of ui
diff --git a/contrib/python3-whitelist b/contrib/python3-whitelist
--- a/contrib/python3-whitelist
+++ b/contrib/python3-whitelist
@@ -153,6 +153,7 @@
 test-glog-topological.t
 test-gpg.t
 test-graft.t
+test-hg-parseurl.py
 test-hghave.t
 test-hgignore.t
 test-hgk.t



To: durin42, #hg-reviewers, yuja, pulkit
Cc: yuja, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3372: keepalive: add ** overlooked in 83250442dc81

2018-04-14 Thread durin42 (Augie Fackler)
durin42 created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Caught by Yuya in https://phab.mercurial-scm.org/D3326.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3372

AFFECTED FILES
  mercurial/keepalive.py

CHANGE DETAILS

diff --git a/mercurial/keepalive.py b/mercurial/keepalive.py
--- a/mercurial/keepalive.py
+++ b/mercurial/keepalive.py
@@ -326,16 +326,16 @@
 data = urllibcompat.getdata(req)
 h.putrequest(
 req.get_method(), urllibcompat.getselector(req),
-skipheaders)
+**skipheaders)
 if r'content-type' not in headers:
 h.putheader(r'Content-type',
 r'application/x-www-form-urlencoded')
 if r'content-length' not in headers:
 h.putheader(r'Content-length', r'%d' % len(data))
 else:
 h.putrequest(
 req.get_method(), urllibcompat.getselector(req),
-skipheaders)
+**skipheaders)
 except socket.error as err:
 raise urlerr.urlerror(err)
 for k, v in headers.items():



To: durin42, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3367: hgwebdir: un-bytes the env dict before re-parsing env

2018-04-14 Thread durin42 (Augie Fackler)
durin42 updated this revision to Diff 8275.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3367?vs=8244=8275

REVISION DETAIL
  https://phab.mercurial-scm.org/D3367

AFFECTED FILES
  mercurial/hgweb/hgwebdir_mod.py

CHANGE DETAILS

diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py
--- a/mercurial/hgweb/hgwebdir_mod.py
+++ b/mercurial/hgweb/hgwebdir_mod.py
@@ -422,8 +422,12 @@
 if real:
 # Re-parse the WSGI environment to take into account our
 # repository path component.
+uenv = req..rawenv
+if pycompat.ispy3:
+uenv = {k.decode('latin1'): v for k, v in
+uenv.iteritems()}
 req = requestmod.parserequestfromenv(
-req.rawenv, reponame=virtualrepo,
+uenv, reponame=virtualrepo,
 altbaseurl=self.ui.config('web', 'baseurl'))
 try:
 # ensure caller gets private copy of ui



To: durin42, #hg-reviewers, yuja
Cc: yuja, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3364: largefiles: opts appears to already be bytes in this instance

2018-04-14 Thread durin42 (Augie Fackler)
durin42 updated this revision to Diff 8274.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3364?vs=8241=8274

REVISION DETAIL
  https://phab.mercurial-scm.org/D3364

AFFECTED FILES
  contrib/python3-whitelist
  hgext/largefiles/overrides.py

CHANGE DETAILS

diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -897,7 +897,7 @@
 # Caching is implicitly limited to 'rev' option, since the dest repo 
was
 # truncated at that point.  The user may expect a download count with
 # this option, so attempt whether or not this is a largefile repo.
-if opts.get(r'all_largefiles'):
+if opts.get('all_largefiles'):
 success, missing = lfcommands.downloadlfiles(ui, repo, None)
 
 if missing != 0:
diff --git a/contrib/python3-whitelist b/contrib/python3-whitelist
--- a/contrib/python3-whitelist
+++ b/contrib/python3-whitelist
@@ -210,6 +210,7 @@
 test-largefiles-misc.t
 test-largefiles-small-disk.t
 test-largefiles-update.t
+test-largefiles.t
 test-lfs-largefiles.t
 test-linerange.py
 test-locate.t



To: durin42, pulkit, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3350: tests: fix up a couple of minor bytes inconsistencies in run-tests.py

2018-04-14 Thread durin42 (Augie Fackler)
durin42 updated this revision to Diff 8269.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3350?vs=8227=8269

REVISION DETAIL
  https://phab.mercurial-scm.org/D3350

AFFECTED FILES
  contrib/python3-whitelist
  tests/run-tests.py

CHANGE DETAILS

diff --git a/tests/run-tests.py b/tests/run-tests.py
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -2215,10 +2215,11 @@
 'Failed to identify failure point for %s' % test)
 continue
 dat = m.groupdict()
-verb = 'broken' if dat['goodbad'] == 'bad' else 'fixed'
+verb = 'broken' if dat['goodbad'] == b'bad' else 'fixed'
 self.stream.writeln(
 '%s %s by %s (%s)' % (
-test, verb, dat['node'], dat['summary']))
+test, verb, dat['node'].decode('ascii'),
+dat['summary'].decode('utf8', 'ignore')))
 
 def printtimes(self, times):
 # iolock held by run
diff --git a/contrib/python3-whitelist b/contrib/python3-whitelist
--- a/contrib/python3-whitelist
+++ b/contrib/python3-whitelist
@@ -392,6 +392,7 @@
 test-revset-outgoing.t
 test-rollback.t
 test-run-tests.py
+test-run-tests.t
 test-schemes.t
 test-serve.t
 test-setdiscovery.t



To: durin42, pulkit, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3351: py3: fix test-shelve.t on Python 3

2018-04-14 Thread durin42 (Augie Fackler)
durin42 updated this revision to Diff 8270.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3351?vs=8228=8270

REVISION DETAIL
  https://phab.mercurial-scm.org/D3351

AFFECTED FILES
  contrib/python3-whitelist
  tests/test-shelve.t

CHANGE DETAILS

diff --git a/tests/test-shelve.t b/tests/test-shelve.t
--- a/tests/test-shelve.t
+++ b/tests/test-shelve.t
@@ -1273,7 +1273,7 @@
   $ rm .hg/unshelverebasestate
   $ hg unshelve --abort
   unshelve of 'default' aborted
-  abort: $ENOENT$
+  abort: $ENOENT$* (glob)
   [255]
 Can the user leave the current state?
   $ hg up -C .
diff --git a/contrib/python3-whitelist b/contrib/python3-whitelist
--- a/contrib/python3-whitelist
+++ b/contrib/python3-whitelist
@@ -397,6 +397,7 @@
 test-serve.t
 test-setdiscovery.t
 test-share.t
+test-shelve.t
 test-show-stack.t
 test-show-work.t
 test-show.t



To: durin42, pulkit, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3358: stringutil: teach pprint how to format None

2018-04-14 Thread durin42 (Augie Fackler)
durin42 updated this revision to Diff 8272.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3358?vs=8235=8272

REVISION DETAIL
  https://phab.mercurial-scm.org/D3358

AFFECTED FILES
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -42,6 +42,8 @@
 return '%d' % o
 elif isinstance(o, float):
 return '%f' % o
+elif o is None:
+return b'None'
 else:
 raise error.ProgrammingError('do not know how to format %r' % o)
 



To: durin42, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3356: wsgicgi: un-do some prior porting work that is now wrong

2018-04-14 Thread durin42 (Augie Fackler)
durin42 updated this revision to Diff 8271.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3356?vs=8233=8271

REVISION DETAIL
  https://phab.mercurial-scm.org/D3356

AFFECTED FILES
  contrib/python3-whitelist
  mercurial/hgweb/wsgicgi.py

CHANGE DETAILS

diff --git a/mercurial/hgweb/wsgicgi.py b/mercurial/hgweb/wsgicgi.py
--- a/mercurial/hgweb/wsgicgi.py
+++ b/mercurial/hgweb/wsgicgi.py
@@ -10,8 +10,10 @@
 
 from __future__ import absolute_import
 
+import os
+
 from .. import (
-encoding,
+pycompat,
 )
 
 from ..utils import (
@@ -26,7 +28,7 @@
 procutil.setbinary(procutil.stdin)
 procutil.setbinary(procutil.stdout)
 
-environ = dict(encoding.environ.iteritems())
+environ = dict(os.environ.iteritems()) # re-exports
 environ.setdefault(r'PATH_INFO', '')
 if environ.get(r'SERVER_SOFTWARE', r'').startswith(r'Microsoft-IIS'):
 # IIS includes script_name in PATH_INFO
@@ -61,9 +63,10 @@
 elif not headers_sent:
 # Before the first output, send the stored headers
 status, response_headers = headers_sent[:] = headers_set
-out.write('Status: %s\r\n' % status)
-for header in response_headers:
-out.write('%s: %s\r\n' % header)
+out.write('Status: %s\r\n' % pycompat.bytesurl(status))
+for hk, hv in response_headers:
+out.write('%s: %s\r\n' % (pycompat.bytesurl(hk),
+  pycompat.bytesurl(hv)))
 out.write('\r\n')
 
 out.write(data)
diff --git a/contrib/python3-whitelist b/contrib/python3-whitelist
--- a/contrib/python3-whitelist
+++ b/contrib/python3-whitelist
@@ -45,6 +45,7 @@
 test-check-pylint.t
 test-check-shbang.t
 test-children.t
+test-clone-cgi.t
 test-clone-pull-corruption.t
 test-clone-r.t
 test-clone-update-order.t



To: durin42, pulkit, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3348: py3: another three passing

2018-04-14 Thread durin42 (Augie Fackler)
durin42 updated this revision to Diff 8268.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3348?vs=8225=8268

REVISION DETAIL
  https://phab.mercurial-scm.org/D3348

AFFECTED FILES
  contrib/python3-whitelist

CHANGE DETAILS

diff --git a/contrib/python3-whitelist b/contrib/python3-whitelist
--- a/contrib/python3-whitelist
+++ b/contrib/python3-whitelist
@@ -140,6 +140,7 @@
 test-exchange-obsmarkers-case-D4.t
 test-execute-bit.t
 test-export.t
+test-extdata.t
 test-extdiff.t
 test-extra-filelog-entry.t
 test-filebranch.t
@@ -175,6 +176,7 @@
 test-http-branchmap.t
 test-http-bundle1.t
 test-http-clone-r.t
+test-http.t
 test-identify.t
 test-import-unknown.t
 test-import.t
@@ -432,6 +434,7 @@
 test-update-names.t
 test-update-reverse.t
 test-upgrade-repo.t
+test-url-download.t
 test-url-rev.t
 test-username-newline.t
 test-verify.t



To: durin42, pulkit, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 3 of 3 V4] revset: skip legacy lookup for revspec wrapped in 'revset(…)'

2018-04-14 Thread Yuya Nishihara
On Sat, 14 Apr 2018 15:07:06 +0200, Boris Feld wrote:
> # HG changeset patch
> # User Boris Feld 
> # Date 1523369212 -7200
> #  Tue Apr 10 16:06:52 2018 +0200
> # Node ID e345b7103fef40be16f792cda46aa899d0ef8dd1
> # Parent  304b6671aa1be37fc410edb38f2f2f3040ce6708
> # EXP-Topic noname
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
> e345b7103fef
> revset: skip legacy lookup for revspec wrapped in 'revset(…)'

>  def matchany(ui, specs, repo=None, localalias=None):
>  """Create a matcher that will include any revisions matching one of the
>  given specs
> @@ -2196,7 +2199,13 @@ def matchany(ui, specs, repo=None, local
>  lookup = lookupfn(repo)
>  parsedspecs = []
>  for s in specs:
> -parsedspecs.append(revsetlang.parse(s, lookup))
> +lookupthis = lookup
> +stripped = s.strip()
> +if (stripped.startswith(prefixrevset)
> +and stripped.endswith(postfixrevset)):
> +s = s[len(prefixrevset):-len(postfixrevset)]
 ^

This would confuse the error reporting. Instead maybe we can handle this
hack in revsetlang.py.

 1) nullify lookup function at revsetlang.parse(), _parsewith(), or
tokenize()
 2) and, rewrite (func 'revset' x[2]) to x[2] by _analyze()

(2) would be something like

elif op == 'func':
f = getsymbol(x[1])
if f == 'revset':
return _analyze(x[2])

"hg debugrevspec -v" will show how the parsed tree will be rewritten.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 3 V4] revset: add more test to show current behaviors with label looking like revset

2018-04-14 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1519922236 18000
#  Thu Mar 01 11:37:16 2018 -0500
# Node ID 5c1a0d784a26d4e8659dcec80503c8764432a303
# Parent  e45545f7895e66d55379a7db48b13831eff6cf2a
# EXP-Topic noname
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
5c1a0d784a26
revset: add more test to show current behaviors with label looking like revset

There are very few constraints on what character can be put into tags and
other labels. We add more tests showing some of extreme cases that user can
currently use.

diff --git a/tests/test-legacy-lookup.t b/tests/test-legacy-lookup.t
new file mode 100644
--- /dev/null
+++ b/tests/test-legacy-lookup.t
@@ -0,0 +1,259 @@
+
+  $ cat >> $HGRCPATH << EOF
+  > [ui]
+  > logtemplate="{rev}:{node|short} {desc} [{tags}]\n"
+  > EOF
+
+  $ hg init legacy-lookup
+  $ cd legacy-lookup
+  $ echo a > a
+  $ hg add a
+  $ hg commit -m 'first'
+  $ echo aa > a
+  $ hg commit -m 'second'
+  $ hg log -G
+  @  1:43114e71eddd second [tip]
+  |
+  o  0:a87874c6ec31 first []
+  
+
+Create a tag that looks like a revset
+
+  $ hg tag 'rev(0)'
+  $ hg log -G
+  @  2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd [tip]
+  |
+  o  1:43114e71eddd second [rev(0)]
+  |
+  o  0:a87874c6ec31 first []
+  
+
+See how various things are resolved
+---
+
+Revision numbers
+
+  $ hg log -r '0'
+  0:a87874c6ec31 first []
+  $ hg log -r '1'
+  1:43114e71eddd second [rev(0)]
+
+"rev(x)" form (the one conflicting with the tags)
+(resolved as a label)
+
+  $ hg log -r 'rev(0)'
+  1:43114e71eddd second [rev(0)]
+  $ hg log -r 'rev(1)'
+  1:43114e71eddd second [rev(0)]
+
+same within a simple revspec
+(still resolved as the label)
+
+  $ hg log -r ':rev(0)'
+  0:a87874c6ec31 first []
+  1:43114e71eddd second [rev(0)]
+  $ hg log -r 'rev(0):'
+  1:43114e71eddd second [rev(0)]
+  2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd [tip]
+
+within a more advances revset
+(still resolved as the label)
+
+  $ hg log -r 'rev(0) and branch(default)'
+  0:a87874c6ec31 first []
+
+some of the above with quote to force its resolution as a label
+
+  $ hg log -r ':"rev(0)"'
+  0:a87874c6ec31 first []
+  1:43114e71eddd second [rev(0)]
+  $ hg log -r '"rev(0)":'
+  1:43114e71eddd second [rev(0)]
+  2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd [tip]
+  $ hg log -r '"rev(0)" and branch(default)'
+  1:43114e71eddd second [rev(0)]
+
+confusing bits within parents
+
+  $ hg log -r '(rev(0))'
+  0:a87874c6ec31 first []
+  $ hg log -r '( rev(0))'
+  0:a87874c6ec31 first []
+  $ hg log -r '("rev(0)")'
+  1:43114e71eddd second [rev(0)]
+
+Test label with quote in them.
+
+  $ hg tag '"foo"'
+
+  $ hg log -r '"foo"'
+  2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
+  $ hg log -r '("foo")'
+  abort: unknown revision 'foo'!
+  [255]
+  $ hg log -r '("\"foo\"")'
+  2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
+
+Test label with dash in them.
+
+  $ hg tag 'foo-bar'
+
+  $ hg log -r 'foo-bar'
+  3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
+  $ hg log -r '(foo-bar)'
+  3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
+  $ hg log -r '"foo-bar"'
+  3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
+  $ hg log -r '("foo-bar")'
+  3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
+
+Test label with + in them.
+
+  $ hg tag 'foo+bar'
+
+  $ hg log -r 'foo+bar'
+  4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
+  $ hg log -r '(foo+bar)'
+  abort: unknown revision 'foo'!
+  [255]
+  $ hg log -r '"foo+bar"'
+  4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
+  $ hg log -r '("foo+bar")'
+  4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
+
+Test tag with numeric version number.
+
+  $ hg tag '1.2'
+
+  $ hg log -r '1.2'
+  5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
+  $ hg log -r '(1.2)'
+  5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
+  $ hg log -r '"1.2"'
+  5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
+  $ hg log -r '("1.2")'
+  5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
+  $ hg log -r '::"1.2"'
+  0:a87874c6ec31 first []
+  1:43114e71eddd second [rev(0)]
+  2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
+  3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
+  4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
+  5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
+  $ hg log -r '::1.2'
+  0:a87874c6ec31 first []
+  1:43114e71eddd second [rev(0)]
+  2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
+  3:a50aae922707 Added tag "foo" for changeset fb616635b18f [foo-bar]
+  4:bbf52b87b370 Added tag 

[PATCH 3 of 3 V4] revset: skip legacy lookup for revspec wrapped in 'revset(…)'

2018-04-14 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1523369212 -7200
#  Tue Apr 10 16:06:52 2018 +0200
# Node ID e345b7103fef40be16f792cda46aa899d0ef8dd1
# Parent  304b6671aa1be37fc410edb38f2f2f3040ce6708
# EXP-Topic noname
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
e345b7103fef
revset: skip legacy lookup for revspec wrapped in 'revset(…)'

Currently, multiple labels can take forms that can be confused with revset
(eg: "rev(0)" is a valid tag). Since we look up for tags before evaluating
revset, this means a tag can shadow a valid revset at any time.

We now enforce the strict revset parsing when wrapped with 'revset(…)'. For now,
This only work on a whole revspec. This might change in the future if we improve
the implementation.

The feature is undocumented for now, keeping it in the experimental namespace.
In case a better approach to achieve the same goal is found.

The syntax looks like a revset but is not implemented as such for now. Since the
goal is to avoid some preprocessing that happens before revset parsing, we
cannot simply implement it as a revset predicate.

There was other approaches discussed over the mailing-list but they were less
convincing.

Having a configuration flag to disable legacy lookup have been considered but
discarded. There are too many common uses of ambiguous identifier (eg: '+',
'-' or '..') to have the legacy lookup mechanism turned off.

In addition, the  approach can control the parsing of each revset, making
it more flexible. For example, a revset used as the value of an existing
configuration option (eg: pushrev) could enforce its resolution as a revset (by
using the prefix) while user inputs would still use the legacy lookup.

In addition of offering a way to unambiguously input a revset, this prefix
allow skipping the name lookup providing a significant speedup in some case.

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -2177,6 +2177,9 @@ def match(ui, spec, repo=None):
 """Create a matcher for a single revision spec"""
 return matchany(ui, [spec], repo=repo)
 
+prefixrevset = 'revset('
+postfixrevset = ')'
+
 def matchany(ui, specs, repo=None, localalias=None):
 """Create a matcher that will include any revisions matching one of the
 given specs
@@ -2196,7 +2199,13 @@ def matchany(ui, specs, repo=None, local
 lookup = lookupfn(repo)
 parsedspecs = []
 for s in specs:
-parsedspecs.append(revsetlang.parse(s, lookup))
+lookupthis = lookup
+stripped = s.strip()
+if (stripped.startswith(prefixrevset)
+and stripped.endswith(postfixrevset)):
+s = s[len(prefixrevset):-len(postfixrevset)]
+lookupthis = None
+parsedspecs.append(revsetlang.parse(s, lookupthis))
 if len(parsedspecs) == 1:
 tree = parsedspecs[0]
 else:
diff --git a/tests/test-legacy-lookup.t b/tests/test-legacy-lookup.t
--- a/tests/test-legacy-lookup.t
+++ b/tests/test-legacy-lookup.t
@@ -62,6 +62,12 @@ within a more advances revset
   $ hg log -r 'rev(0) and branch(default)'
   0:a87874c6ec31 first []
 
+with explicit revset resolution
+(still resolved as the label)
+
+  $ hg log -r 'revset(rev(0))'
+  0:a87874c6ec31 first []
+
 some of the above with quote to force its resolution as a label
 
   $ hg log -r ':"rev(0)"'
@@ -91,8 +97,13 @@ Test label with quote in them.
   $ hg log -r '("foo")'
   abort: unknown revision 'foo'!
   [255]
+  $ hg log -r 'revset("foo")'
+  abort: unknown revision 'foo'!
+  [255]
   $ hg log -r '("\"foo\"")'
   2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
+  $ hg log -r 'revset("\"foo\"")'
+  2:fb616635b18f Added tag rev(0) for changeset 43114e71eddd ["foo"]
 
 Test label with dash in them.
 
@@ -116,6 +127,9 @@ Test label with + in them.
   $ hg log -r '(foo+bar)'
   abort: unknown revision 'foo'!
   [255]
+  $ hg log -r 'revset(foo+bar)'
+  abort: unknown revision 'foo'!
+  [255]
   $ hg log -r '"foo+bar"'
   4:bbf52b87b370 Added tag foo-bar for changeset a50aae922707 [foo+bar]
   $ hg log -r '("foo+bar")'
@@ -129,6 +143,8 @@ Test tag with numeric version number.
   5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
   $ hg log -r '(1.2)'
   5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
+  $ hg log -r 'revset(1.2)'
+  5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
   $ hg log -r '"1.2"'
   5:ff42fde8edbb Added tag foo+bar for changeset bbf52b87b370 [1.2]
   $ hg log -r '("1.2")'
@@ -157,6 +173,9 @@ Test tag with parenthesis (but not a val
   $ hg log -r '(release_4.1(candidate1))'
   hg: parse error: unknown identifier: release_4.1
   [255]
+  $ hg log -r 'revset(release_4.1(candidate1))'
+  hg: parse error: unknown identifier: release_4.1
+  [255]
   $ hg log -r '"release_4.1(candidate1)"'
   

[PATCH 2 of 3 V4] revset: use and explicit loop to resolve each spec

2018-04-14 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1523367822 -7200
#  Tue Apr 10 15:43:42 2018 +0200
# Node ID 304b6671aa1be37fc410edb38f2f2f3040ce6708
# Parent  5c1a0d784a26d4e8659dcec80503c8764432a303
# EXP-Topic noname
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
304b6671aa1b
revset: use and explicit loop to resolve each spec

This is useful to clarify the next changeset.

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -2190,14 +2190,17 @@ def matchany(ui, specs, repo=None, local
 return mfunc
 if not all(specs):
 raise error.ParseError(_("empty query"))
+
 lookup = None
 if repo:
 lookup = lookupfn(repo)
-if len(specs) == 1:
-tree = revsetlang.parse(specs[0], lookup)
+parsedspecs = []
+for s in specs:
+parsedspecs.append(revsetlang.parse(s, lookup))
+if len(parsedspecs) == 1:
+tree = parsedspecs[0]
 else:
-tree = ('or',
-('list',) + tuple(revsetlang.parse(s, lookup) for s in specs))
+tree = ('or', ('list',) + tuple(parsedspecs))
 
 aliases = []
 warn = None
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] templates: make divergentnodes in whyunstable keyword be a hybrid list

2018-04-14 Thread Yuya Nishihara
On Sat, 14 Apr 2018 20:39:21 +0800, Anton Shestakov wrote:
> # HG changeset patch
> # User Anton Shestakov 
> # Date 1523709254 -28800
> #  Sat Apr 14 20:34:14 2018 +0800
> # Node ID c7fc8a7ca7f5ca13e7e54a2690872f4252a41796
> # Parent  987c05eac1801d0b919c874280d03f9e8cccb411
> templates: make divergentnodes in whyunstable keyword be a hybrid list

Queued, thanks.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2] templates: add whyunstable template keyword

2018-04-14 Thread Anton Shestakov
On Sat, 14 Apr 2018 21:03:23 +0900
Yuya Nishihara  wrote:

> On Sat, 14 Apr 2018 19:43:15 +0800, Anton Shestakov wrote:
> > # HG changeset patch
> > # User Anton Shestakov 
> > # Date 1522054812 -28800
> > #  Mon Mar 26 17:00:12 2018 +0800
> > # Node ID 987c05eac1801d0b919c874280d03f9e8cccb411
> > # Parent  8bacc09814ba5500d15fb40c472e84cb95ae2f99
> > templates: add whyunstable template keyword  
> 
> Queued, thanks.
> 
> > +@templatekeyword('whyunstable', requires={'repo', 'ctx'})
> > +def showwhyunstable(context, mapping):
> > +"""List of dicts explaining all instabilities of a changeset.
> > +(EXPERIMENTAL)
> > +"""
> > +repo = context.resource(mapping, 'repo')
> > +ctx = context.resource(mapping, 'ctx')
> > +
> > +def formatnode(ctx):
> > +return ' %s (%s)' % (scmutil.formatchangeid(ctx), ctx.phasestr())  
> 
> Nit: leading ' ' isn't nice when you join() the list.

I was trying to avoid something like '{if(divergentnodes, " ")}', but
maybe it wouldn't be too bad. I'll come back to this tomorrow.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 7] hgweb: make revnav.gen() simply build a list of mappings by one pass

2018-04-14 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1522593269 -32400
#  Sun Apr 01 23:34:29 2018 +0900
# Node ID ec55e9ef2255378a190bdda6f060dca23659cc9d
# Parent  b7742898a29d79f01beb36c1cedd58acfdab05ab
hgweb: make revnav.gen() simply build a list of mappings by one pass

There was actually no lazy stuff.

diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -127,8 +127,7 @@ class revnav(object):
 The return is:
 - a single element tuple
 - containing a dictionary with a `before` and `after` key
-- values are generator functions taking arbitrary number of kwargs
-- yield items are dictionaries with `label` and `node` keys
+- values are dictionaries with `label` and `node` keys
 """
 if not self:
 # empty repo
@@ -143,22 +142,21 @@ class revnav(object):
 targets.sort()
 
 first = self._first()
-navbefore = [("(%i)" % first, self.hex(first))]
+navbefore = [{'label': '(%i)' % first, 'node': self.hex(first)}]
 navafter = []
 for rev in targets:
 if rev not in self._revlog:
 continue
 if pos < rev < limit:
-navafter.append(("+%d" % abs(rev - pos), self.hex(rev)))
+navafter.append({'label': '+%d' % abs(rev - pos),
+ 'node': self.hex(rev)})
 if 0 < rev < pos:
-navbefore.append(("-%d" % abs(rev - pos), self.hex(rev)))
-
+navbefore.append({'label': '-%d' % abs(rev - pos),
+  'node': self.hex(rev)})
 
-navafter.append(("tip", "tip"))
+navafter.append({'label': 'tip', 'node': 'tip'})
 
-data = lambda i: {"label": i[0], "node": i[1]}
-return ({'before': lambda **map: (data(i) for i in navbefore),
- 'after':  lambda **map: (data(i) for i in navafter)},)
+return ({'before': navbefore, 'after': navafter},)
 
 class filerevnav(revnav):
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 7] hgweb: lift {sessionvars} to a wrapped type

2018-04-14 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1522591957 -32400
#  Sun Apr 01 23:12:37 2018 +0900
# Node ID b7742898a29d79f01beb36c1cedd58acfdab05ab
# Parent  8bee5eca0b75333eee2c555663ae535005505991
hgweb: lift {sessionvars} to a wrapped type

Since a sessionvars object is updated in-place, we can't simply wrap it by
mappinglist.

diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -651,7 +651,7 @@ def diffstat(tmpl, ctx, statgen, parity)
 'parity': next(parity),
 })
 
-class sessionvars(object):
+class sessionvars(templateutil.wrapped):
 def __init__(self, vars, start='?'):
 self._start = start
 self._vars = vars
@@ -665,7 +665,7 @@ class sessionvars(object):
 def __copy__(self):
 return sessionvars(copy.copy(self._vars), self._start)
 
-def __iter__(self):
+def itermaps(self, context):
 separator = self._start
 for key, value in sorted(self._vars.iteritems()):
 yield {'name': key,
@@ -674,6 +674,16 @@ class sessionvars(object):
 }
 separator = '&'
 
+def join(self, context, mapping, sep):
+# could be '{separator}{name}={value|urlescape}'
+raise error.ParseError(_('not displayable without template'))
+
+def show(self, context, mapping):
+return self.join(context, '')
+
+def tovalue(self, context, mapping):
+return self._vars
+
 class wsgiui(uimod.ui):
 # default termwidth breaks under mod_wsgi
 def termwidth(self):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 7] hgweb: make sessionvars class less dense

2018-04-14 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1522591438 -32400
#  Sun Apr 01 23:03:58 2018 +0900
# Node ID 8bee5eca0b75333eee2c555663ae535005505991
# Parent  7b406ab5b3e9c3da9527a3001ba62e29506bd73a
hgweb: make sessionvars class less dense

diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -655,12 +655,16 @@ class sessionvars(object):
 def __init__(self, vars, start='?'):
 self._start = start
 self._vars = vars
+
 def __getitem__(self, key):
 return self._vars[key]
+
 def __setitem__(self, key, value):
 self._vars[key] = value
+
 def __copy__(self):
 return sessionvars(copy.copy(self._vars), self._start)
+
 def __iter__(self):
 separator = self._start
 for key, value in sorted(self._vars.iteritems()):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 6 of 7] hgweb: extract a generator function of _siblings class

2018-04-14 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1522594063 -32400
#  Sun Apr 01 23:47:43 2018 +0900
# Node ID 8e479b1d96bf94e81f76c78605c16b2864b219a5
# Parent  affefa7df3fe2dd06be7cab086c16626010bc8b4
hgweb: extract a generator function of _siblings class

_siblings will be converted to a plain function.

diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -181,6 +181,22 @@ class filerevnav(revnav):
 def hex(self, rev):
 return hex(self._changelog.node(self._revlog.linkrev(rev)))
 
+# TODO: maybe this can be a wrapper class for changectx/filectx list, which
+# yields {'ctx': ctx}
+def _ctxsgen(ctxs):
+for s in ctxs:
+d = {
+'node': s.hex(),
+'rev': s.rev(),
+'user': s.user(),
+'date': s.date(),
+'description': s.description(),
+'branch': s.branch(),
+}
+if util.safehasattr(s, 'path'):
+d['file'] = s.path()
+yield d
+
 class _siblings(object):
 def __init__(self, siblings=None, hiderev=None):
 if siblings is None:
@@ -190,18 +206,7 @@ class _siblings(object):
 self.siblings = []
 
 def __iter__(self):
-for s in self.siblings:
-d = {
-'node': s.hex(),
-'rev': s.rev(),
-'user': s.user(),
-'date': s.date(),
-'description': s.description(),
-'branch': s.branch(),
-}
-if util.safehasattr(s, 'path'):
-d['file'] = s.path()
-yield d
+return _ctxsgen(self.siblings)
 
 def __len__(self):
 return len(self.siblings)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 7] hgweb: prefix private variables of sessionvars with '_'

2018-04-14 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1522591382 -32400
#  Sun Apr 01 23:03:02 2018 +0900
# Node ID 7b406ab5b3e9c3da9527a3001ba62e29506bd73a
# Parent  34cde18a454484a1cf6e716a3325ca9282277d59
hgweb: prefix private variables of sessionvars with '_'

diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -653,17 +653,17 @@ def diffstat(tmpl, ctx, statgen, parity)
 
 class sessionvars(object):
 def __init__(self, vars, start='?'):
-self.start = start
-self.vars = vars
+self._start = start
+self._vars = vars
 def __getitem__(self, key):
-return self.vars[key]
+return self._vars[key]
 def __setitem__(self, key, value):
-self.vars[key] = value
+self._vars[key] = value
 def __copy__(self):
-return sessionvars(copy.copy(self.vars), self.start)
+return sessionvars(copy.copy(self._vars), self._start)
 def __iter__(self):
-separator = self.start
-for key, value in sorted(self.vars.iteritems()):
+separator = self._start
+for key, value in sorted(self._vars.iteritems()):
 yield {'name': key,
'value': pycompat.bytestr(value),
'separator': separator,
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 5 of 7] hgweb: wrap {changenav} and {nav} with mappinglist

2018-04-14 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1522593608 -32400
#  Sun Apr 01 23:40:08 2018 +0900
# Node ID affefa7df3fe2dd06be7cab086c16626010bc8b4
# Parent  ec55e9ef2255378a190bdda6f060dca23659cc9d
hgweb: wrap {changenav} and {nav} with mappinglist

diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py
+++ b/mercurial/hgweb/webcommands.py
@@ -1084,7 +1084,7 @@ def filelog(web):
 linerange = webutil.formatlinerange(*lrange)
 # deactivate numeric nav links when linerange is specified as this
 # would required a dedicated "revnav" class
-nav = []
+nav = templateutil.mappinglist([])
 if descend:
 it = dagop.blockdescendants(fctx, *lrange)
 else:
diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -125,13 +125,16 @@ class revnav(object):
 :limit: how far shall we link
 
 The return is:
-- a single element tuple
+- a single element mappinglist
 - containing a dictionary with a `before` and `after` key
 - values are dictionaries with `label` and `node` keys
 """
 if not self:
 # empty repo
-return ({'before': (), 'after': ()},)
+return templateutil.mappinglist([
+{'before': templateutil.mappinglist([]),
+ 'after': templateutil.mappinglist([])},
+])
 
 targets = []
 for f in _navseq(1, pagelen):
@@ -156,7 +159,11 @@ class revnav(object):
 
 navafter.append({'label': 'tip', 'node': 'tip'})
 
-return ({'before': navbefore, 'after': navafter},)
+# TODO: maybe this can be a scalar object supporting tomap()
+return templateutil.mappinglist([
+{'before': templateutil.mappinglist(navbefore),
+ 'after': templateutil.mappinglist(navafter)},
+])
 
 class filerevnav(revnav):
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 2 of 2] templates: make divergentnodes in whyunstable keyword be a mappinglist too (RFC)

2018-04-14 Thread Anton Shestakov
On Sat, 14 Apr 2018 21:09:46 +0900
Yuya Nishihara  wrote:

> On Sat, 14 Apr 2018 19:43:16 +0800, Anton Shestakov wrote:
> > # HG changeset patch
> > # User Anton Shestakov 
> > # Date 1523705764 -28800
> > #  Sat Apr 14 19:36:04 2018 +0800
> > # Node ID 6287c68bde7bcdc1dc260da9983ecc7fffc9ee20
> > # Parent  987c05eac1801d0b919c874280d03f9e8cccb411
> > templates: make divergentnodes in whyunstable keyword be a mappinglist too 
> > (RFC)  
> 
> > I'd like this to work, but it doesn't: "{divergentnodes}" show a178212c3433 
> > as
> > the divergent node, and not 70d5a63ca112 (so the whole test case fails).  
> 
> >  for entry in entries:
> >  if entry.get('divergentnodes'):
> > -dnodes = entry['divergentnodes']
> > -entry['divergentnodes'] = ''.join(formatnode(dnode)
> > -  for dnode in dnodes)
> > +dnodes = [{ctx: dnode} for dnode in entry['divergentnodes']]  
>   ^^^
>   'ctx':

Ah. Yep, that was it.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH] templates: make divergentnodes in whyunstable keyword be a hybrid list

2018-04-14 Thread Anton Shestakov
# HG changeset patch
# User Anton Shestakov 
# Date 1523709254 -28800
#  Sat Apr 14 20:34:14 2018 +0800
# Node ID c7fc8a7ca7f5ca13e7e54a2690872f4252a41796
# Parent  987c05eac1801d0b919c874280d03f9e8cccb411
templates: make divergentnodes in whyunstable keyword be a hybrid list

diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -809,8 +809,11 @@ def showwhyunstable(context, mapping):
 for entry in entries:
 if entry.get('divergentnodes'):
 dnodes = entry['divergentnodes']
-entry['divergentnodes'] = ''.join(formatnode(dnode)
-  for dnode in dnodes)
+dnhybrid = _hybrid(None, [dnode.hex() for dnode in dnodes],
+   lambda x: {'ctx': repo[x]},
+   lambda x: formatnode(repo[x]))
+entry['divergentnodes'] = dnhybrid
+
 
 tmpl = '{instability}:{divergentnodes} {reason} {node|short}'
 return templateutil.mappinglist(entries, tmpl=tmpl, sep='\n')
diff --git a/tests/test-obsolete-divergent.t b/tests/test-obsolete-divergent.t
--- a/tests/test-obsolete-divergent.t
+++ b/tests/test-obsolete-divergent.t
@@ -725,6 +725,8 @@ Use scmutil.cleanupnodes API to create d
   content-divergent: 4:70d5a63ca112 (draft) predecessor a178212c3433
   $ hg log -r 1a2a9b5b0030 --hidden -T 
'{whyunstable%"{instability}:{divergentnodes} {reason} {node}\n"}'
   content-divergent: 4:70d5a63ca112 (draft) predecessor 
a178212c3433c4e77b573f6011e29affb8aefa33
+  $ hg log -r 1a2a9b5b0030 --hidden -T 
'{whyunstable%"{instability}:{divergentnodes % " {node} ({phase})"} {reason} 
{node}\n"}'
+  content-divergent: 70d5a63ca112acb3764bc1d7320ca90ea688d671 (draft) 
predecessor a178212c3433c4e77b573f6011e29affb8aefa33
 
 #if serve
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3365: commands: drop spurious r'' on dry_run in forget

2018-04-14 Thread durin42 (Augie Fackler)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG5fc502e149f1: commands: drop spurious r on 
dry_run in forget (authored by durin42, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3365?vs=8242=8267

REVISION DETAIL
  https://phab.mercurial-scm.org/D3365

AFFECTED FILES
  mercurial/commands.py

CHANGE DETAILS

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -2090,7 +2090,7 @@
 raise error.Abort(_('no files specified'))
 
 m = scmutil.match(repo[None], pats, opts)
-dryrun = opts.get(r'dry_run')
+dryrun = opts.get('dry_run')
 rejected = cmdutil.forget(ui, repo, m, prefix="",
   explicitonly=False, dryrun=dryrun)[0]
 return rejected and 1 or 0



To: durin42, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3366: tests: port inline extension in test-http-bundle1.t to py3

2018-04-14 Thread durin42 (Augie Fackler)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGe481d54f516d: tests: port inline extension in 
test-http-bundle1.t to py3 (authored by durin42, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3366?vs=8243=8266

REVISION DETAIL
  https://phab.mercurial-scm.org/D3366

AFFECTED FILES
  tests/test-http-bundle1.t

CHANGE DETAILS

diff --git a/tests/test-http-bundle1.t b/tests/test-http-bundle1.t
--- a/tests/test-http-bundle1.t
+++ b/tests/test-http-bundle1.t
@@ -179,13 +179,13 @@
   > import base64
   > from mercurial.hgweb import common
   > def perform_authentication(hgweb, req, op):
-  > auth = req.headers.get('Authorization')
+  > auth = req.headers.get(b'Authorization')
   > if not auth:
-  > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who',
-  > [('WWW-Authenticate', 'Basic Realm="mercurial"')])
+  > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, b'who',
+  > [(b'WWW-Authenticate', b'Basic Realm="mercurial"')])
   > if base64.b64decode(auth.split()[1]).split(b':', 1) != [b'user',
   > b'pass']:
-  > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no')
+  > raise common.ErrorResponse(common.HTTP_FORBIDDEN, b'no')
   > def extsetup():
   > common.permhooks.insert(0, perform_authentication)
   > EOT



To: durin42, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3368: stringutil: ast.literal_eval needs a unicode on py3

2018-04-14 Thread durin42 (Augie Fackler)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG3942bd8db8b2: stringutil: ast.literal_eval needs a unicode 
on py3 (authored by durin42, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3368?vs=8245=8264

REVISION DETAIL
  https://phab.mercurial-scm.org/D3368

AFFECTED FILES
  contrib/python3-whitelist
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -510,4 +510,6 @@
 def evalpythonliteral(s):
 """Evaluate a string containing a Python literal expression"""
 # We could backport our tokenizer hack to rewrite '' to u'' if we want
+if pycompat.ispy3:
+return ast.literal_eval(s.decode('latin1'))
 return ast.literal_eval(s)
diff --git a/contrib/python3-whitelist b/contrib/python3-whitelist
--- a/contrib/python3-whitelist
+++ b/contrib/python3-whitelist
@@ -437,4 +437,5 @@
 test-verify.t
 test-websub.t
 test-win32text.t
+test-wireproto-framing.py
 test-xdg.t



To: durin42, pulkit, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2] templates: add whyunstable template keyword

2018-04-14 Thread Yuya Nishihara
On Sat, 14 Apr 2018 19:43:15 +0800, Anton Shestakov wrote:
> # HG changeset patch
> # User Anton Shestakov 
> # Date 1522054812 -28800
> #  Mon Mar 26 17:00:12 2018 +0800
> # Node ID 987c05eac1801d0b919c874280d03f9e8cccb411
> # Parent  8bacc09814ba5500d15fb40c472e84cb95ae2f99
> templates: add whyunstable template keyword

Queued, thanks.

> +@templatekeyword('whyunstable', requires={'repo', 'ctx'})
> +def showwhyunstable(context, mapping):
> +"""List of dicts explaining all instabilities of a changeset.
> +(EXPERIMENTAL)
> +"""
> +repo = context.resource(mapping, 'repo')
> +ctx = context.resource(mapping, 'ctx')
> +
> +def formatnode(ctx):
> +return ' %s (%s)' % (scmutil.formatchangeid(ctx), ctx.phasestr())

Nit: leading ' ' isn't nice when you join() the list.

> +for entry in entries:
> +if entry.get('divergentnodes'):
> +dnodes = entry['divergentnodes']
> +entry['divergentnodes'] = ''.join(formatnode(dnode)
> +  for dnode in dnodes)

Perhaps this can be a hybrid list. Can you send a follow up?

_hybrid(None, [c.hex() for c in dnodes],
lambda x: {'ctx': repo[x]},
lambda x: formatnode(repo[c]))

(We don't have a wrapper for a list of ctx objects yet.)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2] templates: add whyunstable template keyword

2018-04-14 Thread Anton Shestakov
On Mon, 26 Mar 2018 22:13:18 +0900
Yuya Nishihara  wrote:

> On Mon, 26 Mar 2018 19:55:20 +0800, Anton Shestakov wrote:
> > # HG changeset patch
> > # User Anton Shestakov 
> > # Date 1522054812 -28800
> > #  Mon Mar 26 17:00:12 2018 +0800
> > # Node ID 123d9e4d706909c8912f11acee292735c0fb283c
> > # Parent  6f570c501e3ebc3d9b59920f50ed7523d93cb847
> > templates: add whyunstable template keyword  

I went and revived this series. Let's see if I can squeeze some patches
in before the freeze.

> > +def makemap(entry):
> > +item = {'ctx': repo[entry['node']], 'revcache': {}}  
>^^
> 
> 'revcache' is no longer needed.
> 
> Perhaps, obsutil.whyunstable() can put 'ctx' instead of 'node'?

At least in content-divergent cases, common predecessor can be absent
from local repo. I don't think there's any "surrogate" ctx (i.e. created
from hash alone) that would work here yet.

> > +item.update(entry)
> > +if item.get('divergentnodes'):
> > +dnhybrid = _hybrid(None, item['divergentnodes'],
> > +   lambda x: {'ctx': x, 'revcache': {}},
> > +   formatnode)  
> 
> Perhaps showrevslist() can be used. Each hybrid value has to be a printable
> object such as int.

Tried it, but it feels like I'm jumping through hoops for no good
reason: doing ctx.rev() and then repo[rev] right after that just to get
ctx back. Maybe I'm doing something wrong, but I have an idea (not sure
how crazy it is): I'd like to have divergentnodes be a mappinglist with
tmpl that works from inside the entries (also mappinglist). It doesn't
work yet, but I've sent an RFC to get feedback on it.

> > +item['divergentnodes'] = dnhybrid
> > +return item
> > +
> > +entries = obsutil.whyunstable(repo, ctx)
> > +return _hybrid(None, entries, makemap, formatentry)  
> 
> It isn't correct to wrap a list of template mappings by _hybrid. Instead,
> makemap() has to build a mapping dict from a printable value.
> 
> Can you hold off this series for 2-3 weeks? I have long series which will
> add a wrapper for a list of template mappings. Basically it will allow us
> to write the default string representation as template:
> 
>   return mappinglist(entries, tmpl='{instability}: {divergentnodes % ...')
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3367: hgwebdir: un-bytes the env dict before re-parsing env

2018-04-14 Thread yuja (Yuya Nishihara)
yuja requested changes to this revision.
yuja added inline comments.
This revision now requires changes to proceed.

INLINE COMMENTS

> hgwebdir_mod.py:425
>  # repository path component.
> +uenv = {k.decode('latin1'): v for k, v in
> +req.rawenv.iteritems()}

Maybe needs `if ispy3` ?

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3367

To: durin42, #hg-reviewers, yuja
Cc: yuja, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 2] templates: make divergentnodes in whyunstable keyword be a mappinglist too (RFC)

2018-04-14 Thread Anton Shestakov
# HG changeset patch
# User Anton Shestakov 
# Date 1523705764 -28800
#  Sat Apr 14 19:36:04 2018 +0800
# Node ID 6287c68bde7bcdc1dc260da9983ecc7fffc9ee20
# Parent  987c05eac1801d0b919c874280d03f9e8cccb411
templates: make divergentnodes in whyunstable keyword be a mappinglist too (RFC)

I'd like this to work, but it doesn't: "{divergentnodes}" show a178212c3433 as
the divergent node, and not 70d5a63ca112 (so the whole test case fails).

diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -800,20 +800,17 @@ def showwhyunstable(context, mapping):
 """
 repo = context.resource(mapping, 'repo')
 ctx = context.resource(mapping, 'ctx')
-
-def formatnode(ctx):
-return ' %s (%s)' % (scmutil.formatchangeid(ctx), ctx.phasestr())
-
 entries = obsutil.whyunstable(repo, ctx)
+mappinglist = templateutil.mappinglist
 
 for entry in entries:
 if entry.get('divergentnodes'):
-dnodes = entry['divergentnodes']
-entry['divergentnodes'] = ''.join(formatnode(dnode)
-  for dnode in dnodes)
+dnodes = [{ctx: dnode} for dnode in entry['divergentnodes']]
+tmpl = ' {rev}:{node|short} ({phase})'
+entry['divergentnodes'] = mappinglist(dnodes, tmpl=tmpl)
 
 tmpl = '{instability}:{divergentnodes} {reason} {node|short}'
-return templateutil.mappinglist(entries, tmpl=tmpl, sep='\n')
+return mappinglist(entries, tmpl=tmpl, sep='\n')
 
 def loadkeyword(ui, extname, registrarobj):
 """Load template keyword from specified registrarobj
diff --git a/tests/test-obsolete-divergent.t b/tests/test-obsolete-divergent.t
--- a/tests/test-obsolete-divergent.t
+++ b/tests/test-obsolete-divergent.t
@@ -725,6 +725,8 @@ Use scmutil.cleanupnodes API to create d
   content-divergent: 4:70d5a63ca112 (draft) predecessor a178212c3433
   $ hg log -r 1a2a9b5b0030 --hidden -T 
'{whyunstable%"{instability}:{divergentnodes} {reason} {node}\n"}'
   content-divergent: 4:70d5a63ca112 (draft) predecessor 
a178212c3433c4e77b573f6011e29affb8aefa33
+  $ hg log -r 1a2a9b5b0030 --hidden -T 
'{whyunstable%"{instability}:{divergentnodes % " {node} ({phase})"} {reason} 
{node}\n"}'
+  content-divergent: 70d5a63ca112acb3764bc1d7320ca90ea688d671 (draft) 
predecessor a178212c3433c4e77b573f6011e29affb8aefa33
 
 #if serve
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 2] templates: add whyunstable template keyword

2018-04-14 Thread Anton Shestakov
# HG changeset patch
# User Anton Shestakov 
# Date 1522054812 -28800
#  Mon Mar 26 17:00:12 2018 +0800
# Node ID 987c05eac1801d0b919c874280d03f9e8cccb411
# Parent  8bacc09814ba5500d15fb40c472e84cb95ae2f99
templates: add whyunstable template keyword

diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -793,6 +793,28 @@ def showverbosity(context, mapping):
 return 'verbose'
 return ''
 
+@templatekeyword('whyunstable', requires={'repo', 'ctx'})
+def showwhyunstable(context, mapping):
+"""List of dicts explaining all instabilities of a changeset.
+(EXPERIMENTAL)
+"""
+repo = context.resource(mapping, 'repo')
+ctx = context.resource(mapping, 'ctx')
+
+def formatnode(ctx):
+return ' %s (%s)' % (scmutil.formatchangeid(ctx), ctx.phasestr())
+
+entries = obsutil.whyunstable(repo, ctx)
+
+for entry in entries:
+if entry.get('divergentnodes'):
+dnodes = entry['divergentnodes']
+entry['divergentnodes'] = ''.join(formatnode(dnode)
+  for dnode in dnodes)
+
+tmpl = '{instability}:{divergentnodes} {reason} {node|short}'
+return templateutil.mappinglist(entries, tmpl=tmpl, sep='\n')
+
 def loadkeyword(ui, extname, registrarobj):
 """Load template keyword from specified registrarobj
 """
diff --git a/tests/test-obsolete-divergent.t b/tests/test-obsolete-divergent.t
--- a/tests/test-obsolete-divergent.t
+++ b/tests/test-obsolete-divergent.t
@@ -721,6 +721,11 @@ Use scmutil.cleanupnodes API to create d
   $ hg debugwhyunstable 1a2a9b5b0030
   content-divergent: 70d5a63ca112acb3764bc1d7320ca90ea688d671 (draft) 
predecessor a178212c3433c4e77b573f6011e29affb8aefa33
 
+  $ hg log -r 1a2a9b5b0030 --hidden -T '{whyunstable}\n'
+  content-divergent: 4:70d5a63ca112 (draft) predecessor a178212c3433
+  $ hg log -r 1a2a9b5b0030 --hidden -T 
'{whyunstable%"{instability}:{divergentnodes} {reason} {node}\n"}'
+  content-divergent: 4:70d5a63ca112 (draft) predecessor 
a178212c3433c4e77b573f6011e29affb8aefa33
+
 #if serve
 
   $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E 
errors.log
diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t
--- a/tests/test-obsolete.t
+++ b/tests/test-obsolete.t
@@ -1044,6 +1044,15 @@ test debugwhyunstable output
   orphan: obsolete parent 3de5eca88c00aa039da7399a220f4a5221faa585
   phase-divergent: immutable predecessor 
245bde4270cd1072a27757984f9cda8ba26f08ca
 
+test whyunstable template keyword
+
+  $ hg log -r 50c51b361e60 -T '{whyunstable}\n'
+  orphan: obsolete parent 3de5eca88c00
+  phase-divergent: immutable predecessor 245bde4270cd
+  $ hg log -r 50c51b361e60 -T '{whyunstable%"{instability}: {reason} 
{node}\n"}'
+  orphan: obsolete parent 3de5eca88c00aa039da7399a220f4a5221faa585
+  phase-divergent: immutable predecessor 
245bde4270cd1072a27757984f9cda8ba26f08ca
+
 #if serve
 
   $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E 
errors.log
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D2880: bundle: add the possibility to bundle bookmarks (issue5792)

2018-04-14 Thread lothiraldan (Boris Feld)
lothiraldan added inline comments.

INLINE COMMENTS

> martinvonz wrote in test-bundle-bookmarks.t:37-63
> Can we have a similar test case where we create divergence? Create a fork in 
> the graph in the debugdrawdag call above. Let's say you have commit F that 
> branches off of B, then do something like this:
> 
>   $ hg bundle --all bundle
>   $ hg strip --no-backup C
>   $ hg bookmarks -f -r F D1
>   $ hg unbundle -q bundle
>   $ hg log -G -T '{desc} {bookmarks}\n'
> o  E
> |
> o  D D1 D2
> |
> o  C
> |
> |  o F D1@1
> |/
> o  B
> |
> o  A A1
> 
> I don't know if "@1" is the appropriate divergence marker, but I can't think 
> of a better one. I haven't even looked at your code to try to guess what it 
> would be in practice (if it would work at all).

I have added such test and indeed this case is not handled right now. I'm not 
aware of how Mercurial handle this case when exchanging bookmarks, I will need 
to take a look at the code to find out.

What is the correct behavior here? Change the existing bookmark or the bookmark 
from the bundle?

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D2880

To: lothiraldan, #hg-reviewers, indygreg
Cc: martinvonz, indygreg, pulkit, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D2880: bundle: add the possibility to bundle bookmarks (issue5792)

2018-04-14 Thread lothiraldan (Boris Feld)
lothiraldan updated this revision to Diff 8263.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2880?vs=7077=8263

REVISION DETAIL
  https://phab.mercurial-scm.org/D2880

AFFECTED FILES
  mercurial/bundle2.py
  mercurial/commands.py
  mercurial/configitems.py
  mercurial/debugcommands.py
  tests/test-bundle-bookmarks.t

CHANGE DETAILS

diff --git a/tests/test-bundle-bookmarks.t b/tests/test-bundle-bookmarks.t
new file mode 100644
--- /dev/null
+++ b/tests/test-bundle-bookmarks.t
@@ -0,0 +1,116 @@
+  $ cat >> $HGRCPATH < [experimental]
+  > bundle-bookmarks=yes
+  > [extensions]
+  > strip=
+  > drawdag=$TESTDIR/drawdag.py
+  > EOF
+
+Set up repo with linear history
+  $ hg init linear
+  $ cd linear
+  $ hg debugdrawdag <<'EOF'
+  > E
+  > |
+  > D
+  > |
+  > C
+  > |
+  > B
+  > |
+  > A
+  > EOF
+  $ hg bookmarks -r A "A1"
+  $ hg bookmarks -r D "D1"
+  $ hg bookmarks -r D "D2"
+  $ hg log -G -T '{desc} {bookmarks}\n'
+  o  E
+  |
+  o  D D1 D2
+  |
+  o  C
+  |
+  o  B
+  |
+  o  A A1
+  
+Bookmarks are restored when unbundling
+  $ hg bundle --all bundle
+  5 changesets found
+  $ hg debugbundle bundle
+  Stream params: {Compression: BZ}
+  changegroup -- {nbchanges: 5, version: 02}
+  426bada5c67598ca65036d57d9e4b64b0c1ce7a0
+  112478962961147124edd43549aedd1a335e44bf
+  26805aba1e600a82e93661149f2313866a221a7b
+  f585351a92f85104bff7c284233c338b10eb1df7
+  9bc730a19041f9ec7cb33c626e811aa233efb18c
+  bookmarks -- {}
+  A1: Bk\xad\xa5\xc6u\x98\xcae\x03mW\xd9\xe4\xb6K\x0c\x1c\xe7\xa0 (esc)
+  D1: \xf5\x855\x1a\x92\xf8Q\x04\xbf\xf7\xc2\x84#<3\x8b\x10\xeb\x1d\xf7 
(esc)
+  D2: \xf5\x855\x1a\x92\xf8Q\x04\xbf\xf7\xc2\x84#<3\x8b\x10\xeb\x1d\xf7 
(esc)
+  $ hg strip --no-backup C
+  $ hg unbundle -q bundle
+  $ hg log -G -T '{desc} {bookmarks}\n'
+  o  E
+  |
+  o  D D1 D2
+  |
+  o  C
+  |
+  o  B
+  |
+  o  A A1
+  
+Bookmarks doesn't conflict with local bookmarks
+
+  $ hg bookmarks -d A1
+  $ hg bookmarks -r A "A2"
+  $ hg unbundle -q bundle
+  $ hg log -G -T '{desc} {bookmarks}\n'
+  o  E
+  |
+  o  D D1 D2
+  |
+  o  C
+  |
+  o  B
+  |
+  o  A A1 A2
+  
+Test bookmarks divergence
+
+  $ hg bundle --all bundle
+  5 changesets found
+  $ hg strip --no-backup C
+
+Create soem divergence
+  $ hg up B
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ touch F
+  $ hg add F
+  $ hg commit -m "F"
+  $ hg bookmarks -f -r "desc(F)" D1
+
+  $ hg log -G -T '{desc} {bookmarks}\n'
+  @  F D1
+  |
+  o  B D2
+  |
+  o  A A1 A2
+  
+
+  $ hg unbundle -q bundle
+  $ hg log -G -T '{desc} {bookmarks}\n'
+  o  E
+  |
+  o  D D1 D2
+  |
+  o  C
+  |
+  | @  F
+  |/
+  o  B
+  |
+  o  A A1 A2
+  
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -33,6 +33,7 @@
 short,
 )
 from . import (
+bookmarks,
 bundle2,
 changegroup,
 cmdutil,
@@ -326,6 +327,14 @@
 ui.write(indent_string)
 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
 
+def _debugbookmarks(ui, data, indent=0):
+"""display version and markers contained in 'data'"""
+indent_string = ' ' * indent
+bm = bookmarks.binarydecode(data)
+for bookmark in sorted(bm):
+ui.write(indent_string)
+ui.write('%s: %s\n' % (bookmark[0], bookmark[1]))
+
 def _quasirepr(thing):
 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
 return '{%s}' % (
@@ -353,6 +362,9 @@
 if part.type == 'phase-heads':
 if not ui.quiet:
 _debugphaseheads(ui, part, indent=4)
+if part.type == 'bookmarks':
+if not ui.quiet:
+_debugbookmarks(ui, part, indent=4)
 
 @command('debugbundle',
 [('a', 'all', None, _('show all details')),
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -419,6 +419,9 @@
 coreconfigitem('experimental', 'archivemetatemplate',
 default=dynamicdefault,
 )
+coreconfigitem('experimental', 'bundle-bookmarks',
+default=False,
+)
 coreconfigitem('experimental', 'bundle-phases',
 default=False,
 )
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1267,6 +1267,8 @@
 contentopts['obsolescence'] = True
 if repo.ui.configbool('experimental', 'bundle-phases'):
 contentopts['phases'] = True
+if repo.ui.configbool('experimental', 'bundle-bookmarks'):
+contentopts['bookmarks'] = True
 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
contentopts, compression=bcompression,
compopts=compopts)
@@ -5406,7 +5408,7 @@
 """
 fnames = (fname1,) + fnames
 
-with repo.lock():
+with repo.wlock(), repo.lock():
 for fname in fnames:
 

[PATCH] test-check-commit: don't run hg per commit

2018-04-14 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1523694452 -32400
#  Sat Apr 14 17:27:32 2018 +0900
# Node ID 34cde18a454484a1cf6e716a3325ca9282277d59
# Parent  e743b8524d608684b5a947337c37b686cfc0ae5b
test-check-commit: don't run hg per commit

We aren't stress testing CPU.

  $ time ./run-tests.py -l test-check-commit.t --timeout 600
  (orig) 162.59s user 17.98s system 101% cpu 2:58.55 total
  (new)  5.85s user 0.99s system 98% cpu 6.939 total

diff --git a/tests/test-check-commit.t b/tests/test-check-commit.t
--- a/tests/test-check-commit.t
+++ b/tests/test-check-commit.t
@@ -8,15 +8,16 @@ Go back in the hg repo
 
   $ cd $TESTDIR/..
 
-  $ for node in `testrepohg log --rev 'not public() and ::. and not desc("# 
no-check-commit")' --template '{node|short}\n'`; do
-  >testrepohg export --git $node \
-  >| contrib/check-commit > ${TESTTMP}/check-commit.out
+  $ mkdir "$TESTTMP/p"
+  $ testrepohg export --git -o "$TESTTMP/p/%n-%h" \
+  > -r 'not public() and ::. and not desc("# no-check-commit")'
+  $ for f in `ls "$TESTTMP/p"`; do
+  >contrib/check-commit < "$TESTTMP/p/$f" > "$TESTTMP/check-commit.out"
   >if [ $? -ne 0 ]; then
+  >node="${f##*-}"
   >echo "Revision $node does not comply with rules"
   >echo '--'
   >cat ${TESTTMP}/check-commit.out
   >echo
   >   fi
   > done
-
-
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3370: scmutil: introduce shortesthexnodeidprefix()

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGe743b8524d60: scmutil: introduce shortesthexnodeidprefix() 
(authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3370?vs=8254=8262

REVISION DETAIL
  https://phab.mercurial-scm.org/D3370

AFFECTED FILES
  hgext/show.py
  mercurial/scmutil.py
  mercurial/templatefuncs.py

CHANGE DETAILS

diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -590,8 +590,8 @@
 # _partialmatch() of filtered changelog could take O(len(repo)) time,
 # which would be unacceptably slow. so we look for hash collision in
 # unfiltered space, which means some hashes may be slightly longer.
-cl = context.resource(mapping, 'ctx')._repo.unfiltered().changelog
-return cl.shortest(node, minlength)
+repo = context.resource(mapping, 'ctx')._repo
+return scmutil.shortesthexnodeidprefix(repo.unfiltered(), node, minlength)
 
 @templatefunc('strip(text[, chars])')
 def strip(context, mapping, args):
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -443,6 +443,10 @@
 repo.changelog.rev(node)  # make sure node isn't filtered
 return node
 
+def shortesthexnodeidprefix(repo, hexnode, minlength=1):
+"""Find the shortest unambiguous prefix that matches hexnode."""
+return repo.changelog.shortest(hexnode, minlength)
+
 def isrevsymbol(repo, symbol):
 """Checks if a symbol exists in the repo.
 
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -45,6 +45,7 @@
 registrar,
 revset,
 revsetlang,
+scmutil,
 )
 
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' 
for
@@ -447,8 +448,10 @@
 if not revs:
 return minlen
 # don't use filtered repo because it's slow. see templater.shortest().
-cl = repo.unfiltered().changelog
-return max(len(cl.shortest(hex(cl.node(r)), minlen)) for r in revs)
+cl = repo.changelog
+return max(len(scmutil.shortesthexnodeidprefix(repo.unfiltered(),
+   hex(cl.node(r)),
+   minlen)) for r in revs)
 
 # Adjust the docstring of the show command so it shows all registered views.
 # This is a bit hacky because it runs at the end of module load. When moved



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3307: context: set stack level for deprecation warning

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG1764527af92e: context: set stack level for deprecation 
warning (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3307?vs=8113=8258

REVISION DETAIL
  https://phab.mercurial-scm.org/D3307

AFFECTED FILES
  mercurial/context.py

CHANGE DETAILS

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -399,7 +399,7 @@
 #  * If "x" can be a mix of the above, you'll have to figure it out
 #yourself
 repo.ui.deprecwarn("changectx.__init__ is getting more limited, see source 
"
-   "for details", "4.6")
+   "for details", "4.6", stacklevel=4)
 
 class changectx(basectx):
 """A changecontext object makes access to data related to a particular



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3309: scmutil: rename resolvepartialhexnodeid() to resolvehexnodeidprefix()

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG5f8f013e7d52: scmutil: rename resolvepartialhexnodeid() to 
resolvehexnodeidprefix() (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3309?vs=8252=8260

REVISION DETAIL
  https://phab.mercurial-scm.org/D3309

AFFECTED FILES
  hgext/eol.py
  hgext/histedit.py
  mercurial/context.py
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -434,8 +434,8 @@
 hexfunc = short
 return '%d:%s' % (rev, hexfunc(node))
 
-def resolvepartialhexnodeid(repo, prefix):
-# Uses unfiltered repo because it's faster when then prefix is ambiguous/
+def resolvehexnodeidprefix(repo, prefix):
+# Uses unfiltered repo because it's faster when prefix is ambiguous/
 # This matches the "shortest" template function.
 node = repo.unfiltered().changelog._partialmatch(prefix)
 if node is None:
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -392,7 +392,7 @@
 #  * If you know that "x" is a branch or in some other namespace,
 #use the appropriate mechanism for that namespace
 #  * If you know that "x" is a hex nodeid prefix, use
-#repo[scmutil.resolvepartialhexnodeid(repo, x)]
+#repo[scmutil.resolvehexnodeidprefix(repo, x)]
 #  * If "x" is a string that can be any of the above, but you don't want
 #to allow general revsets (perhaps because "x" may come from a remote
 #user and the revset may be too costly), use scmutil.revsymbol(repo, x)
@@ -476,7 +476,7 @@
 except KeyError:
 pass
 
-self._node = scmutil.resolvepartialhexnodeid(repo, changeid)
+self._node = scmutil.resolvehexnodeidprefix(repo, changeid)
 if self._node is not None:
 self._rev = repo.changelog.rev(self._node)
 changectxdeprecwarn(repo)
diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -443,7 +443,7 @@
 """ Verifies semantic correctness of the rule"""
 repo = self.repo
 ha = node.hex(self.node)
-self.node = scmutil.resolvepartialhexnodeid(repo, ha)
+self.node = scmutil.resolvehexnodeidprefix(repo, ha)
 if self.node is None:
 raise error.ParseError(_('unknown changeset %s listed') % ha[:12])
 self._verifynodeconstraints(prev, expected, seen)
diff --git a/hgext/eol.py b/hgext/eol.py
--- a/hgext/eol.py
+++ b/hgext/eol.py
@@ -300,7 +300,7 @@
 hook = checkheadshook
 
 def preupdate(ui, repo, hooktype, parent1, parent2):
-p1node = scmutil.resolvepartialhexnodeid(repo, parent1)
+p1node = scmutil.resolvehexnodeidprefix(repo, parent1)
 repo.loadeol([p1node])
 return False
 



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3310: scmutil: use resolvehexnodeidprefix() from revsymbol()

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGab828755e1ea: scmutil: use resolvehexnodeidprefix() from 
revsymbol() (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3310?vs=8253=8261

REVISION DETAIL
  https://phab.mercurial-scm.org/D3310

AFFECTED FILES
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -503,7 +503,7 @@
 except KeyError:
 pass
 
-node = repo.unfiltered().changelog._partialmatch(symbol)
+node = resolvehexnodeidprefix(repo, symbol)
 if node is not None:
 rev = repo.changelog.rev(node)
 return repo[rev]



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3308: scmutil: document that isrevsymbol() raises on ambiguous node prefix

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG41ac707322ba: scmutil: document that isrevsymbol() raises 
on ambiguous node prefix (authored by martinvonz, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D3308?vs=8251=8259#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3308?vs=8251=8259

REVISION DETAIL
  https://phab.mercurial-scm.org/D3308

AFFECTED FILES
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -444,6 +444,11 @@
 return node
 
 def isrevsymbol(repo, symbol):
+"""Checks if a symbol exists in the repo.
+
+See revsymbol() for details. Raises error.LookupError if the symbol is an
+ambiguous nodeid prefix.
+"""
 try:
 revsymbol(repo, symbol)
 return True



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3331: util: set correct stack level on deprecation warnings

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG5b8a260769a2: util: set correct stack level on deprecation 
warnings (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3331?vs=8151=8257

REVISION DETAIL
  https://phab.mercurial-scm.org/D3331

AFFECTED FILES
  mercurial/util.py

CHANGE DETAILS

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -3781,7 +3781,7 @@
 fn = pycompat.sysbytes(func.__name__)
 mn = modname or pycompat.sysbytes(func.__module__)[len('mercurial.'):]
 msg = "'util.%s' is deprecated, use '%s.%s'" % (fn, mn, fn)
-nouideprecwarn(msg, version)
+nouideprecwarn(msg, version, stacklevel=2)
 return func(*args, **kwargs)
 wrapped.__name__ = func.__name__
 return wrapped



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3311: revset: use resolvehexnodeidprefix() in id() predicate (BC)

2018-04-14 Thread yuja (Yuya Nishihara)
yuja requested changes to this revision.
yuja added a comment.
This revision now requires changes to proceed.


  I have vague memory that it was intentional. Since `rev()` and `id()` never
  error out on unknown identifier, it doesn't make sense to reject only
  ambiguous nodeid.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3311

To: martinvonz, #hg-reviewers, yuja
Cc: yuja, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 3 of 5] lfs: fix the inferred remote store path when using a --prefix

2018-04-14 Thread Yuya Nishihara
On Fri, 13 Apr 2018 18:04:35 -0400, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison 
> # Date 1523643390 14400
> #  Fri Apr 13 14:16:30 2018 -0400
> # Node ID a4c12789ef4bac6e736681ef8a08ccbe71fb5c41
> # Parent  54c1ab20ed7fbf415d087e6e94ca273d172046e8
> lfs: fix the inferred remote store path when using a --prefix

The series looks good to me, except for the test failure.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 2 of 5] lfs: log information about Internal Server Errors reported in the Batch API

2018-04-14 Thread Yuya Nishihara
On Fri, 13 Apr 2018 18:04:34 -0400, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison 
> # Date 1523637594 14400
> #  Fri Apr 13 12:39:54 2018 -0400
> # Node ID 54c1ab20ed7fbf415d087e6e94ca273d172046e8
> # Parent  1d394ac0efd4aa4f61f428fbac140fe57398f0b8
> lfs: log information about Internal Server Errors reported in the Batch API

> +def _logexception(req):
> +"""Write information about the current exception to wsgi.errors."""
> +tb = traceback.format_exc()
> +# We need a native-string newline to poke in the log
> +# message, because we won't get a newline when using an
> +# r-string. This is the easy way out.
> +newline = chr(10)
> +errorlog = req.rawenv[r'wsgi.errors']
> +
> +uri = ''
> +if req.apppath:
> +uri += req.apppath
> +uri += b'/' + req.dispatchpath
> +
> +errorlog.write(r"Exception happened while processing request "
> +   r"'%s':%s%s" % (uri.decode('latin-1'), newline, tb))

errorlog is a binary stream as far as I can tell from our codebase. We'll
instead have to convert tb to bytes by pycompat.sysbytes().
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 5] test-lfs: add tests to force server error path coverage

2018-04-14 Thread Yuya Nishihara
On Fri, 13 Apr 2018 18:04:33 -0400, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison 
> # Date 1523119701 14400
> #  Sat Apr 07 12:48:21 2018 -0400
> # Node ID 1d394ac0efd4aa4f61f428fbac140fe57398f0b8
> # Parent  bfdd20d22a86edc318493b4da84a1d7ff4ef98f2
> test-lfs: add tests to force server error path coverage

The test failed on my machine. Can you take a look?


--- /home/yuya/work/hghacks/mercurial-review/tests/test-lfs-serve-access.t
+++ /home/yuya/work/hghacks/mercurial-review/tests/test-lfs-serve-access.t.err
@@ -270,14 +270,12 @@
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - 
x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ 
partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - 
x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ 
partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - 
x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
-  $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - 
x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - 
x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ 
partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - 
(glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - 
x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d 
x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - 
x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ 
partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - 
x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ 
partial-pull (glob)
-  $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - 
x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=branchmap HTTP/1.1" 200 - 
x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - 
x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ 
partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - 
(glob)

ERROR: test-lfs-serve-access.t output changed
!
Failed test-lfs-serve-access.t: output changed
# Ran 1 tests, 0 skipped, 1 failed.
python hash seed: 3873177365
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3308: scmutil: document that isrevsymbol() raises on ambiguous node prefix

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8251.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3308?vs=8114=8251

REVISION DETAIL
  https://phab.mercurial-scm.org/D3308

AFFECTED FILES
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -444,6 +444,11 @@
 return node
 
 def isrevsymbol(repo, symbol):
+"""Checks if a symbol exists in the repo.
+
+   See revsymbol() for details. Raises error.LookupError if the symbol is 
an
+   ambiguous nodeid prefix.
+"""
 try:
 revsymbol(repo, symbol)
 return True



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3370: scmutil: introduce shortesthexnodeidprefix()

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8254.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3370?vs=8249=8254

REVISION DETAIL
  https://phab.mercurial-scm.org/D3370

AFFECTED FILES
  hgext/show.py
  mercurial/scmutil.py
  mercurial/templatefuncs.py

CHANGE DETAILS

diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -590,8 +590,8 @@
 # _partialmatch() of filtered changelog could take O(len(repo)) time,
 # which would be unacceptably slow. so we look for hash collision in
 # unfiltered space, which means some hashes may be slightly longer.
-cl = context.resource(mapping, 'ctx')._repo.unfiltered().changelog
-return cl.shortest(node, minlength)
+repo = context.resource(mapping, 'ctx')._repo
+return scmutil.shortesthexnodeidprefix(repo.unfiltered(), node, minlength)
 
 @templatefunc('strip(text[, chars])')
 def strip(context, mapping, args):
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -443,6 +443,10 @@
 repo.changelog.rev(node)  # make sure node isn't filtered
 return node
 
+def shortesthexnodeidprefix(repo, hexnode, minlength=1):
+"""Find the shortest unambiguous prefix that matches hexnode."""
+return repo.changelog.shortest(hexnode, minlength)
+
 def isrevsymbol(repo, symbol):
 """Checks if a symbol exists in the repo.
 
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -45,6 +45,7 @@
 registrar,
 revset,
 revsetlang,
+scmutil,
 )
 
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' 
for
@@ -447,8 +448,10 @@
 if not revs:
 return minlen
 # don't use filtered repo because it's slow. see templater.shortest().
-cl = repo.unfiltered().changelog
-return max(len(cl.shortest(hex(cl.node(r)), minlen)) for r in revs)
+cl = repo.changelog
+return max(len(scmutil.shortesthexnodeidprefix(repo.unfiltered(),
+   hex(cl.node(r)),
+   minlen)) for r in revs)
 
 # Adjust the docstring of the show command so it shows all registered views.
 # This is a bit hacky because it runs at the end of module load. When moved



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3310: scmutil: use resolvehexnodeidprefix() from revsymbol()

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8253.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3310?vs=8116=8253

REVISION DETAIL
  https://phab.mercurial-scm.org/D3310

AFFECTED FILES
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -503,7 +503,7 @@
 except KeyError:
 pass
 
-node = repo.unfiltered().changelog._partialmatch(symbol)
+node = resolvehexnodeidprefix(repo, symbol)
 if node is not None:
 rev = repo.changelog.rev(node)
 return repo[rev]



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3309: scmutil: rename resolvepartialhexnodeid() to resolvehexnodeidprefix()

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8252.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3309?vs=8247=8252

REVISION DETAIL
  https://phab.mercurial-scm.org/D3309

AFFECTED FILES
  hgext/eol.py
  hgext/histedit.py
  mercurial/context.py
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -434,8 +434,8 @@
 hexfunc = short
 return '%d:%s' % (rev, hexfunc(node))
 
-def resolvepartialhexnodeid(repo, prefix):
-# Uses unfiltered repo because it's faster when then prefix is ambiguous/
+def resolvehexnodeidprefix(repo, prefix):
+# Uses unfiltered repo because it's faster when prefix is ambiguous/
 # This matches the "shortest" template function.
 node = repo.unfiltered().changelog._partialmatch(prefix)
 if node is None:
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -392,7 +392,7 @@
 #  * If you know that "x" is a branch or in some other namespace,
 #use the appropriate mechanism for that namespace
 #  * If you know that "x" is a hex nodeid prefix, use
-#repo[scmutil.resolvepartialhexnodeid(repo, x)]
+#repo[scmutil.resolvehexnodeidprefix(repo, x)]
 #  * If "x" is a string that can be any of the above, but you don't want
 #to allow general revsets (perhaps because "x" may come from a remote
 #user and the revset may be too costly), use scmutil.revsymbol(repo, x)
@@ -476,7 +476,7 @@
 except KeyError:
 pass
 
-self._node = scmutil.resolvepartialhexnodeid(repo, changeid)
+self._node = scmutil.resolvehexnodeidprefix(repo, changeid)
 if self._node is not None:
 self._rev = repo.changelog.rev(self._node)
 changectxdeprecwarn(repo)
diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -443,7 +443,7 @@
 """ Verifies semantic correctness of the rule"""
 repo = self.repo
 ha = node.hex(self.node)
-self.node = scmutil.resolvepartialhexnodeid(repo, ha)
+self.node = scmutil.resolvehexnodeidprefix(repo, ha)
 if self.node is None:
 raise error.ParseError(_('unknown changeset %s listed') % ha[:12])
 self._verifynodeconstraints(prev, expected, seen)
diff --git a/hgext/eol.py b/hgext/eol.py
--- a/hgext/eol.py
+++ b/hgext/eol.py
@@ -300,7 +300,7 @@
 hook = checkheadshook
 
 def preupdate(ui, repo, hooktype, parent1, parent2):
-p1node = scmutil.resolvepartialhexnodeid(repo, parent1)
+p1node = scmutil.resolvehexnodeidprefix(repo, parent1)
 repo.loadeol([p1node])
 return False
 



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3313: scmutil: make shortesthexnodeidprefix() use unfiltered repo

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8255.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3313?vs=8250=8255

REVISION DETAIL
  https://phab.mercurial-scm.org/D3313

AFFECTED FILES
  hgext/show.py
  mercurial/scmutil.py
  mercurial/templatefuncs.py

CHANGE DETAILS

diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -587,11 +587,8 @@
 # i18n: "shortest" is a keyword
 _("shortest() expects an integer minlength"))
 
-# _partialmatch() of filtered changelog could take O(len(repo)) time,
-# which would be unacceptably slow. so we look for hash collision in
-# unfiltered space, which means some hashes may be slightly longer.
 repo = context.resource(mapping, 'ctx')._repo
-return scmutil.shortesthexnodeidprefix(repo.unfiltered(), node, minlength)
+return scmutil.shortesthexnodeidprefix(repo, node, minlength)
 
 @templatefunc('strip(text[, chars])')
 def strip(context, mapping, args):
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -436,16 +436,19 @@
 
 def resolvehexnodeidprefix(repo, prefix):
 # Uses unfiltered repo because it's faster when prefix is ambiguous/
-# This matches the "shortest" template function.
+# This matches the shortesthexnodeidprefix() function below.
 node = repo.unfiltered().changelog._partialmatch(prefix)
 if node is None:
 return
 repo.changelog.rev(node)  # make sure node isn't filtered
 return node
 
 def shortesthexnodeidprefix(repo, hexnode, minlength=1):
 """Find the shortest unambiguous prefix that matches hexnode."""
-return repo.changelog.shortest(hexnode, minlength)
+# _partialmatch() of filtered changelog could take O(len(repo)) time,
+# which would be unacceptably slow. so we look for hash collision in
+# unfiltered space, which means some hashes may be slightly longer.
+return repo.unfiltered().changelog.shortest(hexnode, minlength)
 
 def isrevsymbol(repo, symbol):
 """Checks if a symbol exists in the repo.
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -447,10 +447,8 @@
 """
 if not revs:
 return minlen
-# don't use filtered repo because it's slow. see templater.shortest().
 cl = repo.changelog
-return max(len(scmutil.shortesthexnodeidprefix(repo.unfiltered(),
-   hex(cl.node(r)),
+return max(len(scmutil.shortesthexnodeidprefix(repo, hex(cl.node(r)),
minlen)) for r in revs)
 
 # Adjust the docstring of the show command so it shows all registered views.



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3371: scmutil: make shortesthexnodeidprefix() take a full binary nodeid

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The shortest() template function depended on the behavior of
  revlog._partialmatch() for these types of inputs:
  
  - non-hex strings
  - ambiguous strings
  - too long strings
  
  revlog._partialmatch() seems to return the input unchanged in these
  cases, but we shouldn't depend on such a low-level function to match
  the behavior we want in the user-facing template function. Instead,
  let's handle these cases in the template function and always pass a
  binary nodeid to _partialmatch().

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3371

AFFECTED FILES
  hgext/show.py
  mercurial/scmutil.py
  mercurial/templatefuncs.py
  tests/test-command-template.t

CHANGE DETAILS

diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -3900,6 +3900,21 @@
   $ hg log -r 'wdir()' -T '{node|shortest}\n'
   
 
+  $ hg log --template '{shortest("f")}\n' -l1
+  f
+
+  $ hg log --template 
'{shortest("0123456789012345678901234567890123456789")}\n' -l1
+  0123456789012345678901234567890123456789
+
+  $ hg log --template 
'{shortest("01234567890123456789012345678901234567890123456789")}\n' -l1
+  01234567890123456789012345678901234567890123456789
+
+  $ hg log --template '{shortest("not a hex string")}\n' -l1
+  not a hex string
+
+  $ hg log --template '{shortest("not a hex string, but it'\''s 40 bytes 
long")}\n' -l1
+  not a hex string, but it's 40 bytes long
+
   $ cd ..
 
 Test shortest(node) with the repo having short hash collision:
diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -26,6 +26,9 @@
 templateutil,
 util,
 )
+from .node import (
+bin,
+)
 from .utils import (
 dateutil,
 stringutil,
@@ -579,15 +582,29 @@
 # i18n: "shortest" is a keyword
 raise error.ParseError(_("shortest() expects one or two arguments"))
 
-node = evalstring(context, mapping, args[0])
+hexnode = evalstring(context, mapping, args[0])
 
 minlength = 4
 if len(args) > 1:
 minlength = evalinteger(context, mapping, args[1],
 # i18n: "shortest" is a keyword
 _("shortest() expects an integer minlength"))
 
 repo = context.resource(mapping, 'ctx')._repo
+if len(hexnode) > 40:
+return hexnode
+elif len(hexnode) == 40:
+try:
+node = bin(hexnode)
+except TypeError:
+return hexnode
+else:
+try:
+node = scmutil.resolvehexnodeidprefix(repo, hexnode)
+except (error.LookupError, error.WdirUnsupported):
+return hexnode
+if not node:
+return hexnode
 return scmutil.shortesthexnodeidprefix(repo, node, minlength)
 
 @templatefunc('strip(text[, chars])')
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -443,12 +443,12 @@
 repo.changelog.rev(node)  # make sure node isn't filtered
 return node
 
-def shortesthexnodeidprefix(repo, hexnode, minlength=1):
+def shortesthexnodeidprefix(repo, node, minlength=1):
 """Find the shortest unambiguous prefix that matches hexnode."""
 # _partialmatch() of filtered changelog could take O(len(repo)) time,
 # which would be unacceptably slow. so we look for hash collision in
 # unfiltered space, which means some hashes may be slightly longer.
-return repo.unfiltered().changelog.shortest(hexnode, minlength)
+return repo.unfiltered().changelog.shortest(hex(node), minlength)
 
 def isrevsymbol(repo, symbol):
 """Checks if a symbol exists in the repo.
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -448,8 +448,8 @@
 if not revs:
 return minlen
 cl = repo.changelog
-return max(len(scmutil.shortesthexnodeidprefix(repo, hex(cl.node(r)),
-   minlen)) for r in revs)
+return max(len(scmutil.shortesthexnodeidprefix(repo, cl.node(r), minlen))
+   for r in revs)
 
 # Adjust the docstring of the show command so it shows all registered views.
 # This is a bit hacky because it runs at the end of module load. When moved



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] dispatch: add a whitelist map of commands to implicitly loaded extensions

2018-04-14 Thread Yuya Nishihara
On Fri, 13 Apr 2018 23:30:43 -0400, Matt Harbison wrote:
> On Fri, 13 Apr 2018 15:10:45 -0400, Gregory Szorc  
>  wrote:
> > What we may want instead is to key things off .hg/requires or a
> > to-be-invented supplemental requirements-like file that declares soft
> > features. localrepository.__init__ could then load trusted extensions at
> > repo open time if a requirements/capability was present/requested. i.e.  
> > if
> > you talk to an LFS server, write a semaphore somewhere into .hg/ and have
> > something in core look for that and automatically load lfs if present.  
> > This would get you the "automatically enable LFS when talking to LFS  
> > servers"
> > benefits.
> 
> Sounds promising.  One of the things the lfs extension is doing is writing  
> '[extensions]\nlfs=' to the repo's local hgrc file in a commit hook (it  
> should probably be handling transactions too).  So it would be nice if  
> this was baked into the core somehow (largefiles could use exactly the  
> same handling, and I'm assuming narrow will be similar).  It's also  
> manually adding to the requires file, since that doesn't seem to be  
> updated in exchange.
> 
> Assuming the semaphore is persistent, it could be beneficial to load  
> extensions indicated by it around the normal load time (e.g., largefiles  
> wraps the clone command and adds extra switches).
> 
> I'm not sure if this addresses Yuya's concern about long lived processes  
> though.

If the extensions to be loaded are bound to a repo, yes, that should be
fine. A well-designed extension should check the repo requirements. What
doesn't work in command server is to load extensions per-command basis.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3309: scmutil: rename resolvepartialhexnodeid() to resolvehexnodeidprefix()

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8247.
martinvonz edited the summary of this revision.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3309?vs=8115=8247

REVISION DETAIL
  https://phab.mercurial-scm.org/D3309

AFFECTED FILES
  hgext/eol.py
  hgext/histedit.py
  mercurial/context.py
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -434,8 +434,8 @@
 hexfunc = short
 return '%d:%s' % (rev, hexfunc(node))
 
-def resolvepartialhexnodeid(repo, prefix):
-# Uses unfiltered repo because it's faster when then prefix is ambiguous/
+def resolvehexnodeidprefix(repo, prefix):
+# Uses unfiltered repo because it's faster when prefix is ambiguous/
 # This matches the "shortest" template function.
 node = repo.unfiltered().changelog._partialmatch(prefix)
 if node is None:
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -392,7 +392,7 @@
 #  * If you know that "x" is a branch or in some other namespace,
 #use the appropriate mechanism for that namespace
 #  * If you know that "x" is a hex nodeid prefix, use
-#repo[scmutil.resolvepartialhexnodeid(repo, x)]
+#repo[scmutil.resolvehexnodeidprefix(repo, x)]
 #  * If "x" is a string that can be any of the above, but you don't want
 #to allow general revsets (perhaps because "x" may come from a remote
 #user and the revset may be too costly), use scmutil.revsymbol(repo, x)
@@ -476,7 +476,7 @@
 except KeyError:
 pass
 
-self._node = scmutil.resolvepartialhexnodeid(repo, changeid)
+self._node = scmutil.resolvehexnodeidprefix(repo, changeid)
 if self._node is not None:
 self._rev = repo.changelog.rev(self._node)
 changectxdeprecwarn(repo)
diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -443,7 +443,7 @@
 """ Verifies semantic correctness of the rule"""
 repo = self.repo
 ha = node.hex(self.node)
-self.node = scmutil.resolvepartialhexnodeid(repo, ha)
+self.node = scmutil.resolvehexnodeidprefix(repo, ha)
 if self.node is None:
 raise error.ParseError(_('unknown changeset %s listed') % ha[:12])
 self._verifynodeconstraints(prev, expected, seen)
diff --git a/hgext/eol.py b/hgext/eol.py
--- a/hgext/eol.py
+++ b/hgext/eol.py
@@ -300,7 +300,7 @@
 hook = checkheadshook
 
 def preupdate(ui, repo, hooktype, parent1, parent2):
-p1node = scmutil.resolvepartialhexnodeid(repo, parent1)
+p1node = scmutil.resolvehexnodeidprefix(repo, parent1)
 repo.loadeol([p1node])
 return False
 



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3311: revset: use resolvehexnodeidprefix() in id() predicate (BC)

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8248.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3311?vs=8117=8248

REVISION DETAIL
  https://phab.mercurial-scm.org/D3311

AFFECTED FILES
  mercurial/revset.py
  tests/test-revset.t

CHANGE DETAILS

diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -1878,7 +1878,8 @@
   [255]
 BROKEN should be '2' (node lookup uses unfiltered repo since dc25ed84bee8)
   $ hg debugrevspec '0:wdir() & id(fffb)'
-  2
+  abort: 00changelog.i@fffb: ambiguous identifier!
+  [255]
   $ hg debugrevspec '0:wdir() & 8'
   4
   $ hg debugrevspec '0:wdir() & f'
diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -1333,7 +1333,7 @@
 else:
 rn = None
 try:
-pm = repo.changelog._partialmatch(n)
+pm = scmutil.resolvehexnodeidprefix(repo, n)
 if pm is not None:
 rn = repo.changelog.rev(pm)
 except error.WdirUnsupported:



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3313: scmutil: make shortesthexnodeidprefix() use unfiltered repo

2018-04-14 Thread martinvonz (Martin von Zweigbergk)
martinvonz updated this revision to Diff 8250.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3313?vs=8119=8250

REVISION DETAIL
  https://phab.mercurial-scm.org/D3313

AFFECTED FILES
  hgext/show.py
  mercurial/scmutil.py
  mercurial/templatefuncs.py

CHANGE DETAILS

diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -587,11 +587,8 @@
 # i18n: "shortest" is a keyword
 _("shortest() expects an integer minlength"))
 
-# _partialmatch() of filtered changelog could take O(len(repo)) time,
-# which would be unacceptably slow. so we look for hash collision in
-# unfiltered space, which means some hashes may be slightly longer.
 repo = context.resource(mapping, 'ctx')._repo
-return scmutil.shortesthexnodeidprefix(repo.unfiltered(), node, minlength)
+return scmutil.shortesthexnodeidprefix(repo, node, minlength)
 
 @templatefunc('strip(text[, chars])')
 def strip(context, mapping, args):
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -436,16 +436,19 @@
 
 def resolvehexnodeidprefix(repo, prefix):
 # Uses unfiltered repo because it's faster when prefix is ambiguous/
-# This matches the "shortest" template function.
+# This matches the shortesthexnodeidprefix() function below.
 node = repo.unfiltered().changelog._partialmatch(prefix)
 if node is None:
 return
 repo.changelog.rev(node)  # make sure node isn't filtered
 return node
 
 def shortesthexnodeidprefix(repo, hexnode, minlength=1):
 """Find the shortest unambiguous prefix that matches hexnode."""
-return repo.changelog.shortest(hexnode)
+# _partialmatch() of filtered changelog could take O(len(repo)) time,
+# which would be unacceptably slow. so we look for hash collision in
+# unfiltered space, which means some hashes may be slightly longer.
+return repo.unfiltered().changelog.shortest(hexnode)
 
 def isrevsymbol(repo, symbol):
 """Checks if a symbol exists in the repo.
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -447,10 +447,8 @@
 """
 if not revs:
 return minlen
-# don't use filtered repo because it's slow. see templater.shortest().
 cl = repo.changelog
-return max(len(scmutil.shortesthexnodeidprefix(repo.unfiltered(),
-   hex(cl.node(r)),
+return max(len(scmutil.shortesthexnodeidprefix(repo, hex(cl.node(r)),
minlen)) for r in revs)
 
 # Adjust the docstring of the show command so it shows all registered views.



To: martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel