Re: [PATCH 8 of 9 pager v2] annotate: migrate to modern pager API

2017-02-18 Thread Jun Wu
Excerpts from Yuya Nishihara's message of 2017-02-19 11:04:19 +0900:
> On Sat, 18 Feb 2017 15:39:08 -0500, Augie Fackler wrote:
> > 
> > > On Feb 18, 2017, at 3:11 PM, Martin von Zweigbergk 
> > >  wrote:
> > > 
> > >> > --- a/mercurial/commands.py
> > >> > +++ b/mercurial/commands.py
> > >> > @@ -361,6 +361,7 @@ def annotate(ui, repo, *pats, **opts):
> > >> >
> > >> >  Returns 0 on success.
> > >> >  """
> > >> > +ui.pager('annotate')
> > >> >  if not pats:
> > >> >  raise error.Abort(_('at least one filename or pattern is 
> > >> > required'))
> > >> 
> > >> Just to make sure. Do we plan to delay ui.pager() call so short error 
> > >> messages
> > >> (and password prompt, etc.) won't be paged?
> > >> 
> > > I was wondering the same, but was hoping the pager would be configured to 
> > > exit if the full text would fit. I have no idea if that's true for most 
> > > systems out there, though. I don't believe I've manually configured mine 
> > > that way, so I suspect it's that way be default on our custom Ubuntu. I 
> > > guess pager on by default will be pretty annoying if that is not a common 
> > > default configuration, so I really hope it is.
> > 
> > I don’t think that’s a safe assumption, sadly. I’ll do a follow-up to try 
> > and make sure that things are sane at least at a high level.
> 
> IIRC, "more" exits automatically, but "less" doesn't by default. Also, "less"
> clears the paged contents on exit.

less can be configured to not clear the screen (-X), and exit automatically
(-F). And another common flag is -R, which will allow colors.

git used to just hard-code LESS=FRX as the default in pager.c [1]. That got
moved to an override-able build variable by [2].

I guess we could do the same, provide "LESS=FRX" as the default to be more
user-friendly.

[1]: 
https://github.com/git/git/blob/c3b1e8d85133e2a19d372b7c166d5b49fcbbfef2/pager.c#L70
[2]: https://github.com/git/git/commit/995bc22d7f8c611e342095a211065f8585a08e65
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 8 of 9 pager v2] annotate: migrate to modern pager API

2017-02-18 Thread Yuya Nishihara
On Sat, 18 Feb 2017 15:39:08 -0500, Augie Fackler wrote:
> 
> > On Feb 18, 2017, at 3:11 PM, Martin von Zweigbergk  
> > wrote:
> > 
> >> > --- a/mercurial/commands.py
> >> > +++ b/mercurial/commands.py
> >> > @@ -361,6 +361,7 @@ def annotate(ui, repo, *pats, **opts):
> >> >
> >> >  Returns 0 on success.
> >> >  """
> >> > +ui.pager('annotate')
> >> >  if not pats:
> >> >  raise error.Abort(_('at least one filename or pattern is 
> >> > required'))
> >> 
> >> Just to make sure. Do we plan to delay ui.pager() call so short error 
> >> messages
> >> (and password prompt, etc.) won't be paged?
> >> 
> > I was wondering the same, but was hoping the pager would be configured to 
> > exit if the full text would fit. I have no idea if that's true for most 
> > systems out there, though. I don't believe I've manually configured mine 
> > that way, so I suspect it's that way be default on our custom Ubuntu. I 
> > guess pager on by default will be pretty annoying if that is not a common 
> > default configuration, so I really hope it is.
> 
> I don’t think that’s a safe assumption, sadly. I’ll do a follow-up to try and 
> make sure that things are sane at least at a high level.

IIRC, "more" exits automatically, but "less" doesn't by default. Also, "less"
clears the paged contents on exit.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2] smartset: convert set to list lazily

2017-02-18 Thread Jun Wu
Excerpts from Martin von Zweigbergk's message of 2017-02-18 17:03:12 -0800:
> @@ -205,5 +215,5 @@ class baseset(abstractsmartset):
> 
>  def __nonzero__(self):
> -return bool(self._list)
> +return bool(len(self))
> 
> Could delete method, I think. Just FYI.

No, because abstractsmartset implements __nonzero__ to
"raise NotImplementedError()".

I think that's reasonable as it will force people to not forget overriding
the __nonzero__ implementation, to make things more explicit.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] smartset: reorder initialization of baseset in more intuitive way

2017-02-18 Thread Jun Wu
Looks good to me. Thanks for the clean-up!

Excerpts from Yuya Nishihara's message of 2017-02-18 18:48:06 +0900:
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1487407072 -32400
> #  Sat Feb 18 17:37:52 2017 +0900
> # Node ID 1ca3469fdd08c0d5d814a4bc359869bc157c7fc9
> # Parent  3f4bdcfe63e9f1e357187fa728ae0da9d35b3973
> smartset: reorder initialization of baseset in more intuitive way
> 
> What we want to do is to assign either _set or _list per the given data
> type.
> 
> diff --git a/mercurial/smartset.py b/mercurial/smartset.py
> --- a/mercurial/smartset.py
> +++ b/mercurial/smartset.py
> @@ -166,16 +166,14 @@ class baseset(abstractsmartset):
>  """
>  self._ascending = None
>  self._istopo = istopo
> -if not isinstance(data, list):
> -if isinstance(data, set):
> -self._set = data
> -# set has no order we pick one for stability purpose
> -self._ascending = True
> -# converting set to list has a cost, do it lazily
> -data = None
> -else:
> +if isinstance(data, set):
> +# converting set to list has a cost, do it lazily
> +self._set = data
> +# set has no order we pick one for stability purpose
> +self._ascending = True
> +else:
> +if not isinstance(data, list):
>  data = list(data)
> -if data is not None:
>  self._list = data
>  self._datarepr = datarepr
>  
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 2 of 2 v2] match: making visitdir() deal with non-recursive entries

2017-02-18 Thread Martin von Zweigbergk via Mercurial-devel
On Feb 17, 2017 10:17 PM, "Yuya Nishihara"  wrote:

On Mon, 13 Feb 2017 17:05:24 -0800, Rodrigo Damazio Bovendorp via
Mercurial-devel wrote:
> # HG changeset patch
> # User Rodrigo Damazio Bovendorp 
> # Date 1487034194 28800
> #  Mon Feb 13 17:03:14 2017 -0800
> # Node ID e90de197586d0749e64cef752613e6fe41d1c8e3
> # Parent  94264a6e6672c917d42518f7ae9322445868d067
> match: making visitdir() deal with non-recursive entries

> @@ -241,7 +250,7 @@
>  return 'all'
>  if dir in self._excluderoots:
>  return False
> -if (self._includeroots and
> +if ((self._includeroots or self._includedirs != set(['.'])) and
>  '.' not in self._includeroots and
>  dir not in self._includeroots and
>  dir not in self._includedirs and

Maybe we'll need to distinguish the explicitly-set 'rootfilesin:.' from
the default value. Since visitdir() is for optimization, this shouldn't be
a blocker, so queued.


Good point, rootfilesin:. doesn't currently get optimized, it seems.

Unrelated to this patch is that the optimization only applies to -I, not if
specified outside of that. I remember working on fixing that two years ago,
but I don't remember how far I got. Seems like it should be possible.

It would also be nice if the dirstate walk could take advantage of the
visitdir logic.


> @@ -642,11 +650,48 @@
>  break
>  root.append(p)
>  r.append('/'.join(root) or '.')
> -elif kind in ('relpath', 'path', 'rootfilesin'):
> +elif kind in ('relpath', 'path'):
>  r.append(pat or '.')
> +elif kind in ('rootfilesin'):
^^^

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


Re: [PATCH 1 of 8 v4] mercurial: use best available timer for perf measurements

2017-02-18 Thread Martin von Zweigbergk via Mercurial-devel
On Feb 16, 2017 10:48 AM, "Bryan O'Sullivan"  wrote:


On Thu, Feb 16, 2017 at 10:35 AM, Martin von Zweigbergk via Mercurial-devel
 wrote:

> As discussed on #mercurial, Augie and I find "timer" confusing,
> because it sounds like it returns a timer object, but in fact it just
> returns a time. Can we have a followup patch that renames it to e.g.
> perftime()?
>

If we're gonna bikeshed, it should be called time, because that's what it
really emulates :-)


Not quite, IIUC. On recent Pythons, it calls a function that returns a
value that's useful for timing, but that's not a time since the epoch.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 2 V2] smartset: add some doctests

2017-02-18 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1487464207 28800
#  Sat Feb 18 16:30:07 2017 -0800
# Node ID deb48622b857d621606a1cdda4adc868b1c663d4
# Parent  22722c297b33c2f68a8a34e0b0be0e6a9e0f4759
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r deb48622b857
smartset: add some doctests

Add doctests explaining the set / list behavior. This will make the
following changes more confident.

diff --git a/mercurial/smartset.py b/mercurial/smartset.py
--- a/mercurial/smartset.py
+++ b/mercurial/smartset.py
@@ -159,4 +159,49 @@ class baseset(abstractsmartset):
 
 Every method in this class should be implemented by any smartset class.
+
+This class could be constructed by an (unordered) set, or an (ordered)
+list-like object. If a set is provided, it'll be sorted lazily.
+
+>>> x = [4, 0, 7, 6]
+>>> y = [5, 6, 7, 3]
+
+Construct by a set:
+>>> xs = baseset(set(x))
+>>> ys = baseset(set(y))
+>>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
+[[0, 4, 6, 7, 3, 5], [6, 7], [0, 4]]
+>>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
+['addset', 'filteredset', 'filteredset']
+
+Construct by a list-like:
+>>> xs = baseset(x)
+>>> ys = baseset(i for i in y)
+>>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
+[[4, 0, 7, 6, 5, 3], [7, 6], [4, 0]]
+>>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
+['addset', 'filteredset', 'filteredset']
+
+Populate "_set" fields in the lists so set optimization may be used:
+>>> [1 in xs, 3 in ys]
+[False, True]
+
+Without sort(), results won't be changed:
+>>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
+[[4, 0, 7, 6, 5, 3], [7, 6], [4, 0]]
+>>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
+['addset', 'filteredset', 'filteredset']
+
+With sort():
+>>> xs.sort(reverse=True)
+>>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
+[[7, 6, 4, 0, 5, 3], [7, 6], [4, 0]]
+>>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
+['addset', 'filteredset', 'filteredset']
+
+>>> ys.sort()
+>>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
+[[7, 6, 4, 0, 3, 5], [7, 6], [4, 0]]
+>>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
+['addset', 'filteredset', 'filteredset']
 """
 def __init__(self, data=(), datarepr=None, istopo=False):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 2 V2] smartset: use native set operations as fast paths

2017-02-18 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1487467423 28800
#  Sat Feb 18 17:23:43 2017 -0800
# Node ID 6f57ef05c74567db95f42426499640ad29bc878f
# Parent  deb48622b857d621606a1cdda4adc868b1c663d4
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 6f57ef05c745
smartset: use native set operations as fast paths

For set operations like "&" and "-", where we know both basesets have their
sets ready, and the first set is sorted, use the native Python set
operations as a fast path.

Note: "+" is not optimized as that will break the ordering.

This leads to noticeable improvements on performance:

  revset| before | after | delta
  
  draft() & draft() & draft() & draft() |776 |   477 | -39%
  draft() + draft() + draft() + draft() |   2849 |  2864 |
  draft() - draft() + draft() - draft() |943 |   240 | -75%
  draft() - draft() - draft() - draft() |557 |   197 | -64%

  (time measured in microseconds)

diff --git a/mercurial/smartset.py b/mercurial/smartset.py
--- a/mercurial/smartset.py
+++ b/mercurial/smartset.py
@@ -172,5 +172,5 @@ class baseset(abstractsmartset):
 [[0, 4, 6, 7, 3, 5], [6, 7], [0, 4]]
 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
-['addset', 'filteredset', 'filteredset']
+['addset', 'baseset', 'baseset']
 
 Construct by a list-like:
@@ -192,10 +192,10 @@ class baseset(abstractsmartset):
 ['addset', 'filteredset', 'filteredset']
 
-With sort():
+With sort(), set optimization could be used:
 >>> xs.sort(reverse=True)
 >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]]
 [[7, 6, 4, 0, 5, 3], [7, 6], [4, 0]]
 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
-['addset', 'filteredset', 'filteredset']
+['addset', 'baseset', 'baseset']
 
 >>> ys.sort()
@@ -203,5 +203,5 @@ class baseset(abstractsmartset):
 [[7, 6, 4, 0, 3, 5], [7, 6], [4, 0]]
 >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]]
-['addset', 'filteredset', 'filteredset']
+['addset', 'baseset', 'baseset']
 """
 def __init__(self, data=(), datarepr=None, istopo=False):
@@ -323,4 +323,20 @@ class baseset(abstractsmartset):
 return None
 
+def _fastsetop(self, other, op):
+# try to use native set operations as fast paths
+if (type(other) is baseset and '_set' in other.__dict__ and '_set' in
+self.__dict__ and self._ascending is not None):
+s = baseset(data=getattr(self._set, op)(other._set))
+s._ascending = self._ascending
+else:
+s = getattr(super(baseset, self), op)(other)
+return s
+
+def __and__(self, other):
+return self._fastsetop(other, '__and__')
+
+def __sub__(self, other):
+return self._fastsetop(other, '__sub__')
+
 def __repr__(self):
 d = {None: '', False: '-', True: '+'}[self._ascending]
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2] smartset: convert set to list lazily

2017-02-18 Thread Martin von Zweigbergk via Mercurial-devel
On Feb 17, 2017 10:02 PM, "Jun Wu"  wrote:

# HG changeset patch
# User Jun Wu 
# Date 1487393969 28800
#  Fri Feb 17 20:59:29 2017 -0800
# Node ID b32af6cafb9b958decb7ae0db7dd754aa5a5f883
# Parent  01eebb65a61d9edcad1665ed747c7092f1ddb8b9
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r
b32af6cafb9b
smartset: convert set to list lazily

If the caller only wants to construct a baseset via a set, and then do
"__contains__" tests. It's unnecessary to initialize the list.

Testing on my unfiltered hg-committed repo where len(draft()) is 2600, this
patch shows about 6% improvement on set intensive queries:

Before:

  $ for i in `seq 5`; hg perfrevset 'draft() & draft() & draft() & draft()'
  ! wall 0.001196 comb 0.00 user 0.00 sys 0.00 (best of 2011)
  ! wall 0.001191 comb 0.00 user 0.00 sys 0.00 (best of 2099)
  ! wall 0.001186 comb 0.01 user 0.01 sys 0.00 (best of 1953)
  ! wall 0.001182 comb 0.00 user 0.00 sys 0.00 (best of 2135)
  ! wall 0.001193 comb 0.00 user 0.00 sys 0.00 (best of 2177)

After:

  $ for i in `seq 5`; hg perfrevset 'draft() & draft() & draft() & draft()'
  ! wall 0.001128 comb 0.00 user 0.00 sys 0.00 (best of 2247)
  ! wall 0.001119 comb 0.00 user 0.00 sys 0.00 (best of 2317)
  ! wall 0.001115 comb 0.00 user 0.00 sys 0.00 (best of 2244)
  ! wall 0.001131 comb 0.00 user 0.00 sys 0.00 (best of 2093)
  ! wall 0.001124 comb 0.00 user 0.00 sys 0.00 (best of 2134)

It could have bigger impact on larger sets in theory.

diff --git a/mercurial/smartset.py b/mercurial/smartset.py
--- a/mercurial/smartset.py
+++ b/mercurial/smartset.py
@@ -172,6 +172,10 @@ class baseset(abstractsmartset):
 # set has no order we pick one for stability purpose
 self._ascending = True
-data = list(data)
-self._list = data
+# converting set to list has a cost, do it lazily
+data = None
+else:
+data = list(data)
+if data is not None:
+self._list = data
 self._datarepr = datarepr

@@ -186,4 +190,10 @@ class baseset(abstractsmartset):
 return asclist

+@util.propertycache
+def _list(self):
+# _list is only lazily constructed if we have _set
+assert '_set' in self.__dict__
+return list(self._set)
+
 def __iter__(self):
 if self._ascending is None:
@@ -205,5 +215,5 @@ class baseset(abstractsmartset):

 def __nonzero__(self):
-return bool(self._list)
+return bool(len(self))


Could delete method, I think. Just FYI.


 def sort(self, reverse=False):
@@ -219,5 +229,8 @@ class baseset(abstractsmartset):

 def __len__(self):
-return len(self._list)
+if '_list' in self.__dict__:
+return len(self._list)
+else:
+return len(self._set)

 def isascending(self):
___
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 py3] ui: construct _keepalnum list in a python3-friendly way

2017-02-18 Thread Martijn Pieters
On 16 Feb 2017, at 16:35, Augie Fackler mailto:r...@durin42.com>> wrote:
> +if pycompat.ispy3:
> +_unicodes = [bytes([c]).decode('latin1') for c in range(256)]
> +_notalnum = [s.encode('latin1') for s in _unicodes if not s.isalnum()]

...
> +_keepalnum = ''.join(_notalnum)

This could be more cheaply calculated as

_keepalnum = bytes(c for c in range(256) if not chr(c).isalnum())

This takes a third of the time.

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


Re: [PATCH 8 of 9 pager v2] annotate: migrate to modern pager API

2017-02-18 Thread Augie Fackler

> On Feb 18, 2017, at 3:11 PM, Martin von Zweigbergk  
> wrote:
> 
>> > --- a/mercurial/commands.py
>> > +++ b/mercurial/commands.py
>> > @@ -361,6 +361,7 @@ def annotate(ui, repo, *pats, **opts):
>> >
>> >  Returns 0 on success.
>> >  """
>> > +ui.pager('annotate')
>> >  if not pats:
>> >  raise error.Abort(_('at least one filename or pattern is 
>> > required'))
>> 
>> Just to make sure. Do we plan to delay ui.pager() call so short error 
>> messages
>> (and password prompt, etc.) won't be paged?
>> 
> I was wondering the same, but was hoping the pager would be configured to 
> exit if the full text would fit. I have no idea if that's true for most 
> systems out there, though. I don't believe I've manually configured mine that 
> way, so I suspect it's that way be default on our custom Ubuntu. I guess 
> pager on by default will be pretty annoying if that is not a common default 
> configuration, so I really hope it is.

I don’t think that’s a safe assumption, sadly. I’ll do a follow-up to try and 
make sure that things are sane at least at a high level.

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


Re: [PATCH 8 of 9 pager v2] annotate: migrate to modern pager API

2017-02-18 Thread Martin von Zweigbergk via Mercurial-devel
On Feb 18, 2017 03:18, "Yuya Nishihara"  wrote:

On Thu, 16 Feb 2017 11:59:17 -0500, Augie Fackler wrote:
> # HG changeset patch
> # User Augie Fackler 
> # Date 1486439567 18000
> #  Mon Feb 06 22:52:47 2017 -0500
> # Node ID 4c2f3f1b67a71401faff082dbca79a3f212b5499
> # Parent  935dccd057eb61b980901b5c7a806fac9fb55d0f
> annotate: migrate to modern pager API
>
> diff --git a/hgext/pager.py b/hgext/pager.py
> --- a/hgext/pager.py
> +++ b/hgext/pager.py
> @@ -110,4 +110,4 @@ def uisetup(ui):
>  extensions.wrapfunction(dispatch, '_runcommand', pagecmd)
>  extensions.afterloaded('color', afterloaded)
>
> -attended = ['annotate', 'cat', 'diff', 'export', 'glog', 'log', 'qdiff']
> +attended = ['cat', 'diff', 'export', 'glog', 'log', 'qdiff']
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -361,6 +361,7 @@ def annotate(ui, repo, *pats, **opts):
>
>  Returns 0 on success.
>  """
> +ui.pager('annotate')
>  if not pats:
>  raise error.Abort(_('at least one filename or pattern is
required'))

Just to make sure. Do we plan to delay ui.pager() call so short error
messages
(and password prompt, etc.) won't be paged?


I was wondering the same, but was hoping the pager would be configured to
exit if the full text would fit. I have no idea if that's true for most
systems out there, though. I don't believe I've manually configured mine
that way, so I suspect it's that way be default on our custom Ubuntu. I
guess pager on by default will be pretty annoying if that is not a common
default configuration, so I really hope it is.


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


[PATCH 2 of 2] chg: deduplicate error handling of ui.system()

2017-02-18 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1487434605 -32400
#  Sun Feb 19 01:16:45 2017 +0900
# Node ID d38553996c178b051dd8ed9aa99149b3952d09d3
# Parent  c6dd20729bb3fd2f7745139c27488ce7279f13e1
chg: deduplicate error handling of ui.system()

This moves 'onerr' handling from low-level util.system() to higher level,
which seems better API separation.

diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py
--- a/mercurial/chgserver.py
+++ b/mercurial/chgserver.py
@@ -179,7 +179,7 @@ def _newchgui(srcui, csystem, attachio):
 else:
 self._csystem = csystem
 
-def _runsystem(self, cmd, environ, cwd, onerr, errprefix, out):
+def _runsystem(self, cmd, environ, cwd, out):
 # fallback to the original system method if the output needs to be
 # captured (to self._buffers), or the output stream is not stdout
 # (e.g. stderr, cStringIO), because the chg client is not aware of
@@ -187,17 +187,9 @@ def _newchgui(srcui, csystem, attachio):
 if (out is not self.fout
 or not util.safehasattr(self.fout, 'fileno')
 or self.fout.fileno() != util.stdout.fileno()):
-return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr,
-   errprefix=errprefix, out=out)
+return util.system(cmd, environ=environ, cwd=cwd, out=out)
 self.flush()
-rc = self._csystem(cmd, util.shellenviron(environ), cwd)
-if rc and onerr:
-errmsg = '%s %s' % (os.path.basename(cmd.split(None, 1)[0]),
-util.explainexit(rc)[0])
-if errprefix:
-errmsg = '%s: %s' % (errprefix, errmsg)
-raise onerr(errmsg)
-return rc
+return self._csystem(cmd, util.shellenviron(environ), cwd)
 
 def _runpager(self, cmd):
 self._csystem(cmd, util.shellenviron(), type='pager',
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -1246,6 +1246,9 @@ class ui(object):
blockedtag=None):
 '''execute shell command with appropriate output stream. command
 output will be redirected if fout is not stdout.
+
+if command fails and onerr is None, return status, else raise onerr
+object as exception.
 '''
 if blockedtag is None:
 blockedtag = 'unknown_system_' + cmd.translate(None, _keepalnum)
@@ -1253,14 +1256,19 @@ class ui(object):
 if any(s[1] for s in self._bufferstates):
 out = self
 with self.timeblockedsection(blockedtag):
-return self._runsystem(cmd, environ=environ, cwd=cwd, onerr=onerr,
-   errprefix=errprefix, out=out)
+rc = self._runsystem(cmd, environ=environ, cwd=cwd, out=out)
+if rc and onerr:
+errmsg = '%s %s' % (os.path.basename(cmd.split(None, 1)[0]),
+util.explainexit(rc)[0])
+if errprefix:
+errmsg = '%s: %s' % (errprefix, errmsg)
+raise onerr(errmsg)
+return rc
 
-def _runsystem(self, cmd, environ, cwd, onerr, errprefix, out):
+def _runsystem(self, cmd, environ, cwd, out):
 """actually execute the given shell command (can be overridden by
 extensions like chg)"""
-return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr,
-   errprefix=errprefix, out=out)
+return util.system(cmd, environ=environ, cwd=cwd, out=out)
 
 def traceback(self, exc=None, force=False):
 '''print exception traceback if traceback printing enabled or forced.
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -1011,20 +1011,16 @@ def shellenviron(environ=None):
 env['HG'] = hgexecutable()
 return env
 
-def system(cmd, environ=None, cwd=None, onerr=None, errprefix=None, out=None):
+def system(cmd, environ=None, cwd=None, out=None):
 '''enhanced shell command execution.
 run with environment maybe modified, maybe in different dir.
 
-if command fails and onerr is None, return status, else raise onerr
-object as exception.
-
 if out is specified, it is assumed to be a file-like object that has a
 write() method. stdout and stderr will be redirected to out.'''
 try:
 stdout.flush()
 except Exception:
 pass
-origcmd = cmd
 cmd = quotecommand(cmd)
 if pycompat.sysplatform == 'plan9' and (sys.version_info[0] == 2
 and sys.version_info[1] < 7):
@@ -1048,12 +1044,6 @@ def system(cmd, environ=None, cwd=None, 
 rc = proc.returncode
 if pycompat.sysplatform == 'OpenVMS' and rc & 1:
 rc = 0
-if rc and onerr:
-errmsg = '%s %s' % (os.path.basename(origcmd.split(None

[PATCH 1 of 2] chg: refactor ui.system() to be partly overridden

2017-02-18 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1487433610 -32400
#  Sun Feb 19 01:00:10 2017 +0900
# Node ID c6dd20729bb3fd2f7745139c27488ce7279f13e1
# Parent  22722c297b33c2f68a8a34e0b0be0e6a9e0f4759
chg: refactor ui.system() to be partly overridden

Since fd598149112b changed the signature of ui.system(), chgui.system()
should have been updated. This patch factors out the util.system() call
so that chg can override how a shell command is executed.

diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py
--- a/mercurial/chgserver.py
+++ b/mercurial/chgserver.py
@@ -179,17 +179,16 @@ def _newchgui(srcui, csystem, attachio):
 else:
 self._csystem = csystem
 
-def system(self, cmd, environ=None, cwd=None, onerr=None,
-   errprefix=None):
+def _runsystem(self, cmd, environ, cwd, onerr, errprefix, out):
 # fallback to the original system method if the output needs to be
 # captured (to self._buffers), or the output stream is not stdout
 # (e.g. stderr, cStringIO), because the chg client is not aware of
 # these situations and will behave differently (write to stdout).
-if (any(s[1] for s in self._bufferstates)
+if (out is not self.fout
 or not util.safehasattr(self.fout, 'fileno')
 or self.fout.fileno() != util.stdout.fileno()):
-return super(chgui, self).system(cmd, environ, cwd, onerr,
- errprefix)
+return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr,
+   errprefix=errprefix, out=out)
 self.flush()
 rc = self._csystem(cmd, util.shellenviron(environ), cwd)
 if rc and onerr:
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -1253,8 +1253,14 @@ class ui(object):
 if any(s[1] for s in self._bufferstates):
 out = self
 with self.timeblockedsection(blockedtag):
-return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr,
-   errprefix=errprefix, out=out)
+return self._runsystem(cmd, environ=environ, cwd=cwd, onerr=onerr,
+   errprefix=errprefix, out=out)
+
+def _runsystem(self, cmd, environ, cwd, onerr, errprefix, out):
+"""actually execute the given shell command (can be overridden by
+extensions like chg)"""
+return util.system(cmd, environ=environ, cwd=cwd, onerr=onerr,
+   errprefix=errprefix, out=out)
 
 def traceback(self, exc=None, force=False):
 '''print exception traceback if traceback printing enabled or forced.
diff --git a/tests/test-chg.t b/tests/test-chg.t
--- a/tests/test-chg.t
+++ b/tests/test-chg.t
@@ -32,6 +32,46 @@ long socket path
 
   $ cd ..
 
+editor
+--
+
+  $ cat >> pushbuffer.py < def reposetup(ui, repo):
+  > repo.ui.pushbuffer(subproc=True)
+  > EOF
+
+  $ chg init editor
+  $ cd editor
+
+by default, system() should be redirected to the client:
+
+  $ touch foo
+  $ CHGDEBUG= HGEDITOR=cat chg ci -Am channeled --edit 2>&1 \
+  > | egrep "HG:|run 'cat"
+  chg: debug: run 'cat "*"' at '$TESTTMP/editor' (glob)
+  HG: Enter commit message.  Lines beginning with 'HG:' are removed.
+  HG: Leave message empty to abort commit.
+  HG: --
+  HG: user: test
+  HG: branch 'default'
+  HG: added foo
+
+but no redirection should be made if output is captured:
+
+  $ touch bar
+  $ CHGDEBUG= HGEDITOR=cat chg ci -Am bufferred --edit \
+  > --config extensions.pushbuffer="$TESTTMP/pushbuffer.py" 2>&1 \
+  > | egrep "HG:|run 'cat"
+  [1]
+
+check that commit commands succeeded:
+
+  $ hg log -T '{rev}:{desc}\n'
+  1:bufferred
+  0:channeled
+
+  $ cd ..
+
 pager
 -
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: RFC: bitmap storage for precursors and phases

2017-02-18 Thread Stanislau Hlebik
Excerpts from Jun Wu's message of 2017-02-17 19:14:12 -0800:
> Excerpts from Bryan O'Sullivan's message of 2017-02-17 13:29:58 -0800:
> > On Fri, Feb 17, 2017 at 10:30 AM, Jun Wu  wrote:
> > 
> > > Excerpts from Stanislau Hlebik's message of 2017-02-17 11:24:34 +:
> > > > As I said before we will load all non-public revs in one set and all
> > >
> > > The problem is, loading a Python set from disk is O(size-of-the-set).
> > >
> > > Bitmap's loading cost should be basically 0 (with mmap). I think that's 
> > > why
> > > we want bitmap at the first place. There are other choices like packfile
> > > index, hash tables, but bitmap is the simplest and most efficient.
> > >
> > 
> > Hey folks,
> > 
> > I haven't yet seen mention of some considerations that seem very important
> > in driving the decision-making, so I'd appreciate it if someone could fill
> > me in.
> > 
> > Firstly, what's our current understanding of the sizes and compositions of
> > these sets of numbers? In theory, we have a lot of data from practical
> > application at Facebook, but nobody's brought it up.
> > 
> > To clarify why this matters, if an obsstore contains say 100 entries, then
> > a very naive implementation should be fine. If it's related to something
> > else, such as the size of, amount of activity in, or local age of a repo,
> > then maybe we have a different set of decisions to make.
> 
> First, I agree that if N is small, O(N) or O(log(N)), or O(1), do not matter
> much in practice. I tend to always reason about future-proof solutions,
> which may or may not be a good habit - I'll adjust in the future.
> 
> I think there are multiple topics being discussed:
> 
>   1. How to solve the overhead loading hiddenrevs with minimal changes?
>   2. Why is the bitmap format interesting (future use-cases)?
> 
> For 1,
> 
>   I once tried to make one bit of revlog flag as the source of truth of
>   "hidden", which looks a nice solution. But it got rejected because revlog
>   has to be append-only. Moving the flag bits out formed the bitmap idea
>   naturally.
> 
>   Bitmap fits here but it does not mean we have to use it to solve this
>   particular problem. For example, stateful chg will get us some easy wins,
>   and see the problem analysis and proposed solution below.
> 
>   Note that we actually have a simple caching format for the "hiddenrevs".
>   See repoview.py, computehidden.
> 
>   But what's wrong with "computehidden" is the choice of the cache key - it
>   calls "hideablerevs", which takes 0.5 seconds in obsolete.getrevs(repo,
>   'obsolete'), which reads the giant obsstore (in hg-committed) and do some
>   complex computation. The result is then hashed and used as a cache key of
>   "computehidden".
> 
>   So, if we do not want to know the "obsolete()" revisions, but just want to
>   know what's hidden. Changing the cache key would be a very straightforward
>   and effective solution which does not require a new file format.

Hm, changing the cache key to smth like phaseroots + obsstore +
changelog mtime + size  may be an easy and good win. That's a good idea.
Although it will still get invalidated after each write.

> 
>   That'll help commands like "hg st", "hg log -T foo", etc. But it won't
>   help complex "log"s which do require the "obsolete()" revisions. To speed
>   up the latter, we can probably just copy the caching infrastructure from
>   repoview.py.
> 
> For 2,
> 
>   len(filteredrevs) in my hg-committed is 2155. It's small. I tend to think
>   about solutions that scale longer and are not too complex to build. That
>   may or may not be a good habit.
>   
>   That said, I agree if the set is small and perf, then whatever easier to
>   implement makes sense.
>   
>   I have some crazy ideas about the future where a giant bitmap is
>   practically useful. For example, source controlling "visible heads" and
>   the obsstore, then adding some C code to quickly fill a bitmap (requires
>   "set" and "setancestors/descendants"), then we can show the user whenever
>   their repo used to look like back in any time by using the bitmap filter.
>   That'll help investigate hard issues, and implement "hg undo".
> 
> > Secondly, what operations are being performed on these sets today, and do
> > we know if those operations are going to change?
> >
> > For instance, if a may be extended via new elements added to its end, then
> > an mmap-based implementation immediately becomes awkward. If a set is
> 
> Not that bad if we preallocate space.
> 
> > traversed or we perform operations like union or intersection, then a
> > bitmap might make sense if the set is very small and dense, but not if it's
> > big and sparse.
> 
> Not necessarily true if we use an advanced variant, like the "roaringbitmap"
> mentioned by you last year [1].
> 
> [1]: 
> https://www.mercurial-scm.org/pipermail/mercurial-devel/2016-September/087864.html
> 
> > (Jun's idea that mmap is effectively free is also not borne out in
> > practice, but that's 

Re: [PATCH 2 of 3 V2] revset: use phasecache.getrevset

2017-02-18 Thread Yuya Nishihara
On Sat, 18 Feb 2017 00:56:09 -0800, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu 
> # Date 1487407171 28800
> #  Sat Feb 18 00:39:31 2017 -0800
> # Node ID 432992303718ec631b81a351795071c34cfe68f6
> # Parent  7e30a7c38d845e9a526a7ac64c648f18ec51687e
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #  hg pull https://bitbucket.org/quark-zju/hg-draft -r 
> 432992303718
> revset: use phasecache.getrevset

> For the pure Python implementation, some operations are faster while "not
> draft()" is noticeably slower:
> 
>   revset  | public()  | not public()  | draft()   | not draft()
>   hidden  |  yes  |  no   |   yes |  no   | yes   |  no   | yes   |  no
>   
>   before  | 18852 | 17183 | 17758 | 15921 | 17505 | 15973 | 41521 | 39822
>   after   | 18924 | 17380 | 17558 | 14545 | 16727 | 13593 | 48356 | 43992
>   delta   |   |   -9% |   -5% |  -15% |  +16% |  +10%
> 
> That may be the different performance characters of generatorset vs.
> filteredset. The "not draft()" query could be optimized in this case where
> both "public" and "secret" are passed to "getrevsets" so it won't iterate
> the whole repo twice.

Yeah, generatorset is somewhat costly for membership tests. Instead, phasecache
could return a filteredset, but it wouldn't be always faster.

  s = smartset.fullreposet(repo)
  s.filter(condition, condrepr=('', phases), cache=False)

I see no regression in contrib/base-revsets.txt, and the performance difference
is only seen in pure build, so this series seems good. Queued, thanks.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


mercurial@31011: 13 new changesets

2017-02-18 Thread Mercurial Commits
13 new changesets in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/334cf948c758
changeset:   30999:334cf948c758
user:Augie Fackler 
date:Mon Feb 06 22:52:47 2017 -0500
summary: annotate: migrate to modern pager API

https://www.mercurial-scm.org/repo/hg/rev/84ec2d6a2831
changeset:   31000:84ec2d6a2831
user:Augie Fackler 
date:Mon Feb 06 23:22:04 2017 -0500
summary: tests: prove that ignore works

https://www.mercurial-scm.org/repo/hg/rev/e7eca6e1372e
changeset:   31001:e7eca6e1372e
user:Rainer Woitok 
date:Fri Feb 17 11:08:36 2017 +0100
summary: doc: correct example concerning "hg purge" alias in man page 
"hgrc.5"

https://www.mercurial-scm.org/repo/hg/rev/a489ee9b2852
changeset:   31002:a489ee9b2852
user:Jun Wu 
date:Fri Feb 17 00:59:09 2017 -0800
summary: runtests: prefer IPv4 to IPv6

https://www.mercurial-scm.org/repo/hg/rev/225f574e0645
changeset:   31003:225f574e0645
user:Jun Wu 
date:Wed Feb 15 21:03:42 2017 -0800
summary: runtests: export HGIPV6 to hint test scripts whether to use IPv6

https://www.mercurial-scm.org/repo/hg/rev/d05fefbb5ab3
changeset:   31004:d05fefbb5ab3
user:Jun Wu 
date:Wed Feb 15 21:09:00 2017 -0800
summary: dumbhttp: use IPv6 if HGIPV6 is set to 1

https://www.mercurial-scm.org/repo/hg/rev/d8d698bcdcd6
changeset:   31005:d8d698bcdcd6
user:Jun Wu 
date:Wed Feb 15 22:53:45 2017 -0800
summary: tinyproxy: use IPv6 if HGIPV6 is set to 1

https://www.mercurial-scm.org/repo/hg/rev/d4916aebf3d0
changeset:   31006:d4916aebf3d0
user:Jun Wu 
date:Thu Feb 16 08:01:19 2017 -0800
summary: runtests: export LOCALIP

https://www.mercurial-scm.org/repo/hg/rev/bfdb0741f9f2
changeset:   31007:bfdb0741f9f2
user:Jun Wu 
date:Wed Feb 15 23:24:03 2017 -0800
summary: dummyssh: use LOCALIP

https://www.mercurial-scm.org/repo/hg/rev/636cf3f7620d
changeset:   31008:636cf3f7620d
user:Jun Wu 
date:Thu Feb 16 09:38:52 2017 -0800
summary: tests: use LOCALIP

https://www.mercurial-scm.org/repo/hg/rev/161ab32b44a1
changeset:   31009:161ab32b44a1
user:Jun Wu 
date:Thu Feb 16 00:13:29 2017 -0800
summary: runtests: set web.address to localhost

https://www.mercurial-scm.org/repo/hg/rev/09ec648cd2a9
changeset:   31010:09ec648cd2a9
user:Jun Wu 
date:Thu Feb 16 08:43:59 2017 -0800
summary: runtests: always set web.ipv6

https://www.mercurial-scm.org/repo/hg/rev/01eebb65a61d
changeset:   31011:01eebb65a61d
bookmark:@
tag: tip
user:Jun Wu 
date:Fri Feb 17 01:21:15 2017 -0800
summary: runtests: add an IPv6 command line flag

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


Re: [PATCH 07 of 10 ipv6 V2] tests: use LOCALIP

2017-02-18 Thread Yuya Nishihara
On Fri, 17 Feb 2017 10:51:21 -0800, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu 
> # Date 1487266732 28800
> #  Thu Feb 16 09:38:52 2017 -0800
> # Node ID 1ea3da89ecc44b59e96cb366e6388c1ac178d3af
> # Parent  bb7f41b2c8043a3115f242fb9b9f71ee461c93a9
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #  hg pull https://bitbucket.org/quark-zju/hg-draft -r 
> 1ea3da89ecc4
> tests: use LOCALIP
> 
> This patch replaces hardcoded 127.0.0.1 with $LOCALIP in all tests.
> 
> Till now, the IPv6 series should make tests pass on common IPv6 systems
> where the local device has the address "::1" and the hostname "localhost"
> resolves to "::1".

> -  $ hg clone http://127.0.0.1:3121/a b
> +  $ hg clone http://$LOCALIP:3121/a b

I'm a little surprised that "http://::1:3121/"; just works thanks to ":3121".
Perhaps it's invalid and should be "http://[::1]:3121/";.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 8 of 9 pager v2] annotate: migrate to modern pager API

2017-02-18 Thread Yuya Nishihara
On Thu, 16 Feb 2017 11:59:17 -0500, Augie Fackler wrote:
> # HG changeset patch
> # User Augie Fackler 
> # Date 1486439567 18000
> #  Mon Feb 06 22:52:47 2017 -0500
> # Node ID 4c2f3f1b67a71401faff082dbca79a3f212b5499
> # Parent  935dccd057eb61b980901b5c7a806fac9fb55d0f
> annotate: migrate to modern pager API
> 
> diff --git a/hgext/pager.py b/hgext/pager.py
> --- a/hgext/pager.py
> +++ b/hgext/pager.py
> @@ -110,4 +110,4 @@ def uisetup(ui):
>  extensions.wrapfunction(dispatch, '_runcommand', pagecmd)
>  extensions.afterloaded('color', afterloaded)
>  
> -attended = ['annotate', 'cat', 'diff', 'export', 'glog', 'log', 'qdiff']
> +attended = ['cat', 'diff', 'export', 'glog', 'log', 'qdiff']
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -361,6 +361,7 @@ def annotate(ui, repo, *pats, **opts):
>  
>  Returns 0 on success.
>  """
> +ui.pager('annotate')
>  if not pats:
>  raise error.Abort(_('at least one filename or pattern is required'))

Just to make sure. Do we plan to delay ui.pager() call so short error messages
(and password prompt, etc.) won't be paged?
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


mercurial@30998: 17 new changesets

2017-02-18 Thread Mercurial Commits
17 new changesets in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/08e6f4dac2ca
changeset:   30982:08e6f4dac2ca
user:Simon Farnsworth 
date:Wed Feb 15 13:34:06 2017 -0800
summary: extdiff: log time spent in external diff program

https://www.mercurial-scm.org/repo/hg/rev/d4825798818b
changeset:   30983:d4825798818b
user:Simon Farnsworth 
date:Wed Feb 15 13:34:06 2017 -0800
summary: histedit: log the time taken to read in the commands list

https://www.mercurial-scm.org/repo/hg/rev/15f9084a9a0c
changeset:   30984:15f9084a9a0c
user:Jun Wu 
date:Wed Feb 15 16:18:31 2017 -0800
summary: runtests: add a function to test if IPv6 is available

https://www.mercurial-scm.org/repo/hg/rev/1f803482844a
changeset:   30985:1f803482844a
user:Jun Wu 
date:Wed Feb 15 16:22:22 2017 -0800
summary: runtests: checkportisavailable should only check one family

https://www.mercurial-scm.org/repo/hg/rev/f07ca071a058
changeset:   30986:f07ca071a058
user:Jun Wu 
date:Wed Feb 15 16:43:27 2017 -0800
summary: runtests: set web.ipv6 if we use IPv6

https://www.mercurial-scm.org/repo/hg/rev/1ee685defe80
changeset:   30987:1ee685defe80
user:Jun Wu 
date:Wed Feb 15 16:29:58 2017 -0800
summary: runtests: unindent an "if True" block

https://www.mercurial-scm.org/repo/hg/rev/d194f0dba7ac
changeset:   30988:d194f0dba7ac
user:Pulkit Goyal <7895pul...@gmail.com>
date:Thu Feb 16 17:30:35 2017 +0530
summary: py3: convert the mode argument of os.fdopen to unicodes

https://www.mercurial-scm.org/repo/hg/rev/74af89c66834
changeset:   30989:74af89c66834
user:Jun Wu 
date:Wed Feb 15 19:41:14 2017 -0800
summary: localrepo: move extension loading to a separate method

https://www.mercurial-scm.org/repo/hg/rev/cb899ee133d8
changeset:   30990:cb899ee133d8
user:Jun Wu 
date:Thu Feb 16 23:10:47 2017 -0800
summary: chgserver: move comments in config example

https://www.mercurial-scm.org/repo/hg/rev/3844b3299a53
changeset:   30991:3844b3299a53
user:Jun Wu 
date:Thu Feb 16 10:33:59 2017 -0800
summary: test-logtoprocess: use cat to wait for outputs

https://www.mercurial-scm.org/repo/hg/rev/61b4122019d3
changeset:   30992:61b4122019d3
user:Augie Fackler 
date:Wed Feb 15 17:47:51 2017 -0500
summary: pager: move pager-initiating code into core

https://www.mercurial-scm.org/repo/hg/rev/9c2977ceaa46
changeset:   30993:9c2977ceaa46
user:Augie Fackler 
date:Wed Feb 15 17:47:57 2017 -0500
summary: pager: move more behavior into core

https://www.mercurial-scm.org/repo/hg/rev/3ed6e43998df
changeset:   30994:3ed6e43998df
user:Augie Fackler 
date:Wed Feb 15 17:48:03 2017 -0500
summary: ui: introduce neverpager() call

https://www.mercurial-scm.org/repo/hg/rev/5e85bab867a7
changeset:   30995:5e85bab867a7
user:Augie Fackler 
date:Mon Feb 06 23:21:45 2017 -0500
summary: ui: add ignore-single-command functionality

https://www.mercurial-scm.org/repo/hg/rev/cc3c9b6f1e09
changeset:   30996:cc3c9b6f1e09
user:Augie Fackler 
date:Mon Feb 06 23:45:30 2017 -0500
summary: tests: clean up a bunch of pager testing that is about to be 
invalidated

https://www.mercurial-scm.org/repo/hg/rev/29a4a8d01bc9
changeset:   30997:29a4a8d01bc9
user:Augie Fackler 
date:Mon Feb 06 23:42:04 2017 -0500
summary: ui: respect historic pager.attend-$COMMAND=no

https://www.mercurial-scm.org/repo/hg/rev/75e325ce538e
changeset:   30998:75e325ce538e
bookmark:@
tag: tip
user:Augie Fackler 
date:Mon Feb 06 23:55:54 2017 -0500
summary: ui: add a debug print right before we start the pager

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


mercurial@30981: 11 new changesets

2017-02-18 Thread Mercurial Commits
11 new changesets in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/bb6385882cfa
changeset:   30971:bb6385882cfa
user:Pierre-Yves David 
date:Thu Dec 22 02:34:22 2016 +0100
summary: color: move configstyles into the core module

https://www.mercurial-scm.org/repo/hg/rev/a3c7e42c7a1f
changeset:   30972:a3c7e42c7a1f
user:Pierre-Yves David 
date:Thu Dec 22 02:37:18 2016 +0100
summary: color: move '_effect_str' function into the core module

https://www.mercurial-scm.org/repo/hg/rev/e5363cb96233
changeset:   30973:e5363cb96233
user:Pierre-Yves David 
date:Thu Dec 22 02:38:53 2016 +0100
summary: color: move the '_render_effects' function to the core module

https://www.mercurial-scm.org/repo/hg/rev/ae5d60bb70c9
changeset:   30974:ae5d60bb70c9
user:Simon Farnsworth 
date:Wed Feb 15 11:53:59 2017 -0800
summary: util: introduce timer()

https://www.mercurial-scm.org/repo/hg/rev/22fbca1d11ed
changeset:   30975:22fbca1d11ed
user:Simon Farnsworth 
date:Wed Feb 15 13:17:39 2017 -0800
summary: mercurial: switch to util.timer for all interval timings

https://www.mercurial-scm.org/repo/hg/rev/e92daf156d5c
changeset:   30976:e92daf156d5c
user:Simon Farnsworth 
date:Wed Feb 15 13:17:45 2017 -0800
summary: ui: provide a mechanism to track and log blocked time

https://www.mercurial-scm.org/repo/hg/rev/5a9e4dc8e4fd
changeset:   30977:5a9e4dc8e4fd
user:Simon Farnsworth 
date:Wed Feb 15 13:07:26 2017 -0800
summary: contrib: add a write microbenchmark to perf.py

https://www.mercurial-scm.org/repo/hg/rev/fdecd24ca4dc
changeset:   30978:fdecd24ca4dc
user:Simon Farnsworth 
date:Wed Feb 15 13:50:06 2017 -0800
summary: ui: log time spent blocked on stdio

https://www.mercurial-scm.org/repo/hg/rev/fd598149112b
changeset:   30979:fd598149112b
user:Simon Farnsworth 
date:Wed Feb 15 13:29:12 2017 -0800
summary: ui: time calls to ui.system

https://www.mercurial-scm.org/repo/hg/rev/60b5db2ab586
changeset:   30980:60b5db2ab586
user:Simon Farnsworth 
date:Wed Feb 15 13:38:00 2017 -0800
summary: ui: give editor() a tag of its own

https://www.mercurial-scm.org/repo/hg/rev/a0c4e57074fe
changeset:   30981:a0c4e57074fe
bookmark:@
tag: tip
user:Simon Farnsworth 
date:Wed Feb 15 13:34:06 2017 -0800
summary: crecord: log blocked time waiting for curses input

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


Re: [PATCH 03 of 10 v5] ui: provide a mechanism to track and log blocked time

2017-02-18 Thread Yuya Nishihara
On Wed, 15 Feb 2017 14:06:53 -0800, Simon Farnsworth wrote:
> # HG changeset patch
> # User Simon Farnsworth 
> # Date 1487193465 28800
> #  Wed Feb 15 13:17:45 2017 -0800
> # Node ID f3a219226ba0658f72801329d07c1ba516152b70
> # Parent  1c71bddbe01e76c1c48b5479ff67d47645afd7b6
> ui: provide a mechanism to track and log blocked time

>  finally:
>  duration = util.timer() - starttime
>  req.ui.flush()
> +if req.ui.logblockedtimes:
> +req.ui._blockedtimes['command_duration'] = duration * 1000
> +req.ui.log('uiblocked', 'ui blocked ms', **req.ui._blockedtimes)

[snip]

>  self._reportuntrusted = self.debugflag or self.configbool("ui",
>  "report_untrusted", True)
>  self.tracebackflag = self.configbool('ui', 'traceback', False)
> +self.logblockedtimes = self.configbool('ui', 'logblockedtimes')

Just curious. Why this config knob is needed only to suppress the output?
I thought this would stop tracking the blocked time at all.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH] help: add pointer how to narrow list of resolved/unresolved files (issue5469)

2017-02-18 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1487408401 -32400
#  Sat Feb 18 18:00:01 2017 +0900
# Node ID ceef988474afe31056a2d8fcef67526cf43c2d6f
# Parent  1ca3469fdd08c0d5d814a4bc359869bc157c7fc9
help: add pointer how to narrow list of resolved/unresolved files (issue5469)

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -4259,6 +4259,8 @@ def resolve(ui, repo, *pats, **opts):
 
 - :hg:`resolve -l`: list files which had or still have conflicts.
   In the printed list, ``U`` = unresolved and ``R`` = resolved.
+  You can use ``set:unresolved()`` or ``set:resolved()`` to filter
+  the list. See :hg:`help filesets` for details.
 
 .. note::
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH] smartset: reorder initialization of baseset in more intuitive way

2017-02-18 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1487407072 -32400
#  Sat Feb 18 17:37:52 2017 +0900
# Node ID 1ca3469fdd08c0d5d814a4bc359869bc157c7fc9
# Parent  3f4bdcfe63e9f1e357187fa728ae0da9d35b3973
smartset: reorder initialization of baseset in more intuitive way

What we want to do is to assign either _set or _list per the given data
type.

diff --git a/mercurial/smartset.py b/mercurial/smartset.py
--- a/mercurial/smartset.py
+++ b/mercurial/smartset.py
@@ -166,16 +166,14 @@ class baseset(abstractsmartset):
 """
 self._ascending = None
 self._istopo = istopo
-if not isinstance(data, list):
-if isinstance(data, set):
-self._set = data
-# set has no order we pick one for stability purpose
-self._ascending = True
-# converting set to list has a cost, do it lazily
-data = None
-else:
+if isinstance(data, set):
+# converting set to list has a cost, do it lazily
+self._set = data
+# set has no order we pick one for stability purpose
+self._ascending = True
+else:
+if not isinstance(data, list):
 data = list(data)
-if data is not None:
 self._list = data
 self._datarepr = datarepr
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


mercurial@30970: 5 new changesets

2017-02-18 Thread Mercurial Commits
5 new changesets in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/520af4cc34de
changeset:   30966:520af4cc34de
user:Pierre-Yves David 
date:Fri Nov 18 18:43:39 2016 +0100
summary: color: spread '_effect' values for readability

https://www.mercurial-scm.org/repo/hg/rev/20990991d384
changeset:   30967:20990991d384
bookmark:@
user:Pierre-Yves David 
date:Fri Nov 18 18:48:38 2016 +0100
summary: color: move '_effect' mapping into core

https://www.mercurial-scm.org/repo/hg/rev/0d2a58a04080
changeset:   30968:0d2a58a04080
user:Pierre-Yves David 
date:Thu Dec 22 02:23:23 2016 +0100
summary: color: move '_terminfo_params' into the core 'color' module

https://www.mercurial-scm.org/repo/hg/rev/ddc80d1777a6
changeset:   30969:ddc80d1777a6
user:Pierre-Yves David 
date:Thu Dec 22 02:26:50 2016 +0100
summary: color: move 'valideffect' function into the core module

https://www.mercurial-scm.org/repo/hg/rev/683606a829e8
changeset:   30970:683606a829e8
tag: tip
user:Pierre-Yves David 
date:Thu Dec 22 02:30:03 2016 +0100
summary: color: rework conditional 'valideffect'

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


[PATCH 3 of 3 V2] obsolete: avoid using revset language to compute the obsolete revset

2017-02-18 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1487408120 28800
#  Sat Feb 18 00:55:20 2017 -0800
# Node ID 286567ff59dbf6cc5645f878b8b223c94c3e4116
# Parent  432992303718ec631b81a351795071c34cfe68f6
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 286567ff59db
obsolete: avoid using revset language to compute the obsolete revset

This is part of a refactoring that moves some phase query optimization from
revset.py to phases.py. See previous patches for the motivation.

Now we have APIs in phasecache to get the non-public set efficiently, let's
use it directly instead of going through the "not public()" revset language
in "obsolete()" computation.

This patch was meaured using:

  for i in 'public()' 'not public()' 'draft()' 'not draft()'; do
  hg perfrevset "$i"; hg perfrevset "$i" --hidden;
  done

and no noticeable (> 1%) performance difference was observed.

diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -1121,5 +1121,5 @@ def _computeobsoleteset(repo):
 obs = set()
 getnode = repo.changelog.node
-notpublic = repo.revs("not public()")
+notpublic = repo._phasecache.getrevset(repo, (phases.draft, phases.secret))
 for r in notpublic:
 if getnode(r) in repo.obsstore.successors:
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 3 V2] phases: add a getrevset method to phasecache

2017-02-18 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1487400545 28800
#  Fri Feb 17 22:49:05 2017 -0800
# Node ID 7e30a7c38d845e9a526a7ac64c648f18ec51687e
# Parent  1315d68b1dcf55247f51208608d139029eaae632
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 7e30a7c38d84
phases: add a getrevset method to phasecache

This is part of a refactoring that moves some phase query optimization from
revset.py to phases.py.

The motivation behind this was chg repo preloading - to make the obsstore
depend on less things (like the revset language). The refactoring also looks
good by itself - phasecache does not expose its private field "_phasesets"
via public methods and revset.py is accessing it in a hacky way.

This patch adds a "getrevset" method, which takes multiple phases and
returns a revset in an best-effort efficient way - for "public" phase, it
returns a lazy generatorset; for "draft" and "secret", it returns efficient
"baseset".

diff --git a/mercurial/phases.py b/mercurial/phases.py
--- a/mercurial/phases.py
+++ b/mercurial/phases.py
@@ -116,4 +116,5 @@ from . import (
 encoding,
 error,
+smartset,
 )
 
@@ -171,4 +172,25 @@ class phasecache(object):
 self.opener = repo.svfs
 
+def getrevset(self, repo, phases):
+"""return a smartset for the given phases"""
+self.loadphaserevs(repo) # ensure phase's sets are loaded
+
+if self._phasesets and all(self._phasesets[p] is not None
+   for p in phases):
+# fast path - use _phasesets
+revs = self._phasesets[phases[0]]
+if len(phases) > 1:
+revs = revs.copy() # only copy when needed
+for p in phases[1:]:
+revs.update(self._phasesets[p])
+if repo.changelog.filteredrevs:
+revs = revs - repo.changelog.filteredrevs
+return smartset.baseset(revs)
+else:
+# slow path - enumerate all revisions
+phase = self.phase
+revs = (r for r in repo if phase(repo, r) in phases)
+return smartset.generatorset(revs, iterasc=True)
+
 def copy(self):
 # Shallow copy meant to ensure isolation in
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 3 V2] revset: use phasecache.getrevset

2017-02-18 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1487407171 28800
#  Sat Feb 18 00:39:31 2017 -0800
# Node ID 432992303718ec631b81a351795071c34cfe68f6
# Parent  7e30a7c38d845e9a526a7ac64c648f18ec51687e
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 432992303718
revset: use phasecache.getrevset

This is part of a refactoring that moves some phase query optimization from
revset.py to phases.py. See the previous patch for motivation.

This patch changes revset code to use phasecache.getrevset so it no longer
accesses the private field: _phasecache._phasesets directly.

For performance impact, this patch was tested using the following query, on
my hg-committed repo:

for i in 'public()' 'not public()' 'draft()' 'not draft()'; do
echo $i;
hg perfrevset "$i";
hg perfrevset "$i" --hidden;
done

For the CPython implementation, most operations are unchanged (within
+/- 1%), while "not public()" and "draft()" is noticeably faster on an
unfiltered repo. It may be because the new code avoids a set copy if
filteredrevs is empty.

  revset  | public()  | not public() | draft()| not draft()
  hidden  |  yes  |  no   |   yes |  no  | yes |  no  | yes  |  no
  --
  before  | 19006 | 17352 |   239 |  286 | 180 |  228 | 7690 | 5745
  after   | 19137 | 17231 |   240 |  207 | 182 |  150 | 7687 | 5658
  delta   |   | -38% | | -52% |

  (timed in microseconds)

For the pure Python implementation, some operations are faster while "not
draft()" is noticeably slower:

  revset  | public()  | not public()  | draft()   | not draft()
  hidden  |  yes  |  no   |   yes |  no   | yes   |  no   | yes   |  no
  
  before  | 18852 | 17183 | 17758 | 15921 | 17505 | 15973 | 41521 | 39822
  after   | 18924 | 17380 | 17558 | 14545 | 16727 | 13593 | 48356 | 43992
  delta   |   |   -9% |   -5% |  -15% |  +16% |  +10%

That may be the different performance characters of generatorset vs.
filteredset. The "not draft()" query could be optimized in this case where
both "public" and "secret" are passed to "getrevsets" so it won't iterate
the whole repo twice.

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -1645,17 +1645,8 @@ def parents(repo, subset, x):
 return subset & ps
 
-def _phase(repo, subset, target):
-"""helper to select all rev in phase """
-repo._phasecache.loadphaserevs(repo) # ensure phase's sets are loaded
-if repo._phasecache._phasesets:
-s = repo._phasecache._phasesets[target] - repo.changelog.filteredrevs
-s = baseset(s)
-s.sort() # set are non ordered, so we enforce ascending
-return subset & s
-else:
-phase = repo._phasecache.phase
-condition = lambda r: phase(repo, r) == target
-return subset.filter(condition, condrepr=('', target),
- cache=False)
+def _phase(repo, subset, *targets):
+"""helper to select all rev in  phases"""
+s = repo._phasecache.getrevset(repo, targets)
+return subset & s
 
 @predicate('draft()', safe=True)
@@ -1718,18 +1709,5 @@ def present(repo, subset, x):
 def _notpublic(repo, subset, x):
 getargs(x, 0, 0, "_notpublic takes no arguments")
-repo._phasecache.loadphaserevs(repo) # ensure phase's sets are loaded
-if repo._phasecache._phasesets:
-s = set()
-for u in repo._phasecache._phasesets[1:]:
-s.update(u)
-s = baseset(s - repo.changelog.filteredrevs)
-s.sort()
-return subset & s
-else:
-phase = repo._phasecache.phase
-target = phases.public
-condition = lambda r: phase(repo, r) != target
-return subset.filter(condition, condrepr=('', target),
- cache=False)
+return _phase(repo, subset, phases.draft, phases.secret)
 
 @predicate('public()', safe=True)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 2 of 2] smartset: use native set operations as fast paths

2017-02-18 Thread Jun Wu
Excerpts from Yuya Nishihara's message of 2017-02-18 17:27:51 +0900:
> A baseset may be ordered. Native set ops are valid only in unordered context
> (or when both sets have the same explicit ascending flag.)
> 
> Can you add some doctests?

Good catch. I'll add them later. I'm preparing the phasecache patches now.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2] smartset: convert set to list lazily

2017-02-18 Thread Yuya Nishihara
On Fri, 17 Feb 2017 22:02:11 -0800, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu 
> # Date 1487393969 28800
> #  Fri Feb 17 20:59:29 2017 -0800
> # Node ID b32af6cafb9b958decb7ae0db7dd754aa5a5f883
> # Parent  01eebb65a61d9edcad1665ed747c7092f1ddb8b9
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #  hg pull https://bitbucket.org/quark-zju/hg-draft -r 
> b32af6cafb9b
> smartset: convert set to list lazily

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


Re: [PATCH py3] ui: construct _keepalnum list in a python3-friendly way

2017-02-18 Thread Yuya Nishihara
On Thu, 16 Feb 2017 11:35:41 -0500, Augie Fackler wrote:
> # HG changeset patch
> # User Augie Fackler 
> # Date 1487262890 18000
> #  Thu Feb 16 11:34:50 2017 -0500
> # Node ID 791b4e846a7b9a0783440b9504585438777fe2d2
> # Parent  1ee685defe80117cf6aafea1ede6c33c478abceb
> ui: construct _keepalnum list in a python3-friendly way

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


Re: [PATCH 2 of 2] smartset: use native set operations as fast paths

2017-02-18 Thread Yuya Nishihara
On Fri, 17 Feb 2017 22:02:12 -0800, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu 
> # Date 1487396855 28800
> #  Fri Feb 17 21:47:35 2017 -0800
> # Node ID 1315d68b1dcf55247f51208608d139029eaae632
> # Parent  b32af6cafb9b958decb7ae0db7dd754aa5a5f883
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #  hg pull https://bitbucket.org/quark-zju/hg-draft -r 
> 1315d68b1dcf
> smartset: use native set operations as fast paths
> 
> For cases where we know both basesets have their sets ready, use native
> Python set operations as a fast path.
> 
> This leads to noticeable improvements on some set operations:
> 
>   revset| before | after | after/before
>   -
>   draft() & draft() & draft() & draft() |   1123 |   818 | 0.72
>   draft() + draft() + draft() + draft() |   3288 |   817 | 0.25
>   draft() - draft() + draft() - draft() |   1277 |   551 | 0.43
>   draft() - draft() - draft() - draft() |864 |   517 | 0.60
> 
>   (time unit: micro second)
> 
> diff --git a/mercurial/smartset.py b/mercurial/smartset.py
> --- a/mercurial/smartset.py
> +++ b/mercurial/smartset.py
> @@ -278,4 +278,28 @@ class baseset(abstractsmartset):
>  return None
>  
> +def _fastsetop(self, other, op):
> +# try to use native set operations as fast paths
> +if (type(other) is baseset and '_set' in other.__dict__ and '_set' in
> +self.__dict__):
> +if op == '__add__':
> +setop = 'union'
> +else:
> +setop = op  # __sub__ or __and__
> +s = baseset(data=getattr(self._set, setop)(other._set),
> +istopo=self._istopo)
> +s._ascending = self._ascending
> +else:
> +s = getattr(super(baseset, self), op)(other)
> +return s
> +
> +def __add__(self, other):
> +return self._fastsetop(other, '__add__')
> +
> +def __and__(self, other):
> +return self._fastsetop(other, '__and__')
> +
> +def __sub__(self, other):
> +return self._fastsetop(other, '__sub__')

A baseset may be ordered. Native set ops are valid only in unordered context
(or when both sets have the same explicit ascending flag.)

Can you add some doctests?
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel