D2057: translate base85.c into rust code

2018-02-07 Thread Ivzhh (Sheng Mao)
Ivzhh added a comment.


  Thank you @indygreg!
  
  The OxidationPlan is my best reference when I started to make a move, and 
this thread is even more helpful. I am really interested in exploring this ;-) 
In 2014 I was trying to change the hg backend storage to Postgres, a silly and 
failed experiment.
  
  Anyway, I will save everyone's time and stop talking. I will come back later 
with a more meaningful implementation.

REPOSITORY
  rHG Mercurial

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

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


D2057: translate base85.c into rust code

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg added a comment.


  To be honest, we're not yet sure what we'll decide for the Python -> Rust 
bridge. The problem is summarized in the `Rust <=> Python Interop` section on 
https://www.mercurial-scm.org/wiki/OxidationPlan.
  
  I suspect at some level we'll need a CPython extension for CPython for 
performance reasons (especially for high volume function calls). PyPy obviously 
uses CFFI. I think the ideal outcome is we can write Rust that exposes a C API 
and use CFFI natively on PyPy and something like `cbindgen` + `Milksnake` to 
auto-generate a CPython extension that acts as a wrapper around the C API 
exposed by Rust. I'm not sure if anyone has invented this exact wheel yet. If 
not, it's probably faster to use `rust-cpython`. Maybe several months from now 
we have enough Rust and maintaining `rust-cpython` is painful enough that we 
pursue the auto-generated CPython extension route.
  
  What I'm trying to say is you have a green field to explore! But at this 
juncture, perfect is the enemy of done. We'll be happy with any forward 
progress, even failed experiments.

REPOSITORY
  rHG Mercurial

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

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


D2057: translate base85.c into rust code

2018-02-07 Thread Ivzhh (Sheng Mao)
Ivzhh added a comment.


  As the author of this patch, actually I have the same concern. I started to 
translate base85 as baby steps to find a way of integrating rust and cpython, 
on my side, Today I modify setup.py, policy.py and makefile to run hg's test 
suit with the new base85. For myself, it is only proof of concept.
  
  Maybe I should take another way: translate more python modules into 
CFFI-style, and let CFFI call rust implementation. And gradually change more 
implementations of python modules with corresponding cffi-style, while keep the 
python interface the same. My own hope is the rust routines will be able to 
call each other and eventually run some __basic__ tasks without calling python 
part. And the rust still lazily provides info to python interface for 
extensions etc.
  
  I am exploring this way now, and hope the findings will be useful for 
community to make decision.
  
  Thank you all for the comments!

REPOSITORY
  rHG Mercurial

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

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


D2094: wireprotoserver: define and use parse_qs from urllib

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

REVISION SUMMARY
  The cgi module is deprecated since Python 2.6. Let's replace uses
  of it in wireprotoserver with a similar function from urllib.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/urllibcompat.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -7,7 +7,6 @@
 from __future__ import absolute_import
 
 import abc
-import cgi
 import contextlib
 import struct
 import sys
@@ -134,12 +133,12 @@
 args = util.rapply(pycompat.bytesurl, self._req.form.copy())
 postlen = int(self._req.env.get(r'HTTP_X_HGARGS_POST', 0))
 if postlen:
-args.update(cgi.parse_qs(
+args.update(urlreq.parseqs(
 self._req.read(postlen), keep_blank_values=True))
 return args
 
 argvalue = decodevaluefromheaders(self._req, r'X-HgArg')
-args.update(cgi.parse_qs(argvalue, keep_blank_values=True))
+args.update(urlreq.parseqs(argvalue, keep_blank_values=True))
 return args
 
 def forwardpayload(self, fp):
diff --git a/mercurial/urllibcompat.py b/mercurial/urllibcompat.py
--- a/mercurial/urllibcompat.py
+++ b/mercurial/urllibcompat.py
@@ -47,6 +47,7 @@
 "urlparse",
 "urlunparse",
 ))
+urlreq._registeralias(urllib.parse, "parse_qs", "parseqs")
 urlreq._registeralias(urllib.parse, "unquote_to_bytes", "unquote")
 import urllib.request
 urlreq._registeraliases(urllib.request, (
@@ -157,6 +158,7 @@
 "urlparse",
 "urlunparse",
 ))
+urlreq._registeralias(urlparse, "parse_qs", "parseqs")
 urlerr._registeraliases(urllib2, (
 "HTTPError",
 "URLError",



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


D2085: wireprotoserver: rename getfile() to forwardpayload() (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5348.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2085?vs=5337=5348

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

AFFECTED FILES
  hgext/largefiles/proto.py
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -64,14 +64,10 @@
 returns a list of values (same order as )"""
 
 @abc.abstractmethod
-def getfile(self, fp):
-"""write the whole content of a file into a file like object
+def forwardpayload(self, fp):
+"""Read the raw payload and forward to a file.
 
-The file is in the form::
-
-(\n)+0\n
-
-chunk size is the ascii version of the int.
+The payload is read in full before the function returns.
 """
 
 @abc.abstractmethod
@@ -145,7 +141,7 @@
 args.update(cgi.parse_qs(argvalue, keep_blank_values=True))
 return args
 
-def getfile(self, fp):
+def forwardpayload(self, fp):
 length = int(self._req.env[r'CONTENT_LENGTH'])
 # If httppostargs is used, we need to read Content-Length
 # minus the amount that was consumed by args.
@@ -392,7 +388,12 @@
 data[arg] = val
 return [data[k] for k in keys]
 
-def getfile(self, fpout):
+def forwardpayload(self, fpout):
+# The file is in the form:
+#
+# \n
+# ...
+# 0\n
 _sshv1respondbytes(self._fout, b'')
 count = int(self._fin.readline())
 while count:
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -1008,7 +1008,7 @@
 fp = os.fdopen(fd, pycompat.sysstr('wb+'))
 r = 0
 try:
-proto.getfile(fp)
+proto.forwardpayload(fp)
 fp.seek(0)
 gen = exchange.readbundle(repo.ui, fp, None)
 if (isinstance(gen, changegroupmod.cg1unpacker)
diff --git a/hgext/largefiles/proto.py b/hgext/largefiles/proto.py
--- a/hgext/largefiles/proto.py
+++ b/hgext/largefiles/proto.py
@@ -40,7 +40,7 @@
 tmpfp = util.atomictempfile(path, createmode=repo.store.createmode)
 
 try:
-proto.getfile(tmpfp)
+proto.forwardpayload(tmpfp)
 tmpfp._fp.seek(0)
 if sha != lfutil.hexsha1(tmpfp._fp):
 raise IOError(0, _('largefile contents do not match hash'))



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


D2087: wireprotoserver: move responsetype() out of http handler

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5350.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2087?vs=5339=5350

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

AFFECTED FILES
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -170,48 +170,6 @@
 urlreq.quote(self._req.env.get('REMOTE_HOST', '')),
 urlreq.quote(self._req.env.get('REMOTE_USER', '')))
 
-def responsetype(self, prefer_uncompressed):
-"""Determine the appropriate response type and compression settings.
-
-Returns a tuple of (mediatype, compengine, engineopts).
-"""
-# Determine the response media type and compression engine based
-# on the request parameters.
-protocaps = decodevaluefromheaders(self._req, r'X-HgProto').split(' ')
-
-if '0.2' in protocaps:
-# All clients are expected to support uncompressed data.
-if prefer_uncompressed:
-return HGTYPE2, util._noopengine(), {}
-
-# Default as defined by wire protocol spec.
-compformats = ['zlib', 'none']
-for cap in protocaps:
-if cap.startswith('comp='):
-compformats = cap[5:].split(',')
-break
-
-# Now find an agreed upon compression format.
-for engine in wireproto.supportedcompengines(self._ui,
- util.SERVERROLE):
-if engine.wireprotosupport().name in compformats:
-opts = {}
-level = self._ui.configint('server',
-  '%slevel' % engine.name())
-if level is not None:
-opts['level'] = level
-
-return HGTYPE2, engine, opts
-
-# No mutually supported compression format. Fall back to the
-# legacy protocol.
-
-# Don't allow untrusted settings because disabling compression or
-# setting a very high compression level could lead to flooding
-# the server's network or CPU.
-opts = {'level': self._ui.configint('server', 'zliblevel')}
-return HGTYPE, util.compengines['zlib'], opts
-
 def iscmd(cmd):
 return cmd in wireproto.commands
 
@@ -252,6 +210,46 @@
 'handleerror': lambda ex: _handlehttperror(ex, req, cmd),
 }
 
+def _httpresponsetype(ui, req, prefer_uncompressed):
+"""Determine the appropriate response type and compression settings.
+
+Returns a tuple of (mediatype, compengine, engineopts).
+"""
+# Determine the response media type and compression engine based
+# on the request parameters.
+protocaps = decodevaluefromheaders(req, r'X-HgProto').split(' ')
+
+if '0.2' in protocaps:
+# All clients are expected to support uncompressed data.
+if prefer_uncompressed:
+return HGTYPE2, util._noopengine(), {}
+
+# Default as defined by wire protocol spec.
+compformats = ['zlib', 'none']
+for cap in protocaps:
+if cap.startswith('comp='):
+compformats = cap[5:].split(',')
+break
+
+# Now find an agreed upon compression format.
+for engine in wireproto.supportedcompengines(ui, util.SERVERROLE):
+if engine.wireprotosupport().name in compformats:
+opts = {}
+level = ui.configint('server', '%slevel' % engine.name())
+if level is not None:
+opts['level'] = level
+
+return HGTYPE2, engine, opts
+
+# No mutually supported compression format. Fall back to the
+# legacy protocol.
+
+# Don't allow untrusted settings because disabling compression or
+# setting a very high compression level could lead to flooding
+# the server's network or CPU.
+opts = {'level': ui.configint('server', 'zliblevel')}
+return HGTYPE, util.compengines['zlib'], opts
+
 def _callhttp(repo, req, proto, cmd):
 def genversion2(gen, engine, engineopts):
 # application/mercurial-0.2 always sends a payload header
@@ -284,8 +282,8 @@
 
 # This code for compression should not be streamres specific. It
 # is here because we only compress streamres at the moment.
-mediatype, engine, engineopts = proto.responsetype(
-rsp.prefer_uncompressed)
+mediatype, engine, engineopts = _httpresponsetype(
+repo.ui, req, rsp.prefer_uncompressed)
 gen = engine.compressstream(gen, engineopts)
 
 if mediatype == HGTYPE2:



To: indygreg, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org

D2092: wireprotoserver: add version to SSH protocol names (API)

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

REVISION SUMMARY
  We recently introduced version 2 of the SSH protocol. Like we
  did for the peer, we will need to differentiate version 1 and 2
  of the server. So, we add version components to the advertised
  name of the protocol handler.
  
  Nothing in core looks for the old value. But an extension may.
  
  .. api::
  
SSH protocol handler now advertises its name internally as
"ssh-v1" instead of "ssh."

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -367,7 +367,7 @@
 
 @property
 def name(self):
-return 'ssh'
+return SSHV1
 
 def getargs(self, args):
 data = {}



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


D2093: tests: add tests for sending recognized command before handshake

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

REVISION SUMMARY
  Rounding out our test coverage for the SSH server.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  tests/test-ssh-proto.t

CHANGE DETAILS

diff --git a/tests/test-ssh-proto.t b/tests/test-ssh-proto.t
--- a/tests/test-ssh-proto.t
+++ b/tests/test-ssh-proto.t
@@ -389,6 +389,33 @@
   0
   0
 
+Send a valid command before the handshake
+
+  $ hg -R server serve --stdio << EOF
+  > heads
+  > hello
+  > between
+  > pairs 81
+  > 
-
+  > EOF
+  41
+  68986213bd4485ea51533535e3fc9e78007a711f
+  384
+  capabilities: lookup changegroupsubset branchmap pushkey known getbundle 
unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ 
unbundle=HG10GZ,HG10BZ,HG10UN
+  1
+  
+
+And a variation that doesn't send the between command
+
+  $ hg -R server serve --stdio << EOF
+  > heads
+  > hello
+  > EOF
+  41
+  68986213bd4485ea51533535e3fc9e78007a711f
+  384
+  capabilities: lookup changegroupsubset branchmap pushkey known getbundle 
unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ 
unbundle=HG10GZ,HG10BZ,HG10UN
+
 Send an upgrade request to a server that doesn't support that command
 
   $ hg -R server serve --stdio << EOF



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


D2088: wireprototypes: move wire protocol response types to new module

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5351.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2088?vs=5340=5351

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py
  mercurial/wireprototypes.py

CHANGE DETAILS

diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py
new file mode 100644
--- /dev/null
+++ b/mercurial/wireprototypes.py
@@ -0,0 +1,61 @@
+# 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
+
+class ooberror(object):
+"""wireproto reply: failure of a batch of operation
+
+Something failed during a batch call. The error message is stored in
+`self.message`.
+"""
+def __init__(self, message):
+self.message = message
+
+class pushres(object):
+"""wireproto reply: success with simple integer return
+
+The call was successful and returned an integer contained in `self.res`.
+"""
+def __init__(self, res, output):
+self.res = res
+self.output = output
+
+class pusherr(object):
+"""wireproto reply: failure
+
+The call failed. The `self.res` attribute contains the error message.
+"""
+def __init__(self, res, output):
+self.res = res
+self.output = output
+
+class streamres(object):
+"""wireproto reply: binary stream
+
+The call was successful and the result is a stream.
+
+Accepts a generator containing chunks of data to be sent to the client.
+
+``prefer_uncompressed`` indicates that the data is expected to be
+uncompressable and that the stream should therefore use the ``none``
+engine.
+"""
+def __init__(self, gen=None, prefer_uncompressed=False):
+self.gen = gen
+self.prefer_uncompressed = prefer_uncompressed
+
+class streamreslegacy(object):
+"""wireproto reply: uncompressed binary stream
+
+The call was successful and the result is a stream.
+
+Accepts a generator containing chunks of data to be sent to the client.
+
+Like ``streamres``, but sends an uncompressed data for "version 1" clients
+using the application/mercurial-0.1 media type.
+"""
+def __init__(self, gen=None):
+self.gen = gen
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -20,6 +20,7 @@
 pycompat,
 util,
 wireproto,
+wireprototypes,
 )
 
 stringio = util.stringio
@@ -273,11 +274,11 @@
 if isinstance(rsp, bytes):
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
-elif isinstance(rsp, wireproto.streamres_legacy):
+elif isinstance(rsp, wireprototypes.streamreslegacy):
 gen = rsp.gen
 req.respond(HTTP_OK, HGTYPE)
 return gen
-elif isinstance(rsp, wireproto.streamres):
+elif isinstance(rsp, wireprototypes.streamres):
 gen = rsp.gen
 
 # This code for compression should not be streamres specific. It
@@ -291,18 +292,18 @@
 
 req.respond(HTTP_OK, mediatype)
 return gen
-elif isinstance(rsp, wireproto.pushres):
+elif isinstance(rsp, wireprototypes.pushres):
 rsp = '%d\n%s' % (rsp.res, rsp.output)
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
-elif isinstance(rsp, wireproto.pusherr):
+elif isinstance(rsp, wireprototypes.pusherr):
 # This is the httplib workaround documented in _handlehttperror().
 req.drain()
 
 rsp = '0\n%s\n' % rsp.res
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
-elif isinstance(rsp, wireproto.ooberror):
+elif isinstance(rsp, wireprototypes.ooberror):
 rsp = rsp.message
 req.respond(HTTP_OK, HGERRTYPE, body=rsp)
 return []
@@ -434,16 +435,16 @@
 
 if isinstance(rsp, bytes):
 _sshv1respondbytes(self._fout, rsp)
-elif isinstance(rsp, wireproto.streamres):
+elif isinstance(rsp, wireprototypes.streamres):
 _sshv1respondstream(self._fout, rsp)
-elif isinstance(rsp, wireproto.streamres_legacy):
+elif isinstance(rsp, wireprototypes.streamreslegacy):
 _sshv1respondstream(self._fout, rsp)
-elif isinstance(rsp, wireproto.pushres):
+elif isinstance(rsp, wireprototypes.pushres):
 _sshv1respondbytes(self._fout, b'')
 _sshv1respondbytes(self._fout, bytes(rsp.res))
-elif isinstance(rsp, wireproto.pusherr):
+elif isinstance(rsp, wireprototypes.pusherr):
 _sshv1respondbytes(self._fout, rsp.res)
-elif isinstance(rsp, wireproto.ooberror):
+elif isinstance(rsp, wireprototypes.ooberror):
 

D2083: wireprotoserver: remove redirect() and restore() (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5346.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2083?vs=5335=5346

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

AFFECTED FILES
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -88,23 +88,6 @@
 won't be captured.
 """
 
-@abc.abstractmethod
-def redirect(self):
-"""may setup interception for stdout and stderr
-
-See also the `restore` method."""
-
-# If the `redirect` function does install interception, the `restore`
-# function MUST be defined. If interception is not used, this function
-# MUST NOT be defined.
-#
-# left commented here on purpose
-#
-#def restore(self):
-#"""reinstall previous stdout and stderr and return intercepted stdout
-#"""
-#raise NotImplementedError()
-
 def decodevaluefromheaders(req, headerprefix):
 """Decode a long value from multiple HTTP request headers.
 
@@ -181,15 +164,6 @@
 self._ui.fout = oldout
 self._ui.ferr = olderr
 
-def redirect(self):
-self._oldio = self._ui.fout, self._ui.ferr
-self._ui.ferr = self._ui.fout = stringio()
-
-def restore(self):
-val = self._ui.fout.getvalue()
-self._ui.ferr, self._ui.fout = self._oldio
-return val
-
 def _client(self):
 return 'remote:%s:%s:%s' % (
 self._req.env.get('wsgi.url_scheme') or 'http',
@@ -425,9 +399,6 @@
 def mayberedirectstdio(self):
 yield None
 
-def redirect(self):
-pass
-
 def _client(self):
 client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
 return 'remote:ssh:' + client



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


D2086: wireproto: remove unused proto argument from supportedcompengines (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5349.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2086?vs=5338=5349

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -192,7 +192,7 @@
 break
 
 # Now find an agreed upon compression format.
-for engine in wireproto.supportedcompengines(self._ui, self,
+for engine in wireproto.supportedcompengines(self._ui,
  util.SERVERROLE):
 if engine.wireprotosupport().name in compformats:
 opts = {}
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -587,7 +587,7 @@
 
 return ui.configbool('server', 'bundle1')
 
-def supportedcompengines(ui, proto, role):
+def supportedcompengines(ui, role):
 """Obtain the list of supported compression engines for a request."""
 assert role in (util.CLIENTROLE, util.SERVERROLE)
 
@@ -824,7 +824,7 @@
 # FUTURE advertise minrx and mintx after consulting config option
 caps.append('httpmediatype=0.1rx,0.1tx,0.2tx')
 
-compengines = supportedcompengines(repo.ui, proto, util.SERVERROLE)
+compengines = supportedcompengines(repo.ui, util.SERVERROLE)
 if compengines:
 comptypes = ','.join(urlreq.quote(e.wireprotosupport().name)
  for e in compengines)



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


D2089: wireproto: introduce type for raw byte responses (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5352.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2089?vs=5341=5352

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

AFFECTED FILES
  hgext/largefiles/proto.py
  mercurial/wireproto.py
  mercurial/wireprotoserver.py
  mercurial/wireprototypes.py
  tests/sshprotoext.py
  tests/test-wireproto.py

CHANGE DETAILS

diff --git a/tests/test-wireproto.py b/tests/test-wireproto.py
--- a/tests/test-wireproto.py
+++ b/tests/test-wireproto.py
@@ -1,8 +1,10 @@
 from __future__ import absolute_import, print_function
 
 from mercurial import (
+error,
 util,
 wireproto,
+wireprototypes,
 )
 stringio = util.stringio
 
@@ -42,7 +44,13 @@
 return ['batch']
 
 def _call(self, cmd, **args):
-return wireproto.dispatch(self.serverrepo, proto(args), cmd)
+res = wireproto.dispatch(self.serverrepo, proto(args), cmd)
+if isinstance(res, wireprototypes.bytesresponse):
+return res.data
+elif isinstance(res, bytes):
+return res
+else:
+raise error.Abort('dummy client does not support response type')
 
 def _callstream(self, cmd, **args):
 return stringio(self._call(cmd, **args))
diff --git a/tests/sshprotoext.py b/tests/sshprotoext.py
--- a/tests/sshprotoext.py
+++ b/tests/sshprotoext.py
@@ -49,7 +49,7 @@
 l = self._fin.readline()
 assert l == b'between\n'
 rsp = wireproto.dispatch(self._repo, self._proto, b'between')
-wireprotoserver._sshv1respondbytes(self._fout, rsp)
+wireprotoserver._sshv1respondbytes(self._fout, rsp.data)
 
 super(prehelloserver, self).serve_forever()
 
@@ -74,7 +74,7 @@
 # Send the upgrade response.
 self._fout.write(b'upgraded %s %s\n' % (token, name))
 servercaps = wireproto.capabilities(self._repo, self._proto)
-rsp = b'capabilities: %s' % servercaps
+rsp = b'capabilities: %s' % servercaps.data
 self._fout.write(b'%d\n' % len(rsp))
 self._fout.write(rsp)
 self._fout.write(b'\n')
diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py
--- a/mercurial/wireprototypes.py
+++ b/mercurial/wireprototypes.py
@@ -5,6 +5,11 @@
 
 from __future__ import absolute_import
 
+class bytesresponse(object):
+"""A wire protocol response consisting of raw bytes."""
+def __init__(self, data):
+self.data = data
+
 class ooberror(object):
 """wireproto reply: failure of a batch of operation
 
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -274,6 +274,9 @@
 if isinstance(rsp, bytes):
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
+elif isinstance(rsp, wireprototypes.bytesresponse):
+req.respond(HTTP_OK, HGTYPE, body=rsp.data)
+return []
 elif isinstance(rsp, wireprototypes.streamreslegacy):
 gen = rsp.gen
 req.respond(HTTP_OK, HGTYPE)
@@ -435,6 +438,8 @@
 
 if isinstance(rsp, bytes):
 _sshv1respondbytes(self._fout, rsp)
+elif isinstance(rsp, wireprototypes.bytesresponse):
+_sshv1respondbytes(self._fout, rsp.data)
 elif isinstance(rsp, wireprototypes.streamres):
 _sshv1respondstream(self._fout, rsp)
 elif isinstance(rsp, wireprototypes.streamreslegacy):
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -37,6 +37,7 @@
 urlerr = util.urlerr
 urlreq = util.urlreq
 
+bytesresponse = wireprototypes.bytesresponse
 ooberror = wireprototypes.ooberror
 pushres = wireprototypes.pushres
 pusherr = wireprototypes.pusherr
@@ -696,16 +697,24 @@
 result = func(repo, proto)
 if isinstance(result, ooberror):
 return result
+
+# For now, all batchable commands must return bytesresponse or
+# raw bytes (for backwards compatibility).
+assert isinstance(result, (bytesresponse, bytes))
+if isinstance(result, bytesresponse):
+result = result.data
 res.append(escapearg(result))
-return ';'.join(res)
+
+return bytesresponse(';'.join(res))
 
 @wireprotocommand('between', 'pairs')
 def between(repo, proto, pairs):
 pairs = [decodelist(p, '-') for p in pairs.split(" ")]
 r = []
 for b in repo.between(pairs):
 r.append(encodelist(b) + "\n")
-return "".join(r)
+
+return bytesresponse(''.join(r))
 
 @wireprotocommand('branchmap')
 def branchmap(repo, proto):
@@ -715,15 +724,17 @@
 branchname = urlreq.quote(encoding.fromlocal(branch))
 branchnodes = encodelist(nodes)
 heads.append('%s %s' % (branchname, branchnodes))
-return '\n'.join(heads)
+
+return bytesresponse('\n'.join(heads))
 
 @wireprotocommand('branches', 'nodes')
 def 

D2084: wireprotoserver: rename _client to client (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5347.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2084?vs=5336=5347

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -88,6 +88,10 @@
 won't be captured.
 """
 
+@abc.abstractmethod
+def client(self):
+"""Returns a string representation of this client (as bytes)."""
+
 def decodevaluefromheaders(req, headerprefix):
 """Decode a long value from multiple HTTP request headers.
 
@@ -164,7 +168,7 @@
 self._ui.fout = oldout
 self._ui.ferr = olderr
 
-def _client(self):
+def client(self):
 return 'remote:%s:%s:%s' % (
 self._req.env.get('wsgi.url_scheme') or 'http',
 urlreq.quote(self._req.env.get('REMOTE_HOST', '')),
@@ -399,7 +403,7 @@
 def mayberedirectstdio(self):
 yield None
 
-def _client(self):
+def client(self):
 client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
 return 'remote:ssh:' + client
 
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -1023,7 +1023,7 @@
   hint=bundle2requiredhint)
 
 r = exchange.unbundle(repo, gen, their_heads, 'serve',
-  proto._client())
+  proto.client())
 if util.safehasattr(r, 'addpart'):
 # The return looks streamable, we are in the bundle2 case
 # and should return a stream.



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


D2082: wireproto: use maybecapturestdio() for push responses (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5345.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2082?vs=5334=5345

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

AFFECTED FILES
  hgext/largefiles/proto.py
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -320,15 +320,13 @@
 req.respond(HTTP_OK, mediatype)
 return gen
 elif isinstance(rsp, wireproto.pushres):
-val = proto.restore()
-rsp = '%d\n%s' % (rsp.res, val)
+rsp = '%d\n%s' % (rsp.res, rsp.output)
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
 elif isinstance(rsp, wireproto.pusherr):
 # This is the httplib workaround documented in _handlehttperror().
 req.drain()
 
-proto.restore()
 rsp = '0\n%s\n' % rsp.res
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -510,16 +510,18 @@
 
 The call was successful and returned an integer contained in `self.res`.
 """
-def __init__(self, res):
+def __init__(self, res, output):
 self.res = res
+self.output = output
 
 class pusherr(object):
 """wireproto reply: failure
 
 The call failed. The `self.res` attribute contains the error message.
 """
-def __init__(self, res):
+def __init__(self, res, output):
 self.res = res
+self.output = output
 
 class ooberror(object):
 """wireproto reply: failure of a batch of operation
@@ -997,97 +999,98 @@
 def unbundle(repo, proto, heads):
 their_heads = decodelist(heads)
 
-try:
-proto.redirect()
-
-exchange.check_heads(repo, their_heads, 'preparing changes')
-
-# write bundle data to temporary file because it can be big
-fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
-fp = os.fdopen(fd, pycompat.sysstr('wb+'))
-r = 0
+with proto.mayberedirectstdio() as output:
 try:
-proto.getfile(fp)
-fp.seek(0)
-gen = exchange.readbundle(repo.ui, fp, None)
-if (isinstance(gen, changegroupmod.cg1unpacker)
-and not bundle1allowed(repo, 'push')):
-if proto.name == 'http':
-# need to special case http because stderr do not get to
-# the http client on failed push so we need to abuse some
-# other error type to make sure the message get to the
-# user.
-return ooberror(bundle2required)
-raise error.Abort(bundle2requiredmain,
-  hint=bundle2requiredhint)
+exchange.check_heads(repo, their_heads, 'preparing changes')
 
-r = exchange.unbundle(repo, gen, their_heads, 'serve',
-  proto._client())
-if util.safehasattr(r, 'addpart'):
-# The return looks streamable, we are in the bundle2 case and
-# should return a stream.
-return streamres_legacy(gen=r.getchunks())
-return pushres(r)
-
-finally:
-fp.close()
-os.unlink(tempname)
-
-except (error.BundleValueError, error.Abort, error.PushRaced) as exc:
-# handle non-bundle2 case first
-if not getattr(exc, 'duringunbundle2', False):
+# write bundle data to temporary file because it can be big
+fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
+fp = os.fdopen(fd, pycompat.sysstr('wb+'))
+r = 0
 try:
-raise
-except error.Abort:
-# The old code we moved used util.stderr directly.
-# We did not change it to minimise code change.
-# This need to be moved to something proper.
-# Feel free to do it.
-util.stderr.write("abort: %s\n" % exc)
-if exc.hint is not None:
-util.stderr.write("(%s)\n" % exc.hint)
-return pushres(0)
-except error.PushRaced:
-return pusherr(str(exc))
+proto.getfile(fp)
+fp.seek(0)
+gen = exchange.readbundle(repo.ui, fp, None)
+if (isinstance(gen, changegroupmod.cg1unpacker)
+and not bundle1allowed(repo, 'push')):
+if proto.name == 'http':
+# need to special case http because stderr do not get 
to
+# the http client on failed push so we need to abuse
+# some other error type to make sure the message get to
+

D2081: wireprotoserver: add context manager mechanism for redirecting stdio

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5344.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2081?vs=5333=5344

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -8,6 +8,7 @@
 
 import abc
 import cgi
+import contextlib
 import struct
 import sys
 
@@ -74,6 +75,20 @@
 """
 
 @abc.abstractmethod
+def mayberedirectstdio(self):
+"""Context manager to possibly redirect stdio.
+
+The context manager yields a file-object like object that receives
+stdout and stderr output when the context manager is active. Or it
+yields ``None`` if no I/O redirection occurs.
+
+The intent of this context manager is to capture stdio output
+so it may be sent in the response. Some transports support streaming
+stdio to the client in real time. For these transports, stdio output
+won't be captured.
+"""
+
+@abc.abstractmethod
 def redirect(self):
 """may setup interception for stdout and stderr
 
@@ -151,6 +166,21 @@
 for s in util.filechunkiter(self._req, limit=length):
 fp.write(s)
 
+@contextlib.contextmanager
+def mayberedirectstdio(self):
+oldout = self._ui.fout
+olderr = self._ui.ferr
+
+out = util.stringio()
+
+try:
+self._ui.fout = out
+self._ui.ferr = out
+yield out
+finally:
+self._ui.fout = oldout
+self._ui.ferr = olderr
+
 def redirect(self):
 self._oldio = self._ui.fout, self._ui.ferr
 self._ui.ferr = self._ui.fout = stringio()
@@ -393,6 +423,10 @@
 fpout.write(self._fin.read(count))
 count = int(self._fin.readline())
 
+@contextlib.contextmanager
+def mayberedirectstdio(self):
+yield None
+
 def redirect(self):
 pass
 
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -978,20 +978,12 @@
 else:
 new = encoding.tolocal(new) # normal path
 
-if util.safehasattr(proto, 'restore'):
-
-proto.redirect()
-
+with proto.mayberedirectstdio() as output:
 r = repo.pushkey(encoding.tolocal(namespace), encoding.tolocal(key),
  encoding.tolocal(old), new) or False
 
-output = proto.restore()
-
-return '%s\n%s' % (int(r), output)
-
-r = repo.pushkey(encoding.tolocal(namespace), encoding.tolocal(key),
- encoding.tolocal(old), new)
-return '%s\n' % int(r)
+output = output.getvalue() if output else ''
+return '%s\n%s' % (int(r), output)
 
 @wireprotocommand('stream_out')
 def stream(repo, proto):



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


D2091: wireprotoserver: extract SSH response handling functions

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5342.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2091?vs=5331=5342

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

AFFECTED FILES
  mercurial/wireprotoserver.py
  tests/sshprotoext.py

CHANGE DETAILS

diff --git a/tests/sshprotoext.py b/tests/sshprotoext.py
--- a/tests/sshprotoext.py
+++ b/tests/sshprotoext.py
@@ -45,11 +45,11 @@
 l = self._fin.readline()
 assert l == b'hello\n'
 # Respond to unknown commands with an empty reply.
-self._sendresponse(b'')
+wireprotoserver._sshv1respondbytes(self._fout, b'')
 l = self._fin.readline()
 assert l == b'between\n'
 rsp = wireproto.dispatch(self._repo, self, b'between')
-self._handlers[rsp.__class__](self, rsp)
+wireprotoserver._sshv1respondbytes(self._fout, rsp)
 
 super(prehelloserver, self).serve_forever()
 
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -336,6 +336,24 @@
 
 return ''
 
+def _sshv1respondbytes(fout, value):
+"""Send a bytes response for protocol version 1."""
+fout.write('%d\n' % len(value))
+fout.write(value)
+fout.flush()
+
+def _sshv1respondstream(fout, source):
+write = fout.write
+for chunk in source.gen:
+write(chunk)
+fout.flush()
+
+def _sshv1respondooberror(fout, ferr, rsp):
+ferr.write(b'%s\n-\n' % rsp)
+ferr.flush()
+fout.write(b'\n')
+fout.flush()
+
 class sshserver(baseprotocolhandler):
 def __init__(self, ui, repo):
 self._ui = ui
@@ -376,60 +394,43 @@
 return [data[k] for k in keys]
 
 def getfile(self, fpout):
-self._sendresponse('')
+_sshv1respondbytes(self._fout, b'')
 count = int(self._fin.readline())
 while count:
 fpout.write(self._fin.read(count))
 count = int(self._fin.readline())
 
 def redirect(self):
 pass
 
-def _sendresponse(self, v):
-self._fout.write("%d\n" % len(v))
-self._fout.write(v)
-self._fout.flush()
-
-def _sendstream(self, source):
-write = self._fout.write
-for chunk in source.gen:
-write(chunk)
-self._fout.flush()
-
-def _sendpushresponse(self, rsp):
-self._sendresponse('')
-self._sendresponse(str(rsp.res))
-
-def _sendpusherror(self, rsp):
-self._sendresponse(rsp.res)
-
-def _sendooberror(self, rsp):
-self._ui.ferr.write('%s\n-\n' % rsp.message)
-self._ui.ferr.flush()
-self._fout.write('\n')
-self._fout.flush()
-
 def serve_forever(self):
 while self.serve_one():
 pass
 sys.exit(0)
 
-_handlers = {
-str: _sendresponse,
-wireproto.streamres: _sendstream,
-wireproto.streamres_legacy: _sendstream,
-wireproto.pushres: _sendpushresponse,
-wireproto.pusherr: _sendpusherror,
-wireproto.ooberror: _sendooberror,
-}
-
 def serve_one(self):
 cmd = self._fin.readline()[:-1]
 if cmd and wireproto.commands.commandavailable(cmd, self):
 rsp = wireproto.dispatch(self._repo, self, cmd)
-self._handlers[rsp.__class__](self, rsp)
+
+if isinstance(rsp, bytes):
+_sshv1respondbytes(self._fout, rsp)
+elif isinstance(rsp, wireproto.streamres):
+_sshv1respondstream(self._fout, rsp)
+elif isinstance(rsp, wireproto.streamres_legacy):
+_sshv1respondstream(self._fout, rsp)
+elif isinstance(rsp, wireproto.pushres):
+_sshv1respondbytes(self._fout, b'')
+_sshv1respondbytes(self._fout, bytes(rsp.res))
+elif isinstance(rsp, wireproto.pusherr):
+_sshv1respondbytes(self._fout, rsp.res)
+elif isinstance(rsp, wireproto.ooberror):
+_sshv1respondooberror(self._fout, self._ui.ferr, rsp.message)
+else:
+raise error.ProgrammingError('unhandled response type from '
+ 'wire protocol command: %s' % rsp)
 elif cmd:
-self._sendresponse("")
+_sshv1respondbytes(self._fout, b'')
 return cmd != ''
 
 def _client(self):



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


[PATCH] tests: stabilize ssh tests on Windows

2018-02-07 Thread Matt Harbison
# HG changeset patch
# User Matt Harbison 
# Date 1518064968 18000
#  Wed Feb 07 23:42:48 2018 -0500
# Node ID 620577fa68a7c6cd6b473c72af9108303bc23167
# Parent  258a474c5f1ba7e9d61f15c5d8f548f5e01e4f95
tests: stabilize ssh tests on Windows

This seems like a somewhat common type of failure (double vs single quote), so
I'm interested in ideas about how to avoid this.  I doubt that we should
automatically fall back from single quote to double quote, like with '/' vs '\'.

diff --git a/tests/test-debugcommands.t b/tests/test-debugcommands.t
--- a/tests/test-debugcommands.t
+++ b/tests/test-debugcommands.t
@@ -390,7 +390,8 @@
   pushable: yes
 
   $ hg --config ui.ssh="\"$PYTHON\" \"$TESTDIR/dummyssh\"" --debug debugpeer 
ssh://user@dummy/debugrevlog
-  running "*" "*/tests/dummyssh" 'user@dummy' 'hg -R debugrevlog serve 
--stdio' (glob)
+  running "*" "*/tests/dummyssh" 'user@dummy' 'hg -R debugrevlog serve 
--stdio' (glob) (no-windows !)
+  running "*" "*\tests/dummyssh" "user@dummy" "hg -R debugrevlog serve 
--stdio" (glob) (windows !)
   devel-peer-request: hello
   sending hello command
   devel-peer-request: between
diff --git a/tests/test-ssh-proto.t b/tests/test-ssh-proto.t
--- a/tests/test-ssh-proto.t
+++ b/tests/test-ssh-proto.t
@@ -17,7 +17,8 @@
 Test a normal behaving server, for sanity
 
   $ hg --debug debugpeer ssh://user@dummy/server
-  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob)
+  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' 
(glob) (no-windows !)
+  running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" 
(glob) (windows !)
   devel-peer-request: hello
   sending hello command
   devel-peer-request: between
@@ -63,7 +64,8 @@
 --debug will print the banner
 
   $ SSHSERVERMODE=banner hg --debug debugpeer ssh://user@dummy/server
-  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob)
+  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' 
(glob) (no-windows !)
+  running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" 
(glob) (windows !)
   devel-peer-request: hello
   sending hello command
   devel-peer-request: between
@@ -114,7 +116,8 @@
 servers.
 
   $ SSHSERVERMODE=no-hello hg --debug debugpeer ssh://user@dummy/server
-  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob)
+  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' 
(glob) (no-windows !)
+  running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" 
(glob) (windows !)
   devel-peer-request: hello
   sending hello command
   devel-peer-request: between
@@ -141,7 +144,8 @@
   
 
   $ hg --config sshpeer.mode=extra-handshake-commands --config 
sshpeer.handshake-mode=pre-no-args --debug debugpeer ssh://user@dummy/server
-  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob)
+  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' 
(glob) (no-windows !)
+  running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" 
(glob) (windows !)
   sending no-args command
   devel-peer-request: hello
   sending hello command
@@ -176,7 +180,8 @@
   
 
   $ hg --config sshpeer.mode=extra-handshake-commands --config 
sshpeer.handshake-mode=pre-multiple-no-args --debug debugpeer 
ssh://user@dummy/server
-  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob)
+  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' 
(glob) (no-windows !)
+  running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" 
(glob) (windows !)
   sending unknown1 command
   sending unknown2 command
   sending unknown3 command
@@ -405,7 +410,8 @@
   
 
   $ hg --config experimental.sshpeer.advertise-v2=true --debug debugpeer 
ssh://user@dummy/server
-  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob)
+  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' 
(glob) (no-windows !)
+  running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" 
(glob) (windows !)
   sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
   devel-peer-request: hello
   sending hello command
@@ -434,7 +440,8 @@
   capabilities: lookup changegroupsubset branchmap pushkey known getbundle 
unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ 
unbundle=HG10GZ,HG10BZ,HG10UN
 
   $ SSHSERVERMODE=upgradev2 hg --config experimental.sshpeer.advertise-v2=true 
--debug debugpeer ssh://user@dummy/server
-  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob)
+  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' 
(glob) (no-windows !)
+  running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" 
(glob) (windows !)
   sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
   devel-peer-request: hello
   sending hello command
@@ -449,7 +456,8 @@

D2089: wireproto: introduce type for raw byte responses (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5341.
indygreg edited the summary of this revision.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2089?vs=5325=5341

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

AFFECTED FILES
  hgext/largefiles/proto.py
  mercurial/wireproto.py
  mercurial/wireprotoserver.py
  mercurial/wireprototypes.py
  tests/sshprotoext.py
  tests/test-wireproto.py

CHANGE DETAILS

diff --git a/tests/test-wireproto.py b/tests/test-wireproto.py
--- a/tests/test-wireproto.py
+++ b/tests/test-wireproto.py
@@ -1,8 +1,10 @@
 from __future__ import absolute_import, print_function
 
 from mercurial import (
+error,
 util,
 wireproto,
+wireprototypes,
 )
 stringio = util.stringio
 
@@ -42,7 +44,13 @@
 return ['batch']
 
 def _call(self, cmd, **args):
-return wireproto.dispatch(self.serverrepo, proto(args), cmd)
+res = wireproto.dispatch(self.serverrepo, proto(args), cmd)
+if isinstance(res, wireprototypes.bytesresponse):
+return res.data
+elif isinstance(res, bytes):
+return res
+else:
+raise error.Abort('dummy client does not support response type')
 
 def _callstream(self, cmd, **args):
 return stringio(self._call(cmd, **args))
diff --git a/tests/sshprotoext.py b/tests/sshprotoext.py
--- a/tests/sshprotoext.py
+++ b/tests/sshprotoext.py
@@ -49,7 +49,7 @@
 l = self._fin.readline()
 assert l == b'between\n'
 rsp = wireproto.dispatch(self._repo, self._proto, b'between')
-wireprotoserver._sshv1respondbytes(self._fout, rsp)
+wireprotoserver._sshv1respondbytes(self._fout, rsp.data)
 
 super(prehelloserver, self).serve_forever()
 
@@ -74,7 +74,7 @@
 # Send the upgrade response.
 self._fout.write(b'upgraded %s %s\n' % (token, name))
 servercaps = wireproto.capabilities(self._repo, self._proto)
-rsp = b'capabilities: %s' % servercaps
+rsp = b'capabilities: %s' % servercaps.data
 self._fout.write(b'%d\n' % len(rsp))
 self._fout.write(rsp)
 self._fout.write(b'\n')
diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py
--- a/mercurial/wireprototypes.py
+++ b/mercurial/wireprototypes.py
@@ -5,6 +5,11 @@
 
 from __future__ import absolute_import
 
+class bytesresponse(object):
+"""A wire protocol response consisting of raw bytes."""
+def __init__(self, data):
+self.data = data
+
 class ooberror(object):
 """wireproto reply: failure of a batch of operation
 
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -274,6 +274,9 @@
 if isinstance(rsp, bytes):
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
+elif isinstance(rsp, wireprototypes.bytesresponse):
+req.respond(HTTP_OK, HGTYPE, body=rsp.data)
+return []
 elif isinstance(rsp, wireprototypes.streamreslegacy):
 gen = rsp.gen
 req.respond(HTTP_OK, HGTYPE)
@@ -435,6 +438,8 @@
 
 if isinstance(rsp, bytes):
 _sshv1respondbytes(self._fout, rsp)
+elif isinstance(rsp, wireprototypes.bytesresponse):
+_sshv1respondbytes(self._fout, rsp.data)
 elif isinstance(rsp, wireprototypes.streamres):
 _sshv1respondstream(self._fout, rsp)
 elif isinstance(rsp, wireprototypes.streamreslegacy):
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -37,6 +37,7 @@
 urlerr = util.urlerr
 urlreq = util.urlreq
 
+bytesresponse = wireprototypes.bytesresponse
 ooberror = wireprototypes.ooberror
 pushres = wireprototypes.pushres
 pusherr = wireprototypes.pusherr
@@ -696,16 +697,24 @@
 result = func(repo, proto)
 if isinstance(result, ooberror):
 return result
+
+# For now, all batchable commands must return bytesresponse or
+# raw bytes (for backwards compatibility).
+assert isinstance(result, (bytesresponse, bytes))
+if isinstance(result, bytesresponse):
+result = result.data
 res.append(escapearg(result))
-return ';'.join(res)
+
+return bytesresponse(';'.join(res))
 
 @wireprotocommand('between', 'pairs')
 def between(repo, proto, pairs):
 pairs = [decodelist(p, '-') for p in pairs.split(" ")]
 r = []
 for b in repo.between(pairs):
 r.append(encodelist(b) + "\n")
-return "".join(r)
+
+return bytesresponse(''.join(r))
 
 @wireprotocommand('branchmap')
 def branchmap(repo, proto):
@@ -715,15 +724,17 @@
 branchname = urlreq.quote(encoding.fromlocal(branch))
 branchnodes = encodelist(nodes)
 heads.append('%s %s' % (branchname, branchnodes))
-return '\n'.join(heads)
+
+return bytesresponse('\n'.join(heads))
 
 

D2086: wireproto: remove unused proto argument from supportedcompengines (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5338.
indygreg retitled this revision from "wireproto: remove unused proto argument 
from supportedcompengines" to "wireproto: remove unused proto argument from 
supportedcompengines (API)".

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2086?vs=5320=5338

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -192,7 +192,7 @@
 break
 
 # Now find an agreed upon compression format.
-for engine in wireproto.supportedcompengines(self._ui, self,
+for engine in wireproto.supportedcompengines(self._ui,
  util.SERVERROLE):
 if engine.wireprotosupport().name in compformats:
 opts = {}
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -587,7 +587,7 @@
 
 return ui.configbool('server', 'bundle1')
 
-def supportedcompengines(ui, proto, role):
+def supportedcompengines(ui, role):
 """Obtain the list of supported compression engines for a request."""
 assert role in (util.CLIENTROLE, util.SERVERROLE)
 
@@ -824,7 +824,7 @@
 # FUTURE advertise minrx and mintx after consulting config option
 caps.append('httpmediatype=0.1rx,0.1tx,0.2tx')
 
-compengines = supportedcompengines(repo.ui, proto, util.SERVERROLE)
+compengines = supportedcompengines(repo.ui, util.SERVERROLE)
 if compengines:
 comptypes = ','.join(urlreq.quote(e.wireprotosupport().name)
  for e in compengines)



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


D2082: wireproto: use maybecapturestdio() for push responses (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5334.
indygreg edited the summary of this revision.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2082?vs=5316=5334

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

AFFECTED FILES
  hgext/largefiles/proto.py
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -320,15 +320,13 @@
 req.respond(HTTP_OK, mediatype)
 return gen
 elif isinstance(rsp, wireproto.pushres):
-val = proto.restore()
-rsp = '%d\n%s' % (rsp.res, val)
+rsp = '%d\n%s' % (rsp.res, rsp.output)
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
 elif isinstance(rsp, wireproto.pusherr):
 # This is the httplib workaround documented in _handlehttperror().
 req.drain()
 
-proto.restore()
 rsp = '0\n%s\n' % rsp.res
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -510,16 +510,18 @@
 
 The call was successful and returned an integer contained in `self.res`.
 """
-def __init__(self, res):
+def __init__(self, res, output):
 self.res = res
+self.output = output
 
 class pusherr(object):
 """wireproto reply: failure
 
 The call failed. The `self.res` attribute contains the error message.
 """
-def __init__(self, res):
+def __init__(self, res, output):
 self.res = res
+self.output = output
 
 class ooberror(object):
 """wireproto reply: failure of a batch of operation
@@ -997,97 +999,98 @@
 def unbundle(repo, proto, heads):
 their_heads = decodelist(heads)
 
-try:
-proto.redirect()
-
-exchange.check_heads(repo, their_heads, 'preparing changes')
-
-# write bundle data to temporary file because it can be big
-fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
-fp = os.fdopen(fd, pycompat.sysstr('wb+'))
-r = 0
+with proto.mayberedirectstdio() as output:
 try:
-proto.getfile(fp)
-fp.seek(0)
-gen = exchange.readbundle(repo.ui, fp, None)
-if (isinstance(gen, changegroupmod.cg1unpacker)
-and not bundle1allowed(repo, 'push')):
-if proto.name == 'http':
-# need to special case http because stderr do not get to
-# the http client on failed push so we need to abuse some
-# other error type to make sure the message get to the
-# user.
-return ooberror(bundle2required)
-raise error.Abort(bundle2requiredmain,
-  hint=bundle2requiredhint)
+exchange.check_heads(repo, their_heads, 'preparing changes')
 
-r = exchange.unbundle(repo, gen, their_heads, 'serve',
-  proto._client())
-if util.safehasattr(r, 'addpart'):
-# The return looks streamable, we are in the bundle2 case and
-# should return a stream.
-return streamres_legacy(gen=r.getchunks())
-return pushres(r)
-
-finally:
-fp.close()
-os.unlink(tempname)
-
-except (error.BundleValueError, error.Abort, error.PushRaced) as exc:
-# handle non-bundle2 case first
-if not getattr(exc, 'duringunbundle2', False):
+# write bundle data to temporary file because it can be big
+fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
+fp = os.fdopen(fd, pycompat.sysstr('wb+'))
+r = 0
 try:
-raise
-except error.Abort:
-# The old code we moved used util.stderr directly.
-# We did not change it to minimise code change.
-# This need to be moved to something proper.
-# Feel free to do it.
-util.stderr.write("abort: %s\n" % exc)
-if exc.hint is not None:
-util.stderr.write("(%s)\n" % exc.hint)
-return pushres(0)
-except error.PushRaced:
-return pusherr(str(exc))
+proto.getfile(fp)
+fp.seek(0)
+gen = exchange.readbundle(repo.ui, fp, None)
+if (isinstance(gen, changegroupmod.cg1unpacker)
+and not bundle1allowed(repo, 'push')):
+if proto.name == 'http':
+# need to special case http because stderr do not get 
to
+# the http client on failed push so we need to abuse
+# some other error type to make 

D2087: wireprotoserver: move responsetype() out of http handler

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5339.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2087?vs=5321=5339

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

AFFECTED FILES
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -170,48 +170,6 @@
 urlreq.quote(self._req.env.get('REMOTE_HOST', '')),
 urlreq.quote(self._req.env.get('REMOTE_USER', '')))
 
-def responsetype(self, prefer_uncompressed):
-"""Determine the appropriate response type and compression settings.
-
-Returns a tuple of (mediatype, compengine, engineopts).
-"""
-# Determine the response media type and compression engine based
-# on the request parameters.
-protocaps = decodevaluefromheaders(self._req, r'X-HgProto').split(' ')
-
-if '0.2' in protocaps:
-# All clients are expected to support uncompressed data.
-if prefer_uncompressed:
-return HGTYPE2, util._noopengine(), {}
-
-# Default as defined by wire protocol spec.
-compformats = ['zlib', 'none']
-for cap in protocaps:
-if cap.startswith('comp='):
-compformats = cap[5:].split(',')
-break
-
-# Now find an agreed upon compression format.
-for engine in wireproto.supportedcompengines(self._ui,
- util.SERVERROLE):
-if engine.wireprotosupport().name in compformats:
-opts = {}
-level = self._ui.configint('server',
-  '%slevel' % engine.name())
-if level is not None:
-opts['level'] = level
-
-return HGTYPE2, engine, opts
-
-# No mutually supported compression format. Fall back to the
-# legacy protocol.
-
-# Don't allow untrusted settings because disabling compression or
-# setting a very high compression level could lead to flooding
-# the server's network or CPU.
-opts = {'level': self._ui.configint('server', 'zliblevel')}
-return HGTYPE, util.compengines['zlib'], opts
-
 def iscmd(cmd):
 return cmd in wireproto.commands
 
@@ -252,6 +210,46 @@
 'handleerror': lambda ex: _handlehttperror(ex, req, cmd),
 }
 
+def _httpresponsetype(ui, req, prefer_uncompressed):
+"""Determine the appropriate response type and compression settings.
+
+Returns a tuple of (mediatype, compengine, engineopts).
+"""
+# Determine the response media type and compression engine based
+# on the request parameters.
+protocaps = decodevaluefromheaders(req, r'X-HgProto').split(' ')
+
+if '0.2' in protocaps:
+# All clients are expected to support uncompressed data.
+if prefer_uncompressed:
+return HGTYPE2, util._noopengine(), {}
+
+# Default as defined by wire protocol spec.
+compformats = ['zlib', 'none']
+for cap in protocaps:
+if cap.startswith('comp='):
+compformats = cap[5:].split(',')
+break
+
+# Now find an agreed upon compression format.
+for engine in wireproto.supportedcompengines(ui, util.SERVERROLE):
+if engine.wireprotosupport().name in compformats:
+opts = {}
+level = ui.configint('server', '%slevel' % engine.name())
+if level is not None:
+opts['level'] = level
+
+return HGTYPE2, engine, opts
+
+# No mutually supported compression format. Fall back to the
+# legacy protocol.
+
+# Don't allow untrusted settings because disabling compression or
+# setting a very high compression level could lead to flooding
+# the server's network or CPU.
+opts = {'level': ui.configint('server', 'zliblevel')}
+return HGTYPE, util.compengines['zlib'], opts
+
 def _callhttp(repo, req, proto, cmd):
 def genversion2(gen, engine, engineopts):
 # application/mercurial-0.2 always sends a payload header
@@ -284,8 +282,8 @@
 
 # This code for compression should not be streamres specific. It
 # is here because we only compress streamres at the moment.
-mediatype, engine, engineopts = proto.responsetype(
-rsp.prefer_uncompressed)
+mediatype, engine, engineopts = _httpresponsetype(
+repo.ui, req, rsp.prefer_uncompressed)
 gen = engine.compressstream(gen, engineopts)
 
 if mediatype == HGTYPE2:



To: indygreg, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org

D2084: wireprotoserver: rename _client to client (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5336.
indygreg edited the summary of this revision.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2084?vs=5318=5336

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -88,6 +88,10 @@
 won't be captured.
 """
 
+@abc.abstractmethod
+def client(self):
+"""Returns a string representation of this client (as bytes)."""
+
 def decodevaluefromheaders(req, headerprefix):
 """Decode a long value from multiple HTTP request headers.
 
@@ -164,7 +168,7 @@
 self._ui.fout = oldout
 self._ui.ferr = olderr
 
-def _client(self):
+def client(self):
 return 'remote:%s:%s:%s' % (
 self._req.env.get('wsgi.url_scheme') or 'http',
 urlreq.quote(self._req.env.get('REMOTE_HOST', '')),
@@ -399,7 +403,7 @@
 def mayberedirectstdio(self):
 yield None
 
-def _client(self):
+def client(self):
 client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
 return 'remote:ssh:' + client
 
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -1023,7 +1023,7 @@
   hint=bundle2requiredhint)
 
 r = exchange.unbundle(repo, gen, their_heads, 'serve',
-  proto._client())
+  proto.client())
 if util.safehasattr(r, 'addpart'):
 # The return looks streamable, we are in the bundle2 case
 # and should return a stream.



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


D2085: wireprotoserver: rename getfile() to forwardpayload() (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5337.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2085?vs=5319=5337

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

AFFECTED FILES
  hgext/largefiles/proto.py
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -64,14 +64,10 @@
 returns a list of values (same order as )"""
 
 @abc.abstractmethod
-def getfile(self, fp):
-"""write the whole content of a file into a file like object
+def forwardpayload(self, fp):
+"""Read the raw payload and forward to a file.
 
-The file is in the form::
-
-(\n)+0\n
-
-chunk size is the ascii version of the int.
+The payload is read in full before the function returns.
 """
 
 @abc.abstractmethod
@@ -145,7 +141,7 @@
 args.update(cgi.parse_qs(argvalue, keep_blank_values=True))
 return args
 
-def getfile(self, fp):
+def forwardpayload(self, fp):
 length = int(self._req.env[r'CONTENT_LENGTH'])
 # If httppostargs is used, we need to read Content-Length
 # minus the amount that was consumed by args.
@@ -392,7 +388,12 @@
 data[arg] = val
 return [data[k] for k in keys]
 
-def getfile(self, fpout):
+def forwardpayload(self, fpout):
+# The file is in the form:
+#
+# \n
+# ...
+# 0\n
 _sshv1respondbytes(self._fout, b'')
 count = int(self._fin.readline())
 while count:
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -1008,7 +1008,7 @@
 fp = os.fdopen(fd, pycompat.sysstr('wb+'))
 r = 0
 try:
-proto.getfile(fp)
+proto.forwardpayload(fp)
 fp.seek(0)
 gen = exchange.readbundle(repo.ui, fp, None)
 if (isinstance(gen, changegroupmod.cg1unpacker)
diff --git a/hgext/largefiles/proto.py b/hgext/largefiles/proto.py
--- a/hgext/largefiles/proto.py
+++ b/hgext/largefiles/proto.py
@@ -40,7 +40,7 @@
 tmpfp = util.atomictempfile(path, createmode=repo.store.createmode)
 
 try:
-proto.getfile(tmpfp)
+proto.forwardpayload(tmpfp)
 tmpfp._fp.seek(0)
 if sha != lfutil.hexsha1(tmpfp._fp):
 raise IOError(0, _('largefile contents do not match hash'))



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


D2088: wireprototypes: move wire protocol response types to new module

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5340.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2088?vs=5324=5340

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py
  mercurial/wireprototypes.py

CHANGE DETAILS

diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py
new file mode 100644
--- /dev/null
+++ b/mercurial/wireprototypes.py
@@ -0,0 +1,61 @@
+# 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
+
+class ooberror(object):
+"""wireproto reply: failure of a batch of operation
+
+Something failed during a batch call. The error message is stored in
+`self.message`.
+"""
+def __init__(self, message):
+self.message = message
+
+class pushres(object):
+"""wireproto reply: success with simple integer return
+
+The call was successful and returned an integer contained in `self.res`.
+"""
+def __init__(self, res, output):
+self.res = res
+self.output = output
+
+class pusherr(object):
+"""wireproto reply: failure
+
+The call failed. The `self.res` attribute contains the error message.
+"""
+def __init__(self, res, output):
+self.res = res
+self.output = output
+
+class streamres(object):
+"""wireproto reply: binary stream
+
+The call was successful and the result is a stream.
+
+Accepts a generator containing chunks of data to be sent to the client.
+
+``prefer_uncompressed`` indicates that the data is expected to be
+uncompressable and that the stream should therefore use the ``none``
+engine.
+"""
+def __init__(self, gen=None, prefer_uncompressed=False):
+self.gen = gen
+self.prefer_uncompressed = prefer_uncompressed
+
+class streamreslegacy(object):
+"""wireproto reply: uncompressed binary stream
+
+The call was successful and the result is a stream.
+
+Accepts a generator containing chunks of data to be sent to the client.
+
+Like ``streamres``, but sends an uncompressed data for "version 1" clients
+using the application/mercurial-0.1 media type.
+"""
+def __init__(self, gen=None):
+self.gen = gen
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -20,6 +20,7 @@
 pycompat,
 util,
 wireproto,
+wireprototypes,
 )
 
 stringio = util.stringio
@@ -273,11 +274,11 @@
 if isinstance(rsp, bytes):
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
-elif isinstance(rsp, wireproto.streamres_legacy):
+elif isinstance(rsp, wireprototypes.streamreslegacy):
 gen = rsp.gen
 req.respond(HTTP_OK, HGTYPE)
 return gen
-elif isinstance(rsp, wireproto.streamres):
+elif isinstance(rsp, wireprototypes.streamres):
 gen = rsp.gen
 
 # This code for compression should not be streamres specific. It
@@ -291,18 +292,18 @@
 
 req.respond(HTTP_OK, mediatype)
 return gen
-elif isinstance(rsp, wireproto.pushres):
+elif isinstance(rsp, wireprototypes.pushres):
 rsp = '%d\n%s' % (rsp.res, rsp.output)
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
-elif isinstance(rsp, wireproto.pusherr):
+elif isinstance(rsp, wireprototypes.pusherr):
 # This is the httplib workaround documented in _handlehttperror().
 req.drain()
 
 rsp = '0\n%s\n' % rsp.res
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
-elif isinstance(rsp, wireproto.ooberror):
+elif isinstance(rsp, wireprototypes.ooberror):
 rsp = rsp.message
 req.respond(HTTP_OK, HGERRTYPE, body=rsp)
 return []
@@ -434,16 +435,16 @@
 
 if isinstance(rsp, bytes):
 _sshv1respondbytes(self._fout, rsp)
-elif isinstance(rsp, wireproto.streamres):
+elif isinstance(rsp, wireprototypes.streamres):
 _sshv1respondstream(self._fout, rsp)
-elif isinstance(rsp, wireproto.streamres_legacy):
+elif isinstance(rsp, wireprototypes.streamreslegacy):
 _sshv1respondstream(self._fout, rsp)
-elif isinstance(rsp, wireproto.pushres):
+elif isinstance(rsp, wireprototypes.pushres):
 _sshv1respondbytes(self._fout, b'')
 _sshv1respondbytes(self._fout, bytes(rsp.res))
-elif isinstance(rsp, wireproto.pusherr):
+elif isinstance(rsp, wireprototypes.pusherr):
 _sshv1respondbytes(self._fout, rsp.res)
-elif isinstance(rsp, wireproto.ooberror):
+elif isinstance(rsp, wireprototypes.ooberror):
 

D2091: wireprotoserver: extract SSH response handling functions

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

REVISION SUMMARY
  The lookup/dispatch table was cute. But it isn't needed. Future
  refactors will benefit from the handlers for individual response
  types living outside the class.
  
  As part of this, I snuck in a change that changes a type compare
  from str to bytes. This has no effect on Python 2. But it might
  make Python 3 a bit happier.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/wireprotoserver.py
  tests/sshprotoext.py

CHANGE DETAILS

diff --git a/tests/sshprotoext.py b/tests/sshprotoext.py
--- a/tests/sshprotoext.py
+++ b/tests/sshprotoext.py
@@ -45,11 +45,11 @@
 l = self._fin.readline()
 assert l == b'hello\n'
 # Respond to unknown commands with an empty reply.
-self._sendresponse(b'')
+wireprotoserver._sshv1respondbytes(self._fout, b'')
 l = self._fin.readline()
 assert l == b'between\n'
 rsp = wireproto.dispatch(self._repo, self, b'between')
-self._handlers[rsp.__class__](self, rsp)
+wireprotoserver._sshv1respondbytes(self._fout, rsp)
 
 super(prehelloserver, self).serve_forever()
 
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -336,6 +336,24 @@
 
 return ''
 
+def _sshv1respondbytes(fout, value):
+"""Send a bytes response for protocol version 1."""
+fout.write('%d\n' % len(value))
+fout.write(value)
+fout.flush()
+
+def _sshv1respondstream(fout, source):
+write = fout.write
+for chunk in source.gen:
+write(chunk)
+fout.flush()
+
+def _sshv1sendooberror(fout, ferr, rsp):
+ferr.write(b'%s\n-\n' % rsp.message)
+ferr.flush()
+fout.write(b'\n')
+fout.flush()
+
 class sshserver(baseprotocolhandler):
 def __init__(self, ui, repo):
 self._ui = ui
@@ -376,60 +394,43 @@
 return [data[k] for k in keys]
 
 def getfile(self, fpout):
-self._sendresponse('')
+_sshv1respondbytes(self._fout, b'')
 count = int(self._fin.readline())
 while count:
 fpout.write(self._fin.read(count))
 count = int(self._fin.readline())
 
 def redirect(self):
 pass
 
-def _sendresponse(self, v):
-self._fout.write("%d\n" % len(v))
-self._fout.write(v)
-self._fout.flush()
-
-def _sendstream(self, source):
-write = self._fout.write
-for chunk in source.gen:
-write(chunk)
-self._fout.flush()
-
-def _sendpushresponse(self, rsp):
-self._sendresponse('')
-self._sendresponse(str(rsp.res))
-
-def _sendpusherror(self, rsp):
-self._sendresponse(rsp.res)
-
-def _sendooberror(self, rsp):
-self._ui.ferr.write('%s\n-\n' % rsp.message)
-self._ui.ferr.flush()
-self._fout.write('\n')
-self._fout.flush()
-
 def serve_forever(self):
 while self.serve_one():
 pass
 sys.exit(0)
 
-_handlers = {
-str: _sendresponse,
-wireproto.streamres: _sendstream,
-wireproto.streamres_legacy: _sendstream,
-wireproto.pushres: _sendpushresponse,
-wireproto.pusherr: _sendpusherror,
-wireproto.ooberror: _sendooberror,
-}
-
 def serve_one(self):
 cmd = self._fin.readline()[:-1]
 if cmd and wireproto.commands.commandavailable(cmd, self):
 rsp = wireproto.dispatch(self._repo, self, cmd)
-self._handlers[rsp.__class__](self, rsp)
+
+if isinstance(rsp, bytes):
+_sshv1respondbytes(self._fout, rsp)
+elif isinstance(rsp, wireproto.streamres):
+_sshv1respondstream(self._fout, rsp)
+elif isinstance(rsp, wireproto.streamres_legacy):
+_sshv1respondstream(self._fout, rsp)
+elif isinstance(rsp, wireproto.pushres):
+_sshv1respondbytes(self._fout, b'')
+_sshv1respondbytes(self._fout, bytes(rsp.res))
+elif isinstance(rsp, wireproto.pusherr):
+_sshv1respondbytes(self._fout, rsp.res)
+elif isinstance(rsp, wireproto.ooberror):
+_sshv1sendooberror(self._fout, self._ui.ferr, rsp)
+else:
+raise error.ProgrammingError('unhandled response type from '
+ 'wire protocol command: %s' % rsp)
 elif cmd:
-self._sendresponse("")
+_sshv1respondbytes(self._fout, b'')
 return cmd != ''
 
 def _client(self):



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


D2080: wireprotoserver: split ssh protocol handler and server

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5332.
indygreg edited the summary of this revision.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2080?vs=5314=5332

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

AFFECTED FILES
  mercurial/wireprotoserver.py
  tests/sshprotoext.py
  tests/test-sshserver.py

CHANGE DETAILS

diff --git a/tests/test-sshserver.py b/tests/test-sshserver.py
--- a/tests/test-sshserver.py
+++ b/tests/test-sshserver.py
@@ -24,7 +24,7 @@
 def assertparse(self, cmd, input, expected):
 server = mockserver(input)
 _func, spec = wireproto.commands[cmd]
-self.assertEqual(server.getargs(spec), expected)
+self.assertEqual(server._proto.getargs(spec), expected)
 
 def mockserver(inbytes):
 ui = mockui(inbytes)
diff --git a/tests/sshprotoext.py b/tests/sshprotoext.py
--- a/tests/sshprotoext.py
+++ b/tests/sshprotoext.py
@@ -48,7 +48,7 @@
 wireprotoserver._sshv1respondbytes(self._fout, b'')
 l = self._fin.readline()
 assert l == b'between\n'
-rsp = wireproto.dispatch(self._repo, self, b'between')
+rsp = wireproto.dispatch(self._repo, self._proto, b'between')
 wireprotoserver._sshv1respondbytes(self._fout, rsp)
 
 super(prehelloserver, self).serve_forever()
@@ -73,7 +73,7 @@
 
 # Send the upgrade response.
 self._fout.write(b'upgraded %s %s\n' % (token, name))
-servercaps = wireproto.capabilities(self._repo, self)
+servercaps = wireproto.capabilities(self._repo, self._proto)
 rsp = b'capabilities: %s' % servercaps
 self._fout.write(b'%d\n' % len(rsp))
 self._fout.write(rsp)
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -354,19 +354,12 @@
 fout.write(b'\n')
 fout.flush()
 
-class sshserver(baseprotocolhandler):
-def __init__(self, ui, repo):
+class sshv1protocolhandler(baseprotocolhandler):
+"""Handler for requests services via version 1 of SSH protocol."""
+def __init__(self, ui, fin, fout):
 self._ui = ui
-self._repo = repo
-self._fin = ui.fin
-self._fout = ui.fout
-
-hook.redirect(True)
-ui.fout = repo.ui.fout = ui.ferr
-
-# Prevent insertion/deletion of CRs
-util.setbinary(self._fin)
-util.setbinary(self._fout)
+self._fin = fin
+self._fout = fout
 
 @property
 def name(self):
@@ -403,15 +396,35 @@
 def redirect(self):
 pass
 
+def _client(self):
+client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
+return 'remote:ssh:' + client
+
+class sshserver(object):
+def __init__(self, ui, repo):
+self._ui = ui
+self._repo = repo
+self._fin = ui.fin
+self._fout = ui.fout
+
+hook.redirect(True)
+ui.fout = repo.ui.fout = ui.ferr
+
+# Prevent insertion/deletion of CRs
+util.setbinary(self._fin)
+util.setbinary(self._fout)
+
+self._proto = sshv1protocolhandler(self._ui, self._fin, self._fout)
+
 def serve_forever(self):
 while self.serve_one():
 pass
 sys.exit(0)
 
 def serve_one(self):
 cmd = self._fin.readline()[:-1]
-if cmd and wireproto.commands.commandavailable(cmd, self):
-rsp = wireproto.dispatch(self._repo, self, cmd)
+if cmd and wireproto.commands.commandavailable(cmd, self._proto):
+rsp = wireproto.dispatch(self._repo, self._proto, cmd)
 
 if isinstance(rsp, bytes):
 _sshv1respondbytes(self._fout, rsp)
@@ -432,7 +445,3 @@
 elif cmd:
 _sshv1respondbytes(self._fout, b'')
 return cmd != ''
-
-def _client(self):
-client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
-return 'remote:ssh:' + client



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


D2083: wireprotoserver: remove redirect() and restore() (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5335.
indygreg edited the summary of this revision.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2083?vs=5317=5335

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

AFFECTED FILES
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -88,23 +88,6 @@
 won't be captured.
 """
 
-@abc.abstractmethod
-def redirect(self):
-"""may setup interception for stdout and stderr
-
-See also the `restore` method."""
-
-# If the `redirect` function does install interception, the `restore`
-# function MUST be defined. If interception is not used, this function
-# MUST NOT be defined.
-#
-# left commented here on purpose
-#
-#def restore(self):
-#"""reinstall previous stdout and stderr and return intercepted stdout
-#"""
-#raise NotImplementedError()
-
 def decodevaluefromheaders(req, headerprefix):
 """Decode a long value from multiple HTTP request headers.
 
@@ -181,15 +164,6 @@
 self._ui.fout = oldout
 self._ui.ferr = olderr
 
-def redirect(self):
-self._oldio = self._ui.fout, self._ui.ferr
-self._ui.ferr = self._ui.fout = stringio()
-
-def restore(self):
-val = self._ui.fout.getvalue()
-self._ui.ferr, self._ui.fout = self._oldio
-return val
-
 def _client(self):
 return 'remote:%s:%s:%s' % (
 self._req.env.get('wsgi.url_scheme') or 'http',
@@ -425,9 +399,6 @@
 def mayberedirectstdio(self):
 yield None
 
-def redirect(self):
-pass
-
 def _client(self):
 client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
 return 'remote:ssh:' + client



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


D2081: wireprotoserver: add context manager mechanism for redirecting stdio

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5333.
indygreg edited the summary of this revision.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2081?vs=5315=5333

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -8,6 +8,7 @@
 
 import abc
 import cgi
+import contextlib
 import struct
 import sys
 
@@ -74,6 +75,20 @@
 """
 
 @abc.abstractmethod
+def mayberedirectstdio(self):
+"""Context manager to possibly redirect stdio.
+
+The context manager yields a file-object like object that receives
+stdout and stderr output when the context manager is active. Or it
+yields ``None`` if no I/O redirection occurs.
+
+The intent of this context manager is to capture stdio output
+so it may be sent in the response. Some transports support streaming
+stdio to the client in real time. For these transports, stdio output
+won't be captured.
+"""
+
+@abc.abstractmethod
 def redirect(self):
 """may setup interception for stdout and stderr
 
@@ -151,6 +166,21 @@
 for s in util.filechunkiter(self._req, limit=length):
 fp.write(s)
 
+@contextlib.contextmanager
+def mayberedirectstdio(self):
+oldout = self._ui.fout
+olderr = self._ui.ferr
+
+out = util.stringio()
+
+try:
+self._ui.fout = out
+self._ui.ferr = out
+yield out
+finally:
+self._ui.fout = oldout
+self._ui.ferr = olderr
+
 def redirect(self):
 self._oldio = self._ui.fout, self._ui.ferr
 self._ui.ferr = self._ui.fout = stringio()
@@ -393,6 +423,10 @@
 fpout.write(self._fin.read(count))
 count = int(self._fin.readline())
 
+@contextlib.contextmanager
+def mayberedirectstdio(self):
+yield None
+
 def redirect(self):
 pass
 
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -978,20 +978,12 @@
 else:
 new = encoding.tolocal(new) # normal path
 
-if util.safehasattr(proto, 'restore'):
-
-proto.redirect()
-
+with proto.mayberedirectstdio() as output:
 r = repo.pushkey(encoding.tolocal(namespace), encoding.tolocal(key),
  encoding.tolocal(old), new) or False
 
-output = proto.restore()
-
-return '%s\n%s' % (int(r), output)
-
-r = repo.pushkey(encoding.tolocal(namespace), encoding.tolocal(key),
- encoding.tolocal(old), new)
-return '%s\n' % int(r)
+output = output.getvalue() if output else ''
+return '%s\n%s' % (int(r), output)
 
 @wireprotocommand('stream_out')
 def stream(repo, proto):



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


Re: FYI: Mercurial 4.6 sprint is March 2nd-4th at Google's Cambridge, MA office

2018-02-07 Thread Kevin Bullock
> On Feb 6, 2018, at 09:01, Augie Fackler  wrote:
> 
> https://www.mercurial-scm.org/wiki/4.6sprint has all the details, and I'll 
> fill in more as I have them.
> 
> Sorry for not doing the usual planning routine on this, but time got away 
> from us and we decided to make some decisions quickly rather than waiting for 
> the usual date-picking routine.
> 
> See (some) of you next month!

If you need travel funding, please add yourself to the wiki page soon! We have 
some travel funding available. If you'd like to take advantage of it, flights 
need to be booked at least 14 days in advance per the Software Freedom 
Conservancy's travel policy[1]. I encourage you to e-mail me off-list if you 
have further questions about travel sponsorship.

Likewise, if you or your company would like to donate to cover people's travel 
expenses, please let me know!

[1]: https://sfconservancy.org/projects/policies/conservancy-travel-policy.html

pacem in terris / мир / शान्ति / ‎‫سَلاَم‬ / 平和
Kevin R. Bullock

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


D2057: translate base85.c into rust code

2018-02-07 Thread krbullock (Kevin Bullock)
krbullock added a comment.


  What would be the advantage of taking this? Since we already have the C 
implementation, it's not likely to gain us any performance. On the other hand, 
it might make a good test case for integrating Rust and Python, finding the 
right API boundaries and experimenting with different approaches, precisely 
//because// we already have a C implementation. @indygreg @durin42 what are 
your thoughts about it?

REPOSITORY
  rHG Mercurial

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

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


D2090: fancyopts: add support for custom multi-arg opts in fancyopts.py

2018-02-07 Thread dploch (Daniel Ploch)
dploch added a comment.


  In https://phab.mercurial-scm.org/D2090#34906, @indygreg wrote:
  
  > The fancyopts code is some of the oldest in Mercurial. We've been wanting 
to rewrite it for a while. This patch seems like an interesting and more 
powerful direction to take the parser.
  >
  > Out of curiosity, do you have an intended use case in mind? Will that use 
case be in Mercurial itself or is this for an extension?
  
  
  I didn't have a use case for Mercurial itself in mind, but I wouldn't be 
surprised if there was one.  My intended use case is the 'csv' flag example in 
the commit description: We have a lot of flags in our internal extensions that 
require the ["alice,bob", "charlie"] -> ["alice", "bob", "charlie"] behavior, 
so it would be really nice to be able to declare a shareable customopt for 
these instead of needing to individually wrap every applicable `opts['flag']` 
lookup.

REPOSITORY
  rHG Mercurial

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

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


D2090: fancyopts: add support for custom multi-arg opts in fancyopts.py

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg added a comment.


  The fancyopts code is some of the oldest in Mercurial. We've been wanting to 
rewrite it for a while. This patch seems like an interesting and more powerful 
direction to take the parser.
  
  Out of curiosity, do you have an intended use case in mind? Will that use 
case be in Mercurial itself or is this for an extension?

REPOSITORY
  rHG Mercurial

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

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


D2090: fancyopts: add support for custom multi-arg opts in fancyopts.py

2018-02-07 Thread dploch (Daniel Ploch)
dploch created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This allows for more complex multi-arg opt logic, such as "--sum 1 --sum 2" 
-> 3, "--csv alice,bob --csv charlie" -> ["alice","bob","charlie"].  The 
current support for callables is insufficient for this.
  
  This is done by introducing a 'customopt' class which can be extended for 
more powerful opts logic.  All existing opt-types are converted to use this 
class, simplifying the fancyopts() logic.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/fancyopts.py

CHANGE DETAILS

diff --git a/mercurial/fancyopts.py b/mercurial/fancyopts.py
--- a/mercurial/fancyopts.py
+++ b/mercurial/fancyopts.py
@@ -7,6 +7,7 @@
 
 from __future__ import absolute_import
 
+import abc
 import functools
 
 from .i18n import _
@@ -201,6 +202,66 @@
 parsedargs.extend(args[pos:])
 return parsedopts, parsedargs
 
+class customopt(object):
+"""Manage defaults and mutations for any type of opt."""
+
+__metaclass__ = abc.ABCMeta
+
+def __init__(self, defaultvalue):
+self.defaultvalue = defaultvalue
+
+def _isboolopt(self):
+return False
+
+@abc.abstractmethod
+def newstate(self, oldstate, newparam, abort):
+"""Adds newparam to oldstate and returns the new state.
+
+On failure, abort can be called with a string error message."""
+
+class _simpleopt(customopt):
+def _isboolopt(self):
+t = type(self.defaultvalue)
+return t is type(False) or t is type(None)
+
+def newstate(self, oldstate, newparam, abort):
+return newparam
+
+class _callableopt(customopt):
+def __init__(self, callable):
+self.callable = callable
+super(_callableopt, self).__init__(None)
+
+def newstate(self, oldstate, newparam, abort):
+return self.callable(newparam)
+
+class _listopt(customopt):
+def newstate(self, oldstate, newparam, abort):
+oldstate.append(newparam)
+return oldstate
+
+class _intopt(customopt):
+def newstate(self, oldstate, newparam, abort):
+try:
+return int(newparam)
+except ValueError:
+abort(_('expected int'))
+
+def _defaultopt(default):
+"""Returns a default opt implementation, given a default value."""
+
+t = type(default)
+if isinstance(default, customopt):
+return default
+elif callable(default):
+return _callableopt(default)
+elif t is type([]):
+return _listopt(default[:])
+elif t is type(1):
+return _intopt(default)
+else:
+return _simpleopt(default)
+
 def fancyopts(args, options, state, gnu=False, early=False, optaliases=None):
 """
 read args, parse options, and store options in state
@@ -220,6 +281,7 @@
   list - parameter string is added to a list
   integer - parameter strings is stored as int
   function - call function with parameter
+  customopt - subclass of 'customopt'
 
 optaliases is a mapping from a canonical option name to a list of
 additional long options. This exists for preserving backward compatibility
@@ -250,18 +312,13 @@
 argmap['-' + short] = name
 for n in onames:
 argmap['--' + n] = name
-defmap[name] = default
+defmap[name] = _defaultopt(default)
 
 # copy defaults to state
-if isinstance(default, list):
-state[name] = default[:]
-elif callable(default):
-state[name] = None
-else:
-state[name] = default
+state[name] = defmap[name].defaultvalue
 
 # does it take a parameter?
-if not (default is None or default is True or default is False):
+if not defmap[name]._isboolopt():
 if short:
 short += ':'
 onames = [n + '=' for n in onames]
@@ -301,21 +358,13 @@
 boolval = False
 name = argmap[opt]
 obj = defmap[name]
-t = type(obj)
-if callable(obj):
-state[name] = defmap[name](val)
-elif t is type(1):
-try:
-state[name] = int(val)
-except ValueError:
-raise error.Abort(_('invalid value %r for option %s, '
-   'expected int') % (val, opt))
-elif t is type(''):
-state[name] = val
-elif t is type([]):
-state[name].append(val)
-elif t is type(None) or t is type(False):
+if obj._isboolopt():
 state[name] = boolval
+else:
+def abort(s):
+raise error.Abort(
+_('invalid value %r for option %s, %s') % (val, opt, s))
+state[name] = defmap[name].newstate(state[name], val, abort)
 
 # return unparsed args
 return args



To: dploch, #hg-reviewers
Cc: mercurial-devel

D2068: revlog: do not use delta for lfs revisions

2018-02-07 Thread quark (Jun Wu)
quark updated this revision to Diff 5329.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2068?vs=5328=5329

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

AFFECTED FILES
  mercurial/revlog.py
  tests/test-lfs-bundle.t
  tests/test-revlog-raw.py

CHANGE DETAILS

diff --git a/tests/test-revlog-raw.py b/tests/test-revlog-raw.py
--- a/tests/test-revlog-raw.py
+++ b/tests/test-revlog-raw.py
@@ -114,6 +114,8 @@
 else:
 # suboptimal deltaparent
 deltaparent = min(0, parentrev)
+if not rlog.candelta(deltaparent, r):
+deltaparent = -1
 return {'node': rlog.node(r), 'p1': pnode, 'p2': node.nullid,
 'cs': rlog.node(rlog.linkrev(r)), 'flags': rlog.flags(r),
 'deltabase': rlog.node(deltaparent),
@@ -151,12 +153,12 @@
 for r in rlog:
 p1 = rlog.node(r - 1)
 p2 = node.nullid
-if r == 0:
+if r == 0 or rlog.flags(r):
 text = rlog.revision(r, raw=True)
 cachedelta = None
 else:
-# deltaparent is more interesting if it has the EXTSTORED flag.
-deltaparent = max([0] + [p for p in range(r - 2) if rlog.flags(p)])
+# deltaparent cannot have EXTSTORED flag.
+deltaparent = max([-1] + [p for p in range(r) if not 
rlog.flags(p)])
 text = None
 cachedelta = (deltaparent, rlog.revdiff(deltaparent, r))
 flags = rlog.flags(r)
@@ -262,8 +264,9 @@
 result.append((text, rawtext))
 
 # Verify flags like isdelta, isext work as expected
-if bool(rlog.deltaparent(rev) > -1) != isdelta:
-abort('rev %d: isdelta is ineffective' % rev)
+# isdelta can be overridden to False if this or p1 has isext set
+if bool(rlog.deltaparent(rev) > -1) and not isdelta:
+abort('rev %d: isdelta is unexpected' % rev)
 if bool(rlog.flags(rev)) != isext:
 abort('rev %d: isext is ineffective' % rev)
 return result
diff --git a/tests/test-lfs-bundle.t b/tests/test-lfs-bundle.t
--- a/tests/test-lfs-bundle.t
+++ b/tests/test-lfs-bundle.t
@@ -90,10 +90,7 @@
    Applying src-normal.bundle to dst-normal 
   OK
    Applying src-normal.bundle to dst-lfs 
-   X@2: unpacking bcc7d23fa6b7: integrity check failed on data/X.i:2
-   Y@2: unpacking 46017a6640e7: integrity check failed on data/Y.i:2
-  2 integrity errors encountered!
-  (first damaged changeset appears to be 2)
+  CRASHED
    Applying src-lfs.bundle to dst-normal 
   OK
    Applying src-lfs.bundle to dst-lfs 
diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -404,6 +404,9 @@
 for candidaterevs in self._getcandidaterevs(p1, p2, cachedelta):
 nominateddeltas = []
 for candidaterev in candidaterevs:
+# no delta for flag processor revision (see "candelta" for why)
+if revlog.flags(candidaterev) & REVIDX_KNOWN_FLAGS:
+continue
 candidatedelta = self._builddeltainfo(revinfo, candidaterev, 
fh)
 if revlog._isgooddeltainfo(candidatedelta, revinfo.textlen):
 nominateddeltas.append(candidatedelta)
@@ -2087,7 +2090,12 @@
 deltacomputer = _deltacomputer(self)
 
 revinfo = _revisioninfo(node, p1, p2, btext, textlen, cachedelta, 
flags)
-deltainfo = deltacomputer.finddeltainfo(revinfo, fh)
+
+# no delta for flag processor revision (see "candelta" for why)
+if flags & REVIDX_KNOWN_FLAGS:
+deltainfo = None
+else:
+deltainfo = deltacomputer.finddeltainfo(revinfo, fh)
 
 if deltainfo is not None:
 base = deltainfo.base



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


D2068: revlog: do not use delta for lfs revisions

2018-02-07 Thread quark (Jun Wu)
quark updated this revision to Diff 5328.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2068?vs=5274=5328

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

AFFECTED FILES
  mercurial/revlog.py
  tests/test-lfs-bundle.t
  tests/test-revlog-raw.py

CHANGE DETAILS

diff --git a/tests/test-revlog-raw.py b/tests/test-revlog-raw.py
--- a/tests/test-revlog-raw.py
+++ b/tests/test-revlog-raw.py
@@ -114,6 +114,8 @@
 else:
 # suboptimal deltaparent
 deltaparent = min(0, parentrev)
+if not rlog.candelta(deltaparent, r):
+deltaparent = -1
 return {'node': rlog.node(r), 'p1': pnode, 'p2': node.nullid,
 'cs': rlog.node(rlog.linkrev(r)), 'flags': rlog.flags(r),
 'deltabase': rlog.node(deltaparent),
@@ -151,12 +153,12 @@
 for r in rlog:
 p1 = rlog.node(r - 1)
 p2 = node.nullid
-if r == 0:
+if r == 0 or rlog.flags(r):
 text = rlog.revision(r, raw=True)
 cachedelta = None
 else:
-# deltaparent is more interesting if it has the EXTSTORED flag.
-deltaparent = max([0] + [p for p in range(r - 2) if rlog.flags(p)])
+# deltaparent cannot have EXTSTORED flag.
+deltaparent = max([-1] + [p for p in range(r) if not 
rlog.flags(p)])
 text = None
 cachedelta = (deltaparent, rlog.revdiff(deltaparent, r))
 flags = rlog.flags(r)
@@ -262,8 +264,9 @@
 result.append((text, rawtext))
 
 # Verify flags like isdelta, isext work as expected
-if bool(rlog.deltaparent(rev) > -1) != isdelta:
-abort('rev %d: isdelta is ineffective' % rev)
+# isdelta can be overridden to False if this or p1 has isext set
+if bool(rlog.deltaparent(rev) > -1) and not isdelta:
+abort('rev %d: isdelta is unexpected' % rev)
 if bool(rlog.flags(rev)) != isext:
 abort('rev %d: isext is ineffective' % rev)
 return result
diff --git a/tests/test-lfs-bundle.t b/tests/test-lfs-bundle.t
--- a/tests/test-lfs-bundle.t
+++ b/tests/test-lfs-bundle.t
@@ -90,10 +90,7 @@
    Applying src-normal.bundle to dst-normal 
   OK
    Applying src-normal.bundle to dst-lfs 
-   X@2: unpacking bcc7d23fa6b7: integrity check failed on data/X.i:2
-   Y@2: unpacking 46017a6640e7: integrity check failed on data/Y.i:2
-  2 integrity errors encountered!
-  (first damaged changeset appears to be 2)
+  CRASHED
    Applying src-lfs.bundle to dst-normal 
   OK
    Applying src-lfs.bundle to dst-lfs 
diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -404,6 +404,9 @@
 for candidaterevs in self._getcandidaterevs(p1, p2, cachedelta):
 nominateddeltas = []
 for candidaterev in candidaterevs:
+# no delta for flag processor revision (see "candelta" for why)
+if revlog.flags(candidaterev) & REVIDX_KNOWN_FLAGS:
+continue
 candidatedelta = self._builddeltainfo(revinfo, candidaterev, 
fh)
 if revlog._isgooddeltainfo(candidatedelta, revinfo.textlen):
 nominateddeltas.append(candidatedelta)
@@ -2087,7 +2090,12 @@
 deltacomputer = _deltacomputer(self)
 
 revinfo = _revisioninfo(node, p1, p2, btext, textlen, cachedelta, 
flags)
-deltainfo = deltacomputer.finddeltainfo(revinfo, fh)
+
+# no delta for flag processor revision (see "candelta" for why)
+if flags & REVIDX_KNOWN_FLAGS:
+deltainfo = deltacomputer.finddeltainfo(revinfo, fh)
+else:
+deltainfo = None
 
 if deltainfo is not None:
 base = deltainfo.base



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


D2067: changegroup: do not delta lfs revisions

2018-02-07 Thread quark (Jun Wu)
quark updated this revision to Diff 5327.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2067?vs=5273=5327

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

AFFECTED FILES
  mercurial/changegroup.py
  mercurial/revlog.py
  tests/test-lfs-bundle.t
  tests/test-lfs.t

CHANGE DETAILS

diff --git a/tests/test-lfs.t b/tests/test-lfs.t
--- a/tests/test-lfs.t
+++ b/tests/test-lfs.t
@@ -349,7 +349,7 @@
   uncompressed size of bundle content:
* (changelog) (glob)
* (manifests) (glob)
-   *  a (glob)
+  * a (glob)
   $ hg --config extensions.strip= strip -r 2 --no-backup --force -q
   $ hg -R bundle.hg log -p -T '{rev} {desc}\n' a
   5 branching
diff --git a/tests/test-lfs-bundle.t b/tests/test-lfs-bundle.t
--- a/tests/test-lfs-bundle.t
+++ b/tests/test-lfs-bundle.t
@@ -95,6 +95,6 @@
   2 integrity errors encountered!
   (first damaged changeset appears to be 2)
    Applying src-lfs.bundle to dst-normal 
-  CRASHED
+  OK
    Applying src-lfs.bundle to dst-lfs 
   OK
diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -713,6 +713,18 @@
 except KeyError:
 return False
 
+def candelta(self, baserev, rev):
+"""whether two revisions (prev, rev) can be delta-ed or not"""
+# Disable delta if either rev requires flag processor (ex. LFS)
+# This is because a flag processor can alter the rawtext content that
+# the delta will be based on, and two clients could have a same revlog
+# node with different flags (i.e. different rawtext contents) and the
+# delta could be incompatible.
+if ((self.flags(baserev) & REVIDX_KNOWN_FLAGS)
+or (self.flags(rev) & REVIDX_KNOWN_FLAGS)):
+return False
+return True
+
 def clearcaches(self):
 self._cache = None
 self._chainbasecache.clear()
diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -770,6 +770,8 @@
 progress(msgbundling, None)
 
 def deltaparent(self, revlog, rev, p1, p2, prev):
+if not revlog.candelta(prev, rev):
+raise error.ProgrammingError('cg1 should not be used in this case')
 return prev
 
 def revchunk(self, revlog, rev, prev, linknode):
@@ -829,16 +831,19 @@
 # expensive. The revlog caches should have prev cached, meaning
 # less CPU for changegroup generation. There is likely room to add
 # a flag and/or config option to control this behavior.
-return prev
+base = prev
 elif dp == nullrev:
 # revlog is configured to use full snapshot for a reason,
 # stick to full snapshot.
-return nullrev
+base = nullrev
 elif dp not in (p1, p2, prev):
 # Pick prev when we can't be sure remote has the base revision.
 return prev
 else:
-return dp
+base = dp
+if base != nullrev and not revlog.candelta(base, rev):
+base = nullrev
+return base
 
 def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags):
 # Do nothing with flags, it is implicitly 0 in cg1 and cg2



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


D2066: lfs: add a test showing bundle application could be broken

2018-02-07 Thread quark (Jun Wu)
quark updated this revision to Diff 5326.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2066?vs=5275=5326

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

AFFECTED FILES
  tests/drawdag.py
  tests/test-lfs-bundle.t

CHANGE DETAILS

diff --git a/tests/test-lfs-bundle.t b/tests/test-lfs-bundle.t
new file mode 100644
--- /dev/null
+++ b/tests/test-lfs-bundle.t
@@ -0,0 +1,100 @@
+In this test, we want to test LFS bundle application on both LFS and non-LFS
+repos.
+
+To make it more interesting, the file revisions will contain hg filelog
+metadata ('\1\n'). The bundle will have 1 file revision overlapping with the
+destination repo.
+
+#  rev  1  2 3
+#  repo:yesyes   no
+#  bundle:  no (base)  yes   yes (deltabase: 2 if possible)
+
+It is interesting because rev 2 could have been stored as LFS in the repo, and
+non-LFS in the bundle; or vice-versa.
+
+Init
+
+  $ cat >> $HGRCPATH << EOF
+  > [extensions]
+  > lfs=
+  > drawdag=$TESTDIR/drawdag.py
+  > [lfs]
+  > url=file://$TESTTMP/lfs-remote
+  > EOF
+
+Helper functions
+
+  $ commitxy() {
+  > hg debugdrawdag "$@" <<'EOS'
+  >  Y  # Y/X=\1\n\nE\nF
+  >  |  # Y/Y=\1\n\nG\nH
+  >  X  # X/X=\1\n\nC\n
+  > # X/Y=\1\n\nD\n
+  > EOS
+  > }
+
+  $ commitz() {
+  > hg debugdrawdag "$@" <<'EOS'
+  >  Z  # Z/X=\1\n\nI\n
+  >  |  # Z/Y=\1\n\nJ\n
+  >  |  # Z/Z=\1\nZ
+  >  Y
+  > EOS
+  > }
+
+  $ enablelfs() {
+  >   cat >> .hg/hgrc < [lfs]
+  > track=all()
+  > EOF
+  > }
+
+Generate bundles
+
+  $ for i in normal lfs; do
+  >   NAME=src-$i
+  >   hg init $TESTTMP/$NAME
+  >   cd $TESTTMP/$NAME
+  >   [ $i = lfs ] && enablelfs
+  >   commitxy
+  >   commitz
+  >   hg bundle -q --base X -r Y+Z $TESTTMP/$NAME.bundle
+  >   SRCNAMES="$SRCNAMES $NAME"
+  > done
+
+Prepare destination repos
+
+  $ for i in normal lfs; do
+  >   NAME=dst-$i
+  >   hg init $TESTTMP/$NAME
+  >   cd $TESTTMP/$NAME
+  >   [ $i = lfs ] && enablelfs
+  >   commitxy
+  >   DSTNAMES="$DSTNAMES $NAME"
+  > done
+
+Apply bundles
+
+  $ for i in $SRCNAMES; do
+  >   for j in $DSTNAMES; do
+  > echo  Applying $i.bundle to $j 
+  > cp -R $TESTTMP/$j $TESTTMP/tmp-$i-$j
+  > cd $TESTTMP/tmp-$i-$j
+  > if hg unbundle $TESTTMP/$i.bundle -q 2>/dev/null; then
+  >   hg verify -q && echo OK
+  > else
+  >   echo CRASHED
+  > fi
+  >   done
+  > done
+   Applying src-normal.bundle to dst-normal 
+  OK
+   Applying src-normal.bundle to dst-lfs 
+   X@2: unpacking bcc7d23fa6b7: integrity check failed on data/X.i:2
+   Y@2: unpacking 46017a6640e7: integrity check failed on data/Y.i:2
+  2 integrity errors encountered!
+  (first damaged changeset appears to be 2)
+   Applying src-lfs.bundle to dst-normal 
+  CRASHED
+   Applying src-lfs.bundle to dst-lfs 
+  OK
diff --git a/tests/drawdag.py b/tests/drawdag.py
--- a/tests/drawdag.py
+++ b/tests/drawdag.py
@@ -371,7 +371,8 @@
 comments = list(_getcomments(text))
 filere = re.compile(br'^(\w+)/([\w/]+)\s*=\s*(.*)$', re.M)
 for name, path, content in filere.findall(b'\n'.join(comments)):
-files[name][path] = content.replace(br'\n', b'\n')
+content = content.replace(br'\n', b'\n').replace(br'\1', b'\1')
+files[name][path] = content
 
 committed = {None: node.nullid}  # {name: node}
 



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


D2088: wireprototypes: move wire protocol response types to new module

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5324.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2088?vs=5322=5324

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py
  mercurial/wireprototypes.py

CHANGE DETAILS

diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py
new file mode 100644
--- /dev/null
+++ b/mercurial/wireprototypes.py
@@ -0,0 +1,61 @@
+# 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
+
+class ooberror(object):
+"""wireproto reply: failure of a batch of operation
+
+Something failed during a batch call. The error message is stored in
+`self.message`.
+"""
+def __init__(self, message):
+self.message = message
+
+class pushres(object):
+"""wireproto reply: success with simple integer return
+
+The call was successful and returned an integer contained in `self.res`.
+"""
+def __init__(self, res, output):
+self.res = res
+self.output = output
+
+class pusherr(object):
+"""wireproto reply: failure
+
+The call failed. The `self.res` attribute contains the error message.
+"""
+def __init__(self, res, output):
+self.res = res
+self.output = output
+
+class streamres(object):
+"""wireproto reply: binary stream
+
+The call was successful and the result is a stream.
+
+Accepts a generator containing chunks of data to be sent to the client.
+
+``prefer_uncompressed`` indicates that the data is expected to be
+uncompressable and that the stream should therefore use the ``none``
+engine.
+"""
+def __init__(self, gen=None, prefer_uncompressed=False):
+self.gen = gen
+self.prefer_uncompressed = prefer_uncompressed
+
+class streamreslegacy(object):
+"""wireproto reply: uncompressed binary stream
+
+The call was successful and the result is a stream.
+
+Accepts a generator containing chunks of data to be sent to the client.
+
+Like ``streamres``, but sends an uncompressed data for "version 1" clients
+using the application/mercurial-0.1 media type.
+"""
+def __init__(self, gen=None):
+self.gen = gen
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -20,6 +20,7 @@
 pycompat,
 util,
 wireproto,
+wireprototypes,
 )
 
 stringio = util.stringio
@@ -273,11 +274,11 @@
 if isinstance(rsp, bytes):
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
-elif isinstance(rsp, wireproto.streamres_legacy):
+elif isinstance(rsp, wireprototypes.streamreslegacy):
 gen = rsp.gen
 req.respond(HTTP_OK, HGTYPE)
 return gen
-elif isinstance(rsp, wireproto.streamres):
+elif isinstance(rsp, wireprototypes.streamres):
 gen = rsp.gen
 
 # This code for compression should not be streamres specific. It
@@ -291,18 +292,18 @@
 
 req.respond(HTTP_OK, mediatype)
 return gen
-elif isinstance(rsp, wireproto.pushres):
+elif isinstance(rsp, wireprototypes.pushres):
 rsp = '%d\n%s' % (rsp.res, rsp.output)
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
-elif isinstance(rsp, wireproto.pusherr):
+elif isinstance(rsp, wireprototypes.pusherr):
 # This is the httplib workaround documented in _handlehttperror().
 req.drain()
 
 rsp = '0\n%s\n' % rsp.res
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
-elif isinstance(rsp, wireproto.ooberror):
+elif isinstance(rsp, wireprototypes.ooberror):
 rsp = rsp.message
 req.respond(HTTP_OK, HGERRTYPE, body=rsp)
 return []
@@ -409,11 +410,11 @@
 
 _handlers = {
 str: _sendresponse,
-wireproto.streamres: _sendstream,
-wireproto.streamres_legacy: _sendstream,
-wireproto.pushres: _sendpushresponse,
-wireproto.pusherr: _sendpusherror,
-wireproto.ooberror: _sendooberror,
+wireprototypes.streamres: _sendstream,
+wireprototypes.streamreslegacy: _sendstream,
+wireprototypes.pushres: _sendpushresponse,
+wireprototypes.pusherr: _sendpusherror,
+wireprototypes.ooberror: _sendooberror,
 }
 
 def client(self):
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -31,11 +31,18 @@
 repository,
 streamclone,
 util,
+wireprototypes,
 )
 
 urlerr = util.urlerr
 urlreq = util.urlreq
 
