[PATCH V5] forget: add --dry-run mode

2018-03-13 Thread Sushil khanchi
# HG changeset patch
# User Sushil khanchi 
# Date 1520665399 -19800
#  Sat Mar 10 12:33:19 2018 +0530
# Node ID bd9d29c4c929d0495e874d0c35d96cae29f5ff72
# Parent  4c71a26a4009d88590c9ae3d64a5912fd556d82e
forget: add --dry-run mode

diff -r 4c71a26a4009 -r bd9d29c4c929 mercurial/cmdutil.py
--- a/mercurial/cmdutil.py  Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/cmdutil.py  Sat Mar 10 12:33:19 2018 +0530
@@ -1996,7 +1996,7 @@
 for subpath in ctx.substate:
 ctx.sub(subpath).addwebdirpath(serverpath, webconf)
 
-def forget(ui, repo, match, prefix, explicitonly):
+def forget(ui, repo, match, prefix, explicitonly, dryrun):
 join = lambda f: os.path.join(prefix, f)
 bad = []
 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
@@ -2012,7 +2012,7 @@
 sub = wctx.sub(subpath)
 try:
 submatch = matchmod.subdirmatcher(subpath, match)
-subbad, subforgot = sub.forget(submatch, prefix)
+subbad, subforgot = sub.forget(submatch, prefix, dryrun=dryrun)
 bad.extend([subpath + '/' + f for f in subbad])
 forgot.extend([subpath + '/' + f for f in subforgot])
 except error.LookupError:
@@ -2039,9 +2039,10 @@
 if ui.verbose or not match.exact(f):
 ui.status(_('removing %s\n') % match.rel(f))
 
-rejected = wctx.forget(forget, prefix)
-bad.extend(f for f in rejected if f in match.files())
-forgot.extend(f for f in forget if f not in rejected)
+if not dryrun:
+rejected = wctx.forget(forget, prefix)
+bad.extend(f for f in rejected if f in match.files())
+forgot.extend(f for f in forget if f not in rejected)
 return bad, forgot
 
 def files(ui, ctx, m, fm, fmt, subrepos):
diff -r 4c71a26a4009 -r bd9d29c4c929 mercurial/commands.py
--- a/mercurial/commands.py Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/commands.py Sat Mar 10 12:33:19 2018 +0530
@@ -2036,7 +2036,10 @@
 with ui.formatter('files', opts) as fm:
 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
 
-@command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
+@command(
+'^forget',
+walkopts + dryrunopts,
+_('[OPTION]... FILE...'), inferrepo=True)
 def forget(ui, repo, *pats, **opts):
 """forget the specified files on the next commit
 
@@ -2071,7 +2074,9 @@
 raise error.Abort(_('no files specified'))
 
 m = scmutil.match(repo[None], pats, opts)
-rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
+dryrun = opts.get(r'dry_run')
+rejected = cmdutil.forget(ui, repo, m, prefix="",
+  explicitonly=False, dryrun=dryrun)[0]
 return rejected and 1 or 0
 
 @command(
diff -r 4c71a26a4009 -r bd9d29c4c929 mercurial/subrepo.py
--- a/mercurial/subrepo.py  Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/subrepo.py  Sat Mar 10 12:33:19 2018 +0530
@@ -811,9 +811,10 @@
 return ctx.walk(match)
 
 @annotatesubrepoerror
-def forget(self, match, prefix):
+def forget(self, match, prefix, dryrun):
 return cmdutil.forget(self.ui, self._repo, match,
-  self.wvfs.reljoin(prefix, self._path), True)
+  self.wvfs.reljoin(prefix, self._path),
+  True, dryrun=dryrun)
 
 @annotatesubrepoerror
 def removefiles(self, matcher, prefix, after, force, subrepos, warnings):
diff -r 4c71a26a4009 -r bd9d29c4c929 tests/test-commit.t
--- a/tests/test-commit.t   Sun Mar 04 21:16:36 2018 -0500
+++ b/tests/test-commit.t   Sat Mar 10 12:33:19 2018 +0530
@@ -832,3 +832,18 @@
 
   $ cd ..
 
+test --dry-run mode in forget
+
+  $ hg init testdir_forget
+  $ cd testdir_forget
+  $ echo foo > foo
+  $ hg add foo
+  $ hg commit -m "foo"
+  $ hg forget foo --dry-run -v
+  removing foo
+  $ hg diff
+  $ hg forget not_exist -n
+  not_exist: $ENOENT$
+  [1]
+
+  $ cd ..
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D2854: hgweb: str/bytes followups after indygreg's refactoring

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


  parsedrequest.headers is supposed to be bytes. One of the goals of this 
refactor was to make the WSGI code all bytes all the time. So if system strings 
are making their way to the new request or response objects (i.e. outside 
request.py), then something is wrong and we should fix that: we shouldn’t need 
to introduce raw literals outside of the very low level WSGI code.

REPOSITORY
  rHG Mercurial

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

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


D2776: hgweb: use a multidict for holding query string parameters

2018-03-13 Thread martinvonz (Martin von Zweigbergk)
martinvonz added inline comments.

INLINE COMMENTS

> request.py:39-41
> +# Stores (key, value) 2-tuples. This isn't the most efficient. But we
> +# don't rely on parameters that much, so it shouldn't be a perf 
> issue.
> +# we can always add dict for fast lookups.

Sure, that's probably fine, but why? Wouldn't it be easier to write it as dict 
of lists anyway?

> request.py:45
> +def __getitem__(self, key):
> +"""Returns the last set value for a key."""
> +for k, v in reversed(self._items):

Would it make sense to make this an error if there isn't exactly one value?

REPOSITORY
  rHG Mercurial

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

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


Re: [PATCH] peer-request: include more details about batch commands

2018-03-13 Thread Augie Fackler


> On Mar 13, 2018, at 12:39, Boris Feld  wrote:
> 
> # HG changeset patch
> # User Boris Feld 
> # Date 1520268508 18000
> #  Mon Mar 05 11:48:28 2018 -0500
> # Node ID 025b0a829b1c9a299b76b7303b4d46c269fcba48
> # Parent  31581528f2421dc5d8a567125b8ecc0367b2b906
> # EXP-Topic peer-request.batch
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
> 025b0a829b1c
> peer-request: include more details about batch commands

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


D2854: hgweb: str/bytes followups after indygreg's refactoring

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

REVISION SUMMARY
  As of this change, we're mostly principled about using native strings
  (so bytes on 2, unicode on 3) for accessing HTTP headers. This
  restores test-getbundle.t (probably among others) to passing on Python
  3.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/hgweb/common.py
  mercurial/hgweb/hgweb_mod.py
  mercurial/hgweb/hgwebdir_mod.py
  mercurial/hgweb/request.py
  mercurial/hgweb/server.py
  mercurial/wireprotoserver.py

CHANGE DETAILS

diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -29,9 +29,9 @@
 
 HTTP_OK = 200
 
-HGTYPE = 'application/mercurial-0.1'
-HGTYPE2 = 'application/mercurial-0.2'
-HGERRTYPE = 'application/hg-error'
+HGTYPE = r'application/mercurial-0.1'
+HGTYPE2 = r'application/mercurial-0.2'
+HGERRTYPE = r'application/hg-error'
 
 SSHV1 = wireprototypes.SSHV1
 SSHV2 = wireprototypes.SSHV2
@@ -44,7 +44,7 @@
 chunks = []
 i = 1
 while True:
-v = req.headers.get(b'%s-%d' % (headerprefix, i))
+v = req.headers.get(r'%s-%d' % (headerprefix, i))
 if v is None:
 break
 chunks.append(pycompat.bytesurl(v))
@@ -79,23 +79,23 @@
 
 def _args(self):
 args = self._req.qsparams.asdictoflists()
-postlen = int(self._req.headers.get(b'X-HgArgs-Post', 0))
+postlen = int(self._req.headers.get(r'X-HgArgs-Post', 0))
 if postlen:
 args.update(urlreq.parseqs(
 self._req.bodyfh.read(postlen), keep_blank_values=True))
 return args
 
-argvalue = decodevaluefromheaders(self._req, b'X-HgArg')
+argvalue = decodevaluefromheaders(self._req, r'X-HgArg')
 args.update(urlreq.parseqs(argvalue, keep_blank_values=True))
 return args
 
 def forwardpayload(self, fp):
 # Existing clients *always* send Content-Length.
-length = int(self._req.headers[b'Content-Length'])
+length = int(self._req.headers[r'Content-Length'])
 
 # If httppostargs is used, we need to read Content-Length
 # minus the amount that was consumed by args.
-length -= int(self._req.headers.get(b'X-HgArgs-Post', 0))
+length -= int(self._req.headers.get(r'X-HgArgs-Post', 0))
 for s in util.filechunkiter(self._req.bodyfh, limit=length):
 fp.write(s)
 
@@ -189,7 +189,7 @@
 # in this case. We send an HTTP 404 for backwards compatibility reasons.
 if req.dispatchpath:
 res.status = hgwebcommon.statusmessage(404)
-res.headers['Content-Type'] = HGTYPE
+res.headers[r'Content-Type'] = HGTYPE
 # TODO This is not a good response to issue for this request. This
 # is mostly for BC for now.
 res.setbodybytes('0\n%s\n' % b'Not Found')
@@ -207,7 +207,7 @@
 except hgwebcommon.ErrorResponse as e:
 for k, v in e.headers:
 res.headers[k] = v
-res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
+res.status = hgwebcommon.statusmessage(e.code, e)
 # TODO This response body assumes the failed command was
 # "unbundle." That assumption is not always valid.
 res.setbodybytes('0\n%s\n' % pycompat.bytestr(e))
@@ -271,11 +271,11 @@
 
 def setresponse(code, contenttype, bodybytes=None, bodygen=None):
 if code == HTTP_OK:
-res.status = '200 Script output follows'
+res.status = r'200 Script output follows'
 else:
 res.status = hgwebcommon.statusmessage(code)
 
-res.headers['Content-Type'] = contenttype
+res.headers[r'Content-Type'] = pycompat.strurl(contenttype)
 
 if bodybytes is not None:
 res.setbodybytes(bodybytes)
diff --git a/mercurial/hgweb/server.py b/mercurial/hgweb/server.py
--- a/mercurial/hgweb/server.py
+++ b/mercurial/hgweb/server.py
@@ -101,7 +101,7 @@
 try:
 self.do_write()
 except Exception:
-self._start_response("500 Internal Server Error", [])
+self._start_response(r"500 Internal Server Error", [])
 self._write("Internal Server Error")
 self._done()
 tb = r"".join(traceback.format_exception(*sys.exc_info()))
@@ -136,26 +136,26 @@
 env[r'CONTENT_TYPE'] = self.headers.get_default_type()
 else:
 env[r'CONTENT_TYPE'] = self.headers.get_content_type()
-length = self.headers.get('content-length')
+length = self.headers.get(r'content-length')
 else:
 if self.headers.typeheader is None:
 env[r'CONTENT_TYPE'] = self.headers.type
 else:
 env[r'CONTENT_TYPE'] = self.headers.typeheader
-length = 

D2847: remotenames: work around move of ABCs in collections

2018-03-13 Thread durin42 (Augie Fackler)
durin42 updated this revision to Diff 7021.
durin42 edited the summary of this revision.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2847?vs=7004=7021

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

AFFECTED FILES
  hgext/remotenames.py

CHANGE DETAILS

diff --git a/hgext/remotenames.py b/hgext/remotenames.py
--- a/hgext/remotenames.py
+++ b/hgext/remotenames.py
@@ -23,6 +23,11 @@
 from __future__ import absolute_import
 
 import collections
+try:
+from collections import abc
+mutablemapping = abc.MutableMapping
+except ImportError:
+mutablemapping = collections.MutableMapping
 
 from mercurial.i18n import _
 
@@ -56,7 +61,7 @@
 default=True,
 )
 
-class lazyremotenamedict(collections.MutableMapping):
+class lazyremotenamedict(mutablemapping):
 """
 Read-only dict-like Class to lazily resolve remotename entries
 



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


D2853: tests: add a cat of `error.log` in subrepo test

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

REVISION SUMMARY
  This made some debugging a lot less painful when something was broken,
  and it costs us almost nothing, so I figure we may as well leave it
  in.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  tests/test-subrepo-deep-nested-change.t

CHANGE DETAILS

diff --git a/tests/test-subrepo-deep-nested-change.t 
b/tests/test-subrepo-deep-nested-change.t
--- a/tests/test-subrepo-deep-nested-change.t
+++ b/tests/test-subrepo-deep-nested-change.t
@@ -114,6 +114,7 @@
   * "GET /?cmd=batch HTTP/1.1" 200 - * (glob)
   * "GET /?cmd=getbundle HTTP/1.1" 200 - * (glob)
   * "GET /../sub1?cmd=capabilities HTTP/1.1" 404 - (glob)
+  $ cat error.log
 
   $ killdaemons.py
   $ rm hg1.pid error.log access.log



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


D2836: wireproto: define permissions-based routing of HTTPv2 wire protocol

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 7014.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2836?vs=7010=7014

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

AFFECTED FILES
  mercurial/debugcommands.py
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoserver.py
  tests/test-http-api-httpv2.t

CHANGE DETAILS

diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t
--- a/tests/test-http-api-httpv2.t
+++ b/tests/test-http-api-httpv2.t
@@ -1,3 +1,5 @@
+  $ HTTPV2=exp-http-v2-0001
+
   $ send() {
   >   hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT/
   > }
@@ -13,7 +15,7 @@
 HTTP v2 protocol not enabled by default
 
   $ send << EOF
-  > httprequest GET api/exp-http-v2-0001
+  > httprequest GET api/$HTTPV2
   > user-agent: test
   > EOF
   using raw connection to peer
@@ -43,14 +45,14 @@
   $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
   $ cat hg.pid > $DAEMON_PIDS
 
-Requests simply echo their path (for now)
+Request to read-only command works out of the box
 
   $ send << EOF
-  > httprequest GET api/exp-http-v2-0001/path1/path2
+  > httprequest GET api/$HTTPV2/ro/capabilities
   > user-agent: test
   > EOF
   using raw connection to peer
-  s> GET /api/exp-http-v2-0001/path1/path2 HTTP/1.1\r\n
+  s> GET /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> user-agent: test\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
@@ -60,6 +62,178 @@
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
   s> Content-Type: text/plain\r\n
-  s> Content-Length: 12\r\n
+  s> Content-Length: 16\r\n
+  s> \r\n
+  s> ro/capabilities\n
+
+Request to unknown command yields 404
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/ro/badcommand
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/ro/badcommand HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 404 Not Found\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 42\r\n
+  s> \r\n
+  s> unknown wire protocol command: badcommand\n
+
+Request to read-write command fails because server is read-only by default
+
+GET to read-write request not allowed
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/rw/capabilities
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/rw/capabilities HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 405 push requires POST request\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Length: 17\r\n
+  s> \r\n
+  s> permission denied
+
+Even for unknown commands
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/rw/badcommand
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/rw/badcommand HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 405 push requires POST request\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Length: 17\r\n
+  s> \r\n
+  s> permission denied
+
+SSL required by default
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/rw/capabilities
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/rw/capabilities HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 403 ssl required\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Length: 17\r\n
   s> \r\n
-  s> path1/path2\n
+  s> permission denied
+
+Restart server to allow non-ssl read-write operations
+
+  $ killdaemons.py
+  $ cat > server/.hg/hgrc << EOF
+  > [experimental]
+  > web.apiserver = true
+  > web.api.http-v2 = true
+  > [web]
+  > push_ssl = false
+  > EOF
+
+  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
+  $ cat hg.pid > $DAEMON_PIDS
+
+Server insists on POST for read-write commands
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/rw/capabilities
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/rw/capabilities HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> 

D2852: wireproto: implement basic frame reading and processing

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

REVISION SUMMARY
  We just implemented support for writing frames. Now let's implement
  support for reading them.
  
  The bulk of the new code is for a class that maintains the state of
  a server. Essentially, you construct an instance, feed frames to it,
  and it tells you what you should do next. The design is inspired by
  the "sans I/O" movement and the reactor pattern. We don't want to
  perform I/O or any major blocking event during frame ingestion because
  this arbitrarily limits ways that server pieces can be implemented.
  For example, it makes it much harder to swap in an alternate
  implementation based on asyncio or do crazy things like have requests
  dispatch to other processes.
  
  We do still implement readframe() which does I/O. But it is decoupled
  from the server reactor.
  
  Because testing server-side ingest is useful and difficult on running
  servers, we create a new "debugreflect" endpoint that will echo back
  to the client what was received and how it was interpreted. This could
  be useful for a server admin, someone implementing a client. But
  immediately, it is useful for testing: we're able to demonstrate that
  frames are parsed correctly and turned into requests to run commands
  without having to implement command dispatch on the server!

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/configitems.py
  mercurial/util.py
  mercurial/wireprotoframing.py
  mercurial/wireprotoserver.py
  tests/test-http-api-httpv2.t

CHANGE DETAILS

diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t
--- a/tests/test-http-api-httpv2.t
+++ b/tests/test-http-api-httpv2.t
@@ -261,7 +261,7 @@
   > allow-push = *
   > EOF
 
-  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
+  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid -E error.log
   $ cat hg.pid > $DAEMON_PIDS
 
 Authorized request for valid read-write command works
@@ -314,3 +314,441 @@
   s> Content-Length: 42\r\n
   s> \r\n
   s> unknown wire protocol command: badcommand\n
+
+debugreflect isn't enabled by default
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/ro/debugreflect
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/ro/debugreflect HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 404 Not Found\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 34\r\n
+  s> \r\n
+  s> debugreflect service not available
+
+Restart server to get debugreflect endpoint
+
+  $ killdaemons.py
+  $ cat > server/.hg/hgrc << EOF
+  > [experimental]
+  > web.apiserver = true
+  > web.api.debugreflect = true
+  > web.api.http-v2 = true
+  > [web]
+  > push_ssl = false
+  > allow-push = *
+  > EOF
+
+  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid -E error.log
+  $ cat hg.pid > $DAEMON_PIDS
+
+Single command frame is decoded
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/ro/debugreflect
+  > accept: $MEDIATYPE
+  > content-type: $MEDIATYPE
+  > user-agent: test
+  > frame command-name eos command1
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/ro/debugreflect HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> accept: application/mercurial-exp-framing-0001\r\n
+  s> content-type: application/mercurial-exp-framing-0001\r\n
+  s> user-agent: test\r\n
+  s> content-length: 12\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> \x08\x00\x00\x11command1
+  s> makefile('rb', None)
+  s> HTTP/1.1 200 OK\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 117\r\n
+  s> \r\n
+  s> received: 1 1 command1\n
+  s> {"action": "runcommand", "args": {}, "command": "command1", "data": 
null}\n
+  s> received: 
+
+Single argument frame is received
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/ro/debugreflect
+  > accept: $MEDIATYPE
+  > content-type: $MEDIATYPE
+  > user-agent: test
+  > frame command-name have-args command1
+  > frame command-argument eoa \x03\x00\x05\x00foovalue
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/ro/debugreflect HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> accept: application/mercurial-exp-framing-0001\r\n
+  s> content-type: application/mercurial-exp-framing-0001\r\n
+  s> user-agent: test\r\n
+  s> content-length: 28\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> 

D2837: wireproto: require POST for all HTTPv2 requests

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 7015.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2837?vs=7011=7015

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

AFFECTED FILES
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoserver.py
  tests/test-http-api-httpv2.t

CHANGE DETAILS

diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t
--- a/tests/test-http-api-httpv2.t
+++ b/tests/test-http-api-httpv2.t
@@ -48,11 +48,11 @@
 Request to read-only command works out of the box
 
   $ send << EOF
-  > httprequest GET api/$HTTPV2/ro/capabilities
+  > httprequest POST api/$HTTPV2/ro/capabilities
   > user-agent: test
   > EOF
   using raw connection to peer
-  s> GET /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
+  s> POST /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> user-agent: test\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
@@ -69,11 +69,11 @@
 Request to unknown command yields 404
 
   $ send << EOF
-  > httprequest GET api/$HTTPV2/ro/badcommand
+  > httprequest POST api/$HTTPV2/ro/badcommand
   > user-agent: test
   > EOF
   using raw connection to peer
-  s> GET /api/exp-http-v2-0001/ro/badcommand HTTP/1.1\r\n
+  s> POST /api/exp-http-v2-0001/ro/badcommand HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> user-agent: test\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
@@ -87,9 +87,30 @@
   s> \r\n
   s> unknown wire protocol command: badcommand\n
 
+GET to read-only command yields a 405
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/ro/capabilities
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 405 Method Not Allowed\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Allow: POST\r\n
+  s> Content-Length: 30\r\n
+  s> \r\n
+  s> commands require POST requests
+
 Request to read-write command fails because server is read-only by default
 
-GET to read-write request not allowed
+GET to read-write request yields 405
 
   $ send << EOF
   > httprequest GET api/$HTTPV2/rw/capabilities
@@ -102,12 +123,13 @@
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> \r\n
   s> makefile('rb', None)
-  s> HTTP/1.1 405 push requires POST request\r\n
+  s> HTTP/1.1 405 Method Not Allowed\r\n
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
-  s> Content-Length: 17\r\n
+  s> Allow: POST\r\n
+  s> Content-Length: 30\r\n
   s> \r\n
-  s> permission denied
+  s> commands require POST requests
 
 Even for unknown commands
 
@@ -122,12 +144,13 @@
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> \r\n
   s> makefile('rb', None)
-  s> HTTP/1.1 405 push requires POST request\r\n
+  s> HTTP/1.1 405 Method Not Allowed\r\n
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
-  s> Content-Length: 17\r\n
+  s> Allow: POST\r\n
+  s> Content-Length: 30\r\n
   s> \r\n
-  s> permission denied
+  s> commands require POST requests
 
 SSL required by default
 
@@ -158,38 +181,6 @@
   > web.api.http-v2 = true
   > [web]
   > push_ssl = false
-  > EOF
-
-  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
-  $ cat hg.pid > $DAEMON_PIDS
-
-Server insists on POST for read-write commands
-
-  $ send << EOF
-  > httprequest GET api/$HTTPV2/rw/capabilities
-  > user-agent: test
-  > EOF
-  using raw connection to peer
-  s> GET /api/exp-http-v2-0001/rw/capabilities HTTP/1.1\r\n
-  s> Accept-Encoding: identity\r\n
-  s> user-agent: test\r\n
-  s> host: $LOCALIP:$HGPORT\r\n (glob)
-  s> \r\n
-  s> makefile('rb', None)
-  s> HTTP/1.1 405 push requires POST request\r\n
-  s> Server: testing stub value\r\n
-  s> Date: $HTTP_DATE$\r\n
-  s> Content-Length: 17\r\n
-  s> \r\n
-  s> permission denied
-
-  $ killdaemons.py
-  $ cat > server/.hg/hgrc << EOF
-  > [experimental]
-  > web.apiserver = true
-  > web.api.http-v2 = true
-  > [web]
-  > push_ssl = false
   > allow-push = *
   > EOF
 
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -299,6 +299,12 @@
 res.setbodybytes(_('unknown permission: %s') % permission)
 return
 
+if req.method != 'POST':
+res.status = b'405 Method Not Allowed'
+res.headers[b'Allow'] = b'POST'
+res.setbodybytes(_('commands require POST requests'))
+return
+
 # At some point we'll want to use our own API instead of recycling the
 # behavior of version 1 of the wire protocol...
 # TODO return reasonable responses - 

D2851: wireproto: define and implement protocol for issuing requests

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

REVISION SUMMARY
  The existing HTTP and SSH wire protocols suffer from a host of flaws
  and shortcomings. I've been wanting to rewrite the protocol for a while
  now. Supporting partial clone - which will require new wire protocol
  commands and capabilities - and other advanced server functionality
  will be much easier if we start from a clean slate and don't have
  to be constrained by limitations of the existing wire protocol.
  
  This commit starts to introduce a new data exchange format for
  use over the wire protocol.
  
  The new protocol is built on top of "frames," which are atomic
  units of metadata + data. Frames will make it easier to implement
  proxies and other mechanisms that want to inspect data without
  having to maintain state. The existing frame metadata is very
  minimal and it will evolve heavily. (We will eventually support
  things like concurrent requests, out-of-order responses,
  compression, side-channels for status updates, etc. Some of
  these will require additions to the frame header.)
  
  Another benefit of frames is that all reads are of a fixed size.
  A reader works by consuming a frame header, extracting the payload
  length, then reading that many bytes. No lookahead, buffering, or
  memory reallocations are needed.
  
  The new protocol attempts to be transport agnostic. I want all that's
  required to use the new protocol to be a pair of unidirectional,
  half-duplex pipes. (Yes, we will eventually make use of full-duplex
  pipes, but that's for another commit.) Notably, when the SSH
  transport switches to this new protocol, stderr will be unused.
  This is by design: the lack of stderr on HTTP harms protocol
  behavior there. By shoehorning everything into a pair of pipes,
  we can have more consistent behavior across transports.
  
  We currently only define the client side parts of the new protocol,
  specifically the bits for requesting that a command run. This keeps
  the new code and feature small and somewhat easy to review.
  
  We add support to `hg debugwireproto` for writing frames into
  HTTP request bodies. Our tests that issue commands to the new
  HTTP endpoint have been updated to transmit frames. The server
  bits haven't been touched to consume the frames yet. This will
  occur in the next commit...
  
  Astute readers may notice that the command name is transmitted in
  both the HTTP request URL and the command request frame. This is
  partially a kludge from me initially implementing the frame-based
  protocol for SSH first. But it is also a feature: I intend to
  eventually support issuing multiple commands per HTTP request. This
  will allow us to replace the abomination that is the "batch" wire
  protocol command with a protocol-level mechanism for performing
  multi-dispatch. Because I want the frame-based protocol to be
  as similar as possible across transports, I'd rather we (redundantly)
  include the command name in the frame than differ behavior between
  transports that have out-of-band routing information (like HTTP)
  readily available.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/debugcommands.py
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoframing.py
  mercurial/wireprotoserver.py
  tests/test-http-api-httpv2.t

CHANGE DETAILS

diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t
--- a/tests/test-http-api-httpv2.t
+++ b/tests/test-http-api-httpv2.t
@@ -1,5 +1,5 @@
   $ HTTPV2=exp-http-v2-0001
-  $ MEDIATYPE=application/mercurial-tbd
+  $ MEDIATYPE=application/mercurial-exp-framing-0001
 
   $ send() {
   >   hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT/
@@ -105,9 +105,9 @@
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
   s> Content-Type: text/plain\r\n
-  s> Content-Length: 72\r\n
+  s> Content-Length: 85\r\n
   s> \r\n
-  s> client MUST specify Accept header with value: 
application/mercurial-tbd\n
+  s> client MUST specify Accept header with value: 
application/mercurial-exp-framing-0001\n
 
 Bad Accept header results in 406
 
@@ -128,9 +128,9 @@
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
   s> Content-Type: text/plain\r\n
-  s> Content-Length: 72\r\n
+  s> Content-Length: 85\r\n
   s> \r\n
-  s> client MUST specify Accept header with value: 
application/mercurial-tbd\n
+  s> client MUST specify Accept header with value: 
application/mercurial-exp-framing-0001\n
 
 Bad Content-Type header results in 415
 
@@ -143,7 +143,7 @@
   using raw connection to peer
   s> POST /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
-  s> accept: application/mercurial-tbd\r\n
+  s> accept: application/mercurial-exp-framing-0001\r\n
   s> 

D2850: wireproto: define content negotiation for HTTPv2

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 7016.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2850?vs=7013=7016

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

AFFECTED FILES
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoserver.py
  tests/test-http-api-httpv2.t

CHANGE DETAILS

diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t
--- a/tests/test-http-api-httpv2.t
+++ b/tests/test-http-api-httpv2.t
@@ -1,4 +1,5 @@
   $ HTTPV2=exp-http-v2-0001
+  $ MEDIATYPE=application/mercurial-tbd
 
   $ send() {
   >   hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT/
@@ -45,27 +46,6 @@
   $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
   $ cat hg.pid > $DAEMON_PIDS
 
-Request to read-only command works out of the box
-
-  $ send << EOF
-  > httprequest POST api/$HTTPV2/ro/capabilities
-  > user-agent: test
-  > EOF
-  using raw connection to peer
-  s> POST /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
-  s> Accept-Encoding: identity\r\n
-  s> user-agent: test\r\n
-  s> host: $LOCALIP:$HGPORT\r\n (glob)
-  s> \r\n
-  s> makefile('rb', None)
-  s> HTTP/1.1 200 OK\r\n
-  s> Server: testing stub value\r\n
-  s> Date: $HTTP_DATE$\r\n
-  s> Content-Type: text/plain\r\n
-  s> Content-Length: 16\r\n
-  s> \r\n
-  s> ro/capabilities\n
-
 Request to unknown command yields 404
 
   $ send << EOF
@@ -108,6 +88,100 @@
   s> \r\n
   s> commands require POST requests
 
+Missing Accept header results in 406
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/ro/capabilities
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 406 Not Acceptable\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 72\r\n
+  s> \r\n
+  s> client MUST specify Accept header with value: 
application/mercurial-tbd\n
+
+Bad Accept header results in 406
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/ro/capabilities
+  > accept: invalid
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> accept: invalid\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 406 Not Acceptable\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 72\r\n
+  s> \r\n
+  s> client MUST specify Accept header with value: 
application/mercurial-tbd\n
+
+Bad Content-Type header results in 415
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/ro/capabilities
+  > accept: $MEDIATYPE
+  > user-agent: test
+  > content-type: badmedia
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> accept: application/mercurial-tbd\r\n
+  s> content-type: badmedia\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 415 Unsupported Media Type\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 75\r\n
+  s> \r\n
+  s> client MUST send Content-Type header with value: 
application/mercurial-tbd\n
+
+Request to read-only command works out of the box
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/ro/capabilities
+  > accept: $MEDIATYPE
+  > content-type: $MEDIATYPE
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> accept: application/mercurial-tbd\r\n
+  s> content-type: application/mercurial-tbd\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 200 OK\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 16\r\n
+  s> \r\n
+  s> ro/capabilities\n
+
 Request to read-write command fails because server is read-only by default
 
 GET to read-write request yields 405
@@ -192,10 +266,14 @@
   $ send << EOF
   > httprequest POST api/$HTTPV2/rw/capabilities
   > user-agent: test
+  > accept: $MEDIATYPE
+  > content-type: $MEDIATYPE
   > EOF
   using raw connection to peer
   s> POST /api/exp-http-v2-0001/rw/capabilities HTTP/1.1\r\n

D2836: wireproto: define permissions-based routing of HTTPv2 wire protocol

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 7010.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2836?vs=6999=7010

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

AFFECTED FILES
  mercurial/debugcommands.py
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoserver.py
  tests/test-http-api-httpv2.t

CHANGE DETAILS

diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t
--- a/tests/test-http-api-httpv2.t
+++ b/tests/test-http-api-httpv2.t
@@ -1,3 +1,5 @@
+  $ HTTPV2=exp-http-v2-0001
+
   $ send() {
   >   hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT/
   > }
@@ -13,7 +15,7 @@
 HTTP v2 protocol not enabled by default
 
   $ send << EOF
-  > httprequest GET api/exp-http-v2-0001
+  > httprequest GET api/$HTTPV2
   > user-agent: test
   > EOF
   using raw connection to peer
@@ -43,14 +45,14 @@
   $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
   $ cat hg.pid > $DAEMON_PIDS
 
-Requests simply echo their path (for now)
+Request to read-only command works out of the box
 
   $ send << EOF
-  > httprequest GET api/exp-http-v2-0001/path1/path2
+  > httprequest GET api/$HTTPV2/ro/known
   > user-agent: test
   > EOF
   using raw connection to peer
-  s> GET /api/exp-http-v2-0001/path1/path2 HTTP/1.1\r\n
+  s> GET /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> user-agent: test\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
@@ -60,6 +62,178 @@
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
   s> Content-Type: text/plain\r\n
-  s> Content-Length: 12\r\n
+  s> Content-Length: 9\r\n
+  s> \r\n
+  s> ro/known\n
+
+Request to unknown command yields 404
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/ro/badcommand
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/ro/badcommand HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 404 Not Found\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 42\r\n
+  s> \r\n
+  s> unknown wire protocol command: badcommand\n
+
+Request to read-write command fails because server is read-only by default
+
+GET to read-write request not allowed
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/rw/known
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/rw/known HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 405 push requires POST request\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Length: 17\r\n
+  s> \r\n
+  s> permission denied
+
+Even for unknown commands
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/rw/badcommand
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/rw/badcommand HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 405 push requires POST request\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Length: 17\r\n
+  s> \r\n
+  s> permission denied
+
+SSL required by default
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/rw/known
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/rw/known HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 403 ssl required\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Length: 17\r\n
   s> \r\n
-  s> path1/path2\n
+  s> permission denied
+
+Restart server to allow non-ssl read-write operations
+
+  $ killdaemons.py
+  $ cat > server/.hg/hgrc << EOF
+  > [experimental]
+  > web.apiserver = true
+  > web.api.http-v2 = true
+  > [web]
+  > push_ssl = false
+  > EOF
+
+  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
+  $ cat hg.pid > $DAEMON_PIDS
+
+Server insists on POST for read-write commands
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/rw/known
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/rw/known HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 405 push requires POST request\r\n
+  s> Server: 

D2721: util: observable proxy objects for sockets

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 7007.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2721?vs=6972=7007

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

AFFECTED FILES
  mercurial/util.py

CHANGE DETAILS

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -687,6 +687,125 @@
 
 return res
 
+PROXIED_SOCKET_METHODS = {
+r'makefile',
+r'recv',
+r'recvfrom',
+r'recvfrom_into',
+r'recv_into',
+r'send',
+r'sendall',
+r'sendto',
+r'setblocking',
+r'settimeout',
+r'gettimeout',
+r'setsockopt',
+}
+
+class socketproxy(object):
+"""A proxy around a socket that tells a watcher when events occur.
+
+This is like ``fileobjectproxy`` except for sockets.
+
+This type is intended to only be used for testing purposes. Think hard
+before using it in important code.
+"""
+__slots__ = (
+r'_orig',
+r'_observer',
+)
+
+def __init__(self, sock, observer):
+object.__setattr__(self, r'_orig', sock)
+object.__setattr__(self, r'_observer', observer)
+
+def __getattribute__(self, name):
+if name in PROXIED_SOCKET_METHODS:
+return object.__getattribute__(self, name)
+
+return getattr(object.__getattribute__(self, r'_orig'), name)
+
+def __delattr__(self, name):
+return delattr(object.__getattribute__(self, r'_orig'), name)
+
+def __setattr__(self, name, value):
+return setattr(object.__getattribute__(self, r'_orig'), name, value)
+
+def __nonzero__(self):
+return bool(object.__getattribute__(self, r'_orig'))
+
+__bool__ = __nonzero__
+
+def _observedcall(self, name, *args, **kwargs):
+# Call the original object.
+orig = object.__getattribute__(self, r'_orig')
+res = getattr(orig, name)(*args, **kwargs)
+
+# Call a method on the observer of the same name with arguments
+# so it can react, log, etc.
+observer = object.__getattribute__(self, r'_observer')
+fn = getattr(observer, name, None)
+if fn:
+fn(res, *args, **kwargs)
+
+return res
+
+def makefile(self, *args, **kwargs):
+res = object.__getattribute__(self, r'_observedcall')(
+r'makefile', *args, **kwargs)
+
+# The file object may be used for I/O. So we turn it into a
+# proxy using our observer.
+observer = object.__getattribute__(self, r'_observer')
+return makeloggingfileobject(observer.fh, res, observer.name,
+ reads=observer.reads,
+ writes=observer.writes,
+ logdata=observer.logdata)
+
+def recv(self, *args, **kwargs):
+return object.__getattribute__(self, r'_observedcall')(
+r'recv', *args, **kwargs)
+
+def recvfrom(self, *args, **kwargs):
+return object.__getattribute__(self, r'_observedcall')(
+r'recvfrom', *args, **kwargs)
+
+def recvfrom_into(self, *args, **kwargs):
+return object.__getattribute__(self, r'_observedcall')(
+r'recvfrom_into', *args, **kwargs)
+
+def recv_into(self, *args, **kwargs):
+return object.__getattribute__(self, r'_observedcall')(
+r'recv_info', *args, **kwargs)
+
+def send(self, *args, **kwargs):
+return object.__getattribute__(self, r'_observedcall')(
+r'send', *args, **kwargs)
+
+def sendall(self, *args, **kwargs):
+return object.__getattribute__(self, r'_observedcall')(
+r'sendall', *args, **kwargs)
+
+def sendto(self, *args, **kwargs):
+return object.__getattribute__(self, r'_observedcall')(
+r'sendto', *args, **kwargs)
+
+def setblocking(self, *args, **kwargs):
+return object.__getattribute__(self, r'_observedcall')(
+r'setblocking', *args, **kwargs)
+
+def settimeout(self, *args, **kwargs):
+return object.__getattribute__(self, r'_observedcall')(
+r'settimeout', *args, **kwargs)
+
+def gettimeout(self, *args, **kwargs):
+return object.__getattribute__(self, r'_observedcall')(
+r'gettimeout', *args, **kwargs)
+
+def setsockopt(self, *args, **kwargs):
+return object.__getattribute__(self, r'_observedcall')(
+r'setsockopt', *args, **kwargs)
+
 DATA_ESCAPE_MAP = {pycompat.bytechr(i): br'\x%02x' % i for i in range(256)}
 DATA_ESCAPE_MAP.update({
 b'\\': b'',
@@ -701,15 +820,7 @@
 
 return DATA_ESCAPE_RE.sub(lambda m: DATA_ESCAPE_MAP[m.group(0)], s)
 
-class fileobjectobserver(object):
-"""Logs file object activity."""
-def __init__(self, fh, name, reads=True, writes=True, logdata=False):
-self.fh = fh
-self.name = name
-self.logdata = logdata
-self.reads = reads
-self.writes = writes
-

D2837: wireproto: require POST for all HTTPv2 requests

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 7011.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2837?vs=7000=7011

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

AFFECTED FILES
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoserver.py
  tests/test-http-api-httpv2.t

CHANGE DETAILS

diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t
--- a/tests/test-http-api-httpv2.t
+++ b/tests/test-http-api-httpv2.t
@@ -48,11 +48,11 @@
 Request to read-only command works out of the box
 
   $ send << EOF
-  > httprequest GET api/$HTTPV2/ro/known
+  > httprequest POST api/$HTTPV2/ro/known
   > user-agent: test
   > EOF
   using raw connection to peer
-  s> GET /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
+  s> POST /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> user-agent: test\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
@@ -69,11 +69,11 @@
 Request to unknown command yields 404
 
   $ send << EOF
-  > httprequest GET api/$HTTPV2/ro/badcommand
+  > httprequest POST api/$HTTPV2/ro/badcommand
   > user-agent: test
   > EOF
   using raw connection to peer
-  s> GET /api/exp-http-v2-0001/ro/badcommand HTTP/1.1\r\n
+  s> POST /api/exp-http-v2-0001/ro/badcommand HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> user-agent: test\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
@@ -87,9 +87,30 @@
   s> \r\n
   s> unknown wire protocol command: badcommand\n
 
+GET to read-only command yields a 405
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/ro/known
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 405 Method Not Allowed\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Allow: POST\r\n
+  s> Content-Length: 30\r\n
+  s> \r\n
+  s> commands require POST requests
+
 Request to read-write command fails because server is read-only by default
 
-GET to read-write request not allowed
+GET to read-write request yields 405
 
   $ send << EOF
   > httprequest GET api/$HTTPV2/rw/known
@@ -102,12 +123,13 @@
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> \r\n
   s> makefile('rb', None)
-  s> HTTP/1.1 405 push requires POST request\r\n
+  s> HTTP/1.1 405 Method Not Allowed\r\n
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
-  s> Content-Length: 17\r\n
+  s> Allow: POST\r\n
+  s> Content-Length: 30\r\n
   s> \r\n
-  s> permission denied
+  s> commands require POST requests
 
 Even for unknown commands
 
@@ -122,12 +144,13 @@
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> \r\n
   s> makefile('rb', None)
-  s> HTTP/1.1 405 push requires POST request\r\n
+  s> HTTP/1.1 405 Method Not Allowed\r\n
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
-  s> Content-Length: 17\r\n
+  s> Allow: POST\r\n
+  s> Content-Length: 30\r\n
   s> \r\n
-  s> permission denied
+  s> commands require POST requests
 
 SSL required by default
 
@@ -158,38 +181,6 @@
   > web.api.http-v2 = true
   > [web]
   > push_ssl = false
-  > EOF
-
-  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
-  $ cat hg.pid > $DAEMON_PIDS
-
-Server insists on POST for read-write commands
-
-  $ send << EOF
-  > httprequest GET api/$HTTPV2/rw/known
-  > user-agent: test
-  > EOF
-  using raw connection to peer
-  s> GET /api/exp-http-v2-0001/rw/known HTTP/1.1\r\n
-  s> Accept-Encoding: identity\r\n
-  s> user-agent: test\r\n
-  s> host: $LOCALIP:$HGPORT\r\n (glob)
-  s> \r\n
-  s> makefile('rb', None)
-  s> HTTP/1.1 405 push requires POST request\r\n
-  s> Server: testing stub value\r\n
-  s> Date: $HTTP_DATE$\r\n
-  s> Content-Length: 17\r\n
-  s> \r\n
-  s> permission denied
-
-  $ killdaemons.py
-  $ cat > server/.hg/hgrc << EOF
-  > [experimental]
-  > web.apiserver = true
-  > web.api.http-v2 = true
-  > [web]
-  > push_ssl = false
   > allow-push = *
   > EOF
 
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -299,6 +299,12 @@
 res.setbodybytes(_('unknown permission: %s') % permission)
 return
 
+if req.method != 'POST':
+res.status = b'405 Method Not Allowed'
+res.headers[b'Allow'] = b'POST'
+res.setbodybytes(_('commands require POST requests'))
+return
+
 # At some point we'll want to use our own API instead of recycling the
 # behavior of version 1 of the wire protocol...
 # TODO return reasonable responses - not responses that overload the
diff --git 

D2849: hgweb: also set Content-Type header

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

REVISION SUMMARY
  Our HTTP/WSGI server may convert the Content-Type HTTP request
  header to the CONTENT_TYPE WSGI environment key and not set
  HTTP_CONTENT_TYPE. Other WSGI server implementations
  do this, so I think the behavior is acceptable.
  
  So assuming this HTTP request header could get "lost" by the WSGI
  server, let's restore it on the request object like we do for
  Content-Length.
  
  FWIW, the WSGI server may also *invent* a Content-Type value. The
  default behavior of Python's RFC 822 message class returns a default
  media type if Content-Type isn't defined. This is kind of annoying.
  But RFC 7231 section 3.1.1.5 does say the recipient may assume a media
  type of application/octet-stream. Python's defaults are for
  text/plain (given we're using an RFC 822 parser). But whatever.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/hgweb/request.py

CHANGE DETAILS

diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py
--- a/mercurial/hgweb/request.py
+++ b/mercurial/hgweb/request.py
@@ -325,6 +325,9 @@
 if 'CONTENT_LENGTH' in env and 'HTTP_CONTENT_LENGTH' not in env:
 headers['Content-Length'] = env['CONTENT_LENGTH']
 
+if 'CONTENT_TYPE' in env and 'HTTP_CONTENT_TYPE' not in env:
+headers['Content-Type'] = env['CONTENT_TYPE']
+
 bodyfh = env['wsgi.input']
 if 'Content-Length' in headers:
 bodyfh = util.cappedreader(bodyfh, int(headers['Content-Length']))



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


D2834: wireproto: support /api/* URL space for exposing APIs

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 7009.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2834?vs=6998=7009

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

AFFECTED FILES
  mercurial/configitems.py
  mercurial/hgweb/hgweb_mod.py
  mercurial/wireprotoserver.py
  mercurial/wireprototypes.py
  tests/test-http-api-httpv2.t
  tests/test-http-api.t

CHANGE DETAILS

diff --git a/tests/test-http-api.t b/tests/test-http-api.t
new file mode 100644
--- /dev/null
+++ b/tests/test-http-api.t
@@ -0,0 +1,201 @@
+  $ send() {
+  >   hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT/
+  > }
+
+  $ hg init server
+  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
+  $ cat hg.pid > $DAEMON_PIDS
+
+Request to /api fails unless web.apiserver is enabled
+
+  $ send << EOF
+  > httprequest GET api
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 404 Not Found\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 44\r\n
+  s> \r\n
+  s> Experimental API server endpoint not enabled
+
+  $ send << EOF
+  > httprequest GET api/
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/ HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 404 Not Found\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 44\r\n
+  s> \r\n
+  s> Experimental API server endpoint not enabled
+
+Restart server with support for API server
+
+  $ killdaemons.py
+  $ cat > server/.hg/hgrc << EOF
+  > [experimental]
+  > web.apiserver = true
+  > EOF
+
+  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
+  $ cat hg.pid > $DAEMON_PIDS
+
+/api lists available APIs (empty since none are available by default)
+
+  $ send << EOF
+  > httprequest GET api
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 200 OK\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 100\r\n
+  s> \r\n
+  s> APIs can be accessed at /api/, where  can be one of the 
following:\n
+  s> \n
+  s> (no available APIs)\n
+
+  $ send << EOF
+  > httprequest GET api/
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/ HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 200 OK\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 100\r\n
+  s> \r\n
+  s> APIs can be accessed at /api/, where  can be one of the 
following:\n
+  s> \n
+  s> (no available APIs)\n
+
+Accessing an unknown API yields a 404
+
+  $ send << EOF
+  > httprequest GET api/unknown
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/unknown HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 404 Not Found\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 33\r\n
+  s> \r\n
+  s> Unknown API: unknown\n
+  s> Known APIs: 
+
+Accessing a known but not enabled API yields a different error
+
+  $ send << EOF
+  > httprequest GET api/exp-http-v2-0001
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001 HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 404 Not Found\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 33\r\n
+  s> \r\n
+  s> API exp-http-v2-0001 not enabled\n
+
+Restart server with support for HTTP v2 API
+
+  $ killdaemons.py
+  $ cat > server/.hg/hgrc << EOF
+  > [experimental]
+  > web.apiserver = true
+  > web.api.http-v2 = true
+  > EOF
+
+  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
+  $ cat hg.pid > $DAEMON_PIDS

D2850: wireproto: define content negotiation for HTTPv2

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

REVISION SUMMARY
  HTTP messages communicate their media types and what media types
  they can understand via the Content-Type and Accept header,
  respectively.
  
  While I don't want the wire protocol to lean too heavily on HTTP
  because I'm aiming for the wire protocol to be as transport
  agnostic as possible, it is nice to play by the spec if possible.
  
  This commit defines our media negotiation mechanism for version
  2 of the HTTP protocol. Essentially, we mandate the use of a
  new media type and how clients and servers should react to
  various headers or lack thereof.
  
  The name of the media type is a placeholder. We purposefully don't
  yet define the format of the new media type because that's a lot
  of work.
  
  I feel pretty strongly that we should use Content-Type. I feel
  less strongly about Accept. I think it is reasonable for servers
  to return the media type that was submitted to them. So we may
  strike this header before the protocol is finished...

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoserver.py
  tests/test-http-api-httpv2.t

CHANGE DETAILS

diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t
--- a/tests/test-http-api-httpv2.t
+++ b/tests/test-http-api-httpv2.t
@@ -1,4 +1,5 @@
   $ HTTPV2=exp-http-v2-0001
+  $ MEDIATYPE=application/mercurial-tbd
 
   $ send() {
   >   hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT/
@@ -45,27 +46,6 @@
   $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
   $ cat hg.pid > $DAEMON_PIDS
 
-Request to read-only command works out of the box
-
-  $ send << EOF
-  > httprequest POST api/$HTTPV2/ro/known
-  > user-agent: test
-  > EOF
-  using raw connection to peer
-  s> POST /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
-  s> Accept-Encoding: identity\r\n
-  s> user-agent: test\r\n
-  s> host: $LOCALIP:$HGPORT\r\n (glob)
-  s> \r\n
-  s> makefile('rb', None)
-  s> HTTP/1.1 200 OK\r\n
-  s> Server: testing stub value\r\n
-  s> Date: $HTTP_DATE$\r\n
-  s> Content-Type: text/plain\r\n
-  s> Content-Length: 9\r\n
-  s> \r\n
-  s> ro/known\n
-
 Request to unknown command yields 404
 
   $ send << EOF
@@ -108,6 +88,100 @@
   s> \r\n
   s> commands require POST requests
 
+Missing Accept header results in 406
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/ro/known
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 406 Not Acceptable\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 72\r\n
+  s> \r\n
+  s> client MUST specify Accept header with value: 
application/mercurial-tbd\n
+
+Bad Accept header results in 406
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/ro/known
+  > accept: invalid
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> accept: invalid\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 406 Not Acceptable\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 72\r\n
+  s> \r\n
+  s> client MUST specify Accept header with value: 
application/mercurial-tbd\n
+
+Bad Content-Type header results in 415
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/ro/known
+  > accept: $MEDIATYPE
+  > user-agent: test
+  > content-type: badmedia
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> accept: application/mercurial-tbd\r\n
+  s> content-type: badmedia\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 415 Unsupported Media Type\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 75\r\n
+  s> \r\n
+  s> client MUST send Content-Type header with value: 
application/mercurial-tbd\n
+
+Request to read-only command works out of the box
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/ro/known
+  > accept: $MEDIATYPE
+  > content-type: $MEDIATYPE
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> POST 

D2842: util: don't log low-level I/O calls for HTTP peer

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 7008.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2842?vs=6996=7008

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

AFFECTED FILES
  mercurial/debugcommands.py
  mercurial/util.py
  tests/test-http-protocol.t

CHANGE DETAILS

diff --git a/tests/test-http-protocol.t b/tests/test-http-protocol.t
--- a/tests/test-http-protocol.t
+++ b/tests/test-http-protocol.t
@@ -175,29 +175,21 @@
   > command listkeys
   > namespace namespaces
   > EOF
-  s> sendall(*, 0): (glob)
   s> GET /?cmd=capabilities HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> accept: application/mercurial-0.1\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> user-agent: mercurial/proto-1.0 (Mercurial *)\r\n (glob)
   s> \r\n
   s> makefile('rb', None)
-  s> readline() -> 36:
   s> HTTP/1.1 200 Script output follows\r\n
-  s> readline() -> 28:
   s> Server: testing stub value\r\n
-  s> readline() -> *: (glob)
   s> Date: $HTTP_DATE$\r\n
-  s> readline() -> 41:
   s> Content-Type: application/mercurial-0.1\r\n
-  s> readline() -> 21:
   s> Content-Length: *\r\n (glob)
-  s> readline() -> 2:
   s> \r\n
-  s> read(*) -> *: lookup branchmap pushkey known getbundle unbundlehash batch 
changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ 
unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx 
compression=$BUNDLE2_COMPRESSIONS$ (glob)
+  s> lookup branchmap pushkey known getbundle unbundlehash batch 
changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ 
unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx 
compression=$BUNDLE2_COMPRESSIONS$
   sending listkeys command
-  s> sendall(*, 0): (glob)
   s> GET /?cmd=listkeys HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> vary: X-HgArg-1,X-HgProto-1\r\n
@@ -208,19 +200,12 @@
   s> user-agent: mercurial/proto-1.0 (Mercurial *)\r\n (glob)
   s> \r\n
   s> makefile('rb', None)
-  s> readline() -> 36:
   s> HTTP/1.1 200 Script output follows\r\n
-  s> readline() -> 28:
   s> Server: testing stub value\r\n
-  s> readline() -> *: (glob)
   s> Date: $HTTP_DATE$\r\n
-  s> readline() -> 41:
   s> Content-Type: application/mercurial-0.1\r\n
-  s> readline() -> 20:
   s> Content-Length: 30\r\n
-  s> readline() -> 2:
   s> \r\n
-  s> read(30) -> 30:
   s> bookmarks \n
   s> namespaces\n
   s> phases
@@ -235,28 +220,20 @@
   > x-hgarg-1: namespace=namespaces
   > EOF
   using raw connection to peer
-  s> sendall(*, 0): (glob)
   s> GET /?cmd=listkeys HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> accept: application/mercurial-0.1\r\n
   s> user-agent: mercurial/proto-1.0 (Mercurial 42)\r\n (glob)
   s> x-hgarg-1: namespace=namespaces\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> \r\n
   s> makefile('rb', None)
-  s> readline() -> 36:
   s> HTTP/1.1 200 Script output follows\r\n
-  s> readline() -> 28:
   s> Server: testing stub value\r\n
-  s> readline() -> *: (glob)
   s> Date: $HTTP_DATE$\r\n
-  s> readline() -> 41:
   s> Content-Type: application/mercurial-0.1\r\n
-  s> readline() -> 20:
   s> Content-Length: 30\r\n
-  s> readline() -> 2:
   s> \r\n
-  s> read(30) -> 30:
   s> bookmarks \n
   s> namespaces\n
   s> phases
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -760,7 +760,8 @@
 return makeloggingfileobject(observer.fh, res, observer.name,
  reads=observer.reads,
  writes=observer.writes,
- logdata=observer.logdata)
+ logdata=observer.logdata,
+ logdataapis=observer.logdataapis)
 
 def recv(self, *args, **kwargs):
 return object.__getattribute__(self, r'_observedcall')(
@@ -823,26 +824,34 @@
 class baseproxyobserver(object):
 def _writedata(self, data):
 if not self.logdata:
-self.fh.write('\n')
+if self.logdataapis:
+self.fh.write('\n')
 return
 
 # Simple case writes all data on a single line.
 if b'\n' not in data:
-self.fh.write(': %s\n' % escapedata(data))
+if self.logdataapis:
+self.fh.write(': %s\n' % escapedata(data))
+else:
+self.fh.write('%s> %s\n' % (self.name, escapedata(data)))
 return
 
 # Data with newlines is written to multiple lines.
-self.fh.write(':\n')
+if self.logdataapis:
+self.fh.write(':\n')
+
 lines = data.splitlines(True)
 for line in lines:
 self.fh.write('%s> %s\n' % (self.name, 

D2848: xdiff: move stdint.h to xdiff.h

2018-03-13 Thread quark (Jun Wu)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGafebb7588e95: xdiff: move stdint.h to xdiff.h (authored by 
quark, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2848?vs=7005=7006

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

AFFECTED FILES
  mercurial/thirdparty/xdiff/xdiff.h
  mercurial/thirdparty/xdiff/xinclude.h

CHANGE DETAILS

diff --git a/mercurial/thirdparty/xdiff/xinclude.h 
b/mercurial/thirdparty/xdiff/xinclude.h
--- a/mercurial/thirdparty/xdiff/xinclude.h
+++ b/mercurial/thirdparty/xdiff/xinclude.h
@@ -24,13 +24,6 @@
 #define XINCLUDE_H
 
 #include 
-#if !defined(_MSC_VER) || _MSC_VER >= 1600
-#include 
-#else
-/* prior to Visual Studio 2010 */
-typedef long long int64_t;
-typedef unsigned long long uint64_t;
-#endif
 #include 
 #include 
 #include 
diff --git a/mercurial/thirdparty/xdiff/xdiff.h 
b/mercurial/thirdparty/xdiff/xdiff.h
--- a/mercurial/thirdparty/xdiff/xdiff.h
+++ b/mercurial/thirdparty/xdiff/xdiff.h
@@ -29,6 +29,14 @@
 
 #include  /* size_t */
 
+#if !defined(_MSC_VER) || _MSC_VER >= 1600
+#include 
+#else
+/* prior to Visual Studio 2010 */
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+#endif
+
 /* xpparm_t.flags */
 #define XDF_NEED_MINIMAL (1 << 0)
 



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


D2848: xdiff: move stdint.h to xdiff.h

2018-03-13 Thread quark (Jun Wu)
quark created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  It's more correct to put it in xdiff.h since that file actually uses int64_t
  etc and xdiff.h is included by xinclude.h.
  
  This should fix the oss-fuzz build. Thanks durin42 for discovering the
  issue.

TEST PLAN
  `make local` and xdiff related tests still work.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/thirdparty/xdiff/xdiff.h
  mercurial/thirdparty/xdiff/xinclude.h

CHANGE DETAILS

diff --git a/mercurial/thirdparty/xdiff/xinclude.h 
b/mercurial/thirdparty/xdiff/xinclude.h
--- a/mercurial/thirdparty/xdiff/xinclude.h
+++ b/mercurial/thirdparty/xdiff/xinclude.h
@@ -24,13 +24,6 @@
 #define XINCLUDE_H
 
 #include 
-#if !defined(_MSC_VER) || _MSC_VER >= 1600
-#include 
-#else
-/* prior to Visual Studio 2010 */
-typedef long long int64_t;
-typedef unsigned long long uint64_t;
-#endif
 #include 
 #include 
 #include 
diff --git a/mercurial/thirdparty/xdiff/xdiff.h 
b/mercurial/thirdparty/xdiff/xdiff.h
--- a/mercurial/thirdparty/xdiff/xdiff.h
+++ b/mercurial/thirdparty/xdiff/xdiff.h
@@ -29,6 +29,14 @@
 
 #include  /* size_t */
 
+#if !defined(_MSC_VER) || _MSC_VER >= 1600
+#include 
+#else
+/* prior to Visual Studio 2010 */
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+#endif
+
 /* xpparm_t.flags */
 #define XDF_NEED_MINIMAL (1 << 0)
 



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


Re: [PATCH V2] forget: add --dry-run mode

2018-03-13 Thread Matt Harbison
On Tue, 13 Mar 2018 17:30:55 -0400, sushil khanchi  
 wrote:



Shall I remove --dry-run from context layer now?


It looks like cmdutil.add() and scmutil.addremove() don't pass it along to  
wctx either, so I guess it's OK to drop for consistency.


But the fact that it doesn't seems like a bug- wctx.add() prints out  
various warnings about portable file names, sizes, etc.  I'd think that  
the whole point of a dry run is to test against that.  Maybe the solution  
to that is to have a mock wctx somehow that simply doesn't flush dirstate  
to disk?

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


D2620: wireproto: define and implement unified framing protocol for SSH

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg abandoned this revision.
indygreg added a comment.


  I'll break this up and send it as multiple commits.

REPOSITORY
  rHG Mercurial

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

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


D2845: hghave: fix xdiff check on Python 3

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

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  tests/hghave.py

CHANGE DETAILS

diff --git a/tests/hghave.py b/tests/hghave.py
--- a/tests/hghave.py
+++ b/tests/hghave.py
@@ -714,6 +714,6 @@
 try:
 from mercurial import policy
 bdiff = policy.importmod('bdiff')
-return bdiff.xdiffblocks('', '') == [(0, 0, 0, 0)]
+return bdiff.xdiffblocks(b'', b'') == [(0, 0, 0, 0)]
 except (ImportError, AttributeError):
 return False



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


D2847: remotenames: work around move of ABCs in collections

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

REVISION SUMMARY
  This starts warning in Python 3.7, and will break in 3.8.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  hgext/remotenames.py

CHANGE DETAILS

diff --git a/hgext/remotenames.py b/hgext/remotenames.py
--- a/hgext/remotenames.py
+++ b/hgext/remotenames.py
@@ -22,7 +22,12 @@
 
 from __future__ import absolute_import
 
-import collections
+try:
+from collections import abc
+MutableMapping = abc.MutableMapping
+except ImportError:
+import collections
+MutableMapping = collections.MutableMapping
 
 from mercurial.i18n import _
 
@@ -56,7 +61,7 @@
 default=True,
 )
 
-class lazyremotenamedict(collections.MutableMapping):
+class lazyremotenamedict(MutableMapping):
 """
 Read-only dict-like Class to lazily resolve remotename entries
 



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


D2846: hghave: fix hardlink-whitelisted check on Python 3

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

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  tests/hghave.py

CHANGE DETAILS

diff --git a/tests/hghave.py b/tests/hghave.py
--- a/tests/hghave.py
+++ b/tests/hghave.py
@@ -372,7 +372,7 @@
 def has_hardlink_whitelisted():
 from mercurial import util
 try:
-fstype = util.getfstype('.')
+fstype = util.getfstype(b'.')
 except OSError:
 return False
 return fstype in util._hardlinkfswhitelist



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


D2844: commandserver: prefer first-party selectors module from Python 3 to backport

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

REVISION SUMMARY
  Caught by some deprecation warnings on Python 3.7.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/commandserver.py

CHANGE DETAILS

diff --git a/mercurial/commandserver.py b/mercurial/commandserver.py
--- a/mercurial/commandserver.py
+++ b/mercurial/commandserver.py
@@ -16,8 +16,13 @@
 import struct
 import traceback
 
+try:
+import selectors
+selectors.BaseSelector
+except ImportError:
+from .thirdparty import selectors2 as selectors
+
 from .i18n import _
-from .thirdparty import selectors2
 from . import (
 encoding,
 error,
@@ -476,8 +481,8 @@
 def _mainloop(self):
 exiting = False
 h = self._servicehandler
-selector = selectors2.DefaultSelector()
-selector.register(self._sock, selectors2.EVENT_READ)
+selector = selectors.DefaultSelector()
+selector.register(self._sock, selectors.EVENT_READ)
 while True:
 if not exiting and h.shouldexit():
 # clients can no longer connect() to the domain socket, so



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


Re: [PATCH V2] forget: add --dry-run mode

2018-03-13 Thread sushil khanchi
Shall I remove --dry-run from context layer now?

On Tue, Mar 13, 2018 at 7:55 PM, Yuya Nishihara  wrote:

> On Mon, 12 Mar 2018 18:27:13 -0400, Matt Harbison wrote:
> > On Sun, 11 Mar 2018 05:49:26 -0400, Sushil khanchi
> >  wrote:
> >
> > > # HG changeset patch
> > > # User Sushil khanchi 
> > > # Date 1520665399 -19800
> > > #  Sat Mar 10 12:33:19 2018 +0530
> > > # Node ID a1be8989c0158abc69ebd97ca8a0cc7dc3801be9
> > > # Parent  4c71a26a4009d88590c9ae3d64a5912fd556d82e
> > > forget: add --dry-run mode
> > >
> > > diff -r 4c71a26a4009 -r a1be8989c015 mercurial/cmdutil.py
> > > --- a/mercurial/cmdutil.py  Sun Mar 04 21:16:36 2018 -0500
> > > +++ b/mercurial/cmdutil.py  Sat Mar 10 12:33:19 2018 +0530
> > > @@ -1996,7 +1996,7 @@
> > >  for subpath in ctx.substate:
> > >  ctx.sub(subpath).addwebdirpath(serverpath, webconf)
> > > -def forget(ui, repo, match, prefix, explicitonly):
> > > +def forget(ui, repo, match, prefix, explicitonly, **opts):
> > >  join = lambda f: os.path.join(prefix, f)
> > >  bad = []
> > >  badfn = lambda x, y: bad.append(x) or match.bad(x, y)
> > > @@ -2039,9 +2039,10 @@
> > >  if ui.verbose or not match.exact(f):
> > >  ui.status(_('removing %s\n') % match.rel(f))
> > > -rejected = wctx.forget(forget, prefix)
> >
> > Shouldn't --dry-run be passed into wctx.forget() too?  Then the warning
> > about bad paths there will be emitted, and you won't have to
> > conditionalize the following lines here.  That in turn won't affect the
> > exit code.
>
> I slightly prefer not to pass --dry-run deep into the context layer
> because it's a command-line business. Just my two cents.
>
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D2721: util: observable proxy objects for sockets

2018-03-13 Thread mharbison72 (Matt Harbison)
mharbison72 added a comment.


  fileobjectproxy needed `__nonzero__()`/`__bool__()`.  Does socketproxy need 
it for consistency?

REPOSITORY
  rHG Mercurial

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

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


D2729: copyfile: preserve stat info (mtime, etc.) when doing copies/renames

2018-03-13 Thread spectral (Kyle Lippincott)
spectral added a comment.


  In https://phab.mercurial-scm.org/D2729#45664, @indygreg wrote:
  
  > I'm sorry, but we cannot ship this as is.
  >
  > The reason is mtime based build systems, like GNU make.
  >
  > We can't have version control modifying files without bumping their mtime 
because this invalidates the target freshness checks of mtime-based build 
systems.
  
  
  If the user does an `mv` in the shell, at least on Linux, it preserves mtime. 
 If they do a `cp`, it doesn't (the file gets the current timestamp).  This 
includes when overwriting a file.  I think I'd be fine with mimicking this 
behavior (only preserve mtime on `hg mv`) if that would make this safer or 
easier to reason about.
  
  > If we want to preserve mtime on file copy or move, I believe it is safe to 
do that if and only if the destination file didn't already exist. But if the 
destination exists, we need to ensure the mtime of the new file is greater than 
the mtime of the old file.
  
  `hg mv` and `hg cp` require `--after` if the destination file already exists; 
in those cases, we don't seem to touch the working directory at all (including 
not modifying the mtime, even with my patch).  With `--after`, this is purely a 
VCS operation that afaict "shouldn't" have any effect on build systems, so I 
think we're safe here for that concern?
  
  > Reading this patch, I /think/ the previous behavior was buggy in edge cases 
because we never ensured the mtime of the replacement was newer than the 
existing file. In 99.99% of cases, it will be because the existing file was 
created sometime in the past. But if bad clocks or other wonky things are in 
play, there's no guarantee that *wall clock now* is greater than the mtime of 
the existing destination file. The correct thing to do in this situation is 
read the mtime of the existing file and ensure the mtime of the new file is at 
least 1s greater than the previous mtime (1s because not all filesystems 
preserve microsecond or millisecond mtime granularity).

REPOSITORY
  rHG Mercurial

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

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


D2721: util: observable proxy objects for sockets

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg requested review of this revision.
indygreg added a comment.


  This series should now be ready to review.

REPOSITORY
  rHG Mercurial

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

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


D2841: debugcommands: support sending HTTP requests with debugwireproto

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

REVISION SUMMARY
  We implement an action that can issue an HTTP request. We can define
  headers via arguments and specify a file to use for the HTTP request
  body.
  
  The request uses the HTTP peer's opener, which is already configured
  for auth, etc. This is both good and bad. Good in that we get some
  nice behavior out of the box. Bad in that some HTTP request headers
  are added automatically.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/debugcommands.py
  tests/test-http-protocol.t

CHANGE DETAILS

diff --git a/tests/test-http-protocol.t b/tests/test-http-protocol.t
--- a/tests/test-http-protocol.t
+++ b/tests/test-http-protocol.t
@@ -226,4 +226,39 @@
   s> phases
   response: bookmarks  \nnamespaces\nphases
 
+Same thing, but with "httprequest" command
+
+  $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
+  > httprequest GET ?cmd=listkeys
+  > accept: application/mercurial-0.1
+  > user-agent: mercurial/proto-1.0 (Mercurial 42)
+  > x-hgarg-1: namespace=namespaces
+  > EOF
+  using raw connection to peer
+  s> sendall(*, 0): (glob)
+  s> GET /?cmd=listkeys HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> accept: application/mercurial-0.1\r\n
+  s> user-agent: mercurial/proto-1.0 (Mercurial 42)\r\n (glob)
+  s> x-hgarg-1: namespace=namespaces\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> readline() -> 36:
+  s> HTTP/1.1 200 Script output follows\r\n
+  s> readline() -> 28:
+  s> Server: testing stub value\r\n
+  s> readline() -> *: (glob)
+  s> Date: $HTTP_DATE$\r\n
+  s> readline() -> 41:
+  s> Content-Type: application/mercurial-0.1\r\n
+  s> readline() -> 20:
+  s> Content-Length: 30\r\n
+  s> readline() -> 2:
+  s> \r\n
+  s> read(30) -> 30:
+  s> bookmarks \n
+  s> namespaces\n
+  s> phases
+
   $ killdaemons.py
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -14,6 +14,7 @@
 import operator
 import os
 import random
+import re
 import socket
 import ssl
 import stat
@@ -2678,6 +2679,24 @@
 
 This action MUST be paired with a ``batchbegin`` action.
 
+httprequest  
+---
+
+(HTTP peer only)
+
+Send an HTTP request to the peer.
+
+The HTTP request line follows the ``httprequest`` action. e.g. ``GET 
/foo``.
+
+Arguments of the form ``: `` are interpreted as HTTP request
+headers to add to the request. e.g. ``Accept: foo``.
+
+The following arguments are special:
+
+``BODYFILE``
+The content of the file defined as the value to this argument will be
+transferred verbatim as the HTTP request body.
+
 close
 -
 
@@ -2740,6 +2759,7 @@
 stdin = None
 stdout = None
 stderr = None
+opener = None
 
 if opts['localssh']:
 # We start the SSH server in its own process so there is process
@@ -2895,6 +2915,42 @@
 ui.status(_('response #%d: %s\n') % (i, 
util.escapedata(chunk)))
 
 batchedcommands = None
+
+elif action.startswith('httprequest '):
+if not opener:
+raise error.Abort(_('cannot use httprequest without an HTTP '
+'peer'))
+
+request = action.split(' ', 2)
+if len(request) != 3:
+raise error.Abort(_('invalid httprequest: expected format is '
+'"httprequest  '))
+
+method, httppath = request[1:]
+headers = {}
+body = None
+for line in lines:
+line = line.lstrip()
+m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
+if m:
+headers[m.group(1)] = m.group(2)
+continue
+
+if line.startswith(b'BODYFILE '):
+with open(line.split(b' ', 1), 'rb') as fh:
+body = fh.read()
+else:
+raise error.Abort(_('unknown argument to httprequest: %s') 
%
+  line)
+
+url = path + httppath
+req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
+
+try:
+opener.open(req).read()
+except util.urlerr.urlerror as e:
+e.read()
+
 elif action == 'close':
 peer.close()
 elif action == 'readavailable':



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

D2842: util: don't log low-level I/O calls for HTTP peer

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

REVISION SUMMARY
  `hg debugwireproto` is useful for testing HTTP interactions. Possibly
  more useful than `get-with-headers.py`. But one thing that makes it
  annoying for mid-level tests is that it logs all API calls, such
  as readline(). This makes output - especially headers - overly
  verbose.
  
  This commit teaches our file and socket observers to not log API
  calls on functions dealing with data.
  
  We change the behavior of `hg debugwireproto` to enable this mode
  by default. --debug can be added to restore the previous behavior.
  
  As the test changes demonstrate, this makes tests much easier to
  read. As a bonus, it also removes some required (glob) over lengths
  in system call results.
  
  One thing that's lacking is knowing which side sent data. But we can
  fix this in a follow-up once it becomes a problem.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/debugcommands.py
  mercurial/util.py
  tests/test-http-protocol.t

CHANGE DETAILS

diff --git a/tests/test-http-protocol.t b/tests/test-http-protocol.t
--- a/tests/test-http-protocol.t
+++ b/tests/test-http-protocol.t
@@ -175,29 +175,21 @@
   > command listkeys
   > namespace namespaces
   > EOF
-  s> sendall(*, 0): (glob)
   s> GET /?cmd=capabilities HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> accept: application/mercurial-0.1\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> user-agent: mercurial/proto-1.0 (Mercurial *)\r\n (glob)
   s> \r\n
   s> makefile('rb', None)
-  s> readline() -> 36:
   s> HTTP/1.1 200 Script output follows\r\n
-  s> readline() -> 28:
   s> Server: testing stub value\r\n
-  s> readline() -> *: (glob)
   s> Date: $HTTP_DATE$\r\n
-  s> readline() -> 41:
   s> Content-Type: application/mercurial-0.1\r\n
-  s> readline() -> 21:
   s> Content-Length: *\r\n (glob)
-  s> readline() -> 2:
   s> \r\n
-  s> read(*) -> *: lookup branchmap pushkey known getbundle unbundlehash batch 
changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ 
unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx 
compression=$BUNDLE2_COMPRESSIONS$ (glob)
+  s> lookup branchmap pushkey known getbundle unbundlehash batch 
changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ 
unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx 
compression=$BUNDLE2_COMPRESSIONS$
   sending listkeys command
-  s> sendall(*, 0): (glob)
   s> GET /?cmd=listkeys HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> vary: X-HgArg-1,X-HgProto-1\r\n
@@ -208,19 +200,12 @@
   s> user-agent: mercurial/proto-1.0 (Mercurial *)\r\n (glob)
   s> \r\n
   s> makefile('rb', None)
-  s> readline() -> 36:
   s> HTTP/1.1 200 Script output follows\r\n
-  s> readline() -> 28:
   s> Server: testing stub value\r\n
-  s> readline() -> *: (glob)
   s> Date: $HTTP_DATE$\r\n
-  s> readline() -> 41:
   s> Content-Type: application/mercurial-0.1\r\n
-  s> readline() -> 20:
   s> Content-Length: 30\r\n
-  s> readline() -> 2:
   s> \r\n
-  s> read(30) -> 30:
   s> bookmarks \n
   s> namespaces\n
   s> phases
@@ -235,28 +220,20 @@
   > x-hgarg-1: namespace=namespaces
   > EOF
   using raw connection to peer
-  s> sendall(*, 0): (glob)
   s> GET /?cmd=listkeys HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> accept: application/mercurial-0.1\r\n
   s> user-agent: mercurial/proto-1.0 (Mercurial 42)\r\n (glob)
   s> x-hgarg-1: namespace=namespaces\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> \r\n
   s> makefile('rb', None)
-  s> readline() -> 36:
   s> HTTP/1.1 200 Script output follows\r\n
-  s> readline() -> 28:
   s> Server: testing stub value\r\n
-  s> readline() -> *: (glob)
   s> Date: $HTTP_DATE$\r\n
-  s> readline() -> 41:
   s> Content-Type: application/mercurial-0.1\r\n
-  s> readline() -> 20:
   s> Content-Length: 30\r\n
-  s> readline() -> 2:
   s> \r\n
-  s> read(30) -> 30:
   s> bookmarks \n
   s> namespaces\n
   s> phases
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -755,7 +755,8 @@
 return makeloggingfileobject(observer.fh, res, observer.name,
  reads=observer.reads,
  writes=observer.writes,
- logdata=observer.logdata)
+ logdata=observer.logdata,
+ logdataapis=observer.logdataapis)
 
 def recv(self, *args, **kwargs):
 return object.__getattribute__(self, r'_observedcall')(
@@ -818,26 +819,34 @@
 class 

D2843: url: support suppressing Accept header

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

REVISION SUMMARY
  Sending this header automatically could interfere with future
  testing and client behavior. Let's add a knob to disable the
  behavior.
  
  We don't have a control for User-Agent because urllib will send
  it if we don't set something. I don't feel like hacking into the
  bowels of urllib to figure out how to suppress that. UA shouldn't
  be used for anything meaningful. So it shouldn't pose any problems
  beyond non-determinism (since the header has the Mercurial version in
  it).

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/debugcommands.py
  mercurial/url.py
  tests/test-http-protocol.t

CHANGE DETAILS

diff --git a/tests/test-http-protocol.t b/tests/test-http-protocol.t
--- a/tests/test-http-protocol.t
+++ b/tests/test-http-protocol.t
@@ -215,15 +215,13 @@
 
   $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
   > httprequest GET ?cmd=listkeys
-  > accept: application/mercurial-0.1
-  > user-agent: mercurial/proto-1.0 (Mercurial 42)
+  > user-agent: test
   > x-hgarg-1: namespace=namespaces
   > EOF
   using raw connection to peer
   s> GET /?cmd=listkeys HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
-  s> accept: application/mercurial-0.1\r\n
-  s> user-agent: mercurial/proto-1.0 (Mercurial 42)\r\n (glob)
+  s> user-agent: test\r\n
   s> x-hgarg-1: namespace=namespaces\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> \r\n
diff --git a/mercurial/url.py b/mercurial/url.py
--- a/mercurial/url.py
+++ b/mercurial/url.py
@@ -494,7 +494,7 @@
 handlerfuncs = []
 
 def opener(ui, authinfo=None, useragent=None, loggingfh=None,
-   loggingname=b's', loggingopts=None):
+   loggingname=b's', loggingopts=None, sendaccept=True):
 '''
 construct an opener suitable for urllib2
 authinfo will be added to the password manager
@@ -506,6 +506,9 @@
 ``loggingname`` denotes the name of the to print when logging.
 ``loggingopts`` is a dict of keyword arguments to pass to the constructed
 ``util.socketobserver`` instance.
+
+``sendaccept`` allows controlling whether the ``Accept`` request header
+is sent. The header is sent by default.
 '''
 handlers = []
 
@@ -562,7 +565,9 @@
 # been sent on all requests since forever. We keep sending it for backwards
 # compatibility reasons. Modern versions of the wire protocol use
 # X-HgProto- for advertising client support.
-opener.addheaders.append((r'Accept', r'application/mercurial-0.1'))
+if sendaccept:
+opener.addheaders.append((r'Accept', r'application/mercurial-0.1'))
+
 return opener
 
 def open(ui, url_, data=None):
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -2832,6 +2832,12 @@
 if ui.debugflag:
 openerargs[r'loggingopts'][r'logdataapis'] = True
 
+# Don't send default headers when in raw mode. This allows us to
+# bypass most of the behavior of our URL handling code so we can
+# have near complete control over what's sent on the wire.
+if opts['peer'] == 'raw':
+openerargs[r'sendaccept'] = False
+
 opener = urlmod.opener(ui, authinfo, **openerargs)
 
 if opts['peer'] == 'raw':



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


D2834: wireproto: support /api/* URL space for exposing APIs

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 6998.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2834?vs=6979=6998

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

AFFECTED FILES
  mercurial/configitems.py
  mercurial/hgweb/hgweb_mod.py
  mercurial/wireprotoserver.py
  mercurial/wireprototypes.py
  tests/test-http-api-httpv2.t
  tests/test-http-api.t

CHANGE DETAILS

diff --git a/tests/test-http-api.t b/tests/test-http-api.t
new file mode 100644
--- /dev/null
+++ b/tests/test-http-api.t
@@ -0,0 +1,201 @@
+  $ send() {
+  >   hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT/
+  > }
+
+  $ hg init server
+  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
+  $ cat hg.pid > $DAEMON_PIDS
+
+Request to /api fails unless web.apiserver is enabled
+
+  $ send << EOF
+  > httprequest GET api
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 404 Not Found\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 44\r\n
+  s> \r\n
+  s> Experimental API server endpoint not enabled
+
+  $ send << EOF
+  > httprequest GET api/
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/ HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 404 Not Found\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 44\r\n
+  s> \r\n
+  s> Experimental API server endpoint not enabled
+
+Restart server with support for API server
+
+  $ killdaemons.py
+  $ cat > server/.hg/hgrc << EOF
+  > [experimental]
+  > web.apiserver = true
+  > EOF
+
+  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
+  $ cat hg.pid > $DAEMON_PIDS
+
+/api lists available APIs (empty since none are available by default)
+
+  $ send << EOF
+  > httprequest GET api
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 200 OK\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 100\r\n
+  s> \r\n
+  s> APIs can be accessed at /api/, where  can be one of the 
following:\n
+  s> \n
+  s> (no available APIs)\n
+
+  $ send << EOF
+  > httprequest GET api/
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/ HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 200 OK\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 100\r\n
+  s> \r\n
+  s> APIs can be accessed at /api/, where  can be one of the 
following:\n
+  s> \n
+  s> (no available APIs)\n
+
+Accessing an unknown API yields a 404
+
+  $ send << EOF
+  > httprequest GET api/unknown
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/unknown HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 404 Not Found\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 33\r\n
+  s> \r\n
+  s> Unknown API: unknown\n
+  s> Known APIs: 
+
+Accessing a known but not enabled API yields a different error
+
+  $ send << EOF
+  > httprequest GET api/exp-http-v2-0001
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001 HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 404 Not Found\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 33\r\n
+  s> \r\n
+  s> API exp-http-v2-0001 not enabled\n
+
+Restart server with support for HTTP v2 API
+
+  $ killdaemons.py
+  $ cat > server/.hg/hgrc << EOF
+  > [experimental]
+  > web.apiserver = true
+  > web.api.http-v2 = true
+  > EOF
+
+  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
+  $ cat hg.pid > $DAEMON_PIDS

D2840: hgweb: allow defining Server response header for HTTP server

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

REVISION SUMMARY
  By default, the string contains the Python version. Server
  operators may want to change this.
  
  Because we like deterministic tests, we change the test harness
  to always set this value to a known string. Various globs over
  the server header have now been removed.
  
  1. no-check-commit because we add version_string()

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/configitems.py
  mercurial/help/config.txt
  mercurial/hgweb/server.py
  tests/run-tests.py
  tests/test-archive.t
  tests/test-basic.t
  tests/test-commandserver.t
  tests/test-hgweb-commands.t
  tests/test-http-protocol.t

CHANGE DETAILS

diff --git a/tests/test-http-protocol.t b/tests/test-http-protocol.t
--- a/tests/test-http-protocol.t
+++ b/tests/test-http-protocol.t
@@ -50,41 +50,41 @@
   200 Script output follows
   content-type: application/mercurial-0.1
   date: $HTTP_DATE$
-  server: * (glob)
+  server: testing stub value
   transfer-encoding: chunked
 
 Server should send application/mercurial-0.1 when client says it wants it
 
   $ get-with-headers.py --hgproto '0.1' --headeronly $LOCALIP:$HGPORT 
'?cmd=getbundle=e93700bd72895c5addab234c56d4024b487a362f='
 -
   200 Script output follows
   content-type: application/mercurial-0.1
   date: $HTTP_DATE$
-  server: * (glob)
+  server: testing stub value
   transfer-encoding: chunked
 
 Server should send application/mercurial-0.2 when client says it wants it
 
   $ get-with-headers.py --hgproto '0.2' --headeronly $LOCALIP:$HGPORT 
'?cmd=getbundle=e93700bd72895c5addab234c56d4024b487a362f='
 -
   200 Script output follows
   content-type: application/mercurial-0.2
   date: $HTTP_DATE$
-  server: * (glob)
+  server: testing stub value
   transfer-encoding: chunked
 
   $ get-with-headers.py --hgproto '0.1 0.2' --headeronly $LOCALIP:$HGPORT 
'?cmd=getbundle=e93700bd72895c5addab234c56d4024b487a362f='
 -
   200 Script output follows
   content-type: application/mercurial-0.2
   date: $HTTP_DATE$
-  server: * (glob)
+  server: testing stub value
   transfer-encoding: chunked
 
 Requesting a compression format that server doesn't support results will fall 
back to 0.1
 
   $ get-with-headers.py --hgproto '0.2 comp=aa' --headeronly $LOCALIP:$HGPORT 
'?cmd=getbundle=e93700bd72895c5addab234c56d4024b487a362f='
 -
   200 Script output follows
   content-type: application/mercurial-0.1
   date: $HTTP_DATE$
-  server: * (glob)
+  server: testing stub value
   transfer-encoding: chunked
 
 #if zstd
@@ -106,7 +106,7 @@
   content-length: 41
   content-type: application/mercurial-0.1
   date: $HTTP_DATE$
-  server: * (glob)
+  server: testing stub value
   
   e93700bd72895c5addab234c56d4024b487a362f
 
diff --git a/tests/test-hgweb-commands.t b/tests/test-hgweb-commands.t
--- a/tests/test-hgweb-commands.t
+++ b/tests/test-hgweb-commands.t
@@ -1923,7 +1923,7 @@
   content-length: 12
   content-type: application/mercurial-0.1
   date: $HTTP_DATE$
-  server: * (glob)
+  server: testing stub value
   
   0
   Not Found
diff --git a/tests/test-commandserver.t b/tests/test-commandserver.t
--- a/tests/test-commandserver.t
+++ b/tests/test-commandserver.t
@@ -215,6 +215,7 @@
   ui.nontty=true
   web.address=localhost
   web\.ipv6=(?:True|False) (re)
+  web.server-header=testing stub value
   *** runcommand init foo
   *** runcommand -R foo showconfig ui defaults
   ui.slash=True
diff --git a/tests/test-basic.t b/tests/test-basic.t
--- a/tests/test-basic.t
+++ b/tests/test-basic.t
@@ -12,6 +12,7 @@
   ui.promptecho=True
   web.address=localhost
   web\.ipv6=(?:True|False) (re)
+  web.server-header=testing stub value
   $ hg init t
   $ cd t
 
diff --git a/tests/test-archive.t b/tests/test-archive.t
--- a/tests/test-archive.t
+++ b/tests/test-archive.t
@@ -128,24 +128,24 @@
   content-type: application/x-gzip
   date: $HTTP_DATE$
   etag: W/"*" (glob)
-  server: * (glob)
+  server: testing stub value
   transfer-encoding: chunked
   
   body: size=408, sha1=8fa06531bddecc365a9f5edb0f88b65974bfe505
   % tar.bz2 and zip disallowed should both give 403
   403 Archive type not allowed: bz2
   content-type: text/html; charset=ascii
   date: $HTTP_DATE$
   etag: W/"*" (glob)
-  server: * (glob)
+  server: testing stub value
   transfer-encoding: chunked
   
   body: size=1451, sha1=4c5cf0f574446c44feb7f88f4e0e2a56bd92c352
   403 Archive type not allowed: zip
   content-type: text/html; charset=ascii
   date: $HTTP_DATE$
   etag: W/"*" (glob)
-  server: * (glob)
+  server: testing stub value
   transfer-encoding: chunked
   
   body: size=1451, sha1=cbfa5574b337348bfd0564cc534474d002e7d6c7
@@ -156,24 +156,24 @@
   content-type: application/x-bzip2
   date: 

D2837: wireproto: require POST for all HTTPv2 requests

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 7000.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2837?vs=6983=7000

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

AFFECTED FILES
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoserver.py
  tests/test-http-api-httpv2.t

CHANGE DETAILS

diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t
--- a/tests/test-http-api-httpv2.t
+++ b/tests/test-http-api-httpv2.t
@@ -48,11 +48,11 @@
 Request to read-only command works out of the box
 
   $ send << EOF
-  > httprequest GET api/$HTTPV2/ro/known
+  > httprequest POST api/$HTTPV2/ro/known
   > user-agent: test
   > EOF
   using raw connection to peer
-  s> GET /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
+  s> POST /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> user-agent: test\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
@@ -69,11 +69,11 @@
 Request to unknown command yields 404
 
   $ send << EOF
-  > httprequest GET api/$HTTPV2/ro/badcommand
+  > httprequest POST api/$HTTPV2/ro/badcommand
   > user-agent: test
   > EOF
   using raw connection to peer
-  s> GET /api/exp-http-v2-0001/ro/badcommand HTTP/1.1\r\n
+  s> POST /api/exp-http-v2-0001/ro/badcommand HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> user-agent: test\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
@@ -87,9 +87,30 @@
   s> \r\n
   s> unknown wire protocol command: badcommand\n
 
+GET to read-only command yields a 405
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/ro/known
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 405 Method Not Allowed\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Allow: POST\r\n
+  s> Content-Length: 30\r\n
+  s> \r\n
+  s> commands require POST requests
+
 Request to read-write command fails because server is read-only by default
 
-GET to read-write request not allowed
+GET to read-write request yields 405
 
   $ send << EOF
   > httprequest GET api/$HTTPV2/rw/known
@@ -102,12 +123,13 @@
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> \r\n
   s> makefile('rb', None)
-  s> HTTP/1.1 405 push requires POST request\r\n
+  s> HTTP/1.1 405 Method Not Allowed\r\n
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
-  s> Content-Length: 17\r\n
+  s> Allow: POST\r\n
+  s> Content-Length: 30\r\n
   s> \r\n
-  s> permission denied
+  s> commands require POST requests
 
 Even for unknown commands
 
@@ -122,12 +144,13 @@
   s> host: $LOCALIP:$HGPORT\r\n (glob)
   s> \r\n
   s> makefile('rb', None)
-  s> HTTP/1.1 405 push requires POST request\r\n
+  s> HTTP/1.1 405 Method Not Allowed\r\n
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
-  s> Content-Length: 17\r\n
+  s> Allow: POST\r\n
+  s> Content-Length: 30\r\n
   s> \r\n
-  s> permission denied
+  s> commands require POST requests
 
 SSL required by default
 
@@ -158,38 +181,6 @@
   > web.api.http-v2 = true
   > [web]
   > push_ssl = false
-  > EOF
-
-  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
-  $ cat hg.pid > $DAEMON_PIDS
-
-Server insists on POST for read-write commands
-
-  $ send << EOF
-  > httprequest GET api/$HTTPV2/rw/known
-  > user-agent: test
-  > EOF
-  using raw connection to peer
-  s> GET /api/exp-http-v2-0001/rw/known HTTP/1.1\r\n
-  s> Accept-Encoding: identity\r\n
-  s> user-agent: test\r\n
-  s> host: $LOCALIP:$HGPORT\r\n (glob)
-  s> \r\n
-  s> makefile('rb', None)
-  s> HTTP/1.1 405 push requires POST request\r\n
-  s> Server: testing stub value\r\n
-  s> Date: $HTTP_DATE$\r\n
-  s> Content-Length: 17\r\n
-  s> \r\n
-  s> permission denied
-
-  $ killdaemons.py
-  $ cat > server/.hg/hgrc << EOF
-  > [experimental]
-  > web.apiserver = true
-  > web.api.http-v2 = true
-  > [web]
-  > push_ssl = false
   > allow-push = *
   > EOF
 
diff --git a/mercurial/wireprotoserver.py b/mercurial/wireprotoserver.py
--- a/mercurial/wireprotoserver.py
+++ b/mercurial/wireprotoserver.py
@@ -299,6 +299,12 @@
 res.setbodybytes(_('unknown permission: %s') % permission)
 return
 
+if req.method != 'POST':
+res.status = b'405 Method Not Allowed'
+res.headers[b'Allow'] = b'POST'
+res.setbodybytes(_('commands require POST requests'))
+return
+
 # At some point we'll want to use our own API instead of recycling the
 # behavior of version 1 of the wire protocol...
 # TODO return reasonable responses - not responses that overload the
diff --git 

D2836: wireproto: define permissions-based routing of HTTPv2 wire protocol

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 6999.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2836?vs=6982=6999

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

AFFECTED FILES
  mercurial/debugcommands.py
  mercurial/help/internals/wireprotocol.txt
  mercurial/wireprotoserver.py
  tests/test-http-api-httpv2.t

CHANGE DETAILS

diff --git a/tests/test-http-api-httpv2.t b/tests/test-http-api-httpv2.t
--- a/tests/test-http-api-httpv2.t
+++ b/tests/test-http-api-httpv2.t
@@ -1,3 +1,5 @@
+  $ HTTPV2=exp-http-v2-0001
+
   $ send() {
   >   hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT/
   > }
@@ -13,7 +15,7 @@
 HTTP v2 protocol not enabled by default
 
   $ send << EOF
-  > httprequest GET api/exp-http-v2-0001
+  > httprequest GET api/$HTTPV2
   > user-agent: test
   > EOF
   using raw connection to peer
@@ -43,14 +45,14 @@
   $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
   $ cat hg.pid > $DAEMON_PIDS
 
-Requests simply echo their path (for now)
+Request to read-only command works out of the box
 
   $ send << EOF
-  > httprequest GET api/exp-http-v2-0001/path1/path2
+  > httprequest GET api/$HTTPV2/ro/known
   > user-agent: test
   > EOF
   using raw connection to peer
-  s> GET /api/exp-http-v2-0001/path1/path2 HTTP/1.1\r\n
+  s> GET /api/exp-http-v2-0001/ro/known HTTP/1.1\r\n
   s> Accept-Encoding: identity\r\n
   s> user-agent: test\r\n
   s> host: $LOCALIP:$HGPORT\r\n (glob)
@@ -60,6 +62,178 @@
   s> Server: testing stub value\r\n
   s> Date: $HTTP_DATE$\r\n
   s> Content-Type: text/plain\r\n
-  s> Content-Length: 12\r\n
+  s> Content-Length: 9\r\n
+  s> \r\n
+  s> ro/known/
+
+Request to unknown command yields 404
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/ro/badcommand
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/ro/badcommand HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 404 Not Found\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Type: text/plain\r\n
+  s> Content-Length: 42\r\n
+  s> \r\n
+  s> unknown wire protocol command: badcommand\n
+
+Request to read-write command fails because server is read-only by default
+
+GET to read-write request not allowed
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/rw/known
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/rw/known HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 405 push requires POST request\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Length: 17\r\n
+  s> \r\n
+  s> permission denied
+
+Even for unknown commands
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/rw/badcommand
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/rw/badcommand HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 405 push requires POST request\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Length: 17\r\n
+  s> \r\n
+  s> permission denied
+
+SSL required by default
+
+  $ send << EOF
+  > httprequest POST api/$HTTPV2/rw/known
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> POST /api/exp-http-v2-0001/rw/known HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 403 ssl required\r\n
+  s> Server: testing stub value\r\n
+  s> Date: $HTTP_DATE$\r\n
+  s> Content-Length: 17\r\n
   s> \r\n
-  s> path1/path2/
+  s> permission denied
+
+Restart server to allow non-ssl read-write operations
+
+  $ killdaemons.py
+  $ cat > server/.hg/hgrc << EOF
+  > [experimental]
+  > web.apiserver = true
+  > web.api.http-v2 = true
+  > [web]
+  > push_ssl = false
+  > EOF
+
+  $ hg -R server serve -p $HGPORT -d --pid-file hg.pid
+  $ cat hg.pid > $DAEMON_PIDS
+
+Server insists on POST for read-write commands
+
+  $ send << EOF
+  > httprequest GET api/$HTTPV2/rw/known
+  > user-agent: test
+  > EOF
+  using raw connection to peer
+  s> GET /api/exp-http-v2-0001/rw/known HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> user-agent: test\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> HTTP/1.1 405 push requires POST request\r\n
+  s> Server: testing 

D2726: debugcommands: support connecting to HTTP peers

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 6994.
indygreg edited the summary of this revision.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2726?vs=6977=6994

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

AFFECTED FILES
  mercurial/debugcommands.py
  tests/test-http-protocol.t

CHANGE DETAILS

diff --git a/tests/test-http-protocol.t b/tests/test-http-protocol.t
--- a/tests/test-http-protocol.t
+++ b/tests/test-http-protocol.t
@@ -161,3 +161,69 @@
   : 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
   0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 6c 69 62 |t follows...zlib|
   0020: 78  |x|
+
+  $ killdaemons.py
+  $ cd ..
+
+Test listkeys for listing namespaces
+
+  $ hg init empty
+  $ hg -R empty serve -p $HGPORT -d --pid-file hg.pid
+  $ cat hg.pid > $DAEMON_PIDS
+
+  $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
+  > command listkeys
+  > namespace namespaces
+  > EOF
+  s> sendall(*, 0): (glob)
+  s> GET /?cmd=capabilities HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> accept: application/mercurial-0.1\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> user-agent: mercurial/proto-1.0 (Mercurial *)\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> readline() -> 36:
+  s> HTTP/1.1 200 Script output follows\r\n
+  s> readline() -> 28:
+  s> Server: testing stub value\r\n
+  s> readline() -> *: (glob)
+  s> Date: $HTTP_DATE$\r\n
+  s> readline() -> 41:
+  s> Content-Type: application/mercurial-0.1\r\n
+  s> readline() -> 21:
+  s> Content-Length: *\r\n (glob)
+  s> readline() -> 2:
+  s> \r\n
+  s> read(*) -> *: lookup branchmap pushkey known getbundle unbundlehash batch 
changegroupsubset streamreqs=generaldelta,revlogv1 $USUAL_BUNDLE2_CAPS_SERVER$ 
unbundle=HG10GZ,HG10BZ,HG10UN httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx 
compression=$BUNDLE2_COMPRESSIONS$ (glob)
+  sending listkeys command
+  s> sendall(*, 0): (glob)
+  s> GET /?cmd=listkeys HTTP/1.1\r\n
+  s> Accept-Encoding: identity\r\n
+  s> vary: X-HgArg-1,X-HgProto-1\r\n
+  s> x-hgarg-1: namespace=namespaces\r\n
+  s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$\r\n
+  s> accept: application/mercurial-0.1\r\n
+  s> host: $LOCALIP:$HGPORT\r\n (glob)
+  s> user-agent: mercurial/proto-1.0 (Mercurial *)\r\n (glob)
+  s> \r\n
+  s> makefile('rb', None)
+  s> readline() -> 36:
+  s> HTTP/1.1 200 Script output follows\r\n
+  s> readline() -> 28:
+  s> Server: testing stub value\r\n
+  s> readline() -> *: (glob)
+  s> Date: $HTTP_DATE$\r\n
+  s> readline() -> 41:
+  s> Content-Type: application/mercurial-0.1\r\n
+  s> readline() -> 20:
+  s> Content-Length: 30\r\n
+  s> readline() -> 2:
+  s> \r\n
+  s> read(30) -> 30:
+  s> bookmarks \n
+  s> namespaces\n
+  s> phases
+  response: bookmarks  \nnamespaces\nphases
+
+  $ killdaemons.py
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -48,6 +48,7 @@
 fileset,
 formatter,
 hg,
+httppeer,
 localrepo,
 lock as lockmod,
 logcmdutil,
@@ -2588,9 +2589,9 @@
 ('', 'peer', '', _('construct a specific version of the peer')),
 ('', 'noreadstderr', False, _('do not read from stderr of the 
remote')),
 ] + cmdutil.remoteopts,
-_('[REPO]'),
+_('[PATH]'),
 optionalrepo=True)
-def debugwireproto(ui, repo, **opts):
+def debugwireproto(ui, repo, path=None, **opts):
 """send wire protocol commands to a server
 
 This command can be used to issue wire protocol commands to remote
@@ -2726,12 +2727,19 @@
 raise error.Abort(_('invalid value for --peer'),
   hint=_('valid values are "raw", "ssh1", and "ssh2"'))
 
+if path and opts['localssh']:
+raise error.Abort(_('cannot specify --localssh with an explicit '
+'path'))
+
 if ui.interactive():
 ui.write(_('(waiting for commands on stdin)\n'))
 
 blocks = list(_parsewirelangblocks(ui.fin))
 
 proc = None
+stdin = None
+stdout = None
+stderr = None
 
 if opts['localssh']:
 # We start the SSH server in its own process so there is process
@@ -2779,22 +2787,61 @@
 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
 autoreadstderr=autoreadstderr)
 
+elif path:
+# We bypass hg.peer() so we can proxy the sockets.
+# TODO consider not doing this because we skip
+# ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
+u = util.url(path)
+if u.scheme != 'http':
+raise error.Abort(_('only http:// paths are currently supported'))
+
+url, authinfo = u.authinfo()
+openerargs = {}
+
+   

D2839: tests: use $HTTP_DATE$ for Date header

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

REVISION SUMMARY
  Support for the $HTTP_DATE$ substitution was recently added. Let's
  adopt it more widely.
  
  We had to tweak the substitution to be case insensitive, since
  HTTP headers are case insensitive. I also found a minor test
  issue not globbing over the length of the Server response header.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  tests/common-pattern.py
  tests/test-archive.t
  tests/test-hgweb-commands.t
  tests/test-http-protocol.t

CHANGE DETAILS

diff --git a/tests/test-http-protocol.t b/tests/test-http-protocol.t
--- a/tests/test-http-protocol.t
+++ b/tests/test-http-protocol.t
@@ -49,41 +49,41 @@
   $ get-with-headers.py --headeronly $LOCALIP:$HGPORT 
'?cmd=getbundle=e93700bd72895c5addab234c56d4024b487a362f='
 -
   200 Script output follows
   content-type: application/mercurial-0.1
-  date: * (glob)
+  date: $HTTP_DATE$
   server: * (glob)
   transfer-encoding: chunked
 
 Server should send application/mercurial-0.1 when client says it wants it
 
   $ get-with-headers.py --hgproto '0.1' --headeronly $LOCALIP:$HGPORT 
'?cmd=getbundle=e93700bd72895c5addab234c56d4024b487a362f='
 -
   200 Script output follows
   content-type: application/mercurial-0.1
-  date: * (glob)
+  date: $HTTP_DATE$
   server: * (glob)
   transfer-encoding: chunked
 
 Server should send application/mercurial-0.2 when client says it wants it
 
   $ get-with-headers.py --hgproto '0.2' --headeronly $LOCALIP:$HGPORT 
'?cmd=getbundle=e93700bd72895c5addab234c56d4024b487a362f='
 -
   200 Script output follows
   content-type: application/mercurial-0.2
-  date: * (glob)
+  date: $HTTP_DATE$
   server: * (glob)
   transfer-encoding: chunked
 
   $ get-with-headers.py --hgproto '0.1 0.2' --headeronly $LOCALIP:$HGPORT 
'?cmd=getbundle=e93700bd72895c5addab234c56d4024b487a362f='
 -
   200 Script output follows
   content-type: application/mercurial-0.2
-  date: * (glob)
+  date: $HTTP_DATE$
   server: * (glob)
   transfer-encoding: chunked
 
 Requesting a compression format that server doesn't support results will fall 
back to 0.1
 
   $ get-with-headers.py --hgproto '0.2 comp=aa' --headeronly $LOCALIP:$HGPORT 
'?cmd=getbundle=e93700bd72895c5addab234c56d4024b487a362f='
 -
   200 Script output follows
   content-type: application/mercurial-0.1
-  date: * (glob)
+  date: $HTTP_DATE$
   server: * (glob)
   transfer-encoding: chunked
 
@@ -105,7 +105,7 @@
   200 Script output follows
   content-length: 41
   content-type: application/mercurial-0.1
-  date: * (glob)
+  date: $HTTP_DATE$
   server: * (glob)
   
   e93700bd72895c5addab234c56d4024b487a362f
diff --git a/tests/test-hgweb-commands.t b/tests/test-hgweb-commands.t
--- a/tests/test-hgweb-commands.t
+++ b/tests/test-hgweb-commands.t
@@ -1922,7 +1922,7 @@
   404 Not Found
   content-length: 12
   content-type: application/mercurial-0.1
-  date: * (glob)
+  date: $HTTP_DATE$
   server: * (glob)
   
   0
diff --git a/tests/test-archive.t b/tests/test-archive.t
--- a/tests/test-archive.t
+++ b/tests/test-archive.t
@@ -126,24 +126,24 @@
   200 Script output follows
   content-disposition: attachment; filename=test-archive-1701ef1f1510.tar.gz
   content-type: application/x-gzip
-  date: * (glob)
+  date: $HTTP_DATE$
   etag: W/"*" (glob)
   server: * (glob)
   transfer-encoding: chunked
   
   body: size=408, sha1=8fa06531bddecc365a9f5edb0f88b65974bfe505
   % tar.bz2 and zip disallowed should both give 403
   403 Archive type not allowed: bz2
   content-type: text/html; charset=ascii
-  date: * (glob)
+  date: $HTTP_DATE$
   etag: W/"*" (glob)
   server: * (glob)
   transfer-encoding: chunked
   
   body: size=1451, sha1=4c5cf0f574446c44feb7f88f4e0e2a56bd92c352
   403 Archive type not allowed: zip
   content-type: text/html; charset=ascii
-  date: * (glob)
+  date: $HTTP_DATE$
   etag: W/"*" (glob)
   server: * (glob)
   transfer-encoding: chunked
@@ -154,24 +154,24 @@
   200 Script output follows
   content-disposition: attachment; filename=test-archive-1701ef1f1510.tar.bz2
   content-type: application/x-bzip2
-  date: * (glob)
+  date: $HTTP_DATE$
   etag: W/"*" (glob)
   server: * (glob)
   transfer-encoding: chunked
   
   body: size=426, sha1=8d87f5aba6e14f1bfea6c232985982c278b2fb0b
   % zip and tar.gz disallowed should both give 403
   403 Archive type not allowed: zip
   content-type: text/html; charset=ascii
-  date: * (glob)
+  date: $HTTP_DATE$
   etag: W/"*" (glob)
   server: * (glob)
   transfer-encoding: chunked
   
   body: size=1451, sha1=cbfa5574b337348bfd0564cc534474d002e7d6c7
   403 Archive type not allowed: gz
   content-type: text/html; charset=ascii
-  date: * (glob)
+  date: 

D2721: util: observable proxy objects for sockets

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg planned changes to this revision.
indygreg added a comment.


  I have significant changes to this series in flight. It's worth holding off 
on review.

REPOSITORY
  rHG Mercurial

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

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


D2834: wireproto: support /api/* URL space for exposing APIs

2018-03-13 Thread mharbison72 (Matt Harbison)
mharbison72 added a comment.


  In https://phab.mercurial-scm.org/D2834#45696, @indygreg wrote:
  
  > In https://phab.mercurial-scm.org/D2834#45666, @mharbison72 wrote:
  >
  > > Will this cause conflicts with `hg serve -S` or hgwebdir with 
subrepo/virtual paths that start with 'api'?  (This was the reason I used the 
LFS URI starting with '.hg/', knowing that isn't committable.)
  >
  >
  > Bleh.
  >
  > So what I'm hearing is that because of hgwebdir's virtual paths and support 
for serving subrepos, pretty much the entire URL space is dangerous because it 
can conflict with the path of a virtual repo or subrepo. I suppose we already 
have problems with existing URLs, like `/rev/`.
  
  
  I think so.  I remember when Yuya suggested putting the `/index` virtual file 
into hgwebdir a year ago, I had to dance around the fact that 'index' could 
have been a repo being served up.   I'm guessing `/rev/` et al. is less of a 
problem, because presumably they've existed since the beginning?
  
  > I agree that putting things under `.hg/` in the URL space seems to be a 
viable workaround.
  > 
  > Changing the URL prefix isn't a big deal as far as the code is concerned. 
We can make that change at any time since we have no BC guarantees at this 
juncture.
  
  I'm fine with landing this as-is and changing it later if needed.  I haven't 
checked this myself, I was just going on a vague memory of issues that I ran 
into, and wondered if you had considered it.

REPOSITORY
  rHG Mercurial

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

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


[PATCH] peer-request: include more details about batch commands

2018-03-13 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1520268508 18000
#  Mon Mar 05 11:48:28 2018 -0500
# Node ID 025b0a829b1c9a299b76b7303b4d46c269fcba48
# Parent  31581528f2421dc5d8a567125b8ecc0367b2b906
# EXP-Topic peer-request.batch
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
025b0a829b1c
peer-request: include more details about batch commands

A batch commands encapsulate multiple other commands. We display a bit more
details about what is actually batched if peer request tracking is set.

diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -400,6 +400,13 @@ class wirepeer(repository.legacypeer):
 
 Returns an iterator of the raw responses from the server.
 """
+ui = self.ui
+if ui.debugflag and ui.configbool('devel', 'debug.peer-request'):
+ui.debug('devel-peer-request: batched-content\n')
+for op, args in req:
+msg = 'devel-peer-request:- %s (%d arguments)\n'
+ui.debug(msg % (op, len(args)))
+
 rsp = self._callstream("batch", cmds=encodebatchcmds(req))
 chunk = rsp.read(1024)
 work = [chunk]
diff --git a/tests/test-http.t b/tests/test-http.t
--- a/tests/test-http.t
+++ b/tests/test-http.t
@@ -257,6 +257,9 @@ test http authentication
   http auth: user user, password 
   devel-peer-request:   finished in *. seconds (200) (glob)
   query 1; heads
+  devel-peer-request: batched-content
+  devel-peer-request:- heads (0 arguments)
+  devel-peer-request:- known (1 arguments)
   sending batch command
   devel-peer-request: GET http://localhost:$HGPORT2/?cmd=batch
   devel-peer-request:   Vary X-HgArg-1,X-HgProto-1
diff --git a/tests/test-ssh.t b/tests/test-ssh.t
--- a/tests/test-ssh.t
+++ b/tests/test-ssh.t
@@ -501,6 +501,9 @@ debug output
   remote: capabilities: lookup branchmap pushkey known getbundle unbundlehash 
batch changegroupsubset streamreqs=generaldelta,revlogv1 
$USUAL_BUNDLE2_CAPS_SERVER$ unbundle=HG10GZ,HG10BZ,HG10UN
   remote: 1 (sshv1 !)
   query 1; heads
+  devel-peer-request: batched-content
+  devel-peer-request:- heads (0 arguments)
+  devel-peer-request:- known (1 arguments)
   devel-peer-request: batch
   devel-peer-request:   cmds: 141 bytes
   sending batch command
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 2] push-discovery: don't turn use generator when comparing bookmarks

2018-03-13 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1520609495 -3600
#  Fri Mar 09 16:31:35 2018 +0100
# Node ID 9ecb102cd955e075a6a637f1b8d4f5c8e3015751
# Parent  2cdf47e14c30dbdc2ebc0fd498fc0b85205ce2b3
# EXP-Topic push-book-handling
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
9ecb102cd955
push-discovery: don't turn use generator when comparing bookmarks

We want extensions to be able to implement their own logic. Generators can be
consume only once, impractical for this purpose.

diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -620,8 +620,8 @@ def _pushdiscoverybookmarks(pushop):
 return hex(x)
 
 def hexifycompbookmarks(bookmarks):
-for b, scid, dcid in bookmarks:
-yield b, safehex(scid), safehex(dcid)
+return [(b, safehex(scid), safehex(dcid))
+for (b, scid, dcid) in bookmarks]
 
 comp = [hexifycompbookmarks(marks) for marks in comp]
 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = comp
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 2] push-discovery: extract the bookmark comparison logic in its own function

2018-03-13 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1520607221 -3600
#  Fri Mar 09 15:53:41 2018 +0100
# Node ID 5b15c9c72bc88931d5a5dc9bfec0935098c04402
# Parent  9ecb102cd955e075a6a637f1b8d4f5c8e3015751
# EXP-Topic push-book-handling
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
5b15c9c72bc8
push-discovery: extract the bookmark comparison logic in its own function

This will help extensions to alter the behavior as they see fit.

diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -624,12 +624,20 @@ def _pushdiscoverybookmarks(pushop):
 for (b, scid, dcid) in bookmarks]
 
 comp = [hexifycompbookmarks(marks) for marks in comp]
+return _processcompared(pushop, ancestors, explicit, remotebookmark, comp)
+
+def _processcompared(pushop, pushed, explicit, remotebms, comp):
+"""take decision on bookmark to pull from the remote bookmark
+
+Exist to help extension who want to alter this behavior."""
 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = comp
 
+repo = pushop.repo
+
 for b, scid, dcid in advsrc:
 if b in explicit:
 explicit.remove(b)
-if not ancestors or repo[scid].rev() in ancestors:
+if not pushed or repo[scid].rev() in pushed:
 pushop.outbookmarks.append((b, dcid, scid))
 # search added bookmark
 for b, scid, dcid in addsrc:
@@ -655,8 +663,8 @@ def _pushdiscoverybookmarks(pushop):
 if explicit:
 explicit = sorted(explicit)
 # we should probably list all of them
-ui.warn(_('bookmark %s does not exist on the local '
-  'or remote repository!\n') % explicit[0])
+pushop.ui.warn(_('bookmark %s does not exist on the local '
+ 'or remote repository!\n') % explicit[0])
 pushop.bkresult = 2
 
 pushop.outbookmarks.sort()
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D2833: tests: teach get-with-headers.py to ignore dynamic headers

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg abandoned this revision.
indygreg added a comment.


  I like Matt's patch and will do something more deterministic.

REPOSITORY
  rHG Mercurial

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

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


D2838: util: clear debugstacktrace call

2018-03-13 Thread lothiraldan (Boris Feld)
lothiraldan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  During the renaming of datestr, it seems that I have forget a debugstacktrace
  in util.py. Remove it.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/util.py

CHANGE DETAILS

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -4027,7 +4027,6 @@
 msg = ("'util.datestr' is deprecated, "
"use 'utils.dateutil.datestr'")
 nouideprecwarn(msg, "4.6")
-debugstacktrace()
 return dateutil.datestr(*args, **kwargs)
 
 def shortdate(*args, **kwargs):



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


mercurial@36855: 10 new changesets

2018-03-13 Thread Mercurial Commits
10 new changesets in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/14f70c44af6c
changeset:   36846:14f70c44af6c
parent:  36843:31581528f242
user:Gregory Szorc 
date:Thu Mar 08 16:38:01 2018 -0800
summary: wireprotoserver: access headers through parsed request

https://www.mercurial-scm.org/repo/hg/rev/ed0456fde625
changeset:   36847:ed0456fde625
user:Gregory Szorc 
date:Sat Mar 10 10:45:12 2018 -0800
summary: hgweb: handle CONTENT_LENGTH

https://www.mercurial-scm.org/repo/hg/rev/16292bbda39c
changeset:   36848:16292bbda39c
user:Gregory Szorc 
date:Sat Mar 10 10:44:56 2018 -0800
summary: hgweb: store and use request method on parsed request

https://www.mercurial-scm.org/repo/hg/rev/0bc771bba220
changeset:   36849:0bc771bba220
user:Gregory Szorc 
date:Thu Mar 08 17:17:48 2018 -0800
summary: wireprotoserver: remove unused argument from _handlehttperror()

https://www.mercurial-scm.org/repo/hg/rev/e85574176467
changeset:   36850:e85574176467
user:Gregory Szorc 
date:Sat Mar 10 10:46:08 2018 -0800
summary: hgweb: remove unused methods on wsgirequest

https://www.mercurial-scm.org/repo/hg/rev/d6cd1451212e
changeset:   36851:d6cd1451212e
user:Gregory Szorc 
date:Thu Mar 08 17:57:07 2018 -0800
summary: hgweb: remove wsgirequest.read()

https://www.mercurial-scm.org/repo/hg/rev/e3f809e0fe8e
changeset:   36852:e3f809e0fe8e
user:Gregory Szorc 
date:Thu Mar 08 18:00:04 2018 -0800
summary: hgweb: remove wsgirequest.__iter__

https://www.mercurial-scm.org/repo/hg/rev/7066617187c1
changeset:   36853:7066617187c1
user:Gregory Szorc 
date:Sat Mar 10 10:47:30 2018 -0800
summary: hgweb: document continuereader

https://www.mercurial-scm.org/repo/hg/rev/290fc4c3d1e0
changeset:   36854:290fc4c3d1e0
user:Gregory Szorc 
date:Sat Mar 10 10:48:34 2018 -0800
summary: hgweb: use a capped reader for WSGI input stream

https://www.mercurial-scm.org/repo/hg/rev/2cdf47e14c30
changeset:   36855:2cdf47e14c30
bookmark:@
tag: tip
user:Gregory Szorc 
date:Sat Mar 10 11:03:45 2018 -0800
summary: hgweb: refactor the request draining code

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


D2834: wireproto: support /api/* URL space for exposing APIs

2018-03-13 Thread indygreg (Gregory Szorc)
indygreg added a comment.


  In https://phab.mercurial-scm.org/D2834#45666, @mharbison72 wrote:
  
  > Will this cause conflicts with `hg serve -S` or hgwebdir with 
subrepo/virtual paths that start with 'api'?  (This was the reason I used the 
LFS URI starting with '.hg/', knowing that isn't committable.)
  
  
  Bleh.
  
  So what I'm hearing is that because of hgwebdir's virtual paths and support 
for serving subrepos, pretty much the entire URL space is dangerous because it 
can conflict with the path of a virtual repo or subrepo. I suppose we already 
have problems with existing URLs, like `/rev/`.
  
  I agree that putting things under `.hg/` in the URL space seems to be a 
viable workaround.
  
  Changing the URL prefix isn't a big deal as far as the code is concerned. We 
can make that change at any time since we have no BC guarantees at this 
juncture.

REPOSITORY
  rHG Mercurial

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

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


Re: [PATCH 1 of 4] pycompat: name maplist() and ziplist() for better traceback message

2018-03-13 Thread Pulkit Goyal
On Tue, Mar 13, 2018 at 7:25 PM, Yuya Nishihara  wrote:
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1520943734 -32400
> #  Tue Mar 13 21:22:14 2018 +0900
> # Node ID aa35c6d7caef9ef9f48d0c9c831f9492c1421c45
> # Parent  6aeb076b1321c540db6419fc48c8a3a552fb596b
> pycompat: name maplist() and ziplist() for better traceback message

Queued the first two patches. Many thanks!
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


mercurial@36845: new changeset (1 on stable)

2018-03-13 Thread Mercurial Commits
New changeset (1 on stable) in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/ff2370a70fe8
changeset:   36845:ff2370a70fe8
branch:  stable
tag: tip
user:Gregory Szorc 
date:Mon Mar 12 13:15:00 2018 -0700
summary: hgweb: garbage collect on every request

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


D2761: rebase: use configoverride context manager for ui.forcemerge

2018-03-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG6b6d7f127ee5: rebase: use configoverride context manager 
for ui.forcemerge (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2761?vs=6873=6987

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

AFFECTED FILES
  hgext/rebase.py

CHANGE DETAILS

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -481,9 +481,8 @@
 if len(repo[None].parents()) == 2:
 repo.ui.debug('resuming interrupted rebase\n')
 else:
-try:
-ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
- 'rebase')
+overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
+with ui.configoverride(overrides, 'rebase'):
 stats = rebasenode(repo, rev, p1, base, self.collapsef,
dest, wctx=self.wctx)
 if stats and stats[3] > 0:
@@ -493,8 +492,6 @@
 raise error.InterventionRequired(
 _('unresolved conflicts (see hg '
   'resolve, then hg rebase --continue)'))
-finally:
-ui.setconfig('ui', 'forcemerge', '', 'rebase')
 if not self.collapsef:
 merging = p2 != nullrev
 editform = cmdutil.mergeeditform(merging, 'rebase')



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


D2759: rebase: fix issue 5494 also with --collapse

2018-03-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG72e58801950a: rebase: fix issue 5494 also with --collapse 
(authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2759?vs=6787=6985

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

AFFECTED FILES
  hgext/rebase.py
  tests/test-rebase-interruptions.t

CHANGE DETAILS

diff --git a/tests/test-rebase-interruptions.t 
b/tests/test-rebase-interruptions.t
--- a/tests/test-rebase-interruptions.t
+++ b/tests/test-rebase-interruptions.t
@@ -479,7 +479,6 @@
   $ hg rebase --continue
   rebasing 2:fdaca8533b86 "b" (tip)
   saved backup bundle to 
$TESTTMP/repo/.hg/strip-backup/fdaca8533b86-7fd70513-rebase.hg
-BROKEN: the merge state was not cleared
   $ hg resolve --list
-  R a
   $ test -d .hg/merge
+  [1]
diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -579,6 +579,12 @@
 editor=editor,
 keepbranches=self.keepbranchesf,
 date=self.date)
+
+if newnode is None:
+# If it ended up being a no-op commit, then the normal
+# merge state clean-up path doesn't happen, so do it
+# here. Fix issue5494
+mergemod.mergestate.clean(repo)
 if newnode is not None:
 newrev = repo[newnode].rev()
 for oldrev in self.state:



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


D2811: rebase: move constant expressions out of inner loop in _performrebase()

2018-03-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG41d6df958331: rebase: move constant expressions out of 
inner loop in _performrebase() (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2811?vs=6876=6990

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

AFFECTED FILES
  hgext/rebase.py

CHANGE DETAILS

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -423,26 +423,24 @@
 
 cands = [k for k, v in self.state.iteritems() if v == revtodo]
 total = len(cands)
-pos = 0
+posholder = [0]
+def progress(ctx):
+posholder[0] += 1
+self.repo.ui.progress(_("rebasing"), posholder[0],
+  ("%d:%s" % (ctx.rev(), ctx)),
+  _('changesets'), total)
+allowdivergence = self.ui.configbool(
+'experimental', 'evolution.allowdivergence')
 for subset in sortsource(self.destmap):
 sortedrevs = self.repo.revs('sort(%ld, -topo)', subset)
-allowdivergence = self.ui.configbool(
-'experimental', 'evolution.allowdivergence')
 if not allowdivergence:
 sortedrevs -= self.repo.revs(
 'descendants(%ld) and not %ld',
 self.obsoletewithoutsuccessorindestination,
 self.obsoletewithoutsuccessorindestination,
 )
-posholder = [pos]
-def progress(ctx):
-posholder[0] += 1
-self.repo.ui.progress(_("rebasing"), posholder[0],
-  ("%d:%s" % (ctx.rev(), ctx)),
-  _('changesets'), total)
 for rev in sortedrevs:
 self._rebasenode(tr, rev, allowdivergence, progress)
-pos = posholder[0]
 ui.progress(_('rebasing'), None)
 ui.note(_('rebase merging completed\n'))
 



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


D2810: rebase: inline _performrebasesubset()

2018-03-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG0cc850a43e6c: rebase: inline _performrebasesubset() 
(authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2810?vs=6875=6989

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

AFFECTED FILES
  hgext/rebase.py

CHANGE DETAILS

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -425,30 +425,27 @@
 total = len(cands)
 pos = 0
 for subset in sortsource(self.destmap):
-pos = self._performrebasesubset(tr, subset, pos, total)
+sortedrevs = self.repo.revs('sort(%ld, -topo)', subset)
+allowdivergence = self.ui.configbool(
+'experimental', 'evolution.allowdivergence')
+if not allowdivergence:
+sortedrevs -= self.repo.revs(
+'descendants(%ld) and not %ld',
+self.obsoletewithoutsuccessorindestination,
+self.obsoletewithoutsuccessorindestination,
+)
+posholder = [pos]
+def progress(ctx):
+posholder[0] += 1
+self.repo.ui.progress(_("rebasing"), posholder[0],
+  ("%d:%s" % (ctx.rev(), ctx)),
+  _('changesets'), total)
+for rev in sortedrevs:
+self._rebasenode(tr, rev, allowdivergence, progress)
+pos = posholder[0]
 ui.progress(_('rebasing'), None)
 ui.note(_('rebase merging completed\n'))
 
-def _performrebasesubset(self, tr, subset, pos, total):
-sortedrevs = self.repo.revs('sort(%ld, -topo)', subset)
-allowdivergence = self.ui.configbool(
-'experimental', 'evolution.allowdivergence')
-if not allowdivergence:
-sortedrevs -= self.repo.revs(
-'descendants(%ld) and not %ld',
-self.obsoletewithoutsuccessorindestination,
-self.obsoletewithoutsuccessorindestination,
-)
-posholder = [pos]
-def progress(ctx):
-posholder[0] += 1
-self.repo.ui.progress(_("rebasing"), posholder[0],
-  ("%d:%s" % (ctx.rev(), ctx)), 
_('changesets'),
-  total)
-for rev in sortedrevs:
-self._rebasenode(tr, rev, allowdivergence, progress)
-return posholder[0]
-
 def _rebasenode(self, tr, rev, allowdivergence, progressfn):
 repo, ui, opts = self.repo, self.ui, self.opts
 dest = self.destmap[rev]



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


D2728: rebase: also include commit of collapsed commits in single transaction

2018-03-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG67e18654a9eb: rebase: also include commit of collapsed 
commits in single transaction (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2728?vs=6768=6984

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

AFFECTED FILES
  hgext/rebase.py
  tests/test-rebase-transaction.t

CHANGE DETAILS

diff --git a/tests/test-rebase-transaction.t b/tests/test-rebase-transaction.t
--- a/tests/test-rebase-transaction.t
+++ b/tests/test-rebase-transaction.t
@@ -29,11 +29,9 @@
   >   |/
   >   A
   > EOF
-- We should only see two status stored messages. One from the start, one from
-- the end.
+- We should only see one status stored message. It comes from the start.
   $ hg rebase --debug -b D -d Z | grep 'status stored'
   rebase status stored
-  rebase status stored
   $ hg tglog
   o  5: D
   |
@@ -64,7 +62,7 @@
   >   A
   > EOF
 - We should only see two status stored messages. One from the start, one from
-- the end.
+- cmdutil.commitforceeditor() which forces tr.writepending()
   $ hg rebase --collapse --debug -b D -d Z | grep 'status stored'
   rebase status stored
   rebase status stored
@@ -162,12 +160,14 @@
   rebasing 1:112478962961 "B" (B)
   rebasing 3:26805aba1e60 "C" (C)
   rebasing 5:f585351a92f8 "D" (D tip)
+  transaction abort!
+  rollback completed
   abort: edit failed: false exited with status 1
   [255]
   $ hg tglog
   o  5: D
   |
-  | @  4: Z
+  | o  4: Z
   | |
   o |  3: C
   | |
@@ -178,9 +178,9 @@
   o  0: A
   
   $ hg rebase --continue
-  already rebased 1:112478962961 "B" (B) as e9b22a392ce0
-  already rebased 3:26805aba1e60 "C" (C) as e9b22a392ce0
-  already rebased 5:f585351a92f8 "D" (D tip) as e9b22a392ce0
+  rebasing 1:112478962961 "B" (B)
+  rebasing 3:26805aba1e60 "C" (C)
+  rebasing 5:f585351a92f8 "D" (D tip)
   saved backup bundle to 
$TESTTMP/collapse-cancel-editor/.hg/strip-backup/112478962961-cb2a9b47-rebase.hg
   $ hg tglog
   o  3: Collapsed revision
diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -573,16 +573,12 @@
 keepbranches=self.keepbranchesf,
 date=self.date, wctx=self.wctx)
 else:
-dsguard = None
-if ui.configbool('rebase', 'singletransaction'):
-dsguard = dirstateguard.dirstateguard(repo, 'rebase')
-with util.acceptintervention(dsguard):
-newnode = concludenode(repo, revtoreuse, p1, self.external,
-commitmsg=commitmsg,
-extrafn=_makeextrafn(self.extrafns),
-editor=editor,
-keepbranches=self.keepbranchesf,
-date=self.date)
+newnode = concludenode(repo, revtoreuse, p1, self.external,
+commitmsg=commitmsg,
+extrafn=_makeextrafn(self.extrafns),
+editor=editor,
+keepbranches=self.keepbranchesf,
+date=self.date)
 if newnode is not None:
 newrev = repo[newnode].rev()
 for oldrev in self.state:
@@ -864,8 +860,7 @@
 dsguard = dirstateguard.dirstateguard(repo, 'rebase')
 with util.acceptintervention(dsguard):
 rbsrt._performrebase(tr)
-
-rbsrt._finishrebase()
+rbsrt._finishrebase()
 
 def _definedestmap(ui, repo, rbsrt, destf=None, srcf=None, basef=None,
revf=None, destspace=None):



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


D2809: rebase: extract function for rebasing a single node

2018-03-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGd56e4d78a366: rebase: extract function for rebasing a 
single node (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2809?vs=6874=6988

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

AFFECTED FILES
  hgext/rebase.py

CHANGE DETAILS

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -430,115 +430,122 @@
 ui.note(_('rebase merging completed\n'))
 
 def _performrebasesubset(self, tr, subset, pos, total):
-repo, ui, opts = self.repo, self.ui, self.opts
-sortedrevs = repo.revs('sort(%ld, -topo)', subset)
+sortedrevs = self.repo.revs('sort(%ld, -topo)', subset)
 allowdivergence = self.ui.configbool(
 'experimental', 'evolution.allowdivergence')
 if not allowdivergence:
-sortedrevs -= repo.revs(
+sortedrevs -= self.repo.revs(
 'descendants(%ld) and not %ld',
 self.obsoletewithoutsuccessorindestination,
 self.obsoletewithoutsuccessorindestination,
 )
+posholder = [pos]
+def progress(ctx):
+posholder[0] += 1
+self.repo.ui.progress(_("rebasing"), posholder[0],
+  ("%d:%s" % (ctx.rev(), ctx)), 
_('changesets'),
+  total)
 for rev in sortedrevs:
-dest = self.destmap[rev]
-ctx = repo[rev]
-desc = _ctxdesc(ctx)
-if self.state[rev] == rev:
-ui.status(_('already rebased %s\n') % desc)
-elif (not allowdivergence
-  and rev in self.obsoletewithoutsuccessorindestination):
-msg = _('note: not rebasing %s and its descendants as '
-'this would cause divergence\n') % desc
-repo.ui.status(msg)
-self.skipped.add(rev)
-elif rev in self.obsoletenotrebased:
-succ = self.obsoletenotrebased[rev]
-if succ is None:
-msg = _('note: not rebasing %s, it has no '
-'successor\n') % desc
-else:
-succdesc = _ctxdesc(repo[succ])
-msg = (_('note: not rebasing %s, already in '
- 'destination as %s\n') % (desc, succdesc))
-repo.ui.status(msg)
-# Make clearrebased aware state[rev] is not a true successor
-self.skipped.add(rev)
-# Record rev as moved to its desired destination in self.state.
-# This helps bookmark and working parent movement.
-dest = max(adjustdest(repo, rev, self.destmap, self.state,
-  self.skipped))
-self.state[rev] = dest
-elif self.state[rev] == revtodo:
-pos += 1
-ui.status(_('rebasing %s\n') % desc)
-ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, ctx)),
-_('changesets'), total)
-p1, p2, base = defineparents(repo, rev, self.destmap,
- self.state, self.skipped,
- self.obsoletenotrebased)
-self.storestatus(tr=tr)
-if len(repo[None].parents()) == 2:
-repo.ui.debug('resuming interrupted rebase\n')
+self._rebasenode(tr, rev, allowdivergence, progress)
+return posholder[0]
+
+def _rebasenode(self, tr, rev, allowdivergence, progressfn):
+repo, ui, opts = self.repo, self.ui, self.opts
+dest = self.destmap[rev]
+ctx = repo[rev]
+desc = _ctxdesc(ctx)
+if self.state[rev] == rev:
+ui.status(_('already rebased %s\n') % desc)
+elif (not allowdivergence
+  and rev in self.obsoletewithoutsuccessorindestination):
+msg = _('note: not rebasing %s and its descendants as '
+'this would cause divergence\n') % desc
+repo.ui.status(msg)
+self.skipped.add(rev)
+elif rev in self.obsoletenotrebased:
+succ = self.obsoletenotrebased[rev]
+if succ is None:
+msg = _('note: not rebasing %s, it has no '
+'successor\n') % desc
+else:
+succdesc = _ctxdesc(repo[succ])
+msg = (_('note: not rebasing %s, already in '
+ 'destination as %s\n') % (desc, succdesc))
+repo.ui.status(msg)
+# Make clearrebased aware state[rev] is not a true successor
+self.skipped.add(rev)
+# Record rev as moved to its desired destination in self.state.
+ 

D2760: rebase: also restore "ui.allowemptycommit" value

2018-03-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG1bfe7e1d65fb: rebase: also restore 
ui.allowemptycommit value (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2760?vs=6872=6986

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

AFFECTED FILES
  hgext/rebase.py

CHANGE DETAILS

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -1054,9 +1054,9 @@
 
 destphase = max(ctx.phase(), phases.draft)
 overrides = {('phases', 'new-commit'): destphase}
+if keepbranch:
+overrides[('ui', 'allowemptycommit')] = True
 with repo.ui.configoverride(overrides, 'rebase'):
-if keepbranch:
-repo.ui.setconfig('ui', 'allowemptycommit', True)
 # Replicates the empty check in ``repo.commit``.
 if wctx.isempty() and not repo.ui.configbool('ui', 'allowemptycommit'):
 return None
@@ -1096,9 +1096,9 @@
 
 destphase = max(ctx.phase(), phases.draft)
 overrides = {('phases', 'new-commit'): destphase}
+if keepbranch:
+overrides[('ui', 'allowemptycommit')] = True
 with repo.ui.configoverride(overrides, 'rebase'):
-if keepbranch:
-repo.ui.setconfig('ui', 'allowemptycommit', True)
 # Commit might fail if unresolved files exist
 if date is None:
 date = ctx.date()



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


Re: [PATCH V2] forget: add --dry-run mode

2018-03-13 Thread Yuya Nishihara
On Mon, 12 Mar 2018 18:27:13 -0400, Matt Harbison wrote:
> On Sun, 11 Mar 2018 05:49:26 -0400, Sushil khanchi  
>  wrote:
> 
> > # HG changeset patch
> > # User Sushil khanchi 
> > # Date 1520665399 -19800
> > #  Sat Mar 10 12:33:19 2018 +0530
> > # Node ID a1be8989c0158abc69ebd97ca8a0cc7dc3801be9
> > # Parent  4c71a26a4009d88590c9ae3d64a5912fd556d82e
> > forget: add --dry-run mode
> >
> > diff -r 4c71a26a4009 -r a1be8989c015 mercurial/cmdutil.py
> > --- a/mercurial/cmdutil.py  Sun Mar 04 21:16:36 2018 -0500
> > +++ b/mercurial/cmdutil.py  Sat Mar 10 12:33:19 2018 +0530
> > @@ -1996,7 +1996,7 @@
> >  for subpath in ctx.substate:
> >  ctx.sub(subpath).addwebdirpath(serverpath, webconf)
> > -def forget(ui, repo, match, prefix, explicitonly):
> > +def forget(ui, repo, match, prefix, explicitonly, **opts):
> >  join = lambda f: os.path.join(prefix, f)
> >  bad = []
> >  badfn = lambda x, y: bad.append(x) or match.bad(x, y)
> > @@ -2039,9 +2039,10 @@
> >  if ui.verbose or not match.exact(f):
> >  ui.status(_('removing %s\n') % match.rel(f))
> > -rejected = wctx.forget(forget, prefix)
> 
> Shouldn't --dry-run be passed into wctx.forget() too?  Then the warning  
> about bad paths there will be emitted, and you won't have to  
> conditionalize the following lines here.  That in turn won't affect the  
> exit code.

I slightly prefer not to pass --dry-run deep into the context layer
because it's a command-line business. Just my two cents.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 3 of 3] lfs: debug print HTTP headers and JSON payload received from the server

2018-03-13 Thread Yuya Nishihara
On Tue, 13 Mar 2018 00:00:08 -0400, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison 
> # Date 1520910527 14400
> #  Mon Mar 12 23:08:47 2018 -0400
> # Node ID d0b66408b224022fd96cb347ff3439e807812b21
> # Parent  f28c282005085edb77f64612be503a7cd43ab994
> lfs: debug print HTTP headers and JSON payload received from the server

Seems fine, queued, thanks.

> +if self.ui.debugflag:
> +self.ui.debug('Status: %d\n' % rsp.status)
> +# lfs-test-server and hg serve return headers in different order
> +self.ui.debug('%s\n'
> +  % '\n'.join(sorted(str(rsp.info()).splitlines(
> +
> +if 'objects' in response:
> +response['objects'] = sorted(response['objects'],
> + key=lambda p: p['oid'])
> +self.ui.debug('%s\n'
> +  % json.dumps(response, indent=2, sort_keys=True))

We'll need some hack for py3 because json is unicode.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] xdiff: fix a hard crash on Windows

2018-03-13 Thread Yuya Nishihara
On Mon, 12 Mar 2018 18:55:26 -0700, Jun Wu wrote:
> Looks good. Thanks for fixing this!
> 
> Excerpts from Matt Harbison's message of 2018-03-12 21:53:12 -0400:
> > # HG changeset patch
> > # User Matt Harbison 
> > # Date 1520905818 14400
> > #  Mon Mar 12 21:50:18 2018 -0400
> > # Node ID 60bb2f7dd9ba313f96374470e8419bf1a20454a1
> > # Parent  aed445748c7885482cd90e56e81f57a13d4ac95c
> > xdiff: fix a hard crash on Windows

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


D2834: wireproto: support /api/* URL space for exposing APIs

2018-03-13 Thread mharbison72 (Matt Harbison)
mharbison72 added a comment.


  Will this cause conflicts with `hg serve -S` or hgwebdir with subrepo/virtual 
paths that start with 'api'?  (This was the reason I used the LFS URI starting 
with '.hg/', knowing that isn't committable.)

REPOSITORY
  rHG Mercurial

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

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


[PATCH 3 of 4] annotate: do not construct attr.s object per line while computing history

2018-03-13 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1520855110 -32400
#  Mon Mar 12 20:45:10 2018 +0900
# Node ID 1ce0d903cfa6e8db0112f86cc346751651db1f80
# Parent  95af54712a25c298d5ee63c385f3d498250c1624
annotate: do not construct attr.s object per line while computing history

Unfortunately, it's way slower to construct an annotateline() object than
creating a plain tuple or a list. This patch changes the internal data
structure from row-based to columnar, so the decorate() function can be
instant.

  (original)
  $ hg annot mercurial/commands.py --time > /dev/null
  time: real 11.470 secs (user 11.400+0.000 sys 0.070+0.000)
  $ hg annot mercurial/commands.py --time --line-number > /dev/null
  time: real 39.590 secs (user 39.500+0.000 sys 0.080+0.000)

  (this patch)
  $ hg annot mercurial/commands.py --time > /dev/null
  time: real 11.780 secs (user 11.710+0.000 sys 0.070+0.000)
  $ hg annot mercurial/commands.py --time --line-number > /dev/null
  time: real 12.240 secs (user 12.170+0.000 sys 0.090+0.000)

diff --git a/mercurial/dagop.py b/mercurial/dagop.py
--- a/mercurial/dagop.py
+++ b/mercurial/dagop.py
@@ -365,10 +365,19 @@ def blockdescendants(fctx, fromline, tol
 @attr.s(slots=True, frozen=True)
 class annotateline(object):
 fctx = attr.ib()
-lineno = attr.ib(default=False)
+lineno = attr.ib()
 # Whether this annotation was the result of a skip-annotate.
 skip = attr.ib(default=False)
 
+@attr.s(slots=True, frozen=True)
+class _annotatedfile(object):
+# list indexed by lineno - 1
+fctxs = attr.ib()
+linenos = attr.ib()
+skips = attr.ib()
+# full file content
+text = attr.ib()
+
 def _countlines(text):
 if text.endswith("\n"):
 return text.count("\n")
@@ -385,7 +394,7 @@ def _annotatepair(parents, childfctx, ch
 
 See test-annotate.py for unit tests.
 '''
-pblocks = [(parent, mdiff.allblocks(parent[1], child[1], opts=diffopts))
+pblocks = [(parent, mdiff.allblocks(parent.text, child.text, 
opts=diffopts))
for parent in parents]
 
 if skipchild:
@@ -398,7 +407,9 @@ def _annotatepair(parents, childfctx, ch
 # Changed blocks ('!') or blocks made only of blank lines ('~')
 # belong to the child.
 if t == '=':
-child[0][b1:b2] = parent[0][a1:a2]
+child.fctxs[b1:b2] = parent.fctxs[a1:a2]
+child.linenos[b1:b2] = parent.linenos[a1:a2]
+child.skips[b1:b2] = parent.skips[a1:a2]
 
 if skipchild:
 # Now try and match up anything that couldn't be matched,
@@ -419,9 +430,11 @@ def _annotatepair(parents, childfctx, ch
 for (a1, a2, b1, b2), _t in blocks:
 if a2 - a1 >= b2 - b1:
 for bk in xrange(b1, b2):
-if child[0][bk].fctx == childfctx:
+if child.fctxs[bk] == childfctx:
 ak = min(a1 + (bk - b1), a2 - 1)
-child[0][bk] = attr.evolve(parent[0][ak], 
skip=True)
+child.fctxs[bk] = parent.fctxs[ak]
+child.linenos[bk] = parent.linenos[ak]
+child.skips[bk] = True
 else:
 remaining[idx][1].append((a1, a2, b1, b2))
 
@@ -430,9 +443,11 @@ def _annotatepair(parents, childfctx, ch
 for parent, blocks in remaining:
 for a1, a2, b1, b2 in blocks:
 for bk in xrange(b1, b2):
-if child[0][bk].fctx == childfctx:
+if child.fctxs[bk] == childfctx:
 ak = min(a1 + (bk - b1), a2 - 1)
-child[0][bk] = attr.evolve(parent[0][ak], skip=True)
+child.fctxs[bk] = parent.fctxs[ak]
+child.linenos[bk] = parent.linenos[ak]
+child.skips[bk] = True
 return child
 
 def annotate(base, parents, linenumber=False, skiprevs=None, diffopts=None):
@@ -443,11 +458,13 @@ def annotate(base, parents, linenumber=F
 
 if linenumber:
 def decorate(text, fctx):
-return ([annotateline(fctx=fctx, lineno=i)
- for i in xrange(1, _countlines(text) + 1)], text)
+n = _countlines(text)
+linenos = pycompat.rangelist(1, n + 1)
+return _annotatedfile([fctx] * n, linenos, [False] * n, text)
 else:
 def decorate(text, fctx):
-return ([annotateline(fctx=fctx)] * _countlines(text), text)
+n = _countlines(text)
+return _annotatedfile([fctx] * n, [False] * n, [False] * n, text)
 
 # This algorithm would prefer to be recursive, but Python is a
 # bit recursion-hostile. Instead we do an iterative
@@ -501,8 +518,10 @@ def annotate(base, parents, linenumber=F
 hist[f] = curr
 del pcache[f]
 
-lineattrs, text = hist[base]
-return 

[PATCH 1 of 4] pycompat: name maplist() and ziplist() for better traceback message

2018-03-13 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1520943734 -32400
#  Tue Mar 13 21:22:14 2018 +0900
# Node ID aa35c6d7caef9ef9f48d0c9c831f9492c1421c45
# Parent  6aeb076b1321c540db6419fc48c8a3a552fb596b
pycompat: name maplist() and ziplist() for better traceback message

diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
--- a/mercurial/pycompat.py
+++ b/mercurial/pycompat.py
@@ -65,8 +65,13 @@ if ispy3:
 if sysexecutable:
 sysexecutable = os.fsencode(sysexecutable)
 stringio = io.BytesIO
-maplist = lambda *args: list(map(*args))
-ziplist = lambda *args: list(zip(*args))
+
+def maplist(*args):
+return list(map(*args))
+
+def ziplist(*args):
+return list(zip(*args))
+
 rawinput = input
 getargspec = inspect.getfullargspec
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 4] annotate: correct parameter name of decorate() function

2018-03-13 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1520854628 -32400
#  Mon Mar 12 20:37:08 2018 +0900
# Node ID 95af54712a25c298d5ee63c385f3d498250c1624
# Parent  aa35c6d7caef9ef9f48d0c9c831f9492c1421c45
annotate: correct parameter name of decorate() function

diff --git a/mercurial/dagop.py b/mercurial/dagop.py
--- a/mercurial/dagop.py
+++ b/mercurial/dagop.py
@@ -442,12 +442,12 @@ def annotate(base, parents, linenumber=F
 """
 
 if linenumber:
-def decorate(text, rev):
-return ([annotateline(fctx=rev, lineno=i)
+def decorate(text, fctx):
+return ([annotateline(fctx=fctx, lineno=i)
  for i in xrange(1, _countlines(text) + 1)], text)
 else:
-def decorate(text, rev):
-return ([annotateline(fctx=rev)] * _countlines(text), text)
+def decorate(text, fctx):
+return ([annotateline(fctx=fctx)] * _countlines(text), text)
 
 # This algorithm would prefer to be recursive, but Python is a
 # bit recursion-hostile. Instead we do an iterative
diff --git a/tests/test-annotate.py b/tests/test-annotate.py
--- a/tests/test-annotate.py
+++ b/tests/test-annotate.py
@@ -25,8 +25,8 @@ class AnnotateTests(unittest.TestCase):
 childdata = b'a\nb2\nc\nc2\nd\n'
 diffopts = mdiff.diffopts()
 
-def decorate(text, rev):
-return ([annotateline(fctx=rev, lineno=i)
+def decorate(text, fctx):
+return ([annotateline(fctx=fctx, lineno=i)
  for i in range(1, text.count(b'\n') + 1)],
 text)
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 4] annotate: drop linenumber flag from fctx.annotate() (API)

2018-03-13 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1520947086 -32400
#  Tue Mar 13 22:18:06 2018 +0900
# Node ID 854d59569873317764fb7ff68b7f0051585caed6
# Parent  1ce0d903cfa6e8db0112f86cc346751651db1f80
annotate: drop linenumber flag from fctx.annotate() (API)

Now linenumber=True is fast enough to be enabled by default.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -387,8 +387,8 @@ def annotate(ui, repo, *pats, **opts):
 continue
 
 fm = rootfm.nested('lines')
-lines = fctx.annotate(follow=follow, linenumber=linenumber,
-  skiprevs=skiprevs, diffopts=diffopts)
+lines = fctx.annotate(follow=follow, skiprevs=skiprevs,
+  diffopts=diffopts)
 if not lines:
 fm.end()
 continue
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -967,14 +967,13 @@ class basefilectx(object):
 return p[1]
 return filectx(self._repo, self._path, fileid=-1, 
filelog=self._filelog)
 
-def annotate(self, follow=False, linenumber=False, skiprevs=None,
- diffopts=None):
-'''returns a list of tuples of ((ctx, number), line) for each line
-in the file, where ctx is the filectx of the node where
-that line was last changed; if linenumber parameter is true, number is
-the line number at the first appearance in the managed file, otherwise,
-number has a fixed value of False.
-'''
+def annotate(self, follow=False, skiprevs=None, diffopts=None):
+"""Returns a list of tuples of (attr, line) for each line in the file
+
+- attr.fctx is the filectx of the node where that line was last changed
+- attr.lineno is the line number at the first appearance in the managed
+  file
+"""
 getlog = util.lrucachefunc(lambda x: self._repo.file(x))
 
 def parents(f):
@@ -1010,8 +1009,8 @@ class basefilectx(object):
 ac = cl.ancestors([base.rev()], inclusive=True)
 base._ancestrycontext = ac
 
-return dagop.annotate(base, parents, linenumber=linenumber,
-  skiprevs=skiprevs, diffopts=diffopts)
+return dagop.annotate(base, parents, skiprevs=skiprevs,
+  diffopts=diffopts)
 
 def ancestors(self, followfirst=False):
 visit = {}
diff --git a/mercurial/dagop.py b/mercurial/dagop.py
--- a/mercurial/dagop.py
+++ b/mercurial/dagop.py
@@ -383,6 +383,11 @@ def _countlines(text):
 return text.count("\n")
 return text.count("\n") + int(bool(text))
 
+def _decoratelines(text, fctx):
+n = _countlines(text)
+linenos = pycompat.rangelist(1, n + 1)
+return _annotatedfile([fctx] * n, linenos, [False] * n, text)
+
 def _annotatepair(parents, childfctx, child, skipchild, diffopts):
 r'''
 Given parent and child fctxes and annotate data for parents, for all lines
@@ -450,22 +455,12 @@ def _annotatepair(parents, childfctx, ch
 child.skips[bk] = True
 return child
 
-def annotate(base, parents, linenumber=False, skiprevs=None, diffopts=None):
+def annotate(base, parents, skiprevs=None, diffopts=None):
 """Core algorithm for filectx.annotate()
 
 `parents(fctx)` is a function returning a list of parent filectxs.
 """
 
-if linenumber:
-def decorate(text, fctx):
-n = _countlines(text)
-linenos = pycompat.rangelist(1, n + 1)
-return _annotatedfile([fctx] * n, linenos, [False] * n, text)
-else:
-def decorate(text, fctx):
-n = _countlines(text)
-return _annotatedfile([fctx] * n, [False] * n, [False] * n, text)
-
 # This algorithm would prefer to be recursive, but Python is a
 # bit recursion-hostile. Instead we do an iterative
 # depth-first search.
@@ -502,7 +497,7 @@ def annotate(base, parents, linenumber=F
 visit.append(p)
 if ready:
 visit.pop()
-curr = decorate(f.data(), f)
+curr = _decoratelines(f.data(), f)
 skipchild = False
 if skiprevs is not None:
 skipchild = f._changeid in skiprevs
diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -186,7 +186,7 @@ def difffeatureopts(req, ui, section):
 
 def annotate(req, fctx, ui):
 diffopts = difffeatureopts(req, ui, 'annotate')
-return fctx.annotate(follow=True, linenumber=True, diffopts=diffopts)
+return fctx.annotate(follow=True, diffopts=diffopts)
 
 def parents(ctx, hide=None):
 if isinstance(ctx, context.basefilectx):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org

Re: [PATCH V4] forget: add --dry-run mode

2018-03-13 Thread Anton Shestakov
On Tue, 13 Mar 2018 15:43:02 +0800
Anton Shestakov  wrote:

> > +rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False, 
> > dryrun=dryrun)[0]  
> 
> This line is too long, don't forget to also run test-check-commit.t.

I saw this already fixed, but I'd like to get this right.

test-check-code.t is the test that would detect lines of code being too
long (not *-commit.t), but running all of the test-check-*.t before
sending patches is a good idea. Small issues can be fixed when
reviewers queue patches, but not all of check-code.py (as an example)
is style checks; some of the rules are important for compatibility
(Python 2 vs 3, and running test suite on different OSes), and they are
put there because they can be tricky to spot during manual review.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Bugzilla stats email

2018-03-13 Thread Feld Boris

Hello,

I've activated the weekly bugzilla stats email on a weekly basics for 
the mercurial-devel mailing-list. The mail comes from 
octo...@octobus.net with the subject "bugzilla weekly report". It's for 
the moment a text version of https://hgbzstats.octobus.net/.


I presented it at the sprint and the feedback were good. I've got two 
improvements requests that are logged here: 
https://bitbucket.org/octobus/hgbzstats/issues?status=new=open, 
don't hesitate to create new issues and vote on most wanted ones, we 
will work on them as soon as possible.


Cheers,

Boris

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


bugzilla weekly report (2018-03-13)

2018-03-13 Thread Octobot
Bug activity report, between 2018-03-06 and 2018-03-13
 * urgent+: 4 bugs (1 added)
 * unconfirmed: 18 bugs (5 added)
 * new: 7 bugs
 * closed: 9 bugs
 * need example: 0 bugs
 * new details: 0 bugs
 * active: 31 bugs
 * long inactive: 5 bugs

urgent+
---

Open of urgent or critical bugs.
Found 4 bugs with our query (1 added).

 id  summary
--- 
(#5165) can't push long bookmark names with bundle2 
(#5748) Unknown exception during commit 
(#5801) pure-python manifest code produces corrupt unsorted manifests   
(#5811) fsmonitor returns bogus stat tuples, breaking after cleanup in f

unconfirmed
---

Bugs with status 'unconfirmed'.
Found 18 bugs with our query (5 added).

 id  summary
--- 
(#5592) Obsolete markers for root changes are not exchanged 
(#5747) Rebase should detect patch that has already been applied.   
(#5753) Support for inline clone bundles when cloning via ssh   
(#5766) pull --rebase aborts if working dir not clean even if nothing to
(#5772) hg fold doesn't move bookmarks  
(#5773) evolve extension should specify progress units  
(#5774) Very slow performance when running commands and fsmonitor instal
(#5776) Disabled path conflict checking for unknown files behavior is di
(#5785) hg up -C  should always fail. 
(#5792) include bookmarks in bundle2 file generation
(#5807) Convert throws "ValueError: I/O operation on closed file"   
(#5808) `hg next` and `hg prev` do not respect commands.update.check
(#5810) warning about overridden commands when both evolve and serveronl
(#5813) pull --rebase via hgnested's npull doesn't rebase correctly 
(#5814) 4.5.2: test hang on NetBSD  
(#5815) ui.debug=True in a config file may prevent extensions from loadi
(#5816) mq doesn't correctly block hg commit --amend on mq-managed commi
(#5817) fold should respect experimental.evolve.allowdivergence 

new
---

Bugs opened during the reporting period.
Found 7 bugs with our query.

 id  summary
--- 
(#5811) fsmonitor returns bogus stat tuples, breaking after cleanup in f
(#5812) paper theme uses inline javascript, making web.csp far less effe
(#5813) pull --rebase via hgnested's npull doesn't rebase correctly 
(#5814) 4.5.2: test hang on NetBSD  
(#5815) ui.debug=True in a config file may prevent extensions from loadi
(#5816) mq doesn't correctly block hg commit --amend on mq-managed commi
(#5817) fold should respect experimental.evolve.allowdivergence 

closed
--

Bugs closed during the reporting period.
Found 9 bugs with our query.

 id  summary
--- 
(#2137) API: after adding changesets, repo.lookup() does not recognized 
(#4074) Huge performance issue committing update to large file  
(#5654) Help text for clone -r option is unclear
(#5694) "hg evolve" does nothing on unstable parent, even though "hg evo
(#5708) topic-ext: "hg previous" on an obsoleted revision fails unintent
(#5779) The files command crashes with "-T ''{files}'"  
(#5793) Fix for #5675 made it impossible to share repositories containin
(#5797) hg config: only 1 config option allowed 
(#5798) annotate output is broken if the file contains multiple CR in a 

need example


Bugs with 'need_example' status and at least a new comment.
Found 0 bugs with our query.

 id  summary
--- 

new details
---

Bugs moved out of 'need_example' during the reporting period.
Found 0 bugs with our query.

 id  summary
--- 

active
--

All bugs with any activity during the reporting period.
Found 31 bugs with our query.

 id  summary
--- 
(#2137) API: after adding changesets, repo.lookup() does not recognized 
(#3885) `hg grep --all -r REV` reports irrelevant diffs 
(#4074) Huge performance issue committing update to large file  
(#4318) unshelve refuses to apply on modified MQ 

[PATCH V4] forget: add --dry-run mode

2018-03-13 Thread Sushil khanchi
# HG changeset patch
# User Sushil khanchi 
# Date 1520665399 -19800
#  Sat Mar 10 12:33:19 2018 +0530
# Node ID 349b51e3bb04862ff7e516f57509ccd974e1b6a2
# Parent  4c71a26a4009d88590c9ae3d64a5912fd556d82e
forget: add --dry-run mode

diff -r 4c71a26a4009 -r 349b51e3bb04 mercurial/cmdutil.py
--- a/mercurial/cmdutil.py  Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/cmdutil.py  Sat Mar 10 12:33:19 2018 +0530
@@ -1996,7 +1996,7 @@
 for subpath in ctx.substate:
 ctx.sub(subpath).addwebdirpath(serverpath, webconf)
 
-def forget(ui, repo, match, prefix, explicitonly):
+def forget(ui, repo, match, prefix, explicitonly, dryrun):
 join = lambda f: os.path.join(prefix, f)
 bad = []
 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
@@ -2012,7 +2012,7 @@
 sub = wctx.sub(subpath)
 try:
 submatch = matchmod.subdirmatcher(subpath, match)
-subbad, subforgot = sub.forget(submatch, prefix)
+subbad, subforgot = sub.forget(submatch, prefix, dryrun=dryrun)
 bad.extend([subpath + '/' + f for f in subbad])
 forgot.extend([subpath + '/' + f for f in subforgot])
 except error.LookupError:
@@ -2039,7 +2039,7 @@
 if ui.verbose or not match.exact(f):
 ui.status(_('removing %s\n') % match.rel(f))
 
-rejected = wctx.forget(forget, prefix)
+rejected = wctx.forget(forget, prefix, dryrun=dryrun)
 bad.extend(f for f in rejected if f in match.files())
 forgot.extend(f for f in forget if f not in rejected)
 return bad, forgot
diff -r 4c71a26a4009 -r 349b51e3bb04 mercurial/commands.py
--- a/mercurial/commands.py Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/commands.py Sat Mar 10 12:33:19 2018 +0530
@@ -2036,7 +2036,10 @@
 with ui.formatter('files', opts) as fm:
 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
 
-@command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
+@command(
+'^forget',
+walkopts + dryrunopts,
+_('[OPTION]... FILE...'), inferrepo=True)
 def forget(ui, repo, *pats, **opts):
 """forget the specified files on the next commit
 
@@ -2071,7 +2074,9 @@
 raise error.Abort(_('no files specified'))
 
 m = scmutil.match(repo[None], pats, opts)
-rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
+dryrun = opts.get(r'dry_run')
+rejected = cmdutil.forget(ui, repo, m, prefix="",
+  explicitonly=False, dryrun=dryrun)[0]
 return rejected and 1 or 0
 
 @command(
diff -r 4c71a26a4009 -r 349b51e3bb04 mercurial/context.py
--- a/mercurial/context.py  Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/context.py  Sat Mar 10 12:33:19 2018 +0530
@@ -1564,7 +1564,7 @@
 ds.add(f)
 return rejected
 
-def forget(self, files, prefix=""):
+def forget(self, files, prefix="", dryrun=False):
 with self._repo.wlock():
 ds = self._repo.dirstate
 uipath = lambda f: ds.pathto(pathutil.join(prefix, f))
@@ -1573,10 +1573,11 @@
 if f not in self._repo.dirstate:
 self._repo.ui.warn(_("%s not tracked!\n") % uipath(f))
 rejected.append(f)
-elif self._repo.dirstate[f] != 'a':
-self._repo.dirstate.remove(f)
-else:
-self._repo.dirstate.drop(f)
+elif not dryrun:
+if self._repo.dirstate[f] != 'a':
+self._repo.dirstate.remove(f)
+else:
+self._repo.dirstate.drop(f)
 return rejected
 
 def undelete(self, list):
diff -r 4c71a26a4009 -r 349b51e3bb04 mercurial/subrepo.py
--- a/mercurial/subrepo.py  Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/subrepo.py  Sat Mar 10 12:33:19 2018 +0530
@@ -811,9 +811,10 @@
 return ctx.walk(match)
 
 @annotatesubrepoerror
-def forget(self, match, prefix):
+def forget(self, match, prefix, dryrun):
 return cmdutil.forget(self.ui, self._repo, match,
-  self.wvfs.reljoin(prefix, self._path), True)
+  self.wvfs.reljoin(prefix, self._path),
+  True, dryrun=dryrun)
 
 @annotatesubrepoerror
 def removefiles(self, matcher, prefix, after, force, subrepos, warnings):
diff -r 4c71a26a4009 -r 349b51e3bb04 tests/test-commit.t
--- a/tests/test-commit.t   Sun Mar 04 21:16:36 2018 -0500
+++ b/tests/test-commit.t   Sat Mar 10 12:33:19 2018 +0530
@@ -832,3 +832,18 @@
 
   $ cd ..
 
+test --dry-run mode in forget
+
+  $ hg init testdir_forget
+  $ cd testdir_forget
+  $ echo foo > foo
+  $ hg add foo
+  $ hg commit -m "foo"
+  $ hg forget foo --dry-run -v
+  removing foo
+  $ hg diff
+  $ hg forget not_exist -n
+  not_exist: $ENOENT$
+  [1]
+
+  $ cd ..

Re: [PATCH V4] forget: add --dry-run mode

2018-03-13 Thread Anton Shestakov
On Tue, 13 Mar 2018 12:17:41 +0530
Sushil khanchi  wrote:

> # HG changeset patch
> # User Sushil khanchi 
> # Date 1520665399 -19800
> #  Sat Mar 10 12:33:19 2018 +0530
> # Node ID 4134d1f103d8e72e80920cd89cf3d3f576e6a2b5
> # Parent  4c71a26a4009d88590c9ae3d64a5912fd556d82e
> forget: add --dry-run mode
> 
> diff -r 4c71a26a4009 -r 4134d1f103d8 mercurial/cmdutil.py
> --- a/mercurial/cmdutil.pySun Mar 04 21:16:36 2018 -0500
> +++ b/mercurial/cmdutil.pySat Mar 10 12:33:19 2018 +0530
> @@ -1996,7 +1996,7 @@
>  for subpath in ctx.substate:
>  ctx.sub(subpath).addwebdirpath(serverpath, webconf)
>  
> -def forget(ui, repo, match, prefix, explicitonly):
> +def forget(ui, repo, match, prefix, explicitonly, dryrun):
>  join = lambda f: os.path.join(prefix, f)
>  bad = []
>  badfn = lambda x, y: bad.append(x) or match.bad(x, y)
> @@ -2012,7 +2012,7 @@
>  sub = wctx.sub(subpath)
>  try:
>  submatch = matchmod.subdirmatcher(subpath, match)
> -subbad, subforgot = sub.forget(submatch, prefix)
> +subbad, subforgot = sub.forget(submatch, prefix, dryrun=dryrun)
>  bad.extend([subpath + '/' + f for f in subbad])
>  forgot.extend([subpath + '/' + f for f in subforgot])
>  except error.LookupError:
> @@ -2039,7 +2039,7 @@
>  if ui.verbose or not match.exact(f):
>  ui.status(_('removing %s\n') % match.rel(f))
>  
> -rejected = wctx.forget(forget, prefix)
> +rejected = wctx.forget(forget, prefix, dryrun=dryrun)
>  bad.extend(f for f in rejected if f in match.files())
>  forgot.extend(f for f in forget if f not in rejected)
>  return bad, forgot
> diff -r 4c71a26a4009 -r 4134d1f103d8 mercurial/commands.py
> --- a/mercurial/commands.py   Sun Mar 04 21:16:36 2018 -0500
> +++ b/mercurial/commands.py   Sat Mar 10 12:33:19 2018 +0530
> @@ -2036,7 +2036,10 @@
>  with ui.formatter('files', opts) as fm:
>  return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
>  
> -@command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
> +@command(
> +'^forget',
> +walkopts + dryrunopts,
> +_('[OPTION]... FILE...'), inferrepo=True)
>  def forget(ui, repo, *pats, **opts):
>  """forget the specified files on the next commit
>  
> @@ -2071,7 +2074,8 @@
>  raise error.Abort(_('no files specified'))
>  
>  m = scmutil.match(repo[None], pats, opts)
> -rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
> +dryrun = opts.get(r'dry_run')
> +rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False, 
> dryrun=dryrun)[0]

This line is too long, don't forget to also run test-check-commit.t.

>  return rejected and 1 or 0
>  
>  @command(
> diff -r 4c71a26a4009 -r 4134d1f103d8 mercurial/context.py
> --- a/mercurial/context.pySun Mar 04 21:16:36 2018 -0500
> +++ b/mercurial/context.pySat Mar 10 12:33:19 2018 +0530
> @@ -1564,7 +1564,7 @@
>  ds.add(f)
>  return rejected
>  
> -def forget(self, files, prefix=""):
> +def forget(self, files, prefix="", dryrun=False):
>  with self._repo.wlock():
>  ds = self._repo.dirstate
>  uipath = lambda f: ds.pathto(pathutil.join(prefix, f))
> @@ -1573,10 +1573,11 @@
>  if f not in self._repo.dirstate:
>  self._repo.ui.warn(_("%s not tracked!\n") % uipath(f))
>  rejected.append(f)
> -elif self._repo.dirstate[f] != 'a':
> -self._repo.dirstate.remove(f)
> -else:
> -self._repo.dirstate.drop(f)
> +elif not dryrun:
> +if self._repo.dirstate[f] != 'a':
> +self._repo.dirstate.remove(f)
> +else:
> +self._repo.dirstate.drop(f)
>  return rejected
>  
>  def undelete(self, list):
> diff -r 4c71a26a4009 -r 4134d1f103d8 mercurial/subrepo.py
> --- a/mercurial/subrepo.pySun Mar 04 21:16:36 2018 -0500
> +++ b/mercurial/subrepo.pySat Mar 10 12:33:19 2018 +0530
> @@ -811,9 +811,10 @@
>  return ctx.walk(match)
>  
>  @annotatesubrepoerror
> -def forget(self, match, prefix):
> +def forget(self, match, prefix, dryrun):
>  return cmdutil.forget(self.ui, self._repo, match,
> -  self.wvfs.reljoin(prefix, self._path), True)
> +  self.wvfs.reljoin(prefix, self._path),
> +  True, dryrun=dryrun)
>  
>  @annotatesubrepoerror
>  def removefiles(self, matcher, prefix, after, force, subrepos, warnings):
> diff -r 4c71a26a4009 -r 4134d1f103d8 tests/test-commit.t
> --- a/tests/test-commit.t Sun Mar 04 21:16:36 2018 -0500
> +++ b/tests/test-commit.t Sat Mar 10 12:33:19 2018 +0530

mercurial@36844: new changeset (1 on stable)

2018-03-13 Thread Mercurial Commits
New changeset (1 on stable) in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/eeb87b24aea7
changeset:   36844:eeb87b24aea7
branch:  stable
tag: tip
parent:  36759:9639c433be54
user:Yuya Nishihara 
date:Sun Mar 11 20:10:38 2018 +0900
summary: amend: abort if unresolved merge conflicts found (issue5805)

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


[PATCH evolve-ext V3] obsdiscovery: include units in ui.progress() calls (issue5773)

2018-03-13 Thread Anton Shestakov
# HG changeset patch
# User Anton Shestakov 
# Date 1519388837 -28800
#  Fri Feb 23 20:27:17 2018 +0800
# Node ID f30a4131c6f28f355af2c1259632399e05dfca07
# Parent  1f0c88a9dd1cdf11d9eb8db48cc5e6e70022230b
obsdiscovery: include units in ui.progress() calls (issue5773)

diff --git a/hgext3rd/evolve/obsdiscovery.py b/hgext3rd/evolve/obsdiscovery.py
--- a/hgext3rd/evolve/obsdiscovery.py
+++ b/hgext3rd/evolve/obsdiscovery.py
@@ -95,7 +95,8 @@ def findcommonobsmarkers(ui, local, remo
 common = set()
 undecided = set(probeset)
 totalnb = len(undecided)
-ui.progress(_("comparing with other"), 0, total=totalnb)
+ui.progress(_("comparing with other"), 0, total=totalnb,
+unit=_("changesets"))
 _takefullsample = setdiscovery._takefullsample
 if remote.capable('_evoext_obshash_1'):
 getremotehash = remote.evoext_obshash1
@@ -114,7 +115,7 @@ def findcommonobsmarkers(ui, local, remo
 
 roundtrips += 1
 ui.progress(_("comparing with other"), totalnb - len(undecided),
-total=totalnb)
+total=totalnb, unit=_("changesets"))
 ui.debug("query %i; still undecided: %i, sample size is: %i\n"
  % (roundtrips, len(undecided), len(sample)))
 # indices between sample and externalized version must match
@@ -175,7 +176,8 @@ def findmissingrange(ui, local, remote, 
 
 local.obsstore.rangeobshashcache.update(local)
 querycount = 0
-ui.progress(_("comparing obsmarker with other"), querycount)
+ui.progress(_("comparing obsmarker with other"), querycount,
+unit=_("queries"))
 overflow = []
 while sample or overflow:
 if overflow:
@@ -230,7 +232,8 @@ def findmissingrange(ui, local, remote, 
 addentry(new)
 assert nbsample == nbreplies
 querycount += 1
-ui.progress(_("comparing obsmarker with other"), querycount)
+ui.progress(_("comparing obsmarker with other"), querycount,
+unit=_("queries"))
 ui.progress(_("comparing obsmarker with other"), None)
 local.obsstore.rangeobshashcache.save(local)
 duration = timer() - starttime
@@ -771,7 +774,8 @@ def _obsrelsethashtree(repo, encodeonema
 cache = []
 unfi = repo.unfiltered()
 markercache = {}
-repo.ui.progress(_("preparing locally"), 0, total=len(unfi))
+repo.ui.progress(_("preparing locally"), 0, total=len(unfi),
+ unit=_("changesets"))
 for i in unfi:
 ctx = unfi[i]
 entry = 0
@@ -801,7 +805,8 @@ def _obsrelsethashtree(repo, encodeonema
 cache.append((ctx.node(), sha.digest()))
 else:
 cache.append((ctx.node(), node.nullid))
-repo.ui.progress(_("preparing locally"), i, total=len(unfi))
+repo.ui.progress(_("preparing locally"), i, total=len(unfi),
+ unit=_("changesets"))
 repo.ui.progress(_("preparing locally"), None)
 return cache
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH STABLE] hgweb: garbage collect on every request

2018-03-13 Thread Gregory Szorc


> On Mar 12, 2018, at 23:18, Anton Shestakov  wrote:
> 
> On Mon, 12 Mar 2018 13:17:21 -0700
> Gregory Szorc  wrote:
> 
>> # HG changeset patch
>> # User Gregory Szorc 
>> # Date 1520885700 25200
>> #  Mon Mar 12 13:15:00 2018 -0700
>> # Branch stable
>> # Node ID 46905416a5f47e9e46aa2db0e2e4f45e7414c979
>> # Parent  9639c433be54191b4136b48fe70fc8344d2b5db2
>> hgweb: garbage collect on every request
> 
> Queued, thanks.
> 
> Unfortunately, this patch doesn't help a lot when evolve extension is
> enabled: until I turned it off to test, hgweb consistently consumed
> 200MB more on every request (on hg-committed), despite gc.collect(). No
> idea why.

:(

My guess is evolve is storing a reference to a repo or some other large data 
structure in a module-level variable. Leaks like that are pretty easy to spot 
using a tool like guppy’s heap snapshots.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH V4] forget: add --dry-run mode

2018-03-13 Thread Sushil khanchi
# HG changeset patch
# User Sushil khanchi 
# Date 1520665399 -19800
#  Sat Mar 10 12:33:19 2018 +0530
# Node ID 4134d1f103d8e72e80920cd89cf3d3f576e6a2b5
# Parent  4c71a26a4009d88590c9ae3d64a5912fd556d82e
forget: add --dry-run mode

diff -r 4c71a26a4009 -r 4134d1f103d8 mercurial/cmdutil.py
--- a/mercurial/cmdutil.py  Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/cmdutil.py  Sat Mar 10 12:33:19 2018 +0530
@@ -1996,7 +1996,7 @@
 for subpath in ctx.substate:
 ctx.sub(subpath).addwebdirpath(serverpath, webconf)
 
-def forget(ui, repo, match, prefix, explicitonly):
+def forget(ui, repo, match, prefix, explicitonly, dryrun):
 join = lambda f: os.path.join(prefix, f)
 bad = []
 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
@@ -2012,7 +2012,7 @@
 sub = wctx.sub(subpath)
 try:
 submatch = matchmod.subdirmatcher(subpath, match)
-subbad, subforgot = sub.forget(submatch, prefix)
+subbad, subforgot = sub.forget(submatch, prefix, dryrun=dryrun)
 bad.extend([subpath + '/' + f for f in subbad])
 forgot.extend([subpath + '/' + f for f in subforgot])
 except error.LookupError:
@@ -2039,7 +2039,7 @@
 if ui.verbose or not match.exact(f):
 ui.status(_('removing %s\n') % match.rel(f))
 
-rejected = wctx.forget(forget, prefix)
+rejected = wctx.forget(forget, prefix, dryrun=dryrun)
 bad.extend(f for f in rejected if f in match.files())
 forgot.extend(f for f in forget if f not in rejected)
 return bad, forgot
diff -r 4c71a26a4009 -r 4134d1f103d8 mercurial/commands.py
--- a/mercurial/commands.py Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/commands.py Sat Mar 10 12:33:19 2018 +0530
@@ -2036,7 +2036,10 @@
 with ui.formatter('files', opts) as fm:
 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
 
-@command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
+@command(
+'^forget',
+walkopts + dryrunopts,
+_('[OPTION]... FILE...'), inferrepo=True)
 def forget(ui, repo, *pats, **opts):
 """forget the specified files on the next commit
 
@@ -2071,7 +2074,8 @@
 raise error.Abort(_('no files specified'))
 
 m = scmutil.match(repo[None], pats, opts)
-rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
+dryrun = opts.get(r'dry_run')
+rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False, 
dryrun=dryrun)[0]
 return rejected and 1 or 0
 
 @command(
diff -r 4c71a26a4009 -r 4134d1f103d8 mercurial/context.py
--- a/mercurial/context.py  Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/context.py  Sat Mar 10 12:33:19 2018 +0530
@@ -1564,7 +1564,7 @@
 ds.add(f)
 return rejected
 
-def forget(self, files, prefix=""):
+def forget(self, files, prefix="", dryrun=False):
 with self._repo.wlock():
 ds = self._repo.dirstate
 uipath = lambda f: ds.pathto(pathutil.join(prefix, f))
@@ -1573,10 +1573,11 @@
 if f not in self._repo.dirstate:
 self._repo.ui.warn(_("%s not tracked!\n") % uipath(f))
 rejected.append(f)
-elif self._repo.dirstate[f] != 'a':
-self._repo.dirstate.remove(f)
-else:
-self._repo.dirstate.drop(f)
+elif not dryrun:
+if self._repo.dirstate[f] != 'a':
+self._repo.dirstate.remove(f)
+else:
+self._repo.dirstate.drop(f)
 return rejected
 
 def undelete(self, list):
diff -r 4c71a26a4009 -r 4134d1f103d8 mercurial/subrepo.py
--- a/mercurial/subrepo.py  Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/subrepo.py  Sat Mar 10 12:33:19 2018 +0530
@@ -811,9 +811,10 @@
 return ctx.walk(match)
 
 @annotatesubrepoerror
-def forget(self, match, prefix):
+def forget(self, match, prefix, dryrun):
 return cmdutil.forget(self.ui, self._repo, match,
-  self.wvfs.reljoin(prefix, self._path), True)
+  self.wvfs.reljoin(prefix, self._path),
+  True, dryrun=dryrun)
 
 @annotatesubrepoerror
 def removefiles(self, matcher, prefix, after, force, subrepos, warnings):
diff -r 4c71a26a4009 -r 4134d1f103d8 tests/test-commit.t
--- a/tests/test-commit.t   Sun Mar 04 21:16:36 2018 -0500
+++ b/tests/test-commit.t   Sat Mar 10 12:33:19 2018 +0530
@@ -832,3 +832,15 @@
 
   $ cd ..
 
+# test --dry-run mode in $hg forget
+
+  $ hg init testdir_forget
+  $ cd testdir_forget
+  $ echo foo > foo
+  $ hg add foo
+  $ hg commit -m "foo"
+  $ hg forget foo --dry-run -v
+  removing foo
+  $ hg diff
+
+  $ cd ..
___
Mercurial-devel mailing list

[PATCH V3] forget: add --dry-run mode

2018-03-13 Thread Sushil khanchi
# HG changeset patch
# User Sushil khanchi 
# Date 1520665399 -19800
#  Sat Mar 10 12:33:19 2018 +0530
# Node ID 759f15ef30ea56f6cb190415e8eaa16dcd95c1a8
# Parent  4c71a26a4009d88590c9ae3d64a5912fd556d82e
forget: add --dry-run mode

diff -r 4c71a26a4009 -r 759f15ef30ea mercurial/cmdutil.py
--- a/mercurial/cmdutil.py  Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/cmdutil.py  Sat Mar 10 12:33:19 2018 +0530
@@ -1996,7 +1996,7 @@
 for subpath in ctx.substate:
 ctx.sub(subpath).addwebdirpath(serverpath, webconf)
 
-def forget(ui, repo, match, prefix, explicitonly):
+def forget(ui, repo, match, prefix, explicitonly, dryrun):
 join = lambda f: os.path.join(prefix, f)
 bad = []
 badfn = lambda x, y: bad.append(x) or match.bad(x, y)
@@ -2012,7 +2012,7 @@
 sub = wctx.sub(subpath)
 try:
 submatch = matchmod.subdirmatcher(subpath, match)
-subbad, subforgot = sub.forget(submatch, prefix)
+subbad, subforgot = sub.forget(submatch, prefix, dryrun=dryrun)
 bad.extend([subpath + '/' + f for f in subbad])
 forgot.extend([subpath + '/' + f for f in subforgot])
 except error.LookupError:
@@ -2039,7 +2039,7 @@
 if ui.verbose or not match.exact(f):
 ui.status(_('removing %s\n') % match.rel(f))
 
-rejected = wctx.forget(forget, prefix)
+rejected = wctx.forget(forget, prefix, dryrun=dryrun)
 bad.extend(f for f in rejected if f in match.files())
 forgot.extend(f for f in forget if f not in rejected)
 return bad, forgot
diff -r 4c71a26a4009 -r 759f15ef30ea mercurial/commands.py
--- a/mercurial/commands.py Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/commands.py Sat Mar 10 12:33:19 2018 +0530
@@ -2036,7 +2036,10 @@
 with ui.formatter('files', opts) as fm:
 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
 
-@command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
+@command(
+'^forget',
+walkopts + dryrunopts,
+_('[OPTION]... FILE...'), inferrepo=True)
 def forget(ui, repo, *pats, **opts):
 """forget the specified files on the next commit
 
@@ -2071,7 +2074,8 @@
 raise error.Abort(_('no files specified'))
 
 m = scmutil.match(repo[None], pats, opts)
-rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
+dryrun = opts.get(r'dry_run')
+rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False, 
dryrun=dryrun)[0]
 return rejected and 1 or 0
 
 @command(
diff -r 4c71a26a4009 -r 759f15ef30ea mercurial/context.py
--- a/mercurial/context.py  Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/context.py  Sat Mar 10 12:33:19 2018 +0530
@@ -1564,7 +1564,7 @@
 ds.add(f)
 return rejected
 
-def forget(self, files, prefix=""):
+def forget(self, files, prefix="", dryrun=False):
 with self._repo.wlock():
 ds = self._repo.dirstate
 uipath = lambda f: ds.pathto(pathutil.join(prefix, f))
@@ -1573,10 +1573,11 @@
 if f not in self._repo.dirstate:
 self._repo.ui.warn(_("%s not tracked!\n") % uipath(f))
 rejected.append(f)
-elif self._repo.dirstate[f] != 'a':
-self._repo.dirstate.remove(f)
-else:
-self._repo.dirstate.drop(f)
+elif not dryrun:
+if self._repo.dirstate[f] != 'a':
+self._repo.dirstate.remove(f)
+else:
+self._repo.dirstate.drop(f)
 return rejected
 
 def undelete(self, list):
diff -r 4c71a26a4009 -r 759f15ef30ea mercurial/subrepo.py
--- a/mercurial/subrepo.py  Sun Mar 04 21:16:36 2018 -0500
+++ b/mercurial/subrepo.py  Sat Mar 10 12:33:19 2018 +0530
@@ -811,9 +811,10 @@
 return ctx.walk(match)
 
 @annotatesubrepoerror
-def forget(self, match, prefix):
+def forget(self, match, prefix, dryrun):
 return cmdutil.forget(self.ui, self._repo, match,
-  self.wvfs.reljoin(prefix, self._path), True)
+  self.wvfs.reljoin(prefix, self._path),
+  True, dryrun=dryrun)
 
 @annotatesubrepoerror
 def removefiles(self, matcher, prefix, after, force, subrepos, warnings):
diff -r 4c71a26a4009 -r 759f15ef30ea tests/test-commit.t
--- a/tests/test-commit.t   Sun Mar 04 21:16:36 2018 -0500
+++ b/tests/test-commit.t   Sat Mar 10 12:33:19 2018 +0530
@@ -832,3 +832,13 @@
 
   $ cd ..
 
+# test --dry-run mode in $hg forget
+
+  $ hg init testdir_forget
+  $ cd testdir_forget
+  $ echo foo > foo
+  $ hg add foo
+  $ hg commit -m "foo"
+  $ hg forget foo --dry-run -v
+  removing foo
+  $ hg diff
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org

Re: [PATCH STABLE] hgweb: garbage collect on every request

2018-03-13 Thread Anton Shestakov
On Mon, 12 Mar 2018 13:17:21 -0700
Gregory Szorc  wrote:

> # HG changeset patch
> # User Gregory Szorc 
> # Date 1520885700 25200
> #  Mon Mar 12 13:15:00 2018 -0700
> # Branch stable
> # Node ID 46905416a5f47e9e46aa2db0e2e4f45e7414c979
> # Parent  9639c433be54191b4136b48fe70fc8344d2b5db2
> hgweb: garbage collect on every request

Queued, thanks.

Unfortunately, this patch doesn't help a lot when evolve extension is
enabled: until I turned it off to test, hgweb consistently consumed
200MB more on every request (on hg-committed), despite gc.collect(). No
idea why.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel