Re: [PATCH 3 of 5] tags: cache `repo.changelog` access when checking tags nodes

2018-11-21 Thread Pulkit Goyal
On Tue, Nov 20, 2018 at 10:23 PM Boris Feld  wrote:

> # HG changeset patch
> # User Boris Feld 
> # Date 1542710295 0
> #  Tue Nov 20 10:38:15 2018 +
> # Node ID 1ad7353bec2584a53f2bb4fbca44310fa827f2d0
> # Parent  7760b12bd4fb467f4fb7e4d0d5094fc324f30f49
> # EXP-Topic perf-tags
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r
> 1ad7353bec25
> tags: cache `repo.changelog` access when checking tags nodes
>
> The tags reading process checks if the nodes referenced in tags exist.
> Caching
> the access to `repo.changelog` provides a large speedup for repositories
> with
> many tags.
>
> before: ! wall 0.393464 comb 0.39 user 0.33 sys 0.06 (median
> of 25)
> after:  ! wall 0.267711 comb 0.27 user 0.21 sys 0.06 (median
> of 38)
>

Can you please add the perf command of which these results are in this
patch also?
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH STABLE] tests: stabilize the recent checkexec changes on Windows

2018-11-21 Thread Yuya Nishihara
On Tue, 20 Nov 2018 18:49:01 -0500, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison 
> # Date 1542757639 18000
> #  Tue Nov 20 18:47:19 2018 -0500
> # Branch stable
> # Node ID 25b7c4cb5de1593e16bbd7a7dafbd28baa743995
> # Parent  bd0874977a5e5921f7f8615f2eb96d267f641c2e
> tests: stabilize the recent checkexec changes on Windows

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


Re: [PATCH 3 of 7 V4] sparse-revlog: add a `index_segment_span` function in C

2018-11-21 Thread Yuya Nishihara
On Tue, 20 Nov 2018 21:44:34 +0100, Boris Feld wrote:
> # HG changeset patch
> # User Boris Feld 
> # Date 1541785396 -3600
> #  Fri Nov 09 18:43:16 2018 +0100
> # Node ID 5bb00d137c14d311c91c7a4f32f58378cd9195ec
> # Parent  8863dc1f7d078827708d178bbbfee5519b4c9b0f
> # EXP-Topic sparse-perf
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
> 5bb00d137c14
> sparse-revlog: add a `index_segment_span` function in C
> 
> We are about to implement a native version of `slicechunktodensity`. For
> clarity, we introduce the helper functions first. This new function provides
> an efficient way to retrieve some of the information needed by
> `slicechunktodensity`.
> 
> diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c
> --- a/mercurial/cext/revlog.c
> +++ b/mercurial/cext/revlog.c
> @@ -1068,6 +1068,27 @@ bail:
>   return NULL;
>  }
>  
> +static inline int64_t
> +index_segment_span(indexObject *self, Py_ssize_t start_rev, Py_ssize_t 
> end_rev)
> +{
> + int64_t start_offset;
> + int64_t end_offset;
> + int end_size;
> + start_offset = index_get_start(self, start_rev);
> + if (start_offset < 0) {
> + return -1;
> + }
> + end_offset = index_get_start(self, end_rev);
> + if (end_offset < 0) {
> + return -1;
> + }
> + end_size = index_get_length(self, end_rev);
> + if (end_size < 0) {
> + return -1;
> + }
> + return (end_offset - start_offset) + (int64_t)end_size;

Nit: maybe raise error if end_offset - start_offset) + (int64_t)end_size < 0 ?

Other than that, the series looks good to me.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 7 V4] sparse-revlog: add a `index_get_start` function in C

2018-11-21 Thread Yuya Nishihara
On Tue, 20 Nov 2018 21:44:32 +0100, Boris Feld wrote:
> # HG changeset patch
> # User Boris Feld 
> # Date 1542725358 0
> #  Tue Nov 20 14:49:18 2018 +
> # Node ID 60a55da39befa4996c1a88ca6f663765ea143ef2
> # Parent  337a389953366f059f2cb88129031ba3e67e0bbc
> # EXP-Topic sparse-perf
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
> 60a55da39bef
> sparse-revlog: add a `index_get_start` function in C

> diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c
> --- a/mercurial/cext/revlog.c
> +++ b/mercurial/cext/revlog.c
> @@ -185,6 +185,46 @@ static inline int index_get_parents(inde
>   return 0;
>  }
>  
> +static inline int64_t index_get_start(indexObject *self, Py_ssize_t rev)

I meant "int index_get_start(*self, rev, *offset)" just like 
index_get_parents(),
but this is also good.

