D4498: util: properly copy lrucachedict instances

2018-09-07 Thread martinvonz (Martin von Zweigbergk)
martinvonz added inline comments.

INLINE COMMENTS

> indygreg wrote in util.py:1302
> Yes, this does feel like a bug. But it feels unrelated to the series, no?
> 
> I can certainly code up a patch easily enough. I may tack one on the end of 
> the series...

Yes, definitely unrelated (that's what the "Btw" was supposed to mean, but I 
could have been clearer)

REPOSITORY
  rHG Mercurial

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

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


D4506: util: update lrucachedict order during get()

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

REVISION SUMMARY
  get() should have the same semantics as __getitem__ for item
  retrieval.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/util.py
  tests/test-lrucachedict.py

CHANGE DETAILS

diff --git a/tests/test-lrucachedict.py b/tests/test-lrucachedict.py
--- a/tests/test-lrucachedict.py
+++ b/tests/test-lrucachedict.py
@@ -63,6 +63,18 @@
 for key in ('a', 'b'):
 self.assertIn(key, d)
 
+def testget(self):
+d = util.lrucachedict(4)
+d['a'] = 'va'
+d['b'] = 'vb'
+d['c'] = 'vc'
+
+self.assertIsNone(d.get('missing'))
+self.assertEqual(list(d), ['c', 'b', 'a'])
+
+self.assertEqual(d.get('a'), 'va')
+self.assertEqual(list(d), ['a', 'c', 'b'])
+
 def testcopypartial(self):
 d = util.lrucachedict(4)
 d.insert('a', 'va', cost=4)
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1332,7 +1332,7 @@
 
 def get(self, k, default=None):
 try:
-return self._cache[k].value
+return self.__getitem__(k)
 except KeyError:
 return default
 



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


Re: [PATCH 09 of 10] shelve: use the internal phase when possible

2018-09-07 Thread Boris FELD

On 30/08/2018 17:02, Augie Fackler wrote:



On Aug 29, 2018, at 12:30 PM, Boris Feld  wrote:

# HG changeset patch
# User Boris Feld 
# Date 1527588738 -7200
#  Tue May 29 12:12:18 2018 +0200
# Node ID ccb9572516145a1b6f11a8d199c4a7da4774898b
# Parent  5726fcca7837180c0f25ed345236625797725aa5
# EXP-Topic internal-phase.shelve
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
ccb957251614
shelve: use the internal phase when possible

The next patch got me to thinking: shouldn’t we only enable this if rebase will 
use obsmarkers instead of strip?
Since we have the bundle and the patch file as backup, we can safely 
strip the internal changeset when doing the rebase's cleanup. It means 
teaching `scmutil.cleanupnodes` code to ignore them.


Patches 4-8 are queued, with a few typo fixes in flight.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


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


D4502: util: allow lrucachedict to track cost of entries

2018-09-07 Thread lothiraldan (Boris Feld)
lothiraldan added inline comments.

INLINE COMMENTS

> util.py:1277
>  if node is not None:
> +self.totalcost -= node.cost
>  node.value = v

I'm not sure this line is tested, I didnd't see a test where we replace an 
entry with an associated cost

REPOSITORY
  rHG Mercurial

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

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


mercurial@39466: 11 new changesets

2018-09-07 Thread Mercurial Commits
11 new changesets in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/8d858fbf2759
changeset:   39456:8d858fbf2759
parent:  39453:ab452995eaff
user:Matt Harbison 
date:Tue Sep 04 22:29:38 2018 -0400
summary: cbor: teach the encoder to handle python `long` type for Windows

https://www.mercurial-scm.org/repo/hg/rev/a913d2892e17
changeset:   39457:a913d2892e17
user:Matt Harbison 
date:Thu Sep 06 00:51:21 2018 -0400
summary: lfs: ensure the blob is linked to the remote store on skipped 
uploads

https://www.mercurial-scm.org/repo/hg/rev/4babb55e4503
changeset:   39458:4babb55e4503
user:Pulkit Goyal 
date:Thu Sep 06 03:24:27 2018 +0530
summary: tests: order the imports in test-fastannotate-hg.t

https://www.mercurial-scm.org/repo/hg/rev/bc3b99d5627e
changeset:   39459:bc3b99d5627e
user:Pulkit Goyal 
date:Thu Sep 06 03:21:05 2018 +0530
summary: py3: add new passing tests spotted by the buildbot

https://www.mercurial-scm.org/repo/hg/rev/35ecaa999a12
changeset:   39460:35ecaa999a12
user:Kyle Lippincott 
date:Fri Aug 17 19:18:53 2018 -0700
summary: match: improve includematcher.visitchildrenset to be much faster 
and cached

https://www.mercurial-scm.org/repo/hg/rev/7df9ae38c75c
changeset:   39461:7df9ae38c75c
user:Yuya Nishihara 
date:Thu Sep 06 21:55:30 2018 +0900
summary: help: add internals.wireprotocolv2 to the table, and remove 
redundant header

https://www.mercurial-scm.org/repo/hg/rev/e5449ff273d6
changeset:   39462:e5449ff273d6
user:Matt Harbison 
date:Thu Sep 06 23:37:24 2018 -0400
summary: tests: stabilize test-removeemptydirs.t on Windows

https://www.mercurial-scm.org/repo/hg/rev/7fea205fd5dc
changeset:   39463:7fea205fd5dc
user:Gregory Szorc 
date:Thu Sep 06 18:30:12 2018 -0700
summary: merge: move purge logic from extension

https://www.mercurial-scm.org/repo/hg/rev/3dd34b401bc2
changeset:   39464:3dd34b401bc2
user:Gregory Szorc 
date:Tue Sep 04 15:55:23 2018 -0700
summary: merge: use vfs methods for I/O

https://www.mercurial-scm.org/repo/hg/rev/4062bbb1d10f
changeset:   39465:4062bbb1d10f
user:Pulkit Goyal 
date:Tue Sep 04 19:26:50 2018 +0300
summary: narrow: use util.readfile() and improve error message using 
--narrowspec

https://www.mercurial-scm.org/repo/hg/rev/83dd656586b1
changeset:   39466:83dd656586b1
bookmark:@
tag: tip
user:Pulkit Goyal 
date:Tue Sep 04 15:16:22 2018 +0300
summary: tests: improve the widening testing in test-narrow-widen*

-- 
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


Re: [PATCH 6 of 7] context: introduce a `_findchangeid` method to `filectx`

2018-09-07 Thread Boris FELD

On 07/09/2018 11:17, Martin von Zweigbergk via Mercurial-devel wrote:



On Fri, Sep 7, 2018 at 8:13 AM Boris Feld > wrote:


# HG changeset patch
# User Boris Feld mailto:boris.f...@octobus.net>>
# Date 1536255775 14400
#      Thu Sep 06 13:42:55 2018 -0400
# Node ID 441c39342d63c75ee101587b2fbf3af60800762f
# Parent  f74f706f6d061cf9369cd45caa3a71d3fc03b293
# EXP-Topic copy-perf
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull
https://bitbucket.org/octobus/mercurial-devel/ -r 441c39342d63
context: introduce a `_findchangeid` method to `filectx`

In the same spirit as `_introrev` we want to introduce a way to
limit graph
walking when resolving `filectx.rev()`.


Can you elaborate? I know what introrev() does.

We tried giving more details in the previous commit:

    We want to add a mechanism to stop iteration early associated to
    intro rev early in some case. However, it does not make sense to
    expose it in the public `filectx` API. So we split the code into an
    internal method instead.

Instead of modifying the `_changeid` property, we move most of the code 
in a new low-level method.


In the next commit, we modify this new low-level method to introduce the 
walk limitation.


We introduce a new internal function for
this purpose.

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -631,16 +631,21 @@ class basefilectx(object):

     @propertycache
     def _changeid(self):
+        return self._findchangeid()
+
+    def _findchangeid(self):


If it's always going to return a revnum (never a nodeid), can we call 
it _findchangrev() instead?


Yes, should we send a V2 or could it be fixed inflight?


         if r'_changeid' in self.__dict__:
-            return self._changeid
+            changeid = self._changeid
         elif r'_changectx' in self.__dict__:
-            return self._changectx.rev()
+            changeid = self._changectx.rev()
         elif r'_descendantrev' in self.__dict__:
             # this file context was created from a revision with
a known
             # descendant, we can (lazily) correct for linkrev aliases
-            return self._adjustlinkrev(self._descendantrev)
+            changeid = self._adjustlinkrev(self._descendantrev)
         else:
-            return self._filelog.linkrev(self._filerev)
+            changeid = self._filelog.linkrev(self._filerev)
+        self._changeid = changeid
+        return changeid

     @propertycache
     def _filenode(self):
@@ -872,7 +877,7 @@ class basefilectx(object):
             else:
                 return self._adjustlinkrev(lazyrev, inclusive=True)
         else:
-            return self.rev()
+            return self._findchangeid()

     def introfilectx(self):
         """Return filectx having identical contents, but pointing
to the
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org

https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel



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


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


D4498: util: properly copy lrucachedict instances

2018-09-07 Thread indygreg (Gregory Szorc)
indygreg added inline comments.

INLINE COMMENTS

> martinvonz wrote in util.py:1302
> Btw, why doesn't this do `return self[k]` instead? It seems surprising that 
> the recency is not updated.

Yes, this does feel like a bug. But it feels unrelated to the series, no?

I can certainly code up a patch easily enough. I may tack one on the end of the 
series...

REPOSITORY
  rHG Mercurial

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

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


D4498: util: properly copy lrucachedict instances

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


  Added https://phab.mercurial-scm.org/D4506 to the series to fix the bug with 
`get()`.

REPOSITORY
  rHG Mercurial

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

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


[PATCH 2 of 4] hgweb: add error template to json so it won't crash

2018-09-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1536326368 -32400
#  Fri Sep 07 22:19:28 2018 +0900
# Node ID 90fe6481af4fd42def159f8e501612f305979822
# Parent  cd0c58017ae949408c1e746c9c81ca6847591b3c
hgweb: add error template to json so it won't crash

diff --git a/mercurial/templates/json/map b/mercurial/templates/json/map
--- a/mercurial/templates/json/map
+++ b/mercurial/templates/json/map
@@ -241,3 +241,6 @@ indexentry = '\{
   "lastchange": {lastchange|json},
   "labels": {labels|json}
   }'
+error = '\{
+  "error": {error|utf8|json}
+  }'
diff --git a/tests/test-hgweb-json.t b/tests/test-hgweb-json.t
--- a/tests/test-hgweb-json.t
+++ b/tests/test-hgweb-json.t
@@ -2183,6 +2183,16 @@ help/{topic} shows an individual help to
 "topic": "phases"
   }
 
+Error page shouldn't crash
+
+  $ request json-changeset/deadbeef
+  404 Not Found
+  
+  {
+"error": "unknown revision 'deadbeef'"
+  }
+  [1]
+
 Commit message with Japanese Kanji 'Noh', which ends with '\x5c'
 
   $ echo foo >> da/foo
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 7] context: fix introrev to avoid computation as initially intended

2018-09-07 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1536254177 14400
#  Thu Sep 06 13:16:17 2018 -0400
# Node ID a4c3eb6c1a36cbbf64fa8930b173154b2e77ef2b
# Parent  9a18509c522deeb62a7b244dcf4c7b79a8dc1132
# EXP-Topic copy-perf
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
a4c3eb6c1a36
context: fix introrev to avoid computation as initially intended

The `filerev.introrev()` method has various logic be as efficient as possible.
In particular, it tries to restrict the range covered by the
`ctx._adjustlinkrev(...)` call. However, it does so using the value returned by
`ctx.rev()`. In some case (eg: copy tracing), that `ctx.rev()` call would do an
`_adjustlinkrev(...)` call on its own, defeating the optimization purpose and
doing the computation twice.

We are about to improve graph traversal associated with copy tracing using code
based on `ctx.introrev()`, so we need this fixed before proceeding further.

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -829,6 +829,23 @@ class basefilectx(object):
 # result is crash somewhere else at to some point.
 return lkr
 
+def _lazyrev(self):
+"""return self.rev() if it is available without computation,
+
+If finding the rev would trigger a possibly expensive computation, we
+return None."""
+attrs = vars(self)
+if r'_changeid' in attrs:
+# We have a cached value already
+return self.rev()
+elif r'_changectx' in attrs:
+# We know which changelog entry we are coming from
+return self.rev()
+elif r'_descendantrev' not in attrs:
+# we have no context, so linkrev will be used
+return self.rev()
+return None
+
 def introrev(self):
 """return the rev of the changeset which introduced this file revision
 
@@ -839,11 +856,14 @@ class basefilectx(object):
 changesets.
 """
 lkr = self.linkrev()
-attrs = vars(self)
-noctx = not (r'_changeid' in attrs or r'_changectx' in attrs)
-if noctx or self.rev() == lkr:
-return self.linkrev()
-return self._adjustlinkrev(self.rev(), inclusive=True)
+lazyrev = self._lazyrev()
+if lazyrev is not None:
+if lazyrev == lkr:
+return lazyrev
+else:
+return self._adjustlinkrev(lazyrev, inclusive=True)
+else:
+return self.rev()
 
 def introfilectx(self):
 """Return filectx having identical contents, but pointing to the
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 6 of 7] context: introduce a `_findchangeid` method to `filectx`

2018-09-07 Thread Martin von Zweigbergk via Mercurial-devel
On Fri, Sep 7, 2018 at 8:13 AM Boris Feld  wrote:

> # HG changeset patch
> # User Boris Feld 
> # Date 1536255775 14400
> #  Thu Sep 06 13:42:55 2018 -0400
> # Node ID 441c39342d63c75ee101587b2fbf3af60800762f
> # Parent  f74f706f6d061cf9369cd45caa3a71d3fc03b293
> # EXP-Topic copy-perf
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r
> 441c39342d63
> context: introduce a `_findchangeid` method to `filectx`
>
> In the same spirit as `_introrev` we want to introduce a way to limit graph
> walking when resolving `filectx.rev()`.


Can you elaborate? I know what introrev() does.


> We introduce a new internal function for
> this purpose.
>
> diff --git a/mercurial/context.py b/mercurial/context.py
> --- a/mercurial/context.py
> +++ b/mercurial/context.py
> @@ -631,16 +631,21 @@ class basefilectx(object):
>
>  @propertycache
>  def _changeid(self):
> +return self._findchangeid()
> +
> +def _findchangeid(self):
>

If it's always going to return a revnum (never a nodeid), can we call it
_findchangrev() instead?


>  if r'_changeid' in self.__dict__:
> -return self._changeid
> +changeid = self._changeid
>  elif r'_changectx' in self.__dict__:
> -return self._changectx.rev()
> +changeid = self._changectx.rev()
>  elif r'_descendantrev' in self.__dict__:
>  # this file context was created from a revision with a known
>  # descendant, we can (lazily) correct for linkrev aliases
> -return self._adjustlinkrev(self._descendantrev)
> +changeid = self._adjustlinkrev(self._descendantrev)
>  else:
> -return self._filelog.linkrev(self._filerev)
> +changeid = self._filelog.linkrev(self._filerev)
> +self._changeid = changeid
> +return changeid
>
>  @propertycache
>  def _filenode(self):
> @@ -872,7 +877,7 @@ class basefilectx(object):
>  else:
>  return self._adjustlinkrev(lazyrev, inclusive=True)
>  else:
> -return self.rev()
> +return self._findchangeid()
>
>  def introfilectx(self):
>  """Return filectx having identical contents, but pointing to the
> ___
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 4] hgweb: do not audit URL path as working-directory path

2018-09-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1535289489 -32400
#  Sun Aug 26 22:18:09 2018 +0900
# Node ID 70d6fff1bccfe8760f06bc92ca0b23a61c3ddca9
# Parent  61b6dff6e23fde7831422b5787430a32003a4d33
hgweb: do not audit URL path as working-directory path

Since hgweb is an interface to repository data, we don't need to prohibit
any paths conflicting within the filesystem. Still an access to working
files is audited by filectx.

diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -320,7 +320,8 @@ def branchentries(repo, stripecount, lim
 
 def cleanpath(repo, path):
 path = path.lstrip('/')
-return pathutil.canonpath(repo.root, '', path)
+auditor = pathutil.pathauditor(repo.root, realfs=False)
+return pathutil.canonpath(repo.root, '', path, auditor=auditor)
 
 def changectx(repo, req):
 changeid = "tip"
diff --git a/tests/test-hgwebdir.t b/tests/test-hgwebdir.t
--- a/tests/test-hgwebdir.t
+++ b/tests/test-hgwebdir.t
@@ -1231,14 +1231,15 @@ Test subrepositories inside intermediate
   
   f2
 
-Test accessing file that is shadowed by another repository
+Test accessing file that could be shadowed by another repository if the URL
+path were audited as a working-directory path:
 
   $ get-with-headers.py localhost:$HGPORT1 
'rcoll/notrepo/f/file/tip/f3/file?style=raw'
-  403 Forbidden
-  
+  200 Script output follows
   
-  error: path 'f3/file' is inside nested repo 'f3'
-  [1]
+  f3/file
+
+Test accessing working-directory file that is shadowed by another repository
 
   $ get-with-headers.py localhost:$HGPORT1 
'rcoll/notrepo/f/file//f3/file?style=raw'
   403 Forbidden
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 7] ancestors: actually iterate over ancestors in topological order (issue5979)

2018-09-07 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1536267628 14400
#  Thu Sep 06 17:00:28 2018 -0400
# Node ID eb80c721aea9715e23dc35cdd119428aa120ea93
# Parent  ab452995eafffa69c34e863e4d8c03e163d8f3ad
# EXP-Topic issue5979
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
eb80c721aea9
ancestors: actually iterate over ancestors in topological order (issue5979)

This code previously used a dequeue logic, the first ancestors seen were the
first ancestors to be emitted. In branching/merging situations, it can result
in ancestors being yielded before their descendants, breaking the object
contract.

We got affected by this issue while working on the copy tracing code. At about
the same time, Axel Hecht  reported the issue and provided
the test case used in this changeset. Thanks Axel.

Running `hg perfancestors` does not show a significant difference between the
old and the new version.

diff --git a/mercurial/ancestor.py b/mercurial/ancestor.py
--- a/mercurial/ancestor.py
+++ b/mercurial/ancestor.py
@@ -7,7 +7,6 @@
 
 from __future__ import absolute_import
 
-import collections
 import heapq
 
 from .node import nullrev
@@ -305,14 +304,15 @@ class lazyancestors(object):
 """Generate the ancestors of _initrevs in reverse topological order.
 
 If inclusive is False, yield a sequence of revision numbers starting
-with the parents of each revision in revs, i.e., each revision is *not*
-considered an ancestor of itself.  Results are in breadth-first order:
-parents of each rev in revs, then parents of those, etc.
+with the parents of each revision in revs, i.e., each revision is
+*not* considered an ancestor of itself. Results are emitted in reverse
+revision number order. That order is also topological: a child is
+always emitted before its parent.
 
 If inclusive is True, yield all the revs first (ignoring stoprev),
-then yield all the ancestors of revs as when inclusive is False.
-If an element in revs is an ancestor of a different rev it is not
-yielded again."""
+then yield all the ancestors of revs as when inclusive is False. If an
+element in revs is an ancestor of a different rev it is not yielded
+again."""
 seen = set()
 revs = self._initrevs
 if self._inclusive:
@@ -322,17 +322,27 @@ class lazyancestors(object):
 
 parentrevs = self._parentrevs
 stoprev = self._stoprev
-visit = collections.deque(revs)
+visit = []
+heapq.heapify(visit)
+schedule = heapq.heappush
+nextitem = heapq.heappop
+see = seen.add
+see(nullrev)
 
-see = seen.add
-schedule = visit.append
+for r in revs:
+for parent in parentrevs(r):
+if parent not in seen:
+schedule(visit, -parent)
+see(parent)
 
 while visit:
-for parent in parentrevs(visit.popleft()):
-if parent >= stoprev and parent not in seen:
-schedule(parent)
-see(parent)
-yield parent
+current = -nextitem(visit)
+if current >= stoprev:
+yield current
+for parent in parentrevs(current):
+if parent not in seen:
+schedule(visit, -parent)
+see(parent)
 
 def __contains__(self, target):
 """Test whether target is an ancestor of self._initrevs."""
diff --git a/tests/test-ancestor.py.out b/tests/test-ancestor.py.out
--- a/tests/test-ancestor.py.out
+++ b/tests/test-ancestor.py.out
@@ -3,16 +3,16 @@ membership: []
 iteration:  []
 % lazy ancestor set for [11, 13], stoprev = 0, inclusive = False
 membership: [7, 8, 3, 4, 1, 0]
-iteration:  [3, 7, 8, 1, 4, 0, 2]
+iteration:  [8, 7, 4, 3, 2, 1, 0]
 % lazy ancestor set for [1, 3], stoprev = 0, inclusive = False
 membership: [1, 0]
-iteration:  [0, 1]
+iteration:  [1, 0]
 % lazy ancestor set for [11, 13], stoprev = 0, inclusive = True
 membership: [11, 13, 7, 8, 3, 4, 1, 0]
-iteration:  [11, 13, 3, 7, 8, 1, 4, 0, 2]
+iteration:  [11, 13, 8, 7, 4, 3, 2, 1, 0]
 % lazy ancestor set for [11, 13], stoprev = 6, inclusive = False
 membership: [7, 8]
-iteration:  [7, 8]
+iteration:  [8, 7]
 % lazy ancestor set for [11, 13], stoprev = 6, inclusive = True
 membership: [11, 13, 7, 8]
-iteration:  [11, 13, 7, 8]
+iteration:  [11, 13, 8, 7]
diff --git a/tests/test-issue5979.t b/tests/test-issue5979.t
new file mode 100644
--- /dev/null
+++ b/tests/test-issue5979.t
@@ -0,0 +1,34 @@
+  $ hg init r1
+  $ cd r1
+  $ hg ci --config ui.allowemptycommit=true -m c0
+  $ hg ci --config ui.allowemptycommit=true -m c1
+  $ hg ci --config ui.allowemptycommit=true -m c2
+  $ hg co -q 0
+  $ hg ci --config ui.allowemptycommit=true -m c3
+  

[PATCH] phase: report number of non-public changeset alongside the new range

2018-09-07 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1535586801 -7200
#  Thu Aug 30 01:53:21 2018 +0200
# Node ID 5f931c1d1422e9a8c08cca3a59804b25a1183449
# Parent  ab452995eafffa69c34e863e4d8c03e163d8f3ad
# EXP-Topic phase-report
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
5f931c1d1422
phase: report number of non-public changeset alongside the new range

When interacting with non-publishing repository or bundle, it is useful to
have some information about the phase of the changeset we just pulled.

This changeset updates the "new changesets MIN:MAX" output to also includes
phases information for non-public changesets. Displaying extra data about
non-public changesets means the output for exchange with publishing repository
(the default) is unaffected.

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -1634,7 +1634,20 @@ def registersummarycallback(repo, otr, t
 revrange = minrev
 else:
 revrange = '%s:%s' % (minrev, maxrev)
-repo.ui.status(_('new changesets %s\n') % revrange)
+draft = len(repo.revs('%ld and draft()', revs))
+secret = len(repo.revs('%ld and secret()', revs))
+if not (draft or secret):
+msg = _('new changesets %s\n') % revrange
+elif draft and secret:
+msg = _('new changesets %s (%d drafts, %d secrets)\n')
+msg %= (revrange, draft, secret)
+elif draft:
+msg = _('new changesets %s (%d drafts)\n')
+msg %= (revrange, draft)
+elif secret:
+msg = _('new changesets %s (%d secrets)\n')
+msg %= (revrange, secret)
+repo.ui.status(msg)
 
 @reportsummary
 def reportphasechanges(repo, tr):
diff --git a/tests/test-audit-path.t b/tests/test-audit-path.t
--- a/tests/test-audit-path.t
+++ b/tests/test-audit-path.t
@@ -82,7 +82,7 @@ unbundle tampered bundle
   adding manifests
   adding file changes
   added 5 changesets with 6 changes to 6 files (+4 heads)
-  new changesets b7da9bf6b037:fc1393d727bc
+  new changesets b7da9bf6b037:fc1393d727bc (5 drafts)
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 attack .hg/test
diff --git a/tests/test-bookmarks-pushpull.t b/tests/test-bookmarks-pushpull.t
--- a/tests/test-bookmarks-pushpull.t
+++ b/tests/test-bookmarks-pushpull.t
@@ -55,7 +55,7 @@ import bookmark by name
   adding remote bookmark X
   updating bookmark Y
   adding remote bookmark Z
-  new changesets 4e3505fd9583
+  new changesets 4e3505fd9583 (1 drafts)
   test-hook-bookmark: X:   -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
   test-hook-bookmark: Y:   -> 
4e3505fd95835d721066b76e75dbb8cc554d7f77
   test-hook-bookmark: Z:   -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
@@ -418,7 +418,7 @@ divergent bookmarks
   divergent bookmark @ stored as @foo
   divergent bookmark X stored as X@foo
   updating bookmark Z
-  new changesets 0d2164f0ce0d
+  new changesets 0d2164f0ce0d (1 drafts)
   test-hook-bookmark: @foo:   -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
   test-hook-bookmark: X@foo:   -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
   test-hook-bookmark: Z:  4e3505fd95835d721066b76e75dbb8cc554d7f77 -> 
0d2164f0ce0d8f1d6f94351eba04b794909be66c
@@ -582,7 +582,7 @@ race conditions
   adding file changes
   added 1 changesets with 1 changes to 1 files
   updating bookmark Y
-  new changesets b0a5eff05604
+  new changesets b0a5eff05604 (1 drafts)
   (run 'hg update' to get a working copy)
   $ hg book
* @ 1:0d2164f0ce0d
@@ -632,7 +632,7 @@ Update a bookmark right after the initia
   adding file changes
   added 1 changesets with 1 changes to 1 files
   updating bookmark Y
-  new changesets 35d1ef0a8d1b
+  new changesets 35d1ef0a8d1b (1 drafts)
   (run 'hg update' to get a working copy)
   $ hg book
  @ 1:0d2164f0ce0d
@@ -796,7 +796,7 @@ hgweb
   adding file changes
   added 5 changesets with 5 changes to 3 files (+2 heads)
   2 new obsolescence markers
-  new changesets 4e3505fd9583:c922c0139ca0
+  new changesets 4e3505fd9583:c922c0139ca0 (5 drafts)
   updating to bookmark @
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R cloned-bookmarks bookmarks
@@ -933,7 +933,7 @@ bookmark, not all outgoing changes:
   adding file changes
   added 5 changesets with 5 changes to 3 files (+2 heads)
   2 new obsolescence markers
-  new changesets 4e3505fd9583:c922c0139ca0
+  new changesets 4e3505fd9583:c922c0139ca0 (5 drafts)
   updating to bookmark @
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd addmarks
@@ -1225,7 +1225,7 @@ Test that pre-pushkey compat for bookmar
   adding manifests
   adding file changes
   added 1 changesets with 1 

[PATCH 7 of 7] context: floor adjustlinkrev graph walk during copy tracing

2018-09-07 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1536255188 14400
#  Thu Sep 06 13:33:08 2018 -0400
# Node ID 0f720a4aa166d08daaa39e8462f2291f77e825c1
# Parent  441c39342d63c75ee101587b2fbf3af60800762f
# EXP-Topic copy-perf
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
0f720a4aa166
context: floor adjustlinkrev graph walk during copy tracing

The `_adjustlinkrev` method gains an optional "floor" argument. The linkrev
adjustment will give up once this floor is reached. The relevant functions
using `_adjustlinkrev` are updated to pass an appropriate value in the copy
tracing code.

In some private repository, about 10% of the status call triggered
pathological case addressed by this change. The speedup varies from one call
to another, the best-observed win is moving from 170s to 11s.

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -633,7 +633,7 @@ class basefilectx(object):
 def _changeid(self):
 return self._findchangeid()
 
-def _findchangeid(self):
+def _findchangeid(self, floor=None):
 if r'_changeid' in self.__dict__:
 changeid = self._changeid
 elif r'_changectx' in self.__dict__:
@@ -641,10 +641,11 @@ class basefilectx(object):
 elif r'_descendantrev' in self.__dict__:
 # this file context was created from a revision with a known
 # descendant, we can (lazily) correct for linkrev aliases
-changeid = self._adjustlinkrev(self._descendantrev)
+changeid = self._adjustlinkrev(self._descendantrev, floor=floor)
 else:
 changeid = self._filelog.linkrev(self._filerev)
-self._changeid = changeid
+if changeid is not None:
+self._changeid = changeid
 return changeid
 
 @propertycache
@@ -788,7 +789,7 @@ class basefilectx(object):
 
 return True
 
-def _adjustlinkrev(self, srcrev, inclusive=False):
+def _adjustlinkrev(self, srcrev, inclusive=False, floor=None):
 """return the first ancestor of  introducing 
 
 If the linkrev of the file revision does not point to an ancestor of
@@ -797,6 +798,10 @@ class basefilectx(object):
 
 :srcrev: the changeset revision we search ancestors from
 :inclusive: if true, the src revision will also be checked
+:floor: an optional revision to stop the walk at. If no introduction
+of this file content could be found before this floor
+revision, the function will returns "None" and stops its
+iteration.
 """
 repo = self._repo
 cl = repo.unfiltered().changelog
@@ -822,6 +827,8 @@ class basefilectx(object):
 fnode = self._filenode
 path = self._path
 for a in iteranc:
+if floor is not None and a < floor:
+return None
 ac = cl.read(a) # get changeset data (we avoid object creation)
 if path in ac[3]: # checking the 'files' field.
 # The file has been touched, check if the content is
@@ -837,8 +844,12 @@ class basefilectx(object):
 def isintroducedafter(self, changelogrev):
 """True if a filectx have been introduced after a given floor revision
 """
-return (changelogrev <= self.linkrev()
-or changelogrev <= self._introrev())
+if changelogrev <= self.linkrev():
+return True
+introrev = self._introrev(floor=changelogrev)
+if introrev is None:
+return False
+return changelogrev <= introrev
 
 def _lazyrev(self):
 """return self.rev() if it is available without computation,
@@ -865,19 +876,28 @@ class basefilectx(object):
 revision is one of its ancestors. This prevents bugs from
 'linkrev-shadowing' when a file revision is used by multiple
 changesets.
+
 """
 return self._introrev()
 
-def _introrev(self):
+def _introrev(self, floor=None):
+"""
+Same as `introrev` but, with an extra argument to limit changelog
+iteration range in some internal usecase.
+
+If `floor` is set, the `introrev` will not be searched past that
+`floor` revision and "None" might be returned. This is useful to limit
+iteration range.
+"""
 lkr = self.linkrev()
 lazyrev = self._lazyrev()
 if lazyrev is not None:
 if lazyrev == lkr:
 return lazyrev
 else:
-return self._adjustlinkrev(lazyrev, inclusive=True)
+return self._adjustlinkrev(lazyrev, inclusive=True, 
floor=floor)
 else:
-return self._findchangeid()
+return self._findchangeid(floor=floor)
 
 def introfilectx(self):
 """Return filectx having 

[PATCH 3 of 4] hgweb: map Abort to 403 error to report inaccessible path for example

2018-09-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1535289805 -32400
#  Sun Aug 26 22:23:25 2018 +0900
# Node ID 61b6dff6e23fde7831422b5787430a32003a4d33
# Parent  90fe6481af4fd42def159f8e501612f305979822
hgweb: map Abort to 403 error to report inaccessible path for example

Abort is so common in our codebase. We could instead introduce a dedicated
type for path auditing errors, but we'll probably have to catch error.Abort
anyway.

As you can see, an abort message may include a full path to the repository,
which might be considered information leak. If that matters, we should hide
the message and send it to the server log instead.

diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -439,6 +439,10 @@ class hgweb(object):
 res.status = '500 Internal Server Error'
 res.headers['Content-Type'] = ctype
 return rctx.sendtemplate('error', error=pycompat.bytestr(e))
+except error.Abort as e:
+res.status = '403 Forbidden'
+res.headers['Content-Type'] = ctype
+return rctx.sendtemplate('error', error=pycompat.bytestr(e))
 except ErrorResponse as e:
 for k, v in e.headers:
 res.headers[k] = v
diff --git a/tests/test-hgwebdir.t b/tests/test-hgwebdir.t
--- a/tests/test-hgwebdir.t
+++ b/tests/test-hgwebdir.t
@@ -66,6 +66,20 @@ create a subdirectory containing reposit
   > EOF
   $ cd ..
 
+add file under the directory which could be shadowed by another repository
+
+  $ mkdir notrepo/f/f3
+  $ echo f3/file > notrepo/f/f3/file
+  $ hg -R notrepo/f ci -Am 'f3/file'
+  adding f3/file
+  $ hg -R notrepo/f update null
+  0 files updated, 0 files merged, 4 files removed, 0 files unresolved
+  $ hg init notrepo/f/f3
+  $ cat <<'EOF' > notrepo/f/f3/.hg/hgrc
+  > [web]
+  > hidden = true
+  > EOF
+
 create repository without .hg/store
 
   $ hg init nostore
@@ -1217,6 +1231,38 @@ Test subrepositories inside intermediate
   
   f2
 
+Test accessing file that is shadowed by another repository
+
+  $ get-with-headers.py localhost:$HGPORT1 
'rcoll/notrepo/f/file/tip/f3/file?style=raw'
+  403 Forbidden
+  
+  
+  error: path 'f3/file' is inside nested repo 'f3'
+  [1]
+
+  $ get-with-headers.py localhost:$HGPORT1 
'rcoll/notrepo/f/file//f3/file?style=raw'
+  403 Forbidden
+  
+  
+  error: path 'f3/file' is inside nested repo 'f3'
+  [1]
+
+Test accessing invalid paths:
+
+  $ get-with-headers.py localhost:$HGPORT1 
'rcoll/notrepo/f/file/tip/..?style=raw'
+  403 Forbidden
+  
+  
+  error: .. not under root '$TESTTMP/dir/webdir/notrepo/f'
+  [1]
+
+  $ get-with-headers.py localhost:$HGPORT1 
'rcoll/notrepo/f/file/tip/.hg/hgrc?style=raw'
+  403 Forbidden
+  
+  
+  error: path contains illegal component: .hg/hgrc
+  [1]
+
 Test descend = False
 
   $ killdaemons.py
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4452: tests: improve the widening testing in test-narrow-widen*

2018-09-07 Thread pulkit (Pulkit Goyal)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG83dd656586b1: tests: improve the widening testing in 
test-narrow-widen* (authored by pulkit, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4452?vs=10731=10830

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

AFFECTED FILES
  tests/test-narrow-widen-no-ellipsis.t
  tests/test-narrow-widen.t

CHANGE DETAILS

diff --git a/tests/test-narrow-widen.t b/tests/test-narrow-widen.t
--- a/tests/test-narrow-widen.t
+++ b/tests/test-narrow-widen.t
@@ -88,23 +88,26 @@
 
   $ cd ..
 
-Widen the narrow spec to see the wider file. This should not get the newly
+Widen the narrow spec to see the widest file. This should not get the newly
 added upstream revisions.
 
   $ cd narrow
-  $ hg tracked --addinclude wider/f
+  $ hg tracked --addinclude widest/f
   comparing with ssh://user@dummy/master
   searching for changes
   no changes found
   saved backup bundle to $TESTTMP/narrow/.hg/strip-backup/*-widen.hg (glob)
   adding changesets
   adding manifests
   adding file changes
-  added 2 changesets with 1 changes to 1 files
+  added 3 changesets with 2 changes to 2 files
   new changesets *:* (glob)
   $ hg tracked
   I path:inside
-  I path:wider/f
+  I path:widest/f
+
+  $ cat widest/f
+  widest
 
 Pull down the newly added upstream revision.
 
@@ -114,27 +117,29 @@
   adding changesets
   adding manifests
   adding file changes
-  added 4 changesets with 2 changes to 2 files
+  added 5 changesets with 4 changes to 2 files
   new changesets *:* (glob)
   (run 'hg update' to get a working copy)
   $ hg update -r 'desc("add wider")'
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ cat wider/f
-  wider
+  $ cat widest/f
+  widest v2
 
   $ hg update -r 'desc("update inside")'
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ cat wider/f
-  wider
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cat widest/f
+  widest v3
   $ cat inside/f
   inside v2
 
   $ hg log -T "{if(ellipsis, '...')}{rev}: {desc}\n"
-  ...5: update widest v4
-  4: update inside
-  ...3: update widest v3
-  2: add wider, update widest
-  ...1: add outside
+  7: update widest v4
+  ...6: add outside2
+  5: update inside
+  4: update widest v3
+  3: add wider, update widest
+  ...2: add outside
+  1: add widest
   0: add inside
 
 Check that widening with a newline fails
@@ -144,9 +149,9 @@
   abort: newlines are not allowed in narrowspec paths
   [255]
 
-widen the narrow spec to include the widest file
+widen the narrow spec to include the wider file
 
-  $ hg tracked --addinclude widest
+  $ hg tracked --addinclude wider
   comparing with ssh://user@dummy/master
   searching for changes
   no changes found
@@ -158,8 +163,8 @@
   new changesets *:* (glob)
   $ hg tracked
   I path:inside
-  I path:wider/f
-  I path:widest
+  I path:wider
+  I path:widest/f
   $ hg update 'desc("add widest")'
   2 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ cat widest/f
diff --git a/tests/test-narrow-widen-no-ellipsis.t 
b/tests/test-narrow-widen-no-ellipsis.t
--- a/tests/test-narrow-widen-no-ellipsis.t
+++ b/tests/test-narrow-widen-no-ellipsis.t
@@ -84,22 +84,25 @@
 
   $ cd ..
 
-Widen the narrow spec to see the wider file. This should not get the newly
+Widen the narrow spec to see the widest file. This should not get the newly
 added upstream revisions.
 
   $ cd narrow
-  $ hg tracked --addinclude wider/f
+  $ hg tracked --addinclude widest/f
   comparing with ssh://user@dummy/master
   searching for changes
   no changes found
   adding changesets
   adding manifests
   adding file changes
-  added 0 changesets with 0 changes to 1 files
+  added 0 changesets with 1 changes to 2 files
   3 local changesets published
   $ hg tracked
   I path:inside
-  I path:wider/f
+  I path:widest/f
+
+  $ cat widest/f
+  widest
 
 Pull down the newly added upstream revision.
 
@@ -109,18 +112,19 @@
   adding changesets
   adding manifests
   adding file changes
-  added 5 changesets with 2 changes to 2 files
+  added 5 changesets with 4 changes to 2 files
   new changesets *:* (glob)
   (run 'hg update' to get a working copy)
   $ hg update -r 'desc("add wider")'
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ cat wider/f
-  wider
+
+  $ cat widest/f
+  widest v2
 
   $ hg update -r 'desc("update inside")'
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ cat wider/f
-  wider
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cat widest/f
+  widest v3
   $ cat inside/f
   inside v2
 
@@ -141,21 +145,21 @@
   abort: newlines are not allowed in narrowspec paths
   [255]
 
-widen the narrow spec to include the widest file
+widen the narrow spec to include the wider file
 
-  $ hg tracked --addinclude widest
+  $ hg tracked 

[PATCH 2 of 7] ancestors: ensure a consistent order even in the "inclusive" case

2018-09-07 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1536277058 14400
#  Thu Sep 06 19:37:38 2018 -0400
# Node ID 9a18509c522deeb62a7b244dcf4c7b79a8dc1132
# Parent  eb80c721aea9715e23dc35cdd119428aa120ea93
# EXP-Topic issue5979
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
9a18509c522d
ancestors: ensure a consistent order even in the "inclusive" case

It seems odds to first issue the "source" revs and then the other ancestors.
In addition, doing so can break the other contract of always issuing a child
before its parent. We update the code to apply the same logic to all yielded
revision. No tests break so we seem in the clear except where we explicitly
test the order.

diff --git a/mercurial/ancestor.py b/mercurial/ancestor.py
--- a/mercurial/ancestor.py
+++ b/mercurial/ancestor.py
@@ -309,31 +309,30 @@ class lazyancestors(object):
 revision number order. That order is also topological: a child is
 always emitted before its parent.
 
-If inclusive is True, yield all the revs first (ignoring stoprev),
-then yield all the ancestors of revs as when inclusive is False. If an
-element in revs is an ancestor of a different rev it is not yielded
-again."""
+If inclusive is True, the source revisions are also yielded. The
+reverse revision number order is still enforced."""
 seen = set()
 revs = self._initrevs
-if self._inclusive:
-for rev in revs:
-yield rev
-seen.update(revs)
 
 parentrevs = self._parentrevs
 stoprev = self._stoprev
-visit = []
-heapq.heapify(visit)
 schedule = heapq.heappush
 nextitem = heapq.heappop
 see = seen.add
 see(nullrev)
 
-for r in revs:
-for parent in parentrevs(r):
-if parent not in seen:
-schedule(visit, -parent)
-see(parent)
+if self._inclusive:
+visit = [-r for r in revs]
+seen.update(revs)
+heapq.heapify(visit)
+else:
+visit = []
+heapq.heapify(visit)
+for r in revs:
+for parent in parentrevs(r):
+if parent not in seen:
+schedule(visit, -parent)
+see(parent)
 
 while visit:
 current = -nextitem(visit)
diff --git a/tests/test-ancestor.py.out b/tests/test-ancestor.py.out
--- a/tests/test-ancestor.py.out
+++ b/tests/test-ancestor.py.out
@@ -9,10 +9,10 @@ membership: [1, 0]
 iteration:  [1, 0]
 % lazy ancestor set for [11, 13], stoprev = 0, inclusive = True
 membership: [11, 13, 7, 8, 3, 4, 1, 0]
-iteration:  [11, 13, 8, 7, 4, 3, 2, 1, 0]
+iteration:  [13, 11, 8, 7, 4, 3, 2, 1, 0]
 % lazy ancestor set for [11, 13], stoprev = 6, inclusive = False
 membership: [7, 8]
 iteration:  [8, 7]
 % lazy ancestor set for [11, 13], stoprev = 6, inclusive = True
 membership: [11, 13, 7, 8]
-iteration:  [11, 13, 8, 7]
+iteration:  [13, 11, 8, 7]
diff --git a/tests/test-revlog-ancestry.py.out 
b/tests/test-revlog-ancestry.py.out
--- a/tests/test-revlog-ancestry.py.out
+++ b/tests/test-revlog-ancestry.py.out
@@ -9,7 +9,7 @@ 6
 Ancestors of 7, including revs
 7 6 5 4 3 2 1 0 
 Ancestors of 7, 5 and 3, including revs
-7 5 3 6 4 2 1 0 
+7 6 5 4 3 2 1 0 
 
 Descendants of 5
 7 8 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 5 of 7] context: split `introrev` logic in a sub function

2018-09-07 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1536255508 14400
#  Thu Sep 06 13:38:28 2018 -0400
# Node ID f74f706f6d061cf9369cd45caa3a71d3fc03b293
# Parent  a7dba588d74f3d71c988b9a89b9591fb530a1d14
# EXP-Topic copy-perf
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
f74f706f6d06
context: split `introrev` logic in a sub function

We want to add a mechanism to stop iteration early associated to intro rev early
in some case. However, it does not make sense to expose it in the public
`filectx` API. So we split the code into an internal method instead.

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -833,7 +833,7 @@ class basefilectx(object):
 """True if a filectx have been introduced after a given floor revision
 """
 return (changelogrev <= self.linkrev()
-or changelogrev <= self.introrev())
+or changelogrev <= self._introrev())
 
 def _lazyrev(self):
 """return self.rev() if it is available without computation,
@@ -861,6 +861,9 @@ class basefilectx(object):
 'linkrev-shadowing' when a file revision is used by multiple
 changesets.
 """
+return self._introrev()
+
+def _introrev(self):
 lkr = self.linkrev()
 lazyrev = self._lazyrev()
 if lazyrev is not None:
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4462: narrow: use util.readfile() and improve error message using --narrowspec

2018-09-07 Thread pulkit (Pulkit Goyal)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG4062bbb1d10f: narrow: use util.readfile() and improve error 
message using --narrowspec (authored by pulkit, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D4462?vs=10742=10829#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4462?vs=10742=10829

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

AFFECTED FILES
  hgext/narrow/narrowcommands.py

CHANGE DETAILS

diff --git a/hgext/narrow/narrowcommands.py b/hgext/narrow/narrowcommands.py
--- a/hgext/narrow/narrowcommands.py
+++ b/hgext/narrow/narrowcommands.py
@@ -84,12 +84,12 @@
 filepath = os.path.join(pycompat.getcwd(), narrowspecfile)
 ui.status(_("reading narrowspec from '%s'\n") % filepath)
 try:
-fp = open(filepath, 'rb')
-except IOError:
-raise error.Abort(_("file '%s' not found") % filepath)
+fdata = util.readfile(filepath)
+except IOError as inst:
+raise error.Abort(_("cannot read narrowspecs from '%s': %s") %
+  (filepath, encoding.strtolocal(inst.strerror)))
 
-includes, excludes, profiles = sparse.parseconfig(ui, fp.read(),
-  'narrow')
+includes, excludes, profiles = sparse.parseconfig(ui, fdata, 'narrow')
 if profiles:
 raise error.Abort(_("cannot specify other files using '%include' 
in"
 " narrowspec"))



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


[PATCH 4 of 7] context: introduce an `isintroducedafter` method and use it in copies

2018-09-07 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1536252767 14400
#  Thu Sep 06 12:52:47 2018 -0400
# Node ID a7dba588d74f3d71c988b9a89b9591fb530a1d14
# Parent  a4c3eb6c1a36cbbf64fa8930b173154b2e77ef2b
# EXP-Topic copy-perf
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
a7dba588d74f
context: introduce an `isintroducedafter` method and use it in copies

Right now, copy tracing make effort to not traverse the graph too much to save
performance. It uses a "limit" acting as a floor revision past which data are no
longer relevant to the current copy tracing.

However, to enforce this limit, it uses a call to `filectx.rev()`, that call can
trigger a graph traversal on its own. That extra graph traversal is oblivious of
the current limit and can become very expensive. That cost is increased by the
nature of work done in adjust link rev, we are not only walking down the graph,
we are also checking the affected file for each revision we walk through.
Something significantly more expensive than the walk itself.

To work around this we need to make the `filectx` operation aware of the current
limit. The first step is to introduce a dedicated method: `isintroducedafter`.
We'll then rework that method logic to stop traversal as soon as possible.

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -829,6 +829,12 @@ class basefilectx(object):
 # result is crash somewhere else at to some point.
 return lkr
 
+def isintroducedafter(self, changelogrev):
+"""True if a filectx have been introduced after a given floor revision
+"""
+return (changelogrev <= self.linkrev()
+or changelogrev <= self.introrev())
+
 def _lazyrev(self):
 """return self.rev() if it is available without computation,
 
diff --git a/mercurial/copies.py b/mercurial/copies.py
--- a/mercurial/copies.py
+++ b/mercurial/copies.py
@@ -139,7 +139,7 @@ def _tracefile(fctx, am, limit=-1):
 for f in fctx.ancestors():
 if am.get(f.path(), None) == f.filenode():
 return f
-if limit >= 0 and f.linkrev() < limit and f.rev() < limit:
+if limit >= 0 and not f.isintroducedafter(limit):
 return None
 
 def _dirstatecopies(d, match=None):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 4] hgweb: show shortlog by default in json output (issue5978)

2018-09-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1536325966 -32400
#  Fri Sep 07 22:12:46 2018 +0900
# Node ID cd0c58017ae949408c1e746c9c81ca6847591b3c
# Parent  83dd656586b14a06b1b7e0fa57ab2a801eab3da5
hgweb: show shortlog by default in json output (issue5978)

diff --git a/mercurial/templates/json/map b/mercurial/templates/json/map
--- a/mercurial/templates/json/map
+++ b/mercurial/templates/json/map
@@ -1,4 +1,6 @@
+default = 'shortlog'
 mimetype = 'application/json'
+
 filerevision = '\{
   "node": {node|json},
   "path": {file|json},
diff --git a/tests/test-hgweb-json.t b/tests/test-hgweb-json.t
--- a/tests/test-hgweb-json.t
+++ b/tests/test-hgweb-json.t
@@ -588,6 +588,187 @@ shortlog/ shows information about a set 
 "node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7"
   }
 
+shortlog is displayed by default (issue5978)
+
+  $ request '?style=json'
+  200 Script output follows
+  
+  {
+"changeset_count": 10,
+"changesets": [
+  {
+"bookmarks": [],
+"branch": "default",
+"date": [
+  0.0,
+  0
+],
+"desc": "merge test-branch into default",
+"node": "cc725e08502a79dd1eda913760fbe06ed7a9abc7",
+"parents": [
+  "ceed296fe500c3fac9541e31dad860cb49c89e45",
+  "ed66c30e87eb65337c05a4229efaa5f1d5285a90"
+],
+"phase": "draft",
+"tags": [
+  "tip"
+],
+"user": "test"
+  },
+  {
+"bookmarks": [],
+"branch": "test-branch",
+"date": [
+  0.0,
+  0
+],
+"desc": "another commit in test-branch",
+"node": "ed66c30e87eb65337c05a4229efaa5f1d5285a90",
+"parents": [
+  "6ab967a8ab3489227a83f80e920faa039a71819f"
+],
+"phase": "draft",
+"tags": [],
+"user": "test"
+  },
+  {
+"bookmarks": [],
+"branch": "test-branch",
+"date": [
+  0.0,
+  0
+],
+"desc": "create test branch",
+"node": "6ab967a8ab3489227a83f80e920faa039a71819f",
+"parents": [
+  "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
+],
+"phase": "draft",
+"tags": [],
+"user": "test"
+  },
+  {
+"bookmarks": [
+  "bookmark2"
+],
+"branch": "default",
+"date": [
+  0.0,
+  0
+],
+"desc": "create tag2",
+"node": "ceed296fe500c3fac9541e31dad860cb49c89e45",
+"parents": [
+  "f2890a05fea49bfaf9fb27ed5490894eba32da78"
+],
+"phase": "draft",
+"tags": [],
+"user": "test"
+  },
+  {
+"bookmarks": [],
+"branch": "default",
+"date": [
+  0.0,
+  0
+],
+"desc": "another commit to da/foo",
+"node": "f2890a05fea49bfaf9fb27ed5490894eba32da78",
+"parents": [
+  "93a8ce14f89156426b7fa981af8042da53f03aa0"
+],
+"phase": "draft",
+"tags": [
+  "tag2"
+],
+"user": "test"
+  },
+  {
+"bookmarks": [],
+"branch": "default",
+"date": [
+  0.0,
+  0
+],
+"desc": "create tag",
+"node": "93a8ce14f89156426b7fa981af8042da53f03aa0",
+"parents": [
+  "78896eb0e102174ce9278438a95e12543e4367a7"
+],
+"phase": "public",
+"tags": [],
+"user": "test"
+  },
+  {
+"bookmarks": [],
+"branch": "default",
+"date": [
+  0.0,
+  0
+],
+"desc": "move foo",
+"node": "78896eb0e102174ce9278438a95e12543e4367a7",
+"parents": [
+  "8d7c456572acf3557e8ed8a07286b10c408bcec5"
+],
+"phase": "public",
+"tags": [
+  "tag1"
+],
+"user": "test"
+  },
+  {
+"bookmarks": [
+  "bookmark1"
+],
+"branch": "default",
+"date": [
+  0.0,
+  0
+],
+"desc": "modify da/foo",
+"node": "8d7c456572acf3557e8ed8a07286b10c408bcec5",
+"parents": [
+  "f8bbb9024b10f93cdbb8d940337398291d40dea8"
+],
+"phase": "public",
+"tags": [],
+"user": "test"
+  },
+  {
+"bookmarks": [],
+"branch": "default",
+"date": [
+  0.0,
+  0
+],
+"desc": "modify foo",
+"node": "f8bbb9024b10f93cdbb8d940337398291d40dea8",
+"parents": [
+  "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e"
+],
+"phase": "public",
+"tags": [],
+"user": "test"
+  },
+  {
+"bookmarks": [],
+"branch": "default",
+"date": [
+  0.0,
+  0
+],
+"desc": "initial",
+"node": "06e557f3edf66faa1ccaba5dd8c203c21cc79f1e",
+"parents": [],
+"phase": "public",
+

D4341: sparse: add local files to temporaryfiles if they exist out of sparse

2018-09-07 Thread pulkit (Pulkit Goyal)
pulkit added a comment.


  gentle ping for review. If something is missing from this patch or if there 
is a way I can make this review easy, let me know. I will be happy to do that.

REPOSITORY
  rHG Mercurial

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

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


[PATCH 6 of 7] context: introduce a `_findchangeid` method to `filectx`

2018-09-07 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1536255775 14400
#  Thu Sep 06 13:42:55 2018 -0400
# Node ID 441c39342d63c75ee101587b2fbf3af60800762f
# Parent  f74f706f6d061cf9369cd45caa3a71d3fc03b293
# EXP-Topic copy-perf
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
441c39342d63
context: introduce a `_findchangeid` method to `filectx`

In the same spirit as `_introrev` we want to introduce a way to limit graph
walking when resolving `filectx.rev()`. We introduce a new internal function for
this purpose.

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -631,16 +631,21 @@ class basefilectx(object):
 
 @propertycache
 def _changeid(self):
+return self._findchangeid()
+
+def _findchangeid(self):
 if r'_changeid' in self.__dict__:
-return self._changeid
+changeid = self._changeid
 elif r'_changectx' in self.__dict__:
-return self._changectx.rev()
+changeid = self._changectx.rev()
 elif r'_descendantrev' in self.__dict__:
 # this file context was created from a revision with a known
 # descendant, we can (lazily) correct for linkrev aliases
-return self._adjustlinkrev(self._descendantrev)
+changeid = self._adjustlinkrev(self._descendantrev)
 else:
-return self._filelog.linkrev(self._filerev)
+changeid = self._filelog.linkrev(self._filerev)
+self._changeid = changeid
+return changeid
 
 @propertycache
 def _filenode(self):
@@ -872,7 +877,7 @@ class basefilectx(object):
 else:
 return self._adjustlinkrev(lazyrev, inclusive=True)
 else:
-return self.rev()
+return self._findchangeid()
 
 def introfilectx(self):
 """Return filectx having identical contents, but pointing to the
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4502: util: allow lrucachedict to track cost of entries

2018-09-07 Thread indygreg (Gregory Szorc)
indygreg updated this revision to Diff 10832.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4502?vs=10821=10832

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

AFFECTED FILES
  contrib/perf.py
  mercurial/util.py
  tests/test-lrucachedict.py

CHANGE DETAILS

diff --git a/tests/test-lrucachedict.py b/tests/test-lrucachedict.py
--- a/tests/test-lrucachedict.py
+++ b/tests/test-lrucachedict.py
@@ -12,27 +12,33 @@
 def testsimple(self):
 d = util.lrucachedict(4)
 self.assertEqual(d.capacity, 4)
-d['a'] = 'va'
+d.insert('a', 'va', cost=2)
 d['b'] = 'vb'
 d['c'] = 'vc'
-d['d'] = 'vd'
+d.insert('d', 'vd', cost=42)
 
 self.assertEqual(d['a'], 'va')
 self.assertEqual(d['b'], 'vb')
 self.assertEqual(d['c'], 'vc')
 self.assertEqual(d['d'], 'vd')
 
+self.assertEqual(d.totalcost, 44)
+
 # 'a' should be dropped because it was least recently used.
 d['e'] = 've'
 self.assertNotIn('a', d)
-
 self.assertIsNone(d.get('a'))
+self.assertEqual(d.totalcost, 42)
 
 self.assertEqual(d['b'], 'vb')
 self.assertEqual(d['c'], 'vc')
 self.assertEqual(d['d'], 'vd')
 self.assertEqual(d['e'], 've')
 
+# Replacing item with different cost adjusts totalcost.
+d.insert('e', 've', cost=4)
+self.assertEqual(d.totalcost, 46)
+
 # Touch entries in some order (both get and set).
 d['e']
 d['c'] = 'vc2'
@@ -63,12 +69,13 @@
 
 def testcopypartial(self):
 d = util.lrucachedict(4)
-d['a'] = 'va'
-d['b'] = 'vb'
+d.insert('a', 'va', cost=4)
+d.insert('b', 'vb', cost=2)
 
 dc = d.copy()
 
 self.assertEqual(len(dc), 2)
+self.assertEqual(dc.totalcost, 6)
 for key in ('a', 'b'):
 self.assertIn(key, dc)
 self.assertEqual(dc[key], 'v%s' % key)
@@ -80,8 +87,10 @@
 
 d['c'] = 'vc'
 del d['b']
+self.assertEqual(d.totalcost, 4)
 dc = d.copy()
 self.assertEqual(len(dc), 2)
+self.assertEqual(dc.totalcost, 4)
 for key in ('a', 'c'):
 self.assertIn(key, dc)
 self.assertEqual(dc[key], 'v%s' % key)
@@ -93,7 +102,7 @@
 
 def testcopyfull(self):
 d = util.lrucachedict(4)
-d['a'] = 'va'
+d.insert('a', 'va', cost=42)
 d['b'] = 'vb'
 d['c'] = 'vc'
 d['d'] = 'vd'
@@ -104,13 +113,19 @@
 self.assertIn(key, dc)
 self.assertEqual(dc[key], 'v%s' % key)
 
+self.assertEqual(d.totalcost, 42)
+self.assertEqual(dc.totalcost, 42)
+
 # 'a' should be dropped because it was least recently used.
 dc['e'] = 've'
 self.assertNotIn('a', dc)
 for key in ('b', 'c', 'd', 'e'):
 self.assertIn(key, dc)
 self.assertEqual(dc[key], 'v%s' % key)
 
+self.assertEqual(d.totalcost, 42)
+self.assertEqual(dc.totalcost, 0)
+
 # Contents and order of original dict should remain unchanged.
 dc['b'] = 'vb_new'
 
@@ -120,25 +135,28 @@
 
 def testcopydecreasecapacity(self):
 d = util.lrucachedict(5)
-d['a'] = 'va'
-d['b'] = 'vb'
+d.insert('a', 'va', cost=4)
+d.insert('b', 'vb', cost=2)
 d['c'] = 'vc'
 d['d'] = 'vd'
 
 dc = d.copy(2)
+self.assertEqual(dc.totalcost, 0)
 for key in ('a', 'b'):
 self.assertNotIn(key, dc)
 for key in ('c', 'd'):
 self.assertIn(key, dc)
 self.assertEqual(dc[key], 'v%s' % key)
 
-dc['e'] = 've'
+dc.insert('e', 've', cost=7)
+self.assertEqual(dc.totalcost, 7)
 self.assertNotIn('c', dc)
 for key in ('d', 'e'):
 self.assertIn(key, dc)
 self.assertEqual(dc[key], 'v%s' % key)
 
 # Original should remain unchanged.
+self.assertEqual(d.totalcost, 6)
 for key in ('a', 'b', 'c', 'd'):
 self.assertIn(key, d)
 self.assertEqual(d[key], 'v%s' % key)
@@ -174,14 +192,16 @@
 
 def testpopoldest(self):
 d = util.lrucachedict(4)
-d['a'] = 'va'
-d['b'] = 'vb'
+d.insert('a', 'va', cost=10)
+d.insert('b', 'vb', cost=5)
 
 self.assertEqual(len(d), 2)
 self.assertEqual(d.popoldest(), ('a', 'va'))
 self.assertEqual(len(d), 1)
+self.assertEqual(d.totalcost, 5)
 self.assertEqual(d.popoldest(), ('b', 'vb'))
 self.assertEqual(len(d), 0)
+self.assertEqual(d.totalcost, 0)
 self.assertIsNone(d.popoldest())
 
 d['a'] = 'va'
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1209,18 +1209,21 @@
 Holds a reference to nodes on either side as well as a key-value
 pair for the 

D4371: treemanifest: use visitchildrenset when doing a walk

2018-09-07 Thread spectral (Kyle Lippincott)
spectral updated this revision to Diff 10837.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4371?vs=10549=10837

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

AFFECTED FILES
  mercurial/manifest.py

CHANGE DETAILS

diff --git a/mercurial/manifest.py b/mercurial/manifest.py
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -1036,20 +1036,22 @@
 
 def _walk(self, match):
 '''Recursively generates matching file names for walk().'''
-if not match.visitdir(self._dir[:-1] or '.'):
+visit = match.visitchildrenset(self._dir[:-1] or '.')
+if not visit:
 return
 
 # yield this dir's files and walk its submanifests
 self._load()
-self._loadalllazy()
+visit = self._loadchildrensetlazy(visit)
 for p in sorted(list(self._dirs) + list(self._files)):
 if p in self._files:
 fullp = self._subpath(p)
 if match(fullp):
 yield fullp
 else:
-for f in self._dirs[p]._walk(match):
-yield f
+if not visit or p[:-1] in visit:
+for f in self._dirs[p]._walk(match):
+yield f
 
 def matches(self, match):
 '''generate a new manifest filtered by the match argument'''



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


D4368: treemanifest: avoid unnecessary copies/processing when using alwaysmatcher

2018-09-07 Thread spectral (Kyle Lippincott)
spectral updated this revision to Diff 10834.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4368?vs=10546=10834

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

AFFECTED FILES
  mercurial/manifest.py

CHANGE DETAILS

diff --git a/mercurial/manifest.py b/mercurial/manifest.py
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -940,7 +940,7 @@
 
 def filesnotin(self, m2, match=None):
 '''Set of files in this manifest that are not in the other'''
-if match:
+if match and not match.always():
 m1 = self.matches(match)
 m2 = m2.matches(match)
 return m1.filesnotin(m2)
@@ -1085,7 +1085,7 @@
 the nodeid will be None and the flags will be the empty
 string.
 '''
-if match:
+if match and not match.always():
 m1 = self.matches(match)
 m2 = m2.matches(match)
 return m1.diff(m2, clean=clean)



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


D4369: treemanifest: avoid loading everything just to get their nodeid

2018-09-07 Thread spectral (Kyle Lippincott)
spectral updated this revision to Diff 10835.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4369?vs=10547=10835

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

AFFECTED FILES
  mercurial/manifest.py

CHANGE DETAILS

diff --git a/mercurial/manifest.py b/mercurial/manifest.py
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -1177,14 +1177,15 @@
 m1._load()
 m2._load()
 emptytree = treemanifest()
-# OPT: Do we really need to load everything? Presumably things in lazy
-# aren't dirty and don't need to be written.
-self._loadalllazy()
-m1._loadalllazy()
-m2._loadalllazy()
+def getnode(m, d):
+ld = m._lazydirs.get(d)
+if ld:
+return ld[1]
+return m._dirs.get(d, emptytree)._node
+
 for d, subm in self._dirs.iteritems():
-subp1 = m1._dirs.get(d, emptytree)._node
-subp2 = m2._dirs.get(d, emptytree)._node
+subp1 = getnode(m1, d)
+subp2 = getnode(m2, d)
 if subp1 == nullid:
 subp1, subp2 = subp2, subp1
 writesubtree(subm, subp1, subp2)



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


D4367: treemanifest: attempt to avoid loading all lazily-loaded subdirs in _isempty

2018-09-07 Thread spectral (Kyle Lippincott)
spectral updated this revision to Diff 10833.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4367?vs=10545=10833

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

AFFECTED FILES
  mercurial/manifest.py

CHANGE DETAILS

diff --git a/mercurial/manifest.py b/mercurial/manifest.py
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -726,9 +726,13 @@
 
 def _isempty(self):
 self._load() # for consistency; already loaded by all callers
+# See if we can skip loading everything.
+if self._files or (self._dirs and
+   any(not m._isempty() for m in self._dirs.values())):
+return False
 self._loadalllazy()
-return (not self._files and (not self._dirs or
-all(m._isempty() for m in self._dirs.values(
+return (not self._dirs or
+all(m._isempty() for m in self._dirs.values()))
 
 def __repr__(self):
 return ('' %



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


D4370: treemanifest: use visitchildrenset when filtering a manifest to a matcher

2018-09-07 Thread spectral (Kyle Lippincott)
spectral updated this revision to Diff 10836.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4370?vs=10548=10836

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

AFFECTED FILES
  mercurial/manifest.py

CHANGE DETAILS

diff --git a/mercurial/manifest.py b/mercurial/manifest.py
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -710,6 +710,25 @@
 self._dirs[d] = readsubtree(path, node)
 del self._lazydirs[d]
 
+def _loadchildrensetlazy(self, visit):
+if not visit:
+return None
+if visit == 'all' or visit == 'this':
+self._loadalllazy()
+return None
+
+todel = []
+for k in visit:
+kslash = k + '/'
+ld = self._lazydirs.get(kslash)
+if ld:
+path, node, readsubtree = ld
+self._dirs[kslash] = readsubtree(path, node)
+todel.append(kslash)
+for kslash in todel:
+del self._lazydirs[kslash]
+return visit
+
 def __len__(self):
 self._load()
 size = len(self._files)
@@ -1043,25 +1062,36 @@
 '''recursively generate a new manifest filtered by the match argument.
 '''
 
-visit = match.visitdir(self._dir[:-1] or '.')
+visit = match.visitchildrenset(self._dir[:-1] or '.')
 if visit == 'all':
 return self.copy()
 ret = treemanifest(self._dir)
 if not visit:
 return ret
 
 self._load()
 for fn in self._files:
+# While visitchildrenset *usually* lists only subdirs, this is
+# actually up to the matcher and may have some files in the set().
+# If visit == 'this', we should obviously look at the files in this
+# directory; if visit is a set, and fn is in it, we should inspect
+# fn (but no need to inspect things not in the set).
+if visit != 'this' and fn not in visit:
+continue
 fullp = self._subpath(fn)
+# visitchildrenset isn't perfect, we still need to call the regular
+# matcher code to further filter results.
 if not match(fullp):
 continue
 ret._files[fn] = self._files[fn]
 if fn in self._flags:
 ret._flags[fn] = self._flags[fn]
 
-# OPT: use visitchildrenset to avoid loading everything
+visit = self._loadchildrensetlazy(visit)
 self._loadalllazy()
 for dir, subm in self._dirs.iteritems():
+if visit and dir[:-1] not in visit:
+continue
 m = subm._matches(match)
 if not m._isempty():
 ret._dirs[dir] = m



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


D4429: narrow: demonstrate that widening is still broken

2018-09-07 Thread pulkit (Pulkit Goyal)
pulkit added a comment.


  Actually the tests were broken. I fixed them in 
https://www.mercurial-scm.org/repo/hg-committed/rev/83dd656586b1.

REPOSITORY
  rHG Mercurial

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

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


D4502: util: allow lrucachedict to track cost of entries

2018-09-07 Thread indygreg (Gregory Szorc)
indygreg planned changes to this revision.
indygreg added inline comments.

INLINE COMMENTS

> lothiraldan wrote in util.py:1277
> I'm not sure this line is tested, I didnd't see a test where we replace an 
> entry with an associated cost

Good catch! I'll send a revised patch.

FWIW, cost accounting on this data structure opens up a lot of potential around 
caching on revlogs. I have some alpha-quality commits to replace the full 
revision cache on the revlog with an `lrucachedict` and to add a decompressed 
chunk cache to revlogs. Such caches can speed up certain operations 
drastically. However, we need to be careful about adding always-on caches to 
revlogs because they can result in memory bloat. I was thinking about adding 
context manager methods to revlogs to temporarily activate certain aggressive 
caches in order to facilitate certain operations. e.g. a fulltext or chunk 
cache when applying delta groups could make it drastically faster to compute 
deltas during bulk insertion. A chunk cache could make reverse walks 
significantly faster. Etc. I figured you'd be interested given recent work in 
this area :)

REPOSITORY
  rHG Mercurial

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

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


Re: [PATCH 2 of 7] ancestors: ensure a consistent order even in the "inclusive" case

2018-09-07 Thread Martin von Zweigbergk via Mercurial-devel
On Fri, Sep 7, 2018 at 8:06 AM Boris Feld  wrote:

> # HG changeset patch
> # User Boris Feld 
> # Date 1536277058 14400
> #  Thu Sep 06 19:37:38 2018 -0400
> # Node ID 9a18509c522deeb62a7b244dcf4c7b79a8dc1132
> # Parent  eb80c721aea9715e23dc35cdd119428aa120ea93
> # EXP-Topic issue5979
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r
> 9a18509c522d
> ancestors: ensure a consistent order even in the "inclusive" case
>

I've queued the first two to start with. Thanks!
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] tests: stabilize test-removeemptydirs.t on Windows

2018-09-07 Thread Yuya Nishihara
On Fri, 07 Sep 2018 00:27:43 -0400, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison 
> # Date 1536291444 14400
> #  Thu Sep 06 23:37:24 2018 -0400
> # Node ID e5449ff273d68abd3fd4e7b5766fb6d22edf30b7
> # Parent  7df9ae38c75ca7fd4d0d20802fbc4ab489bb1f06
> tests: stabilize test-removeemptydirs.t on Windows

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


Re: D4477: merge: move purge logic from extension

2018-09-07 Thread Yuya Nishihara
Queued the series, thanks.

> +matcher = scmutil.match(repo[None], dirs or (), {
> +'include': opts.get('include'),
> +'exclude': opts.get('exclude')})
>  
> -match = scmutil.match(repo[None], dirs, opts)

Restored the original `match` construction, which looks simpler.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4477: merge: move purge logic from extension

2018-09-07 Thread yuja (Yuya Nishihara)
yuja added a comment.


  Queued the series, thanks.
  
  > +matcher = scmutil.match(repo[None], dirs or (), {
  >  +'include': opts.get('include'),
  >  +'exclude': opts.get('exclude')})
  > 
  > - match = scmutil.match(repo[None], dirs, opts)
  
  Restored the original `match` construction, which looks simpler.

REPOSITORY
  rHG Mercurial

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

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


D4477: merge: move purge logic from extension

2018-09-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG7fea205fd5dc: merge: move purge logic from extension 
(authored by indygreg, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D4477?vs=10825=10827#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4477?vs=10825=10827

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

AFFECTED FILES
  hgext/purge.py
  mercurial/merge.py

CHANGE DETAILS

diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -9,6 +9,7 @@
 
 import errno
 import hashlib
+import os
 import shutil
 import struct
 
@@ -2240,3 +2241,71 @@
 # fix up dirstate for copies and renames
 copies.duplicatecopies(repo, repo[None], ctx.rev(), pctx.rev())
 return stats
+
+def purge(repo, matcher, ignored=False, removeemptydirs=True,
+  removefiles=True, abortonerror=False, noop=False):
+"""Purge the working directory of untracked files.
+
+``matcher`` is a matcher configured to scan the working directory -
+potentially a subset.
+
+``ignored`` controls whether ignored files should also be purged.
+
+``removeemptydirs`` controls whether empty directories should be removed.
+
+``removefiles`` controls whether files are removed.
+
+``abortonerror`` causes an exception to be raised if an error occurs
+deleting a file or directory.
+
+``noop`` controls whether to actually remove files. If not defined, actions
+will be taken.
+
+Returns an iterable of relative paths in the working directory that were
+or would be removed.
+"""
+
+def remove(removefn, path):
+try:
+removefn(repo.wvfs.join(path))
+except OSError:
+m = _('%s cannot be removed') % path
+if abortonerror:
+raise error.Abort(m)
+else:
+repo.ui.warn(_('warning: %s\n') % m)
+
+# There's no API to copy a matcher. So mutate the passed matcher and
+# restore it when we're done.
+oldexplicitdir = matcher.explicitdir
+oldtraversedir = matcher.traversedir
+
+res = []
+
+try:
+if removeemptydirs:
+directories = []
+matcher.explicitdir = matcher.traversedir = directories.append
+
+status = repo.status(match=matcher, ignored=ignored, unknown=True)
+
+if removefiles:
+for f in sorted(status.unknown + status.ignored):
+if not noop:
+repo.ui.note(_('removing file %s\n') % f)
+remove(util.unlink, f)
+res.append(f)
+
+if removeemptydirs:
+for f in sorted(directories, reverse=True):
+if matcher(f) and not os.listdir(repo.wvfs.join(f)):
+if not noop:
+repo.ui.note(_('removing directory %s\n') % f)
+remove(os.rmdir, f)
+res.append(f)
+
+return res
+
+finally:
+matcher.explicitdir = oldexplicitdir
+matcher.traversedir = oldtraversedir
diff --git a/hgext/purge.py b/hgext/purge.py
--- a/hgext/purge.py
+++ b/hgext/purge.py
@@ -25,16 +25,13 @@
 '''command to delete untracked files from the working directory'''
 from __future__ import absolute_import
 
-import os
-
 from mercurial.i18n import _
 from mercurial import (
 cmdutil,
-error,
+merge as mergemod,
 pycompat,
 registrar,
 scmutil,
-util,
 )
 
 cmdtable = {}
@@ -86,44 +83,28 @@
 option.
 '''
 opts = pycompat.byteskwargs(opts)
+
 act = not opts.get('print')
 eol = '\n'
 if opts.get('print0'):
 eol = '\0'
 act = False # --print0 implies --print
+
 removefiles = opts.get('files')
 removedirs = opts.get('dirs')
+
 if not removefiles and not removedirs:
 removefiles = True
 removedirs = True
 
-def remove(remove_func, name):
-if act:
-try:
-remove_func(repo.wjoin(name))
-except OSError:
-m = _('%s cannot be removed') % name
-if opts.get('abort_on_err'):
-raise error.Abort(m)
-ui.warn(_('warning: %s\n') % m)
-else:
-ui.write('%s%s' % (name, eol))
+match = scmutil.match(repo[None], dirs, opts)
 
-match = scmutil.match(repo[None], dirs, opts)
-if removedirs:
-directories = []
-match.explicitdir = match.traversedir = directories.append
-status = repo.status(match=match, ignored=opts.get('all'), unknown=True)
+paths = mergemod.purge(
+repo, match, ignored=opts.get('all', False),
+removeemptydirs=removedirs, removefiles=removefiles,
+abortonerror=opts.get('abort_on_err'),
+noop=not act)
 
-if removefiles:
-for f in sorted(status.unknown + status.ignored):
-if act:
-  

D4478: merge: use vfs methods for I/O

2018-09-07 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG3dd34b401bc2: merge: use vfs methods for I/O (authored by 
indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4478?vs=10826=10828

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

AFFECTED FILES
  mercurial/merge.py
  mercurial/vfs.py

CHANGE DETAILS

diff --git a/mercurial/vfs.py b/mercurial/vfs.py
--- a/mercurial/vfs.py
+++ b/mercurial/vfs.py
@@ -213,6 +213,10 @@
 """
 return util.removedirs(self.join(path))
 
+def rmdir(self, path=None):
+"""Remove an empty directory."""
+return os.rmdir(self.join(path))
+
 def rmtree(self, path=None, ignore_errors=False, forcibly=False):
 """Remove a directory tree recursively
 
diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -9,7 +9,6 @@
 
 import errno
 import hashlib
-import os
 import shutil
 import struct
 
@@ -2267,7 +2266,7 @@
 
 def remove(removefn, path):
 try:
-removefn(repo.wvfs.join(path))
+removefn(path)
 except OSError:
 m = _('%s cannot be removed') % path
 if abortonerror:
@@ -2293,15 +2292,15 @@
 for f in sorted(status.unknown + status.ignored):
 if not noop:
 repo.ui.note(_('removing file %s\n') % f)
-remove(util.unlink, f)
+remove(repo.wvfs.unlink, f)
 res.append(f)
 
 if removeemptydirs:
 for f in sorted(directories, reverse=True):
-if matcher(f) and not os.listdir(repo.wvfs.join(f)):
+if matcher(f) and not repo.wvfs.listdir(f):
 if not noop:
 repo.ui.note(_('removing directory %s\n') % f)
-remove(os.rmdir, f)
+remove(repo.wvfs.rmdir, f)
 res.append(f)
 
 return res



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


[Bug 5983] New: `hg pull` resulting in "RevlogError: missing processor for flag '0x2000'"

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

Bug ID: 5983
   Summary: `hg pull` resulting in "RevlogError: missing processor
for flag '0x2000'"
   Product: Mercurial
   Version: stable branch
  Hardware: PC
OS: Linux
Status: UNCONFIRMED
  Severity: feature
  Priority: wish
 Component: Mercurial
  Assignee: bugzi...@mercurial-scm.org
  Reporter: 7895pul...@gmail.com
CC: mercurial-devel@mercurial-scm.org

I was testing the stable branch on our internal repository to ship a new
version of core mercurial and I got the following traceback.

```
$ hg init emptyrepo
$ cd emptyrepo
$ hg pull serverrepo --config experimental.changegroup3=True --config
experimental.format.compression=zstd
pulling from server-repo
requesting all changes
adding changesets
adding manifests
adding file changes 
transaction abort!  
rollback completed

Traceback (most recent call last): 
   
   [13/410]
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/scmutil.py", line
161, in callcatch
return func()
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/dispatch.py", line
345, in _runcatchfunc
return _dispatch(req)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/dispatch.py", line
1003, in _dispatch
cmdpats, cmdoptions)
  File "/storage/pulkit/arcadia/contrib/python/hg/hgext/journal.py", line 90,
in runcommand
return orig(lui, repo, cmd, fullargs, *args)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/dispatch.py", line
733, in runcommand
ret = _runcommand(ui, options, cmd, d)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/dispatch.py", line
1011, in _runcommand
return cmdfunc()
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/dispatch.py", line
1000, in 
d = lambda: util.checksignature(func)(ui, *args, **strcmdopt)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/util.py", line
1528, in check
return func(*args, **kwargs)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/util.py", line
1528, in check
return func(*args, **kwargs)
  File "/storage/pulkit/evolve/hgext3rd/evolve/__init__.py", line 797, in
warnobserrors
return orig(ui, repo, *args, **kwargs)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/util.py", line
1528, in check
return func(*args, **kwargs)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/util.py", line
1528, in check
return func(*args, **kwargs)
  File "/storage/pulkit/evolve/hgext3rd/evolve/__init__.py", line 773, in
wrapmayobsoletewc
res = origfn(ui, repo, *args, **opts)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/util.py", line
1528, in check
return func(*args, **kwargs)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/util.py", line
1528, in check
return func(*args, **kwargs)
  File "/storage/pulkit/arcadia/contrib/python/hg/hgext/rebase.py", line 1820,
in pullrebase
ret = orig(ui, repo, *args, **opts)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/util.py", line
1528, in check
return func(*args, **kwargs)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/commands.py", line
4214, in pull
opargs=pullopargs).cgresult
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/exchange.py", line
1489, in pull
_fullpullbundle2(repo, pullop)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/exchange.py", line
1429, in _fullpullbundle2
_pullbundle2(pullop)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/exchange.py", line
1672, in _pullbundle2
bundle2.processbundle(pullop.repo, bundle, op=op)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/bundle2.py", line
460, in processbundle
processparts(repo, op, unbundler)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/bundle2.py", line
467, in processparts
_processpart(op, part)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/bundle2.py", line
534, in _processpart
handler(op, part)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/bundle2.py", line
1805, in handlechangegroup
expectedtotal=nbchangesets, **extrakwargs)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/bundle2.py", line
470, in _processchangegroup
ret = cg.apply(op.repo, tr, source, url, **kwargs)
  File "/storage/pulkit/arcadia/contrib/python/hg/mercurial/changegroup.py",
line 338, in apply
repo, self, revmap, trp, efiles, needfiles)
  File 

D4370: treemanifest: use visitchildrenset when filtering a manifest to a matcher

2018-09-07 Thread spectral (Kyle Lippincott)
spectral updated this revision to Diff 10838.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4370?vs=10836=10838

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

AFFECTED FILES
  mercurial/manifest.py

CHANGE DETAILS

diff --git a/mercurial/manifest.py b/mercurial/manifest.py
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -710,6 +710,25 @@
 self._dirs[d] = readsubtree(path, node)
 del self._lazydirs[d]
 
+def _loadchildrensetlazy(self, visit):
+if not visit:
+return None
+if visit == 'all' or visit == 'this':
+self._loadalllazy()
+return None
+
+todel = []
+for k in visit:
+kslash = k + '/'
+ld = self._lazydirs.get(kslash)
+if ld:
+path, node, readsubtree = ld
+self._dirs[kslash] = readsubtree(path, node)
+todel.append(kslash)
+for kslash in todel:
+del self._lazydirs[kslash]
+return visit
+
 def __len__(self):
 self._load()
 size = len(self._files)
@@ -1043,25 +1062,35 @@
 '''recursively generate a new manifest filtered by the match argument.
 '''
 
-visit = match.visitdir(self._dir[:-1] or '.')
+visit = match.visitchildrenset(self._dir[:-1] or '.')
 if visit == 'all':
 return self.copy()
 ret = treemanifest(self._dir)
 if not visit:
 return ret
 
 self._load()
 for fn in self._files:
+# While visitchildrenset *usually* lists only subdirs, this is
+# actually up to the matcher and may have some files in the set().
+# If visit == 'this', we should obviously look at the files in this
+# directory; if visit is a set, and fn is in it, we should inspect
+# fn (but no need to inspect things not in the set).
+if visit != 'this' and fn not in visit:
+continue
 fullp = self._subpath(fn)
+# visitchildrenset isn't perfect, we still need to call the regular
+# matcher code to further filter results.
 if not match(fullp):
 continue
 ret._files[fn] = self._files[fn]
 if fn in self._flags:
 ret._flags[fn] = self._flags[fn]
 
-# OPT: use visitchildrenset to avoid loading everything
-self._loadalllazy()
+visit = self._loadchildrensetlazy(visit)
 for dir, subm in self._dirs.iteritems():
+if visit and dir[:-1] not in visit:
+continue
 m = subm._matches(match)
 if not m._isempty():
 ret._dirs[dir] = m



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


[PATCH 1 of 2] ancestor: add test showing inconsistency between __iter__ and __contains__

2018-09-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1536371322 -32400
#  Sat Sep 08 10:48:42 2018 +0900
# Node ID ebcd7abf0d144fb657b90126a1e30d13eefeb364
# Parent  a60dae060bc83e773bdbafb2432bc4cf387ebce2
ancestor: add test showing inconsistency between __iter__ and __contains__

diff --git a/tests/test-ancestor.py b/tests/test-ancestor.py
--- a/tests/test-ancestor.py
+++ b/tests/test-ancestor.py
@@ -215,6 +215,11 @@ def test_lazyancestors():
 s = genlazyancestors([11, 13], stoprev=6, inclusive=True)
 printlazyancestors(s, [11, 13, 7, 9, 8, 3, 6, 4, 1, -1, 0])
 
+# Test with stoprev >= min(initrevs)
+s = genlazyancestors([11, 13], stoprev=11, inclusive=True)
+printlazyancestors(s, [11, 13, 7, 9, 8, 3, 6, 4, 1, -1, 0])
+s = genlazyancestors([11, 13], stoprev=12, inclusive=True)
+printlazyancestors(s, [11, 13, 7, 9, 8, 3, 6, 4, 1, -1, 0])
 
 # The C gca algorithm requires a real repo. These are textual descriptions of
 # DAGs that have been known to be problematic, and, optionally, known pairs
diff --git a/tests/test-ancestor.py.out b/tests/test-ancestor.py.out
--- a/tests/test-ancestor.py.out
+++ b/tests/test-ancestor.py.out
@@ -16,3 +16,9 @@ iteration:  [8, 7]
 % lazy ancestor set for [11, 13], stoprev = 6, inclusive = True
 membership: [11, 13, 7, 8]
 iteration:  [13, 11, 8, 7]
+% lazy ancestor set for [11, 13], stoprev = 11, inclusive = True
+membership: [11, 13]
+iteration:  [13, 11]
+% lazy ancestor set for [11, 13], stoprev = 12, inclusive = True
+membership: [11, 13]
+iteration:  [13]
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 2 of 2] ancestor: filter out initial revisions lower than stoprev

2018-09-07 Thread Martin von Zweigbergk via Mercurial-devel
Good catch. However, I think the docstring needs updating. I think it
explicitly said that inclusive mode emits the initial revs ignoring
stoprev. Will that still be the case after this patch? I'm on mobile right
now and too lazy to confirm, but hopefully I'm remembering it right.

On Fri, Sep 7, 2018, 19:54 Yuya Nishihara  wrote:

> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1536371964 -32400
> #  Sat Sep 08 10:59:24 2018 +0900
> # Node ID 4894b3cdd4c03bb5579bb47f4f51a9410716df84
> # Parent  ebcd7abf0d144fb657b90126a1e30d13eefeb364
> ancestor: filter out initial revisions lower than stoprev
>
> diff --git a/mercurial/ancestor.py b/mercurial/ancestor.py
> --- a/mercurial/ancestor.py
> +++ b/mercurial/ancestor.py
> @@ -273,7 +273,7 @@ class lazyancestors(object):
>
>  Result does not include the null revision."""
>  self._parentrevs = pfunc
> -self._initrevs = revs
> +self._initrevs = revs = [r for r in revs if r >= stoprev]
>  self._stoprev = stoprev
>  self._inclusive = inclusive
>
> diff --git a/tests/test-ancestor.py.out b/tests/test-ancestor.py.out
> --- a/tests/test-ancestor.py.out
> +++ b/tests/test-ancestor.py.out
> @@ -20,5 +20,5 @@ iteration:  [13, 11, 8, 7]
>  membership: [11, 13]
>  iteration:  [13, 11]
>  % lazy ancestor set for [11, 13], stoprev = 12, inclusive = True
> -membership: [11, 13]
> +membership: [13]
>  iteration:  [13]
> ___
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 2 of 2] ancestor: filter out initial revisions lower than stoprev

2018-09-07 Thread Yuya Nishihara
On Fri, 7 Sep 2018 20:49:32 -0700, Martin von Zweigbergk wrote:
> Good catch. However, I think the docstring needs updating. I think it
> explicitly said that inclusive mode emits the initial revs ignoring
> stoprev.

That part was for __iter__(), and was rewritten by Boris' patch. The top-level
doc says:

 - inclusive is a boolean that indicates whether (init)revs should be included
 - revs lower than stoprev will not be generated
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4371: treemanifest: use visitchildrenset when doing a walk

2018-09-07 Thread spectral (Kyle Lippincott)
spectral updated this revision to Diff 10839.
spectral edited the summary of this revision.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4371?vs=10837=10839

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

AFFECTED FILES
  mercurial/manifest.py

CHANGE DETAILS

diff --git a/mercurial/manifest.py b/mercurial/manifest.py
--- a/mercurial/manifest.py
+++ b/mercurial/manifest.py
@@ -1036,20 +1036,22 @@
 
 def _walk(self, match):
 '''Recursively generates matching file names for walk().'''
-if not match.visitdir(self._dir[:-1] or '.'):
+visit = match.visitchildrenset(self._dir[:-1] or '.')
+if not visit:
 return
 
 # yield this dir's files and walk its submanifests
 self._load()
-self._loadalllazy()
+visit = self._loadchildrensetlazy(visit)
 for p in sorted(list(self._dirs) + list(self._files)):
 if p in self._files:
 fullp = self._subpath(p)
 if match(fullp):
 yield fullp
 else:
-for f in self._dirs[p]._walk(match):
-yield f
+if not visit or p[:-1] in visit:
+for f in self._dirs[p]._walk(match):
+yield f
 
 def matches(self, match):
 '''generate a new manifest filtered by the match argument'''



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


[PATCH 2 of 2] ancestor: filter out initial revisions lower than stoprev

2018-09-07 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1536371964 -32400
#  Sat Sep 08 10:59:24 2018 +0900
# Node ID 4894b3cdd4c03bb5579bb47f4f51a9410716df84
# Parent  ebcd7abf0d144fb657b90126a1e30d13eefeb364
ancestor: filter out initial revisions lower than stoprev

diff --git a/mercurial/ancestor.py b/mercurial/ancestor.py
--- a/mercurial/ancestor.py
+++ b/mercurial/ancestor.py
@@ -273,7 +273,7 @@ class lazyancestors(object):
 
 Result does not include the null revision."""
 self._parentrevs = pfunc
-self._initrevs = revs
+self._initrevs = revs = [r for r in revs if r >= stoprev]
 self._stoprev = stoprev
 self._inclusive = inclusive
 
diff --git a/tests/test-ancestor.py.out b/tests/test-ancestor.py.out
--- a/tests/test-ancestor.py.out
+++ b/tests/test-ancestor.py.out
@@ -20,5 +20,5 @@ iteration:  [13, 11, 8, 7]
 membership: [11, 13]
 iteration:  [13, 11]
 % lazy ancestor set for [11, 13], stoprev = 12, inclusive = True
-membership: [11, 13]
+membership: [13]
 iteration:  [13]
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 2] tests: conditionalize an error message about unlinking a non empty directory

2018-09-07 Thread Matt Harbison
# HG changeset patch
# User Matt Harbison 
# Date 1536377989 14400
#  Fri Sep 07 23:39:49 2018 -0400
# Node ID cf6130dd324b0eed4c902b45df503be429fe413f
# Parent  a60dae060bc83e773bdbafb2432bc4cf387ebce2
tests: conditionalize an error message about unlinking a non empty directory

The message on Windows comes from win32.unlink().  It looks like os.unlink() on
posix platforms is a simple call to unlink(3), which turns into unlinkat(2).
Since there's a comment in one of the tests that the message should be improved,
I don't think it's worth adding a check in win32.unlink() to see if it's empty,
if that function is always going to fail on a directory.  (It seems like the
POSIX spec allows unlinking directories though.)

diff --git a/tests/test-merge1.t b/tests/test-merge1.t
--- a/tests/test-merge1.t
+++ b/tests/test-merge1.t
@@ -30,7 +30,8 @@ of the files in a commit we're updating 
 
   $ mkdir b && touch b/nonempty
   $ hg up
-  abort: Directory not empty: '$TESTTMP/t/b'
+  abort: Unlinking directory not permitted: '$TESTTMP/t/b' (windows !)
+  abort: Directory not empty: '$TESTTMP/t/b' (no-windows !)
   [255]
   $ hg ci
   abort: last update was interrupted
diff --git a/tests/test-update-names.t b/tests/test-update-names.t
--- a/tests/test-update-names.t
+++ b/tests/test-update-names.t
@@ -50,7 +50,8 @@ make sure that this does not erase untra
   $ hg st
   ? name/file
   $ hg up 1
-  abort: Directory not empty: '$TESTTMP/r1/r2/name'
+  abort: Unlinking directory not permitted: '$TESTTMP/r1/r2/name' (windows !)
+  abort: Directory not empty: '$TESTTMP/r1/r2/name' (no-windows !)
   [255]
   $ cat name/file
   text
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 2] tests: disable test-nointerrupt on Windows

2018-09-07 Thread Matt Harbison
# HG changeset patch
# User Matt Harbison 
# Date 1536378882 14400
#  Fri Sep 07 23:54:42 2018 -0400
# Node ID 348ed11ba7406045a33d2e99834a341dfad6f57a
# Parent  cf6130dd324b0eed4c902b45df503be429fe413f
tests: disable test-nointerrupt on Windows

Per the followup discussion[1].  proc.send_signal(INT) in timeout.py raises a
ValueError because of an unsupported signal.  I don't like missing test coverage
for this on Windows.  But this is the last test failing on Windows, and red all
the time hides new failures.

[1] https://phab.mercurial-scm.org/D3716

diff --git a/tests/test-nointerrupt.t b/tests/test-nointerrupt.t
--- a/tests/test-nointerrupt.t
+++ b/tests/test-nointerrupt.t
@@ -1,3 +1,5 @@
+#require no-windows
+
 Dummy extension simulating unsafe long running command
   $ cat > sleepext.py < import itertools
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel