[PATCH] py3: refactor token parsing to handle call args properly

2016-10-13 Thread Martijn Pieters
# HG changeset patch
# User Martijn Pieters 
# Date 1476346188 -3600
#  Thu Oct 13 09:09:48 2016 +0100
# Node ID 81d23b9e2b329666db6e342f6bafec54a893687c
# Parent  733fb9f7bc92c694ba6bededaeb93206528c0bcd
py3: refactor token parsing to handle call args properly

The token parsing was getting unwieldy and was too naive about accessing
arguments.

diff --git a/mercurial/__init__.py b/mercurial/__init__.py
--- a/mercurial/__init__.py
+++ b/mercurial/__init__.py
@@ -185,6 +185,61 @@
 OR CACHED FILES WON'T GET INVALIDATED PROPERLY.
 """
 futureimpline = False
+
+# The following utility functions access the tokens list and i index of
+# the for i, t enumerate(tokens) loop below
+def _is_op(j, *o):
+"""Assert that tokens[j] is an OP with one of the given values"""
+try:
+return tokens[j].type == token.OP and tokens[j].string in o
+except IndexError:
+return False
+
+def _find_argn_of_call(n):
+"""Find arg n of a call expression (start at 0)
+
+Returns index of the first token of that argument, or None if
+there is not that many arguments.
+
+Assumes that token[i + 1] is '('.
+
+"""
+j = i + 2
+nested = 0
+try:
+while True:
+if _is_op(j, ')', ']', '}'):
+# end of call, tuple, subscription or dict / set
+nested -= 1
+if nested < 0:
+return None
+elif n == 0:
+# this is the starting position of arg
+return j
+elif _is_op(j, '(', '[', '{'):
+nested += 1
+elif _is_op(j, ',') and nested == 0:
+n -= 1
+j += 1
+except IndexError:
+return None
+
+def _ensure_unicode(j):
+"""Make sure the token at j is a unicode string
+
+This rewrites a string token to include the unicode literal prefix
+so the string transformer won't add the byte prefix.
+
+Ignores tokens that are not strings. Assumes bounds checking has
+already been done.
+
+"""
+st = tokens[j]
+if st.type == token.STRING and st.string.startswith(("'", '"')):
+rt = tokenize.TokenInfo(st.type, 'u%s' % st.string,
+st.start, st.end, st.line)
+tokens[j] = rt
+
 for i, t in enumerate(tokens):
 # Convert most string literals to byte literals. String literals
 # in Python 2 are bytes. String literals in Python 3 are unicode.
@@ -241,91 +296,35 @@
  '')
 continue
 
-try:
-nexttoken = tokens[i + 1]
-except IndexError:
-nexttoken = None
-
-try:
-prevtoken = tokens[i - 1]
-except IndexError:
-prevtoken = None
-
 # This looks like a function call.
-if (t.type == token.NAME and nexttoken and
-nexttoken.type == token.OP and nexttoken.string == '('):
+if t.type == token.NAME and _is_op(i + 1, '('):
 fn = t.string
 
 # *attr() builtins don't accept byte strings to 2nd argument.
-# Rewrite the token to include the unicode literal prefix so
-# the string transformer above doesn't add the byte prefix.
-if fn in ('getattr', 'setattr', 'hasattr', 'safehasattr'):
-try:
-# (NAME, 'getattr')
-# (OP, '(')
-# (NAME, 'foo')
-# (OP, ',')
-# (NAME|STRING, foo)
-st = tokens[i + 4]
-if (st.type == token.STRING and
-st.string[0] in ("'", '"')):
-rt = tokenize.TokenInfo(st.type, 'u%s' % st.string,
-st.start, st.end, st.line)
-tokens[i + 4] = rt
-except IndexError:
-pass
+if (fn in ('getattr', 'setattr', 'hasattr', 'safehasattr') and
+not _is_op(i - 1, '.')):
+arg1idx = _find_argn_of_call(1)
+if arg1idx is not None:
+_ensure_unicode(arg1idx)
 
 # .encode() and .decode() on str/bytes/unicode don't accept
-# byte strings on Python 3. Rewrite the token to include the
-# unicode literal prefix so the string transformer above 
doesn't
- 

[PATCH] py3: use namedtuple._replace to produce new tokens

2016-10-13 Thread Martijn Pieters
# HG changeset patch
# User Martijn Pieters 
# Date 1476347257 -3600
#  Thu Oct 13 09:27:37 2016 +0100
# Node ID 22a15130f57927a79227ebfe763be082e2992f04
# Parent  81d23b9e2b329666db6e342f6bafec54a893687c
py3: use namedtuple._replace to produce new tokens

diff --git a/mercurial/__init__.py b/mercurial/__init__.py
--- a/mercurial/__init__.py
+++ b/mercurial/__init__.py
@@ -236,9 +236,7 @@
 """
 st = tokens[j]
 if st.type == token.STRING and st.string.startswith(("'", '"')):
-rt = tokenize.TokenInfo(st.type, 'u%s' % st.string,
-st.start, st.end, st.line)
-tokens[j] = rt
+tokens[j] = st._replace(string='u%s' % st.string)
 
 for i, t in enumerate(tokens):
 # Convert most string literals to byte literals. String literals
@@ -269,8 +267,7 @@
 continue
 
 # String literal. Prefix to make a b'' string.
-yield tokenize.TokenInfo(t.type, 'b%s' % s, t.start, t.end,
-  t.line)
+yield t._replace(string='b%s' % t.string)
 continue
 
 # Insert compatibility imports at "from __future__ import" line.
@@ -290,10 +287,8 @@
 for u in tokenize.tokenize(io.BytesIO(l).readline):
 if u.type in (tokenize.ENCODING, token.ENDMARKER):
 continue
-yield tokenize.TokenInfo(u.type, u.string,
- (r, c + u.start[1]),
- (r, c + u.end[1]),
- '')
+yield u._replace(
+start=(r, c + u.start[1]), end=(r, c + u.end[1]))
 continue
 
 # This looks like a function call.
@@ -325,8 +320,7 @@
 # It changes iteritems to items as iteritems is not
 # present in Python 3 world.
 elif fn == 'iteritems':
-yield tokenize.TokenInfo(t.type, 'items',
- t.start, t.end, t.line)
+yield t._replace(string='items')
 continue
 
 # Emit unmodified token.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] py3: refactor token parsing to handle call args properly

2016-10-13 Thread Gregory Szorc
On Thu, Oct 13, 2016 at 10:10 AM, Martijn Pieters  wrote:

> # HG changeset patch
> # User Martijn Pieters 
> # Date 1476346188 -3600
> #  Thu Oct 13 09:09:48 2016 +0100
> # Node ID 81d23b9e2b329666db6e342f6bafec54a893687c
> # Parent  733fb9f7bc92c694ba6bededaeb93206528c0bcd
> py3: refactor token parsing to handle call args properly
>
> The token parsing was getting unwieldy and was too naive about accessing
> arguments.
>
> diff --git a/mercurial/__init__.py b/mercurial/__init__.py
> --- a/mercurial/__init__.py
> +++ b/mercurial/__init__.py
> @@ -185,6 +185,61 @@
>  OR CACHED FILES WON'T GET INVALIDATED PROPERLY.
>  """
>  futureimpline = False
> +
> +# The following utility functions access the tokens list and i
> index of
> +# the for i, t enumerate(tokens) loop below
> +def _is_op(j, *o):
> +"""Assert that tokens[j] is an OP with one of the given
> values"""
> +try:
> +return tokens[j].type == token.OP and tokens[j].string in
> o
> +except IndexError:
> +return False
> +
> +def _find_argn_of_call(n):
> +"""Find arg n of a call expression (start at 0)
> +
> +Returns index of the first token of that argument, or None if
> +there is not that many arguments.
> +
> +Assumes that token[i + 1] is '('.
> +
> +"""
> +j = i + 2
> +nested = 0
> +try:
> +while True:
> +if _is_op(j, ')', ']', '}'):
> +# end of call, tuple, subscription or dict / set
> +nested -= 1
> +if nested < 0:
> +return None
> +elif n == 0:
> +# this is the starting position of arg
> +return j
> +elif _is_op(j, '(', '[', '{'):
> +nested += 1
> +elif _is_op(j, ',') and nested == 0:
> +n -= 1
> +j += 1
> +except IndexError:
> +return None
> +
> +def _ensure_unicode(j):
> +"""Make sure the token at j is a unicode string
> +
> +This rewrites a string token to include the unicode literal
> prefix
> +so the string transformer won't add the byte prefix.
> +
> +Ignores tokens that are not strings. Assumes bounds checking
> has
> +already been done.
> +
> +"""
> +st = tokens[j]
> +if st.type == token.STRING and st.string.startswith(("'",
> '"')):
> +rt = tokenize.TokenInfo(st.type, 'u%s' % st.string,
> +st.start, st.end, st.line)
> +tokens[j] = rt
> +
>  for i, t in enumerate(tokens):
>  # Convert most string literals to byte literals. String
> literals
>  # in Python 2 are bytes. String literals in Python 3 are
> unicode.
> @@ -241,91 +296,35 @@
>   '')
>  continue
>
> -try:
> -nexttoken = tokens[i + 1]
> -except IndexError:
> -nexttoken = None
> -
> -try:
> -prevtoken = tokens[i - 1]
> -except IndexError:
> -prevtoken = None
> -
>  # This looks like a function call.
> -if (t.type == token.NAME and nexttoken and
> -nexttoken.type == token.OP and nexttoken.string == '('):
> +if t.type == token.NAME and _is_op(i + 1, '('):
>  fn = t.string
>
>  # *attr() builtins don't accept byte strings to 2nd
> argument.
> -# Rewrite the token to include the unicode literal prefix
> so
> -# the string transformer above doesn't add the byte
> prefix.
> -if fn in ('getattr', 'setattr', 'hasattr', 'safehasattr'):
> -try:
> -# (NAME, 'getattr')
> -# (OP, '(')
> -# (NAME, 'foo')
> -# (OP, ',')
> -# (NAME|STRING, foo)
> -st = tokens[i + 4]
> -if (st.type == token.STRING and
> -st.string[0] in ("'", '"')):
> -rt = tokenize.TokenInfo(st.type, 'u%s' %
> st.string,
> -st.start, st.end,
> st.line)
> -tokens[i + 4] = rt
> -except IndexError:
> -pass
> +if (fn in ('getattr', 'setattr', 'hasattr',
> 'safehasattr') and
> +not _is_op(i - 1, '.')):
> +arg1idx = _find_argn_of_call(1)
> +if 

[PATCH] dirs: add comment about _PyBytes_Resize

2016-10-13 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1476349169 -7200
#  Thu Oct 13 10:59:29 2016 +0200
# Node ID 27e00e6352ceadb48c11c6f5902093a26d58f569
# Parent  733fb9f7bc92c694ba6bededaeb93206528c0bcd
dirs: add comment about _PyBytes_Resize

So readers have a canonical function to compare this code to.

diff --git a/mercurial/dirs.c b/mercurial/dirs.c
--- a/mercurial/dirs.c
+++ b/mercurial/dirs.c
@@ -58,9 +58,10 @@ static int _addpath(PyObject *dirs, PyOb
* implementation details. We also commit violations of the Python
* "protocol" such as mutating immutable objects. But since we only
* mutate objects created in this function or in other well-defined
* locations, the references are known so these violations should go
-   * unnoticed. */
+   * unnoticed. The code for adjusting the length of a PyBytesObject is
+   * essentially a minimal version of _PyBytes_Resize. */
while ((pos = _finddir(cpath, pos - 1)) != -1) {
PyObject *val;
 
/* It's likely that every prefix already has an entry
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] dirs: add comment about _PyBytes_Resize

2016-10-13 Thread Pierre-Yves David



On 10/13/2016 10:59 AM, Gregory Szorc wrote:

# HG changeset patch
# User Gregory Szorc 
# Date 1476349169 -7200
#  Thu Oct 13 10:59:29 2016 +0200
# Node ID 27e00e6352ceadb48c11c6f5902093a26d58f569
# Parent  733fb9f7bc92c694ba6bededaeb93206528c0bcd
dirs: add comment about _PyBytes_Resize

So readers have a canonical function to compare this code to.


Sure, pushed, thanks.

Cheers,

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


Re: [PATCH] py3: refactor token parsing to handle call args properly

2016-10-13 Thread Martijn Pieters
> Nice refactor. While I haven't looked at the code in detail yet, does 
> check-code not complain about the use of underscore_function_names?

Apparently not! I did run the whole test suite, and ran it again just now. 
Nested function names are locals and exempt from the rule it appears.

Should I resend with adjusted function names?

--
Martijn



signature.asc
Description: Message signed with OpenPGP using GPGMail
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] py3: refactor token parsing to handle call args properly

2016-10-13 Thread Gregory Szorc
On Thu, Oct 13, 2016 at 11:09 AM, Martijn Pieters  wrote:

> > Nice refactor. While I haven't looked at the code in detail yet, does
> check-code not complain about the use of underscore_function_names?
>
> Apparently not! I did run the whole test suite, and ran it again just now.
> Nested function names are locals and exempt from the rule it appears.
>
> Should I resend with adjusted function names?
>

Unless I'm missing something obvious, you should.

And my guess is someone will patch the style checker to catch nested
function names :)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] py3: refactor token parsing to handle call args properly

2016-10-13 Thread Pierre-Yves David



On 10/13/2016 11:13 AM, Gregory Szorc wrote:

On Thu, Oct 13, 2016 at 11:09 AM, Martijn Pieters mailto:m...@zopatista.com>> wrote:

> Nice refactor. While I haven't looked at the code in detail yet, does 
check-code not complain about the use of underscore_function_names?

Apparently not! I did run the whole test suite, and ran it again
just now. Nested function names are locals and exempt from the rule
it appears.

Should I resend with adjusted function names?


Unless I'm missing something obvious, you should.


+1


And my guess is someone will patch the style checker to catch nested
function names :)


+1

This makes a total of +2 ;-)

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


[PATCH 2 of 2 V2] py3: use namedtuple._replace to produce new tokens

2016-10-13 Thread Martijn Pieters
# HG changeset patch
# User Martijn Pieters 
# Date 1476347257 -3600
#  Thu Oct 13 09:27:37 2016 +0100
# Node ID cb2bb27c6b29efd78a9e0ee28917c975b9bc5ff3
# Parent  36607cf1bbd9fd4d99b607f927bc807fcc48d0ea
py3: use namedtuple._replace to produce new tokens

diff --git a/mercurial/__init__.py b/mercurial/__init__.py
--- a/mercurial/__init__.py
+++ b/mercurial/__init__.py
@@ -236,9 +236,7 @@
 """
 st = tokens[j]
 if st.type == token.STRING and st.string.startswith(("'", '"')):
-rt = tokenize.TokenInfo(st.type, 'u%s' % st.string,
-st.start, st.end, st.line)
-tokens[j] = rt
+tokens[j] = st._replace(string='u%s' % st.string)
 
 for i, t in enumerate(tokens):
 # Convert most string literals to byte literals. String literals
@@ -269,8 +267,7 @@
 continue
 
 # String literal. Prefix to make a b'' string.
-yield tokenize.TokenInfo(t.type, 'b%s' % s, t.start, t.end,
-  t.line)
+yield t._replace(string='b%s' % t.string)
 continue
 
 # Insert compatibility imports at "from __future__ import" line.
@@ -290,10 +287,8 @@
 for u in tokenize.tokenize(io.BytesIO(l).readline):
 if u.type in (tokenize.ENCODING, token.ENDMARKER):
 continue
-yield tokenize.TokenInfo(u.type, u.string,
- (r, c + u.start[1]),
- (r, c + u.end[1]),
- '')
+yield u._replace(
+start=(r, c + u.start[1]), end=(r, c + u.end[1]))
 continue
 
 # This looks like a function call.
@@ -325,8 +320,7 @@
 # It changes iteritems to items as iteritems is not
 # present in Python 3 world.
 elif fn == 'iteritems':
-yield tokenize.TokenInfo(t.type, 'items',
- t.start, t.end, t.line)
+yield t._replace(string='items')
 continue
 
 # Emit unmodified token.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 2 V2] py3: refactor token parsing to handle call args properly

2016-10-13 Thread Martijn Pieters
# HG changeset patch
# User Martijn Pieters 
# Date 1476350485 -3600
#  Thu Oct 13 10:21:25 2016 +0100
# Node ID 36607cf1bbd9fd4d99b607f927bc807fcc48d0ea
# Parent  733fb9f7bc92c694ba6bededaeb93206528c0bcd
py3: refactor token parsing to handle call args properly

The token parsing was getting unwieldy and was too naive about accessing
arguments.

diff --git a/mercurial/__init__.py b/mercurial/__init__.py
--- a/mercurial/__init__.py
+++ b/mercurial/__init__.py
@@ -185,6 +185,61 @@
 OR CACHED FILES WON'T GET INVALIDATED PROPERLY.
 """
 futureimpline = False
+
+# The following utility functions access the tokens list and i index of
+# the for i, t enumerate(tokens) loop below
+def _isop(j, *o):
+"""Assert that tokens[j] is an OP with one of the given values"""
+try:
+return tokens[j].type == token.OP and tokens[j].string in o
+except IndexError:
+return False
+
+def _findargnofcall(n):
+"""Find arg n of a call expression (start at 0)
+
+Returns index of the first token of that argument, or None if
+there is not that many arguments.
+
+Assumes that token[i + 1] is '('.
+
+"""
+j = i + 2
+nested = 0
+try:
+while True:
+if _isop(j, ')', ']', '}'):
+# end of call, tuple, subscription or dict / set
+nested -= 1
+if nested < 0:
+return None
+elif n == 0:
+# this is the starting position of arg
+return j
+elif _isop(j, '(', '[', '{'):
+nested += 1
+elif _isop(j, ',') and nested == 0:
+n -= 1
+j += 1
+except IndexError:
+return None
+
+def _ensureunicode(j):
+"""Make sure the token at j is a unicode string
+
+This rewrites a string token to include the unicode literal prefix
+so the string transformer won't add the byte prefix.
+
+Ignores tokens that are not strings. Assumes bounds checking has
+already been done.
+
+"""
+st = tokens[j]
+if st.type == token.STRING and st.string.startswith(("'", '"')):
+rt = tokenize.TokenInfo(st.type, 'u%s' % st.string,
+st.start, st.end, st.line)
+tokens[j] = rt
+
 for i, t in enumerate(tokens):
 # Convert most string literals to byte literals. String literals
 # in Python 2 are bytes. String literals in Python 3 are unicode.
@@ -241,91 +296,35 @@
  '')
 continue
 
-try:
-nexttoken = tokens[i + 1]
-except IndexError:
-nexttoken = None
-
-try:
-prevtoken = tokens[i - 1]
-except IndexError:
-prevtoken = None
-
 # This looks like a function call.
-if (t.type == token.NAME and nexttoken and
-nexttoken.type == token.OP and nexttoken.string == '('):
+if t.type == token.NAME and _isop(i + 1, '('):
 fn = t.string
 
 # *attr() builtins don't accept byte strings to 2nd argument.
-# Rewrite the token to include the unicode literal prefix so
-# the string transformer above doesn't add the byte prefix.
-if fn in ('getattr', 'setattr', 'hasattr', 'safehasattr'):
-try:
-# (NAME, 'getattr')
-# (OP, '(')
-# (NAME, 'foo')
-# (OP, ',')
-# (NAME|STRING, foo)
-st = tokens[i + 4]
-if (st.type == token.STRING and
-st.string[0] in ("'", '"')):
-rt = tokenize.TokenInfo(st.type, 'u%s' % st.string,
-st.start, st.end, st.line)
-tokens[i + 4] = rt
-except IndexError:
-pass
+if (fn in ('getattr', 'setattr', 'hasattr', 'safehasattr') and
+not _isop(i - 1, '.')):
+arg1idx = _findargnofcall(1)
+if arg1idx is not None:
+_ensureunicode(arg1idx)
 
 # .encode() and .decode() on str/bytes/unicode don't accept
-# byte strings on Python 3. Rewrite the token to include the
-# unicode literal prefix so the string transformer above 
doesn't
-# a

Re: [PATCH] py3: refactor token parsing to handle call args properly

2016-10-13 Thread Martijn Pieters
On 13 Oct 2016, at 10:13, Gregory Szorc  wrote:
> On Thu, Oct 13, 2016 at 11:09 AM, Martijn Pieters  > wrote:
> > Nice refactor. While I haven't looked at the code in detail yet, does 
> > check-code not complain about the use of underscore_function_names?
> 
> Apparently not! I did run the whole test suite, and ran it again just now. 
> Nested function names are locals and exempt from the rule it appears.
> 
> Should I resend with adjusted function names?
> 
> Unless I'm missing something obvious, you should.

Done (bound together with the smaller follow-up patch that I sent as a 2-patch 
series this time).

--
Martijn



signature.asc
Description: Message signed with OpenPGP using GPGMail
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 3 of 3] eol: on update, only re-check files if filtering changed

2016-10-13 Thread Pierre-Yves David



On 10/09/2016 06:19 PM, Mads Kiilerich wrote:

On 10/09/2016 04:45 PM, Pierre-Yves David wrote:



On 10/09/2016 04:19 PM, Mads Kiilerich wrote:

diff --git a/hgext/eol.py b/hgext/eol.py
--- a/hgext/eol.py
+++ b/hgext/eol.py
@@ -312,10 +312,15 @@ def reposetup(ui, repo):
 self._eolmatch = util.never
 return

+oldeol = None
 try:
 cachemtime = os.path.getmtime(self.join("eol.cache"))


This seems like it should live in the "cache/" directory. Any reason
not to ?



I don't know. I guess it predates the cache directory. I would probably
agree it now would be better if it lived there.

This patch is backwards compatible and doesn't change that. Changing the
location would be a separate independent change - and apparently trivial
and backwards compatible.


Ha yep. We should probably move the file in the cache directory in a 
follow up patch.


I've pushed that patch as is. I've seen some scary (pre-existing) wlock 
handling in the neighborhood of this patch, I'll send a follow up for that.


Cheers,

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


[PATCH 1 of 2] eol: do not wait on lack when writing cache

2016-10-13 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1476359131 -7200
#  Thu Oct 13 13:45:31 2016 +0200
# Node ID 88cc944830d0c1895e527d6ca13687f1d5e1c785
# Parent  747e546c561fbf34d07cd30013eaf42b0190bb3b
eol: do not wait on lack when writing cache

The cache writing process is properly catching and handling the case where the
lock is unavailable. However, it fails to specify the lock can failed to be
acquired when requesting it. This is now fixed.

diff --git a/hgext/eol.py b/hgext/eol.py
--- a/hgext/eol.py
+++ b/hgext/eol.py
@@ -335,7 +335,7 @@ def reposetup(ui, repo):
 
 wlock = None
 try:
-wlock = self.wlock()
+wlock = self.wlock(wait=False)
 for f in self.dirstate:
 if self.dirstate[f] != 'n':
 continue
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 2] eol: make sure we always release the wlock when writing cache

2016-10-13 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1476359267 -7200
#  Thu Oct 13 13:47:47 2016 +0200
# Node ID db0b3bc2e7ae19973240275fb9e3f964ecdeb019
# Parent  88cc944830d0c1895e527d6ca13687f1d5e1c785
eol: make sure we always release the wlock when writing cache

If any exception were to happen after we acquired the wlock, we could leave it
unreleased. We move the wlock release in a 'finally:' close as it should be.

diff --git a/hgext/eol.py b/hgext/eol.py
--- a/hgext/eol.py
+++ b/hgext/eol.py
@@ -360,7 +360,6 @@ def reposetup(ui, repo):
 # Write the cache to update mtime and cache .hgeol
 with self.vfs("eol.cache", "w") as f:
 f.write(hgeoldata)
-wlock.release()
 except error.LockUnavailable:
 # If we cannot lock the repository and clear the
 # dirstate, then a commit might not see all files
@@ -368,6 +367,9 @@ def reposetup(ui, repo):
 # repository, then we can also not make a commit,
 # so ignore the error.
 pass
+finally:
+if wlock is not None:
+wlock.release()
 
 def commitctx(self, ctx, haserror=False):
 for f in sorted(ctx.added() + ctx.modified()):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 2] commit: return 1 for interactive commit with no changes (issue5397)

2016-10-13 Thread Philippe Pepiot
# HG changeset patch
# User Philippe Pepiot 
# Date 1476266974 -7200
#  Wed Oct 12 12:09:34 2016 +0200
# Node ID fa75185b8901e58d4b1117985e9f3f20e89c4e01
# Parent  b85fa6bf298be07804a74d8fdec0d19fdbc6d740
# EXP-Topic record-return-code
commit: return 1 for interactive commit with no changes (issue5397)

For consistency with non interactive commit

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1648,9 +1648,9 @@ def commit(ui, repo, *pats, **opts):
 def _docommit(ui, repo, *pats, **opts):
 if opts.get('interactive'):
 opts.pop('interactive')
-cmdutil.dorecord(ui, repo, commit, None, False,
-cmdutil.recordfilter, *pats, **opts)
-return
+ret = cmdutil.dorecord(ui, repo, commit, None, False,
+   cmdutil.recordfilter, *pats, **opts)
+return 1 if ret == 0 else ret
 
 if opts.get('subrepos'):
 if opts.get('amend'):
diff --git a/tests/test-commit-interactive-curses.t 
b/tests/test-commit-interactive-curses.t
--- a/tests/test-commit-interactive-curses.t
+++ b/tests/test-commit-interactive-curses.t
@@ -37,6 +37,7 @@ Committing some changes but stopping on 
   > EOF
   $ hg commit -i  -m "a" -d "0 0"
   no changes to record
+  [1]
   $ hg tip
   changeset:   -1:
   tag: tip
@@ -60,6 +61,7 @@ Committing some changes
 Check that commit -i works with no changes
   $ hg commit -i
   no changes to record
+  [1]
 
 Committing only one file
 
diff --git a/tests/test-commit-interactive.t b/tests/test-commit-interactive.t
--- a/tests/test-commit-interactive.t
+++ b/tests/test-commit-interactive.t
@@ -29,6 +29,7 @@ Select no files
   examine changes to 'empty-rw'? [Ynesfdaq?] n
   
   no changes to record
+  [1]
 
   $ hg tip -p
   changeset:   -1:
@@ -1376,6 +1377,7 @@ Removing changes from patch
   record this change to 'editedfile'? [Ynesfdaq?] e
   
   no changes to record
+  [1]
   $ cat editedfile
   This change will not be committed
   This is the second line
@@ -1487,6 +1489,7 @@ session
   record this change to 'editedfile'? [Ynesfdaq?] n
   
   no changes to record
+  [1]
 
 
 random text in random positions is still an error
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 2] record: return code from underlying commit

2016-10-13 Thread Philippe Pepiot
# HG changeset patch
# User Philippe Pepiot 
# Date 1476267774 -7200
#  Wed Oct 12 12:22:54 2016 +0200
# Node ID c2e91a572e36b7c9fab8832f210d2d06bf695672
# Parent  fa75185b8901e58d4b1117985e9f3f20e89c4e01
# EXP-Topic record-return-code
record: return code from underlying commit

diff --git a/hgext/record.py b/hgext/record.py
--- a/hgext/record.py
+++ b/hgext/record.py
@@ -70,7 +70,7 @@ def record(ui, repo, *pats, **opts):
 backup = ui.backupconfig('experimental', 'crecord')
 try:
 ui.setconfig('experimental', 'crecord', False, 'record')
-commands.commit(ui, repo, *pats, **opts)
+return commands.commit(ui, repo, *pats, **opts)
 finally:
 ui.restoreconfig(backup)
 
diff --git a/tests/test-record.t b/tests/test-record.t
--- a/tests/test-record.t
+++ b/tests/test-record.t
@@ -77,6 +77,7 @@ Select no files
   examine changes to 'empty-rw'? [Ynesfdaq?] n
   
   no changes to record
+  [1]
 
   $ hg tip -p
   changeset:   -1:
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2] eol: do not wait on lack when writing cache

2016-10-13 Thread Mads Kiilerich

On 10/13/2016 01:53 PM, Pierre-Yves David wrote:

# HG changeset patch
# User Pierre-Yves David 
# Date 1476359131 -7200
#  Thu Oct 13 13:45:31 2016 +0200
# Node ID 88cc944830d0c1895e527d6ca13687f1d5e1c785
# Parent  747e546c561fbf34d07cd30013eaf42b0190bb3b
eol: do not wait on lack when writing cache

The cache writing process is properly catching and handling the case where the
lock is unavailable. However, it fails to specify the lock can failed to be
acquired when requesting it. This is now fixed.


Hmm.

*If* the user has write access to the repo and *could* lock the repo, 
then it seems reasonable that it waits for the lock and does the right 
thing. It would be unfortunate to bail out early and happily continue to 
expose the less optimal state that read only users might have to deal with.


I thus don't think this change would make it less reliable ... and I 
don't see it solving a real problem.


(The next change for proper release is however +1.)

/Mads



diff --git a/hgext/eol.py b/hgext/eol.py
--- a/hgext/eol.py
+++ b/hgext/eol.py
@@ -335,7 +335,7 @@ def reposetup(ui, repo):
  
  wlock = None

  try:
-wlock = self.wlock()
+wlock = self.wlock(wait=False)
  for f in self.dirstate:
  if self.dirstate[f] != 'n':
  continue
___
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 2] commit: return 1 for interactive commit with no changes (issue5397)

2016-10-13 Thread Pierre-Yves David



On 10/13/2016 02:32 PM, Philippe Pepiot wrote:

# HG changeset patch
# User Philippe Pepiot 
# Date 1476266974 -7200
#  Wed Oct 12 12:09:34 2016 +0200
# Node ID fa75185b8901e58d4b1117985e9f3f20e89c4e01
# Parent  b85fa6bf298be07804a74d8fdec0d19fdbc6d740
# EXP-Topic record-return-code
commit: return 1 for interactive commit with no changes (issue5397)

For consistency with non interactive commit

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1648,9 +1648,9 @@ def commit(ui, repo, *pats, **opts):
 def _docommit(ui, repo, *pats, **opts):
 if opts.get('interactive'):
 opts.pop('interactive')
-cmdutil.dorecord(ui, repo, commit, None, False,
-cmdutil.recordfilter, *pats, **opts)
-return
+ret = cmdutil.dorecord(ui, repo, commit, None, False,
+   cmdutil.recordfilter, *pats, **opts)
+return 1 if ret == 0 else ret


I'm confused about this return value. "if ret == 0" we return 1; if 
return is not zero, we return the value. Do we never return 0 or am I 
missing something ?


Cheers,

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


Re: [PATCH 1 of 6] largefiles: when setting/clearing x bit on largefiles, don't change other bits

2016-10-13 Thread Yuya Nishihara
On Sat, 08 Oct 2016 01:26:05 +0200, Mads Kiilerich wrote:
> # HG changeset patch
> # User Mads Kiilerich 
> # Date 1475881180 -7200
> #  Sat Oct 08 00:59:40 2016 +0200
> # Node ID 96315a5833ed015acb7bd8f6d7f1e38db6fa9c50
> # Parent  1779dde4c9ef97cb242f8d501655f236f66e5439
> largefiles: when setting/clearing x bit on largefiles, don't change other bits

The series looks good to me. Queued up to the patch 5, thanks.

> It is only the X bit that it matters to copy from the standin to the largefile
> in the working directory. While it generally doesn't do any harm to copy the
> whole mode, it is also "wrong" to copy more than the X bit we care about. It
> can make a difference if someone should try to handle largefiles differently,
> such as marking them read-only.
> 
> Thus, do similar to what utils.setflags does and set the X bit where there are
> R bits and obey umask.
> 
> diff --git a/hgext/largefiles/lfcommands.py b/hgext/largefiles/lfcommands.py
> --- a/hgext/largefiles/lfcommands.py
> +++ b/hgext/largefiles/lfcommands.py
> @@ -515,9 +515,13 @@ def updatelfiles(ui, repo, filelist=None
>  rellfile = lfile
>  relstandin = lfutil.standin(lfile)
>  if wvfs.exists(relstandin):
> -mode = wvfs.stat(relstandin).st_mode
> -if mode != wvfs.stat(rellfile).st_mode:
> -wvfs.chmod(rellfile, mode)
> +standinexec = wvfs.stat(relstandin).st_mode & 0o100
> +st = wvfs.stat(rellfile).st_mode
> +if standinexec != st & 0o100:
> +st &= ~0o111
> +if standinexec:
> +st |= (st >> 2) & 0o111 & ~util.umask

This 2-bit shift seemed a bit obscure. Any comment would help future readers.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2] commit: return 1 for interactive commit with no changes (issue5397)

2016-10-13 Thread Philippe Pepiot



On 10/13/2016 03:22 PM, Pierre-Yves David wrote:



On 10/13/2016 02:32 PM, Philippe Pepiot wrote:

# HG changeset patch
# User Philippe Pepiot 
# Date 1476266974 -7200
#  Wed Oct 12 12:09:34 2016 +0200
# Node ID fa75185b8901e58d4b1117985e9f3f20e89c4e01
# Parent  b85fa6bf298be07804a74d8fdec0d19fdbc6d740
# EXP-Topic record-return-code
commit: return 1 for interactive commit with no changes (issue5397)

For consistency with non interactive commit

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1648,9 +1648,9 @@ def commit(ui, repo, *pats, **opts):
 def _docommit(ui, repo, *pats, **opts):
 if opts.get('interactive'):
 opts.pop('interactive')
-cmdutil.dorecord(ui, repo, commit, None, False,
-cmdutil.recordfilter, *pats, **opts)
-return
+ret = cmdutil.dorecord(ui, repo, commit, None, False,
+   cmdutil.recordfilter, *pats, **opts)
+return 1 if ret == 0 else ret


I'm confused about this return value. "if ret == 0" we return 1; if 
return is not zero, we return the value. Do we never return 0 or am I 
missing something ?


dorecord() return either 0 if there is no changes to record or the 
return of commitfunc passed in arguments. Here commitfunc = commit that 
return 1 or None, here is the trick.


I agree this is confusing (see also how shelve use dorecord), maybe we 
could raise a custom exception instead of returning 0 in dorecord to 
avoid collisions with commitfunc return value, but I'm not sure how this 
could affect 3rd party extensions ?


Cheers,

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


Re: [PATCH] bashcompletion: allow skipping completion for 'hg status'

2016-10-13 Thread Yuya Nishihara
On Wed, 05 Oct 2016 09:01:51 -0500, Mathias De Maré wrote:
> # HG changeset patch
> # User Mathias De Maré 
> # Date 1474879657 -7200
> #  Mon Sep 26 10:47:37 2016 +0200
> # Node ID 1ad8d68d6e495200969a650992f9cf7ff3f934d1
> # Parent  1779dde4c9ef97cb242f8d501655f236f66e5439
> bashcompletion: allow skipping completion for 'hg status'

because 'hg status' might be slow? Can you add more details to the commit
message?

> --- a/contrib/bash_completion
> +++ b/contrib/bash_completion
> @@ -89,9 +89,11 @@
>  
>  _hg_status()
>  {
> -local files="$(_hg_cmd status -n$1 "glob:$cur**")"
> -local IFS=$'\n'
> -COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
> +if [ -z "$HGCOMPLETE_NOSTATUS" ]; then
> +local files="$(_hg_cmd status -n$1 "glob:$cur**")"
> +local IFS=$'\n'
> +COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
> +fi

Using shell variables seems okay. I found several examples in bash-completion
directory.

$ grep COMP * | grep -v COMPREPLY | grep -v 'COMP_.*WORD' | head -10
ciptool:if [[ -n ${COMP_BLUETOOTH_SCAN:-} ]]; then
colormake:if (( COMP_TYPE != 9 )); then
configure:# if $COMP_CONFIGURE_HINTS is not null, then completions of the 
form
configure:if [[ -n $COMP_CONFIGURE_HINTS ]]; then
cvs:# if $COMP_CVS_REMOTE is not null, 'cvs commit' will
cvs:if [[ -n ${COMP_CVS_REMOTE:-} ]]; then
dfutool:if [[ -n ${COMP_BLUETOOTH_SCAN:-} ]]; then
docker:# DOCKER_COMPLETION_SHOW_NETWORK_IDS
docker:# DOCKER_COMPLETION_SHOW_IMAGE_IDS
docker:# DOCKER_COMPLETION_SHOW_TAGS
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 6] largefiles: when setting/clearing x bit on largefiles, don't change other bits

2016-10-13 Thread Mads Kiilerich

On 10/13/2016 03:39 PM, Yuya Nishihara wrote:

On Sat, 08 Oct 2016 01:26:05 +0200, Mads Kiilerich wrote:

# HG changeset patch
# User Mads Kiilerich 
# Date 1475881180 -7200
#  Sat Oct 08 00:59:40 2016 +0200
# Node ID 96315a5833ed015acb7bd8f6d7f1e38db6fa9c50
# Parent  1779dde4c9ef97cb242f8d501655f236f66e5439
largefiles: when setting/clearing x bit on largefiles, don't change other bits

The series looks good to me. Queued up to the patch 5, thanks.


I have also looked into reworking it to increasing the default chunksize 
to 128k everywhere - that seems a bit cleaner in hindsight. I will send 
that version if you un-queue it again ;-)


/Mads

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


Re: [PATCH 1 of 6] largefiles: when setting/clearing x bit on largefiles, don't change other bits

2016-10-13 Thread Yuya Nishihara
On Thu, 13 Oct 2016 15:46:25 +0200, Mads Kiilerich wrote:
> On 10/13/2016 03:39 PM, Yuya Nishihara wrote:
> > On Sat, 08 Oct 2016 01:26:05 +0200, Mads Kiilerich wrote:
> >> # HG changeset patch
> >> # User Mads Kiilerich 
> >> # Date 1475881180 -7200
> >> #  Sat Oct 08 00:59:40 2016 +0200
> >> # Node ID 96315a5833ed015acb7bd8f6d7f1e38db6fa9c50
> >> # Parent  1779dde4c9ef97cb242f8d501655f236f66e5439
> >> largefiles: when setting/clearing x bit on largefiles, don't change other 
> >> bits
> > The series looks good to me. Queued up to the patch 5, thanks.
> 
> I have also looked into reworking it to increasing the default chunksize 
> to 128k everywhere - that seems a bit cleaner in hindsight. I will send 
> that version if you un-queue it again ;-)

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


Re: Topics [was: news from the topic experiment]

2016-10-13 Thread Pierre-Yves David



On 10/13/2016 07:33 AM, Erik van Zijst wrote:

Working on our Bitbucket spike I wondered if topics could perhaps
benefit from a small simplification. Instead of adding the topic name
as an additional field, what if we defined a topic commit by merely
adding a boolean property to the meta dict; e.g. `is_topic: True`?
Named branches would not have the property set.


As a foreword, I agree the frontier between named branch and topics is 
thin. The difference between them are useful but if we can make their 
management really close, that would be useful. If we did not had the 
backward compatibility constrains, I would happily have `hg branch foo` 
create a "topics" and something like `hg branch --long-lived` create 
what currently is a named branched.


So, thanks for exploring possibilities to make this frontier thiner. 
However, I can see some issues with some aspects of this proposal, using 
the same field for either branch or topic make them mostly mutually 
exclusive. Publishing a topic on a named branch would require to alter 
the changesets data (and therefore, hash) This means people could use 
topic only with the default branch (or significant more complexity to 
work around this). As I understand, Bitbucket enforces a single master 
branch so that might actually fit your model. This is probably too 
restricting for the general project (more about that later).




It would seem to me that this could have some benefits:

1. There would be no risk of a name collision between the branch and
topic namespaces.


I'm not certain this actually avoid the risk of name collision. People 
could use the same branch/topic name on different changesets with 
different values for the flag. That would lead to both a topic and a 
named branch to exists with the same name.


In all cases we should have the local UI fight hard to prevent people to 
create collisions between branch and topic. (And some descent way to 
point out name conflict if they appends).



During our little Bitbucket spike and demo during the sprint we made
the assumption that topics and branches should never clash, which
allowed me to put them in the existing, single branches namespace.
This would seem desirable as topics are essentially branches, with the
only real difference being their anticipated longevity. This greatly
simplified the UI as hardly anything needed to be modified.


That is a interesting though.

I think there is some value in having the option to use a (branch, 
topic) pairs (more about this later), However, the same as people are 
not really exposed to named branch until they get out of default, a UI 
could still omit all named branch informations as long as nothing else 
than "default" exists.



2. Interoperability with non-topic clients would mostly just work.

Currently, when cloning a topics repo with an old client, all topics
would appear as an amorphous mess of anonymous heads on default.
Instead, if we dropped the separate topic name field and just used the
branch name as the topic name, an old client would see the same layout
as a topic-enabled client and while an old client would not be able to
create new topic commits, read-only clients should be totally fine.
This could be a big boon for existing ecosystem tools like CI servers
that wouldn't have to be modified.


There is some very interesting ramification to this proposal. Even if we 
do not go with the flag approach. We store the full (branch, topic) pair 
into the branch field. For example we could use ":" as a separator 
branch=BRANCH:TOPIC. Not only this would allow old clients to transport 
the data (we already have that) but this also mean old client can also 
view and preserve that data (and this is new) even if it does not get 
the behavior improvement related to topic. That would be a large 
usability boost for old client.


This is a great lead thank you very much.


The only downside I can think of is that when the topic and original
branch name are separate fields, that a topic sort of remains
associated with the branch it was based on. This would provide
implicit merge and rebase targets and therefore slightly shorter
commands. However, I'm not sure that's worth giving up the above
points.


I think having the (named, topics) pair is really useful, especially we 
can expect great gains from sensible and clear default (merge, rebase, 
behind computation, etc). In addition, as we can keep hiding the named 
branch concept for all users who do not needs it. I think we can have a 
good trade-off regarding extra-feature vs extra-complexity while keeping 
an initial complexity similar to not having named branch at all.
(But as usual, I'm open to be convinced that the right trade-off is 
somewhere else)


We need to explore a bit more the consequence of having the same topic 
on multiple branches, but I'm not too worried we can eventually defines 
some good behavior+constrains pairs that makes this working.



I do realize it's quite possible I'm overloo

[PATCH RFC] perf: add asv benchmarks

2016-10-13 Thread Philippe Pepiot
# HG changeset patch
# User Philippe Pepiot 
# Date 1475136994 -7200
#  Thu Sep 29 10:16:34 2016 +0200
# Node ID f7847ea1b58780e3508d57376c4fdd63d6aedfcd
# Parent  b85fa6bf298be07804a74d8fdec0d19fdbc6d740
# EXP-Topic hgperf
perf: add asv benchmarks

Airspeed velocity (ASV) is a python framework for benchmarking Python packages
over their lifetime. The results are displayed in an interactive web frontend.

Add ASV benchmarks for mercurial that use contrib/perf.py extension that could
be run against multiple reference repositories.

The benchmark suite now includes revsets from contrib/base-revsets.txt with
variants, perftags, perfstatus, perfmanifest and perfheads.

Installation requires ASV (not yet released
https://github.com/spacetelescope/asv master branch), python-hglib and
virtualenv.

This is part of PerformanceTrackingSuitePlan
https://www.mercurial-scm.org/wiki/PerformanceTrackingSuitePlan

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -49,6 +49,7 @@ mercurial.egg-info
 tags
 cscope.*
 .idea/*
+.asv/*
 i18n/hg.pot
 locale/*/LC_MESSAGES/hg.mo
 hgext/__index__.py
diff --git a/contrib/asv.conf.json b/contrib/asv.conf.json
new file mode 100644
--- /dev/null
+++ b/contrib/asv.conf.json
@@ -0,0 +1,127 @@
+{
+// The version of the config file format.  Do not change, unless
+// you know what you are doing.
+"version": 1,
+
+// The name of the project being benchmarked
+"project": "mercurial",
+
+// The project's homepage
+"project_url": "http://mercurial-scm.org/";,
+
+// The URL or local path of the source code repository for the
+// project being benchmarked
+"repo": "..",
+
+// List of branches to benchmark. If not provided, defaults to "master"
+// (for git) or "default" (for mercurial).
+// "branches": ["master"], // for git
+// "branches": ["default"],// for mercurial
+"branches": ["default", "stable"],
+
+// The DVCS being used.  If not set, it will be automatically
+// determined from "repo" by looking at the protocol in the URL
+// (if remote), or by looking for special directories, such as
+// ".git" (if local).
+// "dvcs": "git",
+
+// The tool to use to create environments.  May be "conda",
+// "virtualenv" or other value depending on the plugins in use.
+// If missing or the empty string, the tool will be automatically
+// determined by looking for tools on the PATH environment
+// variable.
+"environment_type": "virtualenv",
+
+// the base URL to show a commit for the project.
+"show_commit_url": "https://www.selenic.com/hg/rev/";,
+
+// The Pythons you'd like to test against.  If not provided, defaults
+// to the current version of Python used to run `asv`.
+// "pythons": ["2.7", "3.3"],
+
+// The matrix of dependencies to test.  Each key is the name of a
+// package (in PyPI) and the values are version numbers.  An empty
+// list or empty string indicates to just test against the default
+// (latest) version. null indicates that the package is to not be
+// installed. If the package to be tested is only available from
+// PyPi, and the 'environment_type' is conda, then you can preface
+// the package name by 'pip+', and the package will be installed via
+// pip (with all the conda available packages installed first,
+// followed by the pip installed packages).
+//
+// "matrix": {
+// "numpy": ["1.6", "1.7"],
+// "six": ["", null],// test with and without six installed
+// "pip+emcee": [""],   // emcee is only available for install with 
pip.
+// },
+
+// Combinations of libraries/python versions can be excluded/included
+// from the set to test. Each entry is a dictionary containing additional
+// key-value pairs to include/exclude.
+//
+// An exclude entry excludes entries where all values match. The
+// values are regexps that should match the whole string.
+//
+// An include entry adds an environment. Only the packages listed
+// are installed. The 'python' key is required. The exclude rules
+// do not apply to includes.
+//
+// In addition to package names, the following keys are available:
+//
+// - python
+// Python version, as in the *pythons* variable above.
+// - environment_type
+// Environment type, as above.
+// - sys_platform
+// Platform, as in sys.platform. Possible values for the common
+// cases: 'linux2', 'win32', 'cygwin', 'darwin'.
+//
+// "exclude": [
+// {"python": "3.2", "sys_platform": "win32"}, // skip py3.2 on windows
+// {"environment_type": "conda", "six": null}, // don't run without 
six on conda
+// ],
+//
+// "include": [
+// // additional env for python2.7
+// {"python": "2.7", "numpy": "1.8"},
+// // additional env if run on windows+conda
+// {"platform": "win32", "

Re: [PATCH 1 of 6] largefiles: when setting/clearing x bit on largefiles, don't change other bits

2016-10-13 Thread Mads Kiilerich

On 10/13/2016 03:58 PM, Yuya Nishihara wrote:

On Thu, 13 Oct 2016 15:46:25 +0200, Mads Kiilerich wrote:

On 10/13/2016 03:39 PM, Yuya Nishihara wrote:
The series looks good to me. Queued up to the patch 5, thanks. 

I have also looked into reworking it to increasing the default chunksize
to 128k everywhere - that seems a bit cleaner in hindsight. I will send
that version if you un-queue it again ;-)

Unqueue everything?



I have no changes to the first two so it would be great to keep them ... 
but I could also easily resend them - whatever is least trouble ;-)


/Mads

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


mercurial@30138: 19 new changesets

2016-10-13 Thread Mercurial Commits
19 new changesets in mercurial:

http://selenic.com/repo/hg//rev/932faa29b4c1
changeset:   30120:932faa29b4c1
user:Augie Fackler 
date:Sun Oct 09 04:25:22 2016 -0400
summary: test-clone: fix some instability in pooled clone race condition 
test

http://selenic.com/repo/hg//rev/bbbf6bbbd05f
changeset:   30121:bbbf6bbbd05f
user:Augie Fackler 
date:Sun Oct 09 04:37:02 2016 -0400
summary: test-clone: discard lock-related messages

http://selenic.com/repo/hg//rev/b710dca9937a
changeset:   30122:b710dca9937a
user:Pierre-Yves David 
date:Wed Aug 24 04:48:17 2016 +0200
summary: bisect: minor movement of code handle flag updating state

http://selenic.com/repo/hg//rev/2e360578688d
changeset:   30123:2e360578688d
user:Pierre-Yves David 
date:Sun Oct 09 03:50:55 2016 +0200
summary: bisect: rename 'check_code' to match our naming scheme

http://selenic.com/repo/hg//rev/0aea706060cc
changeset:   30124:0aea706060cc
user:Pierre-Yves David 
date:Wed Aug 24 04:22:40 2016 +0200
summary: bisect: remove code about "update-flag" in check_state

http://selenic.com/repo/hg//rev/3528117c7b4e
changeset:   30125:3528117c7b4e
user:Pierre-Yves David 
date:Wed Aug 24 04:23:13 2016 +0200
summary: bisect: simplify conditional in 'check_state'

http://selenic.com/repo/hg//rev/755730fc1e48
changeset:   30126:755730fc1e48
user:Pierre-Yves David 
date:Wed Aug 24 04:25:20 2016 +0200
summary: bisect: move check_state into the bisect module

http://selenic.com/repo/hg//rev/1ee65f1a11a5
changeset:   30127:1ee65f1a11a5
user:Pierre-Yves David 
date:Wed Aug 24 05:04:46 2016 +0200
summary: bisect: factor commonly update sequence

http://selenic.com/repo/hg//rev/e37ee8367ab4
changeset:   30128:e37ee8367ab4
user:Pierre-Yves David 
date:Wed Aug 24 05:06:21 2016 +0200
summary: bisect: build a displayer only once

http://selenic.com/repo/hg//rev/d69d86e7d6c8
changeset:   30129:d69d86e7d6c8
user:Pulkit Goyal <7895pul...@gmail.com>
date:Sun Oct 09 13:59:20 2016 +0200
summary: py3: test to check which commands run

http://selenic.com/repo/hg//rev/7be610198360
changeset:   30130:7be610198360
user:Augie Fackler 
date:Sun Oct 09 09:42:46 2016 -0400
summary: debuginstall: use %d instead of %s for formatting an int

http://selenic.com/repo/hg//rev/85d5708eae4e
changeset:   30131:85d5708eae4e
user:Mateusz Kwapich 
date:Mon Oct 10 05:30:14 2016 -0700
summary: py3: namedtuple takes unicode (journal ext)

http://selenic.com/repo/hg//rev/72f75eda02ba
changeset:   30132:72f75eda02ba
user:Mateusz Kwapich 
date:Mon Oct 10 05:31:31 2016 -0700
summary: py3: use raw strings in line continuation (convert ext)

http://selenic.com/repo/hg//rev/f6dcda7505f9
changeset:   30133:f6dcda7505f9
user:Martijn Pieters 
date:Mon Oct 10 23:11:15 2016 +0100
summary: pycompat: only accept a bytestring filepath in Python 2

http://selenic.com/repo/hg//rev/165c9526e594
changeset:   30134:165c9526e594
user:Pierre-Yves David 
date:Wed Aug 24 05:09:46 2016 +0200
summary: bisect: extra a small initialisation outside of a loop

http://selenic.com/repo/hg//rev/3eae81c0a09d
changeset:   30135:3eae81c0a09d
user:Pierre-Yves David 
date:Sat Oct 08 18:38:42 2016 +0200
summary: checkcopies: rename 'ca' to 'base'

http://selenic.com/repo/hg//rev/8797eadb5d90
changeset:   30136:8797eadb5d90
user:Pierre-Yves David 
date:Sat Oct 08 19:03:16 2016 +0200
summary: checkcopies: minor change to comment

http://selenic.com/repo/hg//rev/f85f9e069e09
changeset:   30137:f85f9e069e09
user:Pierre-Yves David 
date:Sat Oct 08 23:00:55 2016 +0200
summary: checkcopies: add an inline comment about the '_related' call

http://selenic.com/repo/hg//rev/733fb9f7bc92
changeset:   30138:733fb9f7bc92
bookmark:@
tag: tip
user:Pierre-Yves David 
date:Tue Oct 11 01:29:08 2016 +0200
summary: checkcopies: extract the '_related' closure

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


Re: [PATCH 1 of 2] commit: return 1 for interactive commit with no changes (issue5397)

2016-10-13 Thread Pierre-Yves David



On 10/13/2016 03:43 PM, Philippe Pepiot wrote:



On 10/13/2016 03:22 PM, Pierre-Yves David wrote:



On 10/13/2016 02:32 PM, Philippe Pepiot wrote:

# HG changeset patch
# User Philippe Pepiot 
# Date 1476266974 -7200
#  Wed Oct 12 12:09:34 2016 +0200
# Node ID fa75185b8901e58d4b1117985e9f3f20e89c4e01
# Parent  b85fa6bf298be07804a74d8fdec0d19fdbc6d740
# EXP-Topic record-return-code
commit: return 1 for interactive commit with no changes (issue5397)

For consistency with non interactive commit

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1648,9 +1648,9 @@ def commit(ui, repo, *pats, **opts):
 def _docommit(ui, repo, *pats, **opts):
 if opts.get('interactive'):
 opts.pop('interactive')
-cmdutil.dorecord(ui, repo, commit, None, False,
-cmdutil.recordfilter, *pats, **opts)
-return
+ret = cmdutil.dorecord(ui, repo, commit, None, False,
+   cmdutil.recordfilter, *pats, **opts)
+return 1 if ret == 0 else ret


I'm confused about this return value. "if ret == 0" we return 1; if
return is not zero, we return the value. Do we never return 0 or am I
missing something ?


dorecord() return either 0 if there is no changes to record or the
return of commitfunc passed in arguments. Here commitfunc = commit that
return 1 or None, here is the trick.

I agree this is confusing (see also how shelve use dorecord), maybe we
could raise a custom exception instead of returning 0 in dorecord to
avoid collisions with commitfunc return value, but I'm not sure how this
could affect 3rd party extensions ?


Hum, the smaller improvement I can see is to add this explanation as an 
inline comment. I think we should also clean up the dorecord return to 
something better, but we are probably too late in the cycle for that.


Cheers,

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


Re: [PATCH 1 of 6] largefiles: when setting/clearing x bit on largefiles, don't change other bits

2016-10-13 Thread Yuya Nishihara
On Thu, 13 Oct 2016 16:03:03 +0200, Mads Kiilerich wrote:
> On 10/13/2016 03:58 PM, Yuya Nishihara wrote:
> > On Thu, 13 Oct 2016 15:46:25 +0200, Mads Kiilerich wrote:
> >> On 10/13/2016 03:39 PM, Yuya Nishihara wrote:
> >>> The series looks good to me. Queued up to the patch 5, thanks. 
> >> I have also looked into reworking it to increasing the default chunksize
> >> to 128k everywhere - that seems a bit cleaner in hindsight. I will send
> >> that version if you un-queue it again ;-)
> > Unqueue everything?
> 
> I have no changes to the first two so it would be great to keep them ... 
> but I could also easily resend them - whatever is least trouble ;-)

Okay, pruned the following changes from hg-committed:

6661746fd769 largefiles: use constant file chunk size instead of repeating 128 
* 1024
5fc05f266ab0 largefiles: always use filechunkitersize when using filechunkiter
5f07c5a5c49a largefiles: always use filechunkiter when iterating files
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 3] checkcopies: rename 'ca' to 'base'

2016-10-13 Thread Kevin Bullock
> On Oct 9, 2016, at 09:18, Pierre-Yves David  
> wrote:
> 
> # HG changeset patch
> # User Pierre-Yves David 
> # Date 1475944722 -7200
> #  Sat Oct 08 18:38:42 2016 +0200
> # Node ID c06cb63082bf571fb6fc24bac2e23feefe00
> # Parent  2c8ec8c2ddfeb2d229b81eb5b11e3639fb34b0a0
> # EXP-Topic checkcopies
> checkcopies: rename 'ca' to 'base'
> 
> This variable was name after the common ancestor. It is actually the merge
> base that might differ from the common ancestor in the graft case. We rename 
> the
> variable before a larger refactoring to clarify the situation.

One nit with this one: you also renamed `ma` to `mb` and didn't mention it in 
the description. Accepting anyway.

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

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


Re: [PATCH 1 of 3] checkcopies: rename 'ca' to 'base'

2016-10-13 Thread Pierre-Yves David



On 10/13/2016 04:40 PM, Kevin Bullock wrote:

On Oct 9, 2016, at 09:18, Pierre-Yves David  
wrote:

# HG changeset patch
# User Pierre-Yves David 
# Date 1475944722 -7200
#  Sat Oct 08 18:38:42 2016 +0200
# Node ID c06cb63082bf571fb6fc24bac2e23feefe00
# Parent  2c8ec8c2ddfeb2d229b81eb5b11e3639fb34b0a0
# EXP-Topic checkcopies
checkcopies: rename 'ca' to 'base'

This variable was name after the common ancestor. It is actually the merge
base that might differ from the common ancestor in the graft case. We rename the
variable before a larger refactoring to clarify the situation.


One nit with this one: you also renamed `ma` to `mb` and didn't mention it in 
the description. Accepting anyway.


Ha yes, probably worth mentioning. The rename is motivated by the fact 
"ma" was the accronyms for "manifest ancestor" and the name change 
motivate a rename to "manifest base" → mb.


Cheers,

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


Re: [PATCH 1 of 8 V2] perf: introduce safeattrsetter to replace direct attribute assignment

2016-10-13 Thread Yuya Nishihara
On Sun, 09 Oct 2016 01:18:21 +0900, FUJIWARA Katsunori wrote:
> # HG changeset patch
> # User FUJIWARA Katsunori 
> # Date 1475942596 -32400
> #  Sun Oct 09 01:03:16 2016 +0900
> # Node ID a03b967913dd881f750a5848f567d1e0a1d0e7ea
> # Parent  87b8e40eb8125d5ddc848d972b117989346057dd
> perf: introduce safeattrsetter to replace direct attribute assignment

These all look good to me. Queued, many thanks.

> +def safeattrsetter(obj, name, ignoremissing=False):
> +"""Ensure that 'obj' has 'name' attribute before subsequent setattr
> +
> +This function is aborted, if 'obj' doesn't have 'name' attribute
> +at runtime. This avoids overlooking removal of an attribute, which
> +breaks assumption of performance measurement, in the future.
> +
> +This function returns the object to (1) assign a new value, and
> +(2) restore an original value to the attribute.
> +
> +If 'ignoremissing' is true, missing 'name' attribute doesn't cause
> +abortion, and this function returns None. This is useful to
> +examine an attribute, which isn't ensured in all Mercurial
> +versions.
> +"""
> +if not util.safehasattr(obj, name):
> +if ignoremissing:
> +return None
> +raise error.Abort(("missing attribute %s of %s might break 
> assumption"
> +   " of performance measurement") % (name, obj))
> +
> +origvalue = getattr(obj, name)
> +class attrutil(object):
> +def set(self, newvalue):
> +setattr(obj, name, newvalue)
> +def restore(self):
> +setattr(obj, name, origvalue)
> +
> +return attrutil()

This could be a class sefeattrsetter, but we would need to handle ignoremissing
out of its __init__.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 3] checkcopies: rename 'ca' to 'base'

2016-10-13 Thread Kevin Bullock
> On Oct 13, 2016, at 09:47, Pierre-Yves David  
> wrote:
> 
> On 10/13/2016 04:40 PM, Kevin Bullock wrote:
>>> On Oct 9, 2016, at 09:18, Pierre-Yves David 
>>>  wrote:
>>> 
>>> # HG changeset patch
>>> # User Pierre-Yves David 
>>> # Date 1475944722 -7200
>>> #  Sat Oct 08 18:38:42 2016 +0200
>>> # Node ID c06cb63082bf571fb6fc24bac2e23feefe00
>>> # Parent  2c8ec8c2ddfeb2d229b81eb5b11e3639fb34b0a0
>>> # EXP-Topic checkcopies
>>> checkcopies: rename 'ca' to 'base'
>>> 
>>> This variable was name after the common ancestor. It is actually the merge
>>> base that might differ from the common ancestor in the graft case. We 
>>> rename the
>>> variable before a larger refactoring to clarify the situation.
>> 
>> One nit with this one: you also renamed `ma` to `mb` and didn't mention it 
>> in the description. Accepting anyway.
> 
> Ha yes, probably worth mentioning. The rename is motivated by the fact "ma" 
> was the accronyms for "manifest ancestor" and the name change motivate a 
> rename to "manifest base" → mb.

Yeah, that was pretty straightforward from reading the commit, so I didn't 
bother updating the description.

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

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


Re: [PATCH 1 of 2] commit: return 1 for interactive commit with no changes (issue5397)

2016-10-13 Thread Augie Fackler
On Thu, Oct 13, 2016 at 04:13:43PM +0200, Pierre-Yves David wrote:
>
>
> On 10/13/2016 03:43 PM, Philippe Pepiot wrote:
> >
> >
> >On 10/13/2016 03:22 PM, Pierre-Yves David wrote:
> >>
> >>
> >>On 10/13/2016 02:32 PM, Philippe Pepiot wrote:
> >>># HG changeset patch
> >>># User Philippe Pepiot 
> >>># Date 1476266974 -7200
> >>>#  Wed Oct 12 12:09:34 2016 +0200
> >>># Node ID fa75185b8901e58d4b1117985e9f3f20e89c4e01
> >>># Parent  b85fa6bf298be07804a74d8fdec0d19fdbc6d740
> >>># EXP-Topic record-return-code
> >>>commit: return 1 for interactive commit with no changes (issue5397)
> >>>
> >>>For consistency with non interactive commit
> >>>
> >>>diff --git a/mercurial/commands.py b/mercurial/commands.py
> >>>--- a/mercurial/commands.py
> >>>+++ b/mercurial/commands.py
> >>>@@ -1648,9 +1648,9 @@ def commit(ui, repo, *pats, **opts):
> >>> def _docommit(ui, repo, *pats, **opts):
> >>> if opts.get('interactive'):
> >>> opts.pop('interactive')
> >>>-cmdutil.dorecord(ui, repo, commit, None, False,
> >>>-cmdutil.recordfilter, *pats, **opts)
> >>>-return
> >>>+ret = cmdutil.dorecord(ui, repo, commit, None, False,
> >>>+   cmdutil.recordfilter, *pats, **opts)
> >>>+return 1 if ret == 0 else ret
> >>
> >>I'm confused about this return value. "if ret == 0" we return 1; if
> >>return is not zero, we return the value. Do we never return 0 or am I
> >>missing something ?
> >
> >dorecord() return either 0 if there is no changes to record or the
> >return of commitfunc passed in arguments. Here commitfunc = commit that
> >return 1 or None, here is the trick.
> >
> >I agree this is confusing (see also how shelve use dorecord), maybe we
> >could raise a custom exception instead of returning 0 in dorecord to
> >avoid collisions with commitfunc return value, but I'm not sure how this
> >could affect 3rd party extensions ?
>
> Hum, the smaller improvement I can see is to add this explanation as an
> inline comment. I think we should also clean up the dorecord return to
> something better, but we are probably too late in the cycle for that.

FWIW, I'm fine with this patch as-is, and a comment added as a
followup since it's a little wonky.

It's definitely too late in the cycle to go monkeying with dorecord's interface.

>
> Cheers,
>
> --
> Pierre-Yves David
> ___
> 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 2] eol: do not wait on lack when writing cache

2016-10-13 Thread Pierre-Yves David



On 10/13/2016 03:21 PM, Mads Kiilerich wrote:

On 10/13/2016 01:53 PM, Pierre-Yves David wrote:

# HG changeset patch
# User Pierre-Yves David 
# Date 1476359131 -7200
#  Thu Oct 13 13:45:31 2016 +0200
# Node ID 88cc944830d0c1895e527d6ca13687f1d5e1c785
# Parent  747e546c561fbf34d07cd30013eaf42b0190bb3b
eol: do not wait on lack when writing cache

The cache writing process is properly catching and handling the case
where the
lock is unavailable. However, it fails to specify the lock can failed
to be
acquired when requesting it. This is now fixed.


Hmm.

*If* the user has write access to the repo and *could* lock the repo,
then it seems reasonable that it waits for the lock and does the right
thing. It would be unfortunate to bail out early and happily continue to
expose the less optimal state that read only users might have to deal with.


The change introduced by this changeset make the cache in line with how 
most of other cache works in Mercurial. The lock don't really have time 
out so simple read only command could hold themself forever if make this 
call blocking. Given than eol is probably not going to be user on pulling



I thus don't think this change would make it less reliable ... and I
don't see it solving a real problem.


The idea is to align it with what other cache do (reducing the chance of 
simple command working).



(The next change for proper release is however +1.)


yep, next one is a must go ☺

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


4.0 freeze soon - please limit big new features

2016-10-13 Thread Augie Fackler
Hey folks,

We're a little behind on reviews because of the sprint and a couple of
other factors, and the freeze is coming up on the 18th. As such, we'd
appreciate it it you could hold any (new) large series for after 4.0
is done, so we can get caught up and have bandwidth for the bug fixes
that are needed between now and November 1.

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


mercurial@30150: 12 new changesets

2016-10-13 Thread Mercurial Commits
12 new changesets in mercurial:

http://selenic.com/repo/hg//rev/27e00e6352ce
changeset:   30139:27e00e6352ce
user:Gregory Szorc 
date:Thu Oct 13 10:59:29 2016 +0200
summary: dirs: add comment about _PyBytes_Resize

http://selenic.com/repo/hg//rev/747e546c561f
changeset:   30140:747e546c561f
user:Mads Kiilerich 
date:Sun Oct 09 15:54:49 2016 +0200
summary: eol: on update, only re-check files if filtering changed

http://selenic.com/repo/hg//rev/c01acee367ec
changeset:   30141:c01acee367ec
user:Mads Kiilerich 
date:Sat Oct 08 00:59:40 2016 +0200
summary: largefiles: when setting/clearing x bit on largefiles, don't 
change other bits

http://selenic.com/repo/hg//rev/3dcaf1c4e90d
changeset:   30142:3dcaf1c4e90d
user:Mads Kiilerich 
date:Sat Oct 08 00:59:41 2016 +0200
summary: largefiles: use context for file closing

http://selenic.com/repo/hg//rev/2d858c771760
changeset:   30143:2d858c771760
user:FUJIWARA Katsunori 
date:Sun Oct 09 01:03:16 2016 +0900
summary: perf: introduce safeattrsetter to replace direct attribute 
assignment

http://selenic.com/repo/hg//rev/14031d183048
changeset:   30144:14031d183048
user:FUJIWARA Katsunori 
date:Sun Oct 09 01:03:17 2016 +0900
summary: perf: get subsettable from appropriate module for Mercurial 
earlier than 2.9

http://selenic.com/repo/hg//rev/113aa6145020
changeset:   30145:113aa6145020
user:FUJIWARA Katsunori 
date:Sun Oct 09 01:03:17 2016 +0900
summary: perf: avoid actual writing branch cache out correctly

http://selenic.com/repo/hg//rev/148ccd1d9f2f
changeset:   30146:148ccd1d9f2f
user:FUJIWARA Katsunori 
date:Sun Oct 09 01:03:18 2016 +0900
summary: perf: add functions to get vfs-like object for Mercurial earlier 
than 2.3

http://selenic.com/repo/hg//rev/423bf74d2e5b
changeset:   30147:423bf74d2e5b
user:FUJIWARA Katsunori 
date:Sun Oct 09 01:03:18 2016 +0900
summary: perf: define formatter locally for Mercurial earlier than 2.2

http://selenic.com/repo/hg//rev/04f2b980df3c
changeset:   30148:04f2b980df3c
user:FUJIWARA Katsunori 
date:Sun Oct 09 01:03:19 2016 +0900
summary: perf: omit copying from ui.ferr to ui.fout for Mercurial earlier 
than 1.9

http://selenic.com/repo/hg//rev/d8a2c536dd96
changeset:   30149:d8a2c536dd96
user:FUJIWARA Katsunori 
date:Sun Oct 09 01:03:19 2016 +0900
summary: perf: replace ui.configint() by getint() for Mercurial earlier 
than 1.9

http://selenic.com/repo/hg//rev/c0410814002f
changeset:   30150:c0410814002f
bookmark:@
tag: tip
user:FUJIWARA Katsunori 
date:Sun Oct 09 01:03:20 2016 +0900
summary: perf: make perftags clear tags cache correctly

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


Re: [PATCH 1 of 2] eol: do not wait on lack when writing cache

2016-10-13 Thread Mads Kiilerich

On 10/13/2016 05:07 PM, Pierre-Yves David wrote:



On 10/13/2016 03:21 PM, Mads Kiilerich wrote:

On 10/13/2016 01:53 PM, Pierre-Yves David wrote:

# HG changeset patch
# User Pierre-Yves David 
# Date 1476359131 -7200
#  Thu Oct 13 13:45:31 2016 +0200
# Node ID 88cc944830d0c1895e527d6ca13687f1d5e1c785
# Parent  747e546c561fbf34d07cd30013eaf42b0190bb3b
eol: do not wait on lack when writing cache

The cache writing process is properly catching and handling the case
where the
lock is unavailable. However, it fails to specify the lock can failed
to be
acquired when requesting it. This is now fixed.


Hmm.

*If* the user has write access to the repo and *could* lock the repo,
then it seems reasonable that it waits for the lock and does the right
thing. It would be unfortunate to bail out early and happily continue to
expose the less optimal state that read only users might have to deal 
with.


The change introduced by this changeset make the cache in line with 
how most of other cache works in Mercurial. 


A part of the problem here might be that it is unclear to me what 
happens with wait=False. I don't remember the details: will it continue 
without locking or will it raise? It would be nice to get that clarified 
in the localrepo docstrings.


Also, this "cache" is not so much a "store values so we don't have to 
compute them again" cache. It is more about recording how .hgeol looked 
like when file content from the repo was "cached" in the working 
directory. Without this, we have to invalidate the dirstate more often.


The lock don't really have time out so simple read only command could 
hold themself forever if make this call blocking. 


Why not "really"? There is the 10 minutes timeout?


Given than eol is probably not going to be user on pulling


Sorry, I don't understand that sentence.

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


Re: [PATCH 1 of 2] eol: do not wait on lack when writing cache

2016-10-13 Thread Yuya Nishihara
On Thu, 13 Oct 2016 17:28:02 +0200, Mads Kiilerich wrote:
> On 10/13/2016 05:07 PM, Pierre-Yves David wrote:
> > On 10/13/2016 03:21 PM, Mads Kiilerich wrote:
> >> On 10/13/2016 01:53 PM, Pierre-Yves David wrote:
> >>> # HG changeset patch
> >>> # User Pierre-Yves David 
> >>> # Date 1476359131 -7200
> >>> #  Thu Oct 13 13:45:31 2016 +0200
> >>> # Node ID 88cc944830d0c1895e527d6ca13687f1d5e1c785
> >>> # Parent  747e546c561fbf34d07cd30013eaf42b0190bb3b
> >>> eol: do not wait on lack when writing cache
> >>>
> >>> The cache writing process is properly catching and handling the case
> >>> where the
> >>> lock is unavailable. However, it fails to specify the lock can failed
> >>> to be
> >>> acquired when requesting it. This is now fixed.
> >>
> >> Hmm.
> >>
> >> *If* the user has write access to the repo and *could* lock the repo,
> >> then it seems reasonable that it waits for the lock and does the right
> >> thing. It would be unfortunate to bail out early and happily continue to
> >> expose the less optimal state that read only users might have to deal 
> >> with.
> >
> > The change introduced by this changeset make the cache in line with 
> > how most of other cache works in Mercurial. 
> 
> A part of the problem here might be that it is unclear to me what
> happens with wait=False. I don't remember the details: will it continue 
> without locking or will it raise? It would be nice to get that clarified 
> in the localrepo docstrings.

LockHeld would be raised. So we'll need to catch LockError if wait=False.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2] eol: do not wait on lack when writing cache

2016-10-13 Thread Pierre-Yves David



On 10/13/2016 05:34 PM, Yuya Nishihara wrote:

On Thu, 13 Oct 2016 17:28:02 +0200, Mads Kiilerich wrote:

On 10/13/2016 05:07 PM, Pierre-Yves David wrote:

On 10/13/2016 03:21 PM, Mads Kiilerich wrote:

On 10/13/2016 01:53 PM, Pierre-Yves David wrote:

# HG changeset patch
# User Pierre-Yves David 
# Date 1476359131 -7200
#  Thu Oct 13 13:45:31 2016 +0200
# Node ID 88cc944830d0c1895e527d6ca13687f1d5e1c785
# Parent  747e546c561fbf34d07cd30013eaf42b0190bb3b
eol: do not wait on lack when writing cache

The cache writing process is properly catching and handling the case
where the
lock is unavailable. However, it fails to specify the lock can failed
to be
acquired when requesting it. This is now fixed.


Hmm.

*If* the user has write access to the repo and *could* lock the repo,
then it seems reasonable that it waits for the lock and does the right
thing. It would be unfortunate to bail out early and happily continue to
expose the less optimal state that read only users might have to deal
with.


The change introduced by this changeset make the cache in line with
how most of other cache works in Mercurial.


A part of the problem here might be that it is unclear to me what
happens with wait=False. I don't remember the details: will it continue
without locking or will it raise? It would be nice to get that clarified
in the localrepo docstrings.


LockHeld would be raised. So we'll need to catch LockError if wait=False.


And we actually only catch LockUnavailable, lets drop patch 1 for now 
(patch 2 is still valid)


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


Re: [PATCH 1 of 9 V6] exchange: add `_getbookmarks()` function

2016-10-13 Thread Pierre-Yves David



On 10/11/2016 06:25 PM, Stanislau Hlebik wrote:

# HG changeset patch
# User Stanislau Hlebik 
# Date 1476195835 25200
#  Tue Oct 11 07:23:55 2016 -0700
# Node ID 55e997127023d7208488c593adb933a1bfb23312
# Parent  b85fa6bf298be07804a74d8fdec0d19fdbc6d740
exchange: add `_getbookmarks()` function

This function will be used to generate bookmarks bundle2 part.
It is a separate function in order to make it easy to overwrite it
in extensions. Passing `kwargs` to the function makes it easy to
add new parameters in extensions.

diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -1672,6 +1672,17 @@
 if chunks:
 bundler.newpart('hgtagsfnodes', data=''.join(chunks))

+def _getbookmarks(repo, **kwargs):
+"""Returns list of bookmarks.
+
+This function is primarily used to generate `bookmarks` bundle2 part.
+It is a separate function in order to make it easy to wrap it
+in extensions. Passing `kwargs` to the function makes it easy to
+add new parameters in extensions.
+"""
+
+return repo.listkeys(namespace='bookmarks')


I find it quite suspicious that we need to get through listkeys to get 
the list of bookmarks. Instead I would expect us to have a function 
ready to use in the bookmark module itself. Can you look into this ?


Cheers,

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


Re: [PATCH 1 of 6] largefiles: when setting/clearing x bit on largefiles, don't change other bits

2016-10-13 Thread Pierre-Yves David



On 10/13/2016 04:13 PM, Yuya Nishihara wrote:

On Thu, 13 Oct 2016 16:03:03 +0200, Mads Kiilerich wrote:

On 10/13/2016 03:58 PM, Yuya Nishihara wrote:

On Thu, 13 Oct 2016 15:46:25 +0200, Mads Kiilerich wrote:

On 10/13/2016 03:39 PM, Yuya Nishihara wrote:

The series looks good to me. Queued up to the patch 5, thanks.

I have also looked into reworking it to increasing the default chunksize
to 128k everywhere - that seems a bit cleaner in hindsight. I will send
that version if you un-queue it again ;-)

Unqueue everything?


I have no changes to the first two so it would be great to keep them ...
but I could also easily resend them - whatever is least trouble ;-)


Okay, pruned the following changes from hg-committed:


Urg, direct pruning on hg-commmitted is problematic as it makes 
changesets disappear on the contributor see (see the related thread on 
the reviewers mailing list a while back and the drophack¹ extension (for 
reviewers only)).


Cheers,

--
Pierre-Yves David

[1] https://www.mercurial-scm.org/repo/evolve/file/tip/hgext/drophack.py
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 6] largefiles: when setting/clearing x bit on largefiles, don't change other bits

2016-10-13 Thread Mads Kiilerich

On 10/13/2016 05:57 PM, Pierre-Yves David wrote:


On 10/13/2016 04:13 PM, Yuya Nishihara wrote:

Okay, pruned the following changes from hg-committed:


Urg, direct pruning on hg-commmitted is problematic as it makes 
changesets disappear on the contributor see (see the related thread on 
the reviewers mailing list a while back and the drophack¹ extension 
(for reviewers only)).


Don't worry; I don't use evolve - this is one of the reasons ;-)

/Mads

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


Re: [PATCH 2 of 9 V6] bookmarks: introduce BookmarksEncodeError

2016-10-13 Thread Pierre-Yves David



On 10/11/2016 06:25 PM, Stanislau Hlebik wrote:

# HG changeset patch
# User Stanislau Hlebik 
# Date 1476195835 25200
#  Tue Oct 11 07:23:55 2016 -0700
# Node ID 91ae660eb2faf74cb96ee7ee5bdcc1f2507f9cf7
# Parent  55e997127023d7208488c593adb933a1bfb23312
bookmarks: introduce BookmarksEncodeError

Binary encoding for bookmarks will be added in next diffs.
This error will be thrown if there are problems with bookmarks encoding.


Other code I can find about encoding/decoding use ValueError in case of 
trouble. We can probably stick to that for now.


We don't usually introduce very specialized exception unless they have a 
very specialized purpose. From looking at the rest of the series I do 
not see anything special about there usage (but I might have missed 
something).


Cheers

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


Re: [PATCH 3 of 9 V6] bookmarks: introduce BookmarksDecodeError

2016-10-13 Thread Pierre-Yves David



On 10/11/2016 06:25 PM, Stanislau Hlebik wrote:

# HG changeset patch
# User Stanislau Hlebik 
# Date 1476195835 25200
#  Tue Oct 11 07:23:55 2016 -0700
# Node ID 6f5a3300a5457c92eb09170a30c98328ebe3bcce
# Parent  91ae660eb2faf74cb96ee7ee5bdcc1f2507f9cf7
bookmarks: introduce BookmarksDecodeError

Binary encoding for bookmarks will be added in next diffs.
This error will be thrown if there are problems with bookmarks decoding.


Same feedback as for BookmarksEncodeError, it seems lik we could just go 
with ValueError unless I'm missing something.


Cheers,

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


Re: [PATCH] color: replace "purple_background" by "magenta_background"

2016-10-13 Thread Pierre-Yves David



On 10/11/2016 11:39 AM, Denis Laxalde wrote:

# HG changeset patch
# User Denis Laxalde 
# Date 1476176128 -7200
#  Tue Oct 11 10:55:28 2016 +0200
# Node ID 1cf20c1c54cb8172816604de5e1d98d3cd62d711
# Parent  b85fa6bf298be07804a74d8fdec0d19fdbc6d740
# EXP-Topic color-purple-crash
color: replace "purple_background" by "magenta_background"


We probably want to keep both value around for backward compatibility 
reason.


I'm also a bit curious about what all this is about. Can I convinced you 
to dig it a bit further?



`hg debugcolor` crashes on my terminal:

  File "/usr/lib/python2.7/dist-packages/hgext/color.py", line 530, in 
debugcolor
ui.write(('%s\n') % colors, label=label)
  File "/usr/lib/python2.7/dist-packages/hgext/color.py", line 446, in write
*[self.label(a, label) for a in args], **opts)
  File "/usr/lib/python2.7/dist-packages/hgext/color.py", line 488, in label
for s in msg.split('\n')])
  File "/usr/lib/python2.7/dist-packages/hgext/color.py", line 396, in 
render_effects
for effect in ['none'] + effects.split())
  File "/usr/lib/python2.7/dist-packages/hgext/color.py", line 396, in 

for effect in ['none'] + effects.split())
  File "/usr/lib/python2.7/dist-packages/hgext/color.py", line 378, in 
_effect_str
attr, val = _terminfo_params[effect]
KeyError: 'purple'

Not sure where this "purple" comes (been there from initial file check in)
from but "magenta" seems more appropriate.

diff --git a/hgext/color.py b/hgext/color.py
--- a/hgext/color.py
+++ b/hgext/color.py
@@ -182,7 +182,7 @@ testedwith = 'ships-with-hg-core'
 'italic': 3, 'underline': 4, 'inverse': 7, 'dim': 2,
 'black_background': 40, 'red_background': 41,
 'green_background': 42, 'yellow_background': 43,
-'blue_background': 44, 'purple_background': 45,
+'blue_background': 44, 'magenta_background': 45,
 'cyan_background': 46, 'white_background': 47}

 def _terminfosetup(ui, mode):
@@ -591,7 +591,7 @@ else:
 'green_background': _BACKGROUND_GREEN,
 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
 'blue_background': _BACKGROUND_BLUE,
-'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
+'magenta_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
  _BACKGROUND_BLUE),
___
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


Re: [PATCH RFC] perf: add asv benchmarks

2016-10-13 Thread Pierre-Yves David



On 10/12/2016 10:35 AM, Philippe Pepiot wrote:

# HG changeset patch
# User Philippe Pepiot 
# Date 1475136994 -7200
#  Thu Sep 29 10:16:34 2016 +0200
# Node ID f7847ea1b58780e3508d57376c4fdd63d6aedfcd
# Parent  b85fa6bf298be07804a74d8fdec0d19fdbc6d740
# EXP-Topic hgperf
perf: add asv benchmarks


For the record, this is unlikely that we reaches the point were we can 
review this to the point of acceptance before the freeze on Tuesday.


Unless another reviewer pick this, You'll have to resend this when 4.0 
is released on November 1st.




Airspeed velocity (ASV) is a python framework for benchmarking Python packages
over their lifetime. The results are displayed in an interactive web frontend.

Add ASV benchmarks for mercurial that use contrib/perf.py extension that could
be run against multiple reference repositories.

The benchmark suite now includes revsets from contrib/base-revsets.txt with
variants, perftags, perfstatus, perfmanifest and perfheads.

Installation requires ASV (not yet released
https://github.com/spacetelescope/asv master branch), python-hglib and
virtualenv.

This is part of PerformanceTrackingSuitePlan
https://www.mercurial-scm.org/wiki/PerformanceTrackingSuitePlan

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -49,6 +49,7 @@ mercurial.egg-info
 tags
 cscope.*
 .idea/*
+.asv/*
 i18n/hg.pot
 locale/*/LC_MESSAGES/hg.mo
 hgext/__index__.py
diff --git a/contrib/asv.conf.json b/contrib/asv.conf.json
new file mode 100644
--- /dev/null
+++ b/contrib/asv.conf.json
@@ -0,0 +1,127 @@
+{
+// The version of the config file format.  Do not change, unless
+// you know what you are doing.
+"version": 1,
+
+// The name of the project being benchmarked
+"project": "mercurial",
+
+// The project's homepage
+"project_url": "http://mercurial-scm.org/";,
+
+// The URL or local path of the source code repository for the
+// project being benchmarked
+"repo": "..",
+
+// List of branches to benchmark. If not provided, defaults to "master"
+// (for git) or "default" (for mercurial).
+// "branches": ["master"], // for git
+// "branches": ["default"],// for mercurial
+"branches": ["default", "stable"],
+
+// The DVCS being used.  If not set, it will be automatically
+// determined from "repo" by looking at the protocol in the URL
+// (if remote), or by looking for special directories, such as
+// ".git" (if local).
+// "dvcs": "git",
+
+// The tool to use to create environments.  May be "conda",
+// "virtualenv" or other value depending on the plugins in use.
+// If missing or the empty string, the tool will be automatically
+// determined by looking for tools on the PATH environment
+// variable.
+"environment_type": "virtualenv",
+
+// the base URL to show a commit for the project.
+"show_commit_url": "https://www.selenic.com/hg/rev/";,
+
+// The Pythons you'd like to test against.  If not provided, defaults
+// to the current version of Python used to run `asv`.
+// "pythons": ["2.7", "3.3"],
+
+// The matrix of dependencies to test.  Each key is the name of a
+// package (in PyPI) and the values are version numbers.  An empty
+// list or empty string indicates to just test against the default
+// (latest) version. null indicates that the package is to not be
+// installed. If the package to be tested is only available from
+// PyPi, and the 'environment_type' is conda, then you can preface
+// the package name by 'pip+', and the package will be installed via
+// pip (with all the conda available packages installed first,
+// followed by the pip installed packages).
+//
+// "matrix": {
+// "numpy": ["1.6", "1.7"],
+// "six": ["", null],// test with and without six installed
+// "pip+emcee": [""],   // emcee is only available for install with 
pip.
+// },
+
+// Combinations of libraries/python versions can be excluded/included
+// from the set to test. Each entry is a dictionary containing additional
+// key-value pairs to include/exclude.
+//
+// An exclude entry excludes entries where all values match. The
+// values are regexps that should match the whole string.
+//
+// An include entry adds an environment. Only the packages listed
+// are installed. The 'python' key is required. The exclude rules
+// do not apply to includes.
+//
+// In addition to package names, the following keys are available:
+//
+// - python
+// Python version, as in the *pythons* variable above.
+// - environment_type
+// Environment type, as above.
+// - sys_platform
+// Platform, as in sys.platform. Possible values for the common
+// cases: 'linux2', 'win32', 'cygwin', 'darwin'.
+//
+// "exclude": [
+// {"python": "3.2", "sys_platform": "win32"}, // skip py3.2 on windows
+//

[PATCH] pathencode: use assert() for PyBytes_Check()

2016-10-13 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1476387731 -7200
#  Thu Oct 13 21:42:11 2016 +0200
# Node ID 4bbdf012fafbdffd4d4402a712fdc01d3252d00c
# Parent  c0410814002f467c24ef07ce73850ba15b306f8e
pathencode: use assert() for PyBytes_Check()

This should have been added in a8c948ee3668. I sent the patch to the
list prematurely.

diff --git a/mercurial/pathencode.c b/mercurial/pathencode.c
--- a/mercurial/pathencode.c
+++ b/mercurial/pathencode.c
@@ -638,9 +638,9 @@ static PyObject *hashmangle(const char *
if (lastdot >= 0)
memcopy(dest, &destlen, destsize, &src[lastdot],
len - lastdot - 1);
 
-   PyBytes_Check(ret);
+   assert(PyBytes_Check(ret));
Py_SIZE(ret) = destlen;
 
return ret;
 }
@@ -751,9 +751,9 @@ PyObject *pathencode(PyObject *self, PyO
 
newobj = PyBytes_FromStringAndSize(NULL, newlen);
 
if (newobj) {
-   PyBytes_Check(newobj);
+   assert(PyBytes_Check(newobj));
Py_SIZE(newobj)--;
basicencode(PyBytes_AS_STRING(newobj), newlen, path,
len + 1);
}
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH] dirs: document Py_SIZE weirdness

2016-10-13 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1475939263 -7200
#  Sat Oct 08 17:07:43 2016 +0200
# Node ID c05716f3eb0a4a70ef1f59b51cd1b29ee683a145
# Parent  c0410814002f467c24ef07ce73850ba15b306f8e
dirs: document Py_SIZE weirdness

Assigning to what looks like a function is clown shoes. Document that
it is a macro referring to a struct member.

diff --git a/mercurial/dirs.c b/mercurial/dirs.c
--- a/mercurial/dirs.c
+++ b/mercurial/dirs.c
@@ -75,8 +75,10 @@ static int _addpath(PyObject *dirs, PyOb
 pos < 2 ? 2 : pos);
if (key == NULL)
goto bail;
}
+   /* Py_SIZE(o) refers to the ob_size member of the struct. Yes,
+   * assigning to what looks like a function seems wrong. */
Py_SIZE(key) = pos;
((PyBytesObject *)key)->ob_sval[pos] = '\0';
 
val = PyDict_GetItem(dirs, key);
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 6] parsers: alias more PyInt* symbols on Python 3

2016-10-13 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1476357760 -7200
#  Thu Oct 13 13:22:40 2016 +0200
# Node ID b9e9955e74842914d77b892fed7a0ff3a4f2d85e
# Parent  1e3d29ee42903dfb65308a849f987dbe9de97953
parsers: alias more PyInt* symbols on Python 3

I feel dirty for having to do this. But this is currently our approach
for dealing with PyInt -> PyLong in Python 3 for this file.

This removes a ton of compiler warnings by fixing unresolved symbols.

diff --git a/mercurial/parsers.c b/mercurial/parsers.c
--- a/mercurial/parsers.c
+++ b/mercurial/parsers.c
@@ -19,9 +19,12 @@
 /* The mapping of Python types is meant to be temporary to get Python
  * 3 to compile. We should remove this once Python 3 support is fully
  * supported and proper types are used in the extensions themselves. */
 #define PyInt_Type PyLong_Type
+#define PyInt_Check PyLong_Check
 #define PyInt_FromLong PyLong_FromLong
+#define PyInt_FromSsize_t PyLong_FromSsize_t
+#define PyInt_AS_LONG PyLong_AS_LONG
 #define PyInt_AsLong PyLong_AsLong
 #endif
 
 static char *versionerrortext = "Python minor version mismatch";
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 6] bdiff: include util.h

2016-10-13 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1476358034 -7200
#  Thu Oct 13 13:27:14 2016 +0200
# Node ID 569eb5b02fff32b0517c4c1d5ef8fb82dab33023
# Parent  b9e9955e74842914d77b892fed7a0ff3a4f2d85e
bdiff: include util.h

Without this, IS_PY3K isn't define and the preprocessor uses the
incorrect module loading code, causing the module fail to load at
run-time.

After this patch, all our C extensions (except for watchman's) appear
to import correctly in Python 3!

diff --git a/mercurial/bdiff_module.c b/mercurial/bdiff_module.c
--- a/mercurial/bdiff_module.c
+++ b/mercurial/bdiff_module.c
@@ -16,8 +16,9 @@
 #include 
 
 #include "bdiff.h"
 #include "bitmanipulation.h"
+#include "util.h"
 
 
 static PyObject *blocks(PyObject *self, PyObject *args)
 {
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 6] manifest: use PyVarObject_HEAD_INIT

2016-10-13 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1476357443 -7200
#  Thu Oct 13 13:17:23 2016 +0200
# Node ID 1e3d29ee42903dfb65308a849f987dbe9de97953
# Parent  1f30bcebd4bdc26602ec4e9ae924f101c7642594
manifest: use PyVarObject_HEAD_INIT

More appeasing the Python 3 and compiler overlords. The code is
equivalent.

diff --git a/mercurial/manifest.c b/mercurial/manifest.c
--- a/mercurial/manifest.c
+++ b/mercurial/manifest.c
@@ -261,10 +261,9 @@ done:
| Py_TPFLAGS_HAVE_ITER
 #endif
 
 static PyTypeObject lazymanifestEntriesIterator = {
-   PyObject_HEAD_INIT(NULL)
-   0,   /*ob_size */
+   PyVarObject_HEAD_INIT(NULL, 0)
"parsers.lazymanifest.entriesiterator", /*tp_name */
sizeof(lmIter),  /*tp_basicsize */
0,   /*tp_itemsize */
lmiter_dealloc,  /*tp_dealloc */
@@ -310,10 +309,9 @@ static PyObject *lmiter_iterkeysnext(PyO
| Py_TPFLAGS_HAVE_ITER
 #endif
 
 static PyTypeObject lazymanifestKeysIterator = {
-   PyObject_HEAD_INIT(NULL)
-   0,   /*ob_size */
+   PyVarObject_HEAD_INIT(NULL, 0)
"parsers.lazymanifest.keysiterator", /*tp_name */
sizeof(lmIter),  /*tp_basicsize */
0,   /*tp_itemsize */
lmiter_dealloc,  /*tp_dealloc */
@@ -889,10 +887,9 @@ static PyMethodDef lazymanifest_methods[
 #define LAZYMANIFEST_TPFLAGS Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_SEQUENCE_IN
 #endif
 
 static PyTypeObject lazymanifestType = {
-   PyObject_HEAD_INIT(NULL)
-   0,/* ob_size */
+   PyVarObject_HEAD_INIT(NULL, 0)
"parsers.lazymanifest",   /* tp_name */
sizeof(lazymanifest), /* tp_basicsize */
0,/* tp_itemsize */
(destructor)lazymanifest_dealloc, /* tp_dealloc */
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 5 of 6] parsers: avoid PySliceObject cast on Python 3

2016-10-13 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1476358493 -7200
#  Thu Oct 13 13:34:53 2016 +0200
# Node ID 8501cbf27b0ae7402f6c6df6cea68b757a939bb9
# Parent  569eb5b02fff32b0517c4c1d5ef8fb82dab33023
parsers: avoid PySliceObject cast on Python 3

PySlice_GetIndicesEx() accepts a PySliceObject* on Python 2 and a
PyObject* on Python 3. Casting to PySliceObject* on Python 3 was
yielding a compiler warning. So stop doing that.

With this patch, I no longer see any compiler warnings when
building the core extensions for Python 3!

diff --git a/mercurial/parsers.c b/mercurial/parsers.c
--- a/mercurial/parsers.c
+++ b/mercurial/parsers.c
@@ -2275,9 +2275,14 @@ static int index_slice_del(indexObject *
Py_ssize_t start, stop, step, slicelength;
Py_ssize_t length = index_length(self);
int ret = 0;
 
+/* Argument changed from PySliceObject* to PyObject* in Python 3. */
+#ifdef IS_PY3K
+   if (PySlice_GetIndicesEx(item, length,
+#else
if (PySlice_GetIndicesEx((PySliceObject*)item, length,
+#endif
 &start, &stop, &step, &slicelength) < 0)
return -1;
 
if (slicelength <= 0)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 6 of 6] mercurial: support loading C extensions on Python 3

2016-10-13 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1476359054 -7200
#  Thu Oct 13 13:44:14 2016 +0200
# Node ID 1bc4e41ca8a00b42316c1ef64c2687df24cfb81b
# Parent  8501cbf27b0ae7402f6c6df6cea68b757a939bb9
mercurial: support loading C extensions on Python 3

Previously, the module policy and custom importer forced dual Python
and C modules to use the pure Python version on Python 3. Now that the
C extensions compile and load properly on Python 3, this restriction
can be removed.

This patch changes the module policy to not force the policy to "py" on
Python 3. It also changes the path finder to not rewrite paths to
"mercurial.pure.*" for dual use modules and to not use our source
transformer for C extensions.

diff --git a/mercurial/__init__.py b/mercurial/__init__.py
--- a/mercurial/__init__.py
+++ b/mercurial/__init__.py
@@ -137,10 +137,9 @@ if sys.version_info[0] >= 3:
 # Only handle Mercurial-related modules.
 if not fullname.startswith(('mercurial.', 'hgext.', 'hgext3rd.')):
 return None
 
-# This assumes Python 3 doesn't support loading C modules.
-if fullname in _dualmodules:
+if fullname in _dualmodules and modulepolicy in policy.policynoc:
 stem = fullname.split('.')[-1]
 fullname = 'mercurial.pure.%s' % stem
 target = pure
 assert len(path) == 1
@@ -164,11 +163,12 @@ if sys.version_info[0] >= 3:
 
 if fullname.startswith('mercurial.pure.'):
 spec.name = spec.name.replace('.pure.', '.')
 
-# TODO need to support loaders from alternate specs, like zip
-# loaders.
-spec.loader = hgloader(spec.name, spec.origin)
+if fullname not in _dualmodules:
+# TODO need to support loaders from alternate specs, like zip
+# loaders.
+spec.loader = hgloader(spec.name, spec.origin)
 return spec
 
 def replacetokens(tokens, fullname):
 """Transform a stream of tokens from raw to Python 3.
diff --git a/mercurial/policy.py b/mercurial/policy.py
--- a/mercurial/policy.py
+++ b/mercurial/policy.py
@@ -35,11 +35,6 @@ except ImportError:
 # But we don't import platform and don't bloat for it here.
 if '__pypy__' in sys.builtin_module_names:
 policy = 'cffi'
 
-# Our C extensions aren't yet compatible with Python 3. So use pure Python
-# on Python 3 for now.
-if sys.version_info[0] >= 3:
-policy = 'py'
-
 # Environment variable can always force settings.
 policy = os.environ.get('HGMODULEPOLICY', policy)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 3 V3] revlog: add instance variable controlling delta chain use

2016-10-13 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1474745137 25200
#  Sat Sep 24 12:25:37 2016 -0700
# Node ID aed87a8bed99b373eec5fb09dd2f76d166af59e8
# Parent  4c98fccd5b70d2f89fe48bdb81288448daed758c
revlog: add instance variable controlling delta chain use

This is to support disabling delta chains on the changelog in a
subsequent patch.

diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -296,8 +296,10 @@ class revlog(object):
 elif fmt > REVLOGNG:
 raise RevlogError(_("index %s unknown format %d")
   % (self.indexfile, fmt))
 
+self._storedeltachains = True
+
 self._io = revlogio()
 if self.version == REVLOGV0:
 self._io = revlogoldio()
 try:
@@ -1468,9 +1470,9 @@ class revlog(object):
 else:
 textlen = len(text)
 
 # should we try to build a delta?
-if prev != nullrev:
+if prev != nullrev and self._storedeltachains:
 tested = set()
 # This condition is true most of the time when processing
 # changegroup data into a generaldelta repo. The only time it
 # isn't true is if this is the first revision in a delta chain
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 3 V3] changegroup: document deltaparent's choice of previous revision

2016-10-13 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1476355787 -7200
#  Thu Oct 13 12:49:47 2016 +0200
# Node ID 4c98fccd5b70d2f89fe48bdb81288448daed758c
# Parent  c0410814002f467c24ef07ce73850ba15b306f8e
changegroup: document deltaparent's choice of previous revision

As part of debugging low-level changegroup generation, I came across
what I initially thought was a weird behavior: changegroup v2 is
choosing the previous revision in the changegroup as a delta base
instead of p1. I was tempted to rewrite this to use p1, as p1
will delta better than prev in the common case. However, I realized
that taking p1 as the base would potentially require resolving a
revision fulltext and thus require more CPU for e.g. server-side
processing of getbundle requests.

This patch tweaks the code comment to note the choice of behavior.
It also notes there is room for a flag or config option to tweak
this behavior later: using p1 as the delta base would likely make
changegroups smaller at the expense of more CPU, which could be
beneficial for things like clone bundles.

diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -817,10 +817,17 @@ class cg2packer(cg1packer):
 self._reorder = False
 
 def deltaparent(self, revlog, rev, p1, p2, prev):
 dp = revlog.deltaparent(rev)
-# avoid storing full revisions; pick prev in those cases
-# also pick prev when we can't be sure remote has dp
+# Avoid sending full revisions when delta parent is null. Pick
+# prev in that case. It's tempting to pick p1 in this case, as p1
+# will be smaller in the common case. However, computing a delta
+# against p1 may require resolving the raw text of p1, which could
+# be expensive. The revlog caches should have prev cached, meaning
+# less CPU for changegroup generation. There is likely room to add
+# a flag and/or config option to control this behavior.
+#
+# Pick prev when we can't be sure remote has the base revision.
 if dp == nullrev or (dp != p1 and dp != p2 and dp != prev):
 return prev
 return dp
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 3 V3] changelog: disable delta chains

2016-10-13 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1476355827 -7200
#  Thu Oct 13 12:50:27 2016 +0200
# Node ID 231e6b5206857a809198f5535fac32a004686bf1
# Parent  aed87a8bed99b373eec5fb09dd2f76d166af59e8
changelog: disable delta chains

This patch disables delta chains on changelogs. After this patch, new
entries on changelogs - including existing changelogs - will be stored
as the fulltext of that data (likely compressed). No delta computation
will be performed.

An overview of delta chains and data justifying this change follows.

Revlogs try to store entries as a delta against a previous entry (either
a parent revision in the case of generaldelta or the previous physical
revision when not using generaldelta). Most of the time this is the
correct thing to do: it frequently results in less CPU usage and smaller
storage.

Delta chains are most effective when the base revision being deltad
against is similar to the current data. This tends to occur naturally
for manifests and file data, since only small parts of each tend to
change with each revision. Changelogs, however, are a different story.

Changelog entries represent changesets/commits. And unless commits in a
repository are homogonous (same author, changing same files, similar
commit messages, etc), a delta from one entry to the next tends to be
relatively large compared to the size of the entry. This means that
delta chains tend to be short. How short? Here is the full vs delta
revision breakdown on some real world repos:

Repo % Full% Delta   Max Length
hg45.8   54.26
mozilla-central   42.4   57.68
mozilla-unified   42.5   57.5   17
pypy  46.1   53.96
python-zstandard  46.1   53.93

(I threw in python-zstandard as an example of a repo that is homogonous.
It contains a small Python project with changes all from the same
author.)

Contrast this with the manifest revlog for these repos, where 99+% of
revisions are deltas and delta chains run into the thousands.

So delta chains aren't as useful on changelogs. But even a short delta
chain may provide benefits. Let's measure that.

Delta chains may require less CPU to read revisions if the CPU time
spent reading smaller deltas is less than the CPU time used to
decompress larger individual entries. We can measure this via
`hg perfrevlog -c -d 1` to iterate a revlog to resolve each revision's
fulltext. Here are the results of that command on a repo using delta
chains in its changelog and on a repo without delta chains:

hg (forward)
! wall 0.407008 comb 0.41 user 0.41 sys 0.00 (best of 25)
! wall 0.390061 comb 0.39 user 0.39 sys 0.00 (best of 26)

hg (reverse)
! wall 0.515221 comb 0.52 user 0.52 sys 0.00 (best of 19)
! wall 0.400018 comb 0.40 user 0.39 sys 0.01 (best of 25)

mozilla-central (forward)
! wall 4.508296 comb 4.49 user 4.49 sys 0.00 (best of 3)
! wall 4.370222 comb 4.37 user 4.35 sys 0.02 (best of 3)

mozilla-central (reverse)
! wall 5.758995 comb 5.76 user 5.72 sys 0.04 (best of 3)
! wall 4.346503 comb 4.34 user 4.32 sys 0.02 (best of 3)

mozilla-unified (forward)
! wall 4.957088 comb 4.95 user 4.94 sys 0.01 (best of 3)
! wall 4.660528 comb 4.65 user 4.63 sys 0.02 (best of 3)

mozilla-unified (reverse)
! wall 6.119827 comb 6.11 user 6.09 sys 0.02 (best of 3)
! wall 4.675136 comb 4.67 user 4.67 sys 0.00 (best of 3)

pypy (forward)
! wall 1.231122 comb 1.24 user 1.23 sys 0.01 (best of 8)
! wall 1.164896 comb 1.16 user 1.16 sys 0.00 (best of 9)

pypy (reverse)
! wall 1.467049 comb 1.46 user 1.46 sys 0.00 (best of 7)
! wall 1.160200 comb 1.17 user 1.16 sys 0.01 (best of 9)

The data clearly shows that it takes less wall and CPU time to resolve
revisions when there are no delta chains in the changelogs, regardless
of the direction of traversal. Furthermore, not using a delta chain
means that fulltext resolution in reverse is as fast as iterating
forward. So not using delta chains on the changelog is a clear CPU win
for reading operations.

An example of a user-visible operation showing this speed-up is revset
evaluation. Here are results for
`hg perfrevset 'author(gps) or author(mpm)'`:

hg
! wall 1.655506 comb 1.66 user 1.65 sys 0.01 (best of 6)
! wall 1.612723 comb 1.61 user 1.60 sys 0.01 (best of 7)

mozilla-central
! wall 17.629826 comb 17.64 user 17.60 sys 0.04 (best of 3)
! wall 17.311033 comb 17.30 user 17.26 sys 0.04 (best of 3)

What about 00changelog.i size?

RepoDelta Chains No Delta Chains
hg7,033,250 6,976,771
mozilla-central  82,978,74881,574,623
mozilla-unified  88,112,34986,702,162
pypy 20,740,69920,659,741

The data shows that removing delta chains f

[PATCH 1 of 6] dirs: use PyVarObject_HEAD_INIT

2016-10-13 Thread Gregory Szorc
# HG changeset patch
# User Gregory Szorc 
# Date 1476357254 -7200
#  Thu Oct 13 13:14:14 2016 +0200
# Node ID 1f30bcebd4bdc26602ec4e9ae924f101c7642594
# Parent  c0410814002f467c24ef07ce73850ba15b306f8e
dirs: use PyVarObject_HEAD_INIT

This makes a compiler warning go away on Python 3.

diff --git a/mercurial/dirs.c b/mercurial/dirs.c
--- a/mercurial/dirs.c
+++ b/mercurial/dirs.c
@@ -288,9 +288,9 @@ static PyMethodDef dirs_methods[] = {
{"delpath", (PyCFunction)dirs_delpath, METH_VARARGS, "remove a path"},
{NULL} /* Sentinel */
 };
 
-static PyTypeObject dirsType = { PyObject_HEAD_INIT(NULL) };
+static PyTypeObject dirsType = { PyVarObject_HEAD_INIT(NULL, 0) };
 
 void dirs_module_init(PyObject *mod)
 {
dirs_sequence_methods.sq_contains = (objobjproc)dirs_contains;
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


revset arguments on 2.2.1

2016-10-13 Thread Peter Kronenberg
I have a server running 2.2.1 and I can't figure out the arguments for the
result of revset.match

In my 3.9.2 code, I have

revsetQuery = ' ***query goes here*** '
revsetResult = revset.match(ui, revsetQuery)

Now, I want to reference revsetResult(repo) or revsetResult(repo. None),
both of which work in 3.9.2

But 2.2.1 doesn't like the second argument.  It's supposed to be a subset,
but not sure what to put if I don't want to specify a subset.

can anyone help?

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


[PATCH 2 of 3] color: ignore effects missing from terminfo

2016-10-13 Thread danek . duvall
# HG changeset patch
# User Danek Duvall 
# Date 1476385301 25200
#  Thu Oct 13 12:01:41 2016 -0700
# Node ID 333e875ce30da3760c8655e303d9bea554efe7e4
# Parent  61e74a19770c2ce80c0cedc429915112261e5c1b
color: ignore effects missing from terminfo

If terminfo mode is in effect, and an effect is used which is missing from
the terminfo database, simply silently ignore the request, leaving the
output unaffected rather than causing a crash.

diff --git a/hgext/color.py b/hgext/color.py
--- a/hgext/color.py
+++ b/hgext/color.py
@@ -369,7 +369,10 @@ def _effect_str(effect):
 if effect.endswith('_background'):
 bg = True
 effect = effect[:-11]
-attr, val, termcode = _terminfo_params[effect]
+try:
+attr, val, termcode = _terminfo_params[effect]
+except KeyError:
+return ''
 if attr:
 if termcode:
 return termcode
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] color: replace "purple_background" by "magenta_background"

2016-10-13 Thread Danek Duvall
Pierre-Yves David wrote:

> 
> 
> On 10/11/2016 11:39 AM, Denis Laxalde wrote:
> ># HG changeset patch
> ># User Denis Laxalde 
> ># Date 1476176128 -7200
> >#  Tue Oct 11 10:55:28 2016 +0200
> ># Node ID 1cf20c1c54cb8172816604de5e1d98d3cd62d711
> ># Parent  b85fa6bf298be07804a74d8fdec0d19fdbc6d740
> ># EXP-Topic color-purple-crash
> >color: replace "purple_background" by "magenta_background"
> 
> We probably want to keep both value around for backward compatibility
> reason.
> 
> I'm also a bit curious about what all this is about. Can I convinced you to
> dig it a bit further?

_effect_str() strips "_background" off of an effect name to grab the color
name so it can figure out what color code to use.  Since we define
"purple_background", but "magenta" instead of "purple" (and
"magenta_background" doesn't exist, either), then this blows up.

I'll be sending out a patch shortly that just covers up this KeyError, but
either defining purple or magenta_background (or, probably, both) probably
ought to be done, anyway.

Danek

> >`hg debugcolor` crashes on my terminal:
> >
> >  File "/usr/lib/python2.7/dist-packages/hgext/color.py", line 530, in 
> > debugcolor
> >ui.write(('%s\n') % colors, label=label)
> >  File "/usr/lib/python2.7/dist-packages/hgext/color.py", line 446, in 
> > write
> >*[self.label(a, label) for a in args], **opts)
> >  File "/usr/lib/python2.7/dist-packages/hgext/color.py", line 488, in 
> > label
> >for s in msg.split('\n')])
> >  File "/usr/lib/python2.7/dist-packages/hgext/color.py", line 396, in 
> > render_effects
> >for effect in ['none'] + effects.split())
> >  File "/usr/lib/python2.7/dist-packages/hgext/color.py", line 396, in 
> > 
> >for effect in ['none'] + effects.split())
> >  File "/usr/lib/python2.7/dist-packages/hgext/color.py", line 378, in 
> > _effect_str
> >attr, val = _terminfo_params[effect]
> >KeyError: 'purple'
> >
> >Not sure where this "purple" comes (been there from initial file check in)
> >from but "magenta" seems more appropriate.
> >
> >diff --git a/hgext/color.py b/hgext/color.py
> >--- a/hgext/color.py
> >+++ b/hgext/color.py
> >@@ -182,7 +182,7 @@ testedwith = 'ships-with-hg-core'
> > 'italic': 3, 'underline': 4, 'inverse': 7, 'dim': 2,
> > 'black_background': 40, 'red_background': 41,
> > 'green_background': 42, 'yellow_background': 43,
> >-'blue_background': 44, 'purple_background': 45,
> >+'blue_background': 44, 'magenta_background': 45,
> > 'cyan_background': 46, 'white_background': 47}
> >
> > def _terminfosetup(ui, mode):
> >@@ -591,7 +591,7 @@ else:
> > 'green_background': _BACKGROUND_GREEN,
> > 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
> > 'blue_background': _BACKGROUND_BLUE,
> >-'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
> >+'magenta_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
> > 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
> > 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
> >  _BACKGROUND_BLUE),
> >___
> >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
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH v5] copy: distinguish "file exists" cases and add a hint (BC)

2016-10-13 Thread Kevin Bullock
> On Oct 8, 2016, at 12:11, Augie Fackler  wrote:
> 
> # HG changeset patch
> # User Augie Fackler 
> # Date 1474319739 14400
> #  Mon Sep 19 17:15:39 2016 -0400
> # Node ID 3d6ce2e360155bcc7e5af21fd0fda3415aa03110
> # Parent  dd0ff715a82caa9afd0fa999dccca4d967a506a3
> copy: distinguish "file exists" cases and add a hint (BC)

Queued!

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

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


Re: [PATCH] help: backout the boolean flag marking in the help for now

2016-10-13 Thread Kevin Bullock
> On Oct 9, 2016, at 14:33, Pierre-Yves David  
> wrote:
> 
> On 10/09/2016 02:11 PM, Kevin Bullock wrote:
>>> On Oct 9, 2016, at 14:06, Pierre-Yves David 
>>>  wrote:
>>> 
>>> # HG changeset patch
>>> # User Pierre-Yves David 
>>> # Date 1475975478 -7200
>>> #  Sun Oct 09 03:11:18 2016 +0200
>>> # Node ID ae009a7425ca52fdffa451506c0e47ff3750a895
>>> # Parent  dbcef8918bbdd8a64d9f79a37bcfa284a26f3a39
>>> # EXP-Topic flag.bool
>>> help: backout the boolean flag marking in the help for now
>>> 
>> [...]
>>> diff --git a/tests/test-extension.t b/tests/test-extension.t
>>> --- a/tests/test-extension.t
>>> +++ b/tests/test-extension.t
>>> @@ -530,19 +530,19 @@ hide outer repo
>>>  --cwd DIR   change working directory
>>>   -y --noninteractivedo not prompt, automatically pick the first choice 
>>> for
>>>  all prompts
>>> -   -q --[no-]quietsuppress output
>>> -   -v --[no-]verbose  enable additional output
>>> +   -q --quiet suppress output
>>> +   -v --verbose   enable additional output
>> 
>> Why are these showing up in the backout? I thought the final patch that 
>> landed already skipped these flags--is that not true?
> 
> The initial changeset is f3c4edfd35e1 (this fell of the description during 
> the edition :-/) that changeset contains such line. I'm not sure why they end 
> up being there. Does that answer your question ?

That and looking back at  answered my 
question. It was only --help, --version, and --noninteractive that we banned 
from having a --no- variant.

> We should probably reintroduce the original hash in the description.

Yep. Queued with that fix.

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

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


[PATCH 3 of 3] color: debugcolor should emit the user-defined colors

2016-10-13 Thread danek . duvall
# HG changeset patch
# User Danek Duvall 
# Date 1476389401 25200
#  Thu Oct 13 13:10:01 2016 -0700
# Node ID c59334b806a8f10c80c2ea196eba5f4b1b86b229
# Parent  333e875ce30da3760c8655e303d9bea554efe7e4
color: debugcolor should emit the user-defined colors

This also fixes a long-standing bug that reversed the sense of the color
name and the label used to print it, which was never relevant before.

diff --git a/hgext/color.py b/hgext/color.py
--- a/hgext/color.py
+++ b/hgext/color.py
@@ -524,10 +524,16 @@ def debugcolor(ui, repo, **opts):
 _styles = {}
 for effect in _effects.keys():
 _styles[effect] = effect
+if _terminfo_params:
+for k, v in ui.configitems('color'):
+if k.startswith('color.'):
+_styles[k] = k[6:]
+elif k.startswith('terminfo.'):
+_styles[k] = k[9:]
 ui.write(('color mode: %s\n') % ui._colormode)
 ui.write(_('available colors:\n'))
-for label, colors in _styles.items():
-ui.write(('%s\n') % colors, label=label)
+for colorname, label in _styles.items():
+ui.write(('%s\n') % colorname, label=label)
 
 if os.name != 'nt':
 w32effects = None
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: revset arguments on 2.2.1

2016-10-13 Thread Pierre-Yves David



On 10/13/2016 09:44 PM, Peter Kronenberg wrote:

I have a server running 2.2.1 and I can't figure out the arguments for
the result of revset.match

In my 3.9.2 code, I have

revsetQuery = ' ***query goes here*** '
revsetResult = revset.match(ui, revsetQuery)


Any reasons you are using revset.match directly?

The top level way to query a reset from a repository is 
`repo.set(your_query_goes_here)`.



Now, I want to reference revsetResult(repo) or revsetResult(repo. None),
both of which work in 3.9.2

But 2.2.1 doesn't like the second argument.  It's supposed to be a
subset, but not sure what to put if I don't want to specify a subset.


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


Re: revset arguments on 2.2.1

2016-10-13 Thread Peter Kronenberg
Thanks.  Didn't realize that.  How does one tell what is the 'top-level'
way to do things?  The documentation is somewhat sparse, to say the least.

On Thu, Oct 13, 2016 at 6:10 PM, Pierre-Yves David <
pierre-yves.da...@ens-lyon.org> wrote:

>
>
> On 10/13/2016 09:44 PM, Peter Kronenberg wrote:
>
>> I have a server running 2.2.1 and I can't figure out the arguments for
>> the result of revset.match
>>
>> In my 3.9.2 code, I have
>>
>> revsetQuery = ' ***query goes here*** '
>> revsetResult = revset.match(ui, revsetQuery)
>>
>
> Any reasons you are using revset.match directly?
>
> The top level way to query a reset from a repository is
> `repo.set(your_query_goes_here)`.
>
> Now, I want to reference revsetResult(repo) or revsetResult(repo. None),
>> both of which work in 3.9.2
>>
>> But 2.2.1 doesn't like the second argument.  It's supposed to be a
>> subset, but not sure what to put if I don't want to specify a subset.
>>
>
> --
> Pierre-Yves David
>
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 3] color: allow for user-configurable terminfo codes for effects

2016-10-13 Thread danek . duvall
# HG changeset patch
# User Danek Duvall 
# Date 1476384497 25200
#  Thu Oct 13 11:48:17 2016 -0700
# Node ID 61e74a19770c2ce80c0cedc429915112261e5c1b
# Parent  4d93d73b8aecb2436bbfe9248cdfe0ef21582baf
color: allow for user-configurable terminfo codes for effects

If the entry in the terminfo database for your terminal is missing some
attributes, it should be possible to create them on the fly without
resorting to just making them a color.  This change allows you to have

[color]
terminfo. = 

where  might be something like "dim" or "bold", and  is the
escape sequence that would otherwise have come from a call to tigetstr().
If an escape character is needed, use "\E".  Any such settings will
override attributes that are present in the terminfo database.

diff --git a/hgext/color.py b/hgext/color.py
--- a/hgext/color.py
+++ b/hgext/color.py
@@ -187,9 +187,12 @@ def _terminfosetup(ui, mode):
 if mode not in ('auto', 'terminfo'):
 return
 
-_terminfo_params.update((key[6:], (False, int(val)))
+_terminfo_params.update((key[6:], (False, int(val), ''))
 for key, val in ui.configitems('color')
 if key.startswith('color.'))
+_terminfo_params.update((key[9:], (True, '', val.replace('\\E', '\x1b')))
+for key, val in ui.configitems('color')
+if key.startswith('terminfo.'))
 
 try:
 curses.setupterm()
@@ -197,10 +200,10 @@ def _terminfosetup(ui, mode):
 _terminfo_params = {}
 return
 
-for key, (b, e) in _terminfo_params.items():
+for key, (b, e, c) in _terminfo_params.items():
 if not b:
 continue
-if not curses.tigetstr(e):
+if not c and not curses.tigetstr(e):
 # Most terminals don't support dim, invis, etc, so don't be
 # noisy and use ui.debug().
 ui.debug("no terminfo entry for %s\n" % e)
@@ -281,26 +284,26 @@ def _modesetup(ui, coloropt):
 
 try:
 import curses
-# Mapping from effect name to terminfo attribute name or color number.
-# This will also force-load the curses module.
-_terminfo_params = {'none': (True, 'sgr0'),
-'standout': (True, 'smso'),
-'underline': (True, 'smul'),
-'reverse': (True, 'rev'),
-'inverse': (True, 'rev'),
-'blink': (True, 'blink'),
-'dim': (True, 'dim'),
-'bold': (True, 'bold'),
-'invisible': (True, 'invis'),
-'italic': (True, 'sitm'),
-'black': (False, curses.COLOR_BLACK),
-'red': (False, curses.COLOR_RED),
-'green': (False, curses.COLOR_GREEN),
-'yellow': (False, curses.COLOR_YELLOW),
-'blue': (False, curses.COLOR_BLUE),
-'magenta': (False, curses.COLOR_MAGENTA),
-'cyan': (False, curses.COLOR_CYAN),
-'white': (False, curses.COLOR_WHITE)}
+# Mapping from effect name to terminfo attribute name (or raw code) or
+# color number.  This will also force-load the curses module.
+_terminfo_params = {'none': (True, 'sgr0', ''),
+'standout': (True, 'smso', ''),
+'underline': (True, 'smul', ''),
+'reverse': (True, 'rev', ''),
+'inverse': (True, 'rev', ''),
+'blink': (True, 'blink', ''),
+'dim': (True, 'dim', ''),
+'bold': (True, 'bold', ''),
+'invisible': (True, 'invis', ''),
+'italic': (True, 'sitm', ''),
+'black': (False, curses.COLOR_BLACK, ''),
+'red': (False, curses.COLOR_RED, ''),
+'green': (False, curses.COLOR_GREEN, ''),
+'yellow': (False, curses.COLOR_YELLOW, ''),
+'blue': (False, curses.COLOR_BLUE, ''),
+'magenta': (False, curses.COLOR_MAGENTA, ''),
+'cyan': (False, curses.COLOR_CYAN, ''),
+'white': (False, curses.COLOR_WHITE, '')}
 except ImportError:
 _terminfo_params = {}
 
@@ -366,9 +369,12 @@ def _effect_str(effect):
 if effect.endswith('_background'):
 bg = True
 effect = effect[:-11]
-attr, val = _terminfo_params[effect]
+attr, val, termcode = _terminfo_params[effect]
 if attr:
-return curses.tigetstr(val)
+if termcode:
+return termcode
+else:
+return curses.tigetstr(val)
 elif bg:
 return curses.tparm(curses.tigetstr('setab'), val)
 else:
@@ -403,7 +409,7 @@ def valideffect(effect):
 
 def configstyles(ui):
 for status, cfgeffects in ui.configitems('color'):
-if '.

Re: revset arguments on 2.2.1

2016-10-13 Thread Pierre-Yves David



On 10/14/2016 12:13 AM, Peter Kronenberg wrote:

Thanks.  Didn't realize that.  How does one tell what is the 'top-level'
way to do things?  The documentation is somewhat sparse, to say the least.


We do not have an official internal API so there is not too much 
centralized doc about this. But we are slowly building one to help 
internal development.


The method I wanted to point you to is actually `repo.revs(…)` check 
that method documentation for details. This is the methods used by any 
internal piece of code that wants to run a revset.


If you input is user provided, have a look at:

scmutil.revrange(repo, [revset_expression])




On Thu, Oct 13, 2016 at 6:10 PM, Pierre-Yves David
mailto:pierre-yves.da...@ens-lyon.org>>
wrote:



On 10/13/2016 09:44 PM, Peter Kronenberg wrote:

I have a server running 2.2.1 and I can't figure out the
arguments for
the result of revset.match

In my 3.9.2 code, I have

revsetQuery = ' ***query goes here*** '
revsetResult = revset.match(ui, revsetQuery)


Any reasons you are using revset.match directly?

The top level way to query a reset from a repository is
`repo.set(your_query_goes_here)`.

Now, I want to reference revsetResult(repo) or
revsetResult(repo. None),
both of which work in 3.9.2

But 2.2.1 doesn't like the second argument.  It's supposed to be a
subset, but not sure what to put if I don't want to specify a
subset.


--
Pierre-Yves David




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


[PATCH] demandimport: disable lazy import of __builtin__

2016-10-13 Thread Mads Kiilerich
# HG changeset patch
# User Mads Kiilerich 
# Date 1476407019 -7200
#  Fri Oct 14 03:03:39 2016 +0200
# Node ID c0fd76f612735f0354102603ee630437208d8336
# Parent  c0410814002f467c24ef07ce73850ba15b306f8e
demandimport: disable lazy import of __builtin__

Demandimport uses the "try to import __builtin__, else use builtins" trick to
handle Python 3. External libraries and extensions might do something similar.
On Fedora 25 subversion-python-1.9.4-4.fc25.x86_64 will do just that (except
the opposite) ... and it failed all subversion convert tests because
demandimport was hiding that it didn't have builtins but should use
__builtin__.

The builtin module has already been imported when demandimport is loaded so
there is no point in trying to import it on demand. Just always ignore both
variants in demandimport.

diff --git a/mercurial/demandimport.py b/mercurial/demandimport.py
--- a/mercurial/demandimport.py
+++ b/mercurial/demandimport.py
@@ -291,6 +291,8 @@ ignore = [
 'sqlalchemy.events', # has import-time side effects (issue5085)
 # setuptools 8 expects this module to explode early when not on windows
 'distutils.msvc9compiler',
+'__builtin__',
+'builtins',
 ]
 
 if _pypy:
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 2] changegroup: skip delta when the underlying revlog do not use them

2016-10-13 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1476401471 -7200
#  Fri Oct 14 01:31:11 2016 +0200
# Node ID 747c0a1084ef6251a987e469197bad7796756403
# Parent  e19eb107706e7210c3b359d66f5274911b181566
# EXP-Topic storedeltachains
changegroup: skip delta when the underlying revlog do not use them

Revlog can now be configured to store full snapshot only. This is used on the
changelog. However, the changegroup packing was still recomputing deltas to be
sent over the wire.

We now just reuse the full snapshot directly in this case, skipping delta
computation. This provides use with a large speed up(-30%):

# perfchangegroupchangelog on mercurial
! wall 2.010326 comb 2.02 user 2.00 sys 0.02 (best of 5)
! wall 1.382039 comb 1.38 user 1.37 sys 0.01 (best of 8)

# perfchangegroupchangelog on pypy
! wall 5.792589 comb 5.78 user 5.78 sys 0.00 (best of 3)
! wall 3.911158 comb 3.92 user 3.90 sys 0.02 (best of 3)

# perfchangegroupchangelog on mozilla central
! wall 20.683727 comb 20.68 user 20.63 sys 0.05 (best of 3)
! wall 14.190204 comb 14.19 user 14.15 sys 0.04 (best of 3)

Many tests have to be updated because of the change in bundle content. All
theses update have been verified.  Because diffing changelog was not very
valuable, the resulting bundle have similar size (often a bit smaller):

# full bundle of mozilla central
with delta:1142740533B
without delta: 1142173300B

So this is a win all over the board.

diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -818,18 +818,24 @@ class cg2packer(cg1packer):
 
 def deltaparent(self, revlog, rev, p1, p2, prev):
 dp = revlog.deltaparent(rev)
-# Avoid sending full revisions when delta parent is null. Pick
-# prev in that case. It's tempting to pick p1 in this case, as p1
-# will be smaller in the common case. However, computing a delta
-# against p1 may require resolving the raw text of p1, which could
-# be expensive. The revlog caches should have prev cached, meaning
-# less CPU for changegroup generation. There is likely room to add
-# a flag and/or config option to control this behavior.
-#
-# Pick prev when we can't be sure remote has the base revision.
-if dp == nullrev or (dp != p1 and dp != p2 and dp != prev):
+if dp == nullrev and revlog.storedeltachains:
+# Avoid sending full revisions when delta parent is null. Pick prev
+# in that case. It's tempting to pick p1 in this case, as p1 will
+# be smaller in the common case. However, computing a delta against
+# p1 may require resolving the raw text of p1, which could be
+# expensive. The revlog caches should have prev cached, meaning
+# less CPU for changegroup generation. There is likely room to add
+# a flag and/or config option to control this behavior.
 return prev
-return dp
+elif dp == nullrev:
+# revlog is configure to use full snapshot for a reason,
+# stick to full snapshot.
+return nullrev
+elif dp not in (p1, p2, prev):
+# Pick prev when we can't be sure remote has the base revision.
+return prev
+else:
+return dp
 
 def builddeltaheader(self, node, p1n, p2n, basenode, linknode, flags):
 # Do nothing with flags, it is implicitly 0 in cg1 and cg2
diff --git a/tests/test-acl.t b/tests/test-acl.t
--- a/tests/test-acl.t
+++ b/tests/test-acl.t
@@ -113,7 +113,7 @@ Extension disabled for lack of a hook
   adding quux/file.py revisions
   added 3 changesets with 3 changes to 3 files
   updating the branch cache
-  bundle2-input-part: total payload size 1606
+  bundle2-input-part: total payload size 1553
   bundle2-input-part: "pushkey" (params: 4 mandatory) supported
   pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
   bundle2-input-bundle: 3 parts total
@@ -178,7 +178,7 @@ Extension disabled for lack of acl.sourc
   calling hook pretxnchangegroup.acl: hgext.acl.hook
   acl: changes have source "push" - skipping
   updating the branch cache
-  bundle2-input-part: total payload size 1606
+  bundle2-input-part: total payload size 1553
   bundle2-input-part: "pushkey" (params: 4 mandatory) supported
   pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
   bundle2-input-bundle: 3 parts total
@@ -254,7 +254,7 @@ No [acl.allow]/[acl.deny]
   acl: branch access granted: "911600dab2ae" on branch "default"
   acl: path access granted: "911600dab2ae"
   updating the branch cache
-  bundle2-input-part: total payload size 1606
+  bundle2-input-part: total payload size 1553
   bundle2-input-part: "pushkey" (params: 4 mandatory) supported
   pushing key for "phases:911600dab2ae7a9baff75958b84fe606851ce955"
   bundle2-inp

[PATCH 1 of 2 v2] largefiles: always use filechunkiter when iterating files

2016-10-13 Thread Mads Kiilerich
# HG changeset patch
# User Mads Kiilerich 
# Date 1476267738 -7200
#  Wed Oct 12 12:22:18 2016 +0200
# Node ID b7889580507c3d1d40e61904c7a2c2aba335c6cd
# Parent  c0410814002f467c24ef07ce73850ba15b306f8e
largefiles: always use filechunkiter when iterating files

Before, we would sometimes use the default iterator over large files. That
iterator is line based and would add extra buffering and use odd chunk sizes
which could give some overhead.

copyandhash can't just apply a filechunkiter as it sometimes is passed a
genuine generator when downloading remotely.

diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -231,7 +231,8 @@ def copyfromcache(repo, hash, filename):
 # don't use atomic writes in the working copy.
 with open(path, 'rb') as srcfd:
 with wvfs(filename, 'wb') as destfd:
-gothash = copyandhash(srcfd, destfd)
+gothash = copyandhash(
+util.filechunkiter(srcfd), destfd)
 if gothash != hash:
 repo.ui.warn(_('%s: data corruption in %s with hash %s\n')
  % (filename, path, gothash))
diff --git a/hgext/largefiles/localstore.py b/hgext/largefiles/localstore.py
--- a/hgext/largefiles/localstore.py
+++ b/hgext/largefiles/localstore.py
@@ -10,6 +10,7 @@
 from __future__ import absolute_import
 
 from mercurial.i18n import _
+from mercurial import util
 
 from . import (
 basestore,
@@ -42,7 +43,8 @@ class localstore(basestore.basestore):
 raise basestore.StoreError(filename, hash, self.url,
 _("can't get file locally"))
 with open(path, 'rb') as fd:
-return lfutil.copyandhash(fd, tmpfile)
+return lfutil.copyandhash(
+util.filechunkiter(fd), tmpfile)
 
 def _verifyfiles(self, contents, filestocheck):
 failed = False
diff --git a/hgext/largefiles/remotestore.py b/hgext/largefiles/remotestore.py
--- a/hgext/largefiles/remotestore.py
+++ b/hgext/largefiles/remotestore.py
@@ -118,7 +118,7 @@ class remotestore(basestore.basestore):
 raise NotImplementedError('abstract method')
 
 def _get(self, hash):
-'''Get file with the given hash from the remote store.'''
+'''Get a iterator for content with the given hash.'''
 raise NotImplementedError('abstract method')
 
 def _stat(self, hashes):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 2 v2] util: increase filechunkiter size to 128k

2016-10-13 Thread Mads Kiilerich
# HG changeset patch
# User Mads Kiilerich 
# Date 1476402795 -7200
#  Fri Oct 14 01:53:15 2016 +0200
# Node ID 8909ce1593659bce0563cc66ca3fa34525daed65
# Parent  b7889580507c3d1d40e61904c7a2c2aba335c6cd
util: increase filechunkiter size to 128k

util.filechunkiter has been using a chunk size of 64k for more than 10 years,
also in years where Moore's law still was a law. It is probably ok to bump it
now and perhaps get a slight win in some cases.

Also, largefiles have been using 128k for a long time. Specifying that size
multiple times (or forgetting to do it) seems a bit stupid. Decreasing it to
64k also seems unfortunate.

Thus, we will set the default chunksize to 128k and use the default everywhere.

diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -372,7 +372,7 @@ def hashfile(file):
 return ''
 hasher = hashlib.sha1('')
 with open(file, 'rb') as fd:
-for data in util.filechunkiter(fd, 128 * 1024):
+for data in util.filechunkiter(fd):
 hasher.update(data)
 return hasher.hexdigest()
 
diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -1356,7 +1356,7 @@ def overridecat(orig, ui, repo, file1, *
   'downloaded')  % lf)
 path = lfutil.usercachepath(repo.ui, hash)
 with open(path, "rb") as fpin:
-for chunk in util.filechunkiter(fpin, 128 * 1024):
+for chunk in util.filechunkiter(fpin):
 fp.write(chunk)
 err = 0
 return err
diff --git a/hgext/largefiles/proto.py b/hgext/largefiles/proto.py
--- a/hgext/largefiles/proto.py
+++ b/hgext/largefiles/proto.py
@@ -134,7 +134,7 @@ def wirereposetup(ui, repo):
 length))
 
 # SSH streams will block if reading more than length
-for chunk in util.filechunkiter(stream, 128 * 1024, length):
+for chunk in util.filechunkiter(stream, limit=length):
 yield chunk
 # HTTP streams must hit the end to process the last empty
 # chunk of Chunked-Encoding so the connection can be reused.
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1684,9 +1684,9 @@ class chunkbuffer(object):
 
 return ''.join(buf)
 
-def filechunkiter(f, size=65536, limit=None):
+def filechunkiter(f, size=131072, limit=None):
 """Create a generator that produces the data in the file size
-(default 65536) bytes at a time, up to optional limit (default is
+(default 131072) bytes at a time, up to optional limit (default is
 to read all data).  Chunks may be less than size bytes if the
 chunk is the last chunk in the file, or the file is a socket or
 some other type of file that sometimes reads less data than is
diff --git a/tests/test-largefiles-small-disk.t 
b/tests/test-largefiles-small-disk.t
--- a/tests/test-largefiles-small-disk.t
+++ b/tests/test-largefiles-small-disk.t
@@ -11,7 +11,7 @@ Test how largefiles abort in case the di
   > shutil.copyfileobj = copyfileobj
   > #
   > # this makes the rewritten code abort:
-  > def filechunkiter(f, size=65536, limit=None):
+  > def filechunkiter(f, size=131072, limit=None):
   > yield f.read(4)
   > raise IOError(errno.ENOSPC, os.strerror(errno.ENOSPC))
   > util.filechunkiter = filechunkiter
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 3 of 3 V3] changelog: disable delta chains

2016-10-13 Thread Pierre-Yves David

On 10/13/2016 09:44 PM, Gregory Szorc wrote:

# HG changeset patch
# User Gregory Szorc 
# Date 1476355827 -7200
#  Thu Oct 13 12:50:27 2016 +0200
# Node ID 231e6b5206857a809198f5535fac32a004686bf1
# Parent  aed87a8bed99b373eec5fb09dd2f76d166af59e8
changelog: disable delta chains


Theses are pushed, thanks.

Patch 1 inspired me a small change that should make you happy.

Cheers

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


[PATCH 1 of 2] revlog: make 'storedeltachains' a "public" attribute

2016-10-13 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1476404708 -7200
#  Fri Oct 14 02:25:08 2016 +0200
# Node ID e19eb107706e7210c3b359d66f5274911b181566
# Parent  b7a966ce89ed9c68867b05d89ae7d3ab4b085468
# EXP-Topic storedeltachains
revlog: make 'storedeltachains' a "public" attribute

The next changeset will make that attribute read by the changegroup packer. We
make it "public" beforehand.

diff --git a/mercurial/changelog.py b/mercurial/changelog.py
--- a/mercurial/changelog.py
+++ b/mercurial/changelog.py
@@ -267,7 +267,7 @@ class changelog(revlog.revlog):
 # Delta chains for changelogs tend to be very small because entries
 # tend to be small and don't delta well with each. So disable delta
 # chains.
-self._storedeltachains = False
+self.storedeltachains = False
 
 self._realopener = opener
 self._delayed = False
diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -297,7 +297,7 @@ class revlog(object):
 raise RevlogError(_("index %s unknown format %d")
   % (self.indexfile, fmt))
 
-self._storedeltachains = True
+self.storedeltachains = True
 
 self._io = revlogio()
 if self.version == REVLOGV0:
@@ -1471,7 +1471,7 @@ class revlog(object):
 textlen = len(text)
 
 # should we try to build a delta?
-if prev != nullrev and self._storedeltachains:
+if prev != nullrev and self.storedeltachains:
 tested = set()
 # This condition is true most of the time when processing
 # changegroup data into a generaldelta repo. The only time it
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 3 v2] repos: introduce '-R readonly:PATH' for doing local operations "read only"

2016-10-13 Thread Mads Kiilerich
# HG changeset patch
# User Mads Kiilerich 
# Date 1476402795 -7200
#  Fri Oct 14 01:53:15 2016 +0200
# Node ID 491da143c2f310da732c2e1005e7f8394134a51d
# Parent  24a7ccfb932b134da24e58817991943c8bbd63fa
repos: introduce '-R readonly:PATH' for doing local operations "read only"

When used as 'readonly:.', this is pretty much like if the repository was owned
by another user and the current user didn't have write access to anything in
.hg .

Using this feature will for example allow multiple simultaneous pushes,
pushes without phase changes, and will provide a "safe" way to run commands ...
assuming this and our use of VFS is complete and correct.

The existing "API" for repository types could use some cleanup - it requires
modules with special undefined duck typing. This patch seems to do what is
needed.

The existing VFS class hierarchy has a "readonlyvfs" class, but whatever it is,
it doesn't seem suitable for this use; it doesn't seem to be a reusable class
or mixin.

diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -31,6 +31,7 @@ from . import (
 merge as mergemod,
 node,
 phases,
+readonlyrepo,
 repoview,
 scmutil,
 sshpeer,
@@ -112,6 +113,7 @@ schemes = {
 'https': httppeer,
 'ssh': sshpeer,
 'static-http': statichttprepo,
+'readonly': lambda path: readonlyrepo,
 }
 
 def _peerlookup(path):
diff --git a/mercurial/readonlyrepo.py b/mercurial/readonlyrepo.py
new file mode 100644
--- /dev/null
+++ b/mercurial/readonlyrepo.py
@@ -0,0 +1,57 @@
+# readonlyrepo.py - a local repository class for mercurial that can't write
+# or lock the repository
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from __future__ import absolute_import
+
+import errno
+
+from .i18n import _
+from . import (
+localrepo,
+scmutil,
+util,
+)
+
+# created, not thrown yet
+readonlyexception = IOError(errno.EACCES, _('this is a "readonly" repository'))
+
+# this seems to be a necessary part of the repository type API
+islocal = localrepo.islocal
+
+class readonlyvfs(scmutil.vfs):
+"""A VFS that only can be called with read modes - writing will fail with
+an IO error as if the user didn't have write access"""
+
+def __call__(self, path, mode='r', *args, **kw):
+if mode not in ('r', 'rb'):
+raise readonlyexception
+return super(readonlyvfs, self).__call__(path, mode, *args, **kw)
+
+class readonlyrepo(localrepo.localrepository):
+"""A repository that is local but read only, as if the user didn't have
+file system write access."""
+
+def __init__(self, baseui, path=None, create=False):
+# we know the "scheme" for path is "readonly" but do not want to extend
+# the file/bundle hack in the "url" parser - just strip it here
+assert path.startswith('readonly:'), path
+path = path[len('readonly:'):]
+
+super(readonlyrepo, self).__init__(baseui, path=path, create=False)
+
+assert self.vfs.__class__ is scmutil.vfs
+self.vfs.__class__ = readonlyvfs
+assert self.wvfs.__class__ is scmutil.vfs
+self.wvfs.__class__ = readonlyvfs
+
+def lock(self, wait=True):
+raise readonlyexception
+
+def wlock(self, wait=True):
+raise readonlyexception
+
+def instance(ui, path, create):
+return readonlyrepo(ui, util.urllocalpath(path), create=False)
diff --git a/tests/test-phases-exchange.t b/tests/test-phases-exchange.t
--- a/tests/test-phases-exchange.t
+++ b/tests/test-phases-exchange.t
@@ -1197,25 +1197,27 @@ publish changesets as plain push does
   |
   ~
 
-  $ hg -R Upsilon push Pi -r 7
+  $ hg -R readonly:Upsilon push Pi -r 7
   pushing to Pi
   searching for changes
   no changes found
+  cannot lock source repo, skipping local public phase update
   [1]
   $ hgph Upsilon -r 'min(draft())'
-  o  8 draft a-F - b740e3e5c05d
+  o  2 draft a-C - 54acac6f23ab
   |
   ~
 
-  $ hg -R Upsilon push Pi -r 8
+  $ hg -R readonly:Upsilon push Pi -r 8
   pushing to Pi
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  cannot lock source repo, skipping local public phase update
 
   $ hgph Upsilon -r 'min(draft())'
-  o  9 draft a-G - 3e27b6f1eee1
+  o  2 draft a-C - 54acac6f23ab
   |
   ~
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 3 v2] cmdutil: satisfy expections in dirstateguard.__del__, even if __init__ fails

2016-10-13 Thread Mads Kiilerich
# HG changeset patch
# User Mads Kiilerich 
# Date 1476402795 -7200
#  Fri Oct 14 01:53:15 2016 +0200
# Node ID 426994acbf9c9b78aa6922a279dca4091b6508dc
# Parent  c0410814002f467c24ef07ce73850ba15b306f8e
cmdutil: satisfy expections in dirstateguard.__del__, even if __init__ fails

Python "delstructors" are terrible - this one because it assumed that __init__
had completed before it was called. That would not necessarily be the case if
the repository was read only or broken and saving the dirstate thus failed in
unexpected ways. That could give confusing warnings about missing '_active'
after failures.

To fix that, make sure all member variables are "declared" before doing
anything that possibly could fail. [Famous last words.]

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -3508,10 +3508,11 @@ class dirstateguard(object):
 
 def __init__(self, repo, name):
 self._repo = repo
+self._active = False
+self._closed = False
 self._suffix = '.backup.%s.%d' % (name, id(self))
 repo.dirstate.savebackup(repo.currenttransaction(), self._suffix)
 self._active = True
-self._closed = False
 
 def __del__(self):
 if self._active: # still active
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 3 v2] tests: add more test coverage of phase changes when pushing

2016-10-13 Thread Mads Kiilerich
# HG changeset patch
# User Mads Kiilerich 
# Date 1471734720 -7200
#  Sun Aug 21 01:12:00 2016 +0200
# Node ID 24a7ccfb932b134da24e58817991943c8bbd63fa
# Parent  426994acbf9c9b78aa6922a279dca4091b6508dc
tests: add more test coverage of phase changes when pushing

Prepare for test coverage of phase updates with future push --readonly option,
both with and without actually pushing changesets.

diff --git a/tests/test-phases-exchange.t b/tests/test-phases-exchange.t
--- a/tests/test-phases-exchange.t
+++ b/tests/test-phases-exchange.t
@@ -1182,10 +1182,40 @@ 2. Test that failed phases movement are 
   cannot lock source repo, skipping local public phase update
   [1]
   $ chmod -R +w .hg
-  $ hgph Upsilon
 
   $ cd ..
 
-  $ killdaemons.py
+#endif
 
-#endif
+Test that clone behaves like pull and doesn't
+publish changesets as plain push does
+
+  $ hg -R Upsilon phase -q --force --draft 2
+  $ hg clone -q Upsilon Pi -r 7
+  $ hgph Upsilon -r 'min(draft())'
+  o  2 draft a-C - 54acac6f23ab
+  |
+  ~
+
+  $ hg -R Upsilon push Pi -r 7
+  pushing to Pi
+  searching for changes
+  no changes found
+  [1]
+  $ hgph Upsilon -r 'min(draft())'
+  o  8 draft a-F - b740e3e5c05d
+  |
+  ~
+
+  $ hg -R Upsilon push Pi -r 8
+  pushing to Pi
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+
+  $ hgph Upsilon -r 'min(draft())'
+  o  9 draft a-G - 3e27b6f1eee1
+  |
+  ~
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 6 of 9 V6] bundle2: add `bookmarks` part handler

2016-10-13 Thread Pierre-Yves David



On 10/11/2016 06:25 PM, Stanislau Hlebik wrote:

# HG changeset patch
# User Stanislau Hlebik 
# Date 1476197535 25200
#  Tue Oct 11 07:52:15 2016 -0700
# Node ID b9e71247c1b68ce1fac7dd69cf26d106f88f9372
# Parent  f781756b8de11a6f3e7dd5fd6354e9778defd8c3
bundle2: add `bookmarks` part handler

Applies bookmarks part to the local repo. `processbookmarksmode` determines
how remote bookmarks are handled. They are either ignored ('ignore' mode),
diverged ('diverge' mode) or applied ('apply' mode).

diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -154,7 +154,9 @@
 import sys

 from .i18n import _
+from .node import hex
 from . import (
+bookmarks as bookmod,
 changegroup,
 error,
 obsolete,
@@ -287,13 +289,18 @@
 * a way to construct a bundle response when applicable.
 """

-def __init__(self, repo, transactiongetter, captureoutput=True):
+def __init__(self, repo, transactiongetter, captureoutput=True,
+ processbookmarksmode='ignore', explicitbookmarks=(),
+ remotepath=''):
 self.repo = repo
 self.ui = repo.ui
 self.records = unbundlerecords()
 self.gettransaction = transactiongetter
 self.reply = None
 self.captureoutput = captureoutput
+self.processbookmarksmode = processbookmarksmode
+self.explicitbookmarks = explicitbookmarks
+self.remotepath = remotepath


Hum, now that we see this change in practice, it seems a bit odd. The 
unbundle operation do not have business specific logic yet 
(pull/pushoperation does but they are higher level).


The best way here is probably to introduce a "input" attribut on the 
object (or "config" but the name is meh, or anything else good).


That input should probably be a simple dictionnary where higher order 
logic will be able to stick data to be used by part handler.


What do you think ?



 class TransactionUnavailable(RuntimeError):
 pass
@@ -1620,3 +1627,28 @@

 cache.write()
 op.ui.debug('applied %i hgtags fnodes cache entries\n' % count)
+
+@parthandler('bookmarks')
+def handlebookmarks(op, inpart):
+"""Applies bookmarks to the local repo.


"Applies" does not seems to be the best wording as some of the process 
mode do not apply anything.



+
+`processbookmarksmode` determines how remote bookmarks are handled. They 
are
+either ignored ('ignore' mode), diverged ('diverge' mode) or applied
+('apply' mode).
+"""


We should probably explain what use case each more is aimed at.


+
+bookmarks = {}
+bookmarks = bookmod.decodebookmarks(inpart.read())
+if op.processbookmarksmode == 'apply':
+for bookmark, node in bookmarks.items():
+if node:
+op.repo._bookmarks[bookmark] = node
+else:
+del op.repo._bookmarks[bookmark]
+op.repo._bookmarks.recordchange(op.gettransaction())


What is your plan regarding hooks execution here?



+elif op.processbookmarksmode == 'diverge':
+bookmod.updatefromremote(op.ui, op.repo, bookmarks,
+ op.remotepath, op.gettransaction,
+ explicit=op.explicitbookmarks,
+ srchex=hex)
+op.records.add('bookmarks', bookmarks)


How do you handle cases where the part exist multiple time in the bundle ?


cheers

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


Re: [PATCH 7 of 9 V6] exchange: getbundle `bookmarks` part generator

2016-10-13 Thread Pierre-Yves David



On 10/11/2016 06:25 PM, Stanislau Hlebik wrote:

# HG changeset patch
# User Stanislau Hlebik 
# Date 1476195835 25200
#  Tue Oct 11 07:23:55 2016 -0700
# Node ID 48e5db9c751c1eca19019bbc24de43f7cb3368e7
# Parent  b9e71247c1b68ce1fac7dd69cf26d106f88f9372
exchange: getbundle `bookmarks` part generator

This generator will be used during pull operation.


The change itself looks good to me. (you might want to add some details 
about how the creation of the part is triggered from the client if you 
want to make it easier to review, but that's perfectly fine as is).


Now that we have internal documentations, we will want to introduce a 
section about these bundle2 part and related bookmarkes exchange (and 
format).


The documentation lives in mercurial/help/internals/


diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -1672,6 +1672,21 @@
 if chunks:
 bundler.newpart('hgtagsfnodes', data=''.join(chunks))

+@getbundle2partsgenerator('bookmarks')
+def _getbundlebookmarkspart(bundler, repo, source, bundlecaps=None,
+b2caps=None, heads=None, common=None,
+**kwargs):
+if not kwargs.get('bookmarks'):
+return
+if 'bookmarks' not in b2caps:
+raise ValueError(
+_('bookmarks are requested but client is not capable '
+  'of receiving it'))
+
+bookmarks = _getbookmarks(repo, **kwargs)
+encodedbookmarks = bookmod.encodebookmarks(bookmarks)
+bundler.newpart('bookmarks', data=encodedbookmarks)
+
 def _getbookmarks(repo, **kwargs):
 """Returns list of bookmarks.

diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -220,7 +220,8 @@
  'bundlecaps': 'scsv',
  'listkeys': 'csv',
  'cg': 'boolean',
- 'cbattempted': 'boolean'}
+ 'cbattempted': 'boolean',
+ 'bookmarks': 'boolean'}


If you have the chance, put the closing '}' on its own line and use a 
trailing comma on the line you add. This will make the next guy life easier.


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


Re: [PATCH 4 of 9 V6] bookmarks: introduce binary encoding

2016-10-13 Thread Pierre-Yves David



On 10/11/2016 06:25 PM, Stanislau Hlebik wrote:

# HG changeset patch
# User Stanislau Hlebik 
# Date 1476195835 25200
#  Tue Oct 11 07:23:55 2016 -0700
# Node ID 718ed86a3698631077a087efaf668d70513056f5
# Parent  6f5a3300a5457c92eb09170a30c98328ebe3bcce
bookmarks: introduce binary encoding

Bookmarks binary encoding will be used for `bookmarks` bundle2 part.
The format is: <4 bytes - bookmark size, big-endian>
   <1 byte - 0 if node is empty 1 otherwise><20 bytes node>


CCing greg as our binary format overlord,

I'm not sure how useful it is to have the node to be optional. using 
nullid should be fine (and most stream/bundle will be compressed anyway.


This would give us the option to have the node+size first (as fixed 
width) then the bookmark name. Though ?


I do not thing it is necessary to point that the value is big-endian, we 
use big endian for all binary encoding.


Beside that, the change seems good. I've been tempted to advise for 
moving the encoding/decoding directly into the bundle2 part to benefit 
from the bundle2 utility to pack/unpack but it eventually felt more at 
home here.


I've some small comment inline for your consideration.


BookmarksEncodeError and BookmarksDecodeError maybe thrown if input is
incorrect.

diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py
--- a/mercurial/bookmarks.py
+++ b/mercurial/bookmarks.py
@@ -7,8 +7,10 @@

 from __future__ import absolute_import

+import StringIO
 import errno
 import os
+import struct

 from .i18n import _
 from .node import (
@@ -23,6 +25,77 @@
 util,
 )

+_NONEMPTYNODE = chr(1)
+_EMPTYNODE = chr(0)


I would use 'pack' directly here. Who know what awe-full thing around 
char and str python might be preparing for pytnon3.



+
+def _packbookmarksize(size):
+return struct.pack('>i', size)


Any reason we don't just inline this?


+
+def _unpackbookmarksize(stream):
+"""Returns 0 if stream is empty.
+"""
+
+expectedsize = struct.calcsize('>i')
+encodedbookmarksize = stream.read(expectedsize)
+if len(encodedbookmarksize) == 0:
+return 0
+if len(encodedbookmarksize) != expectedsize:
+raise error.BookmarksDecodeError(
+_('cannot decode bookmark size: '
+  'expected size: %d, actual size: %d') %
+(expectedsize, len(encodedbookmarksize)))
+return struct.unpack('>i', encodedbookmarksize)[0]


small nits, The bundle2 code have a lot of utility around reading and 
unpacking, it seems like it could be worthwhile to move this unpacking 
code directly in the part.



+def encodebookmarks(bookmarks):
+"""Encodes bookmark to node mapping to the byte string.
+
+Format: <4 bytes - bookmark size, big-endian>
+<1 byte - 0 if node is empty 1 otherwise><20 bytes node>
+Node may be 20 byte binary string, 40 byte hex string or empty


The part about 'Hex' is surprising is it still up to date.


+parts = []
+for bookmark, node in bookmarks.iteritems():
+encodedbookmarksize = _packbookmarksize(len(bookmark))
+parts.append(encodedbookmarksize)
+bookmark = encoding.fromlocal(bookmark)
+parts.append(bookmark)
+if node:
+if len(node) != 20 and len(node) != 40:
+raise error.BookmarksEncodeError()
+if len(node) == 40:
+node = bin(node)
+parts.append(_NONEMPTYNODE)
+parts.append(node)
+else:
+parts.append(_EMPTYNODE)
+return ''.join(parts)


We should probably have something a bit more subtle than 1 unique byte 
blob. bundle2 part can be fed an iterator yielding the lines one by one 
would be a good way to have this generation smoother.



+
+def decodebookmarks(buf):
+"""Decodes buffer into bookmark to node mapping.
+
+Node is either 20 bytes or empty.
+"""
+
+stream = StringIO.StringIO(buf)
+bookmarks = {}
+while True:
+bookmarksize = _unpackbookmarksize(stream)
+if not bookmarksize:
+break


Could we use 'while bookmark size' as an iteration value. A bare 'while 
True:' is a bit scary.



+bookmark = stream.read(bookmarksize)
+if len(bookmark) != bookmarksize:
+raise error.BookmarksDecodeError(
+'cannot decode bookmark: expected size: %d, '
+'actual size: %d' % (bookmarksize, len(bookmark)))
+bookmark = encoding.tolocal(bookmark)
+emptynode = stream.read(1)
+node = ''
+if emptynode != _EMPTYNODE:
+node = stream.read(20)
+bookmarks[bookmark] = node
+return bookmarks
+
 def _getbkfile(repo):
 """Hook so that extensions that mess with the store can hook bm storage.

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



--
Pierre-Yves David
___

Re: [PATCH 5 of 9 V6] bookmarks: add srchex param to updatefromremote

2016-10-13 Thread Pierre-Yves David



On 10/11/2016 06:25 PM, Stanislau Hlebik wrote:

# HG changeset patch
# User Stanislau Hlebik 
# Date 1476197429 25200
#  Tue Oct 11 07:50:29 2016 -0700
# Node ID f781756b8de11a6f3e7dd5fd6354e9778defd8c3
# Parent  718ed86a3698631077a087efaf668d70513056f5
bookmarks: add srchex param to updatefromremote


I do not understand what the purpose and effect of this changeset is. 
Can you elaborate a little ?




diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py
--- a/mercurial/bookmarks.py
+++ b/mercurial/bookmarks.py
@@ -508,11 +508,12 @@

 return None

-def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()):
+def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=(),
+ srchex=None):
 ui.debug("checking for updated bookmarks\n")
 localmarks = repo._bookmarks
 (addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same
- ) = compare(repo, remotemarks, localmarks, dsthex=hex)
+ ) = compare(repo, remotemarks, localmarks, srchex=srchex, dsthex=hex)

 status = ui.status
 warn = ui.warn
___
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 3 of 3] reposvfs: add a ward to check if locks are properly taken

2016-10-13 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1470672882 -7200
#  Mon Aug 08 18:14:42 2016 +0200
# Node ID e4af8c0de378cd1c7eddc83e086d9416f83755f5
# Parent  8d3ae769555bd7134bb70f31b16e67d17726b627
# EXP-Topic vfs.ward
reposvfs: add a ward to check if locks are properly taken

We use the 'ward' to check for the store lock when accessing file in '.hg/store'
for writing. This caught a couple of instance where the transaction was released
after the lock, we should probably have a dedicated checker for that case.

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -344,8 +344,14 @@ class localrepository(object):
 if inst.errno != errno.ENOENT:
 raise
 
+getsvfs = scmutil.vfs
+if (self.ui.configbool('devel', 'all-warnings') or
+self.ui.configbool('devel', 'check-locks')):
+def getsvfs(*args, **kwargs):
+kwargs['ward'] = self._getsvfsward()
+return scmutil.vfs(*args, **kwargs)
 self.store = store.store(
-self.requirements, self.sharedpath, scmutil.vfs)
+self.requirements, self.sharedpath, getsvfs)
 self.spath = self.store.path
 self.svfs = self.store.vfs
 self.sjoin = self.store.join
@@ -410,6 +416,23 @@ class localrepository(object):
   stacklevel=2)
 return checkvfs
 
+def _getsvfsward(self):
+"""build a ward for self.svfs"""
+rref = weakref.ref(self)
+def checksvfs(f, mode, atomictemp):
+repo = rref()
+if repo is None or not util.safehasattr(repo, '_lockref'):
+return
+if mode in ('r', 'rb'):
+return
+assert f.startswith(repo.sharedpath), (repo.path, f)
+# truncate name relative to the repository (.hg)
+relname = f[len(repo.sharedpath) + 1:]
+if repo._currentlock(repo._lockref) is None:
+repo.ui.develwarn('write with no lock: "%s"' % relname,
+  stacklevel=2)
+return checksvfs
+
 def close(self):
 self._writecaches()
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 3] vfs: add the possibility to have a "ward" to check vfs usage

2016-10-13 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1470323266 -7200
#  Thu Aug 04 17:07:46 2016 +0200
# Node ID 678c3cf029eceec20325928cff063ab71ea99761
# Parent  c0410814002f467c24ef07ce73850ba15b306f8e
# EXP-Topic vfs.ward
vfs: add the possibility to have a "ward" to check vfs usage

The function will be called anytime we open a file. The first usage of this
'ward' will be to check that lock are properly taken before accessing file.
Later we might use it to ensure we use the right vfs to access files, allowing
more vfs to be introduced.

We currently only apply the ward on 'open' operation. We will extend this to
other operations like copy, creation and removal later. The current readonlyvfs
seems to have the same shortcoming.

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -482,7 +482,8 @@ class vfs(abstractvfs):
 This class is used to hide the details of COW semantics and
 remote file access from higher level code.
 '''
-def __init__(self, base, audit=True, expandpath=False, realpath=False):
+def __init__(self, base, audit=True, expandpath=False, realpath=False,
+ ward=None):
 if expandpath:
 base = util.expandpath(base)
 if realpath:
@@ -491,6 +492,11 @@ class vfs(abstractvfs):
 self.mustaudit = audit
 self.createmode = None
 self._trustnlink = None
+# optional function to validate operation on file
+# intended to be user for developer checks.
+#
+# XXX should be call for other things than 'open'
+self._ward = ward
 
 @property
 def mustaudit(self):
@@ -552,6 +558,9 @@ class vfs(abstractvfs):
 if not text and "b" not in mode:
 mode += "b" # for that other OS
 
+if self._ward is not None:
+self._ward(f, mode, atomictemp)
+
 nlink = -1
 if mode not in ('r', 'rb'):
 dirname, basename = util.split(f)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 3] repovfs: add a ward to check if locks are properly taken

2016-10-13 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1471990626 -7200
#  Wed Aug 24 00:17:06 2016 +0200
# Node ID 8d3ae769555bd7134bb70f31b16e67d17726b627
# Parent  678c3cf029eceec20325928cff063ab71ea99761
# EXP-Topic vfs.ward
repovfs: add a ward to check if locks are properly taken

We use the 'ward' feature introduced in the previous email to check for locks
when accessing file in '.hg' for writing. Another changeset will add a 'ward'
for the store vfs (svfs).

This 'ward' system have caught an handful of locking issue that  has been fixed
in previous series. I expect another batch to be caught in third party
extensions.

We introduces two real exceptions from extensions 'blackbox.log' (because a lot 
of
read-only operations add entry to it), and 'last-email.txt' (because 'hg email'
is currently a read only operation and there is value to keep it this way).

In addition we are currently allowing bisect to operate outside of the lock
because the current code is a bit hard to get properly locked for now. Multiple
clean up have been made but there is still a couple of them to do and the freeze
is coming.

diff --git a/hgext/blackbox.py b/hgext/blackbox.py
--- a/hgext/blackbox.py
+++ b/hgext/blackbox.py
@@ -220,6 +220,7 @@ def reposetup(ui, repo):
 
 if util.safehasattr(ui, 'setrepo'):
 ui.setrepo(repo)
+repo._wlockfreeprefix.add('blackbox.log')
 
 @command('^blackbox',
 [('l', 'limit', 10, _('the number of events to show')),
diff --git a/hgext/journal.py b/hgext/journal.py
--- a/hgext/journal.py
+++ b/hgext/journal.py
@@ -69,6 +69,7 @@ def extsetup(ui):
 def reposetup(ui, repo):
 if repo.local():
 repo.journal = journalstorage(repo)
+repo._wlockfreeprefix.add('namejournal')
 
 def runcommand(orig, lui, repo, cmd, fullargs, *args):
 """Track the command line options for recording in the journal"""
diff --git a/hgext/patchbomb.py b/hgext/patchbomb.py
--- a/hgext/patchbomb.py
+++ b/hgext/patchbomb.py
@@ -110,6 +110,10 @@ def uisetup(ui):
 cmdutil.extraexport.append('pullurl')
 cmdutil.extraexportmap['pullurl'] = _addpullheader
 
+def reposetup(ui, repo):
+if not repo.local():
+return
+repo._wlockfreeprefix.add('last-email.txt')
 
 def prompt(ui, prompt, default=None, rest=':'):
 if default:
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -244,6 +244,25 @@ class localrepository(object):
 # only functions defined in module of enabled extensions are invoked
 featuresetupfuncs = set()
 
+# list of prefix for file which can be written without 'wlock'
+# Extensions should extend this list when needed
+_wlockfreeprefix = set([# We migh consider requiring 'wlock' for the next
+# two, but pretty much all the existing code assume
+# wlock is not needed so we keep them excluded for
+# now.
+'hgrc',
+'requires',
+# XXX cache is a complicatged business someone
+# should investigate this in depth at some point
+'cache/',
+# XXX shouldn't be dirstate covered by the wlock?
+'dirstate',
+# XXX bisect was still a bit too messy at the time
+# this changeset was introduced. Someone should fix
+# the remainig bit and drop this line
+'bisect.state',
+])
+
 def __init__(self, baseui, path=None, create=False):
 self.requirements = set()
 self.wvfs = scmutil.vfs(path, expandpath=True, realpath=True)
@@ -254,11 +273,15 @@ class localrepository(object):
 self.auditor = pathutil.pathauditor(self.root, self._checknested)
 self.nofsauditor = pathutil.pathauditor(self.root, self._checknested,
 realfs=False)
-self.vfs = scmutil.vfs(self.path)
-self.opener = self.vfs
 self.baseui = baseui
 self.ui = baseui.copy()
 self.ui.copy = baseui.copy # prevent copying repo configuration
+_vfsward = None
+if (self.ui.configbool('devel', 'all-warnings') or
+self.ui.configbool('devel', 'check-locks')):
+_vfsward = self._getvfsward()
+self.vfs = scmutil.vfs(self.path, ward=_vfsward)
+self.opener = self.vfs
 # A list of callback to shape the phase if no data were found.
 # Callback are in the form: func(repo, roots) --> processed root.
 # This list it to be filled by extension during repo setup
@@ -357,6 +380,36 @@ class localrepository(object):
 # generic mapping between names and nodes
 self.names = namespaces.namespaces()
 
+def _getvfsward(self):
+