+ooberror = wireprototypes.ooberror
+pushres = wireprototypes.pushres
+pusherr = wireprototypes.pusherr
+streamres = wireprototypes.streamres
+streamres_legacy = 

D2089: wireproto: introduce type for raw byte responses (API)

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5325.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2089?vs=5323=5325

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

AFFECTED FILES
  hgext/largefiles/proto.py
  mercurial/wireproto.py
  mercurial/wireprotoserver.py
  mercurial/wireprototypes.py
  tests/sshprotoext.py
  tests/test-wireproto.py

CHANGE DETAILS

diff --git a/tests/test-wireproto.py b/tests/test-wireproto.py
--- a/tests/test-wireproto.py
+++ b/tests/test-wireproto.py
@@ -1,8 +1,10 @@
 from __future__ import absolute_import, print_function
 
 from mercurial import (
+error,
 util,
 wireproto,
+wireprototypes,
 )
 stringio = util.stringio
 
@@ -42,7 +44,13 @@
 return ['batch']
 
 def _call(self, cmd, **args):
-return wireproto.dispatch(self.serverrepo, proto(args), cmd)
+res = wireproto.dispatch(self.serverrepo, proto(args), cmd)
+if isinstance(res, wireprototypes.bytesresponse):
+return res.data
+elif isinstance(res, bytes):
+return res
+else:
+raise error.Abort('dummy client does not support response type')
 
 def _callstream(self, cmd, **args):
 return stringio(self._call(cmd, **args))
diff --git a/tests/sshprotoext.py b/tests/sshprotoext.py
--- a/tests/sshprotoext.py
+++ b/tests/sshprotoext.py
@@ -74,7 +74,7 @@
 # Send the upgrade response.
 self._fout.write(b'upgraded %s %s\n' % (token, name))
 servercaps = wireproto.capabilities(self._repo, self._proto)
-rsp = b'capabilities: %s' % servercaps
+rsp = b'capabilities: %s' % servercaps.data
 self._fout.write(b'%d\n' % len(rsp))
 self._fout.write(rsp)
 self._fout.write(b'\n')
diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py
--- a/mercurial/wireprototypes.py
+++ b/mercurial/wireprototypes.py
@@ -5,6 +5,11 @@
 
 from __future__ import absolute_import
 
+class bytesresponse(object):
+"""A wire protocol response consisting of raw bytes."""
+def __init__(self, data):
+self.data = data
+
 class ooberror(object):
 """wireproto reply: failure of a batch of operation
 
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -274,6 +274,9 @@
 if isinstance(rsp, bytes):
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
+elif isinstance(rsp, wireprototypes.bytesresponse):
+req.respond(HTTP_OK, HGTYPE, body=rsp.data)
+return []
 elif isinstance(rsp, wireprototypes.streamreslegacy):
 gen = rsp.gen
 req.respond(HTTP_OK, HGTYPE)
@@ -389,6 +392,9 @@
 self._fout.write(v)
 self._fout.flush()
 
+def _sendbytes(self, v):
+self._sendresponse(v.data)
+
 def _sendstream(self, source):
 write = self._fout.write
 for chunk in source.gen:
@@ -409,7 +415,8 @@
 self._fout.flush()
 
 _handlers = {
-str: _sendresponse,
+bytes: _sendresponse,
+wireprototypes.bytesresponse: _sendbytes,
 wireprototypes.streamres: _sendstream,
 wireprototypes.streamreslegacy: _sendstream,
 wireprototypes.pushres: _sendpushresponse,
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -37,6 +37,7 @@
 urlerr = util.urlerr
 urlreq = util.urlreq
 
+bytesresponse = wireprototypes.bytesresponse
 ooberror = wireprototypes.ooberror
 pushres = wireprototypes.pushres
 pusherr = wireprototypes.pusherr
@@ -696,16 +697,24 @@
 result = func(repo, proto)
 if isinstance(result, ooberror):
 return result
+
+# For now, all batchable commands must return bytesresponse or
+# raw bytes (for backwards compatibility).
+assert isinstance(result, (bytesresponse, bytes))
+if isinstance(result, bytesresponse):
+result = result.data
 res.append(escapearg(result))
-return ';'.join(res)
+
+return bytesresponse(';'.join(res))
 
 @wireprotocommand('between', 'pairs')
 def between(repo, proto, pairs):
 pairs = [decodelist(p, '-') for p in pairs.split(" ")]
 r = []
 for b in repo.between(pairs):
 r.append(encodelist(b) + "\n")
-return "".join(r)
+
+return bytesresponse(''.join(r))
 
 @wireprotocommand('branchmap')
 def branchmap(repo, proto):
@@ -715,15 +724,17 @@
 branchname = urlreq.quote(encoding.fromlocal(branch))
 branchnodes = encodelist(nodes)
 heads.append('%s %s' % (branchname, branchnodes))
-return '\n'.join(heads)
+
+return bytesresponse('\n'.join(heads))
 
 @wireprotocommand('branches', 'nodes')
 def branches(repo, proto, nodes):
 nodes = decodelist(nodes)
 r = []
 for b in repo.branches(nodes):
 r.append(encodelist(b) + "\n")
-return "".join(r)
+
+return 

D2088: wireprototypes: move wire protocol response types to new module

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

REVISION SUMMARY
  We'll be introducing more types as part of wire protocol version 2.
  These types are shared between the command handling code (in
  wireproto.py) and the protocol/transport code in wireprotoserver.py.
  So they need to go in a new module to prevent a cycle.
  
  The types are aliased into the wireproto module, so API compatibility
  is preserved.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py
  mercurial/wireprototypes.py

CHANGE DETAILS

diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py
new file mode 100644
--- /dev/null
+++ b/mercurial/wireprototypes.py
@@ -0,0 +1,61 @@
+# 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
+
+class ooberror(object):
+"""wireproto reply: failure of a batch of operation
+
+Something failed during a batch call. The error message is stored in
+`self.message`.
+"""
+def __init__(self, message):
+self.message = message
+
+class pushres(object):
+"""wireproto reply: success with simple integer return
+
+The call was successful and returned an integer contained in `self.res`.
+"""
+def __init__(self, res, output):
+self.res = res
+self.output = output
+
+class pusherr(object):
+"""wireproto reply: failure
+
+The call failed. The `self.res` attribute contains the error message.
+"""
+def __init__(self, res, output):
+self.res = res
+self.output = output
+
+class streamres(object):
+"""wireproto reply: binary stream
+
+The call was successful and the result is a stream.
+
+Accepts a generator containing chunks of data to be sent to the client.
+
+``prefer_uncompressed`` indicates that the data is expected to be
+uncompressable and that the stream should therefore use the ``none``
+engine.
+"""
+def __init__(self, gen=None, prefer_uncompressed=False):
+self.gen = gen
+self.prefer_uncompressed = prefer_uncompressed
+
+class streamreslegacy(object):
+"""wireproto reply: uncompressed binary stream
+
+The call was successful and the result is a stream.
+
+Accepts a generator containing chunks of data to be sent to the client.
+
+Like ``streamres``, but sends an uncompressed data for "version 1" clients
+using the application/mercurial-0.1 media type.
+"""
+def __init__(self, gen=None):
+self.gen = gen
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -20,6 +20,7 @@
 pycompat,
 util,
 wireproto,
+wireprototypes,
 )
 
 stringio = util.stringio
@@ -273,11 +274,11 @@
 if isinstance(rsp, bytes):
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
-elif isinstance(rsp, wireproto.streamres_legacy):
+elif isinstance(rsp, wireprototypes.streamres_legacy):
 gen = rsp.gen
 req.respond(HTTP_OK, HGTYPE)
 return gen
-elif isinstance(rsp, wireproto.streamres):
+elif isinstance(rsp, wireprototypes.streamres):
 gen = rsp.gen
 
 # This code for compression should not be streamres specific. It
@@ -291,18 +292,18 @@
 
 req.respond(HTTP_OK, mediatype)
 return gen
-elif isinstance(rsp, wireproto.pushres):
+elif isinstance(rsp, wireprototypes.pushres):
 rsp = '%d\n%s' % (rsp.res, rsp.output)
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
-elif isinstance(rsp, wireproto.pusherr):
+elif isinstance(rsp, wireprototypes.pusherr):
 # This is the httplib workaround documented in _handlehttperror().
 req.drain()
 
 rsp = '0\n%s\n' % rsp.res
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
-elif isinstance(rsp, wireproto.ooberror):
+elif isinstance(rsp, wireprototypes.ooberror):
 rsp = rsp.message
 req.respond(HTTP_OK, HGERRTYPE, body=rsp)
 return []
@@ -409,11 +410,11 @@
 
 _handlers = {
 str: _sendresponse,
-wireproto.streamres: _sendstream,
-wireproto.streamres_legacy: _sendstream,
-wireproto.pushres: _sendpushresponse,
-wireproto.pusherr: _sendpusherror,
-wireproto.ooberror: _sendooberror,
+wireprototypes.streamres: _sendstream,
+wireprototypes.streamres_legacy: _sendstream,
+wireprototypes.pushres: _sendpushresponse,
+wireprototypes.pusherr: _sendpusherror,
+wireprototypes.ooberror: _sendooberror,
 }
 
 def client(self):
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py

D2086: wireproto: remove unused proto argument from supportedcompengines

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

REVISION SUMMARY
  In theory, the protocol should be passed to this function. But the
  argument isn't being used and it is getting in the way of refactoring.
  So let's remove it. We can always add it back later if we need it
  again.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -192,7 +192,7 @@
 break
 
 # Now find an agreed upon compression format.
-for engine in wireproto.supportedcompengines(self._ui, self,
+for engine in wireproto.supportedcompengines(self._ui,
  util.SERVERROLE):
 if engine.wireprotosupport().name in compformats:
 opts = {}
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -587,7 +587,7 @@
 
 return ui.configbool('server', 'bundle1')
 
-def supportedcompengines(ui, proto, role):
+def supportedcompengines(ui, role):
 """Obtain the list of supported compression engines for a request."""
 assert role in (util.CLIENTROLE, util.SERVERROLE)
 
@@ -824,7 +824,7 @@
 # FUTURE advertise minrx and mintx after consulting config option
 caps.append('httpmediatype=0.1rx,0.1tx,0.2tx')
 
-compengines = supportedcompengines(repo.ui, proto, util.SERVERROLE)
+compengines = supportedcompengines(repo.ui, util.SERVERROLE)
 if compengines:
 comptypes = ','.join(urlreq.quote(e.wireprotosupport().name)
  for e in compengines)



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


D2089: wireproto: introduce type for raw byte responses (API)

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

REVISION SUMMARY
  Right now we simply return a str/bytes instance for simple
  responses. I want all wire protocol response types to be strongly
  typed. So let's invent and use a type for raw bytes responses.
  
  While I was here, I also switched a `str` to `bytes` in the
  ssh protocol handler. That should make Python 3 a bit happier.
  
  .. api::
  
Wire protocol command handlers now return a
wireprototypes.bytesresponse instead of a raw bytes instance.
Protocol handlers will continue handling bytes instances. However,
any extensions wrapping wire protocol commands will need to handle
the new type.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  hgext/largefiles/proto.py
  mercurial/wireproto.py
  mercurial/wireprotoserver.py
  mercurial/wireprototypes.py
  tests/sshprotoext.py
  tests/test-wireproto.py

CHANGE DETAILS

diff --git a/tests/test-wireproto.py b/tests/test-wireproto.py
--- a/tests/test-wireproto.py
+++ b/tests/test-wireproto.py
@@ -1,8 +1,10 @@
 from __future__ import absolute_import, print_function
 
 from mercurial import (
+error,
 util,
 wireproto,
+wireprototypes,
 )
 stringio = util.stringio
 
@@ -42,7 +44,13 @@
 return ['batch']
 
 def _call(self, cmd, **args):
-return wireproto.dispatch(self.serverrepo, proto(args), cmd)
+res = wireproto.dispatch(self.serverrepo, proto(args), cmd)
+if isinstance(res, wireprototypes.bytesresponse):
+return res.data
+elif isinstance(res, bytes):
+return res
+else:
+raise error.Abort('dummy client does not support response type')
 
 def _callstream(self, cmd, **args):
 return stringio(self._call(cmd, **args))
diff --git a/tests/sshprotoext.py b/tests/sshprotoext.py
--- a/tests/sshprotoext.py
+++ b/tests/sshprotoext.py
@@ -74,7 +74,7 @@
 # Send the upgrade response.
 self._fout.write(b'upgraded %s %s\n' % (token, name))
 servercaps = wireproto.capabilities(self._repo, self._proto)
-rsp = b'capabilities: %s' % servercaps
+rsp = b'capabilities: %s' % servercaps.data
 self._fout.write(b'%d\n' % len(rsp))
 self._fout.write(rsp)
 self._fout.write(b'\n')
diff --git a/mercurial/wireprototypes.py b/mercurial/wireprototypes.py
--- a/mercurial/wireprototypes.py
+++ b/mercurial/wireprototypes.py
@@ -5,6 +5,11 @@
 
 from __future__ import absolute_import
 
+class bytesresponse(object):
+"""A wire protocol response consisting of raw bytes."""
+def __init__(self, data):
+self.data = data
+
 class ooberror(object):
 """wireproto reply: failure of a batch of operation
 
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -274,6 +274,9 @@
 if isinstance(rsp, bytes):
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
+elif isinstance(rsp, wireprototypes.bytesresponse):
+req.respond(HTTP_OK, HGTYPE, body=rsp.data)
+return []
 elif isinstance(rsp, wireprototypes.streamres_legacy):
 gen = rsp.gen
 req.respond(HTTP_OK, HGTYPE)
@@ -389,6 +392,9 @@
 self._fout.write(v)
 self._fout.flush()
 
+def _sendbytes(self, v):
+self._sendresponse(v.data)
+
 def _sendstream(self, source):
 write = self._fout.write
 for chunk in source.gen:
@@ -409,7 +415,8 @@
 self._fout.flush()
 
 _handlers = {
-str: _sendresponse,
+bytes: _sendresponse,
+wireprototypes.bytesresponse: _sendbytes,
 wireprototypes.streamres: _sendstream,
 wireprototypes.streamres_legacy: _sendstream,
 wireprototypes.pushres: _sendpushresponse,
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -37,6 +37,7 @@
 urlerr = util.urlerr
 urlreq = util.urlreq
 
+bytesresponse = wireprototypes.bytesresponse
 ooberror = wireprototypes.ooberror
 pushres = wireprototypes.pushres
 pusherr = wireprototypes.pusherr
@@ -696,16 +697,24 @@
 result = func(repo, proto)
 if isinstance(result, ooberror):
 return result
+
+# For now, all batchable commands must return bytesresponse or
+# raw bytes (for backwards compatibility).
+assert isinstance(result, (bytesresponse, bytes))
+if isinstance(result, bytesresponse):
+result = result.data
 res.append(escapearg(result))
-return ';'.join(res)
+
+return bytesresponse(';'.join(res))
 
 @wireprotocommand('between', 'pairs')
 def between(repo, proto, pairs):
 pairs = [decodelist(p, '-') for p in pairs.split(" ")]
 r = []
 for b in repo.between(pairs):
 r.append(encodelist(b) + 

D2084: wireprotoserver: rename _client to client (API)

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

REVISION SUMMARY
  This method is called in wireproto.py. It should be part of the public
  API.
  
  .. api::
  
The ``_client()`` method of the wire protocol handler interface has
been renamed to ``client()``.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -88,6 +88,10 @@
 won't be captured.
 """
 
+@abc.abstractmethod
+def client(self):
+"""Returns a string representation of this client (as bytes)."""
+
 def decodevaluefromheaders(req, headerprefix):
 """Decode a long value from multiple HTTP request headers.
 
@@ -164,7 +168,7 @@
 self._ui.fout = oldout
 self._ui.ferr = olderr
 
-def _client(self):
+def client(self):
 return 'remote:%s:%s:%s' % (
 self._req.env.get('wsgi.url_scheme') or 'http',
 urlreq.quote(self._req.env.get('REMOTE_HOST', '')),
@@ -413,7 +417,7 @@
 wireproto.ooberror: _sendooberror,
 }
 
-def _client(self):
+def client(self):
 client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
 return 'remote:ssh:' + client
 
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -1023,7 +1023,7 @@
   hint=bundle2requiredhint)
 
 r = exchange.unbundle(repo, gen, their_heads, 'serve',
-  proto._client())
+  proto.client())
 if util.safehasattr(r, 'addpart'):
 # The return looks streamable, we are in the bundle2 case
 # and should return a stream.



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


D2083: wireprotoserver: remove redirect() and restore() (API)

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

REVISION SUMMARY
  They are no longer used in core.
  
  .. api::
  
redirect() and restore() have been removed from the wire protocol
handler interface. Use mayberedirectstdio() instead.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -88,23 +88,6 @@
 won't be captured.
 """
 
-@abc.abstractmethod
-def redirect(self):
-"""may setup interception for stdout and stderr
-
-See also the `restore` method."""
-
-# If the `redirect` function does install interception, the `restore`
-# function MUST be defined. If interception is not used, this function
-# MUST NOT be defined.
-#
-# left commented here on purpose
-#
-#def restore(self):
-#"""reinstall previous stdout and stderr and return intercepted stdout
-#"""
-#raise NotImplementedError()
-
 def decodevaluefromheaders(req, headerprefix):
 """Decode a long value from multiple HTTP request headers.
 
@@ -181,15 +164,6 @@
 self._ui.fout = oldout
 self._ui.ferr = olderr
 
-def redirect(self):
-self._oldio = self._ui.fout, self._ui.ferr
-self._ui.ferr = self._ui.fout = stringio()
-
-def restore(self):
-val = self._ui.fout.getvalue()
-self._ui.ferr, self._ui.fout = self._oldio
-return val
-
 def _client(self):
 return 'remote:%s:%s:%s' % (
 self._req.env.get('wsgi.url_scheme') or 'http',
@@ -406,9 +380,6 @@
 def mayberedirectstdio(self):
 yield None
 
-def redirect(self):
-pass
-
 def _sendresponse(self, v):
 self._fout.write("%d\n" % len(v))
 self._fout.write(v)



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


D2085: wireprotoserver: rename getfile() to forwardpayload() (API)

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

REVISION SUMMARY
  "file" can mean a lot of things. Let's rename the interface
  method to something more descriptive.
  
  While I was here, I moved the docs about the payload format to
  the implementation of the SSH protocol, because it was lying
  about what the HTTP payload looked like.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  hgext/largefiles/proto.py
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -64,14 +64,10 @@
 returns a list of values (same order as )"""
 
 @abc.abstractmethod
-def getfile(self, fp):
-"""write the whole content of a file into a file like object
+def forwardpayload(self, fp):
+"""Read the raw payload and forward to a file.
 
-The file is in the form::
-
-(\n)+0\n
-
-chunk size is the ascii version of the int.
+The payload is read in full before the function returns.
 """
 
 @abc.abstractmethod
@@ -145,7 +141,7 @@
 args.update(cgi.parse_qs(argvalue, keep_blank_values=True))
 return args
 
-def getfile(self, fp):
+def forwardpayload(self, fp):
 length = int(self._req.env[r'CONTENT_LENGTH'])
 # If httppostargs is used, we need to read Content-Length
 # minus the amount that was consumed by args.
@@ -373,7 +369,12 @@
 data[arg] = val
 return [data[k] for k in keys]
 
-def getfile(self, fpout):
+def forwardpayload(self, fpout):
+# The file is in the form:
+#
+# \n
+# ...
+# 0\n
 self._sendresponse('')
 count = int(self._fin.readline())
 while count:
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -1008,7 +1008,7 @@
 fp = os.fdopen(fd, pycompat.sysstr('wb+'))
 r = 0
 try:
-proto.getfile(fp)
+proto.forwardpayload(fp)
 fp.seek(0)
 gen = exchange.readbundle(repo.ui, fp, None)
 if (isinstance(gen, changegroupmod.cg1unpacker)
diff --git a/hgext/largefiles/proto.py b/hgext/largefiles/proto.py
--- a/hgext/largefiles/proto.py
+++ b/hgext/largefiles/proto.py
@@ -40,7 +40,7 @@
 tmpfp = util.atomictempfile(path, createmode=repo.store.createmode)
 
 try:
-proto.getfile(tmpfp)
+proto.forwardpayload(tmpfp)
 tmpfp._fp.seek(0)
 if sha != lfutil.hexsha1(tmpfp._fp):
 raise IOError(0, _('largefile contents do not match hash'))



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


D2087: wireprotoserver: move responsetype() out of http handler

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

REVISION SUMMARY
  This is our last public attribute not part of the protocol
  interface!

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -170,48 +170,6 @@
 urlreq.quote(self._req.env.get('REMOTE_HOST', '')),
 urlreq.quote(self._req.env.get('REMOTE_USER', '')))
 
-def responsetype(self, prefer_uncompressed):
-"""Determine the appropriate response type and compression settings.
-
-Returns a tuple of (mediatype, compengine, engineopts).
-"""
-# Determine the response media type and compression engine based
-# on the request parameters.
-protocaps = decodevaluefromheaders(self._req, r'X-HgProto').split(' ')
-
-if '0.2' in protocaps:
-# All clients are expected to support uncompressed data.
-if prefer_uncompressed:
-return HGTYPE2, util._noopengine(), {}
-
-# Default as defined by wire protocol spec.
-compformats = ['zlib', 'none']
-for cap in protocaps:
-if cap.startswith('comp='):
-compformats = cap[5:].split(',')
-break
-
-# Now find an agreed upon compression format.
-for engine in wireproto.supportedcompengines(self._ui,
- util.SERVERROLE):
-if engine.wireprotosupport().name in compformats:
-opts = {}
-level = self._ui.configint('server',
-  '%slevel' % engine.name())
-if level is not None:
-opts['level'] = level
-
-return HGTYPE2, engine, opts
-
-# No mutually supported compression format. Fall back to the
-# legacy protocol.
-
-# Don't allow untrusted settings because disabling compression or
-# setting a very high compression level could lead to flooding
-# the server's network or CPU.
-opts = {'level': self._ui.configint('server', 'zliblevel')}
-return HGTYPE, util.compengines['zlib'], opts
-
 def iscmd(cmd):
 return cmd in wireproto.commands
 
@@ -252,6 +210,46 @@
 'handleerror': lambda ex: _handlehttperror(ex, req, cmd),
 }
 
+def _httpresponsetype(ui, req, prefer_uncompressed):
+"""Determine the appropriate response type and compression settings.
+
+Returns a tuple of (mediatype, compengine, engineopts).
+"""
+# Determine the response media type and compression engine based
+# on the request parameters.
+protocaps = decodevaluefromheaders(req, r'X-HgProto').split(' ')
+
+if '0.2' in protocaps:
+# All clients are expected to support uncompressed data.
+if prefer_uncompressed:
+return HGTYPE2, util._noopengine(), {}
+
+# Default as defined by wire protocol spec.
+compformats = ['zlib', 'none']
+for cap in protocaps:
+if cap.startswith('comp='):
+compformats = cap[5:].split(',')
+break
+
+# Now find an agreed upon compression format.
+for engine in wireproto.supportedcompengines(ui, util.SERVERROLE):
+if engine.wireprotosupport().name in compformats:
+opts = {}
+level = ui.configint('server', '%slevel' % engine.name())
+if level is not None:
+opts['level'] = level
+
+return HGTYPE2, engine, opts
+
+# No mutually supported compression format. Fall back to the
+# legacy protocol.
+
+# Don't allow untrusted settings because disabling compression or
+# setting a very high compression level could lead to flooding
+# the server's network or CPU.
+opts = {'level': ui.configint('server', 'zliblevel')}
+return HGTYPE, util.compengines['zlib'], opts
+
 def _callhttp(repo, req, proto, cmd):
 def genversion2(gen, engine, engineopts):
 # application/mercurial-0.2 always sends a payload header
@@ -284,8 +282,8 @@
 
 # This code for compression should not be streamres specific. It
 # is here because we only compress streamres at the moment.
-mediatype, engine, engineopts = proto.responsetype(
-rsp.prefer_uncompressed)
+mediatype, engine, engineopts = _httpresponsetype(
+repo.ui, req, rsp.prefer_uncompressed)
 gen = engine.compressstream(gen, engineopts)
 
 if mediatype == HGTYPE2:



To: indygreg, #hg-reviewers
Cc: mercurial-devel
___

D2082: wireproto: use maybecapturestdio() for push responses (API)

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

REVISION SUMMARY
  The "pushres" and "pusherr" response types currently call
  proto.restore() in the HTTP protocol. This completes the pairing
  with proto.redirect() that occurs in the @wireprotocommand
  functions. (But since the SSH protocol has a no-op redirect(),
  it doesn't bother calling restore() because it would also be
  a no-op.)
  
  Having the disconnect between these paired calls is very confusing.
  Knowing that you must use proto.redirect() if returning a "pushres"
  or a "pusherr" is even wonkier.
  
  We replace this confusing code with our new context manager for
  capturing output (maybe).
  
  The "pushres" and "pusherr" types have gained an "output" argument
  to their constructor and an attribute to hold captured data. The
  HTTP protocol now retrieves output from these objects.
  
  .. api::
  
``wireproto.pushres`` and ``wireproto.pusherr`` now explicitly
track stdio output.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  hgext/largefiles/proto.py
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -320,15 +320,13 @@
 req.respond(HTTP_OK, mediatype)
 return gen
 elif isinstance(rsp, wireproto.pushres):
-val = proto.restore()
-rsp = '%d\n%s' % (rsp.res, val)
+rsp = '%d\n%s' % (rsp.res, rsp.output)
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
 elif isinstance(rsp, wireproto.pusherr):
 # This is the httplib workaround documented in _handlehttperror().
 req.drain()
 
-proto.restore()
 rsp = '0\n%s\n' % rsp.res
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -510,16 +510,18 @@
 
 The call was successful and returned an integer contained in `self.res`.
 """
-def __init__(self, res):
+def __init__(self, res, output):
 self.res = res
+self.output = output
 
 class pusherr(object):
 """wireproto reply: failure
 
 The call failed. The `self.res` attribute contains the error message.
 """
-def __init__(self, res):
+def __init__(self, res, output):
 self.res = res
+self.output = output
 
 class ooberror(object):
 """wireproto reply: failure of a batch of operation
@@ -997,97 +999,98 @@
 def unbundle(repo, proto, heads):
 their_heads = decodelist(heads)
 
-try:
-proto.redirect()
-
-exchange.check_heads(repo, their_heads, 'preparing changes')
-
-# write bundle data to temporary file because it can be big
-fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
-fp = os.fdopen(fd, pycompat.sysstr('wb+'))
-r = 0
+with proto.mayberedirectstdio() as output:
 try:
-proto.getfile(fp)
-fp.seek(0)
-gen = exchange.readbundle(repo.ui, fp, None)
-if (isinstance(gen, changegroupmod.cg1unpacker)
-and not bundle1allowed(repo, 'push')):
-if proto.name == 'http':
-# need to special case http because stderr do not get to
-# the http client on failed push so we need to abuse some
-# other error type to make sure the message get to the
-# user.
-return ooberror(bundle2required)
-raise error.Abort(bundle2requiredmain,
-  hint=bundle2requiredhint)
+exchange.check_heads(repo, their_heads, 'preparing changes')
 
-r = exchange.unbundle(repo, gen, their_heads, 'serve',
-  proto._client())
-if util.safehasattr(r, 'addpart'):
-# The return looks streamable, we are in the bundle2 case and
-# should return a stream.
-return streamres_legacy(gen=r.getchunks())
-return pushres(r)
-
-finally:
-fp.close()
-os.unlink(tempname)
-
-except (error.BundleValueError, error.Abort, error.PushRaced) as exc:
-# handle non-bundle2 case first
-if not getattr(exc, 'duringunbundle2', False):
+# write bundle data to temporary file because it can be big
+fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
+fp = os.fdopen(fd, pycompat.sysstr('wb+'))
+r = 0
 try:
-raise
-except error.Abort:
-# The old code we moved used util.stderr directly.
-# We did not change it to minimise code change.
-# 

D2081: wireprotoserver: add context manager mechanism for redirecting stdio

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

REVISION SUMMARY
  Today, proto.redirect() sets up redirecting stdio and proto.restore()
  undoes that. The API is a bit wonky because restore() is only
  implemented on the HTTP protocol. Furthermore, not all calls to
  redirect() are obviously paired with calls to restore(). For
  example, the call to restore() for "unbundle" requests is handled
  by the response handler for the HTTP protocol.
  
  This commit introduces a new method on the protocol handler interface
  to maybe capture stdio. It emits a file object or None depending on
  whether stdio capture is used by the transport.
  
  To prove it works, the "pushkey" wire protocol command has been
  updated to use the new API.
  
  I'm not convinced this is the best mechanism to capture stdio. I may
  need to come up with something better once the new wire protocol
  emerges into existence. But it is strictly better than before and
  gets us closer to a unified interface between the SSH and HTTP
  transports.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -8,6 +8,7 @@
 
 import abc
 import cgi
+import contextlib
 import struct
 import sys
 
@@ -74,6 +75,20 @@
 """
 
 @abc.abstractmethod
+def mayberedirectstdio(self):
+"""Context manager to possibly redirect stdio.
+
+The context manager yields a file-object like object that receives
+stdout and stderr output when the context manager is active. Or it
+yields ``None`` if no I/O redirection occurs.
+
+The intent of this context manager is to capture stdio output
+so it may be sent in the response. Some transports support streaming
+stdio to the client in real time. For these transports, stdio output
+won't be captured.
+"""
+
+@abc.abstractmethod
 def redirect(self):
 """may setup interception for stdout and stderr
 
@@ -151,6 +166,21 @@
 for s in util.filechunkiter(self._req, limit=length):
 fp.write(s)
 
+@contextlib.contextmanager
+def mayberedirectstdio(self):
+oldout = self._ui.fout
+olderr = self._ui.ferr
+
+out = util.stringio()
+
+try:
+self._ui.fout = out
+self._ui.ferr = out
+yield out
+finally:
+self._ui.fout = oldout
+self._ui.ferr = olderr
+
 def redirect(self):
 self._oldio = self._ui.fout, self._ui.ferr
 self._ui.ferr = self._ui.fout = stringio()
@@ -374,6 +404,10 @@
 fpout.write(self._fin.read(count))
 count = int(self._fin.readline())
 
+@contextlib.contextmanager
+def mayberedirectstdio(self):
+yield None
+
 def redirect(self):
 pass
 
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -978,20 +978,12 @@
 else:
 new = encoding.tolocal(new) # normal path
 
-if util.safehasattr(proto, 'restore'):
-
-proto.redirect()
-
+with proto.mayberedirectstdio() as output:
 r = repo.pushkey(encoding.tolocal(namespace), encoding.tolocal(key),
  encoding.tolocal(old), new) or False
 
-output = proto.restore()
-
-return '%s\n%s' % (int(r), output)
-
-r = repo.pushkey(encoding.tolocal(namespace), encoding.tolocal(key),
- encoding.tolocal(old), new)
-return '%s\n' % int(r)
+output = output.getvalue() if output else ''
+return '%s\n%s' % (int(r), output)
 
 @wireprotocommand('stream_out')
 def stream(repo, proto):



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


D2080: wireprotoserver: split ssh protocol handler and server

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

REVISION SUMMARY
  We want to formalize the interface for protocol handlers. Today,
  server functionality (which is domain specific) is interleaved
  with protocol handling functionality (which conforms to a generic
  interface) in the sshserver class.
  
  This commit splits the ssh protocol handling code out of the
  sshserver class.
  
  The state of the new code isn't great in terms of purity: there
  are still some private attribute accesses from sshserver into
  sshprotocolhandler that shouldn't be there. This will likely
  require some interface changes to address. I'm not yet sure how
  to reconcile things. But this split seems strictly better in
  terms of isolating the wire protocol interface from the rest of
  the code.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/wireprotoserver.py
  tests/sshprotoext.py
  tests/test-sshserver.py

CHANGE DETAILS

diff --git a/tests/test-sshserver.py b/tests/test-sshserver.py
--- a/tests/test-sshserver.py
+++ b/tests/test-sshserver.py
@@ -24,7 +24,7 @@
 def assertparse(self, cmd, input, expected):
 server = mockserver(input)
 _func, spec = wireproto.commands[cmd]
-self.assertEqual(server.getargs(spec), expected)
+self.assertEqual(server._proto.getargs(spec), expected)
 
 def mockserver(inbytes):
 ui = mockui(inbytes)
diff --git a/tests/sshprotoext.py b/tests/sshprotoext.py
--- a/tests/sshprotoext.py
+++ b/tests/sshprotoext.py
@@ -45,11 +45,11 @@
 l = self._fin.readline()
 assert l == b'hello\n'
 # Respond to unknown commands with an empty reply.
-self._sendresponse(b'')
+self._proto._sendresponse(b'')
 l = self._fin.readline()
 assert l == b'between\n'
-rsp = wireproto.dispatch(self._repo, self, b'between')
-self._handlers[rsp.__class__](self, rsp)
+rsp = wireproto.dispatch(self._repo, self._proto, b'between')
+self._proto._handlers[rsp.__class__](self._proto, rsp)
 
 super(prehelloserver, self).serve_forever()
 
@@ -73,7 +73,7 @@
 
 # Send the upgrade response.
 self._fout.write(b'upgraded %s %s\n' % (token, name))
-servercaps = wireproto.capabilities(self._repo, self)
+servercaps = wireproto.capabilities(self._repo, self._proto)
 rsp = b'capabilities: %s' % servercaps
 self._fout.write(b'%d\n' % len(rsp))
 self._fout.write(rsp)
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -336,19 +336,11 @@
 
 return ''
 
-class sshserver(baseprotocolhandler):
-def __init__(self, ui, repo):
+class sshprotocolhandler(baseprotocolhandler):
+def __init__(self, ui, fin, fout):
 self._ui = ui
-self._repo = repo
-self._fin = ui.fin
-self._fout = ui.fout
-
-hook.redirect(True)
-ui.fout = repo.ui.fout = ui.ferr
-
-# Prevent insertion/deletion of CRs
-util.setbinary(self._fin)
-util.setbinary(self._fout)
+self._fin = fin
+self._fout = fout
 
 @property
 def name(self):
@@ -409,11 +401,6 @@
 self._fout.write('\n')
 self._fout.flush()
 
-def serve_forever(self):
-while self.serve_one():
-pass
-sys.exit(0)
-
 _handlers = {
 str: _sendresponse,
 wireproto.streamres: _sendstream,
@@ -423,15 +410,38 @@
 wireproto.ooberror: _sendooberror,
 }
 
-def serve_one(self):
-cmd = self._fin.readline()[:-1]
-if cmd and wireproto.commands.commandavailable(cmd, self):
-rsp = wireproto.dispatch(self._repo, self, cmd)
-self._handlers[rsp.__class__](self, rsp)
-elif cmd:
-self._sendresponse("")
-return cmd != ''
-
 def _client(self):
 client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
 return 'remote:ssh:' + client
+
+class sshserver(object):
+def __init__(self, ui, repo):
+self._ui = ui
+self._repo = repo
+self._fin = ui.fin
+self._fout = ui.fout
+
+hook.redirect(True)
+ui.fout = repo.ui.fout = ui.ferr
+
+# Prevent insertion/deletion of CRs
+util.setbinary(self._fin)
+util.setbinary(self._fout)
+
+self._proto = sshprotocolhandler(self._ui, self._fin, self._fout)
+
+def serve_forever(self):
+while self.serve_one():
+pass
+sys.exit(0)
+
+def serve_one(self):
+# TODO improve boundary between transport layer and protocol handler.
+cmd = self._fin.readline()[:-1]
+if cmd and wireproto.commands.commandavailable(cmd, self._proto):
+rsp = wireproto.dispatch(self._repo, self._proto, cmd)
+

D2065: wireprotoserver: rename abstractserverproto and improve docstring

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG04231e893a12: wireprotoserver: rename abstractserverproto 
and improve docstring (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2065?vs=5299=5313

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

AFFECTED FILES
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -38,10 +38,13 @@
 # to reflect BC breakages.
 SSHV2 = 'exp-ssh-v2-0001'
 
-class abstractserverproto(object):
-"""abstract class that summarizes the protocol API
+class baseprotocolhandler(object):
+"""Abstract base class for wire protocol handlers.
 
-Used as reference and documentation.
+A wire protocol handler serves as an interface between protocol command
+handlers and the wire protocol transport layer. Protocol handlers provide
+methods to read command arguments, redirect stdio for the duration of
+the request, handle response types, etc.
 """
 
 __metaclass__ = abc.ABCMeta
@@ -104,7 +107,7 @@
 
 return ''.join(chunks)
 
-class webproto(abstractserverproto):
+class webproto(baseprotocolhandler):
 def __init__(self, req, ui):
 self._req = req
 self._ui = ui
@@ -333,7 +336,7 @@
 
 return ''
 
-class sshserver(abstractserverproto):
+class sshserver(baseprotocolhandler):
 def __init__(self, ui, repo):
 self._ui = ui
 self._repo = repo



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


D2018: largefiles: register wire protocol commands with modern APIs

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGf540b6448738: largefiles: register wire protocol commands 
with modern APIs (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2018?vs=5172=5308

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

AFFECTED FILES
  hgext/largefiles/uisetup.py

CHANGE DETAILS

diff --git a/hgext/largefiles/uisetup.py b/hgext/largefiles/uisetup.py
--- a/hgext/largefiles/uisetup.py
+++ b/hgext/largefiles/uisetup.py
@@ -165,13 +165,13 @@
 overrides.openlargefile)
 
 # create the new wireproto commands ...
-wireproto.commands['putlfile'] = (proto.putlfile, 'sha')
-wireproto.commands['getlfile'] = (proto.getlfile, 'sha')
-wireproto.commands['statlfile'] = (proto.statlfile, 'sha')
+wireproto.wireprotocommand('putlfile', 'sha')(proto.putlfile)
+wireproto.wireprotocommand('getlfile', 'sha')(proto.getlfile)
+wireproto.wireprotocommand('statlfile', 'sha')(proto.statlfile)
+wireproto.wireprotocommand('lheads', '')(wireproto.heads)
 
 # ... and wrap some existing ones
-wireproto.commands['heads'] = (proto.heads, '')
-wireproto.commands['lheads'] = (wireproto.heads, '')
+wireproto.commands['heads'].func = proto.heads
 
 # make putlfile behave the same as push and {get,stat}lfile behave
 # the same as pull w.r.t. permissions checks



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


D1999: wireproto: function for testing if wire protocol command is available

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG5a56bf4180ad: wireproto: function for testing if wire 
protocol command is available (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D1999?vs=5258=5307

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

AFFECTED FILES
  mercurial/hgweb/hgweb_mod.py
  mercurial/wireproto.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -223,6 +223,13 @@
 yield chunk
 
 rsp = wireproto.dispatch(repo, proto, cmd)
+
+if not wireproto.commands.commandavailable(cmd, proto):
+req.respond(HTTP_OK, HGERRTYPE,
+body=_('requested wire protocol command is not available '
+   'over HTTP'))
+return []
+
 if isinstance(rsp, bytes):
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
@@ -351,7 +358,7 @@
 
 def serve_one(self):
 cmd = self._fin.readline()[:-1]
-if cmd and cmd in wireproto.commands:
+if cmd and wireproto.commands.commandavailable(cmd, self):
 rsp = wireproto.dispatch(self._repo, self, cmd)
 self._handlers[rsp.__class__](self, rsp)
 elif cmd:
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -691,6 +691,12 @@
 
 return super(commanddict, self).__setitem__(k, v)
 
+def commandavailable(self, command, proto):
+"""Determine if a command is available for the requested protocol."""
+# For now, commands are available for all protocols. So do a simple
+# membership test.
+return command in self
+
 commands = commanddict()
 
 def wireprotocommand(name, args=''):
diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -357,6 +357,14 @@
 query = req.env[r'QUERY_STRING'].partition(r'&')[0]
 query = query.partition(r';')[0]
 
+# The ``cmd`` request parameter is used by both the wire protocol
+# and hgweb. We route all known wire protocol commands to the
+# wire protocol handler, even if the command isn't available for
+# this transport. That's better for machine clients in the case
+# of an errant request to an unavailable protocol command. And it
+# prevents hgweb from accidentally using ``cmd`` values used by
+# the wire protocol.
+
 # process this if it's a protocol request
 # protocol bits don't need to create any URLs
 # and the clients always use the old URL structure



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


D2021: wireprotoserver: move error response handling out of hgweb

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG98a00aa0288d: wireprotoserver: move error response handling 
out of hgweb (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2021?vs=5260=5311

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

AFFECTED FILES
  mercurial/hgweb/hgweb_mod.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -242,6 +242,7 @@
 'cmd': cmd,
 'proto': proto,
 'dispatch': lambda: _callhttp(repo, req, proto, cmd),
+'handleerror': lambda ex: _handlehttperror(ex, req, cmd),
 }
 
 def _callhttp(repo, req, proto, cmd):
@@ -303,6 +304,22 @@
 return []
 raise error.ProgrammingError('hgweb.protocol internal failure', rsp)
 
+def _handlehttperror(e, req, cmd):
+"""Called when an ErrorResponse is raised during HTTP request 
processing."""
+# A client that sends unbundle without 100-continue will
+# break if we respond early.
+if (cmd == 'unbundle' and
+(req.env.get('HTTP_EXPECT',
+ '').lower() != '100-continue') or
+req.env.get('X-HgHttp2', '')):
+req.drain()
+else:
+req.headers.append((r'Connection', r'Close'))
+
+req.respond(e, HGTYPE, body='0\n%s\n' % e)
+
+return ''
+
 class sshserver(abstractserverproto):
 def __init__(self, ui, repo):
 self._ui = ui
diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -369,18 +369,7 @@
 if cmd in perms:
 self.check_perm(rctx, req, perms[cmd])
 except ErrorResponse as inst:
-# A client that sends unbundle without 100-continue will
-# break if we respond early.
-if (cmd == 'unbundle' and
-(req.env.get('HTTP_EXPECT',
- '').lower() != '100-continue') or
-req.env.get('X-HgHttp2', '')):
-req.drain()
-else:
-req.headers.append((r'Connection', r'Close'))
-req.respond(inst, wireprotoserver.HGTYPE,
-body='0\n%s\n' % inst)
-return ''
+return protohandler['handleerror'](inst)
 
 return protohandler['dispatch']()
 



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


D2064: wireprotoserver: document and improve the httplib workaround

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG6010fe1da619: wireprotoserver: document and improve the 
httplib workaround (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2064?vs=5261=5312

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

AFFECTED FILES
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -292,8 +292,9 @@
 req.respond(HTTP_OK, HGTYPE, body=rsp)
 return []
 elif isinstance(rsp, wireproto.pusherr):
-# drain the incoming bundle
+# This is the httplib workaround documented in _handlehttperror().
 req.drain()
+
 proto.restore()
 rsp = '0\n%s\n' % rsp.res
 req.respond(HTTP_OK, HGTYPE, body=rsp)
@@ -306,16 +307,28 @@
 
 def _handlehttperror(e, req, cmd):
 """Called when an ErrorResponse is raised during HTTP request 
processing."""
-# A client that sends unbundle without 100-continue will
-# break if we respond early.
-if (cmd == 'unbundle' and
+
+# Clients using Python's httplib are stateful: the HTTP client
+# won't process an HTTP response until all request data is
+# sent to the server. The intent of this code is to ensure
+# we always read HTTP request data from the client, thus
+# ensuring httplib transitions to a state that allows it to read
+# the HTTP response. In other words, it helps prevent deadlocks
+# on clients using httplib.
+
+if (req.env[r'REQUEST_METHOD'] == r'POST' and
+# But not if Expect: 100-continue is being used.
 (req.env.get('HTTP_EXPECT',
  '').lower() != '100-continue') or
+# Or the non-httplib HTTP library is being advertised by
+# the client.
 req.env.get('X-HgHttp2', '')):
 req.drain()
 else:
 req.headers.append((r'Connection', r'Close'))
 
+# TODO This response body assumes the failed command was
+# "unbundle." That assumption is not always valid.
 req.respond(e, HGTYPE, body='0\n%s\n' % e)
 
 return ''



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


D1996: wireproto: remove unnecessary exception trapping

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGae79cf6f9c82: wireproto: remove unnecessary exception 
trapping (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D1996?vs=5135=5304

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

AFFECTED FILES
  mercurial/wireproto.py

CHANGE DETAILS

diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -914,11 +914,8 @@
 
 proto.redirect()
 
-try:
-r = repo.pushkey(encoding.tolocal(namespace), 
encoding.tolocal(key),
- encoding.tolocal(old), new) or False
-except error.Abort:
-r = False
+r = repo.pushkey(encoding.tolocal(namespace), encoding.tolocal(key),
+ encoding.tolocal(old), new) or False
 
 output = proto.restore()
 



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


D2019: wireprotoserver: move protocol parsing and dispatch out of hgweb

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGcdc93fe1da77: wireprotoserver: move protocol parsing and 
dispatch out of hgweb (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2019?vs=5259=5309

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

AFFECTED FILES
  mercurial/hgweb/hgweb_mod.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -208,9 +208,43 @@
 def iscmd(cmd):
 return cmd in wireproto.commands
 
-def callhttp(repo, req, cmd):
+def parsehttprequest(repo, req, query):
+"""Parse the HTTP request for a wire protocol request.
+
+If the current request appears to be a wire protocol request, this
+function returns a dict with details about that request, including
+an ``abstractprotocolserver`` instance suitable for handling the
+request. Otherwise, ``None`` is returned.
+
+``req`` is a ``wsgirequest`` instance.
+"""
+# HTTP version 1 wire protocol requests are denoted by a "cmd" query
+# string parameter. If it isn't present, this isn't a wire protocol
+# request.
+if r'cmd' not in req.form:
+return None
+
+cmd = pycompat.sysbytes(req.form[r'cmd'][0])
+
+# The "cmd" request parameter is used by both the wire protocol and hgweb.
+# While not all wire protocol commands are available for all transports,
+# if we see a "cmd" value that resembles a known wire protocol command, we
+# route it to a protocol handler. This is better than routing possible
+# wire protocol requests to hgweb because it prevents hgweb from using
+# known wire protocol commands and it is less confusing for machine
+# clients.
+if cmd not in wireproto.commands:
+return None
+
 proto = webproto(req, repo.ui)
 
+return {
+'cmd': cmd,
+'proto': proto,
+'dispatch': lambda: _callhttp(repo, req, proto, cmd),
+}
+
+def _callhttp(repo, req, proto, cmd):
 def genversion2(gen, engine, engineopts):
 # application/mercurial-0.2 always sends a payload header
 # identifying the compression engine.
diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -357,26 +357,18 @@
 query = req.env[r'QUERY_STRING'].partition(r'&')[0]
 query = query.partition(r';')[0]
 
-# The ``cmd`` request parameter is used by both the wire protocol
-# and hgweb. We route all known wire protocol commands to the
-# wire protocol handler, even if the command isn't available for
-# this transport. That's better for machine clients in the case
-# of an errant request to an unavailable protocol command. And it
-# prevents hgweb from accidentally using ``cmd`` values used by
-# the wire protocol.
+# Route it to a wire protocol handler if it looks like a wire protocol
+# request.
+protohandler = wireprotoserver.parsehttprequest(rctx.repo, req, query)
 
-# process this if it's a protocol request
-# protocol bits don't need to create any URLs
-# and the clients always use the old URL structure
-
-cmd = pycompat.sysbytes(req.form.get(r'cmd', [r''])[0])
-if wireprotoserver.iscmd(cmd):
+if protohandler:
+cmd = protohandler['cmd']
 try:
 if query:
 raise ErrorResponse(HTTP_NOT_FOUND)
 if cmd in perms:
 self.check_perm(rctx, req, perms[cmd])
-return wireprotoserver.callhttp(rctx.repo, req, cmd)
+return protohandler['dispatch']()
 except ErrorResponse as inst:
 # A client that sends unbundle without 100-continue will
 # break if we respond early.
@@ -425,6 +417,8 @@
 if fn.endswith(ext):
 req.form['node'] = [fn[:-len(ext)]]
 req.form['type'] = [type_]
+else:
+cmd = pycompat.sysbytes(req.form.get(r'cmd', [r''])[0])
 
 # process the web interface request
 



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


D2061: sshpeer: initial definition and implementation of new SSH protocol

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG48a3a9283f09: sshpeer: initial definition and 
implementation of new SSH protocol (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2061?vs=5255=5301

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

AFFECTED FILES
  mercurial/configitems.py
  mercurial/help/internals/wireprotocol.txt
  mercurial/sshpeer.py
  mercurial/wireprotoserver.py
  tests/sshprotoext.py
  tests/test-ssh-proto.t

CHANGE DETAILS

diff --git a/tests/test-ssh-proto.t b/tests/test-ssh-proto.t
--- a/tests/test-ssh-proto.t
+++ b/tests/test-ssh-proto.t
@@ -388,3 +388,107 @@
   0
   0
   0
+
+Send an upgrade request to a server that doesn't support that command
+
+  $ hg -R server serve --stdio << EOF
+  > upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a 
proto=irrelevant1%2Cirrelevant2
+  > hello
+  > between
+  > pairs 81
+  > 
-
+  > EOF
+  0
+  384
+  capabilities: lookup changegroupsubset branchmap pushkey known getbundle 
unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ 
unbundle=HG10GZ,HG10BZ,HG10UN
+  1
+  
+
+  $ hg --config experimental.sshpeer.advertise-v2=true --debug debugpeer 
ssh://user@dummy/server
+  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob)
+  sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
+  devel-peer-request: hello
+  sending hello command
+  devel-peer-request: between
+  devel-peer-request:   pairs: 81 bytes
+  sending between command
+  remote: 0
+  remote: 384
+  remote: capabilities: lookup changegroupsubset branchmap pushkey known 
getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 
$USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
+  remote: 1
+  url: ssh://user@dummy/server
+  local: no
+  pushable: yes
+
+Send an upgrade request to a server that supports upgrade
+
+  $ SSHSERVERMODE=upgradev2 hg -R server serve --stdio << EOF
+  > upgrade this-is-some-token proto=exp-ssh-v2-0001
+  > hello
+  > between
+  > pairs 81
+  > 
-
+  > EOF
+  upgraded this-is-some-token exp-ssh-v2-0001
+  383
+  capabilities: lookup changegroupsubset branchmap pushkey known getbundle 
unbundlehash batch streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ 
unbundle=HG10GZ,HG10BZ,HG10UN
+
+  $ SSHSERVERMODE=upgradev2 hg --config experimental.sshpeer.advertise-v2=true 
--debug debugpeer ssh://user@dummy/server
+  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob)
+  sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
+  devel-peer-request: hello
+  sending hello command
+  devel-peer-request: between
+  devel-peer-request:   pairs: 81 bytes
+  sending between command
+  protocol upgraded to exp-ssh-v2-0001
+  url: ssh://user@dummy/server
+  local: no
+  pushable: yes
+
+Verify the peer has capabilities
+
+  $ SSHSERVERMODE=upgradev2 hg --config experimental.sshpeer.advertise-v2=true 
--debug debugcapabilities ssh://user@dummy/server
+  running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob)
+  sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
+  devel-peer-request: hello
+  sending hello command
+  devel-peer-request: between
+  devel-peer-request:   pairs: 81 bytes
+  sending between command
+  protocol upgraded to exp-ssh-v2-0001
+  Main capabilities:
+batch
+branchmap
+$USUAL_BUNDLE2_CAPS_SERVER$
+changegroupsubset
+getbundle
+known
+lookup
+pushkey
+streamreqs=generaldelta,revlogv1
+unbundle=HG10GZ,HG10BZ,HG10UN
+unbundlehash
+  Bundle2 capabilities:
+HG20
+bookmarks
+changegroup
+  01
+  02
+digests
+  md5
+  sha1
+  sha512
+error
+  abort
+  unsupportedcontent
+  pushraced
+  pushkey
+hgtagsfnodes
+listkeys
+phases
+  heads
+pushkey
+remote-changegroup
+  http
+  https
diff --git a/tests/sshprotoext.py b/tests/sshprotoext.py
--- a/tests/sshprotoext.py
+++ b/tests/sshprotoext.py
@@ -53,6 +53,35 @@
 
 super(prehelloserver, self).serve_forever()
 
+class upgradev2server(wireprotoserver.sshserver):
+"""Tests behavior for clients that issue upgrade to version 2."""
+def serve_forever(self):
+name = wireprotoserver.SSHV2
+l = self._fin.readline()
+assert l.startswith(b'upgrade ')
+token, caps = l[:-1].split(b' ')[1:]
+assert caps == b'proto=%s' % name
+
+# Filter hello and between requests.
+l = self._fin.readline()
+assert l == b'hello\n'
+l = self._fin.readline()
+assert l == b'between\n'
+l = self._fin.readline()
+assert l == 'pairs 81\n'
+self._fin.read(81)
+
+# Send the upgrade response.
+ 

D2020: hgweb: move call to protocol handler outside of try..except

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGe69e65b2b4a9: hgweb: move call to protocol handler outside 
of try..except (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2020?vs=5174=5310

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

AFFECTED FILES
  mercurial/hgweb/hgweb_mod.py

CHANGE DETAILS

diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -368,7 +368,6 @@
 raise ErrorResponse(HTTP_NOT_FOUND)
 if cmd in perms:
 self.check_perm(rctx, req, perms[cmd])
-return protohandler['dispatch']()
 except ErrorResponse as inst:
 # A client that sends unbundle without 100-continue will
 # break if we respond early.
@@ -383,6 +382,8 @@
 body='0\n%s\n' % inst)
 return ''
 
+return protohandler['dispatch']()
+
 # translate user-visible url structure to internal structure
 
 args = query.split('/', 2)



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


D1998: wireproto: define and use types for wire protocol commands

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGef683a0fd21f: wireproto: define and use types for wire 
protocol commands (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D1998?vs=5137=5305

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

AFFECTED FILES
  mercurial/wireproto.py

CHANGE DETAILS

diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -634,8 +634,64 @@
 
 return compengines
 
-# list of commands
-commands = {}
+class commandentry(object):
+"""Represents a declared wire protocol command."""
+def __init__(self, func, args=''):
+self.func = func
+self.args = args
+
+def _merge(self, func, args):
+"""Merge this instance with an incoming 2-tuple.
+
+This is called when a caller using the old 2-tuple API attempts
+to replace an instance. The incoming values are merged with
+data not captured by the 2-tuple and a new instance containing
+the union of the two objects is returned.
+"""
+return commandentry(func, args)
+
+# Old code treats instances as 2-tuples. So expose that interface.
+def __iter__(self):
+yield self.func
+yield self.args
+
+def __getitem__(self, i):
+if i == 0:
+return self.func
+elif i == 1:
+return self.args
+else:
+raise IndexError('can only access elements 0 and 1')
+
+class commanddict(dict):
+"""Container for registered wire protocol commands.
+
+It behaves like a dict. But __setitem__ is overwritten to allow silent
+coercion of values from 2-tuples for API compatibility.
+"""
+def __setitem__(self, k, v):
+if isinstance(v, commandentry):
+pass
+# Cast 2-tuples to commandentry instances.
+elif isinstance(v, tuple):
+if len(v) != 2:
+raise ValueError('command tuples must have exactly 2 elements')
+
+# It is common for extensions to wrap wire protocol commands via
+# e.g. ``wireproto.commands[x] = (newfn, args)``. Because callers
+# doing this aren't aware of the new API that uses objects to store
+# command entries, we automatically merge old state with new.
+if k in self:
+v = self[k]._merge(v[0], v[1])
+else:
+v = commandentry(v[0], v[1])
+else:
+raise ValueError('command entries must be commandentry instances '
+ 'or 2-tuples')
+
+return super(commanddict, self).__setitem__(k, v)
+
+commands = commanddict()
 
 def wireprotocommand(name, args=''):
 """Decorator to declare a wire protocol command.
@@ -646,7 +702,7 @@
 accepts. ``*`` is a special value that says to accept all arguments.
 """
 def register(func):
-commands[name] = (func, args)
+commands[name] = commandentry(func, args)
 return func
 return register
 



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


D1997: wireproto: improve docstring for @wireprotocommand

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGb4976912a6ef: wireproto: improve docstring for 
@wireprotocommand (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D1997?vs=5136=5306

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

AFFECTED FILES
  mercurial/wireproto.py

CHANGE DETAILS

diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -638,7 +638,13 @@
 commands = {}
 
 def wireprotocommand(name, args=''):
-"""decorator for wire protocol command"""
+"""Decorator to declare a wire protocol command.
+
+``name`` is the name of the wire protocol command being provided.
+
+``args`` is a space-delimited list of named arguments that the command
+accepts. ``*`` is a special value that says to accept all arguments.
+"""
 def register(func):
 commands[name] = (func, args)
 return func



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


D2062: sshpeer: rename sshpeer class to sshv1peer (API)

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG625038cb4b1d: sshpeer: rename sshpeer class to sshv1peer 
(API) (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2062?vs=5256=5302

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

AFFECTED FILES
  hgext/largefiles/uisetup.py
  mercurial/sshpeer.py
  tests/test-check-interfaces.py

CHANGE DETAILS

diff --git a/tests/test-check-interfaces.py b/tests/test-check-interfaces.py
--- a/tests/test-check-interfaces.py
+++ b/tests/test-check-interfaces.py
@@ -65,8 +65,8 @@
 checkobject(badpeer())
 checkobject(httppeer.httppeer(ui, 'http://localhost'))
 checkobject(localrepo.localpeer(dummyrepo()))
-checkobject(sshpeer.sshpeer(ui, 'ssh://localhost/foo', None, None, None,
-   None, None))
+checkobject(sshpeer.sshv1peer(ui, 'ssh://localhost/foo', None, None, None,
+  None, None))
 checkobject(bundlerepo.bundlepeer(dummyrepo()))
 checkobject(statichttprepo.statichttppeer(dummyrepo()))
 checkobject(unionrepo.unionpeer(dummyrepo()))
diff --git a/mercurial/sshpeer.py b/mercurial/sshpeer.py
--- a/mercurial/sshpeer.py
+++ b/mercurial/sshpeer.py
@@ -328,7 +328,7 @@
 
 return caps
 
-class sshpeer(wireproto.wirepeer):
+class sshv1peer(wireproto.wirepeer):
 def __init__(self, ui, url, proc, stdin, stdout, stderr, caps):
 """Create a peer from an existing SSH connection.
 
@@ -537,4 +537,4 @@
 _cleanuppipes(ui, stdout, stdin, stderr)
 raise
 
-return sshpeer(ui, path, proc, stdin, stdout, stderr, caps)
+return sshv1peer(ui, path, proc, stdin, stdout, stderr, caps)
diff --git a/hgext/largefiles/uisetup.py b/hgext/largefiles/uisetup.py
--- a/hgext/largefiles/uisetup.py
+++ b/hgext/largefiles/uisetup.py
@@ -185,9 +185,9 @@
 
 # can't do this in reposetup because it needs to have happened before
 # wirerepo.__init__ is called
-proto.ssholdcallstream = sshpeer.sshpeer._callstream
+proto.ssholdcallstream = sshpeer.sshv1peer._callstream
 proto.httpoldcallstream = httppeer.httppeer._callstream
-sshpeer.sshpeer._callstream = proto.sshrepocallstream
+sshpeer.sshv1peer._callstream = proto.sshrepocallstream
 httppeer.httppeer._callstream = proto.httprepocallstream
 
 # override some extensions' stuff as well



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


D2060: internals: refactor wire protocol documentation

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG40d94ea51402: internals: refactor wire protocol 
documentation (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2060?vs=5254=5300

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

AFFECTED FILES
  mercurial/help/internals/wireprotocol.txt

CHANGE DETAILS

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
@@ -10,11 +10,43 @@
 The protocol is synchronous and does not support multiplexing (concurrent
 commands).
 
-Transport Protocols
-===
+Handshake
+=
+
+It is required or common for clients to perform a *handshake* when connecting
+to a server. The handshake serves the following purposes:
+
+* Negotiating protocol/transport level options
+* Allows the client to learn about server capabilities to influence
+  future requests
+* Ensures the underlying transport channel is in a *clean* state
 
-HTTP Transport
---
+An important goal of the handshake is to allow clients to use more modern
+wire protocol features. By default, clients must assume they are talking
+to an old version of Mercurial server (possibly even the very first
+implementation). So, clients should not attempt to call or utilize modern
+wire protocol features until they have confirmation that the server
+supports them. The handshake implementation is designed to allow both
+ends to utilize the latest set of features and capabilities with as
+few round trips as possible.
+
+The handshake mechanism varies by transport and protocol and is documented
+in the sections below.
+
+HTTP Protocol
+=
+
+Handshake
+-
+
+The client sends a ``capabilities`` command request (``?cmd=capabilities``)
+as soon as HTTP requests may be issued.
+
+The server responds with a capabilities string, which the client parses to
+learn about the server's abilities.
+
+HTTP Version 1 Transport
+
 
 Commands are issued as HTTP/1.0 or HTTP/1.1 requests. Commands are
 sent to the base URL of the repository with the command name sent in
@@ -112,11 +144,86 @@
 ``application/mercurial-0.*`` media type and the HTTP response is typically
 using *chunked transfer* (``Transfer-Encoding: chunked``).
 
-SSH Transport
-=
+SSH Protocol
+
+
+Handshake
+-
+
+For all clients, the handshake consists of the client sending 1 or more
+commands to the server using version 1 of the transport. Servers respond
+to commands they know how to respond to and send an empty response (``0\n``)
+for unknown commands (per standard behavior of version 1 of the transport).
+Clients then typically look for a response to the newest sent command to
+determine which transport version to use and what the available features for
+the connection and server are.
+
+Preceding any response from client-issued commands, the server may print
+non-protocol output. It is common for SSH servers to print banners, message
+of the day announcements, etc when clients connect. It is assumed that any
+such *banner* output will precede any Mercurial server output. So clients
+must be prepared to handle server output on initial connect that isn't
+in response to any client-issued command and doesn't conform to Mercurial's
+wire protocol. This *banner* output should only be on stdout. However,
+some servers may send output on stderr.
+
+Pre 0.9.1 clients issue a ``between`` command with the ``pairs`` argument
+having the value
+``-``.
+
+The ``between`` command has been supported since the original Mercurial
+SSH server. Requesting the empty range will return a ``\n`` string response,
+which will be encoded as ``1\n\n`` (value length of ``1`` followed by a newline
+followed by the value, which happens to be a newline).
+
+For pre 0.9.1 clients and all servers, the exchange looks like::
+
+   c: between\n
+   c: pairs 81\n
+   c: 
-
+   s: 1\n
+   s: \n
 
-The SSH transport is a custom text-based protocol suitable for use over any
-bi-directional stream transport. It is most commonly used with SSH.
+0.9.1+ clients send a ``hello`` command (with no arguments) before the
+``between`` command. The response to this command allows clients to
+discover server capabilities and settings.
+
+An example exchange between 0.9.1+ clients and a ``hello`` aware server looks
+like::
+
+   c: hello\n
+   c: between\n
+   c: pairs 81\n
+   c: 
-
+   s: 324\n
+   s: capabilities: lookup changegroupsubset branchmap pushkey known getbundle 
...\n
+   s: 1\n
+   s: \n
+
+And a similar scenario 

D2063: sshpeer: implement peer for version 2 of wire protocol

2018-02-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG59e4a7781a36: sshpeer: implement peer for version 2 of wire 
protocol (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2063?vs=5257=5303

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

AFFECTED FILES
  mercurial/sshpeer.py
  tests/test-check-interfaces.py

CHANGE DETAILS

diff --git a/tests/test-check-interfaces.py b/tests/test-check-interfaces.py
--- a/tests/test-check-interfaces.py
+++ b/tests/test-check-interfaces.py
@@ -67,6 +67,8 @@
 checkobject(localrepo.localpeer(dummyrepo()))
 checkobject(sshpeer.sshv1peer(ui, 'ssh://localhost/foo', None, None, None,
   None, None))
+checkobject(sshpeer.sshv2peer(ui, 'ssh://localhost/foo', None, None, None,
+  None, None))
 checkobject(bundlerepo.bundlepeer(dummyrepo()))
 checkobject(statichttprepo.statichttppeer(dummyrepo()))
 checkobject(unionrepo.unionpeer(dummyrepo()))
diff --git a/mercurial/sshpeer.py b/mercurial/sshpeer.py
--- a/mercurial/sshpeer.py
+++ b/mercurial/sshpeer.py
@@ -326,7 +326,7 @@
 if not caps:
 badresponse()
 
-return caps
+return protoname, caps
 
 class sshv1peer(wireproto.wirepeer):
 def __init__(self, ui, url, proc, stdin, stdout, stderr, caps):
@@ -497,6 +497,12 @@
 self._pipeo.flush()
 self._readerr()
 
+class sshv2peer(sshv1peer):
+"""A peer that speakers version 2 of the transport protocol."""
+# Currently version 2 is identical to version 1 post handshake.
+# And handshake is performed before the peer is instantiated. So
+# we need no custom code.
+
 def instance(ui, path, create):
 """Create an SSH peer.
 
@@ -532,9 +538,16 @@
   remotepath, sshenv)
 
 try:
-caps = _performhandshake(ui, stdin, stdout, stderr)
+protoname, caps = _performhandshake(ui, stdin, stdout, stderr)
 except Exception:
 _cleanuppipes(ui, stdout, stdin, stderr)
 raise
 
-return sshv1peer(ui, path, proc, stdin, stdout, stderr, caps)
+if protoname == wireprotoserver.SSHV1:
+return sshv1peer(ui, path, proc, stdin, stdout, stderr, caps)
+elif protoname == wireprotoserver.SSHV2:
+return sshv2peer(ui, path, proc, stdin, stdout, stderr, caps)
+else:
+_cleanuppipes(ui, stdout, stdin, stderr)
+raise error.RepoError(_('unknown version of SSH protocol: %s') %
+  protoname)



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


D2069: revlog: resolve lfs rawtext to vanilla rawtext before applying delta

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg requested changes to this revision.
indygreg added a comment.
This revision now requires changes to proceed.


  I'd like to see the next versions of hte previous 2 patches before looking at 
this because this patch will likely get some minor rework as well.

REPOSITORY
  rHG Mercurial

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

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


D2068: revlog: do not use delta for lfs revisions

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg requested changes to this revision.
indygreg added inline comments.
This revision now requires changes to proceed.

INLINE COMMENTS

> revlog.py:408
> +# do not use flags != 0 (ex. LFS) revision as delta base
> +if revlog.flags(candidaterev) != REVIDX_DEFAULT_FLAGS:
> +continue

Same comment as previous review: this leaves a foot gun if we ever introduce 
revision flags that aren't related to content presence. We need something to 
help prevent this footgun.

REPOSITORY
  rHG Mercurial

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

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


D2067: changegroup: do not delta lfs revisions

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg requested changes to this revision.
indygreg added a comment.
This revision now requires changes to proceed.


  This looks mostly good. I would like a change to address a future footgun 
though.
  
  I would also appreciate someone familiar with censor and narrow to weigh in 
on the implications of disabling delta generation for revisions that have the 
censor and ellipsis flags set. I'm pretty sure narrow will cope since it 
reimplements changegroup generation. Not sure how censor will react. (But I 
know we already have random code for detecting censored nodes during 
changegroup generation.)

INLINE COMMENTS

> revlog.py:719
> +# disable delta if either rev uses non-default flag (ex. LFS)
> +if self.flags(baserev) or self.flags(rev):
> +return False

This logic assumes that revision flags will only ever be used to influence the 
presence of content. That is true today because our flags are for 
`REVIDX_ISCENSORED`, `REVIDX_ELLIPSIS`, and `REVIDX_EXTSTORED`. But if we ever 
introduced a new revision flag for e.g. compression strategy, then testing for 
non-empty revision flags would be wrong.

I think we want to capture the bitmask of revision flags influencing delta 
generation explicitly. Or we want a big comment by the revision flags constants 
at the top of the file telling people to audit `candelta()` when adding new 
revision flags.

REPOSITORY
  rHG Mercurial

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

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


D1998: wireproto: define and use types for wire protocol commands

2018-02-07 Thread durin42 (Augie Fackler)
durin42 accepted this revision.
durin42 added a comment.
This revision is now accepted and ready to land.


  I'm sold.

REPOSITORY
  rHG Mercurial

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

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


D1998: wireproto: define and use types for wire protocol commands

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg added a comment.


  In https://phab.mercurial-scm.org/D1998#34740, @durin42 wrote:
  
  > I'm curious what registrations you need that don't fit in 2-tuples. Can I 
see a sample of where that's going?
  
  
  I'll be adding additional attributes to `@wireprotocommand` in future series. 
One thing I know I'll add is a mechanism to limit which wire protocol 
versions/transports to expose a command to. This will prevent legacy commands 
from being exposed to modern protocols and vice versa.

REPOSITORY
  rHG Mercurial

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

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


D2065: wireprotoserver: rename abstractserverproto and improve docstring

2018-02-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 5299.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2065?vs=5262=5299

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

AFFECTED FILES
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -38,10 +38,13 @@
 # to reflect BC breakages.
 SSHV2 = 'exp-ssh-v2-0001'
 
-class abstractserverproto(object):
-"""abstract class that summarizes the protocol API
+class baseprotocolhandler(object):
+"""Abstract base class for wire protocol handlers.
 
-Used as reference and documentation.
+A wire protocol handler serves as an interface between protocol command
+handlers and the wire protocol transport layer. Protocol handlers provide
+methods to read command arguments, redirect stdio for the duration of
+the request, handle response types, etc.
 """
 
 __metaclass__ = abc.ABCMeta
@@ -104,7 +107,7 @@
 
 return ''.join(chunks)
 
-class webproto(abstractserverproto):
+class webproto(baseprotocolhandler):
 def __init__(self, req, ui):
 self._req = req
 self._ui = ui
@@ -333,7 +336,7 @@
 
 return ''
 
-class sshserver(abstractserverproto):
+class sshserver(baseprotocolhandler):
 def __init__(self, ui, repo):
 self._ui = ui
 self._repo = repo



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


D2048: utils: copy util.py as utils/dateutil.py

2018-02-07 Thread durin42 (Augie Fackler)
durin42 requested changes to this revision.
durin42 added a comment.
This revision now requires changes to proceed.


  Can we do all of 
https://phab.mercurial-scm.org/D2048::https://phab.mercurial-scm.org/D2056 as a 
single change? What you've done means we have no useful blame information on 
everything done in https://phab.mercurial-scm.org/D2049::D0256...

REPOSITORY
  rHG Mercurial

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

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


D1998: wireproto: define and use types for wire protocol commands

2018-02-07 Thread durin42 (Augie Fackler)
durin42 added a comment.


  I'm curious what registrations you need that don't fit in 2-tuples. Can I see 
a sample of where that's going?

REPOSITORY
  rHG Mercurial

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

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


D2064: wireprotoserver: document and improve the httplib workaround

2018-02-07 Thread durin42 (Augie Fackler)
durin42 accepted this revision.
durin42 added a comment.
This revision is now accepted and ready to land.


  I'm so sorry for this technical debt, even if it's httplib's fault. :/

REPOSITORY
  rHG Mercurial

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

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


D2061: sshpeer: initial definition and implementation of new SSH protocol

2018-02-07 Thread durin42 (Augie Fackler)
durin42 added inline comments.

INLINE COMMENTS

> joerg.sonnenberger wrote in test-ssh-proto.t:396
> I'm a bit concerned about the order here. I would prefer to stay with the 
> spirit of the original SSH protocol and go with the following order instead:
> 
> - client sends hello to the server
> - server sends its capabilities, including the supported "modern" protocol 
> versions
> - client upgrades to the "best" version it supports and sends any additional 
> wire capabilities it has
> 
> I don't think this changes the number of round-trips, but it slightly affects 
> the number of commands that are "unversioned".

I don't feel super-strongly. I think my bias is to let the upgrade happen prior 
to the hello so that we can have custom servers in the future not have to 
support the bad old framing. I'll land the patch as is, but we can continue 
discussing it a bit here or on the list if I haven't convinced you. :)

REPOSITORY
  rHG Mercurial

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

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


D2079: color: honor NO_COLOR

2018-02-07 Thread quark (Jun Wu)
quark added a comment.


  You might want to let run-tests.py drop NO_COLOR for tests.

REPOSITORY
  rHG Mercurial

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

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


D2079: color: honor NO_COLOR

2018-02-07 Thread lothiraldan (Boris Feld)
lothiraldan accepted this revision.
lothiraldan added a comment.


   Hurrah for standards!

REPOSITORY
  rHG Mercurial

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

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


[Bug 5783] New: ValueError (too many values to unpack) in mercurial/obsolete.py

2018-02-07 Thread mercurial-bugs
https://bz.mercurial-scm.org/show_bug.cgi?id=5783

Bug ID: 5783
   Summary: ValueError (too many values to unpack) in
mercurial/obsolete.py
   Product: Mercurial
   Version: stable branch
  Hardware: PC
OS: Linux
Status: UNCONFIRMED
  Severity: bug
  Priority: wish
 Component: evolution
  Assignee: bugzi...@mercurial-scm.org
  Reporter: david.dou...@logilab.fr
CC: mercurial-devel@mercurial-scm.org,
pierre-yves.da...@ens-lyon.org

In a repository (in which we use obsolete and evolve and topics), we've been
hit by the traceback :

[...]
  File
"/home/david/.virtualenvs/hg/local/lib/python2.7/site-packages/mercurial/obsolete.py",
line 296, in _fm0decodemeta
key, value = l.split(':')
ValueError: too many values to unpack

In my context, the variable 'l' contains 2 ':' chars. The content of the
variabel 'data' in this function is:

'date:1518013344.878793
-3600\x00ef1:0\x00note:6c95ca::a1e17f\x00p1:ed7673f73387b36521da58a87f08e02e4a795ded\x00user:Denis
Laxalde '

I mage a simple hotfix replacing this line by:

  key, value = l.split(':', 1)

which seems to work for now.

Note: the problem occurs the same on hg 4.3 (deb package on a jessie machine)
and hg 4.5 (from pip).

David

-- 
You are receiving this mail because:
You are on the CC list for the bug.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 6 of 6] log: pack filematcher and hunksfilter into changesetdiffer object

2018-02-07 Thread Denis Laxalde
Yuya Nishihara a écrit :
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1516517658 -32400
> #  Sun Jan 21 15:54:18 2018 +0900
> # Node ID 5f9dcb5d72da427abbfa2c304bdbe4dd555e0c7d
> # Parent  f95d0d1e012a512550de945350e08f3dc7db090f
> log: pack filematcher and hunksfilter into changesetdiffer object
> 
> This is just a way of getting rid of clumsy makefilematcher/makehunksfilter
> arguments. There might be a better abstraction, but I don't think this is bad.

Alternatively we could have a makediffer(makefilematcher=None,
makehunksfilter=None) factory function returning the showdiff function
with capture context; that would avoid setting _make in
client code. Not sure this is better and I agree that your proposal is
"not bad".

Nice cleanup overall.

> This makes filematcher and hunksfilter available by default, but that should
> be fine.
> 
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -3419,17 +3419,15 @@ def log(ui, repo, *pats, **opts):
>  )
>  
>  repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
> -revs, filematcher = logcmdutil.getrevs(repo, pats, opts)
> -hunksfilter = None
> +revs, differ = logcmdutil.getrevs(repo, pats, opts)
>  
>  if opts.get('graph'):
>  if linerange:
>  raise error.Abort(_('graph not supported with line range 
> patterns'))
> -return logcmdutil.graphlog(ui, repo, revs, filematcher, opts)
> +return logcmdutil.graphlog(ui, repo, revs, differ, opts)
>  
>  if linerange:
> -revs, filematcher, hunksfilter = logcmdutil.getlinerangerevs(
> -repo, revs, opts)
> +revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
>  
>  getrenamed = None
>  if opts.get('copies'):
> @@ -3439,9 +3437,7 @@ def log(ui, repo, *pats, **opts):
>  getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
>  
>  ui.pager('log')
> -displayer = logcmdutil.changesetdisplayer(ui, repo, opts,
> -  makefilematcher=filematcher,
> -  makehunksfilter=hunksfilter,
> +displayer = logcmdutil.changesetdisplayer(ui, repo, opts, differ,
>buffered=True)
>  for rev in revs:
>  ctx = repo[rev]
> diff --git a/mercurial/logcmdutil.py b/mercurial/logcmdutil.py
> --- a/mercurial/logcmdutil.py
> +++ b/mercurial/logcmdutil.py
> @@ -109,6 +109,23 @@ def diffordiffstat(ui, repo, diffopts, n
>  sub.diff(ui, diffopts, tempnode2, submatch, changes=changes,
>   stat=stat, fp=fp, prefix=prefix)
>  
> +class changesetdiffer(object):
> +"""Generate diff of changeset with pre-configured filtering functions"""
> +
> +def _makefilematcher(self, ctx):
> +return scmutil.matchall(ctx.repo())
> +
> +def _makehunksfilter(self, ctx):
> +return None
> +
> +def showdiff(self, ui, ctx, diffopts, stat=False):
> +repo = ctx.repo()
> +node = ctx.node()
> +prev = ctx.p1().node()
> +diffordiffstat(ui, repo, diffopts, prev, node,
> +   match=self._makefilematcher(ctx), stat=stat,
> +   hunksfilterfn=self._makehunksfilter(ctx))
> +
>  def changesetlabels(ctx):
>  labels = ['log.changeset', 'changeset.%s' % ctx.phasestr()]
>  if ctx.obsolete():
> @@ -122,13 +139,11 @@ def changesetlabels(ctx):
>  class changesetprinter(object):
>  '''show changeset information when templating not requested.'''
>  
> -def __init__(self, ui, repo, makefilematcher=None, makehunksfilter=None,
> - diffopts=None, buffered=False):
> +def __init__(self, ui, repo, differ=None, diffopts=None, buffered=False):
>  self.ui = ui
>  self.repo = repo
>  self.buffered = buffered
> -self._makefilematcher = makefilematcher or (lambda ctx: None)
> -self._makehunksfilter = makehunksfilter or (lambda ctx: None)
> +self._differ = differ or changesetdiffer()
>  self.diffopts = diffopts or {}
>  self.header = {}
>  self.hunk = {}
> @@ -267,35 +282,23 @@ class changesetprinter(object):
>  '''
>  
>  def _showpatch(self, ctx):
> -matchfn = self._makefilematcher(ctx)
> -hunksfilterfn = self._makehunksfilter(ctx)
> -if not matchfn:
> -return
>  stat = self.diffopts.get('stat')
>  diff = self.diffopts.get('patch')
>  diffopts = patch.diffallopts(self.ui, self.diffopts)
> -node = ctx.node()
> -prev = ctx.p1().node()
>  if stat:
> -diffordiffstat(self.ui, self.repo, diffopts, prev, node,
> -   match=matchfn, stat=True,
> -   hunksfilterfn=hunksfilterfn)
> +self._differ.showdiff(self.ui, ctx, diffopts, 

D2079: color: honor NO_COLOR

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

REVISION SUMMARY
  The http://no-color.org/ initiative is trying to get programs that
  emit color by default to honor a NO_COLOR environment variable to
  disable color.
  
  I think that's a good idea. So this commit implements support for
  NO_COLOR.
  
  I'm not sure if the precedence of settings is proper here. Right now,
  NO_COLOR overrides config settings set by hgrc or --config. But it
  doesn't override --color. I can see an argument for honoring
  --config as well. Same for hgrc (since color is enabled by default
  these days). But the existing logic/precedence is unclear to me. So
  I went with an easy implementation.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/color.py
  tests/test-status-color.t

CHANGE DETAILS

diff --git a/tests/test-status-color.t b/tests/test-status-color.t
--- a/tests/test-status-color.t
+++ b/tests/test-status-color.t
@@ -46,6 +46,42 @@
   [status.unknown|? ][status.unknown|b/in_b] (glob)
   [status.unknown|? ][status.unknown|in_root]
 
+NO_COLOR disables color
+
+  $ NO_COLOR=1 hg status
+  ? a/1/in_a_1
+  ? a/in_a
+  ? b/1/in_b_1
+  ? b/2/in_b_2
+  ? b/in_b
+  ? in_root
+
+  $ NO_COLOR=0 hg status
+  ? a/1/in_a_1
+  ? a/in_a
+  ? b/1/in_b_1
+  ? b/2/in_b_2
+  ? b/in_b
+  ? in_root
+
+  $ NO_COLOR= hg status
+  ? a/1/in_a_1
+  ? a/in_a
+  ? b/1/in_b_1
+  ? b/2/in_b_2
+  ? b/in_b
+  ? in_root
+
+NO_COLOR is overridden by --color
+
+  $ NO_COLOR=1 hg --color=always status
+  \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
+  \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
+  \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
+  \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
+  \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
+  \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
+
 hg status with template
   $ hg status -T "{label('red', path)}\n" --color=debug
   [red|a/1/in_a_1]
diff --git a/mercurial/color.py b/mercurial/color.py
--- a/mercurial/color.py
+++ b/mercurial/color.py
@@ -198,6 +198,13 @@
 if config == 'debug':
 return 'debug'
 
+# The http://no-color.org/ initiative wants to standardize on an 
environment
+# variable to disable color. The value of this variable doesn't matter.
+if 'NO_COLOR' in encoding.environ:
+# Allow --color CLI argument to override NO_COLOR
+if ui.configsource('ui', 'color') != '--color':
+return None
+
 auto = (config == 'auto')
 always = False
 if not auto and util.parsebool(config):



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


D1957: streamclonebundle: make sure we accept new stream clone bundle spec

2018-02-07 Thread lothiraldan (Boris Feld)
lothiraldan added a subscriber: indygreg.
lothiraldan added a comment.


  @indygreg Could you take a look at the series before it gets too distant to 
merge cleanly?

REPOSITORY
  rHG Mercurial

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

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


D2061: sshpeer: initial definition and implementation of new SSH protocol

2018-02-07 Thread joerg.sonnenberger (Joerg Sonnenberger)
joerg.sonnenberger added inline comments.

INLINE COMMENTS

> test-ssh-proto.t:396
> +  > upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a 
> proto=irrelevant1%2Cirrelevant2
> +  > hello
> +  > between

I'm a bit concerned about the order here. I would prefer to stay with the 
spirit of the original SSH protocol and go with the following order instead:

- client sends hello to the server
- server sends its capabilities, including the supported "modern" protocol 
versions
- client upgrades to the "best" version it supports and sends any additional 
wire capabilities it has

I don't think this changes the number of round-trips, but it slightly affects 
the number of commands that are "unversioned".

REPOSITORY
  rHG Mercurial

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

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


Re: [PATCH 07 of 13] revlog: move index file opening in a method

2018-02-07 Thread Yuya Nishihara
On Tue, 06 Feb 2018 14:21:28 +0100, Boris Feld wrote:
> # HG changeset patch
> # User Boris Feld 
> # Date 1517847733 -3600
> #  Mon Feb 05 17:22:13 2018 +0100
> # Node ID d238ec45ba25f7c1ea9ec22aa11a4ec699c72740
> # Parent  b192ee27b376523292ec1cf52c49c9382a870658
> # EXP-Topic revlog-fp
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
> d238ec45ba25
> revlog: move index file opening in a method

Queud the series, thanks.

> @@ -682,6 +682,15 @@ class revlog(object):
>  def _compressor(self):
>  return util.compengines[self._compengine].revlogcompressor()
>  
> +def _indexfp(self, mode='r'):
> +"""file object for the revlog's index file"""
> +args = {'mode': mode}
> +if mode != 'r':
> +args['checkambig'] = self._checkambig
> +if mode == 'w':
> +args['atomictemp'] = True
> +return self.opener(self.indexfile, **args)

Added r'' in flight to get around py3 transformer.

> -fp = self.opener(self.indexfile, 'w', atomictemp=True,
> - checkambig=self._checkambig)
> +fp = self._indexfp('w')

I don't think it's good idea to make 'w' imply atomictemp=True because here
the atomic-temp semantics is really important, but the series looks good as
a whole.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D2022: ui: improve ui.write performance when not coloring on Windows

2018-02-07 Thread joerg.sonnenberger (Joerg Sonnenberger)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG0ff41ced4c12: diff: improve ui.write performance when not 
coloring on Windows (authored by joerg.sonnenberger, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D2022?vs=5293=5297#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2022?vs=5293=5297

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

AFFECTED FILES
  mercurial/logcmdutil.py
  mercurial/ui.py

CHANGE DETAILS

diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -870,6 +870,17 @@
 
 return "".join(self._buffers.pop())
 
+def canwritewithoutlabels(self):
+'''check if write skips the label'''
+if self._buffers and not self._bufferapplylabels:
+return True
+return self._colormode is None
+
+def canbatchlabeledwrites(self):
+'''check if write calls with labels are batchable'''
+# Windows color printing is special, see ``write``.
+return self._colormode != 'win32'
+
 def write(self, *args, **opts):
 '''write args to output
 
diff --git a/mercurial/logcmdutil.py b/mercurial/logcmdutil.py
--- a/mercurial/logcmdutil.py
+++ b/mercurial/logcmdutil.py
@@ -79,18 +79,31 @@
 width = 80
 if not ui.plain():
 width = ui.termwidth()
-chunks = patch.diff(repo, node1, node2, match, changes, opts=diffopts,
-prefix=prefix, relroot=relroot,
-hunksfilterfn=hunksfilterfn)
-for chunk, label in patch.diffstatui(util.iterlines(chunks),
- width=width):
-write(chunk, label=label)
+
+chunks = patch.diff(repo, node1, node2, match, changes, opts=diffopts,
+prefix=prefix, relroot=relroot,
+hunksfilterfn=hunksfilterfn)
+
+if fp is not None or ui.canwritewithoutlabels():
+if stat:
+chunks = patch.diffstat(util.iterlines(chunks), width=width)
+for chunk in util.filechunkiter(util.chunkbuffer(chunks)):
+write(chunk)
 else:
-for chunk, label in patch.diffui(repo, node1, node2, match,
- changes, opts=diffopts, prefix=prefix,
- relroot=relroot,
- hunksfilterfn=hunksfilterfn):
-write(chunk, label=label)
+if stat:
+chunks = patch.diffstatui(util.iterlines(chunks), width=width)
+else:
+chunks = patch.difflabel(lambda chunks, **kwargs: chunks, chunks,
+ opts=diffopts)
+if ui.canbatchlabeledwrites():
+def gen():
+for chunk, label in chunks:
+yield ui.label(chunk, label=label)
+for chunk in util.filechunkiter(util.chunkbuffer(gen())):
+write(chunk)
+else:
+for chunk, label in chunks:
+write(chunk, label=label)
 
 if listsubrepos:
 ctx1 = repo[node1]



To: joerg.sonnenberger, #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


D2058: chg: enable clang-format on all .c and .h files

2018-02-07 Thread durin42 (Augie Fackler)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG9724f54923ec: chg: enable clang-format on all .c and .h 
files (authored by durin42, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2058?vs=5239=5295

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

AFFECTED FILES
  contrib/chg/chg.c
  contrib/chg/hgclient.c
  contrib/chg/hgclient.h
  contrib/chg/procutil.c
  contrib/chg/util.c
  contrib/chg/util.h
  contrib/clang-format-blacklist

CHANGE DETAILS

diff --git a/contrib/clang-format-blacklist b/contrib/clang-format-blacklist
--- a/contrib/clang-format-blacklist
+++ b/contrib/clang-format-blacklist
@@ -1,12 +1,5 @@
 # Files that just need to be migrated to the formatter.
 # Do not add new files here!
-contrib/chg/chg.c
-contrib/chg/hgclient.c
-contrib/chg/hgclient.h
-contrib/chg/procutil.c
-contrib/chg/procutil.h
-contrib/chg/util.c
-contrib/chg/util.h
 contrib/hgsh/hgsh.c
 mercurial/cext/base85.c
 mercurial/cext/bdiff.c
diff --git a/contrib/chg/util.h b/contrib/chg/util.h
--- a/contrib/chg/util.h
+++ b/contrib/chg/util.h
@@ -32,4 +32,4 @@
 
 int runshellcmd(const char *cmd, const char *envp[], const char *cwd);
 
-#endif  /* UTIL_H_ */
+#endif /* UTIL_H_ */
diff --git a/contrib/chg/util.c b/contrib/chg/util.c
--- a/contrib/chg/util.c
+++ b/contrib/chg/util.c
@@ -62,7 +62,8 @@
 static int debugmsgenabled = 0;
 static double debugstart = 0;
 
-static double now() {
+static double now()
+{
struct timeval t;
gettimeofday(, NULL);
return t.tv_usec / 1e6 + t.tv_sec;
diff --git a/contrib/chg/procutil.c b/contrib/chg/procutil.c
--- a/contrib/chg/procutil.c
+++ b/contrib/chg/procutil.c
@@ -54,7 +54,7 @@
goto error;
 
forwardsignal(sig);
-   if (raise(sig) < 0)  /* resend to self */
+   if (raise(sig) < 0) /* resend to self */
goto error;
if (sigaction(sig, , ) < 0)
goto error;
@@ -205,8 +205,8 @@
close(pipefds[0]);
close(pipefds[1]);
 
-   int r = execle("/bin/sh", "/bin/sh", "-c", pagercmd, NULL,
-   envp);
+   int r =
+   execle("/bin/sh", "/bin/sh", "-c", pagercmd, NULL, envp);
if (r < 0) {
abortmsgerrno("cannot start pager '%s'", pagercmd);
}
diff --git a/contrib/chg/hgclient.h b/contrib/chg/hgclient.h
--- a/contrib/chg/hgclient.h
+++ b/contrib/chg/hgclient.h
@@ -22,9 +22,9 @@
 pid_t hgc_peerpid(const hgclient_t *hgc);
 
 const char **hgc_validate(hgclient_t *hgc, const char *const args[],
- size_t argsize);
+  size_t argsize);
 int hgc_runcommand(hgclient_t *hgc, const char *const args[], size_t argsize);
 void hgc_attachio(hgclient_t *hgc);
 void hgc_setenv(hgclient_t *hgc, const char *const envp[]);
 
-#endif  /* HGCLIENT_H_ */
+#endif /* HGCLIENT_H_ */
diff --git a/contrib/chg/hgclient.c b/contrib/chg/hgclient.c
--- a/contrib/chg/hgclient.c
+++ b/contrib/chg/hgclient.c
@@ -7,7 +7,7 @@
  * GNU General Public License version 2 or any later version.
  */
 
-#include   /* for ntohl(), htonl() */
+#include  /* for ntohl(), htonl() */
 #include 
 #include 
 #include 
@@ -26,33 +26,32 @@
 #include "procutil.h"
 #include "util.h"
 
-enum {
-   CAP_GETENCODING = 0x0001,
-   CAP_RUNCOMMAND = 0x0002,
-   /* cHg extension: */
-   CAP_ATTACHIO = 0x0100,
-   CAP_CHDIR = 0x0200,
-   CAP_SETENV = 0x0800,
-   CAP_SETUMASK = 0x1000,
-   CAP_VALIDATE = 0x2000,
-   CAP_SETPROCNAME = 0x4000,
+enum { CAP_GETENCODING = 0x0001,
+   CAP_RUNCOMMAND = 0x0002,
+   /* cHg extension: */
+   CAP_ATTACHIO = 0x0100,
+   CAP_CHDIR = 0x0200,
+   CAP_SETENV = 0x0800,
+   CAP_SETUMASK = 0x1000,
+   CAP_VALIDATE = 0x2000,
+   CAP_SETPROCNAME = 0x4000,
 };
 
 typedef struct {
const char *name;
unsigned int flag;
 } cappair_t;
 
 static const cappair_t captable[] = {
-   {"getencoding", CAP_GETENCODING},
-   {"runcommand", CAP_RUNCOMMAND},
-   {"attachio", CAP_ATTACHIO},
-   {"chdir", CAP_CHDIR},
-   {"setenv", CAP_SETENV},
-   {"setumask", CAP_SETUMASK},
-   {"validate", CAP_VALIDATE},
-   {"setprocname", CAP_SETPROCNAME},
-   {NULL, 0},  /* terminator */
+{"getencoding", CAP_GETENCODING},
+{"runcommand", CAP_RUNCOMMAND},
+{"attachio", CAP_ATTACHIO},
+{"chdir", CAP_CHDIR},
+{"setenv", CAP_SETENV},
+{"setumask", CAP_SETUMASK},
+{"validate", CAP_VALIDATE},
+{"setprocname", CAP_SETPROCNAME},
+{NULL, 0}, /* terminator */
 };
 
 typedef struct {
@@ -88,8 +87,8 @@
if (newsize <= ctx->maxdatasize)
return;
 
-   newsize = defaultdatasize
-   * ((newsize + defaultdatasize - 1) / defaultdatasize);
+   newsize = defaultdatasize *
+ ((newsize + 

D2059: hgsh: enable clang-format

2018-02-07 Thread durin42 (Augie Fackler)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG580f7b1b88c7: hgsh: enable clang-format (authored by 
durin42, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2059?vs=5240=5296

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

AFFECTED FILES
  contrib/clang-format-blacklist
  contrib/hgsh/hgsh.c

CHANGE DETAILS

diff --git a/contrib/hgsh/hgsh.c b/contrib/hgsh/hgsh.c
--- a/contrib/hgsh/hgsh.c
+++ b/contrib/hgsh/hgsh.c
@@ -48,65 +48,65 @@
  * have such machine, set to NULL.
  */
 #ifndef HG_GATEWAY
-#define HG_GATEWAY "gateway"
+#define HG_GATEWAY "gateway"
 #endif
 
 /*
  * HG_HOST: hostname of mercurial server. if any machine is allowed, set to
  * NULL.
  */
 #ifndef HG_HOST
-#define HG_HOST "mercurial"
+#define HG_HOST "mercurial"
 #endif
 
 /*
  * HG_USER: username to log in from HG_GATEWAY to HG_HOST. if gateway and
  * host username are same, set to NULL.
  */
 #ifndef HG_USER
-#define HG_USER "hg"
+#define HG_USER "hg"
 #endif
 
 /*
  * HG_ROOT: root of tree full of mercurial repos. if you do not want to
  * validate location of repo when someone is try to access, set to NULL.
  */
 #ifndef HG_ROOT
-#define HG_ROOT "/home/hg/repos"
+#define HG_ROOT "/home/hg/repos"
 #endif
 
 /*
  * HG: path to the mercurial executable to run.
  */
 #ifndef HG
-#define HG  "/home/hg/bin/hg"
+#define HG "/home/hg/bin/hg"
 #endif
 
 /*
  * HG_SHELL: shell to use for actions like "sudo" and "su" access to
  * mercurial user, and cron jobs. if you want to make these things
  * impossible, set to NULL.
  */
 #ifndef HG_SHELL
-#define HG_SHELLNULL
+#define HG_SHELL NULL
 /* #define HG_SHELL"/bin/bash" */
 #endif
 
 /*
  * HG_HELP: some way for users to get support if they have problem. if they
  * should not get helpful message, set to NULL.
  */
 #ifndef HG_HELP
-#define HG_HELP "please contact supp...@example.com for help."
+#define HG_HELP "please contact supp...@example.com for help."
 #endif
 
 /*
  * SSH: path to ssh executable to run, if forwarding from HG_GATEWAY to
  * HG_HOST. if you want to use rsh instead (why?), you need to modify
  * arguments it is called with. see forward_through_gateway.
  */
 #ifndef SSH
-#define SSH "/usr/bin/ssh"
+#define SSH "/usr/bin/ssh"
 #endif
 
 /*
@@ -249,7 +249,6 @@
hg_serve,
 };
 
-
 /*
  * attempt to verify that a directory is really a hg repo, by testing
  * for the existence of a subdirectory.
@@ -310,8 +309,7 @@
 
if (sscanf(argv[2], "hg init %as", ) == 1) {
cmd = hg_init;
-   }
-   else if (sscanf(argv[2], "hg -R %as serve --stdio", ) == 1) {
+   } else if (sscanf(argv[2], "hg -R %as serve --stdio", ) == 1) {
cmd = hg_serve;
} else {
goto badargs;
diff --git a/contrib/clang-format-blacklist b/contrib/clang-format-blacklist
--- a/contrib/clang-format-blacklist
+++ b/contrib/clang-format-blacklist
@@ -1,6 +1,5 @@
 # Files that just need to be migrated to the formatter.
 # Do not add new files here!
-contrib/hgsh/hgsh.c
 mercurial/cext/base85.c
 mercurial/cext/bdiff.c
 mercurial/cext/charencode.c



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


D2078: python3: whitelist an additional 11 tests

2018-02-07 Thread durin42 (Augie Fackler)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGfd9f2a22ee83: python3: whitelist an additional 11 tests 
(authored by durin42, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2078?vs=5292=5294

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

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
@@ -3,6 +3,7 @@
 test-addremove.t
 test-amend-subrepo.t
 test-ancestor.py
+test-annotate.py
 test-automv.t
 test-backwards-remove.t
 test-bheads.t
@@ -29,8 +30,10 @@
 test-confused-revert.t
 test-contrib-check-code.t
 test-contrib-check-commit.t
+test-copy-move-merge.t
 test-debugindexdot.t
 test-debugrename.t
+test-diff-binary-file.t
 test-diff-change.t
 test-diff-copy-depth.t
 test-diff-hashes.t
@@ -74,6 +77,7 @@
 test-exchange-obsmarkers-case-D3.t
 test-exchange-obsmarkers-case-D4.t
 test-execute-bit.t
+test-extra-filelog-entry.t
 test-filebranch.t
 test-flags.t
 test-generaldelta.t
@@ -119,9 +123,11 @@
 test-merge7.t
 test-merge8.t
 test-mq-qimport-fail-cleanup.t
+test-mq-qsave.t
 test-obshistory.t
 test-obsolete-changeset-exchange.t
 test-obsolete-checkheads.t
+test-obsolete-distributed.t
 test-parents.t
 test-permissions.t
 test-pull-branch.t
@@ -154,6 +160,9 @@
 test-push-checkheads-unpushed-D6.t
 test-push-checkheads-unpushed-D7.t
 test-push-warn.t
+test-rebase-inmemory.t
+test-rebase-issue-noparam-single-rev.t
+test-rebase-transaction.t
 test-record.t
 test-rename-after-merge.t
 test-rename-dir-merge.t
@@ -164,6 +173,7 @@
 test-revlog-group-emptyiter.t
 test-revlog-mmapindex.t
 test-revlog-packentry.t
+test-revset-dirstate-parents.t
 test-revset-outgoing.t
 test-run-tests.py
 test-show-stack.t
@@ -176,6 +186,7 @@
 test-status-terse.t
 test-strip-cross.t
 test-strip.t
+test-unamend.t
 test-uncommit.t
 test-unified-test.t
 test-unrelated-pull.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


[PATCH 2 of 6] logcmdutil: hold makefilematcher/makehunksfilter() by changesetpriner (API)

2018-02-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1516511272 -32400
#  Sun Jan 21 14:07:52 2018 +0900
# Node ID fa4427fe64617b5822c383f8dfdf6704d16fe01f
# Parent  ca578149cc821eb207e2a844c6cf74e6b66f860c
logcmdutil: hold makefilematcher/makehunksfilter() by changesetpriner (API)

This merges self.matchfn and self.show(matchfn) into self._makefilematcher,
and does the same for hunksfilter. Because changesetprinter seems to have
too many optional arguments, makefilematcher() and makehunksfilter() will
be packed into one object by later patch.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3450,7 +3450,10 @@ def log(ui, repo, *pats, **opts):
 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
 
 ui.pager('log')
-displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
+displayer = logcmdutil.changesetdisplayer(ui, repo, opts,
+  makefilematcher=filematcher,
+  makehunksfilter=hunksfilter,
+  buffered=True)
 for rev in revs:
 ctx = repo[rev]
 copies = None
@@ -3460,16 +3463,7 @@ def log(ui, repo, *pats, **opts):
 rename = getrenamed(fn, rev)
 if rename:
 copies.append((fn, rename[0]))
-if filematcher:
-revmatchfn = filematcher(ctx)
-else:
-revmatchfn = None
-if hunksfilter:
-revhunksfilter = hunksfilter(ctx)
-else:
-revhunksfilter = None
-displayer.show(ctx, copies=copies, matchfn=revmatchfn,
-   hunksfilterfn=revhunksfilter)
+displayer.show(ctx, copies=copies)
 displayer.flush(ctx)
 
 displayer.close()
diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -886,7 +886,8 @@ def _incoming(displaychlist, subreporecu
 ui.status(_("no changes found\n"))
 return subreporecurse()
 ui.pager('incoming')
-displayer = logcmdutil.changesetdisplayer(ui, other, opts, buffered)
+displayer = logcmdutil.changesetdisplayer(ui, other, opts,
+  buffered=buffered)
 displaychlist(other, chlist, displayer)
 displayer.close()
 finally:
diff --git a/mercurial/logcmdutil.py b/mercurial/logcmdutil.py
--- a/mercurial/logcmdutil.py
+++ b/mercurial/logcmdutil.py
@@ -122,11 +122,13 @@ def changesetlabels(ctx):
 class changesetprinter(object):
 '''show changeset information when templating not requested.'''
 
-def __init__(self, ui, repo, matchfn=None, diffopts=None, buffered=False):
+def __init__(self, ui, repo, makefilematcher=None, makehunksfilter=None,
+ diffopts=None, buffered=False):
 self.ui = ui
 self.repo = repo
 self.buffered = buffered
-self.matchfn = matchfn
+self._makefilematcher = makefilematcher or (lambda ctx: None)
+self._makehunksfilter = makehunksfilter or (lambda ctx: None)
 self.diffopts = diffopts or {}
 self.header = {}
 self.hunk = {}
@@ -150,17 +152,16 @@ class changesetprinter(object):
 if self.footer:
 self.ui.write(self.footer)
 
-def show(self, ctx, copies=None, matchfn=None, hunksfilterfn=None,
- **props):
+def show(self, ctx, copies=None, **props):
 props = pycompat.byteskwargs(props)
 if self.buffered:
 self.ui.pushbuffer(labeled=True)
-self._show(ctx, copies, matchfn, hunksfilterfn, props)
+self._show(ctx, copies, props)
 self.hunk[ctx.rev()] = self.ui.popbuffer()
 else:
-self._show(ctx, copies, matchfn, hunksfilterfn, props)
+self._show(ctx, copies, props)
 
-def _show(self, ctx, copies, matchfn, hunksfilterfn, props):
+def _show(self, ctx, copies, props):
 '''show a single changeset or file revision'''
 changenode = ctx.node()
 rev = ctx.rev()
@@ -251,7 +252,7 @@ class changesetprinter(object):
   label='log.summary')
 self.ui.write("\n")
 
-self._showpatch(ctx, matchfn, hunksfilterfn=hunksfilterfn)
+self._showpatch(ctx)
 
 def _showobsfate(self, ctx):
 obsfate = templatekw.showobsfate(repo=self.repo, ctx=ctx, ui=self.ui)
@@ -265,9 +266,9 @@ class changesetprinter(object):
 '''empty method used by extension as a hook point
 '''
 
-def _showpatch(self, ctx, matchfn, hunksfilterfn=None):
-if not matchfn:
-matchfn = self.matchfn
+def _showpatch(self, ctx):
+matchfn = self._makefilematcher(ctx)
+hunksfilterfn = self._makehunksfilter(ctx)
 if matchfn:
 stat = self.diffopts.get('stat')
   

[PATCH 1 of 6] log: pass ctx to makefilematcher() and makehunksfilter() functions

2018-02-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1516509631 -32400
#  Sun Jan 21 13:40:31 2018 +0900
# Node ID ca578149cc821eb207e2a844c6cf74e6b66f860c
# Parent  b62c4154bb287fe0f4c15cdb0d2ef290069288df
log: pass ctx to makefilematcher() and makehunksfilter() functions

This isn't important, but seems more consisntent as changesetprinter.show()
takes a ctx, not a revision number.

diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -392,7 +392,7 @@ def overridelog(orig, ui, repo, *pats, *
 def overridemakefilematcher(repo, pats, opts, badfn=None):
 wctx = repo[None]
 match, pats = oldmatchandpats(wctx, pats, opts, badfn=badfn)
-return lambda rev: match
+return lambda ctx: match
 
 oldmatchandpats = installmatchandpatsfn(overridematchandpats)
 oldmakefilematcher = logcmdutil._makenofollowfilematcher
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3461,11 +3461,11 @@ def log(ui, repo, *pats, **opts):
 if rename:
 copies.append((fn, rename[0]))
 if filematcher:
-revmatchfn = filematcher(ctx.rev())
+revmatchfn = filematcher(ctx)
 else:
 revmatchfn = None
 if hunksfilter:
-revhunksfilter = hunksfilter(rev)
+revhunksfilter = hunksfilter(ctx)
 else:
 revhunksfilter = None
 displayer.show(ctx, copies=copies, matchfn=revmatchfn,
diff --git a/mercurial/logcmdutil.py b/mercurial/logcmdutil.py
--- a/mercurial/logcmdutil.py
+++ b/mercurial/logcmdutil.py
@@ -614,8 +614,8 @@ def _fileancestors(repo, revs, match, fo
 # revision, stored in "fcache". "fcache" is populated as a side effect
 # of the graph traversal.
 fcache = {}
-def filematcher(rev):
-return scmutil.matchfiles(repo, fcache.get(rev, []))
+def filematcher(ctx):
+return scmutil.matchfiles(repo, fcache.get(ctx.rev(), []))
 
 def revgen():
 for rev, cs in dagop.filectxancestors(fctxs, followfirst=followfirst):
@@ -709,7 +709,7 @@ def _initialrevs(repo, opts):
 def getrevs(repo, pats, opts):
 """Return (revs, filematcher) where revs is a smartset
 
-filematcher is a callable taking a revision number and returning a match
+filematcher is a callable taking a changectx and returning a match
 objects filtering the files to be detailed when displaying the revision.
 """
 follow = opts.get('follow') or opts.get('follow_first')
@@ -729,7 +729,7 @@ def getrevs(repo, pats, opts):
 if filematcher is None:
 filematcher = _makenofollowfilematcher(repo, pats, opts)
 if filematcher is None:
-def filematcher(rev):
+def filematcher(ctx):
 return match
 
 expr = _makerevset(repo, match, pats, slowpath, opts)
@@ -771,11 +771,11 @@ def getlinerangerevs(repo, userrevs, opt
 "revs" are revisions obtained by processing "line-range" log options and
 walking block ancestors of each specified file/line-range.
 
-"filematcher(rev) -> match" is a factory function returning a match object
+"filematcher(ctx) -> match" is a factory function returning a match object
 for a given revision for file patterns specified in --line-range option.
 If neither --stat nor --patch options are passed, "filematcher" is None.
 
-"hunksfilter(rev) -> filterfn(fctx, hunks)" is a factory function
+"hunksfilter(ctx) -> filterfn(fctx, hunks)" is a factory function
 returning a hunks filtering function.
 If neither --stat nor --patch options are passed, "filterhunks" is None.
 """
@@ -803,8 +803,8 @@ def getlinerangerevs(repo, userrevs, opt
 def nofilterhunksfn(fctx, hunks):
 return hunks
 
-def hunksfilter(rev):
-fctxlineranges = linerangesbyrev.get(rev)
+def hunksfilter(ctx):
+fctxlineranges = linerangesbyrev.get(ctx.rev())
 if fctxlineranges is None:
 return nofilterhunksfn
 
@@ -824,8 +824,8 @@ def getlinerangerevs(repo, userrevs, opt
 
 return filterfn
 
-def filematcher(rev):
-files = list(linerangesbyrev.get(rev, []))
+def filematcher(ctx):
+files = list(linerangesbyrev.get(ctx.rev(), []))
 return scmutil.matchfiles(repo, files)
 
 revs = sorted(linerangesbyrev, reverse=True)
@@ -886,7 +886,7 @@ def displaygraph(ui, repo, dag, displaye
 copies.append((fn, rename[0]))
 revmatchfn = None
 if filematcher is not None:
-revmatchfn = filematcher(ctx.rev())
+revmatchfn = filematcher(ctx)
 edges = edgefn(type, char, state, rev, parents)
 firstedge = next(edges)
 width = firstedge[2]
___

[PATCH 5 of 6] log: drop dead code to concatenate --line-range patterns and pats

2018-02-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1516517424 -32400
#  Sun Jan 21 15:50:24 2018 +0900
# Node ID f95d0d1e012a512550de945350e08f3dc7db090f
# Parent  03f30f86c95a3847be7bb7b89a8cc22d9abee524
log: drop dead code to concatenate --line-range patterns and pats

It's disabled since 2e45bbd3db7b, and the current implementation is unlikely
to be reused.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3428,20 +3428,9 @@ def log(ui, repo, *pats, **opts):
 return logcmdutil.graphlog(ui, repo, revs, filematcher, opts)
 
 if linerange:
-revs, lrfilematcher, hunksfilter = logcmdutil.getlinerangerevs(
+revs, filematcher, hunksfilter = logcmdutil.getlinerangerevs(
 repo, revs, opts)
 
-if filematcher is not None:
-basefilematcher = filematcher
-
-def filematcher(rev):
-files = (basefilematcher(rev).files()
- + lrfilematcher(rev).files())
-return scmutil.matchfiles(repo, files)
-
-elif filematcher is None:
-filematcher = lrfilematcher
-
 getrenamed = None
 if opts.get('copies'):
 endrev = None
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 6 of 6] log: pack filematcher and hunksfilter into changesetdiffer object

2018-02-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1516517658 -32400
#  Sun Jan 21 15:54:18 2018 +0900
# Node ID 5f9dcb5d72da427abbfa2c304bdbe4dd555e0c7d
# Parent  f95d0d1e012a512550de945350e08f3dc7db090f
log: pack filematcher and hunksfilter into changesetdiffer object

This is just a way of getting rid of clumsy makefilematcher/makehunksfilter
arguments. There might be a better abstraction, but I don't think this is bad.

This makes filematcher and hunksfilter available by default, but that should
be fine.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3419,17 +3419,15 @@ def log(ui, repo, *pats, **opts):
 )
 
 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
-revs, filematcher = logcmdutil.getrevs(repo, pats, opts)
-hunksfilter = None
+revs, differ = logcmdutil.getrevs(repo, pats, opts)
 
 if opts.get('graph'):
 if linerange:
 raise error.Abort(_('graph not supported with line range 
patterns'))
-return logcmdutil.graphlog(ui, repo, revs, filematcher, opts)
+return logcmdutil.graphlog(ui, repo, revs, differ, opts)
 
 if linerange:
-revs, filematcher, hunksfilter = logcmdutil.getlinerangerevs(
-repo, revs, opts)
+revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
 
 getrenamed = None
 if opts.get('copies'):
@@ -3439,9 +3437,7 @@ def log(ui, repo, *pats, **opts):
 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
 
 ui.pager('log')
-displayer = logcmdutil.changesetdisplayer(ui, repo, opts,
-  makefilematcher=filematcher,
-  makehunksfilter=hunksfilter,
+displayer = logcmdutil.changesetdisplayer(ui, repo, opts, differ,
   buffered=True)
 for rev in revs:
 ctx = repo[rev]
diff --git a/mercurial/logcmdutil.py b/mercurial/logcmdutil.py
--- a/mercurial/logcmdutil.py
+++ b/mercurial/logcmdutil.py
@@ -109,6 +109,23 @@ def diffordiffstat(ui, repo, diffopts, n
 sub.diff(ui, diffopts, tempnode2, submatch, changes=changes,
  stat=stat, fp=fp, prefix=prefix)
 
+class changesetdiffer(object):
+"""Generate diff of changeset with pre-configured filtering functions"""
+
+def _makefilematcher(self, ctx):
+return scmutil.matchall(ctx.repo())
+
+def _makehunksfilter(self, ctx):
+return None
+
+def showdiff(self, ui, ctx, diffopts, stat=False):
+repo = ctx.repo()
+node = ctx.node()
+prev = ctx.p1().node()
+diffordiffstat(ui, repo, diffopts, prev, node,
+   match=self._makefilematcher(ctx), stat=stat,
+   hunksfilterfn=self._makehunksfilter(ctx))
+
 def changesetlabels(ctx):
 labels = ['log.changeset', 'changeset.%s' % ctx.phasestr()]
 if ctx.obsolete():
@@ -122,13 +139,11 @@ def changesetlabels(ctx):
 class changesetprinter(object):
 '''show changeset information when templating not requested.'''
 
-def __init__(self, ui, repo, makefilematcher=None, makehunksfilter=None,
- diffopts=None, buffered=False):
+def __init__(self, ui, repo, differ=None, diffopts=None, buffered=False):
 self.ui = ui
 self.repo = repo
 self.buffered = buffered
-self._makefilematcher = makefilematcher or (lambda ctx: None)
-self._makehunksfilter = makehunksfilter or (lambda ctx: None)
+self._differ = differ or changesetdiffer()
 self.diffopts = diffopts or {}
 self.header = {}
 self.hunk = {}
@@ -267,35 +282,23 @@ class changesetprinter(object):
 '''
 
 def _showpatch(self, ctx):
-matchfn = self._makefilematcher(ctx)
-hunksfilterfn = self._makehunksfilter(ctx)
-if not matchfn:
-return
 stat = self.diffopts.get('stat')
 diff = self.diffopts.get('patch')
 diffopts = patch.diffallopts(self.ui, self.diffopts)
-node = ctx.node()
-prev = ctx.p1().node()
 if stat:
-diffordiffstat(self.ui, self.repo, diffopts, prev, node,
-   match=matchfn, stat=True,
-   hunksfilterfn=hunksfilterfn)
+self._differ.showdiff(self.ui, ctx, diffopts, stat=True)
 if stat and diff:
 self.ui.write("\n")
 if diff:
-diffordiffstat(self.ui, self.repo, diffopts, prev, node,
-   match=matchfn, stat=False,
-   hunksfilterfn=hunksfilterfn)
+self._differ.showdiff(self.ui, ctx, diffopts, stat=False)
 if stat or diff:
 self.ui.write("\n")
 
 class jsonchangeset(changesetprinter):
 '''format changeset information.'''
 
-def __init__(self, ui, repo, makefilematcher=None, 

[PATCH 3 of 6] logcmdutil: unindent diff generator of changesetprinter

2018-02-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1516513024 -32400
#  Sun Jan 21 14:37:04 2018 +0900
# Node ID 44e6702bf9cdef9d9df717b8632c1ba5a213b797
# Parent  fa4427fe64617b5822c383f8dfdf6704d16fe01f
logcmdutil: unindent diff generator of changesetprinter

Prepares for the next few patches which will make matchfn and hunksfilterfn
always available.

diff --git a/mercurial/logcmdutil.py b/mercurial/logcmdutil.py
--- a/mercurial/logcmdutil.py
+++ b/mercurial/logcmdutil.py
@@ -269,24 +269,25 @@ class changesetprinter(object):
 def _showpatch(self, ctx):
 matchfn = self._makefilematcher(ctx)
 hunksfilterfn = self._makehunksfilter(ctx)
-if matchfn:
-stat = self.diffopts.get('stat')
-diff = self.diffopts.get('patch')
-diffopts = patch.diffallopts(self.ui, self.diffopts)
-node = ctx.node()
-prev = ctx.p1().node()
-if stat:
-diffordiffstat(self.ui, self.repo, diffopts, prev, node,
-   match=matchfn, stat=True,
-   hunksfilterfn=hunksfilterfn)
-if diff:
-if stat:
-self.ui.write("\n")
-diffordiffstat(self.ui, self.repo, diffopts, prev, node,
-   match=matchfn, stat=False,
-   hunksfilterfn=hunksfilterfn)
-if stat or diff:
-self.ui.write("\n")
+if not matchfn:
+return
+stat = self.diffopts.get('stat')
+diff = self.diffopts.get('patch')
+diffopts = patch.diffallopts(self.ui, self.diffopts)
+node = ctx.node()
+prev = ctx.p1().node()
+if stat:
+diffordiffstat(self.ui, self.repo, diffopts, prev, node,
+   match=matchfn, stat=True,
+   hunksfilterfn=hunksfilterfn)
+if stat and diff:
+self.ui.write("\n")
+if diff:
+diffordiffstat(self.ui, self.repo, diffopts, prev, node,
+   match=matchfn, stat=False,
+   hunksfilterfn=hunksfilterfn)
+if stat or diff:
+self.ui.write("\n")
 
 class jsonchangeset(changesetprinter):
 '''format changeset information.'''
@@ -370,22 +371,21 @@ class jsonchangeset(changesetprinter):
 for k, v in copies))
 
 matchfn = self._makefilematcher(ctx)
-if matchfn:
-stat = self.diffopts.get('stat')
-diff = self.diffopts.get('patch')
-diffopts = patch.difffeatureopts(self.ui, self.diffopts, git=True)
-node, prev = ctx.node(), ctx.p1().node()
-if stat:
-self.ui.pushbuffer()
-diffordiffstat(self.ui, self.repo, diffopts, prev, node,
-   match=matchfn, stat=True)
-self.ui.write((',\n  "diffstat": "%s"')
-  % j(self.ui.popbuffer()))
-if diff:
-self.ui.pushbuffer()
-diffordiffstat(self.ui, self.repo, diffopts, prev, node,
-   match=matchfn, stat=False)
-self.ui.write((',\n  "diff": "%s"') % j(self.ui.popbuffer()))
+stat = self.diffopts.get('stat')
+diff = self.diffopts.get('patch')
+diffopts = patch.difffeatureopts(self.ui, self.diffopts, git=True)
+node, prev = ctx.node(), ctx.p1().node()
+if matchfn and stat:
+self.ui.pushbuffer()
+diffordiffstat(self.ui, self.repo, diffopts, prev, node,
+   match=matchfn, stat=True)
+self.ui.write((',\n  "diffstat": "%s"')
+  % j(self.ui.popbuffer()))
+if matchfn and diff:
+self.ui.pushbuffer()
+diffordiffstat(self.ui, self.repo, diffopts, prev, node,
+   match=matchfn, stat=False)
+self.ui.write((',\n  "diff": "%s"') % j(self.ui.popbuffer()))
 
 self.ui.write("\n }")
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 6] logcmdutil: create hunksfilter and filematcher even if no diff option given

2018-02-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1516516477 -32400
#  Sun Jan 21 15:34:37 2018 +0900
# Node ID 03f30f86c95a3847be7bb7b89a8cc22d9abee524
# Parent  44e6702bf9cdef9d9df717b8632c1ba5a213b797
logcmdutil: create hunksfilter and filematcher even if no diff option given

It's okay since 5fe6f946f111, "log: allow matchfn to be non-null even if both
--patch/--stat are off."

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3431,7 +3431,7 @@ def log(ui, repo, *pats, **opts):
 revs, lrfilematcher, hunksfilter = logcmdutil.getlinerangerevs(
 repo, revs, opts)
 
-if filematcher is not None and lrfilematcher is not None:
+if filematcher is not None:
 basefilematcher = filematcher
 
 def filematcher(rev):
diff --git a/mercurial/logcmdutil.py b/mercurial/logcmdutil.py
--- a/mercurial/logcmdutil.py
+++ b/mercurial/logcmdutil.py
@@ -779,11 +779,9 @@ def getlinerangerevs(repo, userrevs, opt
 
 "filematcher(ctx) -> match" is a factory function returning a match object
 for a given revision for file patterns specified in --line-range option.
-If neither --stat nor --patch options are passed, "filematcher" is None.
 
 "hunksfilter(ctx) -> filterfn(fctx, hunks)" is a factory function
 returning a hunks filtering function.
-If neither --stat nor --patch options are passed, "filterhunks" is None.
 """
 wctx = repo[None]
 
@@ -802,37 +800,33 @@ def getlinerangerevs(repo, userrevs, opt
 rev, {}).setdefault(
 fctx.path(), []).append(linerange)
 
-filematcher = None
-hunksfilter = None
-if opts.get('patch') or opts.get('stat'):
+def nofilterhunksfn(fctx, hunks):
+return hunks
 
-def nofilterhunksfn(fctx, hunks):
-return hunks
-
-def hunksfilter(ctx):
-fctxlineranges = linerangesbyrev.get(ctx.rev())
-if fctxlineranges is None:
-return nofilterhunksfn
+def hunksfilter(ctx):
+fctxlineranges = linerangesbyrev.get(ctx.rev())
+if fctxlineranges is None:
+return nofilterhunksfn
 
-def filterfn(fctx, hunks):
-lineranges = fctxlineranges.get(fctx.path())
-if lineranges is not None:
-for hr, lines in hunks:
-if hr is None: # binary
-yield hr, lines
-continue
-if any(mdiff.hunkinrange(hr[2:], lr)
-   for lr in lineranges):
-yield hr, lines
-else:
-for hunk in hunks:
-yield hunk
+def filterfn(fctx, hunks):
+lineranges = fctxlineranges.get(fctx.path())
+if lineranges is not None:
+for hr, lines in hunks:
+if hr is None: # binary
+yield hr, lines
+continue
+if any(mdiff.hunkinrange(hr[2:], lr)
+   for lr in lineranges):
+yield hr, lines
+else:
+for hunk in hunks:
+yield hunk
 
-return filterfn
+return filterfn
 
-def filematcher(ctx):
-files = list(linerangesbyrev.get(ctx.rev(), []))
-return scmutil.matchfiles(repo, files)
+def filematcher(ctx):
+files = list(linerangesbyrev.get(ctx.rev(), []))
+return scmutil.matchfiles(repo, files)
 
 revs = sorted(linerangesbyrev, reverse=True)
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D2022: ui: improve ui.write performance when not coloring on Windows

2018-02-07 Thread yuja (Yuya Nishihara)
yuja accepted this revision.
yuja added a comment.
This revision is now accepted and ready to land.


  Dropped `**opts` and queued, thanks.

REPOSITORY
  rHG Mercurial

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

To: joerg.sonnenberger, #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


D2022: ui: improve ui.write performance when not coloring on Windows

2018-02-07 Thread joerg.sonnenberger (Joerg Sonnenberger)
joerg.sonnenberger updated this revision to Diff 5293.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2022?vs=5181=5293

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

AFFECTED FILES
  mercurial/logcmdutil.py
  mercurial/ui.py

CHANGE DETAILS

diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -870,6 +870,17 @@
 
 return "".join(self._buffers.pop())
 
+def canwritewithoutlabels(self, **opts):
+'''check if write skips the label'''
+if self._buffers and not self._bufferapplylabels:
+return True
+return self._colormode is None
+
+def canbatchlabeledwrites(self, **opts):
+'''check if write calls with labels are batchable'''
+# Windows color printing is special, see ``write``.
+return self._colormode != 'win32'
+
 def write(self, *args, **opts):
 '''write args to output
 
diff --git a/mercurial/logcmdutil.py b/mercurial/logcmdutil.py
--- a/mercurial/logcmdutil.py
+++ b/mercurial/logcmdutil.py
@@ -79,18 +79,31 @@
 width = 80
 if not ui.plain():
 width = ui.termwidth()
-chunks = patch.diff(repo, node1, node2, match, changes, opts=diffopts,
-prefix=prefix, relroot=relroot,
-hunksfilterfn=hunksfilterfn)
-for chunk, label in patch.diffstatui(util.iterlines(chunks),
- width=width):
-write(chunk, label=label)
+
+chunks = patch.diff(repo, node1, node2, match, changes, opts=diffopts,
+prefix=prefix, relroot=relroot,
+hunksfilterfn=hunksfilterfn)
+
+if fp is not None or ui.canwritewithoutlabels():
+if stat:
+chunks = patch.diffstat(util.iterlines(chunks), width=width)
+for chunk in util.filechunkiter(util.chunkbuffer(chunks)):
+write(chunk)
 else:
-for chunk, label in patch.diffui(repo, node1, node2, match,
- changes, opts=diffopts, prefix=prefix,
- relroot=relroot,
- hunksfilterfn=hunksfilterfn):
-write(chunk, label=label)
+if stat:
+chunks = patch.diffstatui(util.iterlines(chunks), width=width)
+else:
+chunks = patch.difflabel(lambda chunks, **kwargs: chunks, chunks,
+ opts=diffopts)
+if ui.canbatchlabeledwrites():
+def gen():
+for chunk, label in chunks:
+yield ui.label(chunk, label=label)
+for chunk in util.filechunkiter(util.chunkbuffer(gen())):
+write(chunk)
+else:
+for chunk, label in chunks:
+write(chunk, label=label)
 
 if listsubrepos:
 ctx1 = repo[node1]



To: joerg.sonnenberger, #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


mercurial@35950: 30 new changesets (1 on stable)

2018-02-07 Thread Mercurial Commits
30 new changesets (1 on stable) in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/47e737d27e01
changeset:   35921:47e737d27e01
user:Matt Harbison 
date:Sat Jan 27 14:53:16 2018 -0500
summary: lfs: factor out a method for extracting the pointer of a single 
file

https://www.mercurial-scm.org/repo/hg/rev/0b79f99fd7b0
changeset:   35922:0b79f99fd7b0
user:Matt Harbison 
date:Sat Feb 03 21:26:12 2018 -0500
summary: lfs: prefetch lfs blobs when applying merge updates

https://www.mercurial-scm.org/repo/hg/rev/efbd04238029
changeset:   35923:efbd04238029
user:Matt Harbison 
date:Sun Feb 04 14:14:28 2018 -0500
summary: cmdutil: convert _revertprefetch() to a generic stored file hook 
(API)

https://www.mercurial-scm.org/repo/hg/rev/d857cad588e4
changeset:   35924:d857cad588e4
user:Matt Harbison 
date:Sun Feb 04 00:33:28 2018 -0500
summary: lfs: prefetch lfs blobs during revert

https://www.mercurial-scm.org/repo/hg/rev/533f04d4cb6d
changeset:   35925:533f04d4cb6d
user:Matt Harbison 
date:Sun Feb 04 14:31:32 2018 -0500
summary: archive: call the storage prefetch hook

https://www.mercurial-scm.org/repo/hg/rev/264b90a060b7
changeset:   35926:264b90a060b7
user:Matt Harbison 
date:Sun Feb 04 15:26:49 2018 -0500
summary: cat: call the storage prefetch hook

https://www.mercurial-scm.org/repo/hg/rev/9b413478f261
changeset:   35927:9b413478f261
user:Matt Harbison 
date:Sun Feb 04 16:17:43 2018 -0500
summary: lfs: deduplicate oids in the transfer

https://www.mercurial-scm.org/repo/hg/rev/b0d2885c5945
changeset:   35928:b0d2885c5945
user:Gregory Szorc 
date:Sun Feb 04 12:47:37 2018 -0800
summary: sshpeer: make "instance" a function

https://www.mercurial-scm.org/repo/hg/rev/5f029d03cf71
changeset:   35929:5f029d03cf71
user:Gregory Szorc 
date:Sat Feb 03 12:01:01 2018 -0800
summary: debugcommands: introduce debugpeer command

https://www.mercurial-scm.org/repo/hg/rev/83d67257ba90
changeset:   35930:83d67257ba90
user:Gregory Szorc 
date:Sun Feb 04 14:02:41 2018 -0800
summary: tests: add low-level SSH protocol tests

https://www.mercurial-scm.org/repo/hg/rev/b202d360d2a4
changeset:   35931:b202d360d2a4
user:Gregory Szorc 
date:Sun Feb 04 12:55:18 2018 -0800
summary: sshpeer: move URL validation out of sshpeer.__init__

https://www.mercurial-scm.org/repo/hg/rev/31449baf0936
changeset:   35932:31449baf0936
user:Gregory Szorc 
date:Sun Feb 04 19:23:40 2018 -0800
summary: sshpeer: move ssh command and repo creation logic out of __init__

https://www.mercurial-scm.org/repo/hg/rev/805edf16e8e0
changeset:   35933:805edf16e8e0
user:Gregory Szorc 
date:Sun Feb 04 11:37:19 2018 -0800
summary: sshpeer: extract pipe cleanup logic to own function

https://www.mercurial-scm.org/repo/hg/rev/94ba29934f00
changeset:   35934:94ba29934f00
user:Gregory Szorc 
date:Sun Feb 04 11:40:13 2018 -0800
summary: sshpeer: remove frivolous call to _cleanup()

https://www.mercurial-scm.org/repo/hg/rev/00b9e26d727b
changeset:   35935:00b9e26d727b
user:Gregory Szorc 
date:Mon Feb 05 14:05:59 2018 -0800
summary: sshpeer: establish SSH connection before class instantiation

https://www.mercurial-scm.org/repo/hg/rev/f8f034344b39
changeset:   35936:f8f034344b39
user:Gregory Szorc 
date:Mon Feb 05 14:17:24 2018 -0800
summary: sshpeer: clean up API for sshpeer.__init__ (API)

https://www.mercurial-scm.org/repo/hg/rev/a9cffd14aa04
changeset:   35937:a9cffd14aa04
user:Gregory Szorc 
date:Sun Feb 04 14:10:56 2018 -0800
summary: sshpeer: inline I/O into _validaterepo()

https://www.mercurial-scm.org/repo/hg/rev/80a2b8ae42a1
changeset:   35938:80a2b8ae42a1
user:Gregory Szorc 
date:Mon Feb 05 09:14:32 2018 -0800
summary: sshpeer: move handshake outside of sshpeer

https://www.mercurial-scm.org/repo/hg/rev/a622a927fe03
changeset:   35939:a622a927fe03
user:Gregory Szorc 
date:Sun Feb 04 14:44:04 2018 -0800
summary: sshpeer: document the handshake mechanism

https://www.mercurial-scm.org/repo/hg/rev/556218e08e25
changeset:   35940:556218e08e25
user:Gregory Szorc 
date:Sun Feb 04 14:58:32 2018 -0800
summary: sshpeer: remove support for connecting to <0.9.1 servers (BC)


Re: [PATCH 2 of 2] ui: add explicit path to write prompt text bypassing buffers

2018-02-07 Thread Augie Fackler


> On Feb 5, 2018, at 13:11, Yuya Nishihara  wrote:
> 
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1517831331 -32400
> #  Mon Feb 05 20:48:51 2018 +0900
> # Node ID 59869758acd7b38d9de045d5a72f5196cc80f047
> # Parent  9be8a0f8d48502734066a66e3d5b9b22e460ae70
> ui: add explicit path to write prompt text bypassing buffers

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


Re: [PATCH 3 of 3] logcmdutil: mark changesetprinter.showpatch() as private

2018-02-07 Thread Augie Fackler


> On Feb 4, 2018, at 12:18, Yuya Nishihara  wrote:
> 
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1516510856 -32400
> #  Sun Jan 21 14:00:56 2018 +0900
> # Node ID 4d7182357056c2672716d7caf849231d7b25691a
> # Parent  f1a8a49af81a97618a4b1eb7e78c7372db776cdc
> logcmdutil: mark changesetprinter.showpatch() as private

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


Re: [PATCH 2 of 2] mdiff: use str.startswith/endswith() instead of slicing

2018-02-07 Thread Augie Fackler


> On Feb 4, 2018, at 12:17, Yuya Nishihara  wrote:
> 
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1517707994 -32400
> #  Sun Feb 04 10:33:14 2018 +0900
> # Node ID 16b4cc4f0cd6f72f5b7be575a7498ed0017ccea5
> # Parent  d41b22b06360ceee3a9e6e66df5f57f267318314
> mdiff: use str.startswith/endswith() instead of slicing

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


Re: [PATCH STABLE] fileset: don't abort when running copied() on a revision with a removed file

2018-02-07 Thread Augie Fackler


> On Feb 7, 2018, at 05:58, Matt Harbison  wrote:
> 
> # HG changeset patch
> # User Matt Harbison 
> # Date 1517979217 18000
> #  Tue Feb 06 23:53:37 2018 -0500
> # Branch stable
> # Node ID 7b2b82f891bf6355ed87c06ed9198bfcd033fe7d
> # Parent  1d60ad093792706e1dc7a52b20942593f2c19655
> fileset: don't abort when running copied() on a revision with a removed file

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


D2078: python3: whitelist an additional 11 tests

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

REVISION SUMMARY
  I think these are mostly the result of Pulkit's recent work. Thanks!

REPOSITORY
  rHG Mercurial

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

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
@@ -3,6 +3,7 @@
 test-addremove.t
 test-amend-subrepo.t
 test-ancestor.py
+test-annotate.py
 test-automv.t
 test-backwards-remove.t
 test-bheads.t
@@ -29,8 +30,10 @@
 test-confused-revert.t
 test-contrib-check-code.t
 test-contrib-check-commit.t
+test-copy-move-merge.t
 test-debugindexdot.t
 test-debugrename.t
+test-diff-binary-file.t
 test-diff-change.t
 test-diff-copy-depth.t
 test-diff-hashes.t
@@ -74,6 +77,7 @@
 test-exchange-obsmarkers-case-D3.t
 test-exchange-obsmarkers-case-D4.t
 test-execute-bit.t
+test-extra-filelog-entry.t
 test-filebranch.t
 test-flags.t
 test-generaldelta.t
@@ -119,9 +123,11 @@
 test-merge7.t
 test-merge8.t
 test-mq-qimport-fail-cleanup.t
+test-mq-qsave.t
 test-obshistory.t
 test-obsolete-changeset-exchange.t
 test-obsolete-checkheads.t
+test-obsolete-distributed.t
 test-parents.t
 test-permissions.t
 test-pull-branch.t
@@ -154,6 +160,9 @@
 test-push-checkheads-unpushed-D6.t
 test-push-checkheads-unpushed-D7.t
 test-push-warn.t
+test-rebase-inmemory.t
+test-rebase-issue-noparam-single-rev.t
+test-rebase-transaction.t
 test-record.t
 test-rename-after-merge.t
 test-rename-dir-merge.t
@@ -164,6 +173,7 @@
 test-revlog-group-emptyiter.t
 test-revlog-mmapindex.t
 test-revlog-packentry.t
+test-revset-dirstate-parents.t
 test-revset-outgoing.t
 test-run-tests.py
 test-show-stack.t
@@ -176,6 +186,7 @@
 test-status-terse.t
 test-strip-cross.t
 test-strip.t
+test-unamend.t
 test-uncommit.t
 test-unified-test.t
 test-unrelated-pull.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


D2076: py3: use bytes instead of str

2018-02-07 Thread pulkit (Pulkit Goyal)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGf87641bf4d23: py3: use bytes instead of str (authored by 
pulkit, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2076?vs=5282=5290

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

AFFECTED FILES
  hgext/mq.py

CHANGE DETAILS

diff --git a/hgext/mq.py b/hgext/mq.py
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -1272,7 +1272,7 @@
 if msg == defaultmsg.strip():
 msg = ''
 ph.setmessage(msg)
-p.write(str(ph))
+p.write(bytes(ph))
 if commitfiles:
 parent = self.qparents(repo, n)
 if inclsubs:
@@ -1853,7 +1853,7 @@
 self.putsubstate2changes(substatestate, c)
 chunks = patchmod.diff(repo, patchparent,
changes=c, opts=diffopts)
-comments = str(ph)
+comments = bytes(ph)
 if comments:
 patchf.write(comments)
 for chunk in chunks:



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


  1   2   >