Re: [PATCH 6 of 6 py3] commands: make sure using byteschr rather than ascii values

2017-03-16 Thread Pulkit Goyal
On Thu, Mar 16, 2017 at 10:14 AM, Martin von Zweigbergk <
martinv...@google.com> wrote:

> On Wed, Mar 15, 2017 at 9:13 PM, Pulkit Goyal <7895pul...@gmail.com>
> wrote:
> > # HG changeset patch
> > # User Pulkit Goyal <7895pul...@gmail.com>
> > # Date 1489635793 -19800
> > #  Thu Mar 16 09:13:13 2017 +0530
> > # Node ID 63aeb39b5802644ae99eaa5cf0666f3bf5cc4e90
> > # Parent  b5673a08993652a92c0e20a4e24d842194872454
> > commands: make sure using byteschr rather than ascii values
> >
> > 'MAR!?IC' is converted to their ascii values when slicing through it.
> This
> > patch converts them back to bytes string.
> >
> > diff -r b5673a089936 -r 63aeb39b5802 mercurial/commands.py
> > --- a/mercurial/commands.py Thu Mar 16 09:00:27 2017 +0530
> > +++ b/mercurial/commands.py Thu Mar 16 09:13:13 2017 +0530
> > @@ -4768,6 +4768,8 @@
> >  showchar = not opts.get('no_status')
> >
> >  for state, char, files in changestates:
> > +if pycompat.ispy3:
> > +char = bytes([char])
>
> I'd prefer to wrap 'MAR!?C' in pycompat.iterbytestr() to avoid the
> conditional here. What do you think?. Would that work?


​I am not sure about how you are saying to that. Using pycompat.iterbytes()
we can iterate on 'MAR!?C', but in these we are iterating over three things
at once.​
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 3 py3] context: explicitly evaluate list returned by map

2017-03-16 Thread Pulkit Goyal
# HG changeset patch
# User Pulkit Goyal <7895pul...@gmail.com>
# Date 1489639281 -19800
#  Thu Mar 16 10:11:21 2017 +0530
# Node ID 8d85d7ca9fd3eea90a2f09c7d471fc3f3c78d430
# Parent  de18c43f8ce17d52542e6df233e809b6a6ee0a07
context: explicitly evaluate list returned by map

On python 3, map returns an iterator so we need to convert it to list before
finding the len or subscripting it.

After this `hg status --all` works on Python 3.

diff -r de18c43f8ce1 -r 8d85d7ca9fd3 mercurial/context.py
--- a/mercurial/context.py  Thu Mar 16 10:10:00 2017 +0530
+++ b/mercurial/context.py  Thu Mar 16 10:11:21 2017 +0530
@@ -622,7 +622,7 @@
 n2 = c2._node
 if n2 is None:
 n2 = c2._parents[0]._node
-cahs = self._repo.changelog.commonancestorsheads(self._node, n2)
+cahs = list(self._repo.changelog.commonancestorsheads(self._node, n2))
 if not cahs:
 anc = nullid
 elif len(cahs) == 1:
diff -r de18c43f8ce1 -r 8d85d7ca9fd3 mercurial/util.py
--- a/mercurial/util.py Thu Mar 16 10:10:00 2017 +0530
+++ b/mercurial/util.py Thu Mar 16 10:11:21 2017 +0530
@@ -2920,7 +2920,7 @@
 del dirs[base]
 
 def __iter__(self):
-return self._dirs.iterkeys()
+return iter(self._dirs)
 
 def __contains__(self, d):
 return d in self._dirs
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 3 py3] commands: convert opts back to bytes for status

2017-03-16 Thread Pulkit Goyal
# HG changeset patch
# User Pulkit Goyal <7895pul...@gmail.com>
# Date 1489639200 -19800
#  Thu Mar 16 10:10:00 2017 +0530
# Node ID de18c43f8ce17d52542e6df233e809b6a6ee0a07
# Parent  47dae3bbf8560824743293870aab601da2d1ed6c
commands: convert opts back to bytes for status

diff -r 47dae3bbf856 -r de18c43f8ce1 mercurial/commands.py
--- a/mercurial/commands.py Thu Mar 16 10:01:12 2017 +0530
+++ b/mercurial/commands.py Thu Mar 16 10:10:00 2017 +0530
@@ -4720,6 +4720,7 @@
 Returns 0 on success.
 """
 
+opts = pycompat.byteskwargs(opts)
 revs = opts.get('rev')
 change = opts.get('change')
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 3 py3] error: convert the error into strings to pass into ui.warn()

2017-03-16 Thread Pulkit Goyal
# HG changeset patch
# User Pulkit Goyal <7895pul...@gmail.com>
# Date 1489638672 -19800
#  Thu Mar 16 10:01:12 2017 +0530
# Node ID 47dae3bbf8560824743293870aab601da2d1ed6c
# Parent  63aeb39b5802644ae99eaa5cf0666f3bf5cc4e90
error: convert the error into strings to pass into ui.warn()

diff -r 63aeb39b5802 -r 47dae3bbf856 mercurial/scmutil.py
--- a/mercurial/scmutil.py  Thu Mar 16 09:13:13 2017 +0530
+++ b/mercurial/scmutil.py  Thu Mar 16 10:01:12 2017 +0530
@@ -168,7 +168,8 @@
 if inst.hint:
 ui.warn('(%s)\n' % inst.hint)
 except error.RepoError as inst:
-ui.warn(_("abort: %s!\n") % inst)
+if inst.args:
+ui.warn(_("abort: %s!\n") % ''.join(inst.args))
 if inst.hint:
 ui.warn(_("(%s)\n") % inst.hint)
 except error.ResponseError as inst:
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 7 of 7] test: add a basic 'test-check-pylint.t'

2017-03-16 Thread Pierre-Yves David



On 03/15/2017 10:13 AM, Kevin Bullock wrote:

On Mar 15, 2017, at 11:35, Gregory Szorc  wrote:

On Mar 15, 2017, at 07:56, Kevin Bullock  
wrote:


On Mar 15, 2017, at 02:01, Pierre-Yves David  
wrote:

# HG changeset patch
# User Pierre-Yves David 
# Date 1482964970 -3600
#  Wed Dec 28 23:42:50 2016 +0100
# Node ID e1b0b1909c43858ff4b4e1821afbee9626c4cf0f
# Parent  b24451e8f9a6beee5501e9bedc47af7edc283ea4
# EXP-Topic check-pylint
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r e1b0b1909c43
test: add a basic 'test-check-pylint.t'

We add a minimal check using pylint for one case we knows we care about:
"mutable default" argument.

We'll likely extend this over time to cover other useful checks but this is a
good starting point.


I had to dig a bit to convince myself that pyflakes, which we already 
integrated, won't catch this. It indeed will not, so this LGTM. Copy-edited the 
new test and pushed.


We may want to look into flake8. It wraps the popular linters in a single 
interface and is quite nice.

The downside for our use case is that output will be different unless all the 
linters it wraps are present.


Will flake8 also run pylint? I thought it was only pep8 + pyflakes.

There are also a number of ways our style differs from PEP8, so that piece in 
particular wouldn't get us much over this one, where we now have both 
test-check-pyflakes.t and test-check-pylint.t. Worth considering, though, in 
the (very likely) case others know more than I do about flake8's capabilities.


flake8 is run on the evolve extension (I think credit goes to Sean for 
the initial idea). Our style is quite far away from PEP8 so I've 
disabled a fair amount of message, but it still catch many useful thing.


* evolve flake8 tests: 
https://www.mercurial-scm.org/repo/evolve/file/tip/tests/test-check-flake8.t


* evolve flake8 config: 
https://www.mercurial-scm.org/repo/evolve/file/tip/setup.cfg


Cheers,

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


[PATCH 5 of 8] hgweb: explicitly tests for None in webutil

2017-03-16 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1489615809 25200
#  Wed Mar 15 15:10:09 2017 -0700
# Node ID 1596b4613bec63db08c0d4d10e3f26f5635ce21b
# Parent  83112ff862072df863540c8c9356f64eb26faa41
# EXP-Topic mutable-default
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 1596b4613bec
hgweb: explicitly tests for None in webutil

Changeset d2878bec55bd removed the mutable default value, but did not explicitly
tested for None. Such implicit testing can introduce semantic and performance
issue. We move to an explicit testing for None as recommended by PEP8:

https://www.python.org/dev/peps/pep-0008/#programming-recommendations

diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -143,7 +143,9 @@ class filerevnav(revnav):
 
 class _siblings(object):
 def __init__(self, siblings=None, hiderev=None):
-self.siblings = [s for s in siblings or [] if s.node() != nullid]
+if siblings is None:
+siblings = []
+self.siblings = [s for s in siblings if s.node() != nullid]
 if len(self.siblings) == 1 and self.siblings[0].rev() == hiderev:
 self.siblings = []
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 8] rebase: explicitly tests for None

2017-03-16 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1489615423 25200
#  Wed Mar 15 15:03:43 2017 -0700
# Node ID 6c6d8c0cc67de1ecd744a30889419510aa2064d2
# Parent  361bccce566afe250c8d258f770a908713b2d13f
# EXP-Topic mutable-default
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 6c6d8c0cc67d
rebase: explicitly tests for None

Changeset 361bccce566a removed the mutable default value, but did not explicitly
tested for None. Such implicit checking can introduce semantic and performance
issue. We move to an explicit check for None as recommended by PEP8:

https://www.python.org/dev/peps/pep-0008/#programming-recommendations

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -725,7 +725,8 @@ def _definesets(ui, repo, destf=None, sr
 destspace=None):
 """use revisions argument to define destination and rebase set
 """
-revf = revf or []
+if revf is None:
+revf = []
 
 # destspace is here to work around issues with `hg pull --rebase` see
 # issue5214 for details
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 8] mq: explicitly tests for None

2017-03-16 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1489615554 25200
#  Wed Mar 15 15:05:54 2017 -0700
# Node ID 27d5ab143c3344006509c5a3b29e2cb66445aa04
# Parent  6d73a06abb85612fca7231fb71f245f82f7d6863
# EXP-Topic mutable-default
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 27d5ab143c33
mq: explicitly tests for None

Changeset fd3d8eb7f545 removed the mutable default value, but did not explicitly
tested for None. Such implicit testing can introduce semantic and performance
issue. We move to an explicit testing for None as recommended by PEP8:

https://www.python.org/dev/peps/pep-0008/#programming-recommendations

diff --git a/hgext/mq.py b/hgext/mq.py
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -722,7 +722,8 @@ class queue(object):
 
 def printdiff(self, repo, diffopts, node1, node2=None, files=None,
   fp=None, changes=None, opts=None):
-opts = opts or {}
+if opts is None:
+opts = {}
 stat = opts.get('stat')
 m = scmutil.match(repo[node1], files, opts)
 cmdutil.diffordiffstat(self.ui, repo, diffopts, node1, node2,  m,
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 6 of 8] hgweb: explicitly tests for None

2017-03-16 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1489615864 25200
#  Wed Mar 15 15:11:04 2017 -0700
# Node ID 28093cead8791382a984b4c80dcedbe529ea7c41
# Parent  1596b4613bec63db08c0d4d10e3f26f5635ce21b
# EXP-Topic mutable-default
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 28093cead879
hgweb: explicitly tests for None

Changeset 7dafa8d0e006 removed the mutable default value, but did not explicitly
tested for None. Such implicit testing can introduce semantic and performance
issue. We move to an explicit testing for None as recommended by PEP8:

https://www.python.org/dev/peps/pep-0008/#programming-recommendations

diff --git a/mercurial/hgweb/common.py b/mercurial/hgweb/common.py
--- a/mercurial/hgweb/common.py
+++ b/mercurial/hgweb/common.py
@@ -96,7 +96,9 @@ class ErrorResponse(Exception):
 message = _statusmessage(code)
 Exception.__init__(self, message)
 self.code = code
-self.headers = headers or []
+if headers is None:
+headers = []
+self.headers = headers
 
 class continuereader(object):
 def __init__(self, f, write):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 8] util: explicitly tests for None

2017-03-16 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1489615634 25200
#  Wed Mar 15 15:07:14 2017 -0700
# Node ID 6d73a06abb85612fca7231fb71f245f82f7d6863
# Parent  6c6d8c0cc67de1ecd744a30889419510aa2064d2
# EXP-Topic mutable-default
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 6d73a06abb85
util: explicitly tests for None

Changeset 8b6927eb7efd removed the mutable default value, but did not explicitly
tested for None. Such implicit checking can introduce semantic and performance
issue. We move to an explicit check for None as recommended by PEP8:

https://www.python.org/dev/peps/pep-0008/#programming-recommendations

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1830,7 +1830,8 @@ def parsetimezone(s):
 def strdate(string, format, defaults=None):
 """parse a localized time string and return a (unixtime, offset) tuple.
 if the string cannot be parsed, ValueError is raised."""
-defaults = defaults or []
+if defaults is None:
+defaults = []
 
 # NOTE: unixtime = localunixtime + offset
 offset, date = parsetimezone(string)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 7 of 8] filemerge: explicitly tests for None

2017-03-16 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1489615912 25200
#  Wed Mar 15 15:11:52 2017 -0700
# Node ID 414372f08c44186c8dad9dea46d617ab61412503
# Parent  28093cead8791382a984b4c80dcedbe529ea7c41
# EXP-Topic mutable-default
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 414372f08c44
filemerge: explicitly tests for None

Changeset 758526333dec removed the mutable default value, but did not explicitly
tested for None. Such implicit testing can introduce semantic and performance
issue. We move to an explicit testing for None as recommended by PEP8:

https://www.python.org/dev/peps/pep-0008/#programming-recommendations

diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -36,7 +36,9 @@ def _toolbool(ui, tool, part, default=Fa
 return ui.configbool("merge-tools", tool + "." + part, default)
 
 def _toollist(ui, tool, part, default=None):
-return ui.configlist("merge-tools", tool + "." + part, default or [])
+if default is None:
+default = []
+return ui.configlist("merge-tools", tool + "." + part, default)
 
 internals = {}
 # Merge tools to document.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 8] match: explicitly tests for None

2017-03-16 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1489615725 25200
#  Wed Mar 15 15:08:45 2017 -0700
# Node ID 83112ff862072df863540c8c9356f64eb26faa41
# Parent  27d5ab143c3344006509c5a3b29e2cb66445aa04
# EXP-Topic mutable-default
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 83112ff86207
match: explicitly tests for None

Changeset 6168d4b93634 removed the mutable default value, but did not explicitly
tested for None. Such implicit testing can introduce semantic and performance
issue. We move to an explicit testing for None as recommended by PEP8:

https://www.python.org/dev/peps/pep-0008/#programming-recommendations

diff --git a/mercurial/match.py b/mercurial/match.py
--- a/mercurial/match.py
+++ b/mercurial/match.py
@@ -117,8 +117,10 @@ class match(object):
   the same directory
 '' - a pattern of the specified default type
 """
-include = include or []
-exclude = exclude or []
+if include is None:
+include = []
+if exclude is None:
+exclude = []
 
 self._root = root
 self._cwd = cwd
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 8 of 8] context: explicitly tests for None

2017-03-16 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1489617204 25200
#  Wed Mar 15 15:33:24 2017 -0700
# Node ID d912b21f4721d399fd327b6bb7179de7e2a614b6
# Parent  414372f08c44186c8dad9dea46d617ab61412503
# EXP-Topic mutable-default
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r d912b21f4721
context: explicitly tests for None

Changeset 9e57033fec0c removed the mutable default value, but did not explicitly
tested for None. Such implicit testing can introduce semantic and performance
issue. We move to an explicit testing for None as recommended by PEP8:

https://www.python.org/dev/peps/pep-0008/#programming-recommendations

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -300,8 +300,10 @@ class basectx(object):
 
 def match(self, pats=None, include=None, exclude=None, default='glob',
   listsubrepos=False, badfn=None):
+if pats is None:
+pats = []
 r = self._repo
-return matchmod.match(r.root, r.getcwd(), pats or [],
+return matchmod.match(r.root, r.getcwd(), pats,
   include, exclude, default,
   auditor=r.nofsauditor, ctx=self,
   listsubrepos=listsubrepos, badfn=badfn)
@@ -1517,16 +1519,18 @@ class workingctx(committablectx):
 
 def match(self, pats=None, include=None, exclude=None, default='glob',
   listsubrepos=False, badfn=None):
+if pats is None:
+pats = []
 r = self._repo
 
 # Only a case insensitive filesystem needs magic to translate user 
input
 # to actual case in the filesystem.
 if not util.fscasesensitive(r.root):
-return matchmod.icasefsmatcher(r.root, r.getcwd(), pats or [],
+return matchmod.icasefsmatcher(r.root, r.getcwd(), pats,
include, exclude, default, 
r.auditor,
self, listsubrepos=listsubrepos,
badfn=badfn)
-return matchmod.match(r.root, r.getcwd(), pats or [],
+return matchmod.match(r.root, r.getcwd(), pats,
   include, exclude, default,
   auditor=r.auditor, ctx=self,
   listsubrepos=listsubrepos, badfn=badfn)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 6 of 6 py3] commands: make sure using byteschr rather than ascii values

2017-03-16 Thread Martin von Zweigbergk via Mercurial-devel
On Mar 16, 2017 00:18, "Pulkit Goyal" <7895pul...@gmail.com> wrote:



On Thu, Mar 16, 2017 at 10:14 AM, Martin von Zweigbergk <
martinv...@google.com> wrote:

> On Wed, Mar 15, 2017 at 9:13 PM, Pulkit Goyal <7895pul...@gmail.com>
> wrote:
> > # HG changeset patch
> > # User Pulkit Goyal <7895pul...@gmail.com>
> > # Date 1489635793 -19800
> > #  Thu Mar 16 09:13:13 2017 +0530
> > # Node ID 63aeb39b5802644ae99eaa5cf0666f3bf5cc4e90
> > # Parent  b5673a08993652a92c0e20a4e24d842194872454 <(219)%20487-2454>
> > commands: make sure using byteschr rather than ascii values
> >
> > 'MAR!?IC' is converted to their ascii values when slicing through it.
> This
> > patch converts them back to bytes string.
> >
> > diff -r b5673a089936 -r 63aeb39b5802 mercurial/commands.py
> > --- a/mercurial/commands.py Thu Mar 16 09:00:27 2017 +0530
> > +++ b/mercurial/commands.py Thu Mar 16 09:13:13 2017 +0530
> > @@ -4768,6 +4768,8 @@
> >  showchar = not opts.get('no_status')
> >
> >  for state, char, files in changestates:
> > +if pycompat.ispy3:
> > +char = bytes([char])
>
> I'd prefer to wrap 'MAR!?C' in pycompat.iterbytestr() to avoid the
> conditional here. What do you think?. Would that work?


​I am not sure about how you are saying to that. Using pycompat.iterbytes()
we can iterate on 'MAR!?C', but in these we are iterating over three things
at once.​



I mean to wrap it in the call to zip, so zip(x, iterbytes(y), z).
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2 V2] py3: optimize py3 compat.bytechr using Struct.pack

2017-03-16 Thread Yuya Nishihara
On Wed, 15 Mar 2017 10:33:11 -0700, Martin von Zweigbergk via Mercurial-devel 
wrote:
> # HG changeset patch
> # User Martin von Zweigbergk 
> # Date 1489595450 25200
> #  Wed Mar 15 09:30:50 2017 -0700
> # Node ID db74b2599efc1997b0e7e6bb7b699717029c11d8
> # Parent  e83302d437485620c9bc25921f724af34cd5dd55
> py3: optimize py3 compat.bytechr using Struct.pack

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


mercurial@31423: 5 new changesets

2017-03-16 Thread Mercurial Commits
5 new changesets in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/1fc3d1f02865
changeset:   31419:1fc3d1f02865
user:Pulkit Goyal <7895pul...@gmail.com>
date:Thu Mar 16 06:32:33 2017 +0530
summary: scmutil: make function name bytes in class filecache

https://www.mercurial-scm.org/repo/hg/rev/40704098853f
changeset:   31420:40704098853f
user:Pulkit Goyal <7895pul...@gmail.com>
date:Thu Mar 16 07:52:47 2017 +0530
summary: match: make regular expression bytes to prevent TypeError

https://www.mercurial-scm.org/repo/hg/rev/5c9cda37d7f6
changeset:   31421:5c9cda37d7f6
user:Pulkit Goyal <7895pul...@gmail.com>
date:Thu Mar 16 08:03:51 2017 +0530
summary: match: slice over bytes to get the byteschr instead of ascii value

https://www.mercurial-scm.org/repo/hg/rev/2e38a88bbc6c
changeset:   31422:2e38a88bbc6c
user:Pulkit Goyal <7895pul...@gmail.com>
date:Thu Mar 16 09:00:27 2017 +0530
summary: dirstate: use list comprehension to get a list of keys

https://www.mercurial-scm.org/repo/hg/rev/568d80b24b3a
changeset:   31423:568d80b24b3a
bookmark:@
tag: tip
user:Ryan McElroy 
date:Wed Mar 15 19:26:20 2017 -0700
summary: tests: properly drop back to root dir in test-status.t

-- 
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 3 of 7] parsers: avoid PyList_Append when parsing obs markers

2017-03-16 Thread Yuya Nishihara
On Mon, 13 Mar 2017 22:15:45 -0700, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc 
> # Date 1489454332 25200
> #  Mon Mar 13 18:18:52 2017 -0700
> # Node ID 6d3b13f243bea2c9200eecb827d7ec0ea771fc54
> # Parent  3b997adb7efece7395fb585a70b2d70522626648
> parsers: avoid PyList_Append when parsing obs markers
> 
> PyList_Append() has to continuously grow the underlying list as
> available storage is exhausted. This adds overhead within tight
> loops.
> 
> It is better to create a new list of known size then use the
> PyList_SET_ITEM macro to populate each element of the list
> without error checking. This commit switches us to that
> mechanism.
> 
> The new code establishes an array to hold PyObject* instances
> then iterates the array at the end. The bulk of the new code
> is for memory management of the new array. There are some
> inline comments explaining how the array is sized.
> 
> `hg perfloadmarkers` show an improvement with this change:
> 
> ! result: 130264
> ! wall 0.125479 comb 0.13 user 0.12 sys 0.01 (best of 76)
> ! wall 0.120487 comb 0.13 user 0.12 sys 0.01 (best of 79)

I'm not so enthusiastic about this perf number compared to the complexity
of additional memory management. Does this contribute to the net perf win?

> --- a/mercurial/parsers.c
> +++ b/mercurial/parsers.c
> @@ -2792,33 +2792,77 @@ static PyObject *fm1readmarkers(PyObject
>   int datalen;
>   Py_ssize_t offset, stop;
>   PyObject *markers = NULL;
> + PyObject **tmpmarkers = NULL;
> + Py_ssize_t tmpmarkerssize;
> + Py_ssize_t tmpmarkersoffset = 0;
>  
>   if (!PyArg_ParseTuple(args, "s#nn", &data, &datalen, &offset, &stop)) {
>   return NULL;
>   }
>   dataend = data + datalen;
>   data += offset;
> - markers = PyList_New(0);
> - if (!markers) {
> +
> + /*
> +We store an array of pointers to markers then build a list from
> +it at the end. This is faster than appending to a PyList for each
> +element.
> +
> +Reallocating the array constantly could be expensive. We estimate
> +the size of the array by assuming 90 bytes per marker, which is
> +based on data seen in the wild.
> + */
> + tmpmarkerssize = datalen / 90;
> + /* Handle datalen < 90 */
> + tmpmarkerssize = tmpmarkerssize ? tmpmarkerssize : 10;
> +
> + tmpmarkers = (PyObject **)PyMem_Malloc(
> + tmpmarkerssize * sizeof(PyObject *));
> + if (!tmpmarkers) {
> + PyErr_NoMemory();
>   return NULL;
>   }

Maybe we could do PyList_New(estimated_capacity) and shrink it at the end by
PyList_SetSlice(). The API doc doesn't state that PyList_SetSlice() can handle
NULL items, but builtin_zip() appears to do that.

  Python/bltinmodule.c:builtin_zip()

> + free(tmpmarkers);

This should be PyMem_Free() for consistency.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 4 of 7] parsers: handle refcounting of "parents" consistently

2017-03-16 Thread Yuya Nishihara
On Mon, 13 Mar 2017 22:15:46 -0700, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc 
> # Date 1489452553 25200
> #  Mon Mar 13 17:49:13 2017 -0700
> # Node ID d600bd4edd62b3ee74730f1282e53b9d596bbaec
> # Parent  6d3b13f243bea2c9200eecb827d7ec0ea771fc54
> parsers: handle refcounting of "parents" consistently
> 
> Py_None can be refcounted like any other Python object. So
> do that.

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


Re: [PATCH 5 of 7] [RFC] parsers: create a dedicated type for an obs marker

2017-03-16 Thread Yuya Nishihara
On Mon, 13 Mar 2017 22:15:47 -0700, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc 
> # Date 1489467734 25200
> #  Mon Mar 13 22:02:14 2017 -0700
> # Node ID b4159d4c3683f03b6962991f318b080d849d6ba3
> # Parent  d600bd4edd62b3ee74730f1282e53b9d596bbaec
> [RFC] parsers: create a dedicated type for an obs marker

I haven't reviewed these carefully, but I like the direction. fm1readmarkers()
creates a bunch of boxed objects, which would have somewhat significant cost.

Can we split obsmarker handling to new module? It's getting bigger.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 3 of 3 py3] context: explicitly evaluate list returned by map

2017-03-16 Thread Yuya Nishihara
On Thu, 16 Mar 2017 13:23:25 +0530, Pulkit Goyal wrote:
> # HG changeset patch
> # User Pulkit Goyal <7895pul...@gmail.com>
> # Date 1489639281 -19800
> #  Thu Mar 16 10:11:21 2017 +0530
> # Node ID 8d85d7ca9fd3eea90a2f09c7d471fc3f3c78d430
> # Parent  de18c43f8ce17d52542e6df233e809b6a6ee0a07
> context: explicitly evaluate list returned by map
> 
> On python 3, map returns an iterator so we need to convert it to list before
> finding the len or subscripting it.
> 
> After this `hg status --all` works on Python 3.
> 
> diff -r de18c43f8ce1 -r 8d85d7ca9fd3 mercurial/context.py
> --- a/mercurial/context.pyThu Mar 16 10:10:00 2017 +0530
> +++ b/mercurial/context.pyThu Mar 16 10:11:21 2017 +0530
> @@ -622,7 +622,7 @@
>  n2 = c2._node
>  if n2 is None:
>  n2 = c2._parents[0]._node
> -cahs = self._repo.changelog.commonancestorsheads(self._node, n2)
> +cahs = list(self._repo.changelog.commonancestorsheads(self._node, 
> n2))

Perhaps we should make commonancestorsheads() return a list so we'll never
have another iterator-vs-list bug.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 2 of 3 py3] commands: convert opts back to bytes for status

2017-03-16 Thread Yuya Nishihara
On Thu, 16 Mar 2017 13:23:24 +0530, Pulkit Goyal wrote:
> # HG changeset patch
> # User Pulkit Goyal <7895pul...@gmail.com>
> # Date 1489639200 -19800
> #  Thu Mar 16 10:10:00 2017 +0530
> # Node ID de18c43f8ce17d52542e6df233e809b6a6ee0a07
> # Parent  47dae3bbf8560824743293870aab601da2d1ed6c
> commands: convert opts back to bytes for status
> 
> diff -r 47dae3bbf856 -r de18c43f8ce1 mercurial/commands.py
> --- a/mercurial/commands.py   Thu Mar 16 10:01:12 2017 +0530
> +++ b/mercurial/commands.py   Thu Mar 16 10:10:00 2017 +0530
> @@ -4720,6 +4720,7 @@
>  Returns 0 on success.
>  """
>  
> +opts = pycompat.byteskwargs(opts)
>  revs = opts.get('rev')
>  change = opts.get('change')

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


Re: [PATCH 1 of 3 py3] error: convert the error into strings to pass into ui.warn()

2017-03-16 Thread Yuya Nishihara
On Thu, 16 Mar 2017 13:23:23 +0530, Pulkit Goyal wrote:
> # HG changeset patch
> # User Pulkit Goyal <7895pul...@gmail.com>
> # Date 1489638672 -19800
> #  Thu Mar 16 10:01:12 2017 +0530
> # Node ID 47dae3bbf8560824743293870aab601da2d1ed6c
> # Parent  63aeb39b5802644ae99eaa5cf0666f3bf5cc4e90
> error: convert the error into strings to pass into ui.warn()
> 
> diff -r 63aeb39b5802 -r 47dae3bbf856 mercurial/scmutil.py
> --- a/mercurial/scmutil.pyThu Mar 16 09:13:13 2017 +0530
> +++ b/mercurial/scmutil.pyThu Mar 16 10:01:12 2017 +0530
> @@ -168,7 +168,8 @@
>  if inst.hint:
>  ui.warn('(%s)\n' % inst.hint)
>  except error.RepoError as inst:
> -ui.warn(_("abort: %s!\n") % inst)
> +if inst.args:
> +ui.warn(_("abort: %s!\n") % ''.join(inst.args))

Maybe we'll need to implement __bytes__() in our exception classes?
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 4] tests: allow running doctests selectively on Python 3

2017-03-16 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1488978812 -32400
#  Wed Mar 08 22:13:32 2017 +0900
# Node ID f39291c08d86082579b891e844cbd56752b44a59
# Parent  63a39d64788872a5742f8e3143b7ddd603e3af13
tests: allow running doctests selectively on Python 3

Currently most doctests fail on Python 3, but I want to add some.

diff --git a/tests/test-doctest.py b/tests/test-doctest.py
--- a/tests/test-doctest.py
+++ b/tests/test-doctest.py
@@ -5,10 +5,16 @@ from __future__ import absolute_import
 import doctest
 import os
 import sys
+
+ispy3 = (sys.version_info[0] >= 3)
+
 if 'TERM' in os.environ:
 del os.environ['TERM']
 
-def testmod(name, optionflags=0, testtarget=None):
+# TODO: migrate doctests to py3 and enable them on both versions
+def testmod(name, optionflags=0, testtarget=None, py2=True, py3=False):
+if not (not ispy3 and py2 or ispy3 and py3):
+return
 __import__(name)
 mod = sys.modules[name]
 if testtarget is not None:
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 4] py3: use bytestr wrapper in revsetlang.tokenize()

2017-03-16 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1489667781 -32400
#  Thu Mar 16 21:36:21 2017 +0900
# Node ID d21fd508342b1d43ebefaac65f1d6e2e5ca60704
# Parent  649866574c86bae35ab8143c50af72bee7fef810
py3: use bytestr wrapper in revsetlang.tokenize()

This backs out 77270ec0cdd9 and wraps program by bytestr() instead.

diff --git a/mercurial/revsetlang.py b/mercurial/revsetlang.py
--- a/mercurial/revsetlang.py
+++ b/mercurial/revsetlang.py
@@ -78,6 +78,7 @@ def tokenize(program, lookup=None, symin
 [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)]
 
 '''
+program = pycompat.bytestr(program)
 if syminitletters is None:
 syminitletters = _syminitletters
 if symletters is None:
@@ -100,7 +101,7 @@ def tokenize(program, lookup=None, symin
 
 pos, l = 0, len(program)
 while pos < l:
-c = program[pos:pos + 1]
+c = program[pos]
 if c.isspace(): # skip inter-token whitespace
 pass
 elif c == ':' and program[pos:pos + 2] == '::': # look ahead carefully
@@ -118,14 +119,14 @@ def tokenize(program, lookup=None, symin
   program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
 if c == 'r':
 pos += 1
-c = program[pos:pos + 1]
+c = program[pos]
 decode = lambda x: x
 else:
 decode = parser.unescapestr
 pos += 1
 s = pos
 while pos < l: # find closing quote
-d = program[pos:pos + 1]
+d = program[pos]
 if d == '\\': # skip over escaped characters
 pos += 2
 continue
@@ -140,11 +141,10 @@ def tokenize(program, lookup=None, symin
 s = pos
 pos += 1
 while pos < l: # find end of symbol
-d = program[pos:pos + 1]
+d = program[pos]
 if d not in symletters:
 break
-if (d == '.'
-and program[pos - 1:pos] == '.'): # special case for ..
+if d == '.' and program[pos - 1] == '.': # special case for ..
 pos -= 1
 break
 pos += 1
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 4] py3: use bytestr wrapper in revsetlang.formatspec()

2017-03-16 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1489667605 -32400
#  Thu Mar 16 21:33:25 2017 +0900
# Node ID 649866574c86bae35ab8143c50af72bee7fef810
# Parent  aae1bd4b8a03ffe6cb47c23da55b2f70ff5607ef
py3: use bytestr wrapper in revsetlang.formatspec()

This backs out 1c48a8278b2f and wraps expr by bytestr() instead.

diff --git a/mercurial/revsetlang.py b/mercurial/revsetlang.py
--- a/mercurial/revsetlang.py
+++ b/mercurial/revsetlang.py
@@ -640,14 +640,15 @@ def formatspec(expr, *args):
 m = l // 2
 return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t))
 
+expr = pycompat.bytestr(expr)
 ret = ''
 pos = 0
 arg = 0
 while pos < len(expr):
-c = expr[pos:pos + 1]
+c = expr[pos]
 if c == '%':
 pos += 1
-d = expr[pos:pos + 1]
+d = expr[pos]
 if d == '%':
 ret += d
 elif d in 'dsnbr':
@@ -656,7 +657,7 @@ def formatspec(expr, *args):
 elif d == 'l':
 # a list of some type
 pos += 1
-d = expr[pos:pos + 1]
+d = expr[pos]
 ret += listexp(list(args[arg]), d)
 arg += 1
 else:
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 4] pycompat: add bytestr wrapper which mostly acts as a Python 2 str

2017-03-16 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1488980906 -32400
#  Wed Mar 08 22:48:26 2017 +0900
# Node ID aae1bd4b8a03ffe6cb47c23da55b2f70ff5607ef
# Parent  f39291c08d86082579b891e844cbd56752b44a59
pycompat: add bytestr wrapper which mostly acts as a Python 2 str

This allows us to handle bytes in mostly the same manner as Python 2 str,
so we can get rid of ugly s[i:i + 1] hacks:

  s = bytestr(s)
  while i < len(s):
  c = s[i]
  ...

This is the simpler version of the previous RFC patch which tried to preserve
the bytestr type if possible. New version simply drops the bytestr wrapping
so we aren't likely to pass a bytestr to a function that expects Python 3
bytes.

diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
--- a/mercurial/pycompat.py
+++ b/mercurial/pycompat.py
@@ -76,6 +76,67 @@ if ispy3:
 
 bytechr = struct.Struct('>B').pack
 
+class bytestr(bytes):
+"""A bytes which mostly acts as a Python 2 str
+
+>>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), 
bytestr(1)
+(b'', b'foo', b'ascii', b'1')
+>>> s = bytestr(b'foo')
+>>> assert s is bytestr(s)
+
+There's no implicit conversion from non-ascii str as its encoding is
+unknown:
+
+>>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
+Traceback (most recent call last):
+  ...
+UnicodeEncodeError: ...
+
+Comparison between bytestr and bytes should work:
+
+>>> assert bytestr(b'foo') == b'foo'
+>>> assert b'foo' == bytestr(b'foo')
+>>> assert b'f' in bytestr(b'foo')
+>>> assert bytestr(b'f') in b'foo'
+
+Sliced elements should be bytes, not integer:
+
+>>> s[1], s[:2]
+(b'o', b'fo')
+>>> list(s), list(reversed(s))
+([b'f', b'o', b'o'], [b'o', b'o', b'f'])
+
+As bytestr type isn't propagated across operations, you need to cast
+bytes to bytestr explicitly:
+
+>>> s = bytestr(b'foo').upper()
+>>> t = bytestr(s)
+>>> s[0], t[0]
+(70, b'F')
+
+Be careful to not pass a bytestr object to a function which expects
+bytearray-like behavior.
+
+>>> t = bytes(t)  # cast to bytes
+>>> assert type(t) is bytes
+"""
+
+def __new__(cls, s=b''):
+if isinstance(s, bytestr):
+return s
+if not isinstance(s, (bytes, bytearray)):
+s = str(s).encode(u'ascii')
+return bytes.__new__(cls, s)
+
+def __getitem__(self, key):
+s = bytes.__getitem__(self, key)
+if not isinstance(s, bytes):
+s = bytechr(s)
+return s
+
+def __iter__(self):
+return iterbytestr(bytes.__iter__(self))
+
 def iterbytestr(s):
 """Iterate bytes as if it were a str object of Python 2"""
 return map(bytechr, s)
@@ -146,6 +207,7 @@ else:
 import cStringIO
 
 bytechr = chr
+bytestr = str
 iterbytestr = iter
 
 def sysstr(s):
diff --git a/tests/test-doctest.py b/tests/test-doctest.py
--- a/tests/test-doctest.py
+++ b/tests/test-doctest.py
@@ -34,6 +34,7 @@ testmod('mercurial.minirst')
 testmod('mercurial.patch')
 testmod('mercurial.pathutil')
 testmod('mercurial.parser')
+testmod('mercurial.pycompat', py3=True)
 testmod('mercurial.revsetlang')
 testmod('mercurial.smartset')
 testmod('mercurial.store')
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 5 of 7] [RFC] parsers: create a dedicated type for an obs marker

2017-03-16 Thread Gregory Szorc
On Thu, Mar 16, 2017 at 7:34 AM, Yuya Nishihara  wrote:

> On Mon, 13 Mar 2017 22:15:47 -0700, Gregory Szorc wrote:
> > # HG changeset patch
> > # User Gregory Szorc 
> > # Date 1489467734 25200
> > #  Mon Mar 13 22:02:14 2017 -0700
> > # Node ID b4159d4c3683f03b6962991f318b080d849d6ba3
> > # Parent  d600bd4edd62b3ee74730f1282e53b9d596bbaec
> > [RFC] parsers: create a dedicated type for an obs marker
>
> I haven't reviewed these carefully, but I like the direction.
> fm1readmarkers()
> creates a bunch of boxed objects, which would have somewhat significant
> cost.
>
> Can we split obsmarker handling to new module? It's getting bigger.
>

Yes, I was considering that.

But instead of creating N+1 Python modules, I'd like to move us in the
direction of a single module built from multiple .c files. This is the
approach I've taken in python-zstandard, for example. I believe this
approach is superior because having a single compilation unit facilitates
code reuse, inlining between source files, smaller binaries, and better
performance.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 01 of 11] bdiff: use Python memory allocator in fixws

2017-03-16 Thread Gregory Szorc
On Wed, Mar 15, 2017 at 11:16 PM, Jun Wu  wrote:

> Excerpts from Jun Wu's message of 2017-03-15 23:15:13 -0700:
> > I think it makes sense to migrate Python modules to PyMem_*.
> >
> > However, I'm also a bit conservative about the "calloc" perf issue
> mentioned
> > by Yuya. I think it's safe to take Patch 1, 2, 4, 5 where there is no
> calloc
>
> Sorry, it should be "Patch 1, 2, 4, and 6", not 5. I cannot count.
>

I agree with not taking the patches that remove calloc(). I'm pretty sure
we don't actually need to zero the memory in some (all?) of those
instances. But I can deal with that in a follow-up series.


>
> > change for now. We can figure out what to do with calloc / pure C code
> > later.
> >
> > Excerpts from Gregory Szorc's message of 2017-03-09 13:59:09 -0800:
> > > # HG changeset patch
> > > # User Gregory Szorc 
> > > # Date 1489089265 28800
> > > #  Thu Mar 09 11:54:25 2017 -0800
> > > # Node ID 7a8ce919a13a9ff6e73f391fe14d228e18387f15
> > > # Parent  1871a1ee64ed49172b1568b89cdbab126284b309
> > > bdiff: use Python memory allocator in fixws
> > >
> > > Python has its own memory allocation APIs. For allocations
> > > <= 512 bytes, it allocates memory from arenas. This means that
> > > average small allocations don't call the system allocator, which
> > > makes them faster. Also, arena allocations cut down on memory
> > > fragmentation, which can matter for performance in long-running
> > > processes.
> > >
> > > Another advantage of using the Python memory allocator is that
> > > allocations are tracked by Python. This is a bigger deal in
> > > Python 3, as modern versions of Python have some decent built-in
> > > tools for examining memory usage, leaks, etc.
> > >
> > > This patch converts a trivial malloc() + free() in the bdiff code
> > > to use the Python allocator APIs. Since the object being
> > > operated on is a line, chances are it will use an arena. So,
> > > this could have a net positive impact on performance (although
> > > I didn't measure it).
> > >
> > > diff --git a/mercurial/bdiff_module.c b/mercurial/bdiff_module.c
> > > --- a/mercurial/bdiff_module.c
> > > +++ b/mercurial/bdiff_module.c
> > > @@ -158,7 +158,7 @@ static PyObject *fixws(PyObject *self, P
> > >  r = PyBytes_AsString(s);
> > >  rlen = PyBytes_Size(s);
> > >
> > > -w = (char *)malloc(rlen ? rlen : 1);
> > > +w = (char *)PyMem_Malloc(rlen ? rlen : 1);
> > >  if (!w)
> > >  goto nomem;
> > >
> > > @@ -178,7 +178,7 @@ static PyObject *fixws(PyObject *self, P
> > >  result = PyBytes_FromStringAndSize(w, wlen);
> > >
> > >  nomem:
> > > -free(w);
> > > +PyMem_Free(w);
> > >  return result ? result : PyErr_NoMemory();
> > >  }
> > >
>
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 8] rebase: explicitly tests for None

2017-03-16 Thread Gregory Szorc
On Thu, Mar 16, 2017 at 4:28 AM, Pierre-Yves David <
pierre-yves.da...@ens-lyon.org> wrote:

> # HG changeset patch
> # User Pierre-Yves David 
> # Date 1489615423 25200
> #  Wed Mar 15 15:03:43 2017 -0700
> # Node ID 6c6d8c0cc67de1ecd744a30889419510aa2064d2
> # Parent  361bccce566afe250c8d258f770a908713b2d13f
> # EXP-Topic mutable-default
> # Available At https://www.mercurial-scm.org/
> repo/users/marmoute/mercurial/
> #  hg pull https://www.mercurial-scm.org/
> repo/users/marmoute/mercurial/ -r 6c6d8c0cc67d
> rebase: explicitly tests for None
>
> Changeset 361bccce566a removed the mutable default value, but did not
> explicitly
> tested for None. Such implicit checking can introduce semantic and
> performance
> issue. We move to an explicit check for None as recommended by PEP8:
>
> https://www.python.org/dev/peps/pep-0008/#programming-recommendations


I generally disagree with this series on the grounds that it doesn't matter
in these use cases. Yes, there are times where this matters for performance
or because we're leveraging dynamic programming to pass in different types
that can all be empty. These are not those times.

Also, if others insist on the "is None" check, I prefer the inline form
(`revf = revf if revf is not None else []`) because I don't like wasting
lines on type validation... because Python.


>
>
> diff --git a/hgext/rebase.py b/hgext/rebase.py
> --- a/hgext/rebase.py
> +++ b/hgext/rebase.py
> @@ -725,7 +725,8 @@ def _definesets(ui, repo, destf=None, sr
>  destspace=None):
>  """use revisions argument to define destination and rebase set
>  """
> -revf = revf or []
> +if revf is None:
> +revf = []
>
>  # destspace is here to work around issues with `hg pull --rebase` see
>  # issue5214 for details
> ___
> 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


[Bug 5505] New: UnboundLocalError: local variable 'prompts' referenced before assignment

2017-03-16 Thread mercurial-bugs
https://bz.mercurial-scm.org/show_bug.cgi?id=5505

Bug ID: 5505
   Summary: UnboundLocalError: local variable 'prompts' referenced
before assignment
   Product: Mercurial
   Version: 4.1.1
  Hardware: PC
OS: Windows
Status: UNCONFIRMED
  Severity: bug
  Priority: wish
 Component: Mercurial
  Assignee: bugzi...@mercurial-scm.org
  Reporter: m...@michaelbaur.de
CC: mercurial-devel@mercurial-scm.org

I get this error during a large merge.

** Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v
** Mercurial Distributed SCM (version 4.1.1)
** Extensions loaded: transplant, rebase, extdiff, strip
Traceback (most recent call last):
  File "hg", line 49, in 
  File "mercurial\dispatch.pyo", line 63, in run
  File "mercurial\dispatch.pyo", line 129, in dispatch
  File "mercurial\dispatch.pyo", line 219, in _runcatch
  File "mercurial\dispatch.pyo", line 227, in callcatch
  File "mercurial\scmutil.pyo", line 152, in callcatch
  File "mercurial\dispatch.pyo", line 208, in _runcatchf
  File "mercurial\dispatch.pyo", line 811, in _dispatch
  File "mercurial\dispatch.pyo", line 563, in runcommand
  File "mercurial\extensions.pyo", line 223, in closure
  File "hgext\color.pyo", line 460, in colorcmd
  File "mercurial\dispatch.pyo", line 819, in _runcomman
  File "mercurial\dispatch.pyo", line 808, in 
  File "mercurial\util.pyo", line 1051, in check
  File "mercurial\extensions.pyo", line 223, in closure
  File "mercurial\util.pyo", line 1051, in check
  File "hgext\mq.pyo", line 3541, in mqcommand
  File "mercurial\util.pyo", line 1051, in check
  File "mercurial\commands.pyo", line 4757, in merge
  File "mercurial\hg.pyo", line 775, in merge
  File "mercurial\merge.pyo", line 1660, in update
  File "mercurial\merge.pyo", line 1301, in applyupdates
  File "mercurial\subrepo.pyo", line 265, in submerge

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


Re: [PATCH 2 of 2] pager: skip running the pager if it's set to 'cat'

2017-03-16 Thread Augie Fackler

> On Mar 15, 2017, at 21:12, Jun Wu  wrote:
> 
> Another thing that git does (reasonably, I think) is to set default
> environment variable. Say if we decide to go with shell=False, set LESS=FRX
> so people using pager.pager=less will have a better experience.

We should add that environment variable iff it's not already set in the user's 
environment, of course.___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 8] rebase: explicitly tests for None

2017-03-16 Thread Augie Fackler
On Thu, Mar 16, 2017 at 09:35:12AM -0700, Gregory Szorc wrote:
> On Thu, Mar 16, 2017 at 4:28 AM, Pierre-Yves David <
> pierre-yves.da...@ens-lyon.org> wrote:
>
> > # HG changeset patch
> > # User Pierre-Yves David 
> > # Date 1489615423 25200
> > #  Wed Mar 15 15:03:43 2017 -0700
> > # Node ID 6c6d8c0cc67de1ecd744a30889419510aa2064d2
> > # Parent  361bccce566afe250c8d258f770a908713b2d13f
> > # EXP-Topic mutable-default
> > # Available At https://www.mercurial-scm.org/
> > repo/users/marmoute/mercurial/
> > #  hg pull https://www.mercurial-scm.org/
> > repo/users/marmoute/mercurial/ -r 6c6d8c0cc67d
> > rebase: explicitly tests for None
> >
> > Changeset 361bccce566a removed the mutable default value, but did not
> > explicitly
> > tested for None. Such implicit checking can introduce semantic and
> > performance
> > issue. We move to an explicit check for None as recommended by PEP8:
> >
> > https://www.python.org/dev/peps/pep-0008/#programming-recommendations
>
>
> I generally disagree with this series on the grounds that it doesn't matter
> in these use cases. Yes, there are times where this matters for performance
> or because we're leveraging dynamic programming to pass in different types
> that can all be empty. These are not those times.
>
> Also, if others insist on the "is None" check, I prefer the inline form
> (`revf = revf if revf is not None else []`) because I don't like wasting
> lines on type validation... because Python.

It's a minor change, but on the whole it's more idiomatic, so I'm in
favor of it. Queued (I don't object to the one-line form, but given
that this series is here and done, I'm too lazy to re-do all the
work.)

>
>
> >
> >
> > diff --git a/hgext/rebase.py b/hgext/rebase.py
> > --- a/hgext/rebase.py
> > +++ b/hgext/rebase.py
> > @@ -725,7 +725,8 @@ def _definesets(ui, repo, destf=None, sr
> >  destspace=None):
> >  """use revisions argument to define destination and rebase set
> >  """
> > -revf = revf or []
> > +if revf is None:
> > +revf = []
> >
> >  # destspace is here to work around issues with `hg pull --rebase` see
> >  # issue5214 for details
> > ___
> > 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


Re: [PATCH 3 of 7] parsers: avoid PyList_Append when parsing obs markers

2017-03-16 Thread Augie Fackler
On Mon, Mar 13, 2017 at 10:24:21PM -0700, Gregory Szorc wrote:
> On Mon, Mar 13, 2017 at 10:15 PM, Gregory Szorc 
> wrote:
> Assuming there is some truth to the numbers, holy cow the overhead of
> PyObject creation is crazy. I suddenly feel like auditing the C code for
> everywhere we're instantiating PyObjects before it is necessary. I know we
> do this in the revlog index. I wonder if dirstate is impacted...

Yeah, PyObject allocation can be pretty nasty. In my toy rust version
of fm1readmarkers, it's 100x faster than the C code was, then 3x
slower overall due to time spent copying data into PyObjects.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 5 of 7] [RFC] parsers: create a dedicated type for an obs marker

2017-03-16 Thread Augie Fackler
On Thu, Mar 16, 2017 at 09:17:05AM -0700, Gregory Szorc wrote:
> On Thu, Mar 16, 2017 at 7:34 AM, Yuya Nishihara  wrote:
>
> > On Mon, 13 Mar 2017 22:15:47 -0700, Gregory Szorc wrote:
> > > # HG changeset patch
> > > # User Gregory Szorc 
> > > # Date 1489467734 25200
> > > #  Mon Mar 13 22:02:14 2017 -0700
> > > # Node ID b4159d4c3683f03b6962991f318b080d849d6ba3
> > > # Parent  d600bd4edd62b3ee74730f1282e53b9d596bbaec
> > > [RFC] parsers: create a dedicated type for an obs marker
> >
> > I haven't reviewed these carefully, but I like the direction.
> > fm1readmarkers()
> > creates a bunch of boxed objects, which would have somewhat significant
> > cost.
> >
> > Can we split obsmarker handling to new module? It's getting bigger.
> >
>
> Yes, I was considering that.
>
> But instead of creating N+1 Python modules, I'd like to move us in the
> direction of a single module built from multiple .c files. This is the
> approach I've taken in python-zstandard, for example. I believe this
> approach is superior because having a single compilation unit facilitates
> code reuse, inlining between source files, smaller binaries, and better
> performance.
>

+1 for multiple .c files that compile into parsers.so for this.

Also, making a type in C is probably unambiguously the right thing for
handling our data formats anyplace it's viable, for exactly this
reason.

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


Dropping support for Python 2.6 on Windows

2017-03-16 Thread Gregory Szorc
There is a brewing discussion about the future of Python 2.6 in Mercurial.
I'd like to start with what I think will be an easy proposal: officially
dropping support for 2.6 on Windows.

First, I think dropping 2.6 on Windows doesn't really buy us anything
significant. 2.6 and 2.7 build with the same (ancient) Visual Studio
toolchain. So it isn't like 2.6 is holding us back on C primitives we can
use or anything. Also, I'm pretty sure none of the Mercurial on Windows
packages we (or others) distribute use Python 2.6. So I don't think we save
packagers any work.

My main reason for dropping 2.6 on Windows is to get the policy change out
of the way.

Supporting this proposal is the fact that (correct me if I'm wrong)
Mercurial with 2.6 on Windows is not tested nor widely used (see previous
point about no packages targeting it). The only way (I think) people can
get Mercurial running with 2.6 on Windows is if they download the source
and compile it locally (possibly via pip). I think that's generally a small
set of all Mercurial users on Windows and Python 2.6 users are a sliver of
that population.

Furthermore, I'm not aware of anyone in the Mercurial project doing Python
2.6 development on Windows. Linux and 2.6, yes. Windows and 2.7, yes. But
not 2.6 on Windows.

If we can't adequately test and support Mercurial with Python 2.6 on
Windows, I argue it shouldn't be supported.

My formal proposal is:

a) establish a policy that Mercurial with Python 2.6 is not supported on
Windows starting in the 4.2 release
b) setup.py and `hg` reject Python 2.6 on Windows
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH V2] py3: use iter() instead of iterkeys()

2017-03-16 Thread Augie Fackler
On Thu, Mar 16, 2017 at 09:44:54AM +0530, Pulkit Goyal wrote:
> On Thu, Mar 16, 2017 at 4:58 AM, Rishabh Madan 
> wrote:
>
> > # HG changeset patch
> > # User Rishabh Madan 
> > # Date 1489620203 -19800
> > #  Thu Mar 16 04:53:23 2017 +0530
> > # Node ID aab99adf3fd2f100f134ef7378faf4367550a4eb
> > # Parent  1c48a8278b2f015fca607dfc652823560a5ac580
> > py3: use iter() instead of iterkeys()
> >
>
> ​Once this and my current series is pushed, `hg status` works on Python 3.​

This is queued, thanks.


> ___
> 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] localrepo: deprecated '_link'

2017-03-16 Thread Augie Fackler
On Wed, Mar 15, 2017 at 08:25:16AM -0700, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David 
> # Date 1470399345 -7200
> #  Fri Aug 05 14:15:45 2016 +0200
> # Node ID c94039261ff0af3bcc5f7ff060d43eaf36a135f8
> # Parent  91ac4c04240637400bb3f172fc80ff011acfcfb7
> # EXP-Topic vfs.cleanup
> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
> #  hg pull 
> https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r c94039261ff0
> localrepo: deprecated '_link'

queued, thanks

>
> That method had a total on 1 internal user...
>
>
> G: changed mercurial/localrepo.py
>
> diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
> --- a/mercurial/localrepo.py
> +++ b/mercurial/localrepo.py
> @@ -981,6 +981,8 @@ class localrepository(object):
>  return self.wvfs(f, mode)
>
>  def _link(self, f):
> +self.ui.deprecwarn("use 'repo.wvfs.islink' instead of 'repo._link'",
> +   '4.0')
>  return self.wvfs.islink(f)
>
>  def _loadfilter(self, filter):
> ___
> 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 4 of 4] py3: use bytestr wrapper in revsetlang.tokenize()

2017-03-16 Thread Augie Fackler
On Fri, Mar 17, 2017 at 12:31:13AM +0900, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1489667781 -32400
> #  Thu Mar 16 21:36:21 2017 +0900
> # Node ID d21fd508342b1d43ebefaac65f1d6e2e5ca60704
> # Parent  649866574c86bae35ab8143c50af72bee7fef810
> py3: use bytestr wrapper in revsetlang.tokenize()

Sure, queued, thanks. Much cleaner IMO.

>
> This backs out 77270ec0cdd9 and wraps program by bytestr() instead.
>
> diff --git a/mercurial/revsetlang.py b/mercurial/revsetlang.py
> --- a/mercurial/revsetlang.py
> +++ b/mercurial/revsetlang.py
> @@ -78,6 +78,7 @@ def tokenize(program, lookup=None, symin
>  [('symbol', '@', 0), ('::', None, 1), ('end', None, 3)]
>
>  '''
> +program = pycompat.bytestr(program)
>  if syminitletters is None:
>  syminitletters = _syminitletters
>  if symletters is None:
> @@ -100,7 +101,7 @@ def tokenize(program, lookup=None, symin
>
>  pos, l = 0, len(program)
>  while pos < l:
> -c = program[pos:pos + 1]
> +c = program[pos]
>  if c.isspace(): # skip inter-token whitespace
>  pass
>  elif c == ':' and program[pos:pos + 2] == '::': # look ahead 
> carefully
> @@ -118,14 +119,14 @@ def tokenize(program, lookup=None, symin
>program[pos:pos + 2] in ("r'", 'r"')): # handle quoted strings
>  if c == 'r':
>  pos += 1
> -c = program[pos:pos + 1]
> +c = program[pos]
>  decode = lambda x: x
>  else:
>  decode = parser.unescapestr
>  pos += 1
>  s = pos
>  while pos < l: # find closing quote
> -d = program[pos:pos + 1]
> +d = program[pos]
>  if d == '\\': # skip over escaped characters
>  pos += 2
>  continue
> @@ -140,11 +141,10 @@ def tokenize(program, lookup=None, symin
>  s = pos
>  pos += 1
>  while pos < l: # find end of symbol
> -d = program[pos:pos + 1]
> +d = program[pos]
>  if d not in symletters:
>  break
> -if (d == '.'
> -and program[pos - 1:pos] == '.'): # special case for ..
> +if d == '.' and program[pos - 1] == '.': # special case for 
> ..
>  pos -= 1
>  break
>  pos += 1
> ___
> 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 8] util: explicitly tests for None

2017-03-16 Thread Augie Fackler
On Thu, Mar 16, 2017 at 04:28:06AM -0700, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David 
> # Date 1489615634 25200
> #  Wed Mar 15 15:07:14 2017 -0700
> # Node ID 6d73a06abb85612fca7231fb71f245f82f7d6863
> # Parent  6c6d8c0cc67de1ecd744a30889419510aa2064d2
> # EXP-Topic mutable-default
> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
> #  hg pull 
> https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 6d73a06abb85
> util: explicitly tests for None

FYI, this one failed to apply, but I didn't investigate due to time
constraints on my end.

>
> Changeset 8b6927eb7efd removed the mutable default value, but did not 
> explicitly
> tested for None. Such implicit checking can introduce semantic and performance
> issue. We move to an explicit check for None as recommended by PEP8:
>
> https://www.python.org/dev/peps/pep-0008/#programming-recommendations
>
> diff --git a/mercurial/util.py b/mercurial/util.py
> --- a/mercurial/util.py
> +++ b/mercurial/util.py
> @@ -1830,7 +1830,8 @@ def parsetimezone(s):
>  def strdate(string, format, defaults=None):
>  """parse a localized time string and return a (unixtime, offset) tuple.
>  if the string cannot be parsed, ValueError is raised."""
> -defaults = defaults or []
> +if defaults is None:
> +defaults = []
>
>  # NOTE: unixtime = localunixtime + offset
>  offset, date = parsetimezone(string)
> ___
> 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] import-checkers: split tests of the tool from running it on the source

2017-03-16 Thread Augie Fackler
On Tue, Mar 14, 2017 at 11:16:36PM -0700, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David 
> # Date 1489558028 25200
> #  Tue Mar 14 23:07:08 2017 -0700
> # Node ID 6e53450f1d41962edb5df6c2ff35d79adc04c775
> # Parent  ed23f929af38e3249a4c0b258939e89782b20795
> # EXP-Topic import-checkers
> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
> #  hg pull 
> https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 6e53450f1d41
> import-checkers: split tests of the tool from running it on the source

Sure, queued, thanks.

>
> We did such splits for other tools already. The 'test-check-*.t' performs the
> check of the source code while the regular tests verifies the tools works.
>
> One of the benefit is that is provides a simple file to reuse in third party
> extensions.
>
> diff --git a/tests/test-check-module-imports.t 
> b/tests/test-check-module-imports.t
> --- a/tests/test-check-module-imports.t
> +++ b/tests/test-check-module-imports.t
> @@ -3,148 +3,6 @@
>$ . "$TESTDIR/helpers-testrepo.sh"
>$ import_checker="$TESTDIR"/../contrib/import-checker.py
>
> -Run the doctests from the import checker, and make sure
> -it's working correctly.
> -  $ TERM=dumb
> -  $ export TERM
> -  $ python -m doctest $import_checker
> -
> -Run additional tests for the import checker
> -
> -  $ mkdir testpackage
> -  $ touch testpackage/__init__.py
> -
> -  $ cat > testpackage/multiple.py << EOF
> -  > from __future__ import absolute_import
> -  > import os, sys
> -  > EOF
> -
> -  $ cat > testpackage/unsorted.py << EOF
> -  > from __future__ import absolute_import
> -  > import sys
> -  > import os
> -  > EOF
> -
> -  $ cat > testpackage/stdafterlocal.py << EOF
> -  > from __future__ import absolute_import
> -  > from . import unsorted
> -  > import os
> -  > EOF
> -
> -  $ cat > testpackage/requirerelative.py << EOF
> -  > from __future__ import absolute_import
> -  > import testpackage.unsorted
> -  > EOF
> -
> -  $ cat > testpackage/importalias.py << EOF
> -  > from __future__ import absolute_import
> -  > import ui
> -  > EOF
> -
> -  $ cat > testpackage/relativestdlib.py << EOF
> -  > from __future__ import absolute_import
> -  > from .. import os
> -  > EOF
> -
> -  $ cat > testpackage/symbolimport.py << EOF
> -  > from __future__ import absolute_import
> -  > from .unsorted import foo
> -  > EOF
> -
> -  $ cat > testpackage/latesymbolimport.py << EOF
> -  > from __future__ import absolute_import
> -  > from . import unsorted
> -  > from mercurial.node import hex
> -  > EOF
> -
> -  $ cat > testpackage/multiplegroups.py << EOF
> -  > from __future__ import absolute_import
> -  > from . import unsorted
> -  > from . import more
> -  > EOF
> -
> -  $ mkdir testpackage/subpackage
> -  $ cat > testpackage/subpackage/levelpriority.py << EOF
> -  > from __future__ import absolute_import
> -  > from . import foo
> -  > from .. import parent
> -  > EOF
> -
> -  $ touch testpackage/subpackage/foo.py
> -  $ cat > testpackage/subpackage/__init__.py << EOF
> -  > from __future__ import absolute_import
> -  > from . import levelpriority  # should not cause cycle
> -  > EOF
> -
> -  $ cat > testpackage/subpackage/localimport.py << EOF
> -  > from __future__ import absolute_import
> -  > from . import foo
> -  > def bar():
> -  > # should not cause "higher-level import should come first"
> -  > from .. import unsorted
> -  > # but other errors should be detected
> -  > from .. import more
> -  > import testpackage.subpackage.levelpriority
> -  > EOF
> -
> -  $ cat > testpackage/importmodulefromsub.py << EOF
> -  > from __future__ import absolute_import
> -  > from .subpackage import foo  # not a "direct symbol import"
> -  > EOF
> -
> -  $ cat > testpackage/importsymbolfromsub.py << EOF
> -  > from __future__ import absolute_import
> -  > from .subpackage import foo, nonmodule
> -  > EOF
> -
> -  $ cat > testpackage/sortedentries.py << EOF
> -  > from __future__ import absolute_import
> -  > from . import (
> -  > foo,
> -  > bar,
> -  > )
> -  > EOF
> -
> -  $ cat > testpackage/importfromalias.py << EOF
> -  > from __future__ import absolute_import
> -  > from . import ui
> -  > EOF
> -
> -  $ cat > testpackage/importfromrelative.py << EOF
> -  > from __future__ import absolute_import
> -  > from testpackage.unsorted import foo
> -  > EOF
> -
> -  $ mkdir testpackage2
> -  $ touch testpackage2/__init__.py
> -
> -  $ cat > testpackage2/latesymbolimport.py << EOF
> -  > from __future__ import absolute_import
> -  > from testpackage import unsorted
> -  > from mercurial.node import hex
> -  > EOF
> -
> -  $ python "$import_checker" testpackage*/*.py testpackage/subpackage/*.py
> -  testpackage/importalias.py:2: ui module must be "as" aliased to uimod
> -  testpackage/importfromalias.py:2: ui from testpackage must be "as" aliased 
> to uimod
> -  testpackage/importfromrelative.py:2: import should be relative: 
> testpackage.unsor

Re: [PATCH 3 of 7] parsers: avoid PyList_Append when parsing obs markers

2017-03-16 Thread Gregory Szorc
On Thu, Mar 16, 2017 at 9:50 AM, Augie Fackler  wrote:

> On Mon, Mar 13, 2017 at 10:24:21PM -0700, Gregory Szorc wrote:
> > On Mon, Mar 13, 2017 at 10:15 PM, Gregory Szorc  >
> > wrote:
> > Assuming there is some truth to the numbers, holy cow the overhead of
> > PyObject creation is crazy. I suddenly feel like auditing the C code for
> > everywhere we're instantiating PyObjects before it is necessary. I know
> we
> > do this in the revlog index. I wonder if dirstate is impacted...
>
> Yeah, PyObject allocation can be pretty nasty. In my toy rust version
> of fm1readmarkers, it's 100x faster than the C code was, then 3x
> slower overall due to time spent copying data into PyObjects.
>

!!!

If it is 3x slower in the end, I highly suspect something sub-optimal with
the Rust -> PyObject code path. My guess would be having to allocate memory
and copy data for the hashes into PyBytes instances. We can leverage
memoryview or any object implementing the buffer protocol so we can avoid
that copy. You still pay for the PyObject overhead. But at least you aren't
making extra copies of data.

Also, I'm really curious when obs markers actually need to be realized.
There is validation after parsing that successors aren't nullid. That can
easily be inlined into C or deferred until first access. In theory, we
could create our own Python type behaving as a sequence that turned C
structs to PyObjects on demand. I'm just not sure if that buys us anything.
The second you iterate over markers from Python, you throw away that
optimization.

Perhaps it would be better for the obs marker API to conceptually be a
black box store that exposed primitives like "find X for ." That way,
all the expensive computation can be done in C on raw data structures and
we only realize PyObjects as needed. For cases where you are dealing with
lists of fixed-width values, you could return an array of packed data
instead of N PyObjects. Come to think of it, the computation of just hidden
nodes might be the only super critical part to be all in Python. If we can
do that in C without realizing tons PyObjects, I think a lot of read-only
operations/commands just got a lot faster.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 3 of 7] parsers: avoid PyList_Append when parsing obs markers

2017-03-16 Thread Augie Fackler

> On Mar 16, 2017, at 10:09, Gregory Szorc  wrote:
> 
>> On Thu, Mar 16, 2017 at 9:50 AM, Augie Fackler  wrote:
>> On Mon, Mar 13, 2017 at 10:24:21PM -0700, Gregory Szorc wrote:
>> > On Mon, Mar 13, 2017 at 10:15 PM, Gregory Szorc 
>> > wrote:
>> > Assuming there is some truth to the numbers, holy cow the overhead of
>> > PyObject creation is crazy. I suddenly feel like auditing the C code for
>> > everywhere we're instantiating PyObjects before it is necessary. I know we
>> > do this in the revlog index. I wonder if dirstate is impacted...
>> 
>> Yeah, PyObject allocation can be pretty nasty. In my toy rust version
>> of fm1readmarkers, it's 100x faster than the C code was, then 3x
>> slower overall due to time spent copying data into PyObjects.
>> 
> !!!

Yeah, the actual parsing step was so fast I almost didn't believe it. Zero-copy 
parsers are pretty great.

> 
> If it is 3x slower in the end, I highly suspect something sub-optimal with 
> the Rust -> PyObject code path. My guess would be having to allocate memory 
> and copy data for the hashes into PyBytes instances. We can leverage 
> memoryview or any object implementing the buffer protocol so we can avoid 
> that copy. You still pay for the PyObject overhead. But at least you aren't 
> making extra copies of data.

My suspicion is that it's all the string copies, yeah. I also have wondered 
about the bindings I'm using doing something suboptimal with the GIL, but I 
haven't had time to wade through it or try and profile it.

> 
> Also, I'm really curious when obs markers actually need to be realized. There 
> is validation after parsing that successors aren't nullid. That can easily be 
> inlined into C or deferred until first access. In theory, we could create our 
> own Python type behaving as a sequence that turned C structs to PyObjects on 
> demand. I'm just not sure if that buys us anything. The second you iterate 
> over markers from Python, you throw away that optimization. 
> 
> Perhaps it would be better for the obs marker API to conceptually be a black 
> box store that exposed primitives like "find X for ." That way, all the 
> expensive computation can be done in C on raw data structures and we only 
> realize PyObjects as needed. For cases where you are dealing with lists of 
> fixed-width values, you could return an array of packed data instead of N 
> PyObjects. Come to think of it, the computation of just hidden nodes might be 
> the only super critical part to be all in Python. If we can do that in C 
> without realizing tons PyObjects, I think a lot of read-only 
> operations/commands just got a lot faster.

If we build that interface, the rust code I've got sitting around (using nom) 
is probably actually worth exploring in more detail.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: Dropping support for Python 2.6 on Windows

2017-03-16 Thread Augie Fackler
On Thu, Mar 16, 2017 at 09:54:27AM -0700, Gregory Szorc wrote:
> There is a brewing discussion about the future of Python 2.6 in Mercurial.
> I'd like to start with what I think will be an easy proposal: officially
> dropping support for 2.6 on Windows.

I'm in favor of this. Perhaps also sound the alarm that 2.6 will be
dropped either in 4.3 or 4.4, since we keep accidentally breaking it,
and dropping it entirely would be a nice quality of life improvement
for the devs. Also, there's some work afoot in service of pypi and pip
that should let us get cffi'd SecureTransport bindings on OS X, and
probably also a nicer http client I don't have to write, but thoes are
all unlikely to support 2.6.

>
> First, I think dropping 2.6 on Windows doesn't really buy us anything
> significant. 2.6 and 2.7 build with the same (ancient) Visual Studio
> toolchain. So it isn't like 2.6 is holding us back on C primitives we can
> use or anything. Also, I'm pretty sure none of the Mercurial on Windows
> packages we (or others) distribute use Python 2.6. So I don't think we save
> packagers any work.
>
> My main reason for dropping 2.6 on Windows is to get the policy change out
> of the way.
>
> Supporting this proposal is the fact that (correct me if I'm wrong)
> Mercurial with 2.6 on Windows is not tested nor widely used (see previous
> point about no packages targeting it). The only way (I think) people can
> get Mercurial running with 2.6 on Windows is if they download the source
> and compile it locally (possibly via pip). I think that's generally a small
> set of all Mercurial users on Windows and Python 2.6 users are a sliver of
> that population.
>
> Furthermore, I'm not aware of anyone in the Mercurial project doing Python
> 2.6 development on Windows. Linux and 2.6, yes. Windows and 2.7, yes. But
> not 2.6 on Windows.
>
> If we can't adequately test and support Mercurial with Python 2.6 on
> Windows, I argue it shouldn't be supported.
>
> My formal proposal is:
>
> a) establish a policy that Mercurial with Python 2.6 is not supported on
> Windows starting in the 4.2 release
> b) setup.py and `hg` reject Python 2.6 on Windows

> ___
> 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 v2] exewrapper: prefer HackableMercurial python if availbale

2017-03-16 Thread Augie Fackler
On Mon, Mar 13, 2017 at 01:06:41PM -0700, Kostia Balytskyi wrote:
> # HG changeset patch
> # User Kostia Balytskyi 
> # Date 1489434253 25200
> #  Mon Mar 13 12:44:13 2017 -0700
> # Node ID 83925d3a3306e7023b4b43757812285b40fcd90b
> # Parent  7548522742b5f4f9f5c0881ae4a2783ecda2f969
> exewrapper: prefer HackableMercurial python if availbale

Sure, queued. Seems like the right choice.

>
> Currently hg.exe will only try to load python27.dll from hg-python
> subdir if PYTHONHOME environment variable is not set. I think that
> it is better to check whether 'hg-python' subdir exists and load
> python from it in that case, regardless of environment. This allows
> for reliable approach of distributing Mercurial with its own Python.
>
> diff --git a/mercurial/exewrapper.c b/mercurial/exewrapper.c
> --- a/mercurial/exewrapper.c
> +++ b/mercurial/exewrapper.c
> @@ -67,51 +67,35 @@ int main(int argc, char *argv[])
>   }
>
>   pydll = NULL;
> - /*
> - We first check, that environment variable PYTHONHOME is *not* set.
> - This just mimicks the behavior of the regular python.exe, which uses
> - PYTHONHOME to find its installation directory (if it has been set).
> - Note: Users of HackableMercurial are expected to *not* set PYTHONHOME!
> - */
> - if (GetEnvironmentVariable("PYTHONHOME", envpyhome,
> -sizeof(envpyhome)) == 0)
> - {
> - /*
> - Environment var PYTHONHOME is *not* set. Let's see if we are
> - running inside a HackableMercurial.
> - */
> +
> + p = strrchr(pyhome, '\\');
> + if (p == NULL) {
> + err = "can't find backslash in module filename";
> + goto bail;
> + }
> + *p = 0; /* cut at directory */
> +
> + /* check for private Python of HackableMercurial */
> + strcat_s(pyhome, sizeof(pyhome), "\\hg-python");
>
> - p = strrchr(pyhome, '\\');
> - if (p == NULL) {
> - err = "can't find backslash in module filename";
> + hfind = FindFirstFile(pyhome, &fdata);
> + if (hfind != INVALID_HANDLE_VALUE) {
> + /* Path .\hg-python exists. We are probably in HackableMercurial
> + scenario, so let's load python dll from this dir. */
> + FindClose(hfind);
> + strcpy_s(pydllfile, sizeof(pydllfile), pyhome);
> + strcat_s(pydllfile, sizeof(pydllfile), "\\" HGPYTHONLIB ".dll");
> + pydll = LoadLibrary(pydllfile);
> + if (pydll == NULL) {
> + err = "failed to load private Python DLL " HGPYTHONLIB 
> ".dll";
>   goto bail;
>   }
> - *p = 0; /* cut at directory */
> -
> - /* check for private Python of HackableMercurial */
> - strcat_s(pyhome, sizeof(pyhome), "\\hg-python");
> -
> - hfind = FindFirstFile(pyhome, &fdata);
> - if (hfind != INVALID_HANDLE_VALUE) {
> - /* path pyhome exists, let's use it */
> - FindClose(hfind);
> - strcpy_s(pydllfile, sizeof(pydllfile), pyhome);
> - strcat_s(pydllfile, sizeof(pydllfile),
> -  "\\" HGPYTHONLIB ".dll");
> - pydll = LoadLibrary(pydllfile);
> - if (pydll == NULL) {
> - err = "failed to load private Python DLL "
> -   HGPYTHONLIB ".dll";
> - goto bail;
> - }
> - Py_SetPythonHome = (void*)GetProcAddress(pydll,
> - "Py_SetPythonHome");
> - if (Py_SetPythonHome == NULL) {
> - err = "failed to get Py_SetPythonHome";
> - goto bail;
> - }
> - Py_SetPythonHome(pyhome);
> + Py_SetPythonHome = (void*)GetProcAddress(pydll, 
> "Py_SetPythonHome");
> + if (Py_SetPythonHome == NULL) {
> + err = "failed to get Py_SetPythonHome";
> + goto bail;
>   }
> + Py_SetPythonHome(pyhome);
>   }
>
>   if (pydll == NULL) {
> ___
> 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: Dropping support for Python 2.6 on Windows

2017-03-16 Thread Siddharth Agarwal

On 3/16/17 09:54, Gregory Szorc wrote:
There is a brewing discussion about the future of Python 2.6 in 
Mercurial. I'd like to start with what I think will be an easy 
proposal: officially dropping support for 2.6 on Windows.


Sounds reasonable to me.



First, I think dropping 2.6 on Windows doesn't really buy us anything 
significant. 2.6 and 2.7 build with the same (ancient) Visual Studio 
toolchain. So it isn't like 2.6 is holding us back on C primitives we 
can use or anything. Also, I'm pretty sure none of the Mercurial on 
Windows packages we (or others) distribute use Python 2.6. So I don't 
think we save packagers any work.


My main reason for dropping 2.6 on Windows is to get the policy change 
out of the way.


Supporting this proposal is the fact that (correct me if I'm wrong) 
Mercurial with 2.6 on Windows is not tested nor widely used (see 
previous point about no packages targeting it). The only way (I think) 
people can get Mercurial running with 2.6 on Windows is if they 
download the source and compile it locally (possibly via pip). I think 
that's generally a small set of all Mercurial users on Windows and 
Python 2.6 users are a sliver of that population.


Furthermore, I'm not aware of anyone in the Mercurial project doing 
Python 2.6 development on Windows. Linux and 2.6, yes. Windows and 
2.7, yes. But not 2.6 on Windows.


If we can't adequately test and support Mercurial with Python 2.6 on 
Windows, I argue it shouldn't be supported.


My formal proposal is:

a) establish a policy that Mercurial with Python 2.6 is not supported 
on Windows starting in the 4.2 release

b) setup.py and `hg` reject Python 2.6 on Windows


___
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 7 of 7] py3: prove hg tip works

2017-03-16 Thread Augie Fackler
On Mon, Mar 13, 2017 at 11:59:08AM -0700, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1489422293 25200
> #  Mon Mar 13 09:24:53 2017 -0700
> # Node ID f414ec9383e4c4dde3cbede18ef6afd71a78b474
> # Parent  2657aad32bdde8ab6225d988a0a5cd979f6834d1
> py3: prove hg tip works

Very nice. Queued.

>
> diff --git a/tests/test-check-py3-commands.t b/tests/test-check-py3-commands.t
> --- a/tests/test-check-py3-commands.t
> +++ b/tests/test-check-py3-commands.t
> @@ -51,6 +51,17 @@ out some potential warnings that come fr
>\s*14 (re)
>$ $PYTHON3 $HGBIN files | wc -l
>\s*15 (re)
> +
> +Test if `hg tip` works:
> +
> +  $ $PYTHON3 $HGBIN tip
> +  changeset:   10:e76ed1e480ef
> +  tag: tip
> +  user:oxymo...@cinder.waste.org
> +  date:Tue May 03 23:37:43 2005 -0800
> +  summary: Fix linking of changeset revs when merging
> +
> +
>$ cd ..
>  #endif
>
> ___
> 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 3 of 3] py3: call codecs.escape_encode() directly

2017-03-16 Thread Augie Fackler
On Thu, Mar 16, 2017 at 12:09:50AM +0900, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1489588119 -32400
> #  Wed Mar 15 23:28:39 2017 +0900
> # Node ID fb6b172146566c203a18113536002a6f4b296879
> # Parent  8b8d561c82ee5c11827674dfff2866067d034eea
> py3: call codecs.escape_encode() directly

Queued, thanks.

>
> string_escape doesn't exist on Python 3, but fortunately the undocumented
> codecs.escape_encode() function exists on CPython 2.6, 2.7, 3.5 and PyPy 5.6.
> So let's use it for now.
>
> http://stackoverflow.com/a/23151714
>
> diff --git a/mercurial/util.py b/mercurial/util.py
> --- a/mercurial/util.py
> +++ b/mercurial/util.py
> @@ -17,6 +17,7 @@ from __future__ import absolute_import
>
>  import bz2
>  import calendar
> +import codecs
>  import collections
>  import datetime
>  import errno
> @@ -2131,7 +2132,9 @@ bytecount = unitcountfn(
>  )
>
>  def escapestr(s):
> -return s.encode('string_escape')
> +# call underlying function of s.encode('string_escape') directly for
> +# Python 3 compatibility
> +return codecs.escape_encode(s)[0]
>
>  def uirepr(s):
>  # Avoid double backslash in Windows path repr()
> ___
> 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] branchmap: handle nullrev in setcachedata

2017-03-16 Thread Augie Fackler
On Wed, Mar 15, 2017 at 03:51:27PM -0700, Durham Goode wrote:
> # HG changeset patch
> # User Durham Goode 
> # Date 1489618137 25200
> #  Wed Mar 15 15:48:57 2017 -0700
> # Node ID 6257ea07d629e83e85f68d0c83202b4111f6d4fd
> # Parent  e83302d437485620c9bc25921f724af34cd5dd55
> branchmap: handle nullrev in setcachedata

Queued, thanks.

>
> 906be86990 recently changed to switch from:
>
>   self._rbcrevs[rbcrevidx:rbcrevidx + _rbcrecsize] = rec
>
> to
>
>   pack_into(_rbcrecfmt, self._rbcrevs, rbcrevidx, node, branchidx)
>
> This causes an exception if rbcrevidx is -1 (i.e. the nullrev). The old code
> handled this because python handles out of bound sets to arrays gracefully. 
> The
> new code throws because the self._rbcrevs buffer isn't long enough to write 8
> bytes to.  Normally it would've been resized by the immediately preceding 
> line,
> but because the 0 length buffer is greater than the idx (-1) times the size, 
> no
> resize happens.
>
> Setting the branch for the nullrev doesn't make sense anyway, so let's skip 
> it.
> This was caught by external tests in the Facebook extensions repo, but I've
> added a test here that catches the issue.
>
> diff --git a/mercurial/branchmap.py b/mercurial/branchmap.py
> --- a/mercurial/branchmap.py
> +++ b/mercurial/branchmap.py
> @@ -452,6 +452,8 @@ class revbranchcache(object):
>
>  def _setcachedata(self, rev, node, branchidx):
>  """Writes the node's branch data to the in-memory cache data."""
> +if rev == nullrev:
> +return
>  rbcrevidx = rev * _rbcrecsize
>  if len(self._rbcrevs) < rbcrevidx + _rbcrecsize:
>  self._rbcrevs.extend('\0' *
> diff --git a/tests/test-branches.t b/tests/test-branches.t
> --- a/tests/test-branches.t
> +++ b/tests/test-branches.t
> @@ -1,5 +1,10 @@
>$ hg init a
>$ cd a
> +
> +Verify checking branch of nullrev before the cache is created doesnt crash
> +  $ hg log -r 'branch(.)' -T '{branch}\n'
> +
> +Basic test
>$ echo 'root' >root
>$ hg add root
>$ hg commit -d '0 0' -m "Adding root node"
> ___
> 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 3 of 7] parsers: avoid PyList_Append when parsing obs markers

2017-03-16 Thread Gregory Szorc
On Thu, Mar 16, 2017 at 10:12 AM, Augie Fackler  wrote:

>
> > On Mar 16, 2017, at 10:09, Gregory Szorc 
> wrote:
> >
> >> On Thu, Mar 16, 2017 at 9:50 AM, Augie Fackler  wrote:
> >> On Mon, Mar 13, 2017 at 10:24:21PM -0700, Gregory Szorc wrote:
> >> > On Mon, Mar 13, 2017 at 10:15 PM, Gregory Szorc <
> gregory.sz...@gmail.com>
> >> > wrote:
> >> > Assuming there is some truth to the numbers, holy cow the overhead of
> >> > PyObject creation is crazy. I suddenly feel like auditing the C code
> for
> >> > everywhere we're instantiating PyObjects before it is necessary. I
> know we
> >> > do this in the revlog index. I wonder if dirstate is impacted...
> >>
> >> Yeah, PyObject allocation can be pretty nasty. In my toy rust version
> >> of fm1readmarkers, it's 100x faster than the C code was, then 3x
> >> slower overall due to time spent copying data into PyObjects.
> >>
> > !!!
>
> Yeah, the actual parsing step was so fast I almost didn't believe it.
> Zero-copy parsers are pretty great.
>
> >
> > If it is 3x slower in the end, I highly suspect something sub-optimal
> with the Rust -> PyObject code path. My guess would be having to allocate
> memory and copy data for the hashes into PyBytes instances. We can leverage
> memoryview or any object implementing the buffer protocol so we can avoid
> that copy. You still pay for the PyObject overhead. But at least you aren't
> making extra copies of data.
>
> My suspicion is that it's all the string copies, yeah. I also have
> wondered about the bindings I'm using doing something suboptimal with the
> GIL, but I haven't had time to wade through it or try and profile it.
>
> >
> > Also, I'm really curious when obs markers actually need to be realized.
> There is validation after parsing that successors aren't nullid. That can
> easily be inlined into C or deferred until first access. In theory, we
> could create our own Python type behaving as a sequence that turned C
> structs to PyObjects on demand. I'm just not sure if that buys us anything.
> The second you iterate over markers from Python, you throw away that
> optimization.
> >
> > Perhaps it would be better for the obs marker API to conceptually be a
> black box store that exposed primitives like "find X for ." That way,
> all the expensive computation can be done in C on raw data structures and
> we only realize PyObjects as needed. For cases where you are dealing with
> lists of fixed-width values, you could return an array of packed data
> instead of N PyObjects. Come to think of it, the computation of just hidden
> nodes might be the only super critical part to be all in Python. If we can
> do that in C without realizing tons PyObjects, I think a lot of read-only
> operations/commands just got a lot faster.
>
> If we build that interface, the rust code I've got sitting around (using
> nom) is probably actually worth exploring in more detail.


Last time we had the Rust discussion, we couldn't ship Rust due to distro
packaging support. Has that changed?

FWIW, Firefox appears to be driving a lot of distro support for Rust.
Firefox 54+ now require Rust to build. Furthermore, Firefox is pretty
aggressive about adopting new versions of Rust. What this means is that the
next Firefox ESR (after 52, which was released last week) will effectively
require distros to support whatever version of Rust that ESR is using. I'm
not exactly where distros are w.r.t. Rust support today. But the major ones
all know they need to get their Rust story in order for the next Firefox
ESR, which I think is sometime in 2018. Ask me over beers what those
conversations were like :)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 3 of 7] parsers: avoid PyList_Append when parsing obs markers

2017-03-16 Thread Augie Fackler

> On Mar 16, 2017, at 10:43, Gregory Szorc  wrote:
> 
> Last time we had the Rust discussion, we couldn't ship Rust due to distro 
> packaging support. Has that changed?

My gut feeling with my maintainer hat on is that any rust speedups would need 
to be opt-in, much like today's C speedups. My understanding of Rust is that 
it'll have significantly fewer ABI woes for our needs than C++ might.

> FWIW, Firefox appears to be driving a lot of distro support for Rust. Firefox 
> 54+ now require Rust to build. Furthermore, Firefox is pretty aggressive 
> about adopting new versions of Rust. What this means is that the next Firefox 
> ESR (after 52, which was released last week) will effectively require distros 
> to support whatever version of Rust that ESR is using. I'm not exactly where 
> distros are w.r.t. Rust support today. But the major ones all know they need 
> to get their Rust story in order for the next Firefox ESR, which I think is 
> sometime in 2018. Ask me over beers what those conversations were like :)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: Dropping support for Python 2.6 on Windows

2017-03-16 Thread Simon Farnsworth

On 16/03/2017 10:14, Augie Fackler wrote:

On Thu, Mar 16, 2017 at 09:54:27AM -0700, Gregory Szorc wrote:

There is a brewing discussion about the future of Python 2.6 in Mercurial.
I'd like to start with what I think will be an easy proposal: officially
dropping support for 2.6 on Windows.


I'm in favor of this. Perhaps also sound the alarm that 2.6 will be
dropped either in 4.3 or 4.4, since we keep accidentally breaking it,
and dropping it entirely would be a nice quality of life improvement
for the devs. Also, there's some work afoot in service of pypi and pip
that should let us get cffi'd SecureTransport bindings on OS X, and
probably also a nicer http client I don't have to write, but thoes are
all unlikely to support 2.6.

Just as added data for this decision, we (Facebook) will stop shipping 
and testing Mercurial built against Python 2.6 no later than 2017-04-30 
(when we lose internal security support for our Python 2.6 systems). So 
the 4.3 release is likely to be the last release where we provide Python 
2.6 testing during the freeze.


We're hoping that our last consumers of Python 2.6 Mercurial will move 
onto Python 2.7 before 2017-03-31, so for the 4.3 freeze we're likely to 
only be running the test suite, not also getting feedback from real users.

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


[PATCH] util: explicitly tests for None

2017-03-16 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1489615634 25200
#  Wed Mar 15 15:07:14 2017 -0700
# Node ID 4f99a4fb0482a44178f96c29678ef4630056ff4e
# Parent  a5bad127128d8f60060be53d161acfa7a32a17d5
# EXP-Topic mutable-default
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 4f99a4fb0482
util: explicitly tests for None

Changeset 8b6927eb7efd removed the mutable default value, but did not explicitly
tested for None. Such implicit checking can introduce semantic and performance
issue. We move to an explicit check for None as recommended by PEP8:

https://www.python.org/dev/peps/pep-0008/#programming-recommendations

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1831,7 +1831,8 @@ def parsetimezone(s):
 def strdate(string, format, defaults=None):
 """parse a localized time string and return a (unixtime, offset) tuple.
 if the string cannot be parsed, ValueError is raised."""
-defaults = defaults or {}
+if defaults is None:
+defaults = {}
 
 # NOTE: unixtime = localunixtime + offset
 offset, date = parsetimezone(string)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


mercurial@31427: 4 new changesets

2017-03-16 Thread Mercurial Commits
4 new changesets in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/4acc49335a6e
changeset:   31424:4acc49335a6e
user:Martin von Zweigbergk 
date:Wed Mar 15 09:30:50 2017 -0700
summary: py3: optimize py3 compat.bytechr using Struct.pack

https://www.mercurial-scm.org/repo/hg/rev/63a39d647888
changeset:   31425:63a39d647888
user:Martin von Zweigbergk 
date:Wed Mar 15 09:32:18 2017 -0700
summary: py3: make py3 compat.iterbytestr simpler and faster

https://www.mercurial-scm.org/repo/hg/rev/43a7dfbead0c
changeset:   31426:43a7dfbead0c
user:Gregory Szorc 
date:Mon Mar 13 17:49:13 2017 -0700
summary: parsers: handle refcounting of "parents" consistently

https://www.mercurial-scm.org/repo/hg/rev/b2fb0fd239b8
changeset:   31427:b2fb0fd239b8
bookmark:@
tag: tip
user:Pulkit Goyal <7895pul...@gmail.com>
date:Thu Mar 16 10:10:00 2017 +0530
summary: py3: convert opts back to bytes for status

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


[PATCH] wfile: fix deprecation warning version

2017-03-16 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1489688275 25200
#  Thu Mar 16 11:17:55 2017 -0700
# Node ID d26d5987f6ef6a8a260f2aef67838a66b9fe
# Parent  b2fb0fd239b88f0f9ec70c43f30d2f1ef0cb1049
# EXP-Topic fix-depr
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r d26d5987f6ef
wfile: fix deprecation warning version

The patch lingered a bit too long in my local clone and I messed up when I
updated the version number. Since nobody caught it, I'm fixing the version after
the fact.

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -977,7 +977,7 @@ class localrepository(object):
 return self.dirstate.pathto(f, cwd)
 
 def wfile(self, f, mode='r'):
-self.ui.deprecwarn("use 'repo.wvfs' instead of 'repo.wfile'", '4.1')
+self.ui.deprecwarn("use 'repo.wvfs' instead of 'repo.wfile'", '4.2')
 return self.wvfs(f, mode)
 
 def _link(self, f):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] util: explicitly tests for None

2017-03-16 Thread Pierre-Yves David

That one is a V2, but I failed to invoque `hg email` correctly :-(

On 03/16/2017 11:16 AM, Pierre-Yves David wrote:

# HG changeset patch
# User Pierre-Yves David 
# Date 1489615634 25200
#  Wed Mar 15 15:07:14 2017 -0700
# Node ID 4f99a4fb0482a44178f96c29678ef4630056ff4e
# Parent  a5bad127128d8f60060be53d161acfa7a32a17d5
# EXP-Topic mutable-default
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 4f99a4fb0482
util: explicitly tests for None

Changeset 8b6927eb7efd removed the mutable default value, but did not explicitly
tested for None. Such implicit checking can introduce semantic and performance
issue. We move to an explicit check for None as recommended by PEP8:

https://www.python.org/dev/peps/pep-0008/#programming-recommendations

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1831,7 +1831,8 @@ def parsetimezone(s):
 def strdate(string, format, defaults=None):
 """parse a localized time string and return a (unixtime, offset) tuple.
 if the string cannot be parsed, ValueError is raised."""
-defaults = defaults or {}
+if defaults is None:
+defaults = {}

 # NOTE: unixtime = localunixtime + offset
 offset, date = parsetimezone(string)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel



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


[PATCH] context: simplify call to icase matcher in 'match()'

2017-03-16 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1489617482 25200
#  Wed Mar 15 15:38:02 2017 -0700
# Node ID d980847dfbb24f63306441d86a75741df851d3ee
# Parent  a5bad127128d8f60060be53d161acfa7a32a17d5
# EXP-Topic cleanup
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r d980847dfbb2
context: simplify call to icase matcher in 'match()'

The two function takes the very same arguments. We make this clearer and less
error prone by dispatching on the function only and having a single call point
in the code.

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -1525,15 +1525,13 @@ class workingctx(committablectx):
 
 # Only a case insensitive filesystem needs magic to translate user 
input
 # to actual case in the filesystem.
+matcherfunc = matchmod.match
 if not util.fscasesensitive(r.root):
-return matchmod.icasefsmatcher(r.root, r.getcwd(), pats,
-   include, exclude, default, 
r.auditor,
-   self, listsubrepos=listsubrepos,
-   badfn=badfn)
-return matchmod.match(r.root, r.getcwd(), pats,
-  include, exclude, default,
-  auditor=r.auditor, ctx=self,
-  listsubrepos=listsubrepos, badfn=badfn)
+matcherfunc = matchmod.icasefsmatcher
+return matcherfunc(r.root, r.getcwd(), pats,
+   include, exclude, default,
+   auditor=r.auditor, ctx=self,
+   listsubrepos=listsubrepos, badfn=badfn)
 
 def _filtersuspectsymlink(self, files):
 if not files or self._repo.dirstate._checklink:
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[Bug 5506] New: bundle -t zstd fails on long-lived repository

2017-03-16 Thread mercurial-bugs
https://bz.mercurial-scm.org/show_bug.cgi?id=5506

Bug ID: 5506
   Summary: bundle -t zstd fails on long-lived repository
   Product: Mercurial
   Version: 4.1.1
  Hardware: All
OS: All
Status: UNCONFIRMED
  Severity: bug
  Priority: wish
 Component: bundle2
  Assignee: bugzi...@mercurial-scm.org
  Reporter: fo...@lares.dti.ne.jp
CC: mercurial-devel@mercurial-scm.org,
pierre-yves.da...@ens-lyon.org

On long-lived repository (5.5 years or so, or one created with
usegeneraldelta=no, explicitly), "hg bundle --type zstd" fails
with error below.

File "/mercurial/bundle2.py", line 1320, in writebundle
  header, comp = bundletypes[bundletype]
  KeyError: 'HG10ZS'

If current repository doesn't have "generaldelta" in its
requirements, parsebundlespec() in exchange.py returns "v1" as
"appropriate bundle version".

This causes unknown bundle type name "HG10ZS" for "hg bundle
--type zstd".

This issue can be reproduced by steps below.

  $ hg --config format.usegeneraldelta=no init repo
  $ echo a > repo/a
  $ hg -R repo commit -Am '#0'
  $ hg -R repo bundle --all --type zstd bundle.zstd

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


[PATCH 2 of 2 STABLE] exchange: use v2 bundles for modern compression engines (issue5506)

2017-03-16 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1489692795 25200
#  Thu Mar 16 12:33:15 2017 -0700
# Branch stable
# Node ID 35019434aad6952ee9b3b41ee78a5a3efea9a0ab
# Parent  8fed20619acd7a4346408e5819a1c91c52a39ed2
exchange: use v2 bundles for modern compression engines (issue5506)

Previously, `hg bundle zstd` on a non-generaldelta repo would
attempt to use a v1 bundle. This would fail because zstd is not
supported on v1 bundles.

This patch changes the behavior to automatically use a v2 bundle
when the user explicitly requests a bundlespec that is a compression
engine not supported on v1. If the bundlespec is -v1, it is
still explicitly rejected because that request cannot be fulfilled.

diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -130,8 +130,12 @@ def parsebundlespec(repo, spec, strict=T
 if spec in util.compengines.supportedbundlenames:
 compression = spec
 version = 'v1'
+# Generaldelta repos require v2.
 if 'generaldelta' in repo.requirements:
 version = 'v2'
+# Modern compression engines require v2.
+if compression not in _bundlespecv1compengines:
+version = 'v2'
 elif spec in _bundlespeccgversions:
 if spec == 'packed1':
 compression = 'none'
diff --git a/tests/test-bundle-type.t b/tests/test-bundle-type.t
--- a/tests/test-bundle-type.t
+++ b/tests/test-bundle-type.t
@@ -187,9 +187,7 @@ Explicit request for zstd on non-general
   $ hg --config format.usegeneraldelta=false init nogd
   $ hg -q -R nogd pull t1
   $ hg -R nogd bundle -a -t zstd nogd-zstd
-  abort: compression engine zstd is not supported on v1 bundles
-  (see 'hg help bundle' for supported values for --type)
-  [255]
+  1 changesets found
 
 zstd-v1 always fails
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 2 STABLE] exchange: reject new compression engines for v1 bundles (issue5506)

2017-03-16 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1489692236 25200
#  Thu Mar 16 12:23:56 2017 -0700
# Branch stable
# Node ID 8fed20619acd7a4346408e5819a1c91c52a39ed2
# Parent  86cd1f2cfff5d5f5ebda227b147ad71a59058323
exchange: reject new compression engines for v1 bundles (issue5506)

Version 1 bundles only support a fixed set of compression engines.
Before this change, we would accept any compression engine for v1
bundles, even those that may not work on v1. This could lead to
an error.

We define a fixed set of compression engines known to work with v1
bundles and we add checking to ensure a newer engine (like zstd)
won't work with v1 bundles.

I also took the liberty of adding test coverage for unknown compression
names because I noticed we didn't have coverage of it before.

diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -44,6 +44,9 @@ urlreq = util.urlreq
  'bundle2': '02', #legacy
 }
 
+# Compression engines allowed in version 1. THIS SHOULD NEVER CHANGE.
+_bundlespecv1compengines = set(['gzip', 'bzip2', 'none'])
+
 def parsebundlespec(repo, spec, strict=True, externalnames=False):
 """Parse a bundle string specification into parts.
 
@@ -139,6 +142,12 @@ def parsebundlespec(repo, spec, strict=T
 raise error.UnsupportedBundleSpecification(
 _('%s is not a recognized bundle specification') % spec)
 
+# Bundle version 1 only supports a known set of compression engines.
+if version == 'v1' and compression not in _bundlespecv1compengines:
+raise error.UnsupportedBundleSpecification(
+_('compression engine %s is not supported on v1 bundles') %
+compression)
+
 # The specification for packed1 can optionally declare the data formats
 # required to apply it. If we see this metadata, compare against what the
 # repo supports and error if the bundle isn't compatible.
diff --git a/tests/test-bundle-type.t b/tests/test-bundle-type.t
--- a/tests/test-bundle-type.t
+++ b/tests/test-bundle-type.t
@@ -33,6 +33,23 @@ bundle w/o type option
   summary: a
   $ cd ..
 
+Unknown compression type is rejected
+
+  $ hg init t3
+  $ cd t3
+  $ hg -q pull ../b1
+  $ hg bundle -a -t unknown out.hg
+  abort: unknown is not a recognized bundle specification
+  (see 'hg help bundle' for supported values for --type)
+  [255]
+
+  $ hg bundle -a -t unknown-v2 out.hg
+  abort: unknown compression is not supported
+  (see 'hg help bundle' for supported values for --type)
+  [255]
+
+  $ cd ..
+
 test bundle types
 
   $ testbundle() {
@@ -164,6 +181,23 @@ Compression level can be adjusted for bu
   c35a0f9217e65d1fdb90c936ffa7dbe679f83ddf
   zstd-v2
   
+
+Explicit request for zstd on non-generaldelta repos
+
+  $ hg --config format.usegeneraldelta=false init nogd
+  $ hg -q -R nogd pull t1
+  $ hg -R nogd bundle -a -t zstd nogd-zstd
+  abort: compression engine zstd is not supported on v1 bundles
+  (see 'hg help bundle' for supported values for --type)
+  [255]
+
+zstd-v1 always fails
+
+  $ hg -R tzstd bundle -a -t zstd-v1 zstd-v1
+  abort: compression engine zstd is not supported on v1 bundles
+  (see 'hg help bundle' for supported values for --type)
+  [255]
+
 #else
 
 zstd is a valid engine but isn't available
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


hg-git and round-tripping (and file copies?)

2017-03-16 Thread Danek Duvall
In trying to convert

https://hg.java.net/hg/solaris-userland~gate

to a git repo and back, I'm seeing issues at changeset 34, where the hash
changes for reasons I can't see.  If I do a diff of the debug log, I see
it's due to the manifest:

$ diff -u =(hg log -R userland-more --debug -r 34) =(hg log -R 
userland-more.hgagain --debug -r 34 | grep -v "^phase:")
--- /tmp/zshhHyEIb  2017-03-16 11:37:57.601340643 -0700
+++ /tmp/zshlyqHbd  2017-03-16 11:37:57.793642372 -0700
@@ -1,12 +1,10 @@
 no terminfo entry for sitm
-changeset:   34:d20b10eba31725ad8954aa6d20374da512f0e636
-tag: build-149
+changeset:   34:2ccb817b85926f410df2a6bd23000265805088df
 parent:  33:371c8e56136d19872ae7db8d273f9de78c8fa783
 parent:  -1:
-manifest:34:e031f26e68549dadb3dfb4705d429c75622a58b4
+manifest:34:5a12a2a1bf3e7c0f7c30d01bd09a2e37185bcfb6
 user:Norm Jacobs 
 date:Sun Sep 19 13:50:53 2010 -0700
-phase:   public
 files:
components/Makefile
make-rules/prep.mk

and if I use debugdata to look at the manifest at changeset 34, I see:

$ gdiff -a -u =(hg -R userland-more debugdata -m 34) =(hg -R 
userland-more.hgagain debugdata -m 34)
--- /tmp/zshOdnjza  2017-03-16 11:53:16.971130878 +
+++ /tmp/zshzoTzmc  2017-03-16 11:53:17.118194061 +
@@ -24,12 +24,12 @@
 make-rules/setup.py.mk302733d738cc7c6cceb63457442f24f931867472
 make-rules/shared-macros.mk03dd5df583b6e39a17ba66fc6ed6205df7f6be49
 tools/Makefilecc964766028e3b963b4a321c88815d211415006b
-tools/bass-o-matica618ef38ceda467b9a09680dd8b94debcd303037x
+tools/bass-o-matic349f9611499fddf1a110f9488a84fb110c90b7bfx
 tools/build-watch.df69b9a2b6a265c06268733430bbf3f9aa7d5e160x
 tools/build-watch.pl5e23340c7a84ac555e630a5ccdc28eceda95f4b6x
 tools/time.ca0a1f64ff8ac947ce9d045e0448f8ee72f9fd273
-tools/userland-fetch851170bb5cebf2648c53d4909eac26ac2055cdd3x
-tools/userland-unpack0977e35fa356d4cfab889b93613dc75d90d89b6bx
+tools/userland-fetchbae023e70db29fd07f6f989aaa858cfaed09238ax
+tools/userland-unpackb3800b9db86df38a644a653b3095805b269b6ac6x
 transforms/actuatorsc9d84677229efde5f89b1d985de5cd1b09267b56
 transforms/archive-libraries-drop5b346a0133242f460ff66f6689790da094ce27f6
 transforms/comparison-cleanupde1288c586594a171d43a3da5234cb920be408cc

Now, those three files were copied in that changeset, but they're not the
first to be copied, so it's not that, strictly.  But it is the first
changeset in which files were copied without being modified.

The index data is off-by-one, if that makes any difference:

$ hg -R userland-more debugrevlog -d tools/bass-o-matic
# rev p1rev p2rev start   end deltastart base   p1   p2 rawsize totalsize 
compression heads chainlen
0-1-1 0  2175  00006005  6005   
2 10
1 0-1  2175  2228  00005929 11934   
5 11

$ hg -R userland-more.hgagain debugrevlog -d tools/bass-o-matic
# rev p1rev p2rev start   end deltastart base   p1   p2 rawsize totalsize 
compression heads chainlen
0-1-1 0  2174  00006005  6005   
2 10
1 0-1  2174  2227  00005929 11934   
5 11

Any thoughts on how to further debug this?

Or is this just

https://bitbucket.org/durin42/hg-git/issues/46

and I'm out of luck?

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


Re: hg-git and round-tripping (and file copies?)

2017-03-16 Thread Gregory Szorc
On Thu, Mar 16, 2017 at 1:05 PM, Danek Duvall 
wrote:

> In trying to convert
>
> https://hg.java.net/hg/solaris-userland~gate
>
> to a git repo and back, I'm seeing issues at changeset 34, where the hash
> changes for reasons I can't see.  If I do a diff of the debug log, I see
> it's due to the manifest:
>
> $ diff -u =(hg log -R userland-more --debug -r 34) =(hg log -R
> userland-more.hgagain --debug -r 34 | grep -v "^phase:")
> --- /tmp/zshhHyEIb  2017-03-16 11:37:57.601340643 -0700
> +++ /tmp/zshlyqHbd  2017-03-16 11:37:57.793642372 -0700
> @@ -1,12 +1,10 @@
>  no terminfo entry for sitm
> -changeset:   34:d20b10eba31725ad8954aa6d20374da512f0e636
> -tag: build-149
> +changeset:   34:2ccb817b85926f410df2a6bd23000265805088df
>  parent:  33:371c8e56136d19872ae7db8d273f9de78c8fa783
>  parent:  -1:
> -manifest:34:e031f26e68549dadb3dfb4705d429c75622a58b4
> +manifest:34:5a12a2a1bf3e7c0f7c30d01bd09a2e37185bcfb6
>  user:Norm Jacobs 
>  date:Sun Sep 19 13:50:53 2010 -0700
> -phase:   public
>  files:
> components/Makefile
> make-rules/prep.mk
>
> and if I use debugdata to look at the manifest at changeset 34, I see:
>
> $ gdiff -a -u =(hg -R userland-more debugdata -m 34) =(hg -R
> userland-more.hgagain debugdata -m 34)
> --- /tmp/zshOdnjza  2017-03-16 11:53:16.971130878 +
> +++ /tmp/zshzoTzmc  2017-03-16 11:53:17.118194061 +
> @@ -24,12 +24,12 @@
>  make-rules/setup.py.mk302733d738cc7c6cceb63457442f24f931867472
>  make-rules/shared-macros.mk03dd5df583b6e39a17ba66fc6ed6205df7f6be49
>  tools/Makefilecc964766028e3b963b4a321c88815d211415006b
> -tools/bass-o-matica618ef38ceda467b9a09680dd8b94debcd303037x
> +tools/bass-o-matic349f9611499fddf1a110f9488a84fb110c90b7bfx
>  tools/build-watch.df69b9a2b6a265c06268733430bbf3f9aa7d5e160x
>  tools/build-watch.pl5e23340c7a84ac555e630a5ccdc28eceda95f4b6x
>  tools/time.ca0a1f64ff8ac947ce9d045e0448f8ee72f9fd273
> -tools/userland-fetch851170bb5cebf2648c53d4909eac26ac2055cdd3x
> -tools/userland-unpack0977e35fa356d4cfab889b93613dc75d90d89b6bx
> +tools/userland-fetchbae023e70db29fd07f6f989aaa858cfaed09238ax
> +tools/userland-unpackb3800b9db86df38a644a653b3095805b269b6ac6x
>  transforms/actuatorsc9d84677229efde5f89b1d985de5cd1b09267b56
>  transforms/archive-libraries-drop5b346a0133242f460ff66f6689
> 790da094ce27f6
>  transforms/comparison-cleanupde1288c586594a171d43a3da5234cb920be408cc
>
> Now, those three files were copied in that changeset, but they're not the
> first to be copied, so it's not that, strictly.  But it is the first
> changeset in which files were copied without being modified.
>
> The index data is off-by-one, if that makes any difference:
>
> $ hg -R userland-more debugrevlog -d tools/bass-o-matic
> # rev p1rev p2rev start   end deltastart base   p1   p2 rawsize
> totalsize compression heads chainlen
> 0-1-1 0  2175  00006005
> 6005   2 10
> 1 0-1  2175  2228  00005929
>  11934   5 11
>
> $ hg -R userland-more.hgagain debugrevlog -d tools/bass-o-matic
> # rev p1rev p2rev start   end deltastart base   p1   p2 rawsize
> totalsize compression heads chainlen
> 0-1-1 0  2174  00006005
> 6005   2 10
> 1 0-1  2174  2227  00005929
>  11934   5 11
>
> Any thoughts on how to further debug this?
>
> Or is this just
>
> https://bitbucket.org/durin42/hg-git/issues/46
>
> and I'm out of luck?
>

It is effectively impossible to round-trip between Git and Mercurial when
file copies are involved. This is because Mercurial's filelog hashes
include copy metadata and the parent nodes. Git's blob hashes, by contrast,
are effectively content only. When you convert from Mercurial to Git, it
will drop copy metadata (because Git doesn't track it explicitly). Then
when you convert back to Mercurial, the copies have to be detected "just
right" by hg-git for the hashes to align. Furthermore, the files have to be
reintroduced in the same order, or the filelog parents may not align and
the hashes may diverge. If a repo isn't linear, there's a non-zero chance
of that happening.

It is best to have a single canonical repo and replicate from that.
Attempting "syncing" from multiple discrete repos will only lead to
divergence.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 2 of 4] pycompat: add bytestr wrapper which mostly acts as a Python 2 str

2017-03-16 Thread Martin von Zweigbergk via Mercurial-devel
On Thu, Mar 16, 2017 at 8:31 AM, Yuya Nishihara  wrote:
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1488980906 -32400
> #  Wed Mar 08 22:48:26 2017 +0900
> # Node ID aae1bd4b8a03ffe6cb47c23da55b2f70ff5607ef
> # Parent  f39291c08d86082579b891e844cbd56752b44a59
> pycompat: add bytestr wrapper which mostly acts as a Python 2 str
>
> This allows us to handle bytes in mostly the same manner as Python 2 str,
> so we can get rid of ugly s[i:i + 1] hacks:
>
>   s = bytestr(s)
>   while i < len(s):
>   c = s[i]
>   ...
>
> This is the simpler version of the previous RFC patch which tried to preserve
> the bytestr type if possible. New version simply drops the bytestr wrapping
> so we aren't likely to pass a bytestr to a function that expects Python 3
> bytes.
>
> diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
> --- a/mercurial/pycompat.py
> +++ b/mercurial/pycompat.py
> @@ -76,6 +76,67 @@ if ispy3:
>
>  bytechr = struct.Struct('>B').pack
>
> +class bytestr(bytes):
> +"""A bytes which mostly acts as a Python 2 str
> +
> +>>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), 
> bytestr(1)
> +(b'', b'foo', b'ascii', b'1')
> +>>> s = bytestr(b'foo')
> +>>> assert s is bytestr(s)
> +
> +There's no implicit conversion from non-ascii str as its encoding is
> +unknown:
> +
> +>>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
> +Traceback (most recent call last):
> +  ...
> +UnicodeEncodeError: ...
> +
> +Comparison between bytestr and bytes should work:
> +
> +>>> assert bytestr(b'foo') == b'foo'
> +>>> assert b'foo' == bytestr(b'foo')
> +>>> assert b'f' in bytestr(b'foo')
> +>>> assert bytestr(b'f') in b'foo'
> +
> +Sliced elements should be bytes, not integer:
> +
> +>>> s[1], s[:2]
> +(b'o', b'fo')
> +>>> list(s), list(reversed(s))
> +([b'f', b'o', b'o'], [b'o', b'o', b'f'])
> +
> +As bytestr type isn't propagated across operations, you need to cast
> +bytes to bytestr explicitly:
> +
> +>>> s = bytestr(b'foo').upper()
> +>>> t = bytestr(s)
> +>>> s[0], t[0]
> +(70, b'F')
> +
> +Be careful to not pass a bytestr object to a function which expects
> +bytearray-like behavior.
> +
> +>>> t = bytes(t)  # cast to bytes
> +>>> assert type(t) is bytes
> +"""
> +
> +def __new__(cls, s=b''):
> +if isinstance(s, bytestr):
> +return s
> +if not isinstance(s, (bytes, bytearray)):
> +s = str(s).encode(u'ascii')
> +return bytes.__new__(cls, s)
> +
> +def __getitem__(self, key):
> +s = bytes.__getitem__(self, key)
> +if not isinstance(s, bytes):
> +s = bytechr(s)
> +return s
> +
> +def __iter__(self):
> +return iterbytestr(bytes.__iter__(self))
> +
>  def iterbytestr(s):
>  """Iterate bytes as if it were a str object of Python 2"""
>  return map(bytechr, s)
> @@ -146,6 +207,7 @@ else:
>  import cStringIO
>
>  bytechr = chr
> +bytestr = str

Could this even be 'identity' (which apparently doesn't exist, so
would be 'lambda s: s' or something)? Will str(a) create a copy of the
underlying buffer too. I think I know that strings are immutable, so
it shouldn't have to?


>  iterbytestr = iter
>
>  def sysstr(s):
> diff --git a/tests/test-doctest.py b/tests/test-doctest.py
> --- a/tests/test-doctest.py
> +++ b/tests/test-doctest.py
> @@ -34,6 +34,7 @@ testmod('mercurial.minirst')
>  testmod('mercurial.patch')
>  testmod('mercurial.pathutil')
>  testmod('mercurial.parser')
> +testmod('mercurial.pycompat', py3=True)
>  testmod('mercurial.revsetlang')
>  testmod('mercurial.smartset')
>  testmod('mercurial.store')
> ___
> 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 4] pycompat: add bytestr wrapper which mostly acts as a Python 2 str

2017-03-16 Thread Martin von Zweigbergk via Mercurial-devel
On Thu, Mar 16, 2017 at 1:47 PM, Martin von Zweigbergk
 wrote:
> On Thu, Mar 16, 2017 at 8:31 AM, Yuya Nishihara  wrote:
>> # HG changeset patch
>> # User Yuya Nishihara 
>> # Date 1488980906 -32400
>> #  Wed Mar 08 22:48:26 2017 +0900
>> # Node ID aae1bd4b8a03ffe6cb47c23da55b2f70ff5607ef
>> # Parent  f39291c08d86082579b891e844cbd56752b44a59
>> pycompat: add bytestr wrapper which mostly acts as a Python 2 str
>>
>> This allows us to handle bytes in mostly the same manner as Python 2 str,
>> so we can get rid of ugly s[i:i + 1] hacks:
>>
>>   s = bytestr(s)
>>   while i < len(s):
>>   c = s[i]
>>   ...
>>
>> This is the simpler version of the previous RFC patch which tried to preserve
>> the bytestr type if possible. New version simply drops the bytestr wrapping
>> so we aren't likely to pass a bytestr to a function that expects Python 3
>> bytes.
>>
>> diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py
>> --- a/mercurial/pycompat.py
>> +++ b/mercurial/pycompat.py
>> @@ -76,6 +76,67 @@ if ispy3:
>>
>>  bytechr = struct.Struct('>B').pack
>>
>> +class bytestr(bytes):
>> +"""A bytes which mostly acts as a Python 2 str
>> +
>> +>>> bytestr(), bytestr(bytearray(b'foo')), bytestr(u'ascii'), 
>> bytestr(1)
>> +(b'', b'foo', b'ascii', b'1')
>> +>>> s = bytestr(b'foo')
>> +>>> assert s is bytestr(s)
>> +
>> +There's no implicit conversion from non-ascii str as its encoding is
>> +unknown:
>> +
>> +>>> bytestr(chr(0x80)) # doctest: +ELLIPSIS
>> +Traceback (most recent call last):
>> +  ...
>> +UnicodeEncodeError: ...
>> +
>> +Comparison between bytestr and bytes should work:
>> +
>> +>>> assert bytestr(b'foo') == b'foo'
>> +>>> assert b'foo' == bytestr(b'foo')
>> +>>> assert b'f' in bytestr(b'foo')
>> +>>> assert bytestr(b'f') in b'foo'
>> +
>> +Sliced elements should be bytes, not integer:
>> +
>> +>>> s[1], s[:2]
>> +(b'o', b'fo')
>> +>>> list(s), list(reversed(s))
>> +([b'f', b'o', b'o'], [b'o', b'o', b'f'])
>> +
>> +As bytestr type isn't propagated across operations, you need to cast
>> +bytes to bytestr explicitly:
>> +
>> +>>> s = bytestr(b'foo').upper()
>> +>>> t = bytestr(s)
>> +>>> s[0], t[0]
>> +(70, b'F')
>> +
>> +Be careful to not pass a bytestr object to a function which expects
>> +bytearray-like behavior.
>> +
>> +>>> t = bytes(t)  # cast to bytes
>> +>>> assert type(t) is bytes
>> +"""
>> +
>> +def __new__(cls, s=b''):
>> +if isinstance(s, bytestr):
>> +return s
>> +if not isinstance(s, (bytes, bytearray)):
>> +s = str(s).encode(u'ascii')
>> +return bytes.__new__(cls, s)
>> +
>> +def __getitem__(self, key):
>> +s = bytes.__getitem__(self, key)
>> +if not isinstance(s, bytes):
>> +s = bytechr(s)
>> +return s
>> +
>> +def __iter__(self):
>> +return iterbytestr(bytes.__iter__(self))
>> +
>>  def iterbytestr(s):
>>  """Iterate bytes as if it were a str object of Python 2"""
>>  return map(bytechr, s)
>> @@ -146,6 +207,7 @@ else:
>>  import cStringIO
>>
>>  bytechr = chr
>> +bytestr = str
>
> Could this even be 'identity' (which apparently doesn't exist, so
> would be 'lambda s: s' or something)? Will str(a) create a copy of the
> underlying buffer too. I think I know that strings are immutable, so
> it shouldn't have to?

The answer seems to be "no, nothing is copied". I could have sworn
that when I first tested it, "str(a) is b" was False, but I must have
been blind. Sorry about the noise.

>
>
>>  iterbytestr = iter
>>
>>  def sysstr(s):
>> diff --git a/tests/test-doctest.py b/tests/test-doctest.py
>> --- a/tests/test-doctest.py
>> +++ b/tests/test-doctest.py
>> @@ -34,6 +34,7 @@ testmod('mercurial.minirst')
>>  testmod('mercurial.patch')
>>  testmod('mercurial.pathutil')
>>  testmod('mercurial.parser')
>> +testmod('mercurial.pycompat', py3=True)
>>  testmod('mercurial.revsetlang')
>>  testmod('mercurial.smartset')
>>  testmod('mercurial.store')
>> ___
>> 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: hg-git and round-tripping (and file copies?)

2017-03-16 Thread Danek Duvall
Gregory Szorc wrote:

> It is effectively impossible to round-trip between Git and Mercurial when
> file copies are involved. This is because Mercurial's filelog hashes
> include copy metadata and the parent nodes. Git's blob hashes, by contrast,
> are effectively content only. When you convert from Mercurial to Git, it
> will drop copy metadata (because Git doesn't track it explicitly). Then
> when you convert back to Mercurial, the copies have to be detected "just
> right" by hg-git for the hashes to align. Furthermore, the files have to be
> reintroduced in the same order, or the filelog parents may not align and
> the hashes may diverge. If a repo isn't linear, there's a non-zero chance
> of that happening.

Got it.

> It is best to have a single canonical repo and replicate from that.
> Attempting "syncing" from multiple discrete repos will only lead to
> divergence.

Sadly, that's not an option.  We're just going to have to deal with the
breakage, until such time as we can avoid the git intermediary.

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


[PATCH 1 of 2 py3 V2] dirstate: use next(iter) instead of iter.next

2017-03-16 Thread Pulkit Goyal
# HG changeset patch
# User Pulkit Goyal <7895pul...@gmail.com>
# Date 1489634873 -19800
#  Thu Mar 16 08:57:53 2017 +0530
# Node ID c894bad6625973565b21f556896527141f123dd5
# Parent  a5bad127128d8f60060be53d161acfa7a32a17d5
dirstate: use next(iter) instead of iter.next

In Python 3 world, iter.next() is renamed to iter.__next__(). But next(iter)
has the same behaviour. So let's replace iter.next() with next(iter).

diff -r a5bad127128d -r c894bad66259 mercurial/dirstate.py
--- a/mercurial/dirstate.py Wed Mar 15 15:48:57 2017 -0700
+++ b/mercurial/dirstate.py Thu Mar 16 08:57:53 2017 +0530
@@ -1115,9 +1115,8 @@
 else:
 # We may not have walked the full directory tree above,
 # so stat and check everything we missed.
-nf = iter(visit).next
 for st in util.statfiles([join(i) for i in visit]):
-results[nf()] = st
+results[next(iter(visit))] = st
 return results
 
 def status(self, match, subrepos, ignored, clean, unknown):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 2 py3 V2] commands: make sure using byteschr rather than ascii values

2017-03-16 Thread Pulkit Goyal
# HG changeset patch
# User Pulkit Goyal <7895pul...@gmail.com>
# Date 1489635793 -19800
#  Thu Mar 16 09:13:13 2017 +0530
# Node ID ec82445ccda47996e58a0c33fbbe8dbd7be0d2aa
# Parent  c894bad6625973565b21f556896527141f123dd5
commands: make sure using byteschr rather than ascii values

'MAR!?IC' is converted to their ascii values when slicing through it. This
patch uses pycompat.iterbytestr() to get bytes value.

diff -r c894bad66259 -r ec82445ccda4 mercurial/commands.py
--- a/mercurial/commands.py Thu Mar 16 08:57:53 2017 +0530
+++ b/mercurial/commands.py Thu Mar 16 09:13:13 2017 +0530
@@ -4757,7 +4757,7 @@
 stat = repo.status(node1, node2, m,
'ignored' in show, 'clean' in show, 'unknown' in show,
opts.get('subrepos'))
-changestates = zip(states, 'MAR!?IC', stat)
+changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
 
 if (opts.get('all') or opts.get('copies')
 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2 py3 V2] dirstate: use next(iter) instead of iter.next

2017-03-16 Thread Martin von Zweigbergk via Mercurial-devel
On Thu, Mar 16, 2017 at 2:24 PM, Pulkit Goyal <7895pul...@gmail.com> wrote:
> # HG changeset patch
> # User Pulkit Goyal <7895pul...@gmail.com>
> # Date 1489634873 -19800
> #  Thu Mar 16 08:57:53 2017 +0530
> # Node ID c894bad6625973565b21f556896527141f123dd5
> # Parent  a5bad127128d8f60060be53d161acfa7a32a17d5
> dirstate: use next(iter) instead of iter.next
>
> In Python 3 world, iter.next() is renamed to iter.__next__(). But next(iter)
> has the same behaviour. So let's replace iter.next() with next(iter).
>
> diff -r a5bad127128d -r c894bad66259 mercurial/dirstate.py
> --- a/mercurial/dirstate.py Wed Mar 15 15:48:57 2017 -0700
> +++ b/mercurial/dirstate.py Thu Mar 16 08:57:53 2017 +0530
> @@ -1115,9 +1115,8 @@
>  else:
>  # We may not have walked the full directory tree above,
>  # so stat and check everything we missed.
> -nf = iter(visit).next
>  for st in util.statfiles([join(i) for i in visit]):
> -results[nf()] = st
> +results[next(iter(visit))] = st

Won't "next(iter(visit))" get the first element of "visit" every time?

Also, since we can no longer cache the .next function itself, and it
seemed like the old version tried to care about that optimization,
does this make a noticeable difference? Can you try to figure out
under what circumstances nf() (in the old version) gets called very
many times and see if you can measure a difference between the old
version and the new version? Thanks.

>  return results
>
>  def status(self, match, subrepos, ignored, clean, unknown):
> ___
> 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 py3 V2] revlog: explicitly evaluate list to return

2017-03-16 Thread Pulkit Goyal
# HG changeset patch
# User Pulkit Goyal <7895pul...@gmail.com>
# Date 1489639281 -19800
#  Thu Mar 16 10:11:21 2017 +0530
# Node ID 16e1d9557dcebfe827060a4d31781cb7498c2c45
# Parent  e082ef765e4112ef69d3345369b142c87f1da3f4
revlog: explicitly evaluate list to return

On python 3, map returns an iterator so we need to convert it to list before
finding the len or subscripting it.

After this `hg status --all` works on Python 3.

diff -r e082ef765e41 -r 16e1d9557dce mercurial/revlog.py
--- a/mercurial/revlog.py   Thu Mar 16 10:01:12 2017 +0530
+++ b/mercurial/revlog.py   Thu Mar 16 10:11:21 2017 +0530
@@ -943,7 +943,7 @@
 ancs = self.index.commonancestorsheads(a, b)
 except (AttributeError, OverflowError): # C implementation failed
 ancs = ancestor.commonancestorsheads(self.parentrevs, a, b)
-return map(self.node, ancs)
+return list(map(self.node, ancs))
 
 def isancestor(self, a, b):
 """return True if node a is an ancestor of node b
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 8] commit: get rid of ui.backupconfig

2017-03-16 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1489698920 25200
#  Thu Mar 16 14:15:20 2017 -0700
# Node ID def9b72933ce717a48e3cc8fa4934bd3459b9479
# Parent  5c9cda37d7f6b181ab604c8d5a7592b5553f886b
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r def9b72933ce
commit: get rid of ui.backupconfig

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1703,23 +1703,19 @@ def _docommit(ui, repo, *pats, **opts):
 else:
 def commitfunc(ui, repo, message, match, opts):
-backup = ui.backupconfig('phases', 'new-commit')
+configoverride = {}
+if opts.get('secret'):
+configoverride[('phases', 'new-commit')] = 'secret'
+
 baseui = repo.baseui
-basebackup = baseui.backupconfig('phases', 'new-commit')
-try:
-if opts.get('secret'):
-ui.setconfig('phases', 'new-commit', 'secret', 'commit')
-# Propagate to subrepos
-baseui.setconfig('phases', 'new-commit', 'secret', 
'commit')
-
-editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
-editor = cmdutil.getcommiteditor(editform=editform, **opts)
-return repo.commit(message, opts.get('user'), opts.get('date'),
-   match,
-   editor=editor,
-   extra=extra)
-finally:
-ui.restoreconfig(backup)
-repo.baseui.restoreconfig(basebackup)
-
+with baseui.configoverride(configoverride, 'commit'):
+with ui.configoverride(configoverride, 'commit'):
+editform = cmdutil.mergeeditform(repo[None],
+ 'commit.normal')
+editor = cmdutil.getcommiteditor(editform=editform, **opts)
+return repo.commit(message, opts.get('user'),
+   opts.get('date'),
+   match,
+   editor=editor,
+   extra=extra)
 
 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 8] record: get rid of ui.backupconfig

2017-03-16 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1489700075 25200
#  Thu Mar 16 14:34:35 2017 -0700
# Node ID 4ff0515eaa03cf3fdd2b19a3444eb9c2cebdbcea
# Parent  01931210cd8d62aa56447843c096ea57bdf03889
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 4ff0515eaa03
record: get rid of ui.backupconfig

diff --git a/hgext/record.py b/hgext/record.py
--- a/hgext/record.py
+++ b/hgext/record.py
@@ -69,10 +69,7 @@ def record(ui, repo, *pats, **opts):
 
 opts["interactive"] = True
-backup = ui.backupconfig('experimental', 'crecord')
-try:
-ui.setconfig('experimental', 'crecord', False, 'record')
+override = {('experimental', 'crecord'): False}
+with ui.configoverride(override, 'record'):
 return commands.commit(ui, repo, *pats, **opts)
-finally:
-ui.restoreconfig(backup)
 
 def qrefresh(origfn, ui, repo, *pats, **opts):
@@ -118,11 +115,8 @@ def _qrecord(cmdsuggest, ui, repo, patch
 mq.new(ui, repo, patch, *pats, **opts)
 
-backup = ui.backupconfig('experimental', 'crecord')
-try:
-ui.setconfig('experimental', 'crecord', False, 'record')
+override = {('experimental', 'crecord'): False}
+with ui.configoverride(override, 'record'):
 cmdutil.dorecord(ui, repo, committomq, cmdsuggest, False,
  cmdutil.recordfilter, *pats, **opts)
-finally:
-ui.restoreconfig(backup)
 
 def qnew(origfn, ui, repo, patch, *args, **opts):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 6 of 8] mq: get rid of ui.backupconfig

2017-03-16 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1489700358 25200
#  Thu Mar 16 14:39:18 2017 -0700
# Node ID 8b086a28d1b605d6c0726d77c21f8d13188691fa
# Parent  93772a7ad2c443b7c92d0d23e85405f5b0d1a800
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 8b086a28d1b6
mq: get rid of ui.backupconfig

diff --git a/hgext/mq.py b/hgext/mq.py
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -406,16 +406,10 @@ def newcommit(repo, phase, *args, **kwar
 if repo.ui.configbool('mq', 'secret', False):
 phase = phases.secret
+override = {('ui', 'allowemptycommit'): True}
 if phase is not None:
-phasebackup = repo.ui.backupconfig('phases', 'new-commit')
-allowemptybackup = repo.ui.backupconfig('ui', 'allowemptycommit')
-try:
-if phase is not None:
-repo.ui.setconfig('phases', 'new-commit', phase, 'mq')
+override[('phases', 'new-commit')] = phase
+with repo.ui.configoverride(override, 'mq'):
 repo.ui.setconfig('ui', 'allowemptycommit', True)
 return repo.commit(*args, **kwargs)
-finally:
-repo.ui.restoreconfig(allowemptybackup)
-if phase is not None:
-repo.ui.restoreconfig(phasebackup)
 
 class AbortNoCleanup(error.Abort):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 8] clone: get rid of ui.backupconfig

2017-03-16 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1489699130 25200
#  Thu Mar 16 14:18:50 2017 -0700
# Node ID 7b575fd8a7a1e9a96cd79352351d87ac69479270
# Parent  def9b72933ce717a48e3cc8fa4934bd3459b9479
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 7b575fd8a7a1
clone: get rid of ui.backupconfig

diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -614,12 +614,8 @@ def clone(ui, peeropts, source, dest=Non
 stream = None
 # internal config: ui.quietbookmarkmove
-quiet = local.ui.backupconfig('ui', 'quietbookmarkmove')
-try:
-local.ui.setconfig(
-'ui', 'quietbookmarkmove', True, 'clone')
+override = {('ui', 'quietbookmarkmove'): True}
+with local.ui.configoverride(override, 'clone'):
 exchange.pull(local, srcpeer, revs,
   streamclonerequested=stream)
-finally:
-local.ui.restoreconfig(quiet)
 elif srcrepo:
 exchange.push(srcrepo, destpeer, revs=revs,
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 5 of 8] histedit: get rid of ui.backupconfig

2017-03-16 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1489700195 25200
#  Thu Mar 16 14:36:35 2017 -0700
# Node ID 93772a7ad2c443b7c92d0d23e85405f5b0d1a800
# Parent  4ff0515eaa03cf3fdd2b19a3444eb9c2cebdbcea
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 93772a7ad2c4
histedit: get rid of ui.backupconfig

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -503,14 +503,10 @@ def commitfuncfor(repo, src):
 phasemin = src.phase()
 def commitfunc(**kwargs):
-phasebackup = repo.ui.backupconfig('phases', 'new-commit')
-try:
-repo.ui.setconfig('phases', 'new-commit', phasemin,
-  'histedit')
+override = {('phases', 'new-commit'): phasemin}
+with repo.ui.configoverride(override, 'histedit'):
 extra = kwargs.get('extra', {}).copy()
 extra['histedit_source'] = src.hex()
 kwargs['extra'] = extra
 return repo.commit(**kwargs)
-finally:
-repo.ui.restoreconfig(phasebackup)
 return commitfunc
 
@@ -763,12 +759,9 @@ class fold(histeditaction):
 extra['histedit_source'] = '%s,%s' % (ctx.hex(), oldctx.hex())
 commitopts['extra'] = extra
-phasebackup = repo.ui.backupconfig('phases', 'new-commit')
-try:
-phasemin = max(ctx.phase(), oldctx.phase())
-repo.ui.setconfig('phases', 'new-commit', phasemin, 'histedit')
+phasemin = max(ctx.phase(), oldctx.phase())
+override = {('phases', 'new-commit'): phasemin}
+with repo.ui.configoverride(override, 'histedit'):
 n = collapse(repo, ctx, repo[newnode], commitopts,
  skipprompt=self.skipprompt())
-finally:
-repo.ui.restoreconfig(phasebackup)
 if n is None:
 return ctx, []
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 8 of 8] shelve: get rid of ui.backupconfig

2017-03-16 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1489699661 25200
#  Thu Mar 16 14:27:41 2017 -0700
# Node ID 4f98fa7baebed161fe94c98661a8c404dd82a87d
# Parent  8f87b407da24ee802e271f517dbc96ad32f21779
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 4f98fa7baebe
shelve: get rid of ui.backupconfig

diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -315,15 +315,14 @@ def getcommitfunc(extra, interactive, ed
 if hasmq:
 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
-backup = repo.ui.backupconfig('phases', 'new-commit')
+override = {('phases', 'new-commit'): phases.secret}
 try:
-repo.ui.setconfig('phases', 'new-commit', phases.secret)
 editor_ = False
 if editor:
 editor_ = cmdutil.getcommiteditor(editform='shelve.shelve',
   **opts)
-return repo.commit(message, shelveuser, opts.get('date'), match,
-   editor=editor_, extra=extra)
+with repo.ui.configoverride(override):
+return repo.commit(message, shelveuser, opts.get('date'),
+   match, editor=editor_, extra=extra)
 finally:
-repo.ui.restoreconfig(backup)
 if hasmq:
 repo.mq.checkapplied = saved
@@ -851,7 +850,5 @@ def _dounshelve(ui, repo, *shelved, **op
 oldquiet = ui.quiet
 lock = tr = None
-forcemerge = ui.backupconfig('ui', 'forcemerge')
 try:
-ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'unshelve')
 lock = repo.lock()
 
@@ -867,23 +864,26 @@ def _dounshelve(ui, repo, *shelved, **op
 # to the original pctx.
 
-tmpwctx, addedbefore = _commitworkingcopychanges(ui, repo, opts,
- tmpwctx)
-
-repo, shelvectx = _unshelverestorecommit(ui, repo, basename, oldquiet)
-_checkunshelveuntrackedproblems(ui, repo, shelvectx)
-branchtorestore = ''
-if shelvectx.branch() != shelvectx.p1().branch():
-branchtorestore = shelvectx.branch()
+override = {('ui', 'forcemerge'): opts.get('tool', '')}
+with ui.configoverride(override, 'unshelve'):
+tmpwctx, addedbefore = _commitworkingcopychanges(ui, repo, opts,
+ tmpwctx)
 
-shelvectx = _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev,
-  basename, pctx, tmpwctx, shelvectx,
-  branchtorestore)
-mergefiles(ui, repo, pctx, shelvectx)
-restorebranch(ui, repo, branchtorestore)
-_forgetunknownfiles(repo, shelvectx, addedbefore)
+repo, shelvectx = _unshelverestorecommit(ui, repo, basename,
+ oldquiet)
+_checkunshelveuntrackedproblems(ui, repo, shelvectx)
+branchtorestore = ''
+if shelvectx.branch() != shelvectx.p1().branch():
+branchtorestore = shelvectx.branch()
 
-shelvedstate.clear(repo)
-_finishunshelve(repo, oldtiprev, tr)
-unshelvecleanup(ui, repo, basename, opts)
+shelvectx = _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev,
+  basename, pctx, tmpwctx,
+  shelvectx, branchtorestore)
+mergefiles(ui, repo, pctx, shelvectx)
+restorebranch(ui, repo, branchtorestore)
+_forgetunknownfiles(repo, shelvectx, addedbefore)
+
+shelvedstate.clear(repo)
+_finishunshelve(repo, oldtiprev, tr)
+unshelvecleanup(ui, repo, basename, opts)
 finally:
 ui.quiet = oldquiet
@@ -891,5 +891,4 @@ def _dounshelve(ui, repo, *shelved, **op
 tr.release()
 lockmod.release(lock)
-ui.restoreconfig(forcemerge)
 
 @command('shelve',
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 8] import: get rid of ui.backupconfig

2017-03-16 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1489699429 25200
#  Thu Mar 16 14:23:49 2017 -0700
# Node ID 01931210cd8d62aa56447843c096ea57bdf03889
# Parent  7b575fd8a7a1e9a96cd79352351d87ac69479270
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 01931210cd8d
import: get rid of ui.backupconfig

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -972,11 +972,11 @@ def tryimportone(ui, repo, hunk, parents
 else:
 editor = getcommiteditor(editform=editform, **opts)
-allowemptyback = repo.ui.backupconfig('ui', 'allowemptycommit')
 extra = {}
 for idfunc in extrapreimport:
 extrapreimportmap[idfunc](repo, extractdata, extra, opts)
-try:
-if partial:
-repo.ui.setconfig('ui', 'allowemptycommit', True)
+override = {}
+if partial:
+override[('ui', 'allowemptycommit')] = True
+with repo.ui.configoverride(override, 'import'):
 n = repo.commit(message, user,
 date, match=m,
@@ -984,6 +984,4 @@ def tryimportone(ui, repo, hunk, parents
 for idfunc in extrapostimport:
 extrapostimportmap[idfunc](repo[n])
-finally:
-repo.ui.restoreconfig(allowemptyback)
 else:
 if opts.get('exact') or importbranch:
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 7 of 8] rebase: get rid of ui.backupconfig

2017-03-16 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1489700434 25200
#  Thu Mar 16 14:40:34 2017 -0700
# Node ID 8f87b407da24ee802e271f517dbc96ad32f21779
# Parent  8b086a28d1b605d6c0726d77c21f8d13188691fa
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 8f87b407da24
rebase: get rid of ui.backupconfig

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -851,8 +851,7 @@ def concludenode(repo, rev, p1, p2, comm
 extrafn(ctx, extra)
 
-backup = repo.ui.backupconfig('phases', 'new-commit')
-try:
-targetphase = max(ctx.phase(), phases.draft)
-repo.ui.setconfig('phases', 'new-commit', targetphase, 'rebase')
+targetphase = max(ctx.phase(), phases.draft)
+override = {('phases', 'new-commit'): targetphase}
+with repo.ui.configoverride(override, 'rebase'):
 if keepbranch:
 repo.ui.setconfig('ui', 'allowemptycommit', True)
@@ -862,6 +861,4 @@ def concludenode(repo, rev, p1, p2, comm
 newnode = repo.commit(text=commitmsg, user=ctx.user(),
   date=date, extra=extra, editor=editor)
-finally:
-repo.ui.restoreconfig(backup)
 
 repo.dirstate.setbranch(repo[newnode].branch())
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


mercurial@31454: 27 new changesets

2017-03-16 Thread Mercurial Commits
27 new changesets in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/9b361478b03a
changeset:   31428:9b361478b03a
user:Pierre-Yves David 
date:Fri Aug 05 14:19:31 2016 +0200
summary: localrepo: use self.wvfs.islink directly

https://www.mercurial-scm.org/repo/hg/rev/2471368281d1
changeset:   31429:2471368281d1
user:Pierre-Yves David 
date:Fri Aug 05 14:15:45 2016 +0200
summary: localrepo: deprecated '_link'

https://www.mercurial-scm.org/repo/hg/rev/807387581d89
changeset:   31430:807387581d89
user:Rishabh Madan 
date:Thu Mar 16 04:53:23 2017 +0530
summary: py3: use iter() instead of iterkeys()

https://www.mercurial-scm.org/repo/hg/rev/406705701c2d
changeset:   31431:406705701c2d
user:Pierre-Yves David 
date:Wed Mar 15 15:03:43 2017 -0700
summary: rebase: explicitly tests for None

https://www.mercurial-scm.org/repo/hg/rev/6e1c79578e5c
changeset:   31432:6e1c79578e5c
user:Pierre-Yves David 
date:Wed Mar 15 15:05:54 2017 -0700
summary: mq: explicitly tests for None

https://www.mercurial-scm.org/repo/hg/rev/7aac35ada1cb
changeset:   31433:7aac35ada1cb
user:Pierre-Yves David 
date:Wed Mar 15 15:08:45 2017 -0700
summary: match: explicitly tests for None

https://www.mercurial-scm.org/repo/hg/rev/d4645ae6ba15
changeset:   31434:d4645ae6ba15
user:Pierre-Yves David 
date:Wed Mar 15 15:10:09 2017 -0700
summary: hgweb: explicitly tests for None in webutil

https://www.mercurial-scm.org/repo/hg/rev/2daeab02b4b1
changeset:   31435:2daeab02b4b1
user:Pierre-Yves David 
date:Wed Mar 15 15:11:04 2017 -0700
summary: hgweb: explicitly tests for None

https://www.mercurial-scm.org/repo/hg/rev/ac7aa96e4cd8
changeset:   31436:ac7aa96e4cd8
user:Pierre-Yves David 
date:Wed Mar 15 15:11:52 2017 -0700
summary: filemerge: explicitly tests for None

https://www.mercurial-scm.org/repo/hg/rev/084050d76e4f
changeset:   31437:084050d76e4f
user:Pierre-Yves David 
date:Wed Mar 15 15:33:24 2017 -0700
summary: context: explicitly tests for None

https://www.mercurial-scm.org/repo/hg/rev/82350f7fa56c
changeset:   31438:82350f7fa56c
user:Yuya Nishihara 
date:Wed Mar 08 22:13:32 2017 +0900
summary: tests: allow running doctests selectively on Python 3

https://www.mercurial-scm.org/repo/hg/rev/b70407bd84d5
changeset:   31439:b70407bd84d5
user:Yuya Nishihara 
date:Wed Mar 08 22:48:26 2017 +0900
summary: pycompat: add bytestr wrapper which mostly acts as a Python 2 str

https://www.mercurial-scm.org/repo/hg/rev/f784ba187089
changeset:   31440:f784ba187089
user:Yuya Nishihara 
date:Thu Mar 16 21:33:25 2017 +0900
summary: py3: use bytestr wrapper in revsetlang.formatspec()

https://www.mercurial-scm.org/repo/hg/rev/80c8a6db450d
changeset:   31441:80c8a6db450d
user:Yuya Nishihara 
date:Thu Mar 16 21:36:21 2017 +0900
summary: py3: use bytestr wrapper in revsetlang.tokenize()

https://www.mercurial-scm.org/repo/hg/rev/d3a56bb268ee
changeset:   31442:d3a56bb268ee
user:Pierre-Yves David 
date:Tue Mar 14 23:07:08 2017 -0700
summary: import-checkers: split tests of the tool from running it on the 
source

https://www.mercurial-scm.org/repo/hg/rev/0241dd94ed38
changeset:   31443:0241dd94ed38
user:Kostia Balytskyi 
date:Mon Mar 13 12:44:13 2017 -0700
summary: exewrapper: prefer HackableMercurial python if availbale

https://www.mercurial-scm.org/repo/hg/rev/55390e97fdd2
changeset:   31444:55390e97fdd2
user:Yuya Nishihara 
date:Sun Mar 12 17:20:42 2017 -0700
summary: py3: use portable way to stringify cache key of repoview

https://www.mercurial-scm.org/repo/hg/rev/83e080144faf
changeset:   31445:83e080144faf
user:Yuya Nishihara 
date:Mon Mar 13 08:44:57 2017 -0700
summary: py3: rewrite itervalues() as values() by importer

https://www.mercurial-scm.org/repo/hg/rev/9a94239e4f12
changeset:   31446:9a94239e4f12
user:Yuya Nishihara 
date:Mon Mar 13 08:53:31 2017 -0700
summary: py3: use next() to obtain next item from inner generator of 
generatorset

https://www.mercurial-scm.org/repo/hg/rev/067add650129
changeset:   31447:067add650129
user:Yuya Nishihara 
date:Mon Mar 13 09:11:08 2017 -0700
summary: encoding: factor out unicode variants of from/tolocal()

https://www.mercurial-scm.org/repo/hg/rev/6419cd243017
changeset:   31448:6419cd243017
user:Yuya Nishihara 
date:Mon Mar 13 09:12:56 2017 -0700
summary: encoding: add converter between native str and byte string

https://www.mercurial-scm.org/repo/hg/rev/756175623f2e
changeset:   31449:756175623f2e
user:Yuya Nishihara 
date:Mon Mar 13 09:19:07 2017 -0700
summary: py3: call strftime() with native str type

https://www.mercurial-scm.org/repo/hg/rev/b3b4c487707c
changese

Re: [PATCH py3 V2] revlog: explicitly evaluate list to return

2017-03-16 Thread Gregory Szorc
On Thu, Mar 16, 2017 at 2:51 PM, Pulkit Goyal <7895pul...@gmail.com> wrote:

> # HG changeset patch
> # User Pulkit Goyal <7895pul...@gmail.com>
> # Date 1489639281 -19800
> #  Thu Mar 16 10:11:21 2017 +0530
> # Node ID 16e1d9557dcebfe827060a4d31781cb7498c2c45
> # Parent  e082ef765e4112ef69d3345369b142c87f1da3f4
> revlog: explicitly evaluate list to return
>
> On python 3, map returns an iterator so we need to convert it to list
> before
> finding the len or subscripting it.
>
> After this `hg status --all` works on Python 3.
>
> diff -r e082ef765e41 -r 16e1d9557dce mercurial/revlog.py
> --- a/mercurial/revlog.py   Thu Mar 16 10:01:12 2017 +0530
> +++ b/mercurial/revlog.py   Thu Mar 16 10:11:21 2017 +0530
> @@ -943,7 +943,7 @@
>  ancs = self.index.commonancestorsheads(a, b)
>  except (AttributeError, OverflowError): # C implementation failed
>  ancs = ancestor.commonancestorsheads(self.parentrevs, a, b)
> -return map(self.node, ancs)
> +return list(map(self.node, ancs))
>
>
This will create a list copy in Python 2, which could have performance
implications. But for this function, the list shouldn't have many elements,
so it is probably OK. Something to watch out for when doing other porting
work. It /might/ be worthwhile to have a pycompat.maplist() wrapper or some
such.


>  def isancestor(self, a, b):
>  """return True if node a is an ancestor of node b
> ___
> 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: hg-git and round-tripping (and file copies?)

2017-03-16 Thread Mike Hommey
On Thu, Mar 16, 2017 at 01:38:18PM -0700, Gregory Szorc wrote:
> On Thu, Mar 16, 2017 at 1:05 PM, Danek Duvall 
> wrote:
> 
> > In trying to convert
> >
> > https://hg.java.net/hg/solaris-userland~gate
> >
> > to a git repo and back, I'm seeing issues at changeset 34, where the hash
> > changes for reasons I can't see.  If I do a diff of the debug log, I see
> > it's due to the manifest:
> >
> > $ diff -u =(hg log -R userland-more --debug -r 34) =(hg log -R
> > userland-more.hgagain --debug -r 34 | grep -v "^phase:")
> > --- /tmp/zshhHyEIb  2017-03-16 11:37:57.601340643 -0700
> > +++ /tmp/zshlyqHbd  2017-03-16 11:37:57.793642372 -0700
> > @@ -1,12 +1,10 @@
> >  no terminfo entry for sitm
> > -changeset:   34:d20b10eba31725ad8954aa6d20374da512f0e636
> > -tag: build-149
> > +changeset:   34:2ccb817b85926f410df2a6bd23000265805088df
> >  parent:  33:371c8e56136d19872ae7db8d273f9de78c8fa783
> >  parent:  -1:
> > -manifest:34:e031f26e68549dadb3dfb4705d429c75622a58b4
> > +manifest:34:5a12a2a1bf3e7c0f7c30d01bd09a2e37185bcfb6
> >  user:Norm Jacobs 
> >  date:Sun Sep 19 13:50:53 2010 -0700
> > -phase:   public
> >  files:
> > components/Makefile
> > make-rules/prep.mk
> >
> > and if I use debugdata to look at the manifest at changeset 34, I see:
> >
> > $ gdiff -a -u =(hg -R userland-more debugdata -m 34) =(hg -R
> > userland-more.hgagain debugdata -m 34)
> > --- /tmp/zshOdnjza  2017-03-16 11:53:16.971130878 +
> > +++ /tmp/zshzoTzmc  2017-03-16 11:53:17.118194061 +
> > @@ -24,12 +24,12 @@
> >  make-rules/setup.py.mk302733d738cc7c6cceb63457442f24f931867472
> >  make-rules/shared-macros.mk03dd5df583b6e39a17ba66fc6ed6205df7f6be49
> >  tools/Makefilecc964766028e3b963b4a321c88815d211415006b
> > -tools/bass-o-matica618ef38ceda467b9a09680dd8b94debcd303037x
> > +tools/bass-o-matic349f9611499fddf1a110f9488a84fb110c90b7bfx
> >  tools/build-watch.df69b9a2b6a265c06268733430bbf3f9aa7d5e160x
> >  tools/build-watch.pl5e23340c7a84ac555e630a5ccdc28eceda95f4b6x
> >  tools/time.ca0a1f64ff8ac947ce9d045e0448f8ee72f9fd273
> > -tools/userland-fetch851170bb5cebf2648c53d4909eac26ac2055cdd3x
> > -tools/userland-unpack0977e35fa356d4cfab889b93613dc75d90d89b6bx
> > +tools/userland-fetchbae023e70db29fd07f6f989aaa858cfaed09238ax
> > +tools/userland-unpackb3800b9db86df38a644a653b3095805b269b6ac6x
> >  transforms/actuatorsc9d84677229efde5f89b1d985de5cd1b09267b56
> >  transforms/archive-libraries-drop5b346a0133242f460ff66f6689
> > 790da094ce27f6
> >  transforms/comparison-cleanupde1288c586594a171d43a3da5234cb920be408cc
> >
> > Now, those three files were copied in that changeset, but they're not the
> > first to be copied, so it's not that, strictly.  But it is the first
> > changeset in which files were copied without being modified.
> >
> > The index data is off-by-one, if that makes any difference:
> >
> > $ hg -R userland-more debugrevlog -d tools/bass-o-matic
> > # rev p1rev p2rev start   end deltastart base   p1   p2 rawsize
> > totalsize compression heads chainlen
> > 0-1-1 0  2175  00006005
> > 6005   2 10
> > 1 0-1  2175  2228  00005929
> >  11934   5 11
> >
> > $ hg -R userland-more.hgagain debugrevlog -d tools/bass-o-matic
> > # rev p1rev p2rev start   end deltastart base   p1   p2 rawsize
> > totalsize compression heads chainlen
> > 0-1-1 0  2174  00006005
> > 6005   2 10
> > 1 0-1  2174  2227  00005929
> >  11934   5 11
> >
> > Any thoughts on how to further debug this?
> >
> > Or is this just
> >
> > https://bitbucket.org/durin42/hg-git/issues/46

Note that bug is about git->hg conversion where the original repository
is git.

> >
> > and I'm out of luck?
> >
> 
> It is effectively impossible to round-trip between Git and Mercurial when
> file copies are involved. This is because Mercurial's filelog hashes
> include copy metadata and the parent nodes. Git's blob hashes, by contrast,
> are effectively content only. When you convert from Mercurial to Git, it
> will drop copy metadata (because Git doesn't track it explicitly). Then
> when you convert back to Mercurial, the copies have to be detected "just
> right" by hg-git for the hashes to align. Furthermore, the files have to be
> reintroduced in the same order, or the filelog parents may not align and
> the hashes may diverge. If a repo isn't linear, there's a non-zero chance
> of that happening.

hg-git actually "stores" copy/rename in the commit messages, but that's
assuming the commit was done in mercurial and pushed to git with hg-git
in the first place. 

Re: hg-git and round-tripping (and file copies?)

2017-03-16 Thread Danek Duvall
Mike Hommey wrote:

> If your goal trying to round-trip between mercurial and git is to
> provide developers with the possibility to use mercurial or git as they
> like, and somehow make it work with developers pushing on both ends, you
> should instead use a single source of truth (mercurial or git, whichever
> you prefer keeping a server for), and let developers use conversion tools
> on their end. hg-git can be used by developers who prefer mercurial when
> the server is git (although it annoyingly adds visible metadata to git
> commits in that case). git-cinnabar or git-remote-hg can be used by
> developers who prefer git when the server is mercurial. (full
> disclosure, I'm the author of git-cinnabar)

Our source of truth is mercurial.  But our (Oracle Solaris) external,
read-only mirror is being moved from a mercurial repo on java.net to
github.  I would like for people who might have had clones of the mercurial
repo to be able to use hg-git to pull from the github repo and get the same
changeset IDs as they had before (and as we have internally), but that
looks like it's not possible.

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


Re: [PATCH 1 of 2 py3 V2] dirstate: use next(iter) instead of iter.next

2017-03-16 Thread Pulkit Goyal
On Fri, Mar 17, 2017 at 3:17 AM, Martin von Zweigbergk <
martinv...@google.com> wrote:

> On Thu, Mar 16, 2017 at 2:24 PM, Pulkit Goyal <7895pul...@gmail.com>
> wrote:
> > # HG changeset patch
> > # User Pulkit Goyal <7895pul...@gmail.com>
> > # Date 1489634873 -19800
> > #  Thu Mar 16 08:57:53 2017 +0530
> > # Node ID c894bad6625973565b21f556896527141f123dd5
> > # Parent  a5bad127128d8f60060be53d161acfa7a32a17d5
> > dirstate: use next(iter) instead of iter.next
> >
> > In Python 3 world, iter.next() is renamed to iter.__next__(). But
> next(iter)
> > has the same behaviour. So let's replace iter.next() with next(iter).
> >
> > diff -r a5bad127128d -r c894bad66259 mercurial/dirstate.py
> > --- a/mercurial/dirstate.py Wed Mar 15 15:48:57 2017 -0700
> > +++ b/mercurial/dirstate.py Thu Mar 16 08:57:53 2017 +0530
> > @@ -1115,9 +1115,8 @@
> >  else:
> >  # We may not have walked the full directory tree above,
> >  # so stat and check everything we missed.
> > -nf = iter(visit).next
> >  for st in util.statfiles([join(i) for i in visit]):
> > -results[nf()] = st
> > +results[next(iter(visit))] = st
>
> Won't "next(iter(visit))" get the first element of "visit" every time?​


> Also, since we can no longer cache the .next function itself, and it
> seemed like the old version tried to care about that optimization,
> does this make a noticeable difference? Can you try to figure out
> under what circumstances nf() (in the old version) gets called very
> many times and see if you can measure a difference between the old
> version and the new version? Thanks.
>

​This one is breaking the tests (sorry for not checking before sending).

I guess we need to switch to the V1 of this patch.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 7 of 8] rebase: get rid of ui.backupconfig

2017-03-16 Thread Martin von Zweigbergk via Mercurial-devel
On Thu, Mar 16, 2017 at 2:57 PM, Jun Wu  wrote:
> # HG changeset patch
> # User Jun Wu 
> # Date 1489700434 25200
> #  Thu Mar 16 14:40:34 2017 -0700
> # Node ID 8f87b407da24ee802e271f517dbc96ad32f21779
> # Parent  8b086a28d1b605d6c0726d77c21f8d13188691fa
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #  hg pull https://bitbucket.org/quark-zju/hg-draft -r 
> 8f87b407da24
> rebase: get rid of ui.backupconfig
>
> diff --git a/hgext/rebase.py b/hgext/rebase.py
> --- a/hgext/rebase.py
> +++ b/hgext/rebase.py
> @@ -851,8 +851,7 @@ def concludenode(repo, rev, p1, p2, comm
>  extrafn(ctx, extra)
>
> -backup = repo.ui.backupconfig('phases', 'new-commit')
> -try:
> -targetphase = max(ctx.phase(), phases.draft)
> -repo.ui.setconfig('phases', 'new-commit', targetphase, 'rebase')
> +targetphase = max(ctx.phase(), phases.draft)
> +override = {('phases', 'new-commit'): targetphase}
> +with repo.ui.configoverride(override, 'rebase'):
>  if keepbranch:
>  repo.ui.setconfig('ui', 'allowemptycommit', True)

I *think* this is unrelated to this patch, but should this line also
be restored (i.e. part of the overrides)?

> @@ -862,6 +861,4 @@ def concludenode(repo, rev, p1, p2, comm
>  newnode = repo.commit(text=commitmsg, user=ctx.user(),
>date=date, extra=extra, editor=editor)
> -finally:
> -repo.ui.restoreconfig(backup)
>
>  repo.dirstate.setbranch(repo[newnode].branch())
> ___
> 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 7 of 8] rebase: get rid of ui.backupconfig

2017-03-16 Thread Jun Wu
Excerpts from Martin von Zweigbergk's message of 2017-03-16 17:14:33 -0700:
> On Thu, Mar 16, 2017 at 2:57 PM, Jun Wu  wrote:
> > # HG changeset patch
> > # User Jun Wu 
> > # Date 1489700434 25200
> > #  Thu Mar 16 14:40:34 2017 -0700
> > # Node ID 8f87b407da24ee802e271f517dbc96ad32f21779
> > # Parent  8b086a28d1b605d6c0726d77c21f8d13188691fa
> > # Available At https://bitbucket.org/quark-zju/hg-draft 
> > #  hg pull https://bitbucket.org/quark-zju/hg-draft  -r 
> > 8f87b407da24
> > rebase: get rid of ui.backupconfig
> >
> > diff --git a/hgext/rebase.py b/hgext/rebase.py
> > --- a/hgext/rebase.py
> > +++ b/hgext/rebase.py
> > @@ -851,8 +851,7 @@ def concludenode(repo, rev, p1, p2, comm
> >  extrafn(ctx, extra)
> >
> > -backup = repo.ui.backupconfig('phases', 'new-commit')
> > -try:
> > -targetphase = max(ctx.phase(), phases.draft)
> > -repo.ui.setconfig('phases', 'new-commit', targetphase, 
> > 'rebase')
> > +targetphase = max(ctx.phase(), phases.draft)
> > +override = {('phases', 'new-commit'): targetphase}
> > +with repo.ui.configoverride(override, 'rebase'):
> >  if keepbranch:
> >  repo.ui.setconfig('ui', 'allowemptycommit', True)
> 
> I *think* this is unrelated to this patch, but should this line also
> be restored (i.e. part of the overrides)?

Good catch. I think it should. It looks like a bug.

> 
> > @@ -862,6 +861,4 @@ def concludenode(repo, rev, p1, p2, comm
> >  newnode = repo.commit(text=commitmsg, user=ctx.user(),
> >date=date, extra=extra, editor=editor)
> > -finally:
> > -repo.ui.restoreconfig(backup)
> >
> >  repo.dirstate.setbranch(repo[newnode].branch())
> > ___
> > 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 1 of 8] commit: get rid of ui.backupconfig

2017-03-16 Thread Martin von Zweigbergk via Mercurial-devel
On Thu, Mar 16, 2017 at 2:56 PM, Jun Wu  wrote:
> # HG changeset patch
> # User Jun Wu 
> # Date 1489698920 25200
> #  Thu Mar 16 14:15:20 2017 -0700
> # Node ID def9b72933ce717a48e3cc8fa4934bd3459b9479
> # Parent  5c9cda37d7f6b181ab604c8d5a7592b5553f886b
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #  hg pull https://bitbucket.org/quark-zju/hg-draft -r 
> def9b72933ce
> commit: get rid of ui.backupconfig

Queuing this series with some small changes mentioned below. Thanks. I
will not have time to run tests on all commits before I leave for
home, but I'll push anyway, and will update later tonight if tests
fail.

>
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -1703,23 +1703,19 @@ def _docommit(ui, repo, *pats, **opts):
>  else:
>  def commitfunc(ui, repo, message, match, opts):
> -backup = ui.backupconfig('phases', 'new-commit')
> +configoverride = {}

The name confused me for a while because it's the same as the method
on ui, but it's not even a function here. I renamed them throughout
the series to "overrides" (plural and no "config" prefix), which seems
more consistent with the rest of the series and with how we usually
pluralize dict-type variables.

> +if opts.get('secret'):
> +configoverride[('phases', 'new-commit')] = 'secret'
> +
>  baseui = repo.baseui
> -basebackup = baseui.backupconfig('phases', 'new-commit')
> -try:
> -if opts.get('secret'):
> -ui.setconfig('phases', 'new-commit', 'secret', 'commit')
> -# Propagate to subrepos
> -baseui.setconfig('phases', 'new-commit', 'secret', 
> 'commit')
> -
> -editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
> -editor = cmdutil.getcommiteditor(editform=editform, **opts)
> -return repo.commit(message, opts.get('user'), 
> opts.get('date'),
> -   match,
> -   editor=editor,
> -   extra=extra)
> -finally:
> -ui.restoreconfig(backup)
> -repo.baseui.restoreconfig(basebackup)
> -
> +with baseui.configoverride(configoverride, 'commit'):
> +with ui.configoverride(configoverride, 'commit'):
> +editform = cmdutil.mergeeditform(repo[None],
> + 'commit.normal')
> +editor = cmdutil.getcommiteditor(editform=editform, 
> **opts)
> +return repo.commit(message, opts.get('user'),

I wrapped after the first argument too (yes, I know it was
inconsistent before too).

> +   opts.get('date'),
> +   match,
> +   editor=editor,
> +   extra=extra)
>
>  node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
> ___
> 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 1 of 8] commit: get rid of ui.backupconfig

2017-03-16 Thread Jun Wu
Thanks!

Excerpts from Martin von Zweigbergk's message of 2017-03-16 17:19:15 -0700:
> On Thu, Mar 16, 2017 at 2:56 PM, Jun Wu  wrote:
> > # HG changeset patch
> > # User Jun Wu 
> > # Date 1489698920 25200
> > #  Thu Mar 16 14:15:20 2017 -0700
> > # Node ID def9b72933ce717a48e3cc8fa4934bd3459b9479
> > # Parent  5c9cda37d7f6b181ab604c8d5a7592b5553f886b
> > # Available At https://bitbucket.org/quark-zju/hg-draft 
> > #  hg pull https://bitbucket.org/quark-zju/hg-draft  -r 
> > def9b72933ce
> > commit: get rid of ui.backupconfig
> 
> Queuing this series with some small changes mentioned below. Thanks. I
> will not have time to run tests on all commits before I leave for
> home, but I'll push anyway, and will update later tonight if tests
> fail.
> 
> >
> > diff --git a/mercurial/commands.py b/mercurial/commands.py
> > --- a/mercurial/commands.py
> > +++ b/mercurial/commands.py
> > @@ -1703,23 +1703,19 @@ def _docommit(ui, repo, *pats, **opts):
> >  else:
> >  def commitfunc(ui, repo, message, match, opts):
> > -backup = ui.backupconfig('phases', 'new-commit')
> > +configoverride = {}
> 
> The name confused me for a while because it's the same as the method
> on ui, but it's not even a function here. I renamed them throughout
> the series to "overrides" (plural and no "config" prefix), which seems
> more consistent with the rest of the series and with how we usually
> pluralize dict-type variables.
> 
> > +if opts.get('secret'):
> > +configoverride[('phases', 'new-commit')] = 'secret'
> > +
> >  baseui = repo.baseui
> > -basebackup = baseui.backupconfig('phases', 'new-commit')
> > -try:
> > -if opts.get('secret'):
> > -ui.setconfig('phases', 'new-commit', 'secret', 
> > 'commit')
> > -# Propagate to subrepos
> > -baseui.setconfig('phases', 'new-commit', 'secret', 
> > 'commit')
> > -
> > -editform = cmdutil.mergeeditform(repo[None], 
> > 'commit.normal')
> > -editor = cmdutil.getcommiteditor(editform=editform, **opts)
> > -return repo.commit(message, opts.get('user'), 
> > opts.get('date'),
> > -   match,
> > -   editor=editor,
> > -   extra=extra)
> > -finally:
> > -ui.restoreconfig(backup)
> > -repo.baseui.restoreconfig(basebackup)
> > -
> > +with baseui.configoverride(configoverride, 'commit'):
> > +with ui.configoverride(configoverride, 'commit'):
> > +editform = cmdutil.mergeeditform(repo[None],
> > + 'commit.normal')
> > +editor = cmdutil.getcommiteditor(editform=editform, 
> > **opts)
> > +return repo.commit(message, opts.get('user'),
> 
> I wrapped after the first argument too (yes, I know it was
> inconsistent before too).
> 
> > +   opts.get('date'),
> > +   match,
> > +   editor=editor,
> > +   extra=extra)
> >
> >  node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
> > ___
> > 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 evolve-ext] checks: correct the shebang line filtering for python files

2017-03-16 Thread Matt Harbison
# HG changeset patch
# User Matt Harbison 
# Date 1489713417 14400
#  Thu Mar 16 21:16:57 2017 -0400
# Node ID 6a3248558b6929378450b572bb27406afe703ffd
# Parent  e9d5f54765a27e09d35f48dda23db7e6f5b8320a
checks: correct the shebang line filtering for python files

As it is, the only related file is docs/test2rst.py, which was covered by **.py.
Not sure if it matters, but most patterns in core tests are for "#!.*?python".
(Though there are a couple "#!.*python" tests.)

diff --git a/tests/test-check-flake8.t b/tests/test-check-flake8.t
--- a/tests/test-check-flake8.t
+++ b/tests/test-check-flake8.t
@@ -14,5 +14,5 @@
 
 run flake8 if it exists; if it doesn't, then just skip
 
-  $ hg files -0 'set:(**.py or grep("^!#.*python")) - removed()' 2>/dev/null \
+  $ hg files -0 'set:(**.py or grep("^#!.*python")) - removed()' 2>/dev/null \
   > | xargs -0 flake8
diff --git a/tests/test-check-pyflakes.t b/tests/test-check-pyflakes.t
--- a/tests/test-check-pyflakes.t
+++ b/tests/test-check-pyflakes.t
@@ -7,5 +7,5 @@
 run pyflakes on all tracked files ending in .py or without a file ending
 (skipping binary file random-seed)
 
-  $ hg locate 'set:(**.py or grep("^!#.*python")) - removed()' 2>/dev/null \
+  $ hg locate 'set:(**.py or grep("^#!.*python")) - removed()' 2>/dev/null \
   > | xargs pyflakes 2>/dev/null
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 4 V3] filemerge: add `summarize()`

2017-03-16 Thread Phil Cohen
# HG changeset patch
# User Phil Cohen 
# Date 1489716177 25200
#  Thu Mar 16 19:02:57 2017 -0700
# Node ID ad81d182e88ffd3da20364f18204facf6e7750a3
# Parent  568d80b24b3a3e4e6874ac0d95ddee056fef14e4
filemerge: add `summarize()`

returns a dictionary of each version of a conflict, given the contexts

diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -7,6 +7,7 @@
 
 from __future__ import absolute_import
 
+import copy
 import filecmp
 import os
 import re
@@ -567,6 +568,60 @@
 "o": " [%s]" % labels[1],
 }
 
+def summarize(repo, workingfilectx, otherctx, basectx):
+origfile = None if workingfilectx.isabsent() else \
+scmutil.origpath(repo.ui, repo, repo.wjoin(workingfilectx.path()))
+
+def flags(context):
+if isinstance(context, absentfilectx):
+return {'exists': False}
+return {
+'contents': context.data(),
+'exists': True,
+'isexec': context.isexec(),
+'issymlink': context.islink(),
+}
+
+output = flags(workingfilectx)
+
+if origfile and util.filestat(origfile).stat:
+# Since you can start a merge with a dirty working copy (either via
+# `up -n` or `merge -f`), "local" must reflect that, not the underlying
+# commit. Those contents are available in the .orig version, so we look
+# there and mock up the schema to look like the other contexts.
+local = {
+'contents': util.readfile(origfile),
+'exists': True,
+'isexec': util.isexec(origfile),
+'issymlink': util.statislink(util.filestat(origfile).stat),
+}
+else:
+# No backup file. This happens whenever the merge was esoteric enough
+# that we didn't launch a merge tool*, and instead prompted the user to
+# "use (c)hanged version, (d)elete, or leave (u)nresolved".
+#
+# The only way to exit that prompt with a conflict is to choose "u",
+# which leaves the local version in the working copy (with all its
+# pre-merge properties including any local changes), so we can reuse
+# that.
+#
+# Another alternative might be to use repo['.'][path] but that wouldn't
+# have any dirty pre-merge changes.
+#
+# *If we had, we'd've we would've overwritten the working copy, made a
+# backup and hit the above case.
+local = copy.copy(output)
+
+output['path'] = repo.wjoin(workingfilectx.path())
+
+return {
+'base': flags(basectx),
+'local': local,
+'other': flags(otherctx),
+'output': output,
+'path': workingfilectx.path(),
+}
+
 def _filemerge(premerge, repo, mynode, orig, fcd, fco, fca, labels=None):
 """perform a 3-way merge in the working directory
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 4 V3] filemerge: add test cases for corner cases using internal:dumpjson

2017-03-16 Thread Phil Cohen
# HG changeset patch
# User Phil Cohen 
# Date 1489716623 25200
#  Thu Mar 16 19:10:23 2017 -0700
# Node ID 62ab2ddcf1683c3bf2e4dbb21dbe11d065bff93b
# Parent  36d378ac43dbbf559655c70b7cad873768a0e794
filemerge: add test cases for corner cases using internal:dumpjson

diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -589,6 +589,8 @@
 # `up -n` or `merge -f`), "local" must reflect that, not the underlying
 # commit. Those contents are available in the .orig version, so we look
 # there and mock up the schema to look like the other contexts.
+#
+# Test cases affected in test-merge-conflict-cornercases.t: #0
 local = {
 'contents': util.readfile(origfile),
 'exists': True,
@@ -605,6 +607,8 @@
 # pre-merge properties including any local changes), so we can reuse
 # that.
 #
+# Affected test cases: #0b, #1, #6, #11, and #12.
+#
 # Another alternative might be to use repo['.'][path] but that wouldn't
 # have any dirty pre-merge changes.
 #
diff --git a/tests/test-merge-conflict-cornercases.t 
b/tests/test-merge-conflict-cornercases.t
new file mode 100644
--- /dev/null
+++ b/tests/test-merge-conflict-cornercases.t
@@ -0,0 +1,575 @@
+Tests merge conflict corner cases (file-to-directory, binary-to-symlink, etc.)
+"other" == source
+"local" == dest
+
+Setup
+  $ cat >> $HGRCPATH < [extensions]
+  > rebase=
+  > EOF
+
+  $ reset() {
+  >   rm -rf foo
+  >   mkdir foo
+  >   cd foo
+  >   hg init
+  >   echo "base" > file
+  >   hg commit -Aqm "base"
+  > }
+  $ logg() {
+  >   hg log -G -T '({rev}) {desc}\naffected: {files}\ndeleted: 
{file_dels}\n\n'
+  > }
+
+Test case 0: A merge of just contents conflicts (not usually a corner case),
+but the user had local changes and ran `merge -f`.
+
+tldr: Since we can premerge, the working copy is backed up to an origfile.
+  $ reset
+  $ echo "change" > file
+  $ hg commit -Aqm "dest"
+  $ hg up -q 0
+  $ echo "other change" > file
+  $ hg commit -Aqm "source"
+  $ hg up -q 1
+  $ logg
+  o  (2) source
+  |  affected: file
+  |  deleted:
+  |
+  | @  (1) dest
+  |/   affected: file
+  |deleted:
+  |
+  o  (0) base
+ affected: file
+ deleted:
+  
+  $ echo "some local changes" > file
+  $ hg merge 2 -f
+  merging file
+  warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
+  0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+  use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to 
abandon
+  [1]
+
+  $ hg resolve --tool=internal:dumpjson --all
+  [
+   {
+"conflicts": [{"base": {"contents": "base\n", "exists": true, "isexec": 
false, "issymlink": false}, "local": {"contents": "some local changes\n", 
"exists": true, "isexec": false, "issymlink": false}, "other": {"contents": 
"other change\n", "exists": true, "isexec": false, "issymlink": false}, 
"output": {"contents": "<<< working copy: fd7d10c36158 - test: dest\nsome 
local changes\n===\nother change\n>>> merge rev:9b65ba2922f0 - 
test: source\n", "exists": true, "isexec": false, "issymlink": false, "path": 
"$TESTTMP/foo/file"}, "path": "file"}]
+   }
+  ]
+
+Test case 0b: Like #0 but with a corner case: source deleted, local changed
+*and* had local changes using merge -f.
+
+tldr: Since we couldn't premerge, the working copy is left alone.
+  $ reset
+  $ echo "change" > file
+  $ hg commit -Aqm "dest"
+  $ hg up -q 0
+  $ hg rm file
+  $ hg commit -Aqm "source"
+  $ hg up -q 1
+  $ logg
+  o  (2) source
+  |  affected: file
+  |  deleted: file
+  |
+  | @  (1) dest
+  |/   affected: file
+  |deleted:
+  |
+  o  (0) base
+ affected: file
+ deleted:
+  
+  $ echo "some local changes" > file
+  $ chmod +x file
+  $ hg merge 2 -f
+  local [working copy] changed file which other [merge rev] deleted
+  use (c)hanged version, (d)elete, or leave (u)nresolved? u
+  0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+  use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to 
abandon
+  [1]
+
+  $ hg resolve --tool=internal:dumpjson --all
+  [
+   {
+"conflicts": [{"base": {"contents": "base\n", "exists": true, "isexec": 
false, "issymlink": false}, "local": {"contents": "some local changes\n", 
"exists": true, "isexec": true, "issymlink": false}, "other": {"exists": 
false}, "output": {"contents": "some local changes\n", "exists": true, 
"isexec": true, "issymlink": false, "path": "$TESTTMP/foo/foo/file"}, "path": 
"file"}]
+   }
+  ]
+
+Test case 1: Source deleted, dest changed
+  $ reset
+  $ echo "change" > file
+  $ hg commit -Aqm "dest"
+  $ hg up -q 0
+  $ hg rm file
+  $ hg commit -Aqm "source"
+  $ hg up -q 1
+  $ logg
+  o  (2) source
+  |  affected: file
+  |  deleted: file
+  |
+  | @  (1) dest
+  |/   affected: file
+  |deleted:
+  |
+  o  (0) base
+ affected: 

[PATCH 3 of 4 V3] commands: add --tool=internal:dumpjson to resolve

2017-03-16 Thread Phil Cohen
# HG changeset patch
# User Phil Cohen 
# Date 1489716587 25200
#  Thu Mar 16 19:09:47 2017 -0700
# Node ID 36d378ac43dbbf559655c70b7cad873768a0e794
# Parent  864def5028681cdffeaf5b440ff4753e1389f453
commands: add --tool=internal:dumpjson to resolve

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -33,6 +33,7 @@
 error,
 exchange,
 extensions,
+formatter,
 graphmod,
 hbisect,
 help,
@@ -4287,6 +4288,26 @@
 fm.end()
 return 0
 
+if opts.get('tool', '') == "internal:dumpjson":
+formatter = ui.formatter('resolve', {'template': 'json'})
+mergestate = mergemod.mergestate.read(repo)
+matcher = scmutil.match(repo[None], pats, opts)
+workingctx = repo[None]
+
+paths = []
+for filename in mergestate:
+if not matcher(filename):
+continue
+
+val = mergestate.summarizeconflicts(filename, workingctx)
+if val is not None:
+paths.append(val)
+
+formatter.startitem()
+formatter.write('conflicts', '%s\n', paths)
+formatter.end()
+return 0
+
 with repo.wlock():
 ms = mergemod.mergestate.read(repo)
 
diff --git a/tests/test-resolve-dumpjson.t b/tests/test-resolve-dumpjson.t
new file mode 100644
--- /dev/null
+++ b/tests/test-resolve-dumpjson.t
@@ -0,0 +1,83 @@
+1) Make the repo
+  $ hg init
+
+2) Can't run dumpjson outside a conflict
+  $ hg resolve --tool internal:dumpjson
+  abort: no files or directories specified
+  (use --all to re-merge all unresolved files)
+  [255]
+
+3) Make a simple conflict
+  $ echo "Unconflicted base, F1" > F1
+  $ echo "Unconflicted base, F2" > F2
+  $ hg commit -Aqm "initial commit"
+  $ echo "First conflicted version, F1" > F1
+  $ echo "First conflicted version, F2" > F2
+  $ hg commit -m "first version, a"
+  $ hg bookmark a
+  $ hg checkout .~1
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (leaving bookmark a)
+  $ echo "Second conflicted version, F1" > F1
+  $ echo "Second conflicted version, F2" > F2
+  $ hg commit -m "second version, b"
+  created new head
+  $ hg bookmark b 
+  $ hg log -G -T '({rev}) {desc}\nbookmark: {bookmarks}\nfiles: {files}\n\n'
+  @  (2) second version, b
+  |  bookmark: b
+  |  files: F1 F2
+  |
+  | o  (1) first version, a
+  |/   bookmark: a
+  |files: F1 F2
+  |
+  o  (0) initial commit
+ bookmark:
+ files: F1 F2
+  
+
+
+  $ hg merge a
+  merging F1
+  merging F2
+  warning: conflicts while merging F1! (edit, then use 'hg resolve --mark')
+  warning: conflicts while merging F2! (edit, then use 'hg resolve --mark')
+  0 files updated, 0 files merged, 0 files removed, 2 files unresolved
+  use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to 
abandon
+  [1]
+
+5) Get the paths:
+  $ hg resolve --tool internal:dumpjson --all
+  [
+   {
+"conflicts": [{"base": {"contents": "Unconflicted base, F1\n", "isexec": 
false, "issymlink": false}, "local": {"contents": "Second conflicted version, 
F1\n", "isexec": false, "issymlink": false}, "other": {"contents": "First 
conflicted version, F1\n", "isexec": false, "issymlink": false}, "output": 
{"contents": "<<< working copy: 13124abb51b9 b - test: second version, 
b\nSecond conflicted version, F1\n===\nFirst conflicted version, 
F1\n>>> merge rev:6dd692b7db4a a - test: first version, a\n", "isexec": 
false, "issymlink": false, "path": "$TESTTMP/F1"}, "path": "F1"}, {"base": 
{"contents": "Unconflicted base, F2\n", "isexec": false, "issymlink": false}, 
"local": {"contents": "Second conflicted version, F2\n", "isexec": false, 
"issymlink": false}, "other": {"contents": "First conflicted version, F2\n", 
"isexec": false, "issymlink": false}, "output": {"contents": "<<< working 
copy: 13124abb51b9 b - test: second version, b\nSecond conflicted version, 
F2\n===\nFirst conflicted version, F2\n>>> merge rev:6dd692b7db4a a 
- test: first version, a\n", "isexec": false, "issymlink": false, "path": 
"$TESTTMP/F2"}, "path": "F2"}]
+   }
+  ]
+
+6) Only requested paths get dumped
+  $ hg resolve --tool internal:dumpjson F2
+  [
+   {
+"conflicts": [{"base": {"contents": "Unconflicted base, F2\n", "isexec": 
false, "issymlink": false}, "local": {"contents": "Second conflicted version, 
F2\n", "isexec": false, "issymlink": false}, "other": {"contents": "First 
conflicted version, F2\n", "isexec": false, "issymlink": false}, "output": 
{"contents": "<<< working copy: 13124abb51b9 b - test: second version, 
b\nSecond conflicted version, F2\n===\nFirst conflicted version, 
F2\n>>> merge rev:6dd692b7db4a a - test: first version, a\n", "isexec": 
false, "issymlink": false, "path": "$TESTTMP/F2"}, "path": "F2"}]
+   }
+  ]
+
+7) Ensure the paths point to the right contents:
+  $ getcontents() { # Usage: getcontents  
+  >  local script="import sy

[PATCH 2 of 4 V3] merge: add summarizeconflicts()

2017-03-16 Thread Phil Cohen
# HG changeset patch
# User Phil Cohen 
# Date 1489716532 25200
#  Thu Mar 16 19:08:52 2017 -0700
# Node ID 864def5028681cdffeaf5b440ff4753e1389f453
# Parent  ad81d182e88ffd3da20364f18204facf6e7750a3
merge: add summarizeconflicts()

calls `filemerge.summarize()` but only requires a workingctx and a path

diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -544,6 +544,25 @@
 Returns whether the merge is complete, and the exit code."""
 return self._resolve(True, dfile, wctx)
 
+def summarizeconflicts(self, path, workingctx):
+if self[path] in 'rd':
+return None
+stateentry = self._state[path]
+state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
+octx = self._repo[self._other]
+extras = self.extras(path)
+anccommitnode = extras.get('ancestorlinknode')
+if anccommitnode:
+ancestorctx = self._repo[anccommitnode]
+else:
+ancestorctx = None
+workingctx = self._filectxorabsent(hash, workingctx, path)
+otherctx = self._filectxorabsent(onode, octx, ofile)
+basectx = self._repo.filectx(afile, fileid=anode,
+ changeid=ancestorctx)
+
+return filemerge.summarize(self._repo, workingctx, otherctx, basectx)
+
 def resolve(self, dfile, wctx):
 """run merge process (assuming premerge was run) for dfile
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 4 V3] filemerge: add `summarize()`

2017-03-16 Thread Phil Cohen
Two things are new here since last time -- detecting absentfilectxs and 
the 'else' case that runs when the origfile is missing. Let me know if 
the assumption there holds.


The "look at the origfile" behavior (the "if" branch) came from the 
original code that launches the merge tool.


On 3/16/17 7:17 PM, Phil Cohen wrote:

# HG changeset patch
# User Phil Cohen 
# Date 1489716177 25200
#  Thu Mar 16 19:02:57 2017 -0700
# Node ID ad81d182e88ffd3da20364f18204facf6e7750a3
# Parent  568d80b24b3a3e4e6874ac0d95ddee056fef14e4
filemerge: add `summarize()`

returns a dictionary of each version of a conflict, given the contexts

diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -7,6 +7,7 @@

 from __future__ import absolute_import

+import copy
 import filecmp
 import os
 import re
@@ -567,6 +568,60 @@
 "o": " [%s]" % labels[1],
 }

+def summarize(repo, workingfilectx, otherctx, basectx):
+origfile = None if workingfilectx.isabsent() else \
+scmutil.origpath(repo.ui, repo, repo.wjoin(workingfilectx.path()))
+
+def flags(context):
+if isinstance(context, absentfilectx):
+return {'exists': False}
+return {
+'contents': context.data(),
+'exists': True,
+'isexec': context.isexec(),
+'issymlink': context.islink(),
+}
+
+output = flags(workingfilectx)
+
+if origfile and util.filestat(origfile).stat:
+# Since you can start a merge with a dirty working copy (either via
+# `up -n` or `merge -f`), "local" must reflect that, not the underlying
+# commit. Those contents are available in the .orig version, so we look
+# there and mock up the schema to look like the other contexts.
+local = {
+'contents': util.readfile(origfile),
+'exists': True,
+'isexec': util.isexec(origfile),
+'issymlink': util.statislink(util.filestat(origfile).stat),
+}
+else:
+# No backup file. This happens whenever the merge was esoteric enough
+# that we didn't launch a merge tool*, and instead prompted the user to
+# "use (c)hanged version, (d)elete, or leave (u)nresolved".
+#
+# The only way to exit that prompt with a conflict is to choose "u",
+# which leaves the local version in the working copy (with all its
+# pre-merge properties including any local changes), so we can reuse
+# that.
+#
+# Another alternative might be to use repo['.'][path] but that wouldn't
+# have any dirty pre-merge changes.
+#
+# *If we had, we'd've we would've overwritten the working copy, made a
+# backup and hit the above case.
+local = copy.copy(output)
+
+output['path'] = repo.wjoin(workingfilectx.path())
+
+return {
+'base': flags(basectx),
+'local': local,
+'other': flags(otherctx),
+'output': output,
+'path': workingfilectx.path(),
+}
+
 def _filemerge(premerge, repo, mynode, orig, fcd, fco, fca, labels=None):
 """perform a 3-way merge in the working directory

___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2Dscm.org_mailman_listinfo_mercurial-2Ddevel&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=mx0opQh0kf4fCU4SUKtQ-w&m=zNEo24XeGP6uuFpeTZpDknUXdTs3odSRA4zQ58SSUxo&s=lmzkUhUGn-ONxybCITeUUIp5zDxXPo-qLupBGN19eGA&e=


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


Re: [PATCH V2] merge: add `internal:dumpjson` tool to `resolve`, which outputs conflict state

2017-03-16 Thread Phil Cohen
Thanks a lot for the points re: variable names! I'm actually really 
happy to hear that -- these names were taken from elsewhere in the 
codebase, and they were very confusing. I have forgotten/had to relearn 
the difference between fcd/fca/fco/etc several times. Glad to hear that 
slightly longer/clearer names are encouraged.


On 3/15/17 11:20 PM, Ryan McElroy wrote:

More nits inline to consider since you're looking into a v3 anyway...


On 3/15/17 10:48 AM, Durham Goode wrote:



On 3/7/17 11:40 AM, Phil Cohen wrote:

# HG changeset patch
# User Phil Cohen 
# Date 1488915535 28800
#  Tue Mar 07 11:38:55 2017 -0800
# Node ID bbce62e3790220f19e7b37160a2f8351b7461272
# Parent  91e86a6c61c0c6a3b554eefeba906311aa29
merge: add `internal:dumpjson` tool to `resolve`, which outputs
conflict state

This supersedes a previous change which added a --prep option.


Generally we don't reference previous iterations of the patch in the
commit message, since those previous iterations wont' show up in the
repo after this is pushed.


Normally, `hg resolve` takes the user on a whistle-stop tour of each
conflicted
file, pausing to launch the editor to resolve the conflicts. This is an
alternative workflow for resolving many conflicts in a random-access
fashion. It
doesn't change/replace the default behavior.

This commit adds `--tool=internal:dumpjson`. It prints, for each
conflict, the
"base", "other", and "ours" versions (the contents, as well as their
exec/link
flags), and where the user/tool should write a resolved version
(i.e., the
working copy) as JSON. The user will then resolve the conflicts at
their leisure
and run `hg resolve --mark`.


Overall I think it looks good.  Some minor comments inline, but I'd be
ok having this queued (since it's been sitting here a while) and
addressing the nits in a follow up.


diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -33,6 +33,7 @@
 error,
 exchange,
 extensions,
+formatter,
 graphmod,
 hbisect,
 help,
@@ -4284,6 +4285,26 @@
 fm.end()
 return 0

+if opts.get('tool', '') == "internal:dumpjson":
+fm = ui.formatter('resolve', {'template': 'json'})
+ms = mergemod.mergestate.read(repo)


I don't love the short name style hg uses, and I don't see a godo reason
to use it unless there's already a strong-established precedent in the
file.

We've been calling formatters 'fm' for a long time, but 'ms' as
mergestate seems like a new one (to me at least). I'd love a more
descriptive variable name since we have the option right now


+m = scmutil.match(repo[None], pats, opts)


Would prefer this be called 'matcher'


+wctx = repo[None]
+
+paths = []
+for f in ms:


Then this could become:

for filename in mergestate:

And then it's obvious from just reading the loop what it is doing


+if not m(f):


And this would become:

if not matcher(filename):

Which is also much more clear to me at least.


+continue
+
+val = ms.internaldump(f, wctx)
+if val is not None:
+paths.append(val)
+
+fm.startitem()
+fm.write('conflicts', '%s\n', paths)
+fm.end()
+return 0
+
 with repo.wlock():
 ms = mergemod.mergestate.read(repo)

diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -567,6 +567,40 @@
 "o": " [%s]" % labels[1],
 }

+def summarize(repo, fcd, fco, fca):


I'm sure we can come up with better parameter names here too.

fca is probably the "file context ancestor", but I have no idea what fcd
and fco are without diving deep into the code.


+back = None if fcd.isabsent() else \
+scmutil.origpath(repo.ui, repo, repo.wjoin(fcd.path()))


It's unclear to me what 'back' will be used for. Can you add a comment?
(is it the "back"up -- the .orig file?)


+
+def sum(ctx):


I'd name this flags() instead of sum


+return {
+'contents': ctx.data(),
+'isexec': ctx.isexec(),
+'issymlink': ctx.islink(),
+}
+
+ours = None


'ours' is a git thing, not a mercurial thing. Let's use consitent
hg-internal naming if possible:
* local
* other
* base


+if back and util.filestat(back).stat:
+# Replicate the schema of `base` and `other` for `ours`.
Since you can
+# start a merge with a dirty working copy, `ours` must
reflect that,
+# not the underlying commit. That's why we look at .orig
version.
+ours = {
+'path': back,
+'contents': util.readfile(back),
+'isexec': util.isexec(back),
+'issymlink': util.statislink(util.filestat(back).stat)
+}
+
+output = sum(fcd)
+output['path'] = repo.wjoin(fcd.path())
+
+return {
+'path': fcd.path(),
+'base': sum(fca),
+'other'

Re: [PATCH V2] merge: add `internal:dumpjson` tool to `resolve`, which outputs conflict state

2017-03-16 Thread Jun Wu
Just to add some notes on variable names. There are some very common short
names. Like "p1" representing "parent1". And "p1" should be preferred. An
incomplete list is at [1]. It's okay to use "fname" hetlridvnvrtrtf
"filename".

FWIW, Ruby community standard prefers longer names while Golang explicitly
prefers shorter names [2]. I think both are reasonable, as long as the code
is consistent.

For less-common things like "fca", "fco", etc. Longer names are definitely
better. For common objects like "matcher", "manifest", I think either is
okay. Since we are unlikely to rename "p1" to "parent1", I personally prefer
shorter ones for unambiguous common objects, especially when it can reduce
line wraps.

[1]: https://www.mercurial-scm.org/wiki/CodingStyle
[2]: https://github.com/golang/go/wiki/CodeReviewComments#variable-names


Excerpts from Phil Cohen's message of 2017-03-16 19:32:44 -0700:
> Thanks a lot for the points re: variable names! I'm actually really 
> happy to hear that -- these names were taken from elsewhere in the 
> codebase, and they were very confusing. I have forgotten/had to relearn 
> the difference between fcd/fca/fco/etc several times. Glad to hear that 
> slightly longer/clearer names are encouraged.
> 
> On 3/15/17 11:20 PM, Ryan McElroy wrote:
> > More nits inline to consider since you're looking into a v3 anyway...
> >
> >
> > On 3/15/17 10:48 AM, Durham Goode wrote:
> >>
> >>
> >> On 3/7/17 11:40 AM, Phil Cohen wrote:
> >>> # HG changeset patch
> >>> # User Phil Cohen 
> >>> # Date 1488915535 28800
> >>> #  Tue Mar 07 11:38:55 2017 -0800
> >>> # Node ID bbce62e3790220f19e7b37160a2f8351b7461272
> >>> # Parent  91e86a6c61c0c6a3b554eefeba906311aa29
> >>> merge: add `internal:dumpjson` tool to `resolve`, which outputs
> >>> conflict state
> >>>
> >>> This supersedes a previous change which added a --prep option.
> >>
> >> Generally we don't reference previous iterations of the patch in the
> >> commit message, since those previous iterations wont' show up in the
> >> repo after this is pushed.
> >>
> >>> Normally, `hg resolve` takes the user on a whistle-stop tour of each
> >>> conflicted
> >>> file, pausing to launch the editor to resolve the conflicts. This is an
> >>> alternative workflow for resolving many conflicts in a random-access
> >>> fashion. It
> >>> doesn't change/replace the default behavior.
> >>>
> >>> This commit adds `--tool=internal:dumpjson`. It prints, for each
> >>> conflict, the
> >>> "base", "other", and "ours" versions (the contents, as well as their
> >>> exec/link
> >>> flags), and where the user/tool should write a resolved version
> >>> (i.e., the
> >>> working copy) as JSON. The user will then resolve the conflicts at
> >>> their leisure
> >>> and run `hg resolve --mark`.
> >>
> >> Overall I think it looks good.  Some minor comments inline, but I'd be
> >> ok having this queued (since it's been sitting here a while) and
> >> addressing the nits in a follow up.
> >>
> >>> diff --git a/mercurial/commands.py b/mercurial/commands.py
> >>> --- a/mercurial/commands.py
> >>> +++ b/mercurial/commands.py
> >>> @@ -33,6 +33,7 @@
> >>>  error,
> >>>  exchange,
> >>>  extensions,
> >>> +formatter,
> >>>  graphmod,
> >>>  hbisect,
> >>>  help,
> >>> @@ -4284,6 +4285,26 @@
> >>>  fm.end()
> >>>  return 0
> >>>
> >>> +if opts.get('tool', '') == "internal:dumpjson":
> >>> +fm = ui.formatter('resolve', {'template': 'json'})
> >>> +ms = mergemod.mergestate.read(repo)
> >
> > I don't love the short name style hg uses, and I don't see a godo reason
> > to use it unless there's already a strong-established precedent in the
> > file.
> >
> > We've been calling formatters 'fm' for a long time, but 'ms' as
> > mergestate seems like a new one (to me at least). I'd love a more
> > descriptive variable name since we have the option right now
> >
> >>> +m = scmutil.match(repo[None], pats, opts)
> >
> > Would prefer this be called 'matcher'
> >
> >>> +wctx = repo[None]
> >>> +
> >>> +paths = []
> >>> +for f in ms:
> >
> > Then this could become:
> >
> > for filename in mergestate:
> >
> > And then it's obvious from just reading the loop what it is doing
> >
> >>> +if not m(f):
> >
> > And this would become:
> >
> > if not matcher(filename):
> >
> > Which is also much more clear to me at least.
> >
> >>> +continue
> >>> +
> >>> +val = ms.internaldump(f, wctx)
> >>> +if val is not None:
> >>> +paths.append(val)
> >>> +
> >>> +fm.startitem()
> >>> +fm.write('conflicts', '%s\n', paths)
> >>> +fm.end()
> >>> +return 0
> >>> +
> >>>  with repo.wlock():
> >>>  ms = mergemod.mergestate.read(repo)
> >>>
> >>> diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
> >>> --- a/mercurial/filemerge.py
> >>> +++ b/mercurial/filemerge.py
> >>> @@ -567,6 +567,40 @@
> >>>  "o

Re: [PATCH V2] merge: add `internal:dumpjson` tool to `resolve`, which outputs conflict state

2017-03-16 Thread Jun Wu
Fix a cat typing.

Excerpts from Jun Wu's message of 2017-03-16 20:12:28 -0700:
> Just to add some notes on variable names. There are some very common short
> names. Like "p1" representing "parent1". And "p1" should be preferred. An
> incomplete list is at [1]. It's okay to use "fname" hetlridvnvrtrtf
  ^^^
  or "fn" instead of

> "filename".
> 
> FWIW, Ruby community standard prefers longer names while Golang explicitly
> prefers shorter names [2]. I think both are reasonable, as long as the code
> is consistent.
> 
> For less-common things like "fca", "fco", etc. Longer names are definitely
> better. For common objects like "matcher", "manifest", I think either is
> okay. Since we are unlikely to rename "p1" to "parent1", I personally prefer
> shorter ones for unambiguous common objects, especially when it can reduce
> line wraps.
> 
> [1]: https://www.mercurial-scm.org/wiki/CodingStyle
> [2]: https://github.com/golang/go/wiki/CodeReviewComments#variable-names
> 
> Excerpts from Phil Cohen's message of 2017-03-16 19:32:44 -0700:
> > Thanks a lot for the points re: variable names! I'm actually really 
> > happy to hear that -- these names were taken from elsewhere in the 
> > codebase, and they were very confusing. I have forgotten/had to relearn 
> > the difference between fcd/fca/fco/etc several times. Glad to hear that 
> > slightly longer/clearer names are encouraged.
> > 
> > On 3/15/17 11:20 PM, Ryan McElroy wrote:
> > > More nits inline to consider since you're looking into a v3 anyway...
> > >
> > >
> > > On 3/15/17 10:48 AM, Durham Goode wrote:
> > >>
> > >>
> > >> On 3/7/17 11:40 AM, Phil Cohen wrote:
> > >>> # HG changeset patch
> > >>> # User Phil Cohen 
> > >>> # Date 1488915535 28800
> > >>> #  Tue Mar 07 11:38:55 2017 -0800
> > >>> # Node ID bbce62e3790220f19e7b37160a2f8351b7461272
> > >>> # Parent  91e86a6c61c0c6a3b554eefeba906311aa29
> > >>> merge: add `internal:dumpjson` tool to `resolve`, which outputs
> > >>> conflict state
> > >>>
> > >>> This supersedes a previous change which added a --prep option.
> > >>
> > >> Generally we don't reference previous iterations of the patch in the
> > >> commit message, since those previous iterations wont' show up in the
> > >> repo after this is pushed.
> > >>
> > >>> Normally, `hg resolve` takes the user on a whistle-stop tour of each
> > >>> conflicted
> > >>> file, pausing to launch the editor to resolve the conflicts. This is an
> > >>> alternative workflow for resolving many conflicts in a random-access
> > >>> fashion. It
> > >>> doesn't change/replace the default behavior.
> > >>>
> > >>> This commit adds `--tool=internal:dumpjson`. It prints, for each
> > >>> conflict, the
> > >>> "base", "other", and "ours" versions (the contents, as well as their
> > >>> exec/link
> > >>> flags), and where the user/tool should write a resolved version
> > >>> (i.e., the
> > >>> working copy) as JSON. The user will then resolve the conflicts at
> > >>> their leisure
> > >>> and run `hg resolve --mark`.
> > >>
> > >> Overall I think it looks good.  Some minor comments inline, but I'd be
> > >> ok having this queued (since it's been sitting here a while) and
> > >> addressing the nits in a follow up.
> > >>
> > >>> diff --git a/mercurial/commands.py b/mercurial/commands.py
> > >>> --- a/mercurial/commands.py
> > >>> +++ b/mercurial/commands.py
> > >>> @@ -33,6 +33,7 @@
> > >>>  error,
> > >>>  exchange,
> > >>>  extensions,
> > >>> +formatter,
> > >>>  graphmod,
> > >>>  hbisect,
> > >>>  help,
> > >>> @@ -4284,6 +4285,26 @@
> > >>>  fm.end()
> > >>>  return 0
> > >>>
> > >>> +if opts.get('tool', '') == "internal:dumpjson":
> > >>> +fm = ui.formatter('resolve', {'template': 'json'})
> > >>> +ms = mergemod.mergestate.read(repo)
> > >
> > > I don't love the short name style hg uses, and I don't see a godo reason
> > > to use it unless there's already a strong-established precedent in the
> > > file.
> > >
> > > We've been calling formatters 'fm' for a long time, but 'ms' as
> > > mergestate seems like a new one (to me at least). I'd love a more
> > > descriptive variable name since we have the option right now
> > >
> > >>> +m = scmutil.match(repo[None], pats, opts)
> > >
> > > Would prefer this be called 'matcher'
> > >
> > >>> +wctx = repo[None]
> > >>> +
> > >>> +paths = []
> > >>> +for f in ms:
> > >
> > > Then this could become:
> > >
> > > for filename in mergestate:
> > >
> > > And then it's obvious from just reading the loop what it is doing
> > >
> > >>> +if not m(f):
> > >
> > > And this would become:
> > >
> > > if not matcher(filename):
> > >
> > > Which is also much more clear to me at least.
> > >
> > >>> +continue
> > >>> +
> > >>> +val = ms.internaldump(f, wctx)
> > >>> +if val

[PATCH evolve-ext] tests: add glob for Windows

2017-03-16 Thread Matt Harbison
# HG changeset patch
# User Matt Harbison 
# Date 1489720627 14400
#  Thu Mar 16 23:17:07 2017 -0400
# Node ID ab5c2bef148bfb60e1956a55de4b7ba00ebe1817
# Parent  6a3248558b6929378450b572bb27406afe703ffd
tests: add glob for Windows

diff --git a/tests/test-inhibit.t b/tests/test-inhibit.t
--- a/tests/test-inhibit.t
+++ b/tests/test-inhibit.t
@@ -911,7 +911,7 @@
   $ cd not-inhibit
   $ hg book -d foo
   $ hg pull
-  pulling from $TESTTMP/inhibit
+  pulling from $TESTTMP/inhibit (glob)
   searching for changes
   no changes found
   adding remote bookmark foo
diff --git a/tests/test-stablesort.t b/tests/test-stablesort.t
--- a/tests/test-stablesort.t
+++ b/tests/test-stablesort.t
@@ -138,7 +138,7 @@
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R repo_B pull --rev 13
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
@@ -146,7 +146,7 @@
   added 4 changesets with 0 changes to 0 files (+1 heads)
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg -R repo_B pull --rev 14
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
@@ -154,7 +154,7 @@
   added 1 changesets with 0 changes to 0 files (+1 heads)
   (run 'hg heads .' to see heads, 'hg merge' to merge)
   $ hg -R repo_B pull
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
@@ -204,7 +204,7 @@
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R repo_C pull --rev 12
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
@@ -212,7 +212,7 @@
   added 2 changesets with 0 changes to 0 files (+1 heads)
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg -R repo_C pull --rev 15
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
@@ -220,7 +220,7 @@
   added 4 changesets with 0 changes to 0 files (+1 heads)
   (run 'hg heads .' to see heads, 'hg merge' to merge)
   $ hg -R repo_C pull
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
@@ -270,7 +270,7 @@
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R repo_D pull --rev 10
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
@@ -278,7 +278,7 @@
   added 5 changesets with 0 changes to 0 files
   (run 'hg update' to get a working copy)
   $ hg -R repo_D pull --rev 15
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
@@ -286,7 +286,7 @@
   added 4 changesets with 0 changes to 0 files (+1 heads)
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg -R repo_D pull
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
@@ -404,7 +404,7 @@
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R repo_E pull --rev e7d9710d9fc6
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
@@ -420,7 +420,7 @@
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R repo_F pull --rev d62d843c9a01
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
@@ -436,7 +436,7 @@
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R repo_G pull --rev 43227190fef8
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
@@ -444,7 +444,7 @@
   added 1 changesets with 0 changes to 0 files (+1 heads)
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg -R repo_G pull --rev 2702dd0c91e7
-  pulling from $TESTTMP/repo_A
+  pulling from $TESTTMP/repo_A (glob)
   searching for changes
   adding changesets
   adding manifests
diff --git a/tests/test-topic-dest.t b/tests/test-topic-dest.t
--- a/tests/test-topic-dest.t
+++ b/tests/test-topic-dest.t
@@ -276,7 +276,7 @@
   $ hg add other
   $ hg ci -m 'c_other'
   $ hg pull -r default --rebase
-  pulling from $TESTTMP/jungle
+  pulling from $TESTTMP/jungle (glob)
   searching for changes
   adding changesets
   adding manifests
diff --git a/tests/test-topic-push.t b/tests/test-topic-push.t
--- a/tests/test-topic-push.t
+++ b

Re: [PATCH V2] merge: add `internal:dumpjson` tool to `resolve`, which outputs conflict state

2017-03-16 Thread Phil Cohen
I agree with pretty much all of that. Short standardized names that represent 
universal concepts in the codebase (like p1) are very useful.

To steal Siracusa's description of Perl, it is a bit like Huffman coding: make 
the common case easy and short, and the more unusual case longer and more 
descriptive.



From: Jun Wu
Sent: Thursday, March 16, 2017 8:15 PM
To: Jun Wu
Cc: Phil Cohen; Ryan McElroy; Durham Goode; mercurial-devel
Subject: Re: [PATCH V2] merge: add `internal:dumpjson` tool to `resolve`, which 
outputs conflict state
    
Fix a cat typing.

Excerpts from Jun Wu's message of 2017-03-16 20:12:28 -0700:
> Just to add some notes on variable names. There are some very common short
> names. Like "p1" representing "parent1". And "p1" should be preferred. An
> incomplete list is at [1]. It's okay to use "fname" hetlridvnvrtrtf
  ^^^
  or "fn" instead of

> "filename".
> 
> FWIW, Ruby community standard prefers longer names while Golang explicitly
> prefers shorter names [2]. I think both are reasonable, as long as the code
> is consistent.
> 
> For less-common things like "fca", "fco", etc. Longer names are definitely
> better. For common objects like "matcher", "manifest", I think either is
> okay. Since we are unlikely to rename "p1" to "parent1", I personally prefer
> shorter ones for unambiguous common objects, especially when it can reduce
> line wraps.
> 
> [1]: https://www.mercurial-scm.org/wiki/CodingStyle


CodingStyle - Mercurial
www.mercurial-scm.org
1. Introduction. This page is intended to save new developers a few round-trips 
when contributing changes. It doesn't cover everything, but it does cover some 
of the ...

> [2]:  https://github.com/golang/go/wiki/CodeReviewComments#variable-names

 https://avatars1.githubusercontent.com/u/4314092?v=3&s=400 

CodeReviewComments · golang/go Wiki · GitHub
github.com
The former declares a nil slice value, while the latter is non-nil but 
zero-length. They are functionally equivalent—their len and cap are both 
zero—but the nil ...

> 
> Excerpts from Phil Cohen's message of 2017-03-16 19:32:44 -0700:
> > Thanks a lot for the points re: variable names! I'm actually really 
> > happy to hear that -- these names were taken from elsewhere in the 
> > codebase, and they were very confusing. I have forgotten/had to relearn 
> > the difference between fcd/fca/fco/etc several times. Glad to hear that 
> > slightly longer/clearer names are encouraged.
> > 
> > On 3/15/17 11:20 PM, Ryan McElroy wrote:
> > > More nits inline to consider since you're looking into a v3 anyway...
> > >
> > >
> > > On 3/15/17 10:48 AM, Durham Goode wrote:
> > >>
> > >>
> > >> On 3/7/17 11:40 AM, Phil Cohen wrote:
> > >>> # HG changeset patch
> > >>> # User Phil Cohen 
> > >>> # Date 1488915535 28800
> > >>> #  Tue Mar 07 11:38:55 2017 -0800
> > >>> # Node ID bbce62e3790220f19e7b37160a2f8351b7461272
> > >>> # Parent  91e86a6c61c0c6a3b554eefeba906311aa29
> > >>> merge: add `internal:dumpjson` tool to `resolve`, which outputs
> > >>> conflict state
> > >>>
> > >>> This supersedes a previous change which added a --prep option.
> > >>
> > >> Generally we don't reference previous iterations of the patch in the
> > >> commit message, since those previous iterations wont' show up in the
> > >> repo after this is pushed.
> > >>
> > >>> Normally, `hg resolve` takes the user on a whistle-stop tour of each
> > >>> conflicted
> > >>> file, pausing to launch the editor to resolve the conflicts. This is an
> > >>> alternative workflow for resolving many conflicts in a random-access
> > >>> fashion. It
> > >>> doesn't change/replace the default behavior.
> > >>>
> > >>> This commit adds `--tool=internal:dumpjson`. It prints, for each
> > >>> conflict, the
> > >>> "base", "other", and "ours" versions (the contents, as well as their
> > >>> exec/link
> > >>> flags), and where the user/tool should write a resolved version
> > >>> (i.e., the
> > >>> working copy) as JSON. The user will then resolve the conflicts at
> > >>> their leisure
> > >>> and run `hg resolve --mark`.
> > >>
> > >> Overall I think it looks good.  Some minor comments inline, but I'd be
> > >> ok having this queued (since it's been sitting here a while) and
> > >> addressing the nits in a follow up.
> > >>
> > >>> diff --git a/mercurial/commands.py b/mercurial/commands.py
> > >>> --- a/mercurial/commands.py
> > >>> +++ b/mercurial/commands.py
> > >>> @@ -33,6 +33,7 @@
> > >>>  error,
> > >>>  exchange,
> > >>>  extensions,
> > >>> +    formatter,
> > >>>  graphmod,
> > >>>  hbisect,
> > >>>  help,
> > >>> @@ -4284,6 +4285,26 @@
> > >>>  fm.end()
> > >>>  return 0
> > >>>
> > >>> +    if opts.get('tool', '') == "internal:dumpjson":
> > >>> +    fm = ui.formatter('resolve', {'template': 'json'})
> > >>> +    ms = mergemod.mergestate.read(repo)
> > >
> > > I