> +{
> + uint64_t offset;
> + if (rev >= self->length) {
> + PyObject *tuple;
> + PyObject *pylong;
> + unsigned PY_LONG_LONG tmp;
> + tuple = PyList_GET_ITEM(self->added, rev - self->length);
> + pylong = PyTuple_GET_ITEM(tuple, 0);
> +#ifndef IS_PY3K
> + if (PyInt_Check(pylong)) {
> + long tmp2 = PyInt_AsLong(pylong);
> + if (tmp2 < 0) {
> + return -1;
> + }
> + tmp = (unsigned PY_LONG_LONG)tmp2;
> + } else {
> +#endif
> + tmp = PyLong_AsUnsignedLongLong(pylong);
> + if (tmp == (unsigned PY_LONG_LONG) - 1) {
> + return -1;
> + }
> +
> +#ifndef IS_PY3K
> + }
> +#endif
> + offset = (uint64_t)tmp;

Sigh, PyLong API is so inconsistent on Python 2. Let's switch to
PyLong_AsLongLong(), which can handle PyInt as well. I think it's
okay to raise OverflowError if offset >= 1 << (63 - 16).

FWIW, PyLong_AsUnsignedLongLong() of Python 2 would raise BadInternalCall
if non-long type were passed.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 2 of 7 V4] sparse-revlog: add a `index_get_length` function in C

2018-11-21 Thread Yuya Nishihara
On Tue, 20 Nov 2018 21:44:33 +0100, Boris Feld wrote:
> # HG changeset patch
> # User Boris Feld 
> # Date 1541785378 -3600
> #  Fri Nov 09 18:42:58 2018 +0100
> # Node ID 8863dc1f7d078827708d178bbbfee5519b4c9b0f
> # Parent  60a55da39befa4996c1a88ca6f663765ea143ef2
> # EXP-Topic sparse-perf
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
> 8863dc1f7d07
> sparse-revlog: add a `index_get_length` function in C
> 
> We are about to implement a native version of `slicechunktodensity`. For
> clarity, we introduce the helper functions first. This new function provides
> an efficient way to retrieve some of the information needed by
> `slicechunktodensity`.
> 
> diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c
> --- a/mercurial/cext/revlog.c
> +++ b/mercurial/cext/revlog.c
> @@ -225,6 +225,44 @@ static inline int64_t index_get_start(in
>   return (int64_t)(offset >> 16);
>  }
>  
> +static inline int index_get_length(indexObject *self, Py_ssize_t rev)
> +{
> + if (rev >= self->length) {
> + PyObject *tuple;
> + PyObject *pylong;
> + unsigned PY_LONG_LONG tmp;
> + tuple = PyList_GET_ITEM(self->added, rev - self->length);
> + pylong = PyTuple_GET_ITEM(tuple, 1);
> +#ifndef IS_PY3K
> + if (PyInt_Check(pylong)) {
> + long tmp2 = PyInt_AsLong(pylong);
> + if (tmp2 < 0) {
> + return -1;

Nit: exception wouldn't be set if the value was actually -1.

> + }
> + tmp = (unsigned PY_LONG_LONG)tmp2;
> + } else {
> +#endif
> + tmp = PyLong_AsUnsignedLongLong(pylong);
> + if (tmp == (unsigned PY_LONG_LONG) - 1) {
> + return -1;
> + }

IIUC, we can simply use PyInt_AsLong() here since a valid length should be
in int range. PyInt_AsLong is aliased to PyLong_AsLong on Python 3.

To be clear, what I have in mind is something like this:

  long ret = PyInt_AsLong(PyTuple_GET_ITEM(tuple, 1));
  if (ret == -1 && PyErr_Occurred())
  return -1;
  if (ret < 0 || ret > (long)INT_MAX)
  set overflow error and return -1;

> + if (tmp > INT_MAX) {
> + PyErr_Format(PyExc_OverflowError,
> +  "revlog entry size too large (%llu)",
> +  (long long)tmp);
> + return -1;
> + }
> + return (int)tmp;
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: D5287: py3: use node.hex(m.digest()) instead of m.hexdigest()

2018-11-21 Thread Yuya Nishihara
>   > hgext/remotefilelog/basepack.py:472: import 'node' from line 12 shadowed 
> by loop variable
>   
>   Looks like a False positive/negative.

Might be, but it's better to not shadow global names by local ones.

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


D5287: py3: use node.hex(m.digest()) instead of m.hexdigest()

2018-11-21 Thread yuja (Yuya Nishihara)
yuja added a comment.


  >   > hgext/remotefilelog/basepack.py:472: import 'node' from line 12 
shadowed by loop variable
  >   
  >   Looks like a False positive/negative.
  
  Might be, but it's better to not shadow global names by local ones.
  
  Queued, thanks.

REPOSITORY
  rHG Mercurial

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

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


D5287: py3: use node.hex(m.digest()) instead of m.hexdigest()

2018-11-21 Thread pulkit (Pulkit Goyal)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG9fcf8084ada8: py3: use node.hex(m.digest()) instead of 
m.hexdigest() (authored by pulkit, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5287?vs=12574&id=12575

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

AFFECTED FILES
  hgext/fastannotate/context.py
  hgext/largefiles/lfcommands.py
  hgext/lfs/blobstore.py
  hgext/remotefilelog/basepack.py

CHANGE DETAILS

diff --git a/hgext/remotefilelog/basepack.py b/hgext/remotefilelog/basepack.py
--- a/hgext/remotefilelog/basepack.py
+++ b/hgext/remotefilelog/basepack.py
@@ -10,6 +10,7 @@
 
 from mercurial.i18n import _
 from mercurial import (
+node as nodemod,
 policy,
 pycompat,
 util,
@@ -412,7 +413,7 @@
 return
 
 try:
-sha = self.sha.hexdigest()
+sha = nodemod.hex(self.sha.digest())
 self.packfp.close()
 self.writeindex()
 
diff --git a/hgext/lfs/blobstore.py b/hgext/lfs/blobstore.py
--- a/hgext/lfs/blobstore.py
+++ b/hgext/lfs/blobstore.py
@@ -20,6 +20,7 @@
 from mercurial import (
 encoding,
 error,
+node,
 pathutil,
 pycompat,
 url as urlmod,
@@ -156,7 +157,7 @@
 fp.write(chunk)
 sha256.update(chunk)
 
-realoid = sha256.hexdigest()
+realoid = node.hex(sha256.digest())
 if realoid != oid:
 raise LfsCorruptionError(_('corrupt remote lfs object: %s')
  % oid)
@@ -206,7 +207,7 @@
 # Don't abort if corruption is detected, because `hg verify` will
 # give more useful info about the corruption- simply don't add the
 # hardlink.
-if verify or hashlib.sha256(blob).hexdigest() == oid:
+if verify or node.hex(hashlib.sha256(blob).digest()) == oid:
 self.ui.note(_('lfs: found %s in the usercache\n') % oid)
 lfutil.link(self.cachevfs.join(oid), self.vfs.join(oid))
 else:
@@ -230,7 +231,7 @@
 for chunk in util.filechunkiter(fp, size=1048576):
 sha256.update(chunk)
 
-return oid == sha256.hexdigest()
+return oid == node.hex(sha256.digest())
 
 def has(self, oid):
 """Returns True if the local blobstore contains the requested blob,
@@ -587,7 +588,7 @@
 return reduced.values()
 
 def _verify(oid, content):
-realoid = hashlib.sha256(content).hexdigest()
+realoid = node.hex(hashlib.sha256(content).digest())
 if realoid != oid:
 raise LfsCorruptionError(_('detected corrupt lfs object: %s') % oid,
  hint=_('run hg verify'))
diff --git a/hgext/largefiles/lfcommands.py b/hgext/largefiles/lfcommands.py
--- a/hgext/largefiles/lfcommands.py
+++ b/hgext/largefiles/lfcommands.py
@@ -240,7 +240,7 @@
 # largefile was modified, update standins
 m = hashlib.sha1('')
 m.update(ctx[f].data())
-hash = m.hexdigest()
+hash = node.hex(m.digest())
 if f not in lfiletohash or lfiletohash[f] != hash:
 rdst.wwrite(f, ctx[f].data(), ctx[f].flags())
 executable = 'x' in ctx[f].flags()
diff --git a/hgext/fastannotate/context.py b/hgext/fastannotate/context.py
--- a/hgext/fastannotate/context.py
+++ b/hgext/fastannotate/context.py
@@ -138,7 +138,7 @@
 (k, getattr(diffopts, k))
 for k in mdiff.diffopts.defaults
 ))
-return hashlib.sha1(diffoptstr).hexdigest()[:6]
+return node.hex(hashlib.sha1(diffoptstr).digest())[:6]
 
 _defaultdiffopthash = hashdiffopts(mdiff.defaultopts)
 



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


Re: [PATCH 4 of 5] extensions: add "uipopulate" hook, called per instance, not per process

2018-11-21 Thread Yuya Nishihara
On Sun, 18 Nov 2018 23:19:20 +0900, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1542024651 -32400
> #  Mon Nov 12 21:10:51 2018 +0900
> # Node ID 1e1427e07940f57d4146c38a0757e5104a88985c
> # Parent  7b0e4efc0a7140a3d6f0814214e0c2bfa6c60acf
> extensions: add "uipopulate" hook, called per instance, not per process

> +Ui instance setup
> +-
> +
> +The optional ``uipopulate`` is called for each ``ui`` instance after
> +configuration is loaded, where extensions can set up additional ui members,
> +update configuration by ``ui.setconfig()``, and extend the class dynamically.
> +
> +Typically there are three ``ui`` instances involved in command execution:
> +
> +``req.ui`` (or ``repo.baseui``)
> +Only system and user configurations are loaded into it.
> +``lui``
> +Local repository configuration is loaded as well. This will be used at
> +early dispatching stage where a repository isn't available.
> +``repo.ui``
> +The fully-loaded ``ui`` used after a repository is instantiated. This
> +will be created from the ``req.ui`` per repository.
> +
> +Be aware that the ``req.ui`` wouldn't see local repository configuration,
> +and the ``repo.ui`` will be copied from the base ``req.ui`` *after*
> +``uipopulate`` is called. Use ``reposetup`` to set up ``repo.ui`` instance
> +with repository-local configuration.

I'll send V2 which will simply call uipopulate(repo.ui) after repo/hgrc is
loaded. That seems less error-prone.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 5 V2] ui: unify argument name of ui.log()

2018-11-21 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1541926763 -32400
#  Sun Nov 11 17:59:23 2018 +0900
# Node ID 84a17834f4aa3bafba00b1b448d1a90dadd6d9e7
# Parent  96d5d57ab30e831b11e48f92936c3ebcfb3e7510
ui: unify argument name of ui.log()

It's called an "event" in both blackbox and logtoprocess.

diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -1709,10 +1709,10 @@ class ui(object):
 '''exists only so low-level modules won't need to import scmutil'''
 return scmutil.progress(self, topic, unit, total)
 
-def log(self, service, *msg, **opts):
+def log(self, event, *msg, **opts):
 '''hook for logging facility extensions
 
-service should be a readily-identifiable subsystem, which will
+event should be a readily-identifiable subsystem, which will
 allow filtering.
 
 *msg should be a newline-terminated format string to log, and
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 5 V2] logtoprocess: extract logger class from ui wrapper

2018-11-21 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1541925918 -32400
#  Sun Nov 11 17:45:18 2018 +0900
# Node ID 96d5d57ab30e831b11e48f92936c3ebcfb3e7510
# Parent  1a6bb5a85e3055d745d83e72fe17f3a6a8a13f63
logtoprocess: extract logger class from ui wrapper

It provides the same interface as the blackboxlogger. The ui wrapper will
be removed shortly.

diff --git a/hgext/logtoprocess.py b/hgext/logtoprocess.py
--- a/hgext/logtoprocess.py
+++ b/hgext/logtoprocess.py
@@ -38,6 +38,7 @@ import os
 
 from mercurial import (
 pycompat,
+util,
 )
 from mercurial.utils import (
 procutil,
@@ -49,27 +50,50 @@ from mercurial.utils import (
 # leave the attribute unspecified.
 testedwith = 'ships-with-hg-core'
 
+class processlogger(object):
+"""Map log events to external commands
+
+Arguments are passed on as environment variables.
+"""
+
+def __init__(self, ui):
+self._scripts = dict(ui.configitems(b'logtoprocess'))
+
+def tracked(self, event):
+return bool(self._scripts.get(event))
+
+def log(self, ui, event, msg, opts):
+script = self._scripts.get(event)
+if not script:
+return
+env = {
+b'EVENT': event,
+b'HGPID': os.getpid(),
+b'MSG1': msg[0] % msg[1:],
+}
+# keyword arguments get prefixed with OPT_ and uppercased
+env.update((b'OPT_%s' % key.upper(), value)
+   for key, value in pycompat.byteskwargs(opts).items())
+fullenv = procutil.shellenviron(env)
+procutil.runbgcommand(script, fullenv, shell=True)
+
 def uisetup(ui):
 
 class logtoprocessui(ui.__class__):
-def log(self, event, *msg, **opts):
-"""Map log events to external commands
-
-Arguments are passed on as environment variables.
+def __init__(self, src=None):
+super(logtoprocessui, self).__init__(src)
+if src and r'_ltplogger' in src.__dict__:
+self._ltplogger = src._ltplogger
 
-"""
-script = self.config('logtoprocess', event)
-if script:
-env = {
-b'EVENT': event,
-b'HGPID': os.getpid(),
-b'MSG1': msg[0] % msg[1:],
-}
-# keyword arguments get prefixed with OPT_ and uppercased
-env.update((b'OPT_%s' % key.upper(), value)
-   for key, value in 
pycompat.byteskwargs(opts).items())
-fullenv = procutil.shellenviron(env)
-procutil.runbgcommand(script, fullenv, shell=True)
+# trick to initialize logger after configuration is loaded, which
+# can be replaced later with processlogger(ui) in uisetup(), where
+# both user and repo configurations should be available.
+@util.propertycache
+def _ltplogger(self):
+return processlogger(self)
+
+def log(self, event, *msg, **opts):
+self._ltplogger.log(self, event, msg, opts)
 return super(logtoprocessui, self).log(event, *msg, **opts)
 
 # Replace the class for this instance and all clones created from it:
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 5 V2] hgweb: load globally-enabled extensions explicitly

2018-11-21 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1542449505 -32400
#  Sat Nov 17 19:11:45 2018 +0900
# Node ID 39c91c2915f3452039109d182c91c8082aabc81a
# Parent  84a17834f4aa3bafba00b1b448d1a90dadd6d9e7
hgweb: load globally-enabled extensions explicitly

Before, extensions were loaded as a side effect of hg.repository() if the
hgweb was executed as a CGI/WSGI. I want to make it explicit so that another
ui hook can be inserted after extensions.loadall().

diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -22,6 +22,7 @@ from .common import (
 from .. import (
 encoding,
 error,
+extensions,
 formatter,
 hg,
 hook,
@@ -212,6 +213,7 @@ class hgweb(object):
 u = baseui.copy()
 else:
 u = uimod.ui.load()
+extensions.loadall(u)
 r = hg.repository(u, repo)
 else:
 # we trust caller to give us a private copy
diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py
--- a/mercurial/hgweb/hgwebdir_mod.py
+++ b/mercurial/hgweb/hgwebdir_mod.py
@@ -30,6 +30,7 @@ from .. import (
 configitems,
 encoding,
 error,
+extensions,
 hg,
 profiling,
 pycompat,
@@ -268,6 +269,9 @@ class hgwebdir(object):
 self.lastrefresh = 0
 self.motd = None
 self.refresh()
+if not baseui:
+# set up environment for new ui
+extensions.loadall(self.ui)
 
 def refresh(self):
 if self.ui:
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 5 V2] extensions: add "uipopulate" hook, called per instance, not per process

2018-11-21 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1542024651 -32400
#  Mon Nov 12 21:10:51 2018 +0900
# Node ID 9e8a18bf900b65f91f1cb9b9e65bb9e654fa3dd8
# Parent  39c91c2915f3452039109d182c91c8082aabc81a
extensions: add "uipopulate" hook, called per instance, not per process

In short, this is the "reposetup" function for ui. It allows us to modify
ui attributes without extending ui.__class__. Before, the only way to do
that was to abuse the config dictionary, which is copied across ui instances.

See the next patch for usage example.

diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py
--- a/mercurial/chgserver.py
+++ b/mercurial/chgserver.py
@@ -246,6 +246,10 @@ def _loadnewui(srcui, args):
 rpath = options['repository']
 path, newlui = dispatch._getlocal(newui, rpath, wd=cwd)
 
+extensions.populateui(newui)
+if newui is not newlui:
+extensions.populateui(newlui)
+
 return (newui, newlui)
 
 class channeledsystem(object):
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -866,6 +866,9 @@ def _dispatch(req):
 # Check abbreviation/ambiguity of shell alias.
 shellaliasfn = _checkshellalias(lui, ui, args)
 if shellaliasfn:
+# no additional configs will be set, set up the ui instances
+for ui_ in uis:
+extensions.populateui(ui_)
 return shellaliasfn()
 
 # check for fallback encoding
@@ -948,6 +951,10 @@ def _dispatch(req):
 for ui_ in uis:
 ui_.disablepager()
 
+# configs are fully loaded, set up the ui instances
+for ui_ in uis:
+extensions.populateui(ui_)
+
 if options['version']:
 return commands.version_(ui)
 if options['help']:
diff --git a/mercurial/extensions.py b/mercurial/extensions.py
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -405,6 +405,25 @@ def afterloaded(extension, callback):
 else:
 _aftercallbacks.setdefault(extension, []).append(callback)
 
+def populateui(ui):
+"""Run extension hooks on the given ui to populate additional members,
+extend the class dynamically, etc.
+
+This will be called after the configuration is loaded, and/or extensions
+are loaded. In general, it's once per ui instance, but in command-server
+and hgweb, this may be called more than once with the same ui.
+"""
+for name, mod in extensions(ui):
+hook = getattr(mod, 'uipopulate', None)
+if not hook:
+continue
+try:
+hook(ui)
+except Exception as inst:
+ui.traceback(force=True)
+ui.warn(_('*** failed to populate ui by extension %s: %s\n')
+% (name, stringutil.forcebytestr(inst)))
+
 def bind(func, *args):
 '''Partial function application
 
diff --git a/mercurial/help/internals/extensions.txt 
b/mercurial/help/internals/extensions.txt
--- a/mercurial/help/internals/extensions.txt
+++ b/mercurial/help/internals/extensions.txt
@@ -183,6 +183,29 @@ Command table setup
 After ``extsetup``, the ``cmdtable`` is copied into the global command table
 in Mercurial.
 
+Ui instance setup
+-
+
+The optional ``uipopulate`` is called for each ``ui`` instance after
+configuration is loaded, where extensions can set up additional ui members,
+update configuration by ``ui.setconfig()``, and extend the class dynamically.
+
+Typically there are three ``ui`` instances involved in command execution:
+
+``req.ui`` (or ``repo.baseui``)
+Only system and user configurations are loaded into it.
+``lui``
+Local repository configuration is loaded as well. This will be used at
+early dispatching stage where a repository isn't available.
+``repo.ui``
+The fully-loaded ``ui`` used after a repository is instantiated. This
+will be created from the ``req.ui`` per repository.
+
+In command server and hgweb, this may be called more than once for the same
+``ui`` instance.
+
+(New in Mercurial 4.9)
+
 Repository setup
 
 
@@ -304,7 +327,8 @@ uisetup
   a change made here will be visible by other extensions during ``extsetup``.
 * Monkeypatches or function wraps (``extensions.wrapfunction``) of ``dispatch``
   module members
-* Setup of ``pre-*`` and ``post-*`` hooks
+* Set up ``pre-*`` and ``post-*`` hooks. (DEPRECATED. ``uipopulate`` is
+  preferred on Mercurial 4.9 and later.)
 * ``pushkey`` setup
 
 extsetup
@@ -314,9 +338,17 @@ extsetup
 * Add a global option to all commands
 * Extend revsets
 
+uipopulate
+--
+
+* Modify ``ui`` instance attributes and configuration variables.
+* Changes to ``ui.__class__`` per instance.
+* Set up all hooks per scoped configuration.
+
 reposetup
 -
 
-* All hooks but ``pre-*`` and ``post-*``
+* Set up all hooks but ``pre-*`` and ``post-*``. (DEPRECATED. ``uipopulate`` is
+  preferred on Mercurial 4.9 and later.)
 * Modi

[PATCH 5 of 5 V2] ui: manage logger instances and event filtering by core ui

2018-11-21 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1541927313 -32400
#  Sun Nov 11 18:08:33 2018 +0900
# Node ID a580ee2c7ef735dfc0efb69a30ec1482576ea1df
# Parent  9e8a18bf900b65f91f1cb9b9e65bb9e654fa3dd8
ui: manage logger instances and event filtering by core ui

The setup code in blackbox needs more tweaks since it has lots of black
magics. I'll fix them by follow-up patches.

To be clear, the goal of this series is to provide a proper way for command
server to install its own logger. I need it to debug in-memory repository
cache.

diff --git a/hgext/blackbox.py b/hgext/blackbox.py
--- a/hgext/blackbox.py
+++ b/hgext/blackbox.py
@@ -53,7 +53,6 @@ from mercurial import (
 pycompat,
 registrar,
 ui as uimod,
-util,
 )
 from mercurial.utils import (
 dateutil,
@@ -147,9 +146,6 @@ class blackboxlogger(object):
 
 def log(self, ui, event, msg, opts):
 global _lastlogger
-if not self.tracked(event):
-return
-
 if self._bbvfs:
 _lastlogger = self
 elif _lastlogger and _lastlogger._bbvfs:
@@ -201,33 +197,20 @@ class blackboxlogger(object):
 
 def wrapui(ui):
 class blackboxui(ui.__class__):
-def __init__(self, src=None):
-super(blackboxui, self).__init__(src)
-if src and r'_bblogger' in src.__dict__:
-self._bblogger = src._bblogger
-
-# trick to initialize logger after configuration is loaded, which
-# can be replaced later with blackboxlogger(ui) in uisetup(), where
-# both user and repo configurations should be available.
-@util.propertycache
-def _bblogger(self):
-return blackboxlogger(self)
-
 def debug(self, *msg, **opts):
 super(blackboxui, self).debug(*msg, **opts)
 if self.debugflag:
 self.log('debug', '%s', ''.join(msg))
 
-def log(self, event, *msg, **opts):
-super(blackboxui, self).log(event, *msg, **opts)
-self._bblogger.log(self, event, msg, opts)
-
 ui.__class__ = blackboxui
 uimod.ui = blackboxui
 
 def uisetup(ui):
 wrapui(ui)
 
+def uipopulate(ui):
+ui.setlogger(b'blackbox', blackboxlogger(ui))
+
 def reposetup(ui, repo):
 # During 'hg pull' a httppeer repo is created to represent the remote repo.
 # It doesn't have a .hg directory to put a blackbox in, so we don't do
@@ -235,7 +218,10 @@ def reposetup(ui, repo):
 if not repo.local():
 return
 
-logger = getattr(ui, '_bblogger', None)
+# Since blackbox.log is stored in the repo directory, the logger should be
+# instantiated per repository.
+logger = blackboxlogger(ui)
+ui.setlogger(b'blackbox', logger)
 if logger:
 logger.setrepo(repo)
 
diff --git a/hgext/logtoprocess.py b/hgext/logtoprocess.py
--- a/hgext/logtoprocess.py
+++ b/hgext/logtoprocess.py
@@ -38,7 +38,6 @@ import os
 
 from mercurial import (
 pycompat,
-util,
 )
 from mercurial.utils import (
 procutil,
@@ -63,9 +62,7 @@ class processlogger(object):
 return bool(self._scripts.get(event))
 
 def log(self, ui, event, msg, opts):
-script = self._scripts.get(event)
-if not script:
-return
+script = self._scripts[event]
 env = {
 b'EVENT': event,
 b'HGPID': os.getpid(),
@@ -77,24 +74,5 @@ class processlogger(object):
 fullenv = procutil.shellenviron(env)
 procutil.runbgcommand(script, fullenv, shell=True)
 
-def uisetup(ui):
-
-class logtoprocessui(ui.__class__):
-def __init__(self, src=None):
-super(logtoprocessui, self).__init__(src)
-if src and r'_ltplogger' in src.__dict__:
-self._ltplogger = src._ltplogger
-
-# trick to initialize logger after configuration is loaded, which
-# can be replaced later with processlogger(ui) in uisetup(), where
-# both user and repo configurations should be available.
-@util.propertycache
-def _ltplogger(self):
-return processlogger(self)
-
-def log(self, event, *msg, **opts):
-self._ltplogger.log(self, event, msg, opts)
-return super(logtoprocessui, self).log(event, *msg, **opts)
-
-# Replace the class for this instance and all clones created from it:
-ui.__class__ = logtoprocessui
+def uipopulate(ui):
+ui.setlogger(b'logtoprocess', processlogger(ui))
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -235,6 +235,7 @@ class ui(object):
 self._fmsgout = src._fmsgout
 self._fmsgerr = src._fmsgerr
 self._finoutredirected = src._finoutredirected
+self._loggers = src._loggers.copy()
 self.pageractive = src.pageractive
 self._disablepager = src._disablepager
 self._tweaked = src._tweaked
@@ -263,6 +264,7 @@ class ui(object):
 self._fmsgout 

D5291: branchmap: build the revbranchcache._namesreverse() only when required

2018-11-21 Thread pulkit (Pulkit Goyal)
pulkit created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  On big repositories with a lot of named branches and that also increasing over
  time, building of this dict can be expensive and shows up in profile.
  
  For our internal repository, this saves ~0.05 seconds.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/branchmap.py

CHANGE DETAILS

diff --git a/mercurial/branchmap.py b/mercurial/branchmap.py
--- a/mercurial/branchmap.py
+++ b/mercurial/branchmap.py
@@ -397,13 +397,13 @@
 self._names = []
 self._rbcnamescount = len(self._names) # number of names read at
# _rbcsnameslen
-self._namesreverse = dict((b, r) for r, b in enumerate(self._names))
+self._namesreverse = None
 
 def _clear(self):
 self._rbcsnameslen = 0
 del self._names[:]
 self._rbcnamescount = 0
-self._namesreverse.clear()
+self._namesreverse = None
 self._rbcrevslen = len(self._repo.changelog)
 self._rbcrevs = bytearray(self._rbcrevslen * _rbcrecsize)
 
@@ -453,6 +453,8 @@
 """Retrieve branch info from changelog and update _rbcrevs"""
 changelog = self._repo.changelog
 b, close = changelog.branchinfo(rev)
+if self._namesreverse is None:
+self._namesreverse = dict((b, r) for r, b in 
enumerate(self._names))
 if b in self._namesreverse:
 branchidx = self._namesreverse[b]
 else:
@@ -467,6 +469,8 @@
 
 def setdata(self, branch, rev, node, close):
 """add new data information to the cache"""
+if self._namesreverse is None:
+self._namesreverse = dict((b, r) for r, b in 
enumerate(self._names))
 if branch in self._namesreverse:
 branchidx = self._namesreverse[branch]
 else:



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


Re: D5288: tests: make test-alias.t pass with re2

2018-11-21 Thread Yuya Nishihara
>   Thanks. FWIW, re2 options allow to choose an encoding which is latin1 or 
> utf8 (https://github.com/google/re2/blob/master/re2/re2.h#L609). Presumably 
> latin1 means that "." matches a byte, which would seem more compatible with 
> re, but python bindings don't provide the ability to choose this encoding.

Indeed. We could pass in a fat unicode array (i.e. each byte as latin-1 char)
to re2, but that would sacrifice the performance.

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


D5288: tests: make test-alias.t pass with re2

2018-11-21 Thread yuja (Yuya Nishihara)
yuja added a comment.


  >   Thanks. FWIW, re2 options allow to choose an encoding which is latin1 or 
utf8 (https://github.com/google/re2/blob/master/re2/re2.h#L609). Presumably 
latin1 means that "." matches a byte, which would seem more compatible with re, 
but python bindings don't provide the ability to choose this encoding.
  
  Indeed. We could pass in a fat unicode array (i.e. each byte as latin-1 char)
  to re2, but that would sacrifice the performance.
  
  Thanks for the info.

REPOSITORY
  rHG Mercurial

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

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


Re: D5291: branchmap: build the revbranchcache._namesreverse() only when required

2018-11-21 Thread Yuya Nishihara
> +if self._namesreverse is None:
> +self._namesreverse = dict((b, r) for r, b in 
> enumerate(self._names))
>  if b in self._namesreverse:
>  branchidx = self._namesreverse[b]
>  else:
> @@ -467,6 +469,8 @@
>  
>  def setdata(self, branch, rev, node, close):
>  """add new data information to the cache"""
> +if self._namesreverse is None:
> +self._namesreverse = dict((b, r) for r, b in 
> enumerate(self._names))

Maybe _namesreverse can be a propertycache, instead of duplicating it.
`del self.__dict__[r'...']` can be used to discard the cache.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5291: branchmap: build the revbranchcache._namesreverse() only when required

2018-11-21 Thread yuja (Yuya Nishihara)
yuja added a comment.


  > +if self._namesreverse is None:
  >  +self._namesreverse = dict((b, r) for r, b in 
enumerate(self._names))
  > 
  >   if b in self._namesreverse:
  >   branchidx = self._namesreverse[b]
  >   else:
  > 
  > @@ -467,6 +469,8 @@
  > 
  >   def setdata(self, branch, rev, node, close):
  >   """add new data information to the cache"""
  > 
  > +if self._namesreverse is None:
  >  +self._namesreverse = dict((b, r) for r, b in 
enumerate(self._names))
  
  Maybe _namesreverse can be a propertycache, instead of duplicating it.
  `del self.__dict__[r'...']` can be used to discard the cache.

REPOSITORY
  rHG Mercurial

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

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


D5292: branchmap: make it easier for extensions not to break branchcache

2018-11-21 Thread mjpieters (Martijn Pieters)
mjpieters created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The _branchcache global gives us a reference for super() to use even if an
  extension subclasses branchmap.branchcache then replaces the class in the
  module.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/branchmap.py

CHANGE DETAILS

diff --git a/mercurial/branchmap.py b/mercurial/branchmap.py
--- a/mercurial/branchmap.py
+++ b/mercurial/branchmap.py
@@ -211,7 +211,7 @@
 
 def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev,
  filteredhash=None, closednodes=None):
-super(branchcache, self).__init__(entries)
+super(_branchcache, self).__init__(entries)
 self.tipnode = tipnode
 self.tiprev = tiprev
 self.filteredhash = filteredhash
@@ -369,6 +369,11 @@
 self.write(repo)
 
 
+# keep a private reference to the class object so that subclasses that
+# replace the branchcache class do not break super()
+_branchcache = branchcache
+
+
 class remotebranchcache(branchcache):
 """Branchmap info for a remote connection, should not write locally"""
 def write(self, repo):



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


Re: [PATCH 1 of 7 V4] sparse-revlog: add a `index_get_start` function in C

2018-11-21 Thread Boris FELD

On 21/11/2018 13:30, Yuya Nishihara wrote:
> On Tue, 20 Nov 2018 21:44:32 +0100, Boris Feld wrote:
>> # HG changeset patch
>> # User Boris Feld 
>> # Date 1542725358 0
>> #  Tue Nov 20 14:49:18 2018 +
>> # Node ID 60a55da39befa4996c1a88ca6f663765ea143ef2
>> # Parent  337a389953366f059f2cb88129031ba3e67e0bbc
>> # EXP-Topic sparse-perf
>> # Available At https://bitbucket.org/octobus/mercurial-devel/
>> #  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
>> 60a55da39bef
>> sparse-revlog: add a `index_get_start` function in C
>> diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c
>> --- a/mercurial/cext/revlog.c
>> +++ b/mercurial/cext/revlog.c
>> @@ -185,6 +185,46 @@ static inline int index_get_parents(inde
>>  return 0;
>>  }
>>  
>> +static inline int64_t index_get_start(indexObject *self, Py_ssize_t rev)
> I meant "int index_get_start(*self, rev, *offset)" just like 
> index_get_parents(),
> but this is also good.
Since the return is simpler than index_get_parent, it seemed simpler to
return the value directly.
>
>> +{
>> +uint64_t offset;
>> +if (rev >= self->length) {
>> +PyObject *tuple;
>> +PyObject *pylong;
>> +unsigned PY_LONG_LONG tmp;
>> +tuple = PyList_GET_ITEM(self->added, rev - self->length);
>> +pylong = PyTuple_GET_ITEM(tuple, 0);
>> +#ifndef IS_PY3K
>> +if (PyInt_Check(pylong)) {
>> +long tmp2 = PyInt_AsLong(pylong);
>> +if (tmp2 < 0) {
>> +return -1;
>> +}
>> +tmp = (unsigned PY_LONG_LONG)tmp2;
>> +} else {
>> +#endif
>> +tmp = PyLong_AsUnsignedLongLong(pylong);
>> +if (tmp == (unsigned PY_LONG_LONG) - 1) {
>> +return -1;
>> +}
>> +
>> +#ifndef IS_PY3K
>> +}
>> +#endif
>> +offset = (uint64_t)tmp;
> Sigh, PyLong API is so inconsistent on Python 2. Let's switch to
> PyLong_AsLongLong(), which can handle PyInt as well. I think it's
> okay to raise OverflowError if offset >= 1 << (63 - 16).

Okay, so dropping the special case and directly using:

  offset = PyLong_AsLongLong(pylong);
  if (offset < 0){ … }

Right?
>
> FWIW, PyLong_AsUnsignedLongLong() of Python 2 would raise BadInternalCall
> if non-long type were passed.
Yep, I saw that, and it's how I ended up adding the PyInt case.
> ___
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 3 of 7 V4] sparse-revlog: add a `index_segment_span` function in C

2018-11-21 Thread Boris FELD

On 21/11/2018 13:27, Yuya Nishihara wrote:
> On Tue, 20 Nov 2018 21:44:34 +0100, Boris Feld wrote:
>> # HG changeset patch
>> # User Boris Feld 
>> # Date 1541785396 -3600
>> #  Fri Nov 09 18:43:16 2018 +0100
>> # Node ID 5bb00d137c14d311c91c7a4f32f58378cd9195ec
>> # Parent  8863dc1f7d078827708d178bbbfee5519b4c9b0f
>> # EXP-Topic sparse-perf
>> # Available At https://bitbucket.org/octobus/mercurial-devel/
>> #  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
>> 5bb00d137c14
>> sparse-revlog: add a `index_segment_span` function in C
>>
>> We are about to implement a native version of `slicechunktodensity`. For
>> clarity, we introduce the helper functions first. This new function provides
>> an efficient way to retrieve some of the information needed by
>> `slicechunktodensity`.
>>
>> diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c
>> --- a/mercurial/cext/revlog.c
>> +++ b/mercurial/cext/revlog.c
>> @@ -1068,6 +1068,27 @@ bail:
>>  return NULL;
>>  }
>>  
>> +static inline int64_t
>> +index_segment_span(indexObject *self, Py_ssize_t start_rev, Py_ssize_t 
>> end_rev)
>> +{
>> +int64_t start_offset;
>> +int64_t end_offset;
>> +int end_size;
>> +start_offset = index_get_start(self, start_rev);
>> +if (start_offset < 0) {
>> +return -1;
>> +}
>> +end_offset = index_get_start(self, end_rev);
>> +if (end_offset < 0) {
>> +return -1;
>> +}
>> +end_size = index_get_length(self, end_rev);
>> +if (end_size < 0) {
>> +return -1;
>> +}
>> +return (end_offset - start_offset) + (int64_t)end_size;
> Nit: maybe raise error if end_offset - start_offset) + (int64_t)end_size < 0 ?

Unless the revlog is corrupted, we have:

  start_rev <= end_rev

and:

  start_offset <= end_offset

So this value will be positive. If the revlog is corrupt I assume we'll
have more troubles sooner.

Or do you want extra checks on the above assertion?
>
> Other than that, the series looks good to me.
> ___
> 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


D5293: py3: whitelist three more passing test caught by buildbot

2018-11-21 Thread pulkit (Pulkit Goyal)
pulkit created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The number of failing test is back to two digits.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  contrib/python3-whitelist

CHANGE DETAILS

diff --git a/contrib/python3-whitelist b/contrib/python3-whitelist
--- a/contrib/python3-whitelist
+++ b/contrib/python3-whitelist
@@ -306,8 +306,11 @@
 test-largefiles-small-disk.t
 test-largefiles-update.t
 test-largefiles.t
+test-lfconvert.t
+test-lfs-bundle.t
 test-lfs-largefiles.t
 test-lfs-pointer.py
+test-lfs.t
 test-linelog.py
 test-linerange.py
 test-locate.t



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


Re: [PATCH] blackbox: add configitem for format of log timestamps

2018-11-21 Thread MATTHEW DEVORE
Ping. Did you have any trouble applying this updated patch? This one should not 
have any mangled spaces.
> On October 23, 2018 at 1:49 PM Matthew DeVore wrote:
>
>
> From: Matt DeVore
>
> My e-mail client was mangling spaces, which is why you couldn't apply the
> patch earlier. I'm sending this again with a different tool and e-mail 
> address.
> 
>
> # HG changeset patch
> # User Matt DeVore
> # Date 1539816481 25200
> # Wed Oct 17 15:48:01 2018 -0700
> # Node ID 13c2fe6d3b30a743daa1984404a70ed769779d11
> # Parent a0e7fa019290d5348c4a83f6b287f2612d645025
> blackbox: add configitem for format of log timestamps
>
> Sometimes blackbox logs are used to report performance problems, but the
> timestamps are only at second granularity, so often the timings have to
> stated separately by the reporter. This is inconvenient and error-prone,
> so I would like to include %f in the date format. This patch makes that
> possible.
>
> diff --git a/hgext/blackbox.py b/hgext/blackbox.py
> --- a/hgext/blackbox.py
> +++ b/hgext/blackbox.py
> @@ -33,6 +33,11 @@ Examples::
> # rotate up to N log files when the current one gets too big
> maxfiles = 3
>
> + [blackbox]
> + # Include nanoseconds in log entries with %f (see Python function
> + # datetime.datetime.strftime)
> + date-format = '%Y-%m-%d @ %H:%M:%S.%f'
> +
> """
>
> from __future__ import absolute_import
> @@ -82,6 +87,9 @@ configitem('blackbox', 'maxfiles',
> configitem('blackbox', 'track',
> default=lambda: ['*'],
> )
> +configitem('blackbox', 'date-format',
> + default='%Y/%m/%d %H:%M:%S',
> +)
>
> lastui = None
>
> @@ -169,7 +177,9 @@ def wrapui(ui):
> return
> ui._bbinlog = True
> default = self.configdate('devel', 'default-date')
> - date = dateutil.datestr(default, '%Y/%m/%d %H:%M:%S')
> + format = ui.config('blackbox', 'date-format')
> + date = dateutil.datestr(default,
> + ui.config('blackbox', 'date-format'))
> user = procutil.getuser()
> pid = '%d' % procutil.getpid()
> formattedmsg = msg[0] % msg[1:]
> diff --git a/tests/test-blackbox.t b/tests/test-blackbox.t
> --- a/tests/test-blackbox.t
> +++ b/tests/test-blackbox.t
> @@ -82,6 +82,16 @@ recursive aliases work correctly
> 1970/01/01 00:00:00 bob @ (5000)> 
> so-confusing exited 0 after * seconds (glob)
> 1970/01/01 00:00:00 bob @ (5000)> 
> blackbox
>
> +custom date format
> + $ rm ./.hg/blackbox.log
> + $ hg --config blackbox.date-format='%Y-%m-%d @ %H:%M:%S' \
> + > --config devel.default-date='1334347993 0' --traceback status
> + A a
> + $ hg blackbox
> + 2012-04-13 @ 20:13:13 bob @ (5000)> 
> --config 'blackbox.date-format=%Y-%m-%d @ %H:%M:%S' --config 
> 'devel.default-date=1334347993 0' --traceback status
> + 2012-04-13 @ 20:13:13 bob @ (5000)> 
> --config 'blackbox.date-format=%Y-%m-%d @ %H:%M:%S' --config 
> 'devel.default-date=1334347993 0' --traceback status exited 0 after * seconds 
> (glob)
> + 1970/01/01 00:00:00 bob @ (5000)> 
> blackbox
> +
> incoming change tracking
>
> create two heads to verify that we only see one change in the log later
>
>___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] blackbox: add configitem for format of log timestamps

2018-11-21 Thread Martin von Zweigbergk via Mercurial-devel
On Wed, Nov 21, 2018 at 8:32 AM MATTHEW DEVORE  wrote:

> Ping. Did you have any trouble applying this updated patch? This one
> should not have any mangled spaces.
>

This was queued as https://www.mercurial-scm.org/repo/hg/rev/25f1c7bd649d
(Yuya replied to you at Oct 24, 2018, 4:15 AM Pacific time).


> > On October 23, 2018 at 1:49 PM Matthew DeVore wrote:
> >
> >
> > From: Matt DeVore
> >
> > My e-mail client was mangling spaces, which is why you couldn't apply
> the
> > patch earlier. I'm sending this again with a different tool and e-mail
> address.
> >
> 
>
> >
> > # HG changeset patch
> > # User Matt DeVore
> > # Date 1539816481 25200
> > # Wed Oct 17 15:48:01 2018 -0700
> > # Node ID 13c2fe6d3b30a743daa1984404a70ed769779d11
> > # Parent a0e7fa019290d5348c4a83f6b287f2612d645025
> > blackbox: add configitem for format of log timestamps
> >
> > Sometimes blackbox logs are used to report performance problems, but the
> > timestamps are only at second granularity, so often the timings have to
> > stated separately by the reporter. This is inconvenient and error-prone,
> > so I would like to include %f in the date format. This patch makes that
> > possible.
> >
> > diff --git a/hgext/blackbox.py b/hgext/blackbox.py
> > --- a/hgext/blackbox.py
> > +++ b/hgext/blackbox.py
> > @@ -33,6 +33,11 @@ Examples::
> > # rotate up to N log files when the current one gets too big
> > maxfiles = 3
> >
> > + [blackbox]
> > + # Include nanoseconds in log entries with %f (see Python function
> > + # datetime.datetime.strftime)
> > + date-format = '%Y-%m-%d @ %H:%M:%S.%f'
> > +
> > """
> >
> > from __future__ import absolute_import
> > @@ -82,6 +87,9 @@ configitem('blackbox', 'maxfiles',
> > configitem('blackbox', 'track',
> > default=lambda: ['*'],
> > )
> > +configitem('blackbox', 'date-format',
> > + default='%Y/%m/%d %H:%M:%S',
> > +)
> >
> > lastui = None
> >
> > @@ -169,7 +177,9 @@ def wrapui(ui):
> > return
> > ui._bbinlog = True
> > default = self.configdate('devel', 'default-date')
> > - date = dateutil.datestr(default, '%Y/%m/%d %H:%M:%S')
> > + format = ui.config('blackbox', 'date-format')
> > + date = dateutil.datestr(default,
> > + ui.config('blackbox', 'date-format'))
> > user = procutil.getuser()
> > pid = '%d' % procutil.getpid()
> > formattedmsg = msg[0] % msg[1:]
> > diff --git a/tests/test-blackbox.t b/tests/test-blackbox.t
> > --- a/tests/test-blackbox.t
> > +++ b/tests/test-blackbox.t
> > @@ -82,6 +82,16 @@ recursive aliases work correctly
> > 1970/01/01 00:00:00 bob @
> (5000)> so-confusing exited 0 after * seconds (glob)
> > 1970/01/01 00:00:00 bob @
> (5000)> blackbox
> >
> > +custom date format
> > + $ rm ./.hg/blackbox.log
> > + $ hg --config blackbox.date-format='%Y-%m-%d @ %H:%M:%S' \
> > + > --config devel.default-date='1334347993 0' --traceback status
> > + A a
> > + $ hg blackbox
> > + 2012-04-13 @ 20:13:13 bob @
> (5000)> --config 'blackbox.date-format=%Y-%m-%d @ %H:%M:%S' --config
> 'devel.default-date=1334347993 0' --traceback status
> > + 2012-04-13 @ 20:13:13 bob @
> (5000)> --config 'blackbox.date-format=%Y-%m-%d @ %H:%M:%S' --config
> 'devel.default-date=1334347993 0' --traceback status exited 0 after *
> seconds (glob)
> > + 1970/01/01 00:00:00 bob @
> (5000)> blackbox
> > +
> > incoming change tracking
> >
> > create two heads to verify that we only see one change in the log later
> >
> >
> ___
> 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] blackbox: add configitem for format of log timestamps

2018-11-21 Thread Pulkit Goyal
On Wed, Nov 21, 2018 at 7:32 PM MATTHEW DEVORE  wrote:

> Ping. Did you have any trouble applying this updated patch? This one
> should not have any mangled spaces.
>

Your patch is already pushed.
https://www.mercurial-scm.org/repo/hg/rev/25f1c7bd649d
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] blackbox: add configitem for format of log timestamps

2018-11-21 Thread Matthew DeVore via Mercurial-devel
I see now Yuya told me the change was queued in a prior e-mail. This
thread is actually a nexus of 5 or 6 e-mail screw-ups on my part, so I
didn't see it.

Thank you all for helping me and I'll try Phabricator next time :)
On Wed, Nov 21, 2018 at 8:37 AM Pulkit Goyal <7895pul...@gmail.com> wrote:
>
>
>
> On Wed, Nov 21, 2018 at 7:32 PM MATTHEW DEVORE  wrote:
>>
>> Ping. Did you have any trouble applying this updated patch? This one should 
>> not have any mangled spaces.
>
>
> Your patch is already pushed. 
> https://www.mercurial-scm.org/repo/hg/rev/25f1c7bd649d
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5294: tests: make test-check-module-imports more robust

2018-11-21 Thread valentin.gatienbaron (Valentin Gatien-Baron)
valentin.gatienbaron created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  It fails for me with (among other things):
  
tests/test-commandserver.t:19: relative import of stdlib module
tests/test-lfs-serve.t:108: relative import of stdlib module
tests/test-lfs-serve.t:255: relative import of stdlib module
tests/test-lfs-serve.t:362: relative import of stdlib module
tests/test-lfs-serve.t:406: relative import of stdlib module
  
  This is because every module is considered a stdlib module, because
  the stdlib_prefixes is /usr, and my repo is in /usr/local/home (so
  sys.path[0] is /usr/local/home/../hg/contrib since import-checker.py
  lives there). So remove the import-checker directory.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  contrib/import-checker.py

CHANGE DETAILS

diff --git a/contrib/import-checker.py b/contrib/import-checker.py
--- a/contrib/import-checker.py
+++ b/contrib/import-checker.py
@@ -260,9 +260,9 @@
 break
 else:
 stdlib_prefixes.add(dirname)
-for libpath in sys.path:
-# We want to walk everything in sys.path that starts with
-# something in stdlib_prefixes.
+for libpath in sys.path[1:]:
+# We want to walk everything in sys.path (other than the directory of
+# the current script) that starts with something in stdlib_prefixes.
 if not any(libpath.startswith(p) for p in stdlib_prefixes):
 continue
 for top, dirs, files in os.walk(libpath):



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


D5294: tests: make test-check-module-imports more robust

2018-11-21 Thread valentin.gatienbaron (Valentin Gatien-Baron)
valentin.gatienbaron updated this revision to Diff 12580.
valentin.gatienbaron edited the summary of this revision.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5294?vs=12579&id=12580

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

AFFECTED FILES
  contrib/import-checker.py

CHANGE DETAILS

diff --git a/contrib/import-checker.py b/contrib/import-checker.py
--- a/contrib/import-checker.py
+++ b/contrib/import-checker.py
@@ -260,10 +260,12 @@
 break
 else:
 stdlib_prefixes.add(dirname)
+sourceroot = os.path.dirname(sys.path[0])
 for libpath in sys.path:
-# We want to walk everything in sys.path that starts with
-# something in stdlib_prefixes.
-if not any(libpath.startswith(p) for p in stdlib_prefixes):
+# We want to walk everything in sys.paththat starts with something in
+# stdlib_prefixes, but not directories from the hg sources.
+if (libpath.startswith(sourceroot)
+or not any(libpath.startswith(p) for p in stdlib_prefixes)):
 continue
 for top, dirs, files in os.walk(libpath):
 for i, d in reversed(list(enumerate(dirs))):



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


[PATCH 1 of 8] perf: explicitly pass title as a keyword argument in `perfdiffwd`

2018-11-21 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1542668549 0
#  Mon Nov 19 23:02:29 2018 +
# Node ID 954159d40a5f4bf43465c50cc97261ea139f0032
# Parent  dba590f27c7abacbd7e9b27f3e06822bb0b339cb
# EXP-Topic perf-ignore
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
954159d40a5f
perf: explicitly pass title as a keyword argument in `perfdiffwd`

This will help to update the timer function arguments in a later changeset.

diff --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -1404,7 +1404,7 @@ def perfdiffwd(ui, repo, **opts):
 ui.popbuffer()
 diffopt = diffopt.encode('ascii')
 title = b'diffopts: %s' % (diffopt and (b'-' + diffopt) or b'none')
-timer(d, title)
+timer(d, title=title)
 fm.end()
 
 @command(b'perfrevlogindex', revlogopts + formatteropts,
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 8] perf: add a `setup` argument to run code outside of the timed section

2018-11-21 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1542668107 0
#  Mon Nov 19 22:55:07 2018 +
# Node ID 04a1a32aaaedc6a75117994dbf2823e39204fd7d
# Parent  954159d40a5f4bf43465c50cc97261ea139f0032
# EXP-Topic perf-ignore
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
04a1a32aaaed
perf: add a `setup` argument to run code outside of the timed section

With this new argument, it is possible to perform special setup and cleanup
outside of code actually timed. This is useful to provide more accurate
benchmark.

diff --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -275,7 +275,7 @@ def gettimer(ui, opts=None):
 displayall = ui.configbool(b"perf", b"all-timing", False)
 return functools.partial(_timer, fm, displayall=displayall), fm
 
-def stub_timer(fm, func, title=None):
+def stub_timer(fm, func, setup=None, title=None):
 func()
 
 @contextlib.contextmanager
@@ -289,12 +289,14 @@ def timeone():
 a, b = ostart, ostop
 r.append((cstop - cstart, b[0] - a[0], b[1]-a[1]))
 
-def _timer(fm, func, title=None, displayall=False):
+def _timer(fm, func, setup=None, title=None, displayall=False):
 gc.collect()
 results = []
 begin = util.timer()
 count = 0
 while True:
+if setup is not None:
+setup()
 with timeone() as item:
 r = func()
 count += 1
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 8] perf: use the new setup function in "perfbookmarks"

2018-11-21 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1542669286 0
#  Mon Nov 19 23:14:46 2018 +
# Node ID 73f19cded5865968e672a0e1d1b6aaaef2b77e18
# Parent  04a1a32aaaedc6a75117994dbf2823e39204fd7d
# EXP-Topic perf-ignore
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
73f19cded586
perf: use the new setup function in "perfbookmarks"

This command was picked arbitrarily to display the usefulness of the new
feature. In my Mercurial repository (with very few bookmarks), moving cache
cleanup in the dedicated setup function has a visible  and stable effect on
the benchmark number.

before: ! wall 0.61 comb 0.00 user 0.00 sys 0.00 (median of 
40837)
after:  ! wall 0.58 comb 0.00 user 0.00 sys 0.00 (median of 
40500)

diff --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -576,10 +576,12 @@ def perfbookmarks(ui, repo, **opts):
 """benchmark parsing bookmarks from disk to memory"""
 opts = _byteskwargs(opts)
 timer, fm = gettimer(ui, opts)
-def d():
+
+def s():
 clearfilecache(repo, b'_bookmarks')
+def d():
 repo._bookmarks
-timer(d)
+timer(d, setup=s)
 fm.end()
 
 @command(b'perfbundleread', formatteropts, b'BUNDLE')
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 8] perf: make `clearfilecache` helper work with any object

2018-11-21 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1542646221 0
#  Mon Nov 19 16:50:21 2018 +
# Node ID ea3a9f11bceef210118fc368908f4cfcd5a814fa
# Parent  73f19cded5865968e672a0e1d1b6aaaef2b77e18
# EXP-Topic perf-ignore
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
ea3a9f11bcee
perf: make `clearfilecache` helper work with any object

If the object is not a localrepo, it won't have an `unfiltered` method (and
won't need one).

diff --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -457,11 +457,13 @@ def repocleartagscachefunc(repo):
 
 # utilities to clear cache
 
-def clearfilecache(repo, attrname):
-unfi = repo.unfiltered()
-if attrname in vars(unfi):
-delattr(unfi, attrname)
-unfi._filecache.pop(attrname, None)
+def clearfilecache(obj, attrname):
+unfiltered = getattr(obj, 'unfiltered', None)
+if unfiltered is not None:
+obj = obj.unfiltered()
+if attrname in vars(obj):
+delattr(obj, attrname)
+obj._filecache.pop(attrname, None)
 
 # perf commands
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 6 of 8] match: avoid translating glob to matcher multiple times for large sets

2018-11-21 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1542651672 0
#  Mon Nov 19 18:21:12 2018 +
# Node ID 03b60ccca50c77a552de85ac3402c5174539f150
# Parent  aeea6de7f1a88e2e710ee01299fe4fe9e1f0d336
# EXP-Topic perf-ignore
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
03b60ccca50c
match: avoid translating glob to matcher multiple times for large sets

For hgignore with many globs, the resulting regexp might not fit under the 20K
length limit. So the patterns need to be broken up in smaller pieces.

Before this change, the logic was re-starting the full process from scratch
for each smaller pieces, including the translation of globs into regexp.
Effectively doing the work over and over.

If the 20K limit is reached, we are likely in a case where there is many such
glob, so exporting them is especially expensive and we should be careful not
to do that work more than once.

To work around this, we now translate glob to regexp once and for all. Then,
we assemble the resulting individual regexp into valid blocks.

This raises a very significant performance win for large `.hgignore file`:

Before: ! wall 0.153153 comb 0.15 user 0.15 sys 0.00 (median of 66)
After:  ! wall 0.059793 comb 0.06 user 0.06 sys 0.00 (median of 100)

diff --git a/mercurial/match.py b/mercurial/match.py
--- a/mercurial/match.py
+++ b/mercurial/match.py
@@ -1184,25 +1184,40 @@ def _buildmatch(kindpats, globsuffix, li
 else:
 return regex, lambda f: any(mf(f) for mf in matchfuncs)
 
+MAXRESIZE = 2
+
+def _groupregexps(regexps):
+return '(?:%s)' % '|'.join(regexps)
+
 def _buildregexmatch(kindpats, globsuffix):
 """Build a match function from a list of kinds and kindpats,
 return regexp string and a matcher function."""
 try:
-regex = '(?:%s)' % '|'.join([_regex(k, p, globsuffix)
- for (k, p, s) in kindpats])
-if len(regex) > 2:
-raise OverflowError
-return regex, _rematcher(regex)
-except OverflowError:
-# We're using a Python with a tiny regex engine and we
-# made it explode, so we'll divide the pattern list in two
-# until it works
-l = len(kindpats)
-if l < 2:
-raise
-regexa, a = _buildregexmatch(kindpats[:l//2], globsuffix)
-regexb, b = _buildregexmatch(kindpats[l//2:], globsuffix)
-return regex, lambda s: a(s) or b(s)
+allgroups = []
+regexps = [_regex(k, p, globsuffix) for (k, p, s) in kindpats]
+fullregexp = _groupregexps(regexps)
+
+startidx = 0
+groupsize = 3
+for idx, r in enumerate(regexps):
+piecesize = len(r)
+if piecesize > MAXRESIZE:
+raise OverflowError
+elif (groupsize + 1 + piecesize) > MAXRESIZE:
+group = regexps[startidx:idx]
+allgroups.append(_groupregexps(group))
+startidx = idx
+groupsize = 3
+groupsize += piecesize
+
+if startidx == 0:
+func = _rematcher(fullregexp)
+else:
+group = regexps[startidx:idx]
+allgroups.append(_groupregexps(group))
+allmatchers = [_rematcher(g) for g in allgroups]
+func = lambda s: any(m(s) for m in allmatchers)
+return fullregexp, func
 except re.error:
 for k, p, s in kindpats:
 try:
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 5 of 8] perf: add a perfignore command

2018-11-21 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1542669732 0
#  Mon Nov 19 23:22:12 2018 +
# Node ID aeea6de7f1a88e2e710ee01299fe4fe9e1f0d336
# Parent  ea3a9f11bceef210118fc368908f4cfcd5a814fa
# EXP-Topic perf-ignore
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
aeea6de7f1a8
perf: add a perfignore command

The command is meant to benchmark operations related to hgignore. Right now the
command is benchmarking the loading time of the hgignore rules.

diff --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -960,6 +960,23 @@ def perfchangeset(ui, repo, rev, **opts)
 timer(d)
 fm.end()
 
+@command(b'perfignore', formatteropts)
+def perfignore(ui, repo, **opts):
+"""benchmark operation related to computing ignore"""
+opts = _byteskwargs(opts)
+timer, fm = gettimer(ui, opts)
+dirstate = repo.dirstate
+
+def setupone():
+dirstate.invalidate()
+clearfilecache(dirstate, b'_ignore')
+
+def runone():
+dirstate._ignore
+
+timer(runone, setup=setupone, title="load")
+fm.end()
+
 @command(b'perfindex', formatteropts)
 def perfindex(ui, repo, **opts):
 import mercurial.revlog
diff --git a/tests/test-contrib-perf.t b/tests/test-contrib-perf.t
--- a/tests/test-contrib-perf.t
+++ b/tests/test-contrib-perf.t
@@ -83,6 +83,7 @@ perfstatus
perffncachewrite
  (no help text available)
perfheads (no help text available)
+   perfignorebenchmark operation related to computing ignore
perfindex (no help text available)
perflinelogedits
  (no help text available)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 8 of 8] match: reformat `syntaxes` dictionary for better maintainability

2018-11-21 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1542647994 0
#  Mon Nov 19 17:19:54 2018 +
# Node ID 865075265c79c576c53c1bd2b1a6d4b9f5719e2d
# Parent  8992601f1d1a54a42c984518097a246b49c06c12
# EXP-Topic perf-ignore
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
865075265c79
match: reformat `syntaxes` dictionary for better maintainability

diff --git a/mercurial/match.py b/mercurial/match.py
--- a/mercurial/match.py
+++ b/mercurial/match.py
@@ -1346,8 +1346,13 @@ def readpatternfile(filepath, warn, sour
 (pattern, lineno, originalline). This is useful to debug ignore patterns.
 '''
 
-syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:',
-'include': 'include', 'subinclude': 'subinclude'}
+syntaxes = {
+'re': 'relre:',
+'regexp': 'relre:',
+'glob': 'relglob:',
+'include': 'include',
+'subinclude': 'subinclude',
+}
 syntax = 'relre:'
 patterns = []
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 7 of 8] match: provide and use a quick way to escape a single byte

2018-11-21 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1542653684 0
#  Mon Nov 19 18:54:44 2018 +
# Node ID 8992601f1d1a54a42c984518097a246b49c06c12
# Parent  03b60ccca50c77a552de85ac3402c5174539f150
# EXP-Topic perf-ignore
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
8992601f1d1a
match: provide and use a quick way to escape a single byte

The previous function has a lot of overhead (including being a function). In
the `_globre` case, we always escape a single byte. So we provide a dictionary
dedicated to this use case. We directly use the dictionary to avoid a function
call, these are expensive in Python.

Again, this raise a very significant performance gain:

Before: ! wall 0.059793 comb 0.06 user 0.06 sys 0.00 (median of 100)
After:  ! wall 0.020390 comb 0.02 user 0.02 sys 0.00 (median of 146)

Total improvement for the full series:

Before: ! wall 0.153153 comb 0.15 user 0.15 sys 0.00 (median of 66)
After:  ! wall 0.020390 comb 0.02 user 0.02 sys 0.00 (median of 146)

diff --git a/mercurial/match.py b/mercurial/match.py
--- a/mercurial/match.py
+++ b/mercurial/match.py
@@ -1057,14 +1057,14 @@ def _globre(pat):
 i, n = 0, len(pat)
 res = ''
 group = 0
-escape = util.stringutil.reescape
+escape = util.stringutil.regexbytesescapemap.get
 def peek():
 return i < n and pat[i:i + 1]
 while i < n:
 c = pat[i:i + 1]
 i += 1
 if c not in '*?[{},\\':
-res += escape(c)
+res += escape(c, c)
 elif c == '*':
 if peek() == '*':
 i += 1
@@ -1105,11 +1105,11 @@ def _globre(pat):
 p = peek()
 if p:
 i += 1
-res += escape(p)
+res += escape(p, p)
 else:
-res += escape(c)
+res += escape(c, c)
 else:
-res += escape(c)
+res += escape(c, c)
 return res
 
 def _regex(kind, pat, globsuffix):
diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -28,6 +28,7 @@ from .. import (
 # which was part of Python 3.7.
 _respecial = pycompat.bytestr(b'()[]{}?*+-|^$\\.&~# \t\n\r\v\f')
 _regexescapemap = {ord(i): (b'\\' + i).decode('latin1') for i in _respecial}
+regexbytesescapemap = {i: (b'\\' + i) for i in _respecial}
 
 def reescape(pat):
 """Drop-in replacement for re.escape."""
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5294: tests: make test-check-module-imports more robust

2018-11-21 Thread valentin.gatienbaron (Valentin Gatien-Baron)
valentin.gatienbaron updated this revision to Diff 12581.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5294?vs=12580&id=12581

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

AFFECTED FILES
  contrib/import-checker.py

CHANGE DETAILS

diff --git a/contrib/import-checker.py b/contrib/import-checker.py
--- a/contrib/import-checker.py
+++ b/contrib/import-checker.py
@@ -260,10 +260,12 @@
 break
 else:
 stdlib_prefixes.add(dirname)
+sourceroot = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
 for libpath in sys.path:
-# We want to walk everything in sys.path that starts with
-# something in stdlib_prefixes.
-if not any(libpath.startswith(p) for p in stdlib_prefixes):
+# We want to walk everything in sys.path that starts with something in
+# stdlib_prefixes, but not directories from the hg sources.
+if (os.path.abspath(libpath).startswith(sourceroot)
+or not any(libpath.startswith(p) for p in stdlib_prefixes)):
 continue
 for top, dirs, files in os.walk(libpath):
 for i, d in reversed(list(enumerate(dirs))):



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


Extra files in changelog "changed files" and bundles

2018-11-21 Thread Mads Kiilerich

Hi

I see some odd and potentially related behaviour:

The files list in changelog entries for merges sometimes contain files 
that didn't change, but where the manifest use the same filelog entry as 
one of the parents.

It seems to often be related to merge of file moves.

Also, sometimes there are different filelog entries, but 
debugrevlogindex shows rename entries (p1=null) with length 0 and where 
debugdata confirms that the content is the same as their p2.


And because of these extra "changedfiles" entries, bundles sometimes 
contains too many files. Linkrev is used for pruning, but is too fragile 
to handle it correctly. (I have a PoC for pruning all filelog entries 
that are reused from the parents "common" and outside the bundled set.) 
(It also doesn't seem to use an optimal delta parent when bundling - 
that could perhaps mitigate it.)


Sorry for the vague description. I have not been fully able to reproduce 
the problems - perhaps because bugs have been fixed. Are you aware of 
changes/fixes that can explain this? Or hints about where to look or 
related problems?


/Mads

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


Re: [PATCH v2] graft: introduce --base option for using custom base revision while merging

2018-11-21 Thread Mads Kiilerich

On 10/23/18 4:59 PM, Augie Fackler wrote:

On Oct 14, 2018, at 11:15, Mads Kiilerich  wrote:

# HG changeset patch
# User Mads Kiilerich 
# Date 1539529698 -7200
#  Sun Oct 14 17:08:18 2018 +0200
# Node ID 258029c642d97ef663396476c63ce34dbef89b13
# Parent  38ac525b44c93fcadb3680d4ded56f1e5a0029b2
graft: introduce --base option for using custom base revision while merging

queued



Thanks.



At the sprint you had mentioned maybe being able to use this to help backing 
out a merge - if you know the incantation for that maybe send that as a 
follow-up for the verbose help?


IIRC, graft has other safety mechanisms that prevent using a descendant 
as base. The primary use of this is to "graft merges".


Backout of merges should be possible with existing backout 
functionality. The change help hinted in that direction:



+
+  For using non-ancestors as the base to backout changes, see the backout
+  command and the hidden --parent option.



(But ok, backout could use more helpful help too.)

/Mads

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


Re: [PATCH 1 of 7 V4] sparse-revlog: add a `index_get_start` function in C

2018-11-21 Thread Yuya Nishihara
On Wed, 21 Nov 2018 16:50:35 +0100, Boris FELD wrote:
> > Sigh, PyLong API is so inconsistent on Python 2. Let's switch to
> > PyLong_AsLongLong(), which can handle PyInt as well. I think it's
> > okay to raise OverflowError if offset >= 1 << (63 - 16).
> 
> Okay, so dropping the special case and directly using:
> 
>   offset = PyLong_AsLongLong(pylong);
>   if (offset < 0){ … }
> 
> Right?

Yep, something similar to the one I proposed for the PATCH 2.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 3 of 7 V4] sparse-revlog: add a `index_segment_span` function in C

2018-11-21 Thread Yuya Nishihara
On Wed, 21 Nov 2018 16:52:22 +0100, Boris FELD wrote:
> 
> On 21/11/2018 13:27, Yuya Nishihara wrote:
> > On Tue, 20 Nov 2018 21:44:34 +0100, Boris Feld wrote:
> >> # HG changeset patch
> >> # User Boris Feld 
> >> # Date 1541785396 -3600
> >> #  Fri Nov 09 18:43:16 2018 +0100
> >> # Node ID 5bb00d137c14d311c91c7a4f32f58378cd9195ec
> >> # Parent  8863dc1f7d078827708d178bbbfee5519b4c9b0f
> >> # EXP-Topic sparse-perf
> >> # Available At https://bitbucket.org/octobus/mercurial-devel/
> >> #  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
> >> 5bb00d137c14
> >> sparse-revlog: add a `index_segment_span` function in C
> >>
> >> We are about to implement a native version of `slicechunktodensity`. For
> >> clarity, we introduce the helper functions first. This new function 
> >> provides
> >> an efficient way to retrieve some of the information needed by
> >> `slicechunktodensity`.
> >>
> >> diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c
> >> --- a/mercurial/cext/revlog.c
> >> +++ b/mercurial/cext/revlog.c
> >> @@ -1068,6 +1068,27 @@ bail:
> >>return NULL;
> >>  }
> >>  
> >> +static inline int64_t
> >> +index_segment_span(indexObject *self, Py_ssize_t start_rev, Py_ssize_t 
> >> end_rev)
> >> +{
> >> +  int64_t start_offset;
> >> +  int64_t end_offset;
> >> +  int end_size;
> >> +  start_offset = index_get_start(self, start_rev);
> >> +  if (start_offset < 0) {
> >> +  return -1;
> >> +  }
> >> +  end_offset = index_get_start(self, end_rev);
> >> +  if (end_offset < 0) {
> >> +  return -1;
> >> +  }
> >> +  end_size = index_get_length(self, end_rev);
> >> +  if (end_size < 0) {
> >> +  return -1;
> >> +  }
> >> +  return (end_offset - start_offset) + (int64_t)end_size;
> > Nit: maybe raise error if end_offset - start_offset) + (int64_t)end_size < 
> > 0 ?
> 
> Unless the revlog is corrupted, we have:
> 
>   start_rev <= end_rev
> 
> and:
> 
>   start_offset <= end_offset
> 
> So this value will be positive. If the revlog is corrupt I assume we'll
> have more troubles sooner.
> 
> Or do you want extra checks on the above assertion?

I just want to make sure that the CPython function never return NULL without
setting an exception, even if index_segment_span() happens to return -1
due to revlog corruption.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel