mercurial@30041: 11 new changesets

2016-10-03 Thread Mercurial Commits
11 new changesets in mercurial:

http://selenic.com/repo/hg//rev/0f6d6fdd3c2a
changeset:   30031:0f6d6fdd3c2a
parent:  30028:3741a8f86e88
user:Yuya Nishihara 
date:Wed Sep 28 20:01:23 2016 +0900
summary: pycompat: provide 'ispy3' constant

http://selenic.com/repo/hg//rev/2219f4f82ede
changeset:   30032:2219f4f82ede
user:Yuya Nishihara 
date:Wed Sep 28 22:32:09 2016 +0900
summary: pycompat: extract function that converts attribute or encoding 
name to str

http://selenic.com/repo/hg//rev/02dbfaa6df0b
changeset:   30033:02dbfaa6df0b
user:Yuya Nishihara 
date:Wed Sep 28 20:39:06 2016 +0900
summary: py3: convert encoding name and mode to str

http://selenic.com/repo/hg//rev/e4a6b439acc5
changeset:   30034:e4a6b439acc5
user:Yuya Nishihara 
date:Wed Sep 28 20:05:34 2016 +0900
summary: py3: provide encoding.environ which is a dict of bytes

http://selenic.com/repo/hg//rev/02328b5d775d
changeset:   30035:02328b5d775d
user:Yuya Nishihara 
date:Wed Sep 28 20:07:32 2016 +0900
summary: py3: make i18n use encoding.environ

http://selenic.com/repo/hg//rev/3f4e1c033f40
changeset:   30036:3f4e1c033f40
user:Yuya Nishihara 
date:Fri Sep 30 21:38:47 2016 +0900
summary: url: fix crash by empty path with #fragments

http://selenic.com/repo/hg//rev/cd7276f7ea83
changeset:   30037:cd7276f7ea83
parent:  30036:3f4e1c033f40
parent:  30030:8d74027bd4e7
user:Augie Fackler 
date:Sat Oct 01 15:10:38 2016 -0400
summary: merge with stable

http://selenic.com/repo/hg//rev/42ead5b3aa7b
changeset:   30038:42ead5b3aa7b
user:Pulkit Goyal <7895pul...@gmail.com>
date:Sun Oct 02 03:38:14 2016 +0530
summary: py3: use unicodes in __slots__

http://selenic.com/repo/hg//rev/ff7697b436ab
changeset:   30039:ff7697b436ab
user:Pulkit Goyal <7895pul...@gmail.com>
date:Sun Oct 02 05:29:17 2016 +0530
summary: py3: use unicode in is_frozen()

http://selenic.com/repo/hg//rev/3e3f2201bbdf
changeset:   30040:3e3f2201bbdf
user:Jun Wu 
date:Sat Oct 01 14:18:58 2016 +0100
summary: annotate: calculate line count correctly

http://selenic.com/repo/hg//rev/1779dde4c9ef
changeset:   30041:1779dde4c9ef
bookmark:@
tag: tip
user:Gregory Szorc 
date:Sun Oct 02 22:34:40 2016 -0700
summary: hg: set default path correctly when doing a clone+share (issue5378)

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


Re: [PATCH remotenames-ext] tests: adjust tests to respect negation in cmd flags

2016-10-03 Thread Sean Farley
Kostia Balytskyi  writes:

> # HG changeset patch
> # User Kostia Balytskyi 
> # Date 1475505045 25200
> #  Mon Oct 03 07:30:45 2016 -0700
> # Node ID e4c0713ea86204b900a2e1cce238f61e4bef2062
> # Parent  3aa5c4dbf5086615dbbe42b0d2d9fd5ca0488cf1
> tests: adjust tests to respect negation in cmd flags

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


Re: [Bug 5388] New: have hg show similar like git show to show the commit in great detail.

2016-10-03 Thread alain leufroy
Also "hg export" should do the trick.

Le lun. 3 oct. 2016 23:43,  a écrit :

> https://bz.mercurial-scm.org/show_bug.cgi?id=5388
>
> Bug ID: 5388
>Summary: have hg show similar like git show to show the commit
> in great detail.
>Product: Mercurial
>Version: 3.9.1
>   Hardware: PC
> OS: Linux
> Status: UNCONFIRMED
>   Severity: feature
>   Priority: wish
>  Component: Mercurial
>   Assignee: bugzi...@selenic.com
>   Reporter: shirisha...@gmail.com
> CC: mercurial-de...@selenic.com
>
> It would be a nice feature to have. Currently this is done by
> https://slaptijack.com/software/git-show-in-hg.html but it would be nicer
> if
> the user didn't need to do things that way and would be command compatible
> to
> git.
>
> --
> You are receiving this mail because:
> You are on the CC list for the bug.
> ___
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[Bug 5388] New: have hg show similar like git show to show the commit in great detail.

2016-10-03 Thread bugzilla
https://bz.mercurial-scm.org/show_bug.cgi?id=5388

Bug ID: 5388
   Summary: have hg show similar like git show to show the commit
in great detail.
   Product: Mercurial
   Version: 3.9.1
  Hardware: PC
OS: Linux
Status: UNCONFIRMED
  Severity: feature
  Priority: wish
 Component: Mercurial
  Assignee: bugzi...@selenic.com
  Reporter: shirisha...@gmail.com
CC: mercurial-de...@selenic.com

It would be a nice feature to have. Currently this is done by
https://slaptijack.com/software/git-show-in-hg.html but it would be nicer if
the user didn't need to do things that way and would be command compatible to
git.

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


Re: [PATCH 2 of 5] extdata: add revset support for extdata

2016-10-03 Thread Matt Mackall
On Tue, 2016-09-27 at 14:41 +0200, Pierre-Yves David wrote:
> 
> On 09/25/2016 12:43 AM, Matt Mackall wrote:
> > 
> > On Sat, 2016-09-24 at 00:22 +0200, Pierre-Yves David wrote:
> > > 
> > > 
> > > On 09/23/2016 07:34 PM, Matt Mackall wrote:
> > > > 
> > > > 
> > > > On Fri, 2016-09-23 at 19:49 +0900, FUJIWARA Katsunori wrote:
> > > > > 
> > > > > 
> > > > > At Thu, 22 Sep 2016 13:21:36 -0500,
> > > > > Matt Mackall wrote:
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > # HG changeset patch
> > > > > > # User Matt Mackall 
> > > > > > # Date 1474293900 18000
> > > > > > #  Mon Sep 19 09:05:00 2016 -0500
> > > > > > # Node ID 9c8847df32a0c5045e60aded2e03a9c97507f909
> > > > > > # Parent  19bf2776dfe39befdc479253e1e7d030b41c08f9
> > > > > > extdata: add revset support for extdata
> > > > > > 
> > > > > > This inserts extdata into the revset function support. Planned
> > > > > > extensions of extdata support arguments, so this is the most
> > > > > > appropriate place for it.
> > > > > > 
> > > > > > Unfortunately, the registrar framework is not a good fit here.
> > > > > > First,
> > > > > > setting an appropriate load point is still an unsolved problem (we
> > > > > > want the code to live in revset.py, but that module may never be
> > > > > > loaded).
> > > > > > Second, registered methods become global and the data sources are
> > > > > > likely
> > > > > > to
> > > > > > be
> > > > > > repo-specific. This won't work well in a context like hgwebdir.
> > > > > Is there any reason not to define extdata() revset predicate (or
> > > > > template function), which requires external data source name like as
> > > > > extdata('filedata') ? (for convenience ?)
> > > > It's mostly convenience. But I also plan to add support for arguments.
> > > I think I really like foozy idea about using a generic 'extdata("key")'
> > > predicate. That will probably be okay for many case and prevent
> > > unexpected collision with other revsets. If needed, the user can easily
> > > define a revset alias for the sources in needs easy access to. As
> > > configuration of the source is needed anyway, this does seems like a
> > > bearable burden.
> > > 
> > > If I remember correctly, it does not seems to have limitation in the
> > > current implementation of revset that would prevent use to do
> > > 'extdata("key", arg1, arg2)'
> > You get to implement this version, because I think it's an awful idea.'ll

> hu? I'm not sure of when the Mercurial review process switched to from 
> "reviewers give feedback to submitter" to "reviewer can update submitter 
> patch them-self if they don't like it". That seems quite the opposite of 
> what you have been teaching us in the past 10 years.

I've always been aware that there's a risk that contributors will walk away if
I'm too nitpicky with their patches or ask them to make a change that they find
distasteful. And I've often taken imperfect or incomplete patches because of it.
Just so long as forward progress is made and no regressions are introduced.

In rare cases, where I find a feature desirable, but can't get a contributor to
do it to my satisfaction, I've written it myself (merge-tools comes to mind).
The downside of this approach is that there's no reason for the original
contributor to feel vested in it further, and I am thus on the hook for
maintaining it.

This extdata() proposal is a rather silly suggestion because every other
namespace in Mercurial already collides. And they collide intentionally because
it's convenient for users. We already have revset aliases creating the exact
same collision risk so the idea that a) extdata() is somehow protecting me from
something but b) I can still get the effect I want by also adding a revset alias
is a bit of a self-contradiction. Never mind that I put out an RFC on this topic
months ago and that the prototype has been in use for six.

But the real issue is that I am still completely exhausted with arguing with you
personally, so when you decided to latch on to this proposal, I was immediately
reminded of how much I was looking forward to doing other things with my time.

So I'm not going to write the extdata() version. You can either shrug and say "I
guess we won't have that feature" or you can do it.

-- 
Mathematics is the supreme nostalgia of our time.

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


Re: [PATCH 3 of 3 RFC] chgserve: preimport enabled extensions

2016-10-03 Thread Jun Wu
Excerpts from Yuya Nishihara's message of 2016-10-04 00:29:09 +0900:
> On Mon, 3 Oct 2016 15:39:24 +0100, Jun Wu wrote:
> > Excerpts from Yuya Nishihara's message of 2016-10-03 21:59:02 +0900:
> > > Regarding this, I was thinking about 'extensions.:enabled' syntax so
> > > users (or sysadmins) can define a set of conditionally-enabled extensions
> > > globally.
> > > 
> > >   [extensions]
> > >   rebase =
> > >   topic = /path/to/topic.py
> > >   topic:enabled = False
> > > 
> > > chg daemon will import all extensions listed in ~/.hgrc. And if :enabled 
> > > = True
> > > is flagged by repo/.hg/hgrc, ui/reposetup() will be run.
> > 
> > This may make the implementation more complex and fragile. One area that chg
> > currently cannot handle 100% correct is things like "-r bundles", shared
> > repo, or inferrepo - confighash may mismatch forever because of differences
> > between chg's config loading logic and the non-chg one. If that happens, chg
> > may redirect forever.
> 
> Isn't the goal of this series to get rid of the confighash?

Yes. "confighash" will only contain sensitive environment variables like
PYTHONPATH, LD_PRELOAD etc. ui.config won't affect confighash.

> > Because of the above two reasons, I prefer no uisetup for all extensions. It
> > leads to a simpler and safer implementation.
> 
> Yep. No ui/reposetup() in the main server process. My idea is how to tell
> chg server to pre-import extensions which can't be enabled globally.

That has been taken care of in patch 4, which I haven't sent yet. [1]

[1]: https://bitbucket.org/quark-zju/hg-draft/commits/51278775

> > Regarding on reposetup, I'm aware that some repo state like the radix tree
> > index needs to be persistent in memory. In my opinion, it would be better
> > solved by other IPC means, like shared memory or a background daemon
> > speaking some protocol.
> 
> Like memcached in some ways.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH remotenames-ext] bookmarks: adopt the formatter isplain method

2016-10-03 Thread Kostia Balytskyi
On 10/3/16, 5:29 PM, "Mercurial-devel on behalf of Kevin Bullock" 
 wrote:

> On Oct 3, 2016, at 10:48, Kostia Balytskyi  wrote:
> 
> # HG changeset patch
> # User Kostia Balytskyi 
> # Date 1475508913 25200
> #  Mon Oct 03 08:35:13 2016 -0700
> # Node ID bc204ce8544ee98aed0119cbf5eec6a3618bf0db
> # Parent  e4c0713ea86204b900a2e1cce238f61e4bef2062
> bookmarks: adopt the formatter isplain method
> 
> Main hg repo changed the way formatter is supposed to be checked for
> plainness: previously people would run `if not fm`, thus relying on
> `__nonzero__` method, but now there is `isplain` method of formatter.
> Remotenames needs to adopt it.
> 
> diff --git a/remotenames.py b/remotenames.py
> --- a/remotenames.py
> +++ b/remotenames.py
> @@ -1047,7 +1047,7 @@ def displaylocalbookmarks(ui, repo, opts
> fm = ui.formatter('bookmarks', opts)
> hexfn = fm.hexfunc
> marks = repo._bookmarks
> -if len(marks) == 0 and not fm:
> +if len(marks) == 0 and (not fm or  fm.isplain()):
Nit: extra space here --^
Yeah, sorry for that. I expect that this can be fixed in-flight, but can resend.

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

___
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 remotenames-ext] bookmarks: adopt the formatter isplain method

2016-10-03 Thread Kevin Bullock
> On Oct 3, 2016, at 10:48, Kostia Balytskyi  wrote:
> 
> # HG changeset patch
> # User Kostia Balytskyi 
> # Date 1475508913 25200
> #  Mon Oct 03 08:35:13 2016 -0700
> # Node ID bc204ce8544ee98aed0119cbf5eec6a3618bf0db
> # Parent  e4c0713ea86204b900a2e1cce238f61e4bef2062
> bookmarks: adopt the formatter isplain method
> 
> Main hg repo changed the way formatter is supposed to be checked for
> plainness: previously people would run `if not fm`, thus relying on
> `__nonzero__` method, but now there is `isplain` method of formatter.
> Remotenames needs to adopt it.
> 
> diff --git a/remotenames.py b/remotenames.py
> --- a/remotenames.py
> +++ b/remotenames.py
> @@ -1047,7 +1047,7 @@ def displaylocalbookmarks(ui, repo, opts
> fm = ui.formatter('bookmarks', opts)
> hexfn = fm.hexfunc
> marks = repo._bookmarks
> -if len(marks) == 0 and not fm:
> +if len(marks) == 0 and (not fm or  fm.isplain()):
Nit: extra space here --^

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

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


[PATCH 3 of 3] mq: release lock after transaction in qrefresh

2016-10-03 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1470920717 -7200
#  Thu Aug 11 15:05:17 2016 +0200
# Node ID 870b39c306bef0889f738d292006a1a322757e22
# Parent  901855444329e0a4ad7ad0e41cf0a1b6fd3ed5bc
# EXP-Topic vfs.ward
mq: release lock after transaction in qrefresh

The transaction should be closed within the lock.

diff --git a/hgext/mq.py b/hgext/mq.py
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -1840,7 +1840,7 @@ class queue(object):
 
 self.applied.append(statusentry(n, patchfn))
 finally:
-lockmod.release(lock, tr)
+lockmod.release(tr, lock)
 except: # re-raises
 ctx = repo[cparents[0]]
 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 3] pull: grab wlock during pull

2016-10-03 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1471988879 -7200
#  Tue Aug 23 23:47:59 2016 +0200
# Node ID fbd46d349985f6baa9ea5439697920726757ad38
# Parent  3741a8f86e88702595c29f8ed824a28da0cfa961
# EXP-Topic vfs.ward
pull: grab wlock during pull

because pull might move bookmarks and bookmark are protected by wlock, we have
to grab wlock for pull :-(

This required a small upgrade of the 'lockdelay' extension used by
'test-clone.t' because the delay must apply to a single lock only.

diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -1201,8 +1201,10 @@ def pull(repo, remote, heads=None, force
 " %s") % (', '.join(sorted(missing)))
 raise error.Abort(msg)
 
-lock = pullop.repo.lock()
+wlock = lock = None
 try:
+wlock = pullop.repo.wlock()
+lock = pullop.repo.lock()
 pullop.trmanager = transactionmanager(repo, 'pull', remote.url())
 streamclone.maybeperformlegacystreamclone(pullop)
 # This should ideally be in _pullbundle2(). However, it needs to run
@@ -1217,8 +1219,7 @@ def pull(repo, remote, heads=None, force
 _pullobsolete(pullop)
 pullop.trmanager.close()
 finally:
-pullop.trmanager.release()
-lock.release()
+lockmod.release(pullop.trmanager, lock, wlock)
 
 return pullop
 
diff --git a/tests/lockdelay.py b/tests/lockdelay.py
--- a/tests/lockdelay.py
+++ b/tests/lockdelay.py
@@ -7,20 +7,16 @@ from __future__ import absolute_import
 import os
 import time
 
-from mercurial import (
-lock as lockmod,
-)
+def reposetup(ui, repo):
 
-class delaylock(lockmod.lock):
-def lock(self):
-delay = float(os.environ.get('HGPRELOCKDELAY', '0.0'))
-if delay:
-time.sleep(delay)
-res = super(delaylock, self).lock()
-delay = float(os.environ.get('HGPOSTLOCKDELAY', '0.0'))
-if delay:
-time.sleep(delay)
-return res
-
-def extsetup(ui):
-lockmod.lock = delaylock
+class delayedlockrepo(repo.__class__):
+def lock(self):
+delay = float(os.environ.get('HGPRELOCKDELAY', '0.0'))
+if delay:
+time.sleep(delay)
+res = super(delayedlockrepo, self).lock()
+delay = float(os.environ.get('HGPOSTLOCKDELAY', '0.0'))
+if delay:
+time.sleep(delay)
+return res
+repo.__class__ = delayedlockrepo
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 3] perf: release lock after transaction in perffncachewrite

2016-10-03 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1470919879 -7200
#  Thu Aug 11 14:51:19 2016 +0200
# Node ID 901855444329e0a4ad7ad0e41cf0a1b6fd3ed5bc
# Parent  fbd46d349985f6baa9ea5439697920726757ad38
# EXP-Topic vfs.ward
perf: release lock after transaction in perffncachewrite

The transaction should be closed within the lock.

diff --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -575,8 +575,8 @@ def perffncachewrite(ui, repo, **opts):
 s.fncache._dirty = True
 s.fncache.write(tr)
 timer(d)
+tr.close()
 lock.release()
-tr.close()
 fm.end()
 
 @command('perffncacheencode', formatteropts)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH remotenames-ext] tests: adjust tests to respect negation in cmd flags

2016-10-03 Thread Kostia Balytskyi
# HG changeset patch
# User Kostia Balytskyi 
# Date 1475505045 25200
#  Mon Oct 03 07:30:45 2016 -0700
# Node ID e4c0713ea86204b900a2e1cce238f61e4bef2062
# Parent  3aa5c4dbf5086615dbbe42b0d2d9fd5ca0488cf1
tests: adjust tests to respect negation in cmd flags

diff --git a/tests/test-remotenames.t b/tests/test-remotenames.t
--- a/tests/test-remotenames.t
+++ b/tests/test-remotenames.t
@@ -289,9 +289,9 @@ Test loading with hggit
   $ echo "hggit=" >> $HGRCPATH
   $ hg help bookmarks  | grep -A 3 -- '--track'
-t --track BOOKMARK track this bookmark or remote name
-   -u --untrackremove tracking for this bookmark
-   -a --allshow both remote and local bookmarks
-  --remote show only remote bookmarks
+   -u --[no-]untrack   remove tracking for this bookmark
+   -a --[no-]all   show both remote and local bookmarks
+  --[no-]remoteshow only remote bookmarks
 
 Test branches marked as closed are not loaded
   $ cd ../alpha
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH remotenames-ext] bookmarks: adopt the formatter isplain method

2016-10-03 Thread Kostia Balytskyi
# HG changeset patch
# User Kostia Balytskyi 
# Date 1475508913 25200
#  Mon Oct 03 08:35:13 2016 -0700
# Node ID bc204ce8544ee98aed0119cbf5eec6a3618bf0db
# Parent  e4c0713ea86204b900a2e1cce238f61e4bef2062
bookmarks: adopt the formatter isplain method

Main hg repo changed the way formatter is supposed to be checked for
plainness: previously people would run `if not fm`, thus relying on
`__nonzero__` method, but now there is `isplain` method of formatter.
Remotenames needs to adopt it.

diff --git a/remotenames.py b/remotenames.py
--- a/remotenames.py
+++ b/remotenames.py
@@ -1047,7 +1047,7 @@ def displaylocalbookmarks(ui, repo, opts
 fm = ui.formatter('bookmarks', opts)
 hexfn = fm.hexfunc
 marks = repo._bookmarks
-if len(marks) == 0 and not fm:
+if len(marks) == 0 and (not fm or  fm.isplain()):
 ui.status(_("no bookmarks set\n"))
 
 tracking = _readtracking(repo)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 3 of 3 RFC] chgserve: preimport enabled extensions

2016-10-03 Thread Yuya Nishihara
On Mon, 3 Oct 2016 15:39:24 +0100, Jun Wu wrote:
> Excerpts from Yuya Nishihara's message of 2016-10-03 21:59:02 +0900:
> > Regarding this, I was thinking about 'extensions.:enabled' syntax so
> > users (or sysadmins) can define a set of conditionally-enabled extensions
> > globally.
> > 
> >   [extensions]
> >   rebase =
> >   topic = /path/to/topic.py
> >   topic:enabled = False
> > 
> > chg daemon will import all extensions listed in ~/.hgrc. And if :enabled = 
> > True
> > is flagged by repo/.hg/hgrc, ui/reposetup() will be run.
> 
> This may make the implementation more complex and fragile. One area that chg
> currently cannot handle 100% correct is things like "-r bundles", shared
> repo, or inferrepo - confighash may mismatch forever because of differences
> between chg's config loading logic and the non-chg one. If that happens, chg
> may redirect forever.

Isn't the goal of this series to get rid of the confighash?

> Because of the above two reasons, I prefer no uisetup for all extensions. It
> leads to a simpler and safer implementation.

Yep. No ui/reposetup() in the main server process. My idea is how to tell
chg server to pre-import extensions which can't be enabled globally.

> Regarding on reposetup, I'm aware that some repo state like the radix tree
> index needs to be persistent in memory. In my opinion, it would be better
> solved by other IPC means, like shared memory or a background daemon
> speaking some protocol.

Like memcached in some ways.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH] merge: update doc of manifestmerge() per 18c2184c27dc

2016-10-03 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1475397092 -32400
#  Sun Oct 02 17:31:32 2016 +0900
# Node ID 1fcc4a460a7e86aea018e06e776048e149b36f78
# Parent  cd7276f7ea8308df2c5d8874d335d73247d0f357
merge: update doc of manifestmerge() per 18c2184c27dc

p1 was renamed to wctx by 18c2184c27dc.

diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -781,7 +781,7 @@ def driverconclude(repo, ms, wctx, label
 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, matcher,
   acceptremote, followcopies):
 """
-Merge p1 and p2 with ancestor pa and generate merge action list
+Merge wctx and p2 with ancestor pa and generate merge action list
 
 branchmerge and force are as passed in to update
 matcher = matcher to filter file lists
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 2 v9] graft: support grafting across move/copy (issue4028)

2016-10-03 Thread Yuya Nishihara
On Mon, 3 Oct 2016 10:28:37 +, Gábor STEFANIK wrote:
> > > +_c1 = c1.p1() if c1.rev() is None else c1
> > > +_c2 = c2.p1() if c2.rev() is None else c2
> > > +dirty_c1 = not (ca == _c1 or ca.descendant(_c1))
> > > +dirty_c2 = not (ca == _c2 or ca.descendant(_c2))
> > > +graft = dirty_c1 or dirty_c2
> > > +if graft:
> > > +cta = _c1.ancestor(_c2)
> >
> > Can you fix ctx.descendant() to handle wctx? or maybe this could be
> >
> >   dirtyc = ca != ca.ancestor(c)  # for n = 1, 2
> >
> > and one of ca.ancestor(c) would be cta. (I don't carefully investigate 
> > criss-
> > cross merge case, so I might be wrong.)
> 
> ctx.ancestor() always returns just one common ancestor, not all possible 
> candidates.

Yes. My guess was ca.ancestor(c1) (not c1.ancestor(c2)) would have only one
common ancestor if it is ca, but I didn't think that deeply.

> So unfortunately there is no way to eliminate the use of descendant() here, 
> nor do I feel
> that there is a need to do so. descendant() is still faster than ancestor() 
> or especially
> commonancestorsheads().

Anyway, if descendant() is faster than ancestor(), no need to take a slow path.

> > > -u1, u2 = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2)
> > > +_u1, _u2 = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2)
> >
> > Can you give them better names? '_' prefix in local variables generally 
> > means
> > they are placeholder (unused output) variables. (Perhaps we can start with a
> > trivial patch that separates u1/2 and _u1/2, which will describe why we need
> > them.)
> 
> u1r, u2r, u1u, u2u (for rotated/unrotated)? I'm wary of using longer names, 
> as many lines
> in copies.py are already borderline for the 80-character rule, and will 
> require reformatting
> with the introduction of longer variable names.

Shorter names seem good so long as they are consistent.

> > And it would be nice if there's a brief comment when to use ca/ma over
> > cta/mta.
> >
> > > -seen = set([f])
> > > -for oc in getfctx(f, m1[f]).ancestors():
> > > +seen = {f: [getfctx(f, m1[f])]}
> > > +for oc in seen[f][0].ancestors():
> > >  ocr = oc.linkrev()
> > >  of = oc.path()
> > >  if of in seen:
> > > +seen[of].append(oc)
> > >  # check limit late - grab last rename before
> > >  if ocr < limit:
> > >  break
> > >  continue
> > > -seen.add(of)
> > > +seen[of] = [oc]
> >
> > nit: maybe we only need a dict of file nodes, not a dict of file contexts?
> 
> how do I get a file node id from a file context? ancestors() gives us 
> contexts.

fctx.filenode()

See also basefilectx.__eq__() to make sure if using .filenode() is appropriate
compared to the current code.

> > > -fullcopy[f] = of # remember for dir rename detection
> > > +# remember for dir rename detection
> > > +if backwards:
> > > +fullcopy[of] = f # grafting backwards through renames
> > > +else:
> > > +fullcopy[f] = of
> > >  if of not in m2:
> > >  continue # no match, keep looking
> > >  if m2[of] == ma.get(of):
> > > -break # no merge needed, quit early
> > > +return # no merge needed, quit early
> >
> > So we no longer set diverge[of] = [f] this case. I don't know if it was
> > necessary to populate 'renamedelete', but this change seems good for a
> > separate patch to make sure it never break anything.
> 
> This isn't just some optimization, it's necessary for correct behavior of the
> new checkcopies. And it would break the old checkcopies if applied separately
> before the main patch.

Can you add a test that should fail if we only do s/break/return/ ?
Unfortunately, all tests passed if I tried that.

> Is that really necessary? It's a lot of additional work for me, to find 
> intermediate states that may work,
> and fix each of them so they don't break anything in the testsuite, only for 
> those fixes to be reverted
> by the next patch in the series. It would be the digital equipment of digging 
> and filling pits in the ground.
> 
> Splitting isn't the hard part; ensuring no breakage in the intermediate 
> states is.

If that requires lots of unwanted intermediate states, that wouldn't be what
we should take. I guess this patch could be split to a) a few trivial changes
plus b) one (or two) core change. Hopefully (a) will reduce noises in (b).

(I'm not skilled around this code, so please feel free to ignore my comments
if they seem wrong.)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 3 of 3 RFC] chgserve: preimport enabled extensions

2016-10-03 Thread Jun Wu
Excerpts from Yuya Nishihara's message of 2016-10-03 21:59:02 +0900:
> Regarding this, I was thinking about 'extensions.:enabled' syntax so
> users (or sysadmins) can define a set of conditionally-enabled extensions
> globally.
> 
>   [extensions]
>   rebase =
>   topic = /path/to/topic.py
>   topic:enabled = False
> 
> chg daemon will import all extensions listed in ~/.hgrc. And if :enabled = 
> True
> is flagged by repo/.hg/hgrc, ui/reposetup() will be run.

This may make the implementation more complex and fragile. One area that chg
currently cannot handle 100% correct is things like "-r bundles", shared
repo, or inferrepo - confighash may mismatch forever because of differences
between chg's config loading logic and the non-chg one. If that happens, chg
may redirect forever. I have seen this but haven't got enough time to find
out what's going on exactly. In comparison, the new code can load a random
hgrc and do not worry about if the extensions listed will be enabled or
disabled because of the nice side-effect-free assumption.

Running "uisetup" is not safe for extensions reading configs from "ui". I
think controlling them via configs is not very friendly for average users.
They may mess up and get surprised.

Because of the above two reasons, I prefer no uisetup for all extensions. It
leads to a simpler and safer implementation.

That said, I understand "uisetup" can be fat and expensive. I think if that
happens, the extension author can do the slow logic at import-time. So
instead of:

  def uisetup(ui):
x = expensive()
...

They can write:

  x = expensive()

  def uisetup(ui):
global x
...

So uisetup would remain cheap. If "expensive()" relies on "ui", it cannot
be pre-calculated, since chg cannot provide a "correct" "ui" because of 
possible future config changes.

Regarding on reposetup, I'm aware that some repo state like the radix tree
index needs to be persistent in memory. In my opinion, it would be better
solved by other IPC means, like shared memory or a background daemon
speaking some protocol.

> 
> > +def _importext(orig, name, path=None, reportfunc=None):
> > +mod = _preimported.get((name, path))
> > +if mod:
> > +return mod
> > +else:
> > +return orig(name, path, reportfunc)
> > +
> > +def _preimportextensions(ui):
> > +for name, path in ui.configitems("extensions"):
> > +# only enabled extensions are pre-imported - assuming importing an
> > +# extension is side-effect free.
> > +if path.startswith('!'):
> > +continue
> > +try:
> > +mod = extensions._importext(name, path)
> > +except ImportError:
> > +pass
> > +else:
> > +_preimported[(name, path)] = mod
> 
> Perhaps path needs to be normalized.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


history at diff blocks level

2016-10-03 Thread Denis Laxalde

Hi all,

I've been recently thinking about adding some support in Mercurial to
query repository history based on changes within a given line range in a
file. I think that would be useful in at least two commands:

* log, to restrict history to revisions that modify specified part(s) of
file(s) and only display the diff around specified line range and,

* annotate, to window the annotate result and maybe consider walking
file revision from tip to base to reduce computation costs.

(The "log" part is more interesting, I think.)


From UI point of view, the basic idea is to specify a (file name, line
range) pair and the simplest solution I could find is something like:

  hg log/annotate --line-range fromline,toline FILE

but this does not work well with several files. (Perhaps something like
hg log FILE:fromline:toline would be better.) I also thought about a
"changes(filename, fromline, toline)" revset (or an extension of the
existing "modifies()" revset), but it seems to me that this would not
fit well for both log and annotate. Suggestions welcome.


From the technical point of view, my idea is to rely on
mdiff.allblocks(, ) (used
in both annotate and log, when --patch option is given) to:

1. filter blocks depending on whether they are relevant to specified
line range (e.g., for the log command there's some "!" block), and,

2. track the evolution of the line range across revisions (namely, given
the line range at rev2, find the line range at rev1 in the example above).

I have something working concerning this "low level" aspect, but I'm
somehow getting stuck when it comes to plug things into the log command
call. Namely, I need to pass the "line range" information from one
revision to another during iterations of the loop on revisions in
commands.log() [1] and pass this information down to the mdiff.unidiff()
call [2] which would then give me back another line range to push up to
the outer loop on revisions. Given the complexity of the call chain, I
actually think this is not a very good idea... So the best idea I could
come up with is to filter revisions beforehand (as would a revset do)
but this would imply keeping track of files' line ranges per revision
(to avoid processing diff blocks twice when --patch option is specified
in particular). All in all, it's not clear to me which "tool" I may use
to achieve this (I thought about using the "filematcher" built along
with "revs" in commands.log(), but not really sure it's a good idea).
Maybe I just need a data structure that does not exist yet?
I'd appreciate any pointer to move forward.

(I'll be at the sprint, so this can also be a working topic if some
people are interested.)


--
Denis Laxalde
Logilab http://www.logilab.fr

[1] https://selenic.com/repo/hg/file/tip/mercurial/commands.py#l5295
[2] https://selenic.com/repo/hg/file/tip/mercurial/patch.py#l2506
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 4] bisect: access the filesystem through vfs when reseting

2016-10-03 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1472005909 -7200
#  Wed Aug 24 04:31:49 2016 +0200
# Node ID ec6cb977f8e62bf13f86c3a7ebbee182ae50422e
# Parent  ff7697b436aba70b752a6277eaf4e9ef298e3640
# EXP-Topic bisect
bisect: access the filesystem through vfs when reseting

We have nice and shiny abstractions now.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -902,9 +902,8 @@ def bisect(ui, repo, rev=None, extra=Non
 cmdutil.checkunfinished(repo)
 
 if reset:
-p = repo.join("bisect.state")
-if os.path.exists(p):
-os.unlink(p)
+if repo.vfs.exists("bisect.state"):
+repo.vfs.unlink("bisect.state")
 return
 
 state = hbisect.load_state(repo)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 4] bisect: move the 'extendrange' to the 'hbisect' module

2016-10-03 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1472004967 -7200
#  Wed Aug 24 04:16:07 2016 +0200
# Node ID 2c643f89b68448619f6cf4326c58ef8cc686e51a
# Parent  efd8013b1521399d07ca956c1cba7bd9f7dfc6e0
# EXP-Topic bisect
bisect: move the 'extendrange' to the 'hbisect' module

We have a module ready to host any bisect logic. That logic was already isolated
in a function so we just migrate it as is.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -835,20 +835,6 @@ def bisect(ui, repo, rev=None, extra=Non
 
 Returns 0 on success.
 """
-def extendbisectrange(nodes, good):
-# bisect is incomplete when it ends on a merge node and
-# one of the parent was not checked.
-parents = repo[nodes[0]].parents()
-if len(parents) > 1:
-if good:
-side = state['bad']
-else:
-side = state['good']
-num = len(set(i.node() for i in parents) & set(side))
-if num == 1:
-return parents[0].ancestor(parents[1])
-return None
-
 def print_result(nodes, good):
 displayer = cmdutil.show_changeset(ui, repo, {})
 if len(nodes) == 1:
@@ -858,7 +844,7 @@ def bisect(ui, repo, rev=None, extra=Non
 else:
 ui.write(_("The first bad revision is:\n"))
 displayer.show(repo[nodes[0]])
-extendnode = extendbisectrange(nodes, good)
+extendnode = hbisect.extendrange(repo, state, nodes, good)
 if extendnode is not None:
 ui.write(_('Not all ancestors of this changeset have been'
' checked.\nUse bisect --extend to continue the '
@@ -977,7 +963,7 @@ def bisect(ui, repo, rev=None, extra=Non
 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
 if extend:
 if not changesets:
-extendnode = extendbisectrange(nodes, good)
+extendnode = hbisect.extendrange(repo, state, nodes, good)
 if extendnode is not None:
 ui.write(_("Extending search to changeset %d:%s\n")
  % (extendnode.rev(), extendnode))
diff --git a/mercurial/hbisect.py b/mercurial/hbisect.py
--- a/mercurial/hbisect.py
+++ b/mercurial/hbisect.py
@@ -139,6 +139,19 @@ def bisect(changelog, state):
 
 return ([best_node], tot, good)
 
+def extendrange(repo, state, nodes, good):
+# bisect is incomplete when it ends on a merge node and
+# one of the parent was not checked.
+parents = repo[nodes[0]].parents()
+if len(parents) > 1:
+if good:
+side = state['bad']
+else:
+side = state['good']
+num = len(set(i.node() for i in parents) & set(side))
+if num == 1:
+return parents[0].ancestor(parents[1])
+return None
 
 def load_state(repo):
 state = {'current': [], 'good': [], 'bad': [], 'skip': []}
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] hg: set default path correctly when doing a clone+share (issue5378)

2016-10-03 Thread Yuya Nishihara
On Sun, 02 Oct 2016 22:39:02 -0700, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc 
> # Date 1475472880 25200
> #  Sun Oct 02 22:34:40 2016 -0700
> # Node ID 5333771304e905cecc8b35c4c137d407fc49eb92
> # Parent  cd7276f7ea8308df2c5d8874d335d73247d0f357
> hg: set default path correctly when doing a clone+share (issue5378)

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


Re: [PATCH 3 of 3 RFC] chgserve: preimport enabled extensions

2016-10-03 Thread Yuya Nishihara
On Mon, 3 Oct 2016 07:11:20 +0100, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu 
> # Date 1475463449 -3600
> #  Mon Oct 03 03:57:29 2016 +0100
> # Node ID 6f38a7d259add12c44040535681c4b3ceef0a791
> # Parent  7d106c3386e17746c9b49ab9c788535634b3e8f6
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #  hg pull https://bitbucket.org/quark-zju/hg-draft -r 
> 6f38a7d259ad
> chgserve: preimport enabled extensions
> 
> This patch pre-imports enabled extensions, so performance improvement is
> visible. It's about 0.01 seconds slower than the old chg, which seems to be
> acceptable.

(I haven't read the patch 1 and 2 yet.)

Regarding this, I was thinking about 'extensions.:enabled' syntax so
users (or sysadmins) can define a set of conditionally-enabled extensions
globally.

  [extensions]
  rebase =
  topic = /path/to/topic.py
  topic:enabled = False

chg daemon will import all extensions listed in ~/.hgrc. And if :enabled = True
is flagged by repo/.hg/hgrc, ui/reposetup() will be run.

> +def _importext(orig, name, path=None, reportfunc=None):
> +mod = _preimported.get((name, path))
> +if mod:
> +return mod
> +else:
> +return orig(name, path, reportfunc)
> +
> +def _preimportextensions(ui):
> +for name, path in ui.configitems("extensions"):
> +# only enabled extensions are pre-imported - assuming importing an
> +# extension is side-effect free.
> +if path.startswith('!'):
> +continue
> +try:
> +mod = extensions._importext(name, path)
> +except ImportError:
> +pass
> +else:
> +_preimported[(name, path)] = mod

Perhaps path needs to be normalized.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


RE: [PATCH 1 of 2 v9] graft: support grafting across move/copy (issue4028)

2016-10-03 Thread Gábor STEFANIK
>


--
This message, including its attachments, is confidential. For more information 
please read NNG's email policy here:
http://www.nng.com/emailpolicy/
By responding to this email you accept the email policy.


-Original Message-
> From: Yuya Nishihara [mailto:you...@gmail.com] On Behalf Of Yuya
> Nishihara
> Sent: Sunday, October 2, 2016 6:02 PM
> To: Gábor STEFANIK 
> Cc: mercurial-devel@mercurial-scm.org
> Subject: Re: [PATCH 1 of 2 v9] graft: support grafting across move/copy
> (issue4028)
>
> On Fri, 16 Sep 2016 15:45:18 -0500, Gábor Stefanik wrote:
> > # HG changeset patch
> > # User Gábor Stefanik  # Date 1474058125 -7200
> > #  Fri Sep 16 22:35:25 2016 +0200
> > # Node ID 63a2ea1bc3aa51caaf22bdfe31e7ae685ac3894f
> > # Parent  285a8c3e53f2183438f0cdbc238e4ab851d0d110
> > graft: support grafting across move/copy (issue4028)
>
> > diff --git a/mercurial/copies.py b/mercurial/copies.py
> > --- a/mercurial/copies.py
> > +++ b/mercurial/copies.py
> > @@ -321,6 +321,23 @@
> >  if repo.ui.configbool('experimental', 'disablecopytrace'):
> >  return {}, {}, {}, {}
> >
> > +# In certain scenarios (e.g. graft, update or rebase), ca can be
> overridden
> > +# We still need to know a real common ancestor in this case
> > +# We can't just compute _c1.ancestor(_c2) and compare it to ca,
> because
> > +# there can be multiple common ancestors, e.g. in case of bidmerge.
> > +# Because our caller may not know if the revision passed in lieu of the
> CA
> > +# is a genuine common ancestor or not without explicitly checking it, 
> > it's
> > +# better to determine that here.
> > +cta = ca
> > +# ca.descendant(wc) and ca.descendant(ca) are False, work around that
> > +_c1 = c1.p1() if c1.rev() is None else c1
> > +_c2 = c2.p1() if c2.rev() is None else c2
> > +dirty_c1 = not (ca == _c1 or ca.descendant(_c1))
> > +dirty_c2 = not (ca == _c2 or ca.descendant(_c2))
> > +graft = dirty_c1 or dirty_c2
> > +if graft:
> > +cta = _c1.ancestor(_c2)
>
> Can you fix ctx.descendant() to handle wctx? or maybe this could be
>
>   dirtyc = ca != ca.ancestor(c)  # for n = 1, 2
>
> and one of ca.ancestor(c) would be cta. (I don't carefully investigate 
> criss-
> cross merge case, so I might be wrong.)

ctx.ancestor() always returns just one common ancestor, not all possible 
candidates.

bidmerge uses a function called commonancestorsheads() instead (not sure where 
that
can be found), but a non-head common ancestor also shouldn't trigger graft 
logic.

So unfortunately there is no way to eliminate the use of descendant() here, nor 
do I feel
that there is a need to do so. descendant() is still faster than ancestor() or 
especially
commonancestorsheads().

>
> >  # find interesting file sets from manifests
> > +if graft:
> > +repo.ui.debug("  computing unmatched files in rotated DAG\n")
> >  addedinm1 = m1.filesnotin(ma)
> >  addedinm2 = m2.filesnotin(ma)
> > -u1, u2 = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2)
> > +_u1, _u2 = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2)
>
> Can you give them better names? '_' prefix in local variables generally means
> they are placeholder (unused output) variables. (Perhaps we can start with a
> trivial patch that separates u1/2 and _u1/2, which will describe why we need
> them.)

u1r, u2r, u1u, u2u (for rotated/unrotated)? I'm wary of using longer names, as 
many lines
in copies.py are already borderline for the 80-character rule, and will require 
reformatting
with the introduction of longer variable names.

>
> > +# combine partial copy paths discovered in the previous step
> > +copyfrom, copyto = incomplete1, incomplete2
> > +if dirty_c1:
> > +copyfrom, copyto = incomplete2, incomplete1
> > +for f in copyfrom:
> > +if f in copyto:
> > +copy[copyto[f]] = copyfrom[f]
> > +del copyto[f]
> > +for f in incompletediverge:
> > +assert f not in diverge
> > +ic = incompletediverge[f]
> > +if ic[0] in copyto:
> > +diverge[f] = [copyto[ic[0]], ic[1]]
>
> Perhaps this can be a separate function, which would avoid spilling out
> temporary variables, copyfrom/to.

Sounds doable.

>
> > +_incomplete = _incomplete2
> > +if dirty_c1:
> > +_incomplete = _incomplete1
> > +assert _incomplete2 == {}
> > +else:
> > +assert _incomplete1 == {}
> > +for f in _diverge:
> > +assert f not in bothdiverge
> > +ic = _diverge[f]
> > +if ic[0] in _incomplete:
> > +bothdiverge[f] = [_incomplete[ic[0]], ic[1]]
> > +elif ic[0] in (m1 if dirty_c1 else m2):
> > +# backed-out rename on one side, but watch out for deleted 
> > files
> > +bothdiverge[f] = ic
>
> This looks 

[PATCH 1 of 3 RFC] chg: add a standalone entry point

2016-10-03 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1475458616 -3600
#  Mon Oct 03 02:36:56 2016 +0100
# Node ID 7b19924c9fd57fbb7fa39c103902d51d7ea9beb4
# Parent  cd7276f7ea8308df2c5d8874d335d73247d0f357
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 7b19924c9fd5
chg: add a standalone entry point

This is the beginning of a series that does a re-architect to chg mentioned
in [1], to achieve better compatibility.

The compatibility issues are mainly around "uisetup"s and "reposetup"s:

  - Developers are usually unaware that uisetup runs only once per chg
process. We cannot reliably devel-warn them. The result is, potential
broken code are written. For example, it's really hard for chg to deal
with "experimental.evolution" changed from unset to manually set in
config files because setconfig is used if that config option is not set.
  - An unnecessary "reposetup" caused by "hg serve" may have unwanted
side effects. This can become troublesome if the repo requires things
like remotefilelog or lz4revlog, and the user sets HGRCPATH to run
tests.

The current chg implementation assumes that "loading" an extension is not
side effect free - if extension related config has changed, a restart is
needed. The new idea is, "loading" = "importing" + "run ui/extsetup", the
"importing" part can be side-effect free for some extensions. And benchmark
shows "import" takes most of the time consumed, while "uisetup" is usually
very fast. We can afford running "uisetup"s per request.

To be able to (pre-)"import" extensions without running any "uisetup"s, a
different entry point is needed. Otherwise as long as we go through the
normal dispatch / runcommand ("hg serve") flow, "uisetup"s cannot be
avoided.

Aside from better compatibility, we can also remove some hacks:

  - chg client: no longer needs to extract sensitive argv
  - chg server: confighash can be changed to only hash environment variables
(reduce the number of server processes)
  - chg server: srcui.walkconfig hack is no longer necessary

This patch adds a new script "chgserve" as the new entry point. Currently,
it is just a minimal implementation that makes "CHGHG=chgserve chg ..."
work, without doing any pre-importing. The change could also be done in the
"hg" script. But since chg is still experimental, let's keep "hg" untouched
for now.

[1]: www.mercurial-scm.org/pipermail/mercurial-devel/2016-July/085965.html

diff --git a/contrib/chg/chgserve b/contrib/chg/chgserve
new file mode 100755
--- /dev/null
+++ b/contrib/chg/chgserve
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+
+from __future__ import absolute_import
+
+import os
+import sys
+
+from mercurial import (
+cmdutil,
+commands,
+commandserver,
+dispatch,
+fancyopts,
+ui as uimod,
+util,
+)
+
+from hgext import chgserver
+
+def _confighash(ui):
+envitems = [(k, v) for k, v in os.environ.iteritems()
+if chgserver._envre.match(k)]
+envhash = chgserver._hashlist(sorted(envitems))
+return envhash[:12]
+
+def _startchgservice():
+# patch chgserver's confighash to only hash environment variables
+chgserver._confighash = _confighash
+
+ui = uimod.ui()
+repo = None
+args = sys.argv[2:]
+dispatch._earlygetopt(['--config'], args)
+opts = {}
+fancyopts.fancyopts(args, commands.table['^serve'][1], opts)
+
+service = chgserver.chgunixservice(ui, repo, opts)
+cmdutil.service(opts, initfn=service.init, runfn=service.run)
+
+def _setbinary():
+for fp in (sys.stdin, sys.stdout, sys.stderr):
+util.setbinary(fp)
+
+if __name__ == '__main__':
+_setbinary()
+sys.exit(_startchgservice())
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 3 RFC] chgserve: preimport enabled extensions

2016-10-03 Thread Jun Wu
# HG changeset patch
# User Jun Wu 
# Date 1475463449 -3600
#  Mon Oct 03 03:57:29 2016 +0100
# Node ID 6f38a7d259add12c44040535681c4b3ceef0a791
# Parent  7d106c3386e17746c9b49ab9c788535634b3e8f6
# Available At https://bitbucket.org/quark-zju/hg-draft
#  hg pull https://bitbucket.org/quark-zju/hg-draft -r 6f38a7d259ad
chgserve: preimport enabled extensions

This patch pre-imports enabled extensions, so performance improvement is
visible. It's about 0.01 seconds slower than the old chg, which seems to be
acceptable.

diff --git a/contrib/chg/chgserve b/contrib/chg/chgserve
--- a/contrib/chg/chgserve
+++ b/contrib/chg/chgserve
@@ -11,4 +11,5 @@ from mercurial import (
 commandserver,
 dispatch,
+extensions,
 fancyopts,
 ui as uimod,
@@ -24,4 +25,27 @@ def _confighash(ui):
 return envhash[:12]
 
+_preimported = {} # {(name, path): mod}
+
+def _importext(orig, name, path=None, reportfunc=None):
+mod = _preimported.get((name, path))
+if mod:
+return mod
+else:
+return orig(name, path, reportfunc)
+
+def _preimportextensions(ui):
+for name, path in ui.configitems("extensions"):
+# only enabled extensions are pre-imported - assuming importing an
+# extension is side-effect free.
+if path.startswith('!'):
+continue
+try:
+mod = extensions._importext(name, path)
+except ImportError:
+pass
+else:
+_preimported[(name, path)] = mod
+ui.debug('chg: preimported %s\n' % name)
+
 def _startchgservice():
 # patch chgserver's confighash to only hash environment variables
@@ -35,4 +59,7 @@ def _startchgservice():
 fancyopts.fancyopts(args, commands.table['^serve'][1], opts)
 
+_preimportextensions(ui)
+extensions.wrapfunction(extensions, '_importext', _importext)
+
 service = chgserver.chgunixservice(ui, repo, opts)
 cmdutil.service(opts, initfn=service.init, runfn=service.run)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel