Re: [PATCH V7] hgweb: expose a followlines UI in filerevision view

2017-03-31 Thread Gregory Szorc
On Fri, Mar 31, 2017 at 4:47 AM, Denis Laxalde  wrote:

> # HG changeset patch
> # User Denis Laxalde 
> # Date 1490819176 -7200
> #  Wed Mar 29 22:26:16 2017 +0200
> # Node ID be7965e3afe82be35d258a2cff12b389a857ef88
> # Parent  dea2a17cbfd00bf08ee87b3e44b1c71499189f89
> # Available At http://hg.logilab.org/users/dlaxalde/hg
> #  hg pull http://hg.logilab.org/users/dlaxalde/hg -r
> be7965e3afe8
> hgweb: expose a followlines UI in filerevision view
>

This looks good to me and I think it can be queued. There is obviously some
follow-up work:

* Add support for gitweb (and other styles if we care)
* Add floating labels (or similar) to help draw attention to the feature
* Add support on the blame page (and anywhere else it makes sense)
* CSS tweaking (if others want to)

But this can be deferred until after landing. Perfect is the enemy of good.

This is an awesome feature and I can wait to use it!

Before I forget, I think someone should record a demo video or an animated
GIF of this to put in the 4.2 release notes. AFAIK no other VCS has this
feature and I think we could turn some heads by calling attention to it.


>
> In filerevision view (/file//) we add some event listeners on
> mouse clicks of  elements in the  block.
> Those listeners will capture a range of lines selected between two mouse
> clicks and a box inviting to follow the history of selected lines will then
> show up. Selected lines (i.e. the block of lines) get a CSS class which
> make
> them highlighted. Selection can be cancelled (and restarted) by either
> clicking on the cancel ("x") button in the invite box or clicking on any
> other
> source line. Also clicking twice on the same line will abort the selection
> and
> reset event listeners to restart the process.
>
> As a first step, this action is only advertised by the "cursor: cell" CSS
> rule
> on source lines elements as any other mechanisms would make the code
> significantly more complicated. This might be improved later.
>
> All JavaScript code lives in a new "linerangelog.js" file, sourced in
> filerevision template (only in "paper" style for now).
>
> diff --git a/contrib/wix/templates.wxs b/contrib/wix/templates.wxs
> --- a/contrib/wix/templates.wxs
> +++ b/contrib/wix/templates.wxs
> @@ -225,6 +225,7 @@
>  
>  
>  
> +
>  
>  
>  
> diff --git a/mercurial/templates/paper/filerevision.tmpl
> b/mercurial/templates/paper/filerevision.tmpl
> --- a/mercurial/templates/paper/filerevision.tmpl
> +++ b/mercurial/templates/paper/filerevision.tmpl
> @@ -71,8 +71,11 @@
>  
>  line wrap:  class="linewraplink" href="javascript:toggleLinewrap()">on
>   line source
> -{text%fileline}
> + data-logurl="{url|urlescape}log/{symrev}/{file|urlescape}"
> >{text%fileline}
>  
> +
> +
> +
>  
>  
>
> diff --git a/mercurial/templates/static/linerangelog.js
> b/mercurial/templates/static/linerangelog.js
> new file mode 100644
> --- /dev/null
> +++ b/mercurial/templates/static/linerangelog.js
> @@ -0,0 +1,163 @@
> +// linerangelog.js - JavaScript utilities for followlines UI
> +//
> +// Copyright 2017 Logilab SA 
> +//
> +// This software may be used and distributed according to the terms of the
> +// GNU General Public License version 2 or any later version.
> +
> +//** Install event listeners for line block selection and followlines
> action */
> +function installLineSelect() {
> +var sourcelines = document.getElementsByClassName('sourcelines')[0];
> +if (typeof sourcelines === 'undefined') {
> +return;
> +}
> +// URL to complement with "linerange" query parameter
> +var targetUri = sourcelines.dataset.logurl;
> +if (typeof targetUri === 'undefined') {
> +return;
> +}
> +
> +// retrieve all direct  children of 
> +var spans = Array.prototype.filter.call(
> +sourcelines.children,
> +function(x) { return x.tagName === 'SPAN' });
> +
> +var lineSelectedCSSClass = 'followlines-selected';
> +
> +//** add CSS class on  element in `from`-`to` line range */
> +function addSelectedCSSClass(from, to) {
> +for (var i = from; i <= to; i++) {
> +spans[i].classList.add(lineSelectedCSSClass);
> +}
> +}
> +
> +//** remove CSS class from previously selected lines */
> +function removeSelectedCSSClass() {
> +var elements = sourcelines.getElementsByClassName(
> +lineSelectedCSSClass);
> +while (elements.length) {
> +elements[0].classList.remove(lineSelectedCSSClass);
> +}
> +}
> +
> +// ** return the  element parent of `element` */
> +function findParentSpan(element) {
> +var parent = element.parentElement;
> +if (parent === null) {
> +return null;
> +}
> +if (element.tagName == 'SPAN' && parent.isSameNode(sourcelines))
> {
> +

Internal-changeset concept (was: re: [PATCH RFC] repo: add an ability to hide nodes in an appropriate way)

2017-03-31 Thread Pierre-Yves David

[And here is the actual reply, sorry for the initial misstep]

On 03/30/2017 07:08 PM, Ryan McElroy wrote:

On 3/30/17 3:15 PM, Pierre-Yves David wrote:

[…]
I hope this long message help to clarify various concept. We have way
forward to reduce the use of stripping without abusing the
obsolescence concept in a way that will create issue for users. These
way forward are in reach and would not take too long to build.




For what it's worth, I find this essay pretty convincing: obsmarkers
have their use-case, they are lightly abused now (for temp-amend-commit)
but it probably makes sense to not abuse them further.

It sounds like an "internal" phase above "secret" would actually map
fairly well onto the temp-amend-commit, hidden shelves never meant to be
exchanged, aborted rebase, etc places.

Pierre-Yves, since you've thought about this a lot, does a phase here
make sense (note that I'm not saying a general hiding place like
"archive" phase, but just for internal nodes that we generally don't
want shown or exchanged, but are also not "technically obsolete".


You are right. Given the property of internal changesets, phases may be 
a good pick for them.


I'll do a full review of the problem space and its possible solutions, 
if you want the short conclusion, skip to the end.


I've also created a plan page related to this:

  https://www.mercurial-scm.org/wiki/InternalsPlan


Problem Space
=

Possible approach
-

Since introducing a new "internal" concept will requires a new 
repository requirement. We have multiple options at hands.


   1) dedicated 'internal' phases,
   2) ad-hoc mechanism (let us says bytemap),
   3) key in changeset extra,

(If someone think about something else, let me know)

Internal changeset property
---

   A) They are irrelevant to the users,
   B) Nothing will be based on them,
   C) Once done with their purpose, we should not need them again,
   D) They never leave the repository,
   E) They never stop being internal changesets,

Life Cycle of Internal Changeset
-

Let us review how we use internal changesets and when do we need them 
visible ?


amend
`

   1) transaction is open,
   2) a temporary commit is created,
   3)  is used to build the result of the amend,
   4) obsmarkers are created (between old and new),
   5)  is "archived" (currently obsmarkers),
   6) transaction is committed.

The commit is created and "archived" in the same transaction. It is 
never visible to anyone.


Actually, we could fully remove this changeset with appropriate 
in-memory-ctx capabilities.



histedit


Scenario:

   pick 
   pick 
   roll  # the important part is the fold
   pick 

(Assuming single transaction for simplicity)

   1) transaction is open,
   2)  is rebased on base
 (possible conflict and associated transaction open/close)
  -> creates ,
   3)  is rebased on the 
 (possible conflict and associated transaction open/close)
  -> creates ,
   4)  is rebased on the  (no commit),
 (possible conflict and associated transaction open/close)
   5) changes are folded in  as 
   6)  is rebased on the 
 (possible conflict and associated transaction open/close)
  -> creates ,
   7) transaction is committed.

Possible rebase conflict during (4) will expose  to 
the user as:

 * part of the merge conflict
 * working directory parent.

The user needs to see that temporary commit during the merge conflict 
resolution.



shelve
``

shelving:

   1) transaction is open,
   2) shelved change are committed,
   3) commit is recorded as a shelve-changeset,
   4) apply hiding on this shelve,
   5) transaction is committed

unshelving (I might be wrong, I've not followed everything):

   1) transaction is open
   2) uncommitted changes are put in a temporary commit
   *) access the shelve-changeset (somehow),
   3) hg rebase -r  -d 
   <) possible conflict resolution that requires transaction commit
   >) possible transaction reopen (if conflict)
   =) rebase complete
   4) grab the result of the shelve and restore working copy parent
   5) hide  and 
   6) close transaction

Note: during possible rebase conflict, the "shelve" is currently visible 
to the user. Can we change this ?


* At minimum, it needs to be at least visible to the "hg resolve 
command". This is easy to achieve in all cases.


* Having it visible seems valuable for the user experience.

conclusion in life cycle


Even if many internal never needs to be visible out of a transaction 
that creates them. There seems to be valid cases were the internal 
changeset is exposed to the user to help with merge conflict (histedit 
and shelve).


In general however, once an internal changeset has been hidden, we won't 
need it again. There is a small exception with  changeset. More 
on that below.



Additional note about shelve
-

The shelve extensions use a 

[PATCH 7 of 7 V2] hook: add hook name information to external hook

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490954036 -7200
#  Fri Mar 31 11:53:56 2017 +0200
# Node ID 0df8b9ce67f408e590b5acfab24da02b4218
# Parent  98116be5e0363b37ff9d63aa6b44466dbe11bb56
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 0df8b9ce67f4
hook: add hook name information to external hook

While we are here, we can also add the hook name information to external hook.

diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -844,9 +844,10 @@ Example ``.hg/hgrc``::
 Most hooks are run with environment variables set that give useful
 additional information. For each hook below, the environment variables
 it is passed are listed with names of the form ``$HG_foo``. The
-``$HG_HOOKTYPE`` variable is set for all hooks. It contains the type of
-hook which triggered the run. In the example about this will be
-``$HG_HOOKTYPE=incoming``.
+``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
+their respectively contains the type of hook which triggered the run and
+the full name of the hooks in the config. In the example about this will
+be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
 
 ``changegroup``
   Run after a changegroup has been added via push, pull or unbundle.  ID of the
diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -127,6 +127,7 @@ def _exthook(ui, repo, htype, name, cmd,
 if tr and tr.writepending():
 env['HG_PENDING'] = repo.root
 env['HG_HOOKTYPE'] = htype
+env['HG_HOOKNAME'] = name
 
 for k, v in args.iteritems():
 if callable(v):
diff --git a/tests/test-bundle.t b/tests/test-bundle.t
--- a/tests/test-bundle.t
+++ b/tests/test-bundle.t
@@ -232,7 +232,7 @@ hg -R bundle://../full.hg verify
   adding manifests
   adding file changes
   added 9 changesets with 7 changes to 4 files (+1 heads)
-  changegroup hook: HG_HOOKTYPE=changegroup 
HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
+  changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup 
HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 Rollback empty
@@ -255,7 +255,7 @@ Pull full.hg into empty again (using -R;
   adding manifests
   adding file changes
   added 9 changesets with 7 changes to 4 files (+1 heads)
-  changegroup hook: HG_HOOKTYPE=changegroup 
HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
+  changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup 
HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 Cannot produce streaming clone bundles with "hg bundle"
diff --git a/tests/test-bundle2-exchange.t b/tests/test-bundle2-exchange.t
--- a/tests/test-bundle2-exchange.t
+++ b/tests/test-bundle2-exchange.t
@@ -41,7 +41,7 @@ The extension requires a repo (currently
   $ hg commit -m 'a'
   pre-close-tip:3903775176ed draft 
   postclose-tip:3903775176ed draft 
-  txnclose hook: HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ 
HG_TXNNAME=commit
+  txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose 
HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
 
   $ hg unbundle $TESTDIR/bundles/rebase.hg
   adding changesets
@@ -50,7 +50,7 @@ The extension requires a repo (currently
   added 8 changesets with 7 changes to 7 files (+3 heads)
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_HOOKTYPE=txnclose 
HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
HG_SOURCE=unbundle HG_TXNID=TXN:$ID$ HG_TXNNAME=unbundle
+  txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose 
HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
HG_SOURCE=unbundle HG_TXNID=TXN:$ID$ HG_TXNNAME=unbundle
   bundle:*/tests/bundles/rebase.hg HG_URL=bundle:*/tests/bundles/rebase.hg 
(glob)
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
@@ -64,18 +64,18 @@ Add more obsolescence information
   $ hg -R main debugobsolete -d '0 0'  
`getmainid 9520eea781bc`
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose 

[PATCH 6 of 7 V2] hook: provide hook type information to external hook

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490951291 -7200
#  Fri Mar 31 11:08:11 2017 +0200
# Node ID 98116be5e0363b37ff9d63aa6b44466dbe11bb56
# Parent  87bd941f005ffa248180907aff7d277de7b9bcee
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 98116be5e036
hook: provide hook type information to external hook

The python hooks have access to the hook type information. There is not reason
for external hook to not be aware of it too.

For the record my use case is to make sure a hook script is configured for the
right type.

diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -842,8 +842,11 @@ Example ``.hg/hgrc``::
   priority.incoming.autobuild = 1
 
 Most hooks are run with environment variables set that give useful
-additional information. For each hook below, the environment
-variables it is passed are listed with names of the form ``$HG_foo``.
+additional information. For each hook below, the environment variables
+it is passed are listed with names of the form ``$HG_foo``. The
+``$HG_HOOKTYPE`` variable is set for all hooks. It contains the type of
+hook which triggered the run. In the example about this will be
+``$HG_HOOKTYPE=incoming``.
 
 ``changegroup``
   Run after a changegroup has been added via push, pull or unbundle.  ID of the
diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -114,7 +114,7 @@ def _pythonhook(ui, repo, htype, hname, 
 ui.warn(_('warning: %s hook failed\n') % hname)
 return r, False
 
-def _exthook(ui, repo, name, cmd, args, throw):
+def _exthook(ui, repo, htype, name, cmd, args, throw):
 ui.note(_("running hook %s: %s\n") % (name, cmd))
 
 starttime = util.timer()
@@ -126,6 +126,7 @@ def _exthook(ui, repo, name, cmd, args, 
 repo.dirstate.write(tr)
 if tr and tr.writepending():
 env['HG_PENDING'] = repo.root
+env['HG_HOOKTYPE'] = htype
 
 for k, v in args.iteritems():
 if callable(v):
@@ -248,7 +249,7 @@ def runhooks(ui, repo, htype, hooks, thr
 r, raised = _pythonhook(ui, repo, htype, hname, hookfn, args,
 throw)
 else:
-r = _exthook(ui, repo, hname, cmd, args, throw)
+r = _exthook(ui, repo, htype, hname, cmd, args, throw)
 raised = False
 
 res[hname] = r, raised
diff --git a/tests/test-bundle.t b/tests/test-bundle.t
--- a/tests/test-bundle.t
+++ b/tests/test-bundle.t
@@ -232,7 +232,7 @@ hg -R bundle://../full.hg verify
   adding manifests
   adding file changes
   added 9 changesets with 7 changes to 4 files (+1 heads)
-  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
+  changegroup hook: HG_HOOKTYPE=changegroup 
HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 Rollback empty
@@ -255,7 +255,7 @@ Pull full.hg into empty again (using -R;
   adding manifests
   adding file changes
   added 9 changesets with 7 changes to 4 files (+1 heads)
-  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
+  changegroup hook: HG_HOOKTYPE=changegroup 
HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 Cannot produce streaming clone bundles with "hg bundle"
diff --git a/tests/test-bundle2-exchange.t b/tests/test-bundle2-exchange.t
--- a/tests/test-bundle2-exchange.t
+++ b/tests/test-bundle2-exchange.t
@@ -41,7 +41,7 @@ The extension requires a repo (currently
   $ hg commit -m 'a'
   pre-close-tip:3903775176ed draft 
   postclose-tip:3903775176ed draft 
-  txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
+  txnclose hook: HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ 
HG_TXNNAME=commit
 
   $ hg unbundle $TESTDIR/bundles/rebase.hg
   adding changesets
@@ -50,7 +50,7 @@ The extension requires a repo (currently
   added 8 changesets with 7 changes to 7 files (+3 heads)
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
HG_SOURCE=unbundle HG_TXNID=TXN:$ID$ HG_TXNNAME=unbundle
+  txnclose hook: 

[PATCH 2 of 7 V2] hook: use "htype" as variable name in _pythonhook

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490950777 -7200
#  Fri Mar 31 10:59:37 2017 +0200
# Node ID c81fb978412978f5d10879987ed5a571cb9b0904
# Parent  d808e447f5188f30ec37243016536367bfe5b2c0
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r c81fb9784129
hook: use "htype" as variable name  in _pythonhook

We rename 'name' to 'htype' because it fits the variable content better.
Multiple python hooks already use 'htype' as a name for the argument. This makes
the difference with "hname" clearer and the code less error prone.

diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -19,7 +19,7 @@ from . import (
 util,
 )
 
-def _pythonhook(ui, repo, name, hname, funcname, args, throw):
+def _pythonhook(ui, repo, htype, hname, funcname, args, throw):
 '''call python hook. hook is callable object, looked up as
 name in python module. if callable returns "true", hook
 fails, else passes. if hook raises exception, treated as
@@ -90,7 +90,7 @@ def _pythonhook(ui, repo, name, hname, f
 starttime = util.timer()
 
 try:
-r = obj(ui=ui, repo=repo, hooktype=name, **args)
+r = obj(ui=ui, repo=repo, hooktype=htype, **args)
 except Exception as exc:
 if isinstance(exc, error.Abort):
 ui.warn(_('error: %s hook failed: %s\n') %
@@ -107,7 +107,7 @@ def _pythonhook(ui, repo, name, hname, f
 finally:
 duration = util.timer() - starttime
 ui.log('pythonhook', 'pythonhook-%s: %s finished in %0.2f seconds\n',
-   name, funcname, duration)
+   htype, funcname, duration)
 if r:
 if throw:
 raise error.HookAbort(_('%s hook failed') % hname)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 5 of 7 V2] hook: use 'htype' in 'hook'

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490951202 -7200
#  Fri Mar 31 11:06:42 2017 +0200
# Node ID 87bd941f005ffa248180907aff7d277de7b9bcee
# Parent  2043a184b25cda298f5d590c5c08500471c488d9
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 87bd941f005f
hook: use 'htype' in 'hook'

Same rational as for 'runhooks', we fix the naming in another function.

diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -186,16 +186,16 @@ def redirect(state):
 global _redirect
 _redirect = state
 
-def hook(ui, repo, name, throw=False, **args):
+def hook(ui, repo, htype, throw=False, **args):
 if not ui.callhooks:
 return False
 
 hooks = []
 for hname, cmd in _allhooks(ui):
-if hname.split('.')[0] == name and cmd:
+if hname.split('.')[0] == htype and cmd:
 hooks.append((hname, cmd))
 
-res = runhooks(ui, repo, name, hooks, throw=throw, **args)
+res = runhooks(ui, repo, htype, hooks, throw=throw, **args)
 r = False
 for hname, cmd in hooks:
 r = res[hname][0] or r
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 7 V2] run-tests: auto-replace 'TXNID' output

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490887743 -7200
#  Thu Mar 30 17:29:03 2017 +0200
# Node ID d808e447f5188f30ec37243016536367bfe5b2c0
# Parent  2632df096fc0ac7582382b1f94ea4b9ad0bce8f2
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r d808e447f518
run-tests: auto-replace 'TXNID' output

Hooks related to the transaction are aware of the transaction id. By definition
this txn-id is unique and different for each transaction. As a result it can
never be predicted in test and always needs matching. As a result, touching any
like with this data is annoying. We solve the problem once and for all by
installing an automatic replacement. In test, this will now show as:

  TXNID=TXN:$ID$

diff --git a/tests/run-tests.py b/tests/run-tests.py
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -848,6 +848,7 @@ class Test(unittest.TestCase):
 (br'(?m)^(saved backup bundle to .*\.hg)( \(glob\))?$',
  br'\1 (glob)'),
 (br'([^0-9])%s' % re.escape(self._localip()), br'\1$LOCALIP'),
+(br'\bHG_TXNID=TXN:[a-f0-9]{40}\b', br'HG_TXNID=TXN:$ID$'),
 ]
 r.append((self._escapepath(self._testtmp), b'$TESTTMP'))
 
diff --git a/tests/test-bundle.t b/tests/test-bundle.t
--- a/tests/test-bundle.t
+++ b/tests/test-bundle.t
@@ -232,7 +232,7 @@ hg -R bundle://../full.hg verify
   adding manifests
   adding file changes
   added 9 changesets with 7 changes to 4 files (+1 heads)
-  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:* HG_URL=bundle?../full.hg (glob)
+  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 Rollback empty
@@ -255,7 +255,7 @@ Pull full.hg into empty again (using -R;
   adding manifests
   adding file changes
   added 9 changesets with 7 changes to 4 files (+1 heads)
-  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:* HG_URL=bundle:empty+full.hg (glob)
+  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 Cannot produce streaming clone bundles with "hg bundle"
diff --git a/tests/test-bundle2-exchange.t b/tests/test-bundle2-exchange.t
--- a/tests/test-bundle2-exchange.t
+++ b/tests/test-bundle2-exchange.t
@@ -41,7 +41,7 @@ The extension requires a repo (currently
   $ hg commit -m 'a'
   pre-close-tip:3903775176ed draft 
   postclose-tip:3903775176ed draft 
-  txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
+  txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
 
   $ hg unbundle $TESTDIR/bundles/rebase.hg
   adding changesets
@@ -50,7 +50,7 @@ The extension requires a repo (currently
   added 8 changesets with 7 changes to 7 files (+3 heads)
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
HG_SOURCE=unbundle HG_TXNID=TXN:* HG_TXNNAME=unbundle (glob)
+  txnclose hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
HG_SOURCE=unbundle HG_TXNID=TXN:$ID$ HG_TXNNAME=unbundle
   bundle:*/tests/bundles/rebase.hg HG_URL=bundle:*/tests/bundles/rebase.hg 
(glob)
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
@@ -64,18 +64,18 @@ Add more obsolescence information
   $ hg -R main debugobsolete -d '0 0'  
`getmainid 9520eea781bc`
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete 
(glob)
+  txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
   $ hg -R main debugobsolete -d '0 0'  
`getmainid 24b6387c8c8c`
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete 
(glob)
+  txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
 
 clone --pull
 
   $ hg -R main phase --public cd010b8cd998
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=phase (glob)
+  txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ 

[PATCH 4 of 7 V2] hook: use 'htype' in 'runhooks'

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490951003 -7200
#  Fri Mar 31 11:03:23 2017 +0200
# Node ID 2043a184b25cda298f5d590c5c08500471c488d9
# Parent  e033dfed0a983e7c4230fd16eb86bce0e2008659
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 2043a184b25c
hook: use 'htype' in 'runhooks'

Same rational as for '_pythonhook', 'htype' is more accurate and less error
prone. We just fixed an error from the 'name'/'hname' confusion and this should
prevent them in the future.

diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -201,7 +201,7 @@ def hook(ui, repo, name, throw=False, **
 r = res[hname][0] or r
 return r
 
-def runhooks(ui, repo, name, hooks, throw=False, **args):
+def runhooks(ui, repo, htype, hooks, throw=False, **args):
 res = {}
 oldstdout = -1
 
@@ -229,7 +229,8 @@ def runhooks(ui, repo, name, hooks, thro
 r = 1
 raised = False
 elif callable(cmd):
-r, raised = _pythonhook(ui, repo, name, hname, cmd, args, 
throw)
+r, raised = _pythonhook(ui, repo, htype, hname, cmd, args,
+throw)
 elif cmd.startswith('python:'):
 if cmd.count(':') >= 2:
 path, cmd = cmd[7:].rsplit(':', 1)
@@ -244,7 +245,7 @@ def runhooks(ui, repo, name, hooks, thro
 hookfn = getattr(mod, cmd)
 else:
 hookfn = cmd[7:].strip()
-r, raised = _pythonhook(ui, repo, name, hname, hookfn, args,
+r, raised = _pythonhook(ui, repo, htype, hname, hookfn, args,
 throw)
 else:
 r = _exthook(ui, repo, hname, cmd, args, throw)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 7 V2] hook: fix name used in untrusted message

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490950925 -7200
#  Fri Mar 31 11:02:05 2017 +0200
# Node ID e033dfed0a983e7c4230fd16eb86bce0e2008659
# Parent  c81fb978412978f5d10879987ed5a571cb9b0904
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r e033dfed0a98
hook: fix name used in untrusted message

The name used in the message we issue when a hook is untrusted was using "name"
which is actually the hook type and not the name of the hook.

diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -223,9 +223,9 @@ def runhooks(ui, repo, name, hooks, thro
 if cmd is _fromuntrusted:
 if throw:
 raise error.HookAbort(
-_('untrusted hook %s not executed') % name,
+_('untrusted hook %s not executed') % hname,
 hint = _("see 'hg help config.trusted'"))
-ui.warn(_('warning: untrusted hook %s not executed\n') % name)
+ui.warn(_('warning: untrusted hook %s not executed\n') % hname)
 r = 1
 raised = False
 elif callable(cmd):
diff --git a/tests/test-hook.t b/tests/test-hook.t
--- a/tests/test-hook.t
+++ b/tests/test-hook.t
@@ -904,7 +904,7 @@ Non-blocking hook
   > txnclose.testing=echo txnclose hook called
   > EOF
   $ touch a && hg commit -Aqm a
-  warning: untrusted hook txnclose not executed
+  warning: untrusted hook txnclose.testing not executed
   $ hg log
   changeset:   0:3903775176ed
   tag: tip
@@ -923,7 +923,7 @@ Non-blocking hook
   $ touch b && hg commit -Aqm a
   transaction abort!
   rollback completed
-  abort: untrusted hook pretxnclose not executed
+  abort: untrusted hook pretxnclose.testing not executed
   (see 'hg help config.trusted')
   [255]
   $ hg log
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: Internal-changeset concept

2017-03-31 Thread Pierre-Yves David

grmlm, this half-written draft was sent by mistake, please disregard

On 03/31/2017 10:46 PM, Pierre-Yves David wrote:



On 03/30/2017 07:08 PM, Ryan McElroy wrote:

On 3/30/17 3:15 PM, Pierre-Yves David wrote:

[…]
I hope this long message help to clarify various concept. We have way
forward to reduce the use of stripping without abusing the
obsolescence concept in a way that will create issue for users. These
way forward are in reach and would not take too long to build.




For what it's worth, I find this essay pretty convincing: obsmarkers
have their use-case, they are lightly abused now (for temp-amend-commit)
but it probably makes sense to not abuse them further.

It sounds like an "internal" phase above "secret" would actually map
fairly well onto the temp-amend-commit, hidden shelves never meant to be
exchanged, aborted rebase, etc places.

Pierre-Yves, since you've thought about this a lot, does a phase here
make sense (note that I'm not saying a general hiding place like
"archive" phase, but just for internal nodes that we generally don't
want shown or exchanged, but are also not "technically obsolete".


Yes, phase could actually work when we talk about internal changesets.
They property makes is

  * They are irrelevant to the users,

So, we do not care about preserving draft/secret phase,

  * We should never-ever base anything on them,

So the inheritance to parent will not be an issue

  * We should never-ever access them ever again,

So we can thrown them in the phase and never think about them again.

  * They should never-ever leave the repository.

So their should not be any distributed related issue with them (and even
if they are hard copied, it is fine to never-ever mention them during
exchange.

  * They never stop being internal-changesets

That one is a bit less "phasee", we would have to adds some boundary.

---

You I are right, given the property of internal changesets phases may be
a good pick for them.

I'll do a full review of the problem space and its possible solution, if
you want the summary skip to the end


Problem Space
=

Possible approach
-

Since introducing a new "internal" concept will requires a new
repository requirement. Lets discussion all options we have at hands.

  1) dedicated 'internal' phases,
  2) ad-hoc mechanism (lets says bytemap),
  3) Something in changeset extra,

(If someone think about something else, let me know)

Internal changeset property
---

Now let us summarize their property of internal changesets

  A) They are irrelevant to the users,
  B) Nothing will be based on them,
  C) Once done with their purpose, we should not need them again,
  D) They never leave the repository,
  E) They never stop being internal changesets,

Life Cycle of Internal Changeset
-

And lets look at the life cycle of internal changeset we know:

amend
`

  1) transaction is open,
  2) a temporary commit is created,
  3) and used to build the result of the amend,
  4) obsmarkers are created (between old and new),
  5) temporary commit is disposed of (currently obsmarkers),
  6) transaction is committed.

The commit is created and "hidden" in the same transaction. It is never
visible to anyone.

Actually, we would fully remove this change set with appropriate
in-memory-ctx capabilities.


histedit


Scenario:

  pick second-changeset
  pick first-changeset
  roll fourth changeset # the important part is the fold
  pick third changeset

(Assuming single transaction for simplicity)

  1) transaction is open,
  2)  is rebased on base
(possible conflict and associated transaction open/close)
 -> creates ,
  3)  is rebased on the result
(possible conflict and associated transaction open/close)
 -> creates ,
  4)  is rebased on the result (no commit),
(possible conflict and associated transaction open/close)
  5) result is folded in  as 
  6)  is rebased on the result
(possible conflict and associated transaction open/close)
 -> creates ,
  7) transaction is committed.

Possible conflict during (4) will expose  as visible
to the user, part of the merge conflict and working directory parent.


shelve
``

shelving:

  1) transaction is open,
  2) shelved change are committed,
  3) commit is recorded as a shelve-changeset,
  4) apply hidding on this shelve,
  5) transaction is committed



unshelving (I might be wrong, I've not followed everything):

  1) transaction is open
  2) uncommitted changes are put in an temporary commit
  *) access the shelve-changeset (somehow),
  3) hg rebase -r  -d 
  <) possible conflict resolution that requires transaction commit
  >) possible transaction reopen (if conflict)
  =) rebase complete
  4) grab the result of the shelve and restore working copy parent
  5) hide  and 
  6) close transaction

Note: during possible rebase conflict, the "shelve" is currently visible
to the user. Can we change this ?

* At 

Internal-changeset concept (was: re: [PATCH RFC] repo: add an ability to hide nodes in an appropriate way)

2017-03-31 Thread Pierre-Yves David



On 03/30/2017 07:08 PM, Ryan McElroy wrote:

On 3/30/17 3:15 PM, Pierre-Yves David wrote:

[…]
I hope this long message help to clarify various concept. We have way
forward to reduce the use of stripping without abusing the
obsolescence concept in a way that will create issue for users. These
way forward are in reach and would not take too long to build.




For what it's worth, I find this essay pretty convincing: obsmarkers
have their use-case, they are lightly abused now (for temp-amend-commit)
but it probably makes sense to not abuse them further.

It sounds like an "internal" phase above "secret" would actually map
fairly well onto the temp-amend-commit, hidden shelves never meant to be
exchanged, aborted rebase, etc places.

Pierre-Yves, since you've thought about this a lot, does a phase here
make sense (note that I'm not saying a general hiding place like
"archive" phase, but just for internal nodes that we generally don't
want shown or exchanged, but are also not "technically obsolete".


Yes, phase could actually work when we talk about internal changesets.
They property makes is

  * They are irrelevant to the users,

So, we do not care about preserving draft/secret phase,

  * We should never-ever base anything on them,

So the inheritance to parent will not be an issue

  * We should never-ever access them ever again,

So we can thrown them in the phase and never think about them again.

  * They should never-ever leave the repository.

So their should not be any distributed related issue with them (and even 
if they are hard copied, it is fine to never-ever mention them during 
exchange.


  * They never stop being internal-changesets

That one is a bit less "phasee", we would have to adds some boundary.

---

You I are right, given the property of internal changesets phases may be 
a good pick for them.


I'll do a full review of the problem space and its possible solution, if 
you want the summary skip to the end



Problem Space
=

Possible approach
-

Since introducing a new "internal" concept will requires a new 
repository requirement. Lets discussion all options we have at hands.


  1) dedicated 'internal' phases,
  2) ad-hoc mechanism (lets says bytemap),
  3) Something in changeset extra,

(If someone think about something else, let me know)

Internal changeset property
---

Now let us summarize their property of internal changesets

  A) They are irrelevant to the users,
  B) Nothing will be based on them,
  C) Once done with their purpose, we should not need them again,
  D) They never leave the repository,
  E) They never stop being internal changesets,

Life Cycle of Internal Changeset
-

And lets look at the life cycle of internal changeset we know:

amend
`

  1) transaction is open,
  2) a temporary commit is created,
  3) and used to build the result of the amend,
  4) obsmarkers are created (between old and new),
  5) temporary commit is disposed of (currently obsmarkers),
  6) transaction is committed.

The commit is created and "hidden" in the same transaction. It is never 
visible to anyone.


Actually, we would fully remove this change set with appropriate 
in-memory-ctx capabilities.



histedit


Scenario:

  pick second-changeset
  pick first-changeset
  roll fourth changeset # the important part is the fold
  pick third changeset

(Assuming single transaction for simplicity)

  1) transaction is open,
  2)  is rebased on base
(possible conflict and associated transaction open/close)
 -> creates ,
  3)  is rebased on the result
(possible conflict and associated transaction open/close)
 -> creates ,
  4)  is rebased on the result (no commit),
(possible conflict and associated transaction open/close)
  5) result is folded in  as 
  6)  is rebased on the result
(possible conflict and associated transaction open/close)
 -> creates ,
  7) transaction is committed.

Possible conflict during (4) will expose  as visible 
to the user, part of the merge conflict and working directory parent.



shelve
``

shelving:

  1) transaction is open,
  2) shelved change are committed,
  3) commit is recorded as a shelve-changeset,
  4) apply hidding on this shelve,
  5) transaction is committed



unshelving (I might be wrong, I've not followed everything):

  1) transaction is open
  2) uncommitted changes are put in an temporary commit
  *) access the shelve-changeset (somehow),
  3) hg rebase -r  -d 
  <) possible conflict resolution that requires transaction commit
  >) possible transaction reopen (if conflict)
  =) rebase complete
  4) grab the result of the shelve and restore working copy parent
  5) hide  and 
  6) close transaction

Note: during possible rebase conflict, the "shelve" is currently visible 
to the user. Can we change this ?


* At minimum, it needs to be at least visible to the "hg resolve 
command". This is easy to achieve in all 

Re: [PATCH 7 of 7] hook: add hook name information to external hook

2017-03-31 Thread Pierre-Yves David



On 03/31/2017 07:48 PM, Jun Wu wrote:

This series looks straightforward to me. I have marked pre-reviewed except
for Patch 1 where I think using "HG_TXNID" is more consistent.


Good catch in patch 1, the last 2 patch will no apply without the first 
one. I'll go through the re-run and submit a V2. If someone want to take 
all the cleanup patch in between in the mean time. Feel free.


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


Re: [PATCH 1 of 7] run-tests: auto-replace 'TXNID' output

2017-03-31 Thread Pierre-Yves David



On 03/31/2017 07:42 PM, Jun Wu wrote:

Excerpts from Pierre-Yves David's message of 2017-03-31 12:17:16 +0200:

# HG changeset patch
# User Pierre-Yves David 
# Date 1490887743 -7200
#  Thu Mar 30 17:29:03 2017 +0200
# Node ID fa07a4f8bc38b3c598c2ff115eca6cdbf2de3ad7
# Parent  2632df096fc0ac7582382b1f94ea4b9ad0bce8f2
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/  -r fa07a4f8bc38
run-tests: auto-replace 'TXNID' output

Hooks related to the transaction are aware of the transaction id. By definition
this txn-id is unique and different for each transaction. As a result it can
never be predicted in test and always needs matching. As a result, touching any
like with this data is annoying. We solve the problem once and for all by
installing an automatic replacement. In test, this will now show as:

  TXNID=TXN:$ID$

diff --git a/tests/run-tests.py b/tests/run-tests.py
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -848,6 +848,7 @@ class Test(unittest.TestCase):
 (br'(?m)^(saved backup bundle to .*\.hg)( \(glob\))?$',
  br'\1 (glob)'),
 (br'([^0-9])%s' % re.escape(self._localip()), br'\1$LOCALIP'),
+(br'\bHG_TXNID=TXN:[a-f0-9]{40}\b', br'TXNID=TXN:$ID$'),


Is there a reason to drop the "HG_" prefix?


Absolutely not. Good catch !

This will requires a rerun of the test for patch 1 and the last 2.

I'll send a V2.

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


Re: [PATCH 7 of 7] hook: add hook name information to external hook

2017-03-31 Thread Jun Wu
This series looks straightforward to me. I have marked pre-reviewed except
for Patch 1 where I think using "HG_TXNID" is more consistent.

Excerpts from Pierre-Yves David's message of 2017-03-31 12:17:22 +0200:
> # HG changeset patch
> # User Pierre-Yves David 
> # Date 1490954036 -7200
> #  Fri Mar 31 11:53:56 2017 +0200
> # Node ID ce04d3eb4be0c920a21a6d14d2d71941ba3615d3
> # Parent  67387fa9e82e6a84ab801ebdb28c8faa50e652ff
> # EXP-Topic hookname
> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ 
> #  hg pull 
> https://www.mercurial-scm.org/repo/users/marmoute/mercurial/  -r ce04d3eb4be0
> hook: add hook name information to external hook
> 
> While we are here, we can also add the hook name information to external hook.
> 
> diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
> --- a/mercurial/help/config.txt
> +++ b/mercurial/help/config.txt
> @@ -844,9 +844,10 @@ Example ``.hg/hgrc``::
>  Most hooks are run with environment variables set that give useful
>  additional information. For each hook below, the environment variables
>  it is passed are listed with names of the form ``$HG_foo``. The
> -``$HG_HOOKTYPE`` variable is set for all hooks. It contains the type of
> -hook which triggered the run. In the example about this will be
> -``$HG_HOOKTYPE=incoming``.
> +``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
> +their respectively contains the type of hook which triggered the run and
> +the full name of the hooks in the config. In the example about this will
> +be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
>  
>  ``changegroup``
>Run after a changegroup has been added via push, pull or unbundle.  ID of 
> the
> diff --git a/mercurial/hook.py b/mercurial/hook.py
> --- a/mercurial/hook.py
> +++ b/mercurial/hook.py
> @@ -127,6 +127,7 @@ def _exthook(ui, repo, htype, name, cmd,
>  if tr and tr.writepending():
>  env['HG_PENDING'] = repo.root
>  env['HG_HOOKTYPE'] = htype
> +env['HG_HOOKNAME'] = name
>  
>  for k, v in args.iteritems():
>  if callable(v):
> diff --git a/tests/test-bundle.t b/tests/test-bundle.t
> --- a/tests/test-bundle.t
> +++ b/tests/test-bundle.t
> @@ -232,7 +232,7 @@ hg -R bundle://../full.hg verify
>adding manifests
>adding file changes
>added 9 changesets with 7 changes to 4 files (+1 heads)
> -  changegroup hook: HG_HOOKTYPE=changegroup 
> HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
> HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
> TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
> +  changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup 
> HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
> HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
> TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
>(run 'hg heads' to see heads, 'hg merge' to merge)
>  
>  Rollback empty
> @@ -255,7 +255,7 @@ Pull full.hg into empty again (using -R;
>adding manifests
>adding file changes
>added 9 changesets with 7 changes to 4 files (+1 heads)
> -  changegroup hook: HG_HOOKTYPE=changegroup 
> HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
> HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
> TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
> +  changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup 
> HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
> HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
> TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
>(run 'hg heads' to see heads, 'hg merge' to merge)
>  
>  Cannot produce streaming clone bundles with "hg bundle"
> diff --git a/tests/test-bundle2-exchange.t b/tests/test-bundle2-exchange.t
> --- a/tests/test-bundle2-exchange.t
> +++ b/tests/test-bundle2-exchange.t
> @@ -41,7 +41,7 @@ The extension requires a repo (currently
>$ hg commit -m 'a'
>pre-close-tip:3903775176ed draft 
>postclose-tip:3903775176ed draft 
> -  txnclose hook: HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 TXNID=TXN:$ID$ 
> HG_TXNNAME=commit
> +  txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose 
> HG_PHASES_MOVED=1 TXNID=TXN:$ID$ HG_TXNNAME=commit
>  
>$ hg unbundle $TESTDIR/bundles/rebase.hg
>adding changesets
> @@ -50,7 +50,7 @@ The extension requires a repo (currently
>added 8 changesets with 7 changes to 7 files (+3 heads)
>pre-close-tip:02de42196ebe draft 
>postclose-tip:02de42196ebe draft 
> -  txnclose hook: HG_HOOKTYPE=txnclose 
> HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
> HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
> HG_SOURCE=unbundle TXNID=TXN:$ID$ HG_TXNNAME=unbundle
> +  txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose 
> HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
> HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
> HG_SOURCE=unbundle TXNID=TXN:$ID$ 

Re: [PATCH 1 of 7] run-tests: auto-replace 'TXNID' output

2017-03-31 Thread Jun Wu
Excerpts from Pierre-Yves David's message of 2017-03-31 12:17:16 +0200:
> # HG changeset patch
> # User Pierre-Yves David 
> # Date 1490887743 -7200
> #  Thu Mar 30 17:29:03 2017 +0200
> # Node ID fa07a4f8bc38b3c598c2ff115eca6cdbf2de3ad7
> # Parent  2632df096fc0ac7582382b1f94ea4b9ad0bce8f2
> # EXP-Topic hookname
> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ 
> #  hg pull 
> https://www.mercurial-scm.org/repo/users/marmoute/mercurial/  -r fa07a4f8bc38
> run-tests: auto-replace 'TXNID' output
> 
> Hooks related to the transaction are aware of the transaction id. By 
> definition
> this txn-id is unique and different for each transaction. As a result it can
> never be predicted in test and always needs matching. As a result, touching 
> any
> like with this data is annoying. We solve the problem once and for all by
> installing an automatic replacement. In test, this will now show as:
> 
>   TXNID=TXN:$ID$
> 
> diff --git a/tests/run-tests.py b/tests/run-tests.py
> --- a/tests/run-tests.py
> +++ b/tests/run-tests.py
> @@ -848,6 +848,7 @@ class Test(unittest.TestCase):
>  (br'(?m)^(saved backup bundle to .*\.hg)( \(glob\))?$',
>   br'\1 (glob)'),
>  (br'([^0-9])%s' % re.escape(self._localip()), br'\1$LOCALIP'),
> +(br'\bHG_TXNID=TXN:[a-f0-9]{40}\b', br'TXNID=TXN:$ID$'),

Is there a reason to drop the "HG_" prefix?

>  ]
>  r.append((self._escapepath(self._testtmp), b'$TESTTMP'))
>  
> diff --git a/tests/test-bundle.t b/tests/test-bundle.t
> --- a/tests/test-bundle.t
> +++ b/tests/test-bundle.t
> @@ -232,7 +232,7 @@ hg -R bundle://../full.hg verify
>adding manifests
>adding file changes
>added 9 changesets with 7 changes to 4 files (+1 heads)
> -  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
> HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
> HG_TXNID=TXN:* HG_URL=bundle?../full.hg (glob)
> +  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
> HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
> TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
>(run 'hg heads' to see heads, 'hg merge' to merge)
>  
>  Rollback empty
> @@ -255,7 +255,7 @@ Pull full.hg into empty again (using -R;
>adding manifests
>adding file changes
>added 9 changesets with 7 changes to 4 files (+1 heads)
> -  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
> HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
> HG_TXNID=TXN:* HG_URL=bundle:empty+full.hg (glob)
> +  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
> HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
> TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
>(run 'hg heads' to see heads, 'hg merge' to merge)
>  
>  Cannot produce streaming clone bundles with "hg bundle"
> diff --git a/tests/test-bundle2-exchange.t b/tests/test-bundle2-exchange.t
> --- a/tests/test-bundle2-exchange.t
> +++ b/tests/test-bundle2-exchange.t
> @@ -41,7 +41,7 @@ The extension requires a repo (currently
>$ hg commit -m 'a'
>pre-close-tip:3903775176ed draft 
>postclose-tip:3903775176ed draft 
> -  txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
> +  txnclose hook: HG_PHASES_MOVED=1 TXNID=TXN:$ID$ HG_TXNNAME=commit
>  
>$ hg unbundle $TESTDIR/bundles/rebase.hg
>adding changesets
> @@ -50,7 +50,7 @@ The extension requires a repo (currently
>added 8 changesets with 7 changes to 7 files (+3 heads)
>pre-close-tip:02de42196ebe draft 
>postclose-tip:02de42196ebe draft 
> -  txnclose hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
> HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
> HG_SOURCE=unbundle HG_TXNID=TXN:* HG_TXNNAME=unbundle (glob)
> +  txnclose hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
> HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
> HG_SOURCE=unbundle TXNID=TXN:$ID$ HG_TXNNAME=unbundle
>bundle:*/tests/bundles/rebase.hg HG_URL=bundle:*/tests/bundles/rebase.hg 
> (glob)
>(run 'hg heads' to see heads, 'hg merge' to merge)
>  
> @@ -64,18 +64,18 @@ Add more obsolescence information
>$ hg -R main debugobsolete -d '0 0' 
>  `getmainid 9520eea781bc`
>pre-close-tip:02de42196ebe draft 
>postclose-tip:02de42196ebe draft 
> -  txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete 
> (glob)
> +  txnclose hook: HG_NEW_OBSMARKERS=1 TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
>$ hg -R main debugobsolete -d '0 0' 
>  `getmainid 24b6387c8c8c`
>pre-close-tip:02de42196ebe draft 
>postclose-tip:02de42196ebe draft 
> -  txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete 
> (glob)
> +  txnclose hook: HG_NEW_OBSMARKERS=1 

[PATCH 7 of 7] largefiles: use readasstandin() to read hex hash directly from filectx

2017-03-31 Thread FUJIWARA Katsunori
# HG changeset patch
# User FUJIWARA Katsunori 
# Date 1490981569 -32400
#  Sat Apr 01 02:32:49 2017 +0900
# Node ID bd7e74372d5d3763b38717159a805cf557b07604
# Parent  89507622f5b4cb8b8e9f99a02db43b64f10d95f3
largefiles: use readasstandin() to read hex hash directly from filectx

BTW, C implementation of hexdigest() for SHA-1/256/512 returns hex
hash in lower case, and doctest in Python standard hashlib assumes
that, too. But it isn't explicitly described in API document or so.

Therefore, we can't assume that hexdigest() always returns hex hash in
lower case, for any hash algorithms, on any Python runtimes and
versions.

From point of view of that, it is reasonable for portability that
40800668e019 applies lower() on hex hash in overridefilemerge().

But on the other hand, in largefiles extension, there are still many
code paths comparing between hex hashes or storing hex hash into
standin file, without lower().

Switching to hash algorithm other than SHA-1 may be good chance to
clarify our policy about hexdigest()-ed hash value string.

  - assume that hexdigest() always returns hex hash in lower case, or

  - apply lower() on hex hash in appropriate layers to ensure
lower-case-ness of it for portability

diff --git a/hgext/largefiles/basestore.py b/hgext/largefiles/basestore.py
--- a/hgext/largefiles/basestore.py
+++ b/hgext/largefiles/basestore.py
@@ -130,7 +130,7 @@ class basestore(object):
 key = (filename, fctx.filenode())
 if key not in verified:
 verified.add(key)
-expectedhash = fctx.data().strip()
+expectedhash = lfutil.readasstandin(fctx)
 filestocheck.append((cset, filename, expectedhash))
 
 failed = self._verifyfiles(contents, filestocheck)
diff --git a/hgext/largefiles/lfcommands.py b/hgext/largefiles/lfcommands.py
--- a/hgext/largefiles/lfcommands.py
+++ b/hgext/largefiles/lfcommands.py
@@ -406,7 +406,7 @@ def cachelfiles(ui, repo, node, filelist
 ctx = repo[node]
 for lfile in lfiles:
 try:
-expectedhash = ctx[lfutil.standin(lfile)].data().strip()
+expectedhash = lfutil.readasstandin(ctx[lfutil.standin(lfile)])
 except IOError as err:
 if err.errno == errno.ENOENT:
 continue # node must be None and standin wasn't found in wctx
diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -174,7 +174,7 @@ def lfdirstatestatus(lfdirstate, repo):
 fctx = pctx[standin(lfile)]
 except LookupError:
 fctx = None
-if not fctx or fctx.data().strip() != hashfile(repo.wjoin(lfile)):
+if not fctx or readasstandin(fctx) != hashfile(repo.wjoin(lfile)):
 modified.append(lfile)
 else:
 clean.append(lfile)
@@ -528,7 +528,7 @@ def getlfilestoupload(repo, missing, add
 files.add(f)
 for fn in files:
 if isstandin(fn) and fn in ctx:
-addfunc(fn, ctx[fn].data().strip())
+addfunc(fn, readasstandin(ctx[fn]))
 repo.ui.progress(_('finding outgoing largefiles'), None)
 
 def updatestandinsbymatch(repo, match):
diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -553,9 +553,9 @@ def overridefilemerge(origfn, premerge, 
 return origfn(premerge, repo, mynode, orig, fcd, fco, fca,
   labels=labels)
 
-ahash = fca.data().strip().lower()
-dhash = fcd.data().strip().lower()
-ohash = fco.data().strip().lower()
+ahash = lfutil.readasstandin(fca).lower()
+dhash = lfutil.readasstandin(fcd).lower()
+ohash = lfutil.readasstandin(fco).lower()
 if (ohash != ahash and
 ohash != dhash and
 (dhash == ahash or
diff --git a/hgext/largefiles/reposetup.py b/hgext/largefiles/reposetup.py
--- a/hgext/largefiles/reposetup.py
+++ b/hgext/largefiles/reposetup.py
@@ -172,7 +172,7 @@ def reposetup(ui, repo):
 if standin not in ctx1:
 # from second parent
 modified.append(lfile)
-elif ctx1[standin].data().strip() \
+elif lfutil.readasstandin(ctx1[standin]) \
 != lfutil.hashfile(self.wjoin(lfile)):
 modified.append(lfile)
 else:
@@ -188,7 +188,7 @@ def reposetup(ui, repo):
 standin = lfutil.standin(lfile)
 if standin in ctx1:
 abslfile = self.wjoin(lfile)
-if ((ctx1[standin].data().strip() !=
+if 

[PATCH 6 of 7] largefiles: remove unused readstandin()

2017-03-31 Thread FUJIWARA Katsunori
# HG changeset patch
# User FUJIWARA Katsunori 
# Date 1490981569 -32400
#  Sat Apr 01 02:32:49 2017 +0900
# Node ID 89507622f5b4cb8b8e9f99a02db43b64f10d95f3
# Parent  b9fb0f258b9e13605fac19a7aba4cad71e465326
largefiles: remove unused readstandin()

Now, there is no client of readstandin().

diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -361,11 +361,6 @@ def readasstandin(fctx):
 This encapsulates how "standin" data is stored into storage layer.'''
 return fctx.data().strip()
 
-def readstandin(repo, filename, node=None):
-'''read hex hash from standin for filename at given node, or working
-directory if no node is given'''
-return readasstandin(repo[node][standin(filename)])
-
 def writestandin(repo, standin, hash, executable):
 '''write hash to /'''
 repo.wwrite(standin, hash + '\n', executable and 'x' or '')
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 5 of 7] largefiles: make copytostore() accept only changectx as the 2nd argument (API)

2017-03-31 Thread FUJIWARA Katsunori
# HG changeset patch
# User FUJIWARA Katsunori 
# Date 1490981568 -32400
#  Sat Apr 01 02:32:48 2017 +0900
# Node ID b9fb0f258b9e13605fac19a7aba4cad71e465326
# Parent  24fcc76be71a6eede3ecff2bc18a119f649b9ad5
largefiles: make copytostore() accept only changectx as the 2nd argument (API)

As the name describes, the 2nd argument 'revorctx' of copytostore()
can accept non-changectx value, for historical reason,

But, since 10561eb97c7f, copyalltostore(), the only one copytostore()
client in Mercurial source tree, always passes changectx as
'revorctx'.

Therefore, it is reasonable to make copytostore() accept only
changectx as the 2nd argument, now.

diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -245,9 +245,9 @@ def copyfromcache(repo, hash, filename):
 return False
 return True
 
-def copytostore(repo, revorctx, file, fstandin):
+def copytostore(repo, ctx, file, fstandin):
 wvfs = repo.wvfs
-hash = readasstandin(repo[revorctx][fstandin])
+hash = readasstandin(ctx[fstandin])
 if instore(repo, hash):
 return
 if wvfs.exists(file):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 7] largefiles: introduce readasstandin() to read hex hash from given filectx

2017-03-31 Thread FUJIWARA Katsunori
# HG changeset patch
# User FUJIWARA Katsunori 
# Date 1490981551 -32400
#  Sat Apr 01 02:32:31 2017 +0900
# Node ID 340c76876899a57ded1f59fee4e2035f078895d7
# Parent  6be6e4becaafd1bf24f01a2d0464df9cea67588d
largefiles: introduce readasstandin() to  read hex hash from given filectx

This will be used to centralize and encapsulate the logic to read hash
from given (filectx of) standin file. readstandin() isn't suitable for
this purpose, because there are some code paths, which want to read
hex hash directly from filectx.

diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -355,10 +355,16 @@ def updatestandin(repo, lfile, standin):
 else:
 raise error.Abort(_('%s: file not found!') % lfile)
 
+def readasstandin(fctx):
+'''read hex hash from given filectx of standin file
+
+This encapsulates how "standin" data is stored into storage layer.'''
+return fctx.data().strip()
+
 def readstandin(repo, filename, node=None):
 '''read hex hash from standin for filename at given node, or working
 directory if no node is given'''
-return repo[node][standin(filename)].data().strip()
+return readasstandin(repo[node][standin(filename)])
 
 def writestandin(repo, standin, hash, executable):
 '''write hash to /'''
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 7] largefiles: remove unused keyword argument of copytostore() (API)

2017-03-31 Thread FUJIWARA Katsunori
# HG changeset patch
# User FUJIWARA Katsunori 
# Date 1490981568 -32400
#  Sat Apr 01 02:32:48 2017 +0900
# Node ID 24fcc76be71a6eede3ecff2bc18a119f649b9ad5
# Parent  30fde597a072c6bc6419fcbdfab4889cb1c72914
largefiles: remove unused keyword argument of copytostore() (API)

AFAIK, 'uploaded' argument of copytostore() (or copytocache(), before
renaming at c65f5b6e26d4) has been never used both on caller and
callee sides, since official release of bundled largefiles extension.

diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -245,7 +245,7 @@ def copyfromcache(repo, hash, filename):
 return False
 return True
 
-def copytostore(repo, revorctx, file, fstandin, uploaded=False):
+def copytostore(repo, revorctx, file, fstandin):
 wvfs = repo.wvfs
 hash = readasstandin(repo[revorctx][fstandin])
 if instore(repo, hash):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 7] largefiles: replace readstandin() by readasstandin()

2017-03-31 Thread FUJIWARA Katsunori
# HG changeset patch
# User FUJIWARA Katsunori 
# Date 1490981567 -32400
#  Sat Apr 01 02:32:47 2017 +0900
# Node ID a99b27d2fdfb148aa44d1fec88b6b7accadd8084
# Parent  340c76876899a57ded1f59fee4e2035f078895d7
largefiles: replace readstandin() by readasstandin()

These code paths already (or should, for efficiency at repetition)
know the target changectx and path of standin file.

diff --git a/hgext/largefiles/lfcommands.py b/hgext/largefiles/lfcommands.py
--- a/hgext/largefiles/lfcommands.py
+++ b/hgext/largefiles/lfcommands.py
@@ -474,7 +474,7 @@ def updatelfiles(ui, repo, filelist=None
 shutil.copyfile(wvfs.join(rellfile),
 wvfs.join(rellfileorig))
 wvfs.unlinkpath(relstandinorig)
-expecthash = lfutil.readstandin(repo, lfile)
+expecthash = lfutil.readasstandin(wctx[relstandin])
 if expecthash != '':
 if lfile not in wctx: # not switched to normal file
 wvfs.unlinkpath(rellfile, ignoremissing=True)
diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -434,10 +434,11 @@ class storeprotonotcapable(Exception):
 def getstandinsstate(repo):
 standins = []
 matcher = getstandinmatcher(repo)
+wctx = repo[None]
 for standin in repo.dirstate.walk(matcher, [], False, False):
 lfile = splitstandin(standin)
 try:
-hash = readstandin(repo, lfile)
+hash = readasstandin(wctx[standin])
 except IOError:
 hash = None
 standins.append((lfile, hash))
diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -1357,7 +1357,7 @@ def overridecat(orig, ui, repo, file1, *
 data = repo.wwritedata(f, data)
 fp.write(data)
 else:
-hash = lfutil.readstandin(repo, lf, ctx)
+hash = lfutil.readasstandin(ctx[f])
 if not lfutil.inusercache(repo.ui, hash):
 store = storefactory.openstore(repo)
 success, missing = store.get([(lf, hash)])
@@ -1409,7 +1409,7 @@ def mergeupdate(orig, repo, node, branch
 lfutil.writestandin(repo, standin, lfhash,
 lfutil.getexecutable(lfileabs))
 if (standin in pctx and
-lfhash == lfutil.readstandin(repo, lfile, pctx)):
+lfhash == lfutil.readasstandin(pctx[standin])):
 oldclean.add(lfile)
 for lfile in s.added:
 fstandin = lfutil.standin(lfile)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 7] largefiles: add copytostore() fstandin argument to replace readstandin() (API)

2017-03-31 Thread FUJIWARA Katsunori
# HG changeset patch
# User FUJIWARA Katsunori 
# Date 1490981568 -32400
#  Sat Apr 01 02:32:48 2017 +0900
# Node ID 30fde597a072c6bc6419fcbdfab4889cb1c72914
# Parent  a99b27d2fdfb148aa44d1fec88b6b7accadd8084
largefiles: add copytostore() fstandin argument to replace readstandin() (API)

copyalltostore(), only one caller of copytostore(), already knows
standin file name of the target largefile. Therefore, passing it to
copytostore() is more efficient than calculating it in copytostore()
or readstandin().

diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -245,9 +245,9 @@ def copyfromcache(repo, hash, filename):
 return False
 return True
 
-def copytostore(repo, revorctx, file, uploaded=False):
+def copytostore(repo, revorctx, file, fstandin, uploaded=False):
 wvfs = repo.wvfs
-hash = readstandin(repo, file, revorctx)
+hash = readasstandin(repo[revorctx][fstandin])
 if instore(repo, hash):
 return
 if wvfs.exists(file):
@@ -263,7 +263,7 @@ def copyalltostore(repo, node):
 for filename in ctx.files():
 realfile = splitstandin(filename)
 if realfile is not None and filename in ctx.manifest():
-copytostore(repo, ctx, realfile)
+copytostore(repo, ctx, realfile, filename)
 
 def copytostoreabsolute(repo, file, hash):
 if inusercache(repo.ui, hash):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH remotefilelog-ext] debian: clean with "--component remotefilelog" to not need Cython

2017-03-31 Thread Martin von Zweigbergk via Mercurial-devel
# HG changeset patch
# User Martin von Zweigbergk 
# Date 1490978878 25200
#  Fri Mar 31 09:47:58 2017 -0700
# Node ID c7cfe5ae5271e68ae78f53516b68fe60e896a7d2
# Parent  b5df1d5f3e303a75c550f8e8770afad9945edd86
debian: clean with "--component remotefilelog" to not need Cython

I was trying to build a Debian package on a build machine without
Cython installed. That failed when it was running "dh clean --with
python2", which calls the dh_auto_clean target, which in turn calls
"python setup.py clean --all". Overriding that target to pass
"--component remotefilelog" seems to solve the problem.

The internet wasn't able to tell me what else is supposed to be done
in dh_auto_clean, so I can only hope that nothing else than "python
setup.py clean --all" was supposed to be done there.

diff -r b5df1d5f3e30 -r c7cfe5ae5271 contrib/debian/rules
--- a/contrib/debian/rules  Thu Mar 30 04:17:12 2017 -0700
+++ b/contrib/debian/rules  Fri Mar 31 09:47:58 2017 -0700
@@ -6,6 +6,9 @@
 %:
dh $@ --with python2
 
+override_dh_clean:
+   python$(PYVERS) setup.py clean --all --component remotefilelog
+
 override_dh_auto_install:
python$(PYVERS) setup.py install --root $(CURDIR)/debian/remotefilelog 
--install-layout=deb --component remotefilelog
find $(CURDIR)/debian/remotefilelog -name '*.egg-info' -delete
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 6 of 7 shelve-ext v5] shelve: add obs-based unshelve functionality

2017-03-31 Thread Kostia Balytskyi


On 30/03/2017 10:24, Ryan McElroy wrote:
> On 3/29/17 2:18 PM, Kostia Balytskyi wrote:
>> # HG changeset patch
>> # User Kostia Balytskyi 
>> # Date 1490790691 25200
>> #  Wed Mar 29 05:31:31 2017 -0700
>> # Node ID 9ce0a366a6316d1cffc2a875e7dc6b4a3227c851
>> # Parent  743fea249a852994c5bd3e47cdfb617719f19a0a
>> shelve: add obs-based unshelve functionality
>>
>> Obsolescense-based unshelve works as follows:
>> 1. Instead of stripping temporary nodes, markers are created to
>> obsolete them.
>> 2. Restoring commit is just finding it in an unfiltered repo.
>> 3. '--keep' is only passed to rebase on traditional unshelves
>> (and thus traditional rebases), becuase we want markers to be
>> created fro obsolete-based rebases.
> s/fro/for
>
>> 4. 'hg unshelve' uses unfiltered repo to perform rebases
>> because we want rebase to be able to create markers between original
>> and new commits. 'rebaseskipobsolete' is disabled to make rebase not
>> skip the commit altogether.
>> 5. As per sprint discussions, hiding commits with obsmarkers is
>> not ideal. This is okay for now, as long as obsshelve is an
>> experimental feature. In future, once a better approach to
> s/In future/In the future
>
>> hiding things is implemented, we can change the way obsshelve
>> works (and also change its name to not refer to obsolescense).
> This is a great comment.
>
>>
>> Tests for obs-shelve are coming in a separate series.
> Why?
It is not yet clear what is the best way to send them. It can either be 
a single >1000 line
file or ~30 separate patches. In any case, I want to have series as 
short as possible.
>
>>
>> diff --git a/hgext/shelve.py b/hgext/shelve.py
>> --- a/hgext/shelve.py
>> +++ b/hgext/shelve.py
>> @@ -25,6 +25,7 @@ from __future__ import absolute_import
>>   import collections
>>   import errno
>>   import itertools
>> +import time
>> from mercurial.i18n import _
>>   from mercurial import (
>> @@ -254,8 +255,13 @@ class shelvedstate(object):
>> def prunenodes(self, ui, repo):
>>   """Cleanup temporary nodes from the repo"""
>> -repair.strip(ui, repo, self.nodestoprune, backup=False,
>> - topic='shelve')
>> +if self.obsshelve:
>> +unfi = repo.unfiltered()
>> +relations = [(unfi[n], ()) for n in self.nodestoprune]
>> +obsolete.createmarkers(repo, relations)
>> +else:
>> +repair.strip(ui, repo, self.nodestoprune, backup=False,
>> + topic='shelve')
>> def cleanupoldbackups(repo):
>>   vfs = vfsmod.vfs(repo.vfs.join(backupdir))
>> @@ -675,9 +681,14 @@ def unshelvecontinue(ui, repo, state, op
>> repo.vfs.rename('unshelverebasestate', 'rebasestate')
>>   try:
>> -rebase.rebase(ui, repo, **{
>> -'continue' : True
>> -})
>> +# if shelve is obs-based, we want rebase to be able
>> +# to create markers to already-obsoleted commits
>> +_repo = repo.unfiltered() if state.obsshelve else repo
>> +with ui.configoverride({('experimental', 
>> 'rebaseskipobsolete'):
>> +'off'}, 'unshelve'):
>> +rebase.rebase(ui, _repo, **{
>> +'continue' : True,
>> +})
>>   except Exception:
>>   repo.vfs.rename('rebasestate', 'unshelverebasestate')
>>   raise
>> @@ -717,31 +728,59 @@ def _commitworkingcopychanges(ui, repo,
>>   with ui.configoverride({('ui', 'quiet'): True}):
>>   node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
>>   tmpwctx = repo[node]
>> +ui.debug("temporary working copy commit: %s:%s\n" %
>> + (tmpwctx.rev(), nodemod.short(node)))
>>   return tmpwctx, addedbefore
>>   -def _unshelverestorecommit(ui, repo, basename):
>> +def _unshelverestorecommit(ui, repo, basename, obsshelve):
>>   """Recreate commit in the repository during the unshelve"""
>>   with ui.configoverride({('ui', 'quiet'): True}):
>> -shelvedfile(repo, basename, 'hg').applybundle()
>> -shelvectx = repo['tip']
>> +if obsshelve:
>> +md = shelvedfile(repo, basename, 
>> 'oshelve').readobsshelveinfo()
>> +shelvenode = nodemod.bin(md['node'])
>> +repo = repo.unfiltered()
>> +try:
>> +shelvectx = repo[shelvenode]
>> +except error.RepoLookupError:
>> +m = _("shelved node %s not found in repo")
>> +raise error.Abort(m % md['node'])
>> +else:
>> +shelvedfile(repo, basename, 'hg').applybundle()
>> +shelvectx = repo['tip']
>>   return repo, shelvectx
>> def _rebaserestoredcommit(ui, repo, opts, tr, oldtiprev, 
>> basename, pctx,
>> tmpwctx, shelvectx, branchtorestore,
>> -  activebookmark):
>> +   

Re: [PATCH 5 of 5] ui: use bytes IO and convert EOL manually in ui.editor()

2017-03-31 Thread David Soria Parra
On Wed, Mar 29, 2017 at 11:46:41PM +0900, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1490791418 -32400
> #  Wed Mar 29 21:43:38 2017 +0900
> # Node ID 81aa3738f703e4354b0f853e87548a139b129bdd
> # Parent  c43fe15a4a4bec542b7411087a1ad0233cb5614f
> ui: use bytes IO and convert EOL manually in ui.editor()
> 
I am not sure if we should convert line endings. In particular crecord is
calling ui.edit() with a patch. A patch that would have CRLF line endings would
be displayed wrong and if someone wants to add a lineending or remove it in the
process, we would wrongly convert it to LF on Windows machines.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 1 of 5] check-code: detect r.revision(r.node(rev))

2017-03-31 Thread Yuya Nishihara
On Wed, 29 Mar 2017 16:57:34 -0700, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu 
> # Date 1490831217 25200
> #  Wed Mar 29 16:46:57 2017 -0700
> # Node ID e28b3818efa140482be9849f7bd8dd915e25fa07
> # Parent  cda83a1bfb3ac3a23cfa158c407be93755c1018e
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #  hg pull https://bitbucket.org/quark-zju/hg-draft -r 
> e28b3818efa1
> check-code: detect r.revision(r.node(rev))

> diff --git a/tests/test-check-code.t b/tests/test-check-code.t
> --- a/tests/test-check-code.t
> +++ b/tests/test-check-code.t
> @@ -10,5 +10,14 @@ New errors are not allowed. Warnings are
>$ hg locate -X contrib/python-zstandard -X hgext/fsmonitor/pywatchman |
>> sed 's-\\-/-g' | xargs "$check_code" --warnings --per-file=0 || false
> +  contrib/perf.py:859:
> +   > r.revision(r.node(x))
> +   don't covert rev to node before passing to revision(nodeorrev)

Updated test-contrib-perf.t as well.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] sslutil: clarify internal documentation

2017-03-31 Thread Yuya Nishihara
On Fri, 31 Mar 2017 11:11:17 +0100, Ryan McElroy wrote:
> On 3/31/17 2:32 AM, Matt Harbison wrote:
> > # HG changeset patch
> > # User Matt Harbison 
> > # Date 1490795674 14400
> > #  Wed Mar 29 09:54:34 2017 -0400
> > # Node ID 9505a8771bb00e56230e4c4b265e8369e659a54f
> > # Parent  2632df096fc0ac7582382b1f94ea4b9ad0bce8f2
> > sslutil: clarify internal documentation
> >
> > I ran into this python issue with an incomplete certificate chain on Windows
> > recently, and this is the clarification that came from that experimenting.  
> > The
> > comment I left on the bug tracker [1] with a reference to the CPython code 
> > [2]
> > indicates that the original problem I had is a different bug, but happened 
> > to
> > be mentioned under issue20916 on the Python bug tracker.
> 
> This looks like a good clarification to me. Marked at pre-reviewed in 
> patchwork.

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


Re: [PATCH] hgweb: prefix line id by ctx shortnode in filelog when patches are shown

2017-03-31 Thread Yuya Nishihara
On Fri, 31 Mar 2017 10:55:57 +0200, Denis Laxalde wrote:
> # HG changeset patch
> # User Denis Laxalde 
> # Date 1490902810 -7200
> #  Thu Mar 30 21:40:10 2017 +0200
> # Node ID 7ae1cc7ae6c50a037525f27e203a2ce75fc3004f
> # Parent  dea2a17cbfd00bf08ee87b3e44b1c71499189f89
> # Available At http://hg.logilab.org/users/dlaxalde/hg
> #  hg pull http://hg.logilab.org/users/dlaxalde/hg -r 7ae1cc7ae6c5
> hgweb: prefix line id by ctx shortnode in filelog when patches are shown

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


Re: [PATCH] test-check-code: prevent files being added to the root directory

2017-03-31 Thread Yuya Nishihara
On Wed, 29 Mar 2017 12:14:42 -0700, Jun Wu wrote:
> # HG changeset patch
> # User Jun Wu 
> # Date 1490814860 25200
> #  Wed Mar 29 12:14:20 2017 -0700
> # Node ID 4b4345a62fbd9fb0f4610d013c4ee5c9c06287e0
> # Parent  cda83a1bfb3ac3a23cfa158c407be93755c1018e
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #  hg pull https://bitbucket.org/quark-zju/hg-draft -r 
> 4b4345a62fbd
> test-check-code: prevent files being added to the root directory

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


Re: [PATCH 5 of 5] perf: workaround check-code

2017-03-31 Thread Yuya Nishihara
On Thu, 30 Mar 2017 09:48:35 +0100, Ryan McElroy wrote:
> On 3/30/17 12:57 AM, Jun Wu wrote:
> > # HG changeset patch
> > # User Jun Wu 
> > # Date 1490831529 25200
> > #  Wed Mar 29 16:52:09 2017 -0700
> > # Node ID 5ca313b3da12d145f1d49a85dd8b753e22d51521
> > # Parent  265ea657d75905fb59a27194a75aaff49be94598
> > perf: workaround check-code
> 
> The code int his series all looks good to me. I'll mark as pre-reviewed 
> in patchwork.

Queued 1-4, thanks.

> The only question I have is whether we prefer to leave
> check-code errors in place inside the test, or workaround it with hacks 
> like this?

We can add an ignore pattern for that purpose. See "re-raises" for example.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 2 of 2 V3] serve: make the URL the same for `hg serve` and `hg serve -S`

2017-03-31 Thread Yuya Nishihara
On Thu, 30 Mar 2017 21:21:27 -0400, Matt Harbison wrote:
> On Tue, 28 Mar 2017 10:02:34 -0400, Yuya Nishihara  wrote:
> 
> > On Sun, 26 Mar 2017 23:04:31 -0400, Matt Harbison wrote:
> >> # HG changeset patch
> >> # User Matt Harbison 
> >> # Date 1488146777 18000
> >> #  Sun Feb 26 17:06:17 2017 -0500
> >> # Node ID d584ca4bc33bd2ebeaf9a7bd86440b3cdcecc138
> >> # Parent  0ff9bef3e0f67422cf29c200fa4a671d861d060b
> >> serve: make the URL the same for `hg serve` and `hg serve -S`
> >>
> >> It's perfectly workable to serve up the parent repo without the -S for  
> >> push and
> >> pull, as long as there are no subrepo changes in play.  Therefore,  
> >> having a
> >> different URL for the main repo based on the presence of this option  
> >> seems like
> >> it would get annoying.
> >
> > This looks good, but more detailed commit message will help since some
> > changes in hgweb/hgwebdir are really subtle.
> 
> Other than noting that this change allows repos to be hosted at "", is  
> there something else to mention on this one?

Not really. That's the most important thing should be noted, I think. That
partly describes why the following change is needed. I would phrase the
summary line as "hgwebdir: allow repo to be hosted at /" or something.

> -if not virtual or (virtual == 'index' and virtual not in repos):
> +if (not virtual or virtual == 'index') and virtual not in repos:

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


RE: [PATCH 3 of 7 shelve-ext v5] shelve: add obs-based shelve functionality

2017-03-31 Thread Kostia Balytskyi
Thunderbird lets me down, so I will reply one more time from Outlook. I do not 
understand why we need to unhide a commit. Can you explain?

-Original Message-
From: Mercurial-devel [mailto:mercurial-devel-boun...@mercurial-scm.org] On 
Behalf Of Jun Wu
Sent: Thursday, 30 March, 2017 19:03
To: Kostia Balytskyi 
Cc: mercurial-devel@mercurial-scm.org
Subject: Re: [PATCH 3 of 7 shelve-ext v5] shelve: add obs-based shelve 
functionality

As long as evolve does not have a way to unhide a commit. I think we do need to 
use strip on repos that with obsstore enabled. So I'd say the patch probably 
needs to be deferred until we can unhide a commit.

Excerpts from Kostia Balytskyi's message of 2017-03-30 10:11:55 +:
> 
> On 30/03/2017 10:15, Ryan McElroy wrote:
> >
> >
> > On 3/29/17 2:18 PM, Kostia Balytskyi wrote:
> >> # HG changeset patch
> >> # User Kostia Balytskyi  # Date 1490790691 25200
> >> #  Wed Mar 29 05:31:31 2017 -0700
> >> # Node ID fc1144e5993a5c85060b913e2d92cd4b1b61772e
> >> # Parent  0aa864184c9d78c11d18980cf0faa10828445ff5
> >> shelve: add obs-based shelve functionality
> >>
> >> Obsolescense-based shelve works in a following way:
> >
> > s/ a/ the
> sigh :/ Will fix.
> >
> >> 1. In order to shelve some changes, it creates a commit, records 
> >> its node into a .oshelve file and prunes created commit.
> >> 2. In order to finish a shelve operation, transaction is just 
> >> closed and not aborted.
> >
> > s/transaction/the transaction
> >
> >>
> >> diff --git a/hgext/shelve.py b/hgext/shelve.py
> >> --- a/hgext/shelve.py
> >> +++ b/hgext/shelve.py
> >> @@ -380,10 +380,15 @@ def _nothingtoshelvemessaging(ui, repo,
> >>   else:
> >>   ui.status(_("nothing changed\n"))
> >>   -def _shelvecreatedcommit(repo, node, name):
> >> -bases = list(mutableancestors(repo[node]))
> >> -shelvedfile(repo, name, 'hg').writebundle(bases, node)
> >> -cmdutil.export(repo, [node],
> >> +def _shelvecreatedcommit(ui, repo, node, name, tr):
> >> +if isobsshelve(repo, ui):
> >> +shelvedfile(repo, name, 'oshelve').writeobsshelveinfo({
> >> +'node': nodemod.hex(node)
> >> +})
> >> +else:
> >> +bases = list(mutableancestors(repo[node]))
> >> +shelvedfile(repo, name, 'hg').writebundle(bases, node)
> >> +cmdutil.export(repo.unfiltered(), [node],
> >>  fp=shelvedfile(repo, name, 
> >> patchextension).opener('wb'),
> >>  opts=mdiff.diffopts(git=True))
> >
> > I'm a latecomer to paying attention to this series, so please push 
> > back on me if this has already been discussed, but I think it would 
> > be "cleaner" to not mix old shelve and logic, and instead have just 
> > have the main function _shelvecreatedcommit() call out to
> > _obsshelvecreatedcommit() or _abortshelvecreatedcommit() (or 
> > whatever we call the traditional version).
> >
> > Again, feel free to push back if this has already been discussed or 
> > discarded as a direction, or if there are other reasons to not do it.
> I agree that this can be made better. Sean Farley (if I'm not 
> mistaken) suggested that this should be a class. I do not mind 
> refactrong it later, but I want to get it in first as a functionality. 
> Also, currently, if I understand you correctly, you want to split an 
> 11 line function into two. I don't think it's worth it at the moment.
> >
> >>   @@ -394,8 +399,13 @@ def _includeunknownfiles(repo, pats, opt
> >>   extra['shelve_unknown'] = '\0'.join(s.unknown)
> >>   repo[None].add(s.unknown)
> >>   -def _finishshelve(repo):
> >> -_aborttransaction(repo)
> >> +def _finishshelve(ui, repo, tr, node):
> >> +if isobsshelve(repo, ui):
> >> +obsolete.createmarkers(repo, [(repo.unfiltered()[node], ())])
> >> +tr.close()
> >> +tr.release()
> >> +else:
> >> +_aborttransaction(repo)
> >> def _docreatecmd(ui, repo, pats, opts):
> >>   wctx = repo[None]
> >> @@ -417,9 +427,12 @@ def _docreatecmd(ui, repo, pats, opts):
> >>   try:
> >>   lock = repo.lock()
> >>   -# use an uncommitted transaction to generate the bundle to 
> >> avoid
> >> -# pull races. ensure we don't print the abort message to 
> >> stderr.
> >> -tr = repo.transaction('commit', report=lambda x: None)
> >> +# depending on whether shelve is traditional or
> >> +# obsolescense-based, we either abort or commit this
> >> +# transaction in the end. If we abort it, we don't
> >> +# want to print anything to stderr
> >> +report = None if isobsshelve(repo, ui) else (lambda x: None)
> >> +tr = repo.transaction('commit', report=report)
> >> interactive = opts.get('interactive', False)
> >>   includeunknown = (opts.get('unknown', False) and @@ 
> >> -447,16 +460,19 @@ def _docreatecmd(ui, repo, pats, opts):
> >>   

Re: [PATCH] revlog: use raw revision for rawsize

2017-03-31 Thread Yuya Nishihara
On Wed, 29 Mar 2017 11:30:50 +0100, Ryan McElroy wrote:
> On 3/29/17 4:31 AM, Jun Wu wrote:
> > # HG changeset patch
> > # User Jun Wu 
> > # Date 1490758201 25200
> > #  Tue Mar 28 20:30:01 2017 -0700
> > # Node ID 5c6ebe1cd99e9557b61ef51ed88e335ac87df8da
> > # Parent  31073077267b5e330925d48098dd6e0fd28bdd8e
> > revlog: use raw revision for rawsize
> >
> > diff --git a/mercurial/revlog.py b/mercurial/revlog.py
> > --- a/mercurial/revlog.py
> > +++ b/mercurial/revlog.py
> > @@ -439,5 +439,5 @@ class revlog(object):
> >   return l
> >   
> > -t = self.revision(self.node(rev))
> > +t = self.revision(self.node(rev), raw=True)
> >   return len(t)
> >   size = rawsize
> >
> 
> Having looked at the code, this is inside the "rawsize" function so this 
> is an obviously correct fix. I have marked pre-reviewed in patchwork.

Yeah sounds good, but I'm not pretty sure if the "raw" of rawsize() is related
to flagprocessor's. It was added at 56a7721ee3ec to bypass filelog.size().

This should be queued by someone who has more knowledge.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH] test-verify: add a testcase where the file has magic meta header

2017-03-31 Thread Yuya Nishihara
On Thu, 30 Mar 2017 10:02:34 +0100, Ryan McElroy wrote:
> On 3/29/17 9:45 PM, Jun Wu wrote:
> > # HG changeset patch
> > # User Jun Wu 
> > # Date 1490820077 25200
> > #  Wed Mar 29 13:41:17 2017 -0700
> > # Node ID e9fda3b8614a8b701bd48041afa8b709e1227f27
> > # Parent  cda83a1bfb3ac3a23cfa158c407be93755c1018e
> > test-verify: add a testcase where the file has magic meta header
> >
> > We use a magic header "\1\n" to store metadata like renames. See filelog.py.
> > The patch adds tests about files with the special header.
> 
> Sure, but why? Just to prevent regressions of handling files with this 
> data that "looks like" metadata in them? What's the motivation for 
> adding this test? Just future safety or did you run into something?
> 
> I'm not against it -- adding this test seems like a good idea, but I'd 
> love more context on what led you to write it.

I remember I ran into a weird bug in production and fixed as 012b285cf643,
so I'm sure this test will avoid future bugs caused by '\1\n'.

Jun, can you resend it with more context, perhaps in your verify/rawsize
series? (There seem multiple threads related to this, but I don't follow
all of them.)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH V7] hgweb: expose a followlines UI in filerevision view

2017-03-31 Thread Denis Laxalde
# HG changeset patch
# User Denis Laxalde 
# Date 1490819176 -7200
#  Wed Mar 29 22:26:16 2017 +0200
# Node ID be7965e3afe82be35d258a2cff12b389a857ef88
# Parent  dea2a17cbfd00bf08ee87b3e44b1c71499189f89
# Available At http://hg.logilab.org/users/dlaxalde/hg
#  hg pull http://hg.logilab.org/users/dlaxalde/hg -r be7965e3afe8
hgweb: expose a followlines UI in filerevision view

In filerevision view (/file//) we add some event listeners on
mouse clicks of  elements in the  block.
Those listeners will capture a range of lines selected between two mouse
clicks and a box inviting to follow the history of selected lines will then
show up. Selected lines (i.e. the block of lines) get a CSS class which make
them highlighted. Selection can be cancelled (and restarted) by either
clicking on the cancel ("x") button in the invite box or clicking on any other
source line. Also clicking twice on the same line will abort the selection and
reset event listeners to restart the process.

As a first step, this action is only advertised by the "cursor: cell" CSS rule
on source lines elements as any other mechanisms would make the code
significantly more complicated. This might be improved later.

All JavaScript code lives in a new "linerangelog.js" file, sourced in
filerevision template (only in "paper" style for now).

diff --git a/contrib/wix/templates.wxs b/contrib/wix/templates.wxs
--- a/contrib/wix/templates.wxs
+++ b/contrib/wix/templates.wxs
@@ -225,6 +225,7 @@
 
 
 
+
 
 
 
diff --git a/mercurial/templates/paper/filerevision.tmpl 
b/mercurial/templates/paper/filerevision.tmpl
--- a/mercurial/templates/paper/filerevision.tmpl
+++ b/mercurial/templates/paper/filerevision.tmpl
@@ -71,8 +71,11 @@
 
 line wrap: on
  line source
-{text%fileline}
+{text%fileline}
 
+
+
+
 
 
 
diff --git a/mercurial/templates/static/linerangelog.js 
b/mercurial/templates/static/linerangelog.js
new file mode 100644
--- /dev/null
+++ b/mercurial/templates/static/linerangelog.js
@@ -0,0 +1,163 @@
+// linerangelog.js - JavaScript utilities for followlines UI
+//
+// Copyright 2017 Logilab SA 
+//
+// This software may be used and distributed according to the terms of the
+// GNU General Public License version 2 or any later version.
+
+//** Install event listeners for line block selection and followlines action */
+function installLineSelect() {
+var sourcelines = document.getElementsByClassName('sourcelines')[0];
+if (typeof sourcelines === 'undefined') {
+return;
+}
+// URL to complement with "linerange" query parameter
+var targetUri = sourcelines.dataset.logurl;
+if (typeof targetUri === 'undefined') {
+return;
+}
+
+// retrieve all direct  children of 
+var spans = Array.prototype.filter.call(
+sourcelines.children,
+function(x) { return x.tagName === 'SPAN' });
+
+var lineSelectedCSSClass = 'followlines-selected';
+
+//** add CSS class on  element in `from`-`to` line range */
+function addSelectedCSSClass(from, to) {
+for (var i = from; i <= to; i++) {
+spans[i].classList.add(lineSelectedCSSClass);
+}
+}
+
+//** remove CSS class from previously selected lines */
+function removeSelectedCSSClass() {
+var elements = sourcelines.getElementsByClassName(
+lineSelectedCSSClass);
+while (elements.length) {
+elements[0].classList.remove(lineSelectedCSSClass);
+}
+}
+
+// ** return the  element parent of `element` */
+function findParentSpan(element) {
+var parent = element.parentElement;
+if (parent === null) {
+return null;
+}
+if (element.tagName == 'SPAN' && parent.isSameNode(sourcelines)) {
+return element;
+}
+return findParentSpan(parent);
+}
+
+//** event handler for "click" on the first line of a block */
+function lineSelectStart(e) {
+var startElement = findParentSpan(e.target);
+if (startElement === null) {
+// not a  (maybe ): abort, keeping event listener
+// registered for other click with  target
+return;
+}
+var startId = parseInt(startElement.id.slice(1));
+startElement.classList.add(lineSelectedCSSClass); // CSS
+
+// remove this event listener
+sourcelines.removeEventListener('click', lineSelectStart);
+
+//** event handler for "click" on the last line of the block */
+function lineSelectEnd(e) {
+var endElement = findParentSpan(e.target);
+if (endElement === null) {
+// not a  (maybe ): abort, keeping event listener
+// registered for other click with  target
+return;
+}
+
+// remove this event listener
+

[PATCH 2 of 7] hook: use "htype" as variable name in _pythonhook

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490950777 -7200
#  Fri Mar 31 10:59:37 2017 +0200
# Node ID 4c9bd7ff0722abc6ce410648c68a04222c91d836
# Parent  fa07a4f8bc38b3c598c2ff115eca6cdbf2de3ad7
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 4c9bd7ff0722
hook: use "htype" as variable name  in _pythonhook

We rename 'name' to 'htype' because it fits the variable content better.
Multiple python hooks already use 'htype' as a name for the argument. This makes
the difference with "hname" clearer and the code less error prone.

diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -19,7 +19,7 @@ from . import (
 util,
 )
 
-def _pythonhook(ui, repo, name, hname, funcname, args, throw):
+def _pythonhook(ui, repo, htype, hname, funcname, args, throw):
 '''call python hook. hook is callable object, looked up as
 name in python module. if callable returns "true", hook
 fails, else passes. if hook raises exception, treated as
@@ -90,7 +90,7 @@ def _pythonhook(ui, repo, name, hname, f
 starttime = util.timer()
 
 try:
-r = obj(ui=ui, repo=repo, hooktype=name, **args)
+r = obj(ui=ui, repo=repo, hooktype=htype, **args)
 except Exception as exc:
 if isinstance(exc, error.Abort):
 ui.warn(_('error: %s hook failed: %s\n') %
@@ -107,7 +107,7 @@ def _pythonhook(ui, repo, name, hname, f
 finally:
 duration = util.timer() - starttime
 ui.log('pythonhook', 'pythonhook-%s: %s finished in %0.2f seconds\n',
-   name, funcname, duration)
+   htype, funcname, duration)
 if r:
 if throw:
 raise error.HookAbort(_('%s hook failed') % hname)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 5 of 7] hook: use 'htype' in 'hook'

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490951202 -7200
#  Fri Mar 31 11:06:42 2017 +0200
# Node ID f9989c947fb9ce29d78fd4e159534e7f6e4f1cfa
# Parent  d87f911de0d81391cd17e080a42050e91d45d2a7
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r f9989c947fb9
hook: use 'htype' in 'hook'

Same rational as for 'runhooks', we fix the naming in another function.

diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -186,16 +186,16 @@ def redirect(state):
 global _redirect
 _redirect = state
 
-def hook(ui, repo, name, throw=False, **args):
+def hook(ui, repo, htype, throw=False, **args):
 if not ui.callhooks:
 return False
 
 hooks = []
 for hname, cmd in _allhooks(ui):
-if hname.split('.')[0] == name and cmd:
+if hname.split('.')[0] == htype and cmd:
 hooks.append((hname, cmd))
 
-res = runhooks(ui, repo, name, hooks, throw=throw, **args)
+res = runhooks(ui, repo, htype, hooks, throw=throw, **args)
 r = False
 for hname, cmd in hooks:
 r = res[hname][0] or r
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 3 of 7] hook: fix name used in untrusted message

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490950925 -7200
#  Fri Mar 31 11:02:05 2017 +0200
# Node ID 945e7d8bb4f7e8e5d7032b77d8cf45acd6d24349
# Parent  4c9bd7ff0722abc6ce410648c68a04222c91d836
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 945e7d8bb4f7
hook: fix name used in untrusted message

The name used in the message we issue when a hook is untrusted was using "name"
which is actually the hook type and not the name of the hook.

diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -223,9 +223,9 @@ def runhooks(ui, repo, name, hooks, thro
 if cmd is _fromuntrusted:
 if throw:
 raise error.HookAbort(
-_('untrusted hook %s not executed') % name,
+_('untrusted hook %s not executed') % hname,
 hint = _("see 'hg help config.trusted'"))
-ui.warn(_('warning: untrusted hook %s not executed\n') % name)
+ui.warn(_('warning: untrusted hook %s not executed\n') % hname)
 r = 1
 raised = False
 elif callable(cmd):
diff --git a/tests/test-hook.t b/tests/test-hook.t
--- a/tests/test-hook.t
+++ b/tests/test-hook.t
@@ -904,7 +904,7 @@ Non-blocking hook
   > txnclose.testing=echo txnclose hook called
   > EOF
   $ touch a && hg commit -Aqm a
-  warning: untrusted hook txnclose not executed
+  warning: untrusted hook txnclose.testing not executed
   $ hg log
   changeset:   0:3903775176ed
   tag: tip
@@ -923,7 +923,7 @@ Non-blocking hook
   $ touch b && hg commit -Aqm a
   transaction abort!
   rollback completed
-  abort: untrusted hook pretxnclose not executed
+  abort: untrusted hook pretxnclose.testing not executed
   (see 'hg help config.trusted')
   [255]
   $ hg log
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 7] hook: use 'htype' in 'runhooks'

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490951003 -7200
#  Fri Mar 31 11:03:23 2017 +0200
# Node ID d87f911de0d81391cd17e080a42050e91d45d2a7
# Parent  945e7d8bb4f7e8e5d7032b77d8cf45acd6d24349
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r d87f911de0d8
hook: use 'htype' in 'runhooks'

Same rational as for '_pythonhook', 'htype' is more accurate and less error
prone. We just fixed an error from the 'name'/'hname' confusion and this should
prevent them in the future.

diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -201,7 +201,7 @@ def hook(ui, repo, name, throw=False, **
 r = res[hname][0] or r
 return r
 
-def runhooks(ui, repo, name, hooks, throw=False, **args):
+def runhooks(ui, repo, htype, hooks, throw=False, **args):
 res = {}
 oldstdout = -1
 
@@ -229,7 +229,8 @@ def runhooks(ui, repo, name, hooks, thro
 r = 1
 raised = False
 elif callable(cmd):
-r, raised = _pythonhook(ui, repo, name, hname, cmd, args, 
throw)
+r, raised = _pythonhook(ui, repo, htype, hname, cmd, args,
+throw)
 elif cmd.startswith('python:'):
 if cmd.count(':') >= 2:
 path, cmd = cmd[7:].rsplit(':', 1)
@@ -244,7 +245,7 @@ def runhooks(ui, repo, name, hooks, thro
 hookfn = getattr(mod, cmd)
 else:
 hookfn = cmd[7:].strip()
-r, raised = _pythonhook(ui, repo, name, hname, hookfn, args,
+r, raised = _pythonhook(ui, repo, htype, hname, hookfn, args,
 throw)
 else:
 r = _exthook(ui, repo, hname, cmd, args, throw)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 7 of 7] hook: add hook name information to external hook

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490954036 -7200
#  Fri Mar 31 11:53:56 2017 +0200
# Node ID ce04d3eb4be0c920a21a6d14d2d71941ba3615d3
# Parent  67387fa9e82e6a84ab801ebdb28c8faa50e652ff
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r ce04d3eb4be0
hook: add hook name information to external hook

While we are here, we can also add the hook name information to external hook.

diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -844,9 +844,10 @@ Example ``.hg/hgrc``::
 Most hooks are run with environment variables set that give useful
 additional information. For each hook below, the environment variables
 it is passed are listed with names of the form ``$HG_foo``. The
-``$HG_HOOKTYPE`` variable is set for all hooks. It contains the type of
-hook which triggered the run. In the example about this will be
-``$HG_HOOKTYPE=incoming``.
+``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
+their respectively contains the type of hook which triggered the run and
+the full name of the hooks in the config. In the example about this will
+be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
 
 ``changegroup``
   Run after a changegroup has been added via push, pull or unbundle.  ID of the
diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -127,6 +127,7 @@ def _exthook(ui, repo, htype, name, cmd,
 if tr and tr.writepending():
 env['HG_PENDING'] = repo.root
 env['HG_HOOKTYPE'] = htype
+env['HG_HOOKNAME'] = name
 
 for k, v in args.iteritems():
 if callable(v):
diff --git a/tests/test-bundle.t b/tests/test-bundle.t
--- a/tests/test-bundle.t
+++ b/tests/test-bundle.t
@@ -232,7 +232,7 @@ hg -R bundle://../full.hg verify
   adding manifests
   adding file changes
   added 9 changesets with 7 changes to 4 files (+1 heads)
-  changegroup hook: HG_HOOKTYPE=changegroup 
HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
+  changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup 
HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 Rollback empty
@@ -255,7 +255,7 @@ Pull full.hg into empty again (using -R;
   adding manifests
   adding file changes
   added 9 changesets with 7 changes to 4 files (+1 heads)
-  changegroup hook: HG_HOOKTYPE=changegroup 
HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
+  changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup 
HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 Cannot produce streaming clone bundles with "hg bundle"
diff --git a/tests/test-bundle2-exchange.t b/tests/test-bundle2-exchange.t
--- a/tests/test-bundle2-exchange.t
+++ b/tests/test-bundle2-exchange.t
@@ -41,7 +41,7 @@ The extension requires a repo (currently
   $ hg commit -m 'a'
   pre-close-tip:3903775176ed draft 
   postclose-tip:3903775176ed draft 
-  txnclose hook: HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 TXNID=TXN:$ID$ 
HG_TXNNAME=commit
+  txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose 
HG_PHASES_MOVED=1 TXNID=TXN:$ID$ HG_TXNNAME=commit
 
   $ hg unbundle $TESTDIR/bundles/rebase.hg
   adding changesets
@@ -50,7 +50,7 @@ The extension requires a repo (currently
   added 8 changesets with 7 changes to 7 files (+3 heads)
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_HOOKTYPE=txnclose 
HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
HG_SOURCE=unbundle TXNID=TXN:$ID$ HG_TXNNAME=unbundle
+  txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose 
HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
HG_SOURCE=unbundle TXNID=TXN:$ID$ HG_TXNNAME=unbundle
   bundle:*/tests/bundles/rebase.hg HG_URL=bundle:*/tests/bundles/rebase.hg 
(glob)
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
@@ -64,18 +64,18 @@ Add more obsolescence information
   $ hg -R main debugobsolete -d '0 0'  
`getmainid 9520eea781bc`
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_HOOKTYPE=txnclose 

[PATCH 1 of 7] run-tests: auto-replace 'TXNID' output

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490887743 -7200
#  Thu Mar 30 17:29:03 2017 +0200
# Node ID fa07a4f8bc38b3c598c2ff115eca6cdbf2de3ad7
# Parent  2632df096fc0ac7582382b1f94ea4b9ad0bce8f2
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r fa07a4f8bc38
run-tests: auto-replace 'TXNID' output

Hooks related to the transaction are aware of the transaction id. By definition
this txn-id is unique and different for each transaction. As a result it can
never be predicted in test and always needs matching. As a result, touching any
like with this data is annoying. We solve the problem once and for all by
installing an automatic replacement. In test, this will now show as:

  TXNID=TXN:$ID$

diff --git a/tests/run-tests.py b/tests/run-tests.py
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -848,6 +848,7 @@ class Test(unittest.TestCase):
 (br'(?m)^(saved backup bundle to .*\.hg)( \(glob\))?$',
  br'\1 (glob)'),
 (br'([^0-9])%s' % re.escape(self._localip()), br'\1$LOCALIP'),
+(br'\bHG_TXNID=TXN:[a-f0-9]{40}\b', br'TXNID=TXN:$ID$'),
 ]
 r.append((self._escapepath(self._testtmp), b'$TESTTMP'))
 
diff --git a/tests/test-bundle.t b/tests/test-bundle.t
--- a/tests/test-bundle.t
+++ b/tests/test-bundle.t
@@ -232,7 +232,7 @@ hg -R bundle://../full.hg verify
   adding manifests
   adding file changes
   added 9 changesets with 7 changes to 4 files (+1 heads)
-  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:* HG_URL=bundle?../full.hg (glob)
+  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 Rollback empty
@@ -255,7 +255,7 @@ Pull full.hg into empty again (using -R;
   adding manifests
   adding file changes
   added 9 changesets with 7 changes to 4 files (+1 heads)
-  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
HG_TXNID=TXN:* HG_URL=bundle:empty+full.hg (glob)
+  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 Cannot produce streaming clone bundles with "hg bundle"
diff --git a/tests/test-bundle2-exchange.t b/tests/test-bundle2-exchange.t
--- a/tests/test-bundle2-exchange.t
+++ b/tests/test-bundle2-exchange.t
@@ -41,7 +41,7 @@ The extension requires a repo (currently
   $ hg commit -m 'a'
   pre-close-tip:3903775176ed draft 
   postclose-tip:3903775176ed draft 
-  txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=commit (glob)
+  txnclose hook: HG_PHASES_MOVED=1 TXNID=TXN:$ID$ HG_TXNNAME=commit
 
   $ hg unbundle $TESTDIR/bundles/rebase.hg
   adding changesets
@@ -50,7 +50,7 @@ The extension requires a repo (currently
   added 8 changesets with 7 changes to 7 files (+3 heads)
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
HG_SOURCE=unbundle HG_TXNID=TXN:* HG_TXNNAME=unbundle (glob)
+  txnclose hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
HG_SOURCE=unbundle TXNID=TXN:$ID$ HG_TXNNAME=unbundle
   bundle:*/tests/bundles/rebase.hg HG_URL=bundle:*/tests/bundles/rebase.hg 
(glob)
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
@@ -64,18 +64,18 @@ Add more obsolescence information
   $ hg -R main debugobsolete -d '0 0'  
`getmainid 9520eea781bc`
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete 
(glob)
+  txnclose hook: HG_NEW_OBSMARKERS=1 TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
   $ hg -R main debugobsolete -d '0 0'  
`getmainid 24b6387c8c8c`
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:* HG_TXNNAME=debugobsolete 
(glob)
+  txnclose hook: HG_NEW_OBSMARKERS=1 TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
 
 clone --pull
 
   $ hg -R main phase --public cd010b8cd998
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_PHASES_MOVED=1 HG_TXNID=TXN:* HG_TXNNAME=phase (glob)
+  txnclose hook: HG_PHASES_MOVED=1 TXNID=TXN:$ID$ HG_TXNNAME=phase
   $ hg clone main 

[PATCH 6 of 7] hook: provide hook type information to external hook

2017-03-31 Thread Pierre-Yves David
# HG changeset patch
# User Pierre-Yves David 
# Date 1490951291 -7200
#  Fri Mar 31 11:08:11 2017 +0200
# Node ID 67387fa9e82e6a84ab801ebdb28c8faa50e652ff
# Parent  f9989c947fb9ce29d78fd4e159534e7f6e4f1cfa
# EXP-Topic hookname
# Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
#  hg pull 
https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 67387fa9e82e
hook: provide hook type information to external hook

The python hooks have access to the hook type information. There is not reason
for external hook to not be aware of it too.

For the record my use case is to make sure a hook script is configured for the
right type.

diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -842,8 +842,11 @@ Example ``.hg/hgrc``::
   priority.incoming.autobuild = 1
 
 Most hooks are run with environment variables set that give useful
-additional information. For each hook below, the environment
-variables it is passed are listed with names of the form ``$HG_foo``.
+additional information. For each hook below, the environment variables
+it is passed are listed with names of the form ``$HG_foo``. The
+``$HG_HOOKTYPE`` variable is set for all hooks. It contains the type of
+hook which triggered the run. In the example about this will be
+``$HG_HOOKTYPE=incoming``.
 
 ``changegroup``
   Run after a changegroup has been added via push, pull or unbundle.  ID of the
diff --git a/mercurial/hook.py b/mercurial/hook.py
--- a/mercurial/hook.py
+++ b/mercurial/hook.py
@@ -114,7 +114,7 @@ def _pythonhook(ui, repo, htype, hname, 
 ui.warn(_('warning: %s hook failed\n') % hname)
 return r, False
 
-def _exthook(ui, repo, name, cmd, args, throw):
+def _exthook(ui, repo, htype, name, cmd, args, throw):
 ui.note(_("running hook %s: %s\n") % (name, cmd))
 
 starttime = util.timer()
@@ -126,6 +126,7 @@ def _exthook(ui, repo, name, cmd, args, 
 repo.dirstate.write(tr)
 if tr and tr.writepending():
 env['HG_PENDING'] = repo.root
+env['HG_HOOKTYPE'] = htype
 
 for k, v in args.iteritems():
 if callable(v):
@@ -248,7 +249,7 @@ def runhooks(ui, repo, htype, hooks, thr
 r, raised = _pythonhook(ui, repo, htype, hname, hookfn, args,
 throw)
 else:
-r = _exthook(ui, repo, hname, cmd, args, throw)
+r = _exthook(ui, repo, htype, hname, cmd, args, throw)
 raised = False
 
 res[hname] = r, raised
diff --git a/tests/test-bundle.t b/tests/test-bundle.t
--- a/tests/test-bundle.t
+++ b/tests/test-bundle.t
@@ -232,7 +232,7 @@ hg -R bundle://../full.hg verify
   adding manifests
   adding file changes
   added 9 changesets with 7 changes to 4 files (+1 heads)
-  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
+  changegroup hook: HG_HOOKTYPE=changegroup 
HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 Rollback empty
@@ -255,7 +255,7 @@ Pull full.hg into empty again (using -R;
   adding manifests
   adding file changes
   added 9 changesets with 7 changes to 4 files (+1 heads)
-  changegroup hook: HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
+  changegroup hook: HG_HOOKTYPE=changegroup 
HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 
HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull 
TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
 Cannot produce streaming clone bundles with "hg bundle"
diff --git a/tests/test-bundle2-exchange.t b/tests/test-bundle2-exchange.t
--- a/tests/test-bundle2-exchange.t
+++ b/tests/test-bundle2-exchange.t
@@ -41,7 +41,7 @@ The extension requires a repo (currently
   $ hg commit -m 'a'
   pre-close-tip:3903775176ed draft 
   postclose-tip:3903775176ed draft 
-  txnclose hook: HG_PHASES_MOVED=1 TXNID=TXN:$ID$ HG_TXNNAME=commit
+  txnclose hook: HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 TXNID=TXN:$ID$ 
HG_TXNNAME=commit
 
   $ hg unbundle $TESTDIR/bundles/rebase.hg
   adding changesets
@@ -50,7 +50,7 @@ The extension requires a repo (currently
   added 8 changesets with 7 changes to 7 files (+3 heads)
   pre-close-tip:02de42196ebe draft 
   postclose-tip:02de42196ebe draft 
-  txnclose hook: HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 
HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 
HG_SOURCE=unbundle TXNID=TXN:$ID$ HG_TXNNAME=unbundle
+  txnclose hook: HG_HOOKTYPE=txnclose 

Re: [PATCH 1 of 2 V2] verify: document corner cases

2017-03-31 Thread Ryan McElroy

On 3/30/17 10:51 PM, Jun Wu wrote:

# HG changeset patch
# User Jun Wu 
# Date 1490823901 25200
#  Wed Mar 29 14:45:01 2017 -0700
# Node ID 17b41390f4912a4c18538d778837bc2cf4a1be92
# Parent  dea2a17cbfd00bf08ee87b3e44b1c71499189f89
# Available At 
https://urldefense.proofpoint.com/v2/url?u=https-3A__bitbucket.org_quark-2Dzju_hg-2Ddraft=DwIGaQ=5VD0RTtNlTh3ycd41b3MUw=Jw8rundaE7TbmqBYd1txIQ=kuj9GJXY5gbugZhlyrbxjthYrYkZ6M3HZHYFrfQg_ZY=yj22qlE05uO47PYA0xtQ2kgE_-D5kRIk7mybLrSUZdg=
#  hg pull 
https://urldefense.proofpoint.com/v2/url?u=https-3A__bitbucket.org_quark-2Dzju_hg-2Ddraft=DwIGaQ=5VD0RTtNlTh3ycd41b3MUw=Jw8rundaE7TbmqBYd1txIQ=kuj9GJXY5gbugZhlyrbxjthYrYkZ6M3HZHYFrfQg_ZY=yj22qlE05uO47PYA0xtQ2kgE_-D5kRIk7mybLrSUZdg=
  -r 17b41390f491
verify: document corner cases

It seems a good idea to list all kinds of "surprises" and expected behavior
to make the upcoming changes easier to understand.

Note: the comment added does not reflect the actual behavior of the current
code.

diff --git a/mercurial/verify.py b/mercurial/verify.py
--- a/mercurial/verify.py
+++ b/mercurial/verify.py
@@ -380,5 +380,51 @@ class verifier(object):
  del filenodes[f][n]
  
-# verify contents

+# Verify contents. 4 cases to care about:
+#
+#   common: the most common case
+#   rename: with a rename
+#   meta: file content starts with b'\1\n', the metadata
+# header defined in filelog.py, but without a rename
+#   ext: largefiles. content stored elsewhere
+#
+# More formally, their differences are shown below:
+#
+#   | common | rename | meta  | ext
+#  ---
+#   flags() | 0  | 0  | 0 | not 0
+#   renamed()   | False  | True   | False | ?
+#   rawtext[0:2]=='\1\n'| False  | True   | True  | ?
+#
+# "rawtext" means the raw text stored in revlog data, which
+# could be retrieved by "revision(rev, raw=True)". "text"
+# mentioned below is "revision(rev, raw=False)".
+#
+# There are 3 different lengths stored physically:
+#  1. L1: rawsize, stored in revlog index
+#  2. L2: len(rawtext), stored in revlog data
+#  3. L3: len(text), stored in revlog data if flags==0, or
+# possibly somewhere else if flags!=0
+#
+# L1 should be equal to L2. L3 could be different from them.
+# "text" may or may not affect commit hash depending on flag
+# processors (see revlog.addflagprocessor).
+#
+#  | common  | rename | meta  | ext
+# -
+#rawsize() | L1  | L1 | L1| L1
+#   size() | L1  | L2-LM  | L1(*) | L1 (?)
+# len(rawtext) | L2  | L2 | L2| L2
+#len(text) | L2  | L2 | L2| L3
+#  len(read()) | L2  | L2-LM  | L2-LM | L3 (?)
+#
+# LM:  length of metadata, depending on rawtext
+# (*): not ideal, see comment in filelog.size
+# (?): could be "- len(meta)" if the resolved content has
+#  rename metadata
+#
+# Checks needed to be done:
+#  1. length check: L1 == L2, in all cases.
+#  2. hash check: depending on flag processor, we may need to
+# use either "text" (external), or "rawtext" (in revlog).
  try:
  l = len(fl.read(n))


This comment is very clear to me now. Well done and thanks!
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


Re: [PATCH 2 of 2 V2] verify: fix length check

2017-03-31 Thread Ryan McElroy

On 3/30/17 10:51 PM, Jun Wu wrote:

# HG changeset patch
# User Jun Wu 
# Date 1490824154 25200
#  Wed Mar 29 14:49:14 2017 -0700
# Node ID 35902a0e3f38c76a66d0dfbf76ec72091832
# Parent  17b41390f4912a4c18538d778837bc2cf4a1be92
verify: fix length check

This series looks good to me. Marked as pre-reviewed in patchwork.



According to the document added above, we should check L1 == L2, and the
only way to get L1 in all cases is to call "rawsize()", and the only way to
get L2 is to call "revision(raw=True)". Therefore the fix.

Meanwhile there are still a lot of things about flagprocessor broken in
revlog.py. Tests will be added after revlog.py gets fixed.

diff --git a/mercurial/verify.py b/mercurial/verify.py
--- a/mercurial/verify.py
+++ b/mercurial/verify.py
@@ -431,5 +431,6 @@ class verifier(object):
  rp = fl.renamed(n)
  if l != fl.size(i):
-if len(fl.revision(n)) != fl.size(i):
+# the "L1 == L2" check
+if len(fl.revision(n, raw=True)) != fl.rawsize(i):
  self.err(lr, _("unpacked size is %s, %s 
expected") %
   (l, fl.size(i)), f)



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


Re: [PATCH] sslutil: clarify internal documentation

2017-03-31 Thread Ryan McElroy

On 3/31/17 2:32 AM, Matt Harbison wrote:

# HG changeset patch
# User Matt Harbison 
# Date 1490795674 14400
#  Wed Mar 29 09:54:34 2017 -0400
# Node ID 9505a8771bb00e56230e4c4b265e8369e659a54f
# Parent  2632df096fc0ac7582382b1f94ea4b9ad0bce8f2
sslutil: clarify internal documentation

I ran into this python issue with an incomplete certificate chain on Windows
recently, and this is the clarification that came from that experimenting.  The
comment I left on the bug tracker [1] with a reference to the CPython code [2]
indicates that the original problem I had is a different bug, but happened to
be mentioned under issue20916 on the Python bug tracker.


This looks like a good clarification to me. Marked at pre-reviewed in 
patchwork.




[1] 
https://urldefense.proofpoint.com/v2/url?u=https-3A__bz.mercurial-2Dscm.org_show-5Fbug.cgi-3Fid-3D5313-23c7=DwIGaQ=5VD0RTtNlTh3ycd41b3MUw=Jw8rundaE7TbmqBYd1txIQ=iK6FTLLdR8XoO7DBC_cybhU5iy0JJFk1_nX69IELeQo=c6IpMyl5Lj5dkIDbpvIOghBgB-v5qZLgtvPOKyS8jkM=
[2] 
https://urldefense.proofpoint.com/v2/url?u=https-3A__hg.python.org_cpython_file_v2.7.12_Modules_-5Fssl.c-23l628=DwIGaQ=5VD0RTtNlTh3ycd41b3MUw=Jw8rundaE7TbmqBYd1txIQ=iK6FTLLdR8XoO7DBC_cybhU5iy0JJFk1_nX69IELeQo=2hYPqWC9CvlufBnn24ngNt9Fd8P8i1fU86saihe0FTM=

diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -414,8 +414,10 @@
  # a hint to the user.
  # Only modern ssl module exposes SSLContext.get_ca_certs() so we can
  # only show this warning if modern ssl is available.
-# The exception handler is here because of
-# 
https://urldefense.proofpoint.com/v2/url?u=https-3A__bugs.python.org_issue20916=DwIGaQ=5VD0RTtNlTh3ycd41b3MUw=Jw8rundaE7TbmqBYd1txIQ=iK6FTLLdR8XoO7DBC_cybhU5iy0JJFk1_nX69IELeQo=QNXlhziGIzRjCA4SsOAJ6TJ9-sd6Xx7T9772Y01YpJo=
 .
+# The exception handler is here to handle bugs around cert attributes:
+# 
https://urldefense.proofpoint.com/v2/url?u=https-3A__bugs.python.org_issue20916-23msg213479=DwIGaQ=5VD0RTtNlTh3ycd41b3MUw=Jw8rundaE7TbmqBYd1txIQ=iK6FTLLdR8XoO7DBC_cybhU5iy0JJFk1_nX69IELeQo=4e_4aFyB-W1agNiXm6RNvSOlp0Hex2GjWOzbfPXXYws=
 .  (See issues5313.)
+# When the main 20916 bug occurs, 'sslcontext.get_ca_certs()' is a
+# non-empty list, but the following conditional is otherwise True.
  try:
  if (caloaded and settings['verifymode'] == ssl.CERT_REQUIRED and
  modernssl and not sslcontext.get_ca_certs()):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2Dscm.org_mailman_listinfo_mercurial-2Ddevel=DwIGaQ=5VD0RTtNlTh3ycd41b3MUw=Jw8rundaE7TbmqBYd1txIQ=iK6FTLLdR8XoO7DBC_cybhU5iy0JJFk1_nX69IELeQo=HSqjsFw1fqi9rRnK3Pbh9Jln4nbdzkFVaL9jngxBu3A=


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


Re: [PATCH 9 of 9 V2] revlog: add a fast path for revision(raw=False)

2017-03-31 Thread Ryan McElroy

On 3/31/17 5:45 AM, Jun Wu wrote:

# HG changeset patch
# User Jun Wu 
# Date 1490934075 25200
#  Thu Mar 30 21:21:15 2017 -0700
# Node ID 70c6b2eecf4d580d38404f157ef99da237593a68
# Parent  3a4dd24ccf078c47722582f00872a88d33042ac3
revlog: add a fast path for revision(raw=False)


Wow! This series is enormously more clear than it's precursor. The way 
you refactored the test is superb and clearly shows the progression of 
the fixes. This is fantastic!


I have reviewed the patches and they all look good to me. These are 
important fixes and they are now clearly presented.


*slowclap*

(Marking as pre-reviewed in patchwork)



If cache hit and flags are empty, no flag processor runs and "text" equals
to "rawtext". So we check flags, and return rawtext.

This resolves performance issue introduced by a previous patch.

diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -1275,4 +1275,11 @@ class revlog(object):
  if raw:
  return self._cache[2]
+# duplicated, but good for perf
+if rev is None:
+rev = self.rev(node)
+# no extra flags set, no flag processor runs, text = rawtext
+if self.flags(rev) == REVIDX_DEFAULT_FLAGS:
+return self._cache[2]
+
  cachedrev = self._cache[1]
  


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


[PATCH] hgweb: prefix line id by ctx shortnode in filelog when patches are shown

2017-03-31 Thread Denis Laxalde
# HG changeset patch
# User Denis Laxalde 
# Date 1490902810 -7200
#  Thu Mar 30 21:40:10 2017 +0200
# Node ID 7ae1cc7ae6c50a037525f27e203a2ce75fc3004f
# Parent  dea2a17cbfd00bf08ee87b3e44b1c71499189f89
# Available At http://hg.logilab.org/users/dlaxalde/hg
#  hg pull http://hg.logilab.org/users/dlaxalde/hg -r 7ae1cc7ae6c5
hgweb: prefix line id by ctx shortnode in filelog when patches are shown

When "patch" query parameter is present in requests to filelog view, line ids
in patches diff are no longer unique in the page since several patches are
shown on the same page. We now prefix line id by changeset shortnode when
several patches are displayed in the same page to have unique line ids
overall.

diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py
+++ b/mercurial/hgweb/webcommands.py
@@ -998,7 +998,8 @@ def filelog(web, req, tmpl):
 basectx = ctx.p1()
 path = fctx.path()
 return webutil.diffs(web, tmpl, ctx, basectx, [path], diffstyle,
- linerange=linerange)
+ linerange=linerange,
+ lineidprefix='%s-' % ctx.hex()[:12])
 
 linerange = None
 if lrange is not None:
diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -434,7 +434,8 @@ def listfilediffs(tmpl, files, node, max
 if len(files) > max:
 yield tmpl('fileellipses')
 
-def diffs(web, tmpl, ctx, basectx, files, style, linerange=None):
+def diffs(web, tmpl, ctx, basectx, files, style, linerange=None,
+  lineidprefix=''):
 
 def prettyprintlines(lines, blockno):
 for lineno, l in enumerate(lines, 1):
@@ -450,7 +451,7 @@ def diffs(web, tmpl, ctx, basectx, files
 yield tmpl(ltype,
line=l,
lineno=lineno,
-   lineid="l%s" % difflineno,
+   lineid=lineidprefix + "l%s" % difflineno,
linenumber="% 8s" % difflineno)
 
 repo = web.repo
diff --git a/tests/test-hgweb-filelog.t b/tests/test-hgweb-filelog.t
--- a/tests/test-hgweb-filelog.t
+++ b/tests/test-hgweb-filelog.t
@@ -1124,10 +1124,10 @@ filelog with patch
 


-  --- /dev/null  Thu Jan 01 00:00:00 
1970 +
-  +++ b/a Thu Jan 01 00:00:00 1970 
+
-  @@ -0,0 +1,1 @@
-  +b
+  --- /dev/null Thu Jan 01 
00:00:00 1970 +
+  +++ b/aThu Jan 01 
00:00:00 1970 +
+  @@ -0,0 +1,1 @@
+  +b

 Thu, 01 Jan 1970 00:00:00 +
 test
@@ -1137,10 +1137,10 @@ filelog with patch
 


-  --- /dev/null  Thu Jan 01 00:00:00 
1970 +
-  +++ b/a Thu Jan 01 00:00:00 1970 
+
-  @@ -0,0 +1,1 @@
-  +a
+  --- /dev/null Thu Jan 01 
00:00:00 1970 +
+  +++ b/aThu Jan 01 
00:00:00 1970 +
+  @@ -0,0 +1,1 @@
+  +a
   
   
   
@@ -1404,16 +1404,16 @@ filelog with 'linerange' and 'patch'
 


-  --- a/cThu Jan 01 00:00:00 1970 
+
-  +++ b/c Thu Jan 01 00:00:00 1970 
+
-  @@ -1,6 +1,6 @@
-   0
-   0
-  -b
-  +b-
-   c++
-   
-   a
+  --- a/c   Thu Jan 01 
00:00:00 1970 +
+  +++ b/cThu Jan 01 
00:00:00 1970 +
+  @@ -1,6 +1,6 @@
+   0
+   0
+  -b
+  +b-
+   c++
+   
+   a

 Thu, 01 Jan 1970 00:00:00 +
 test
@@ -1423,17 +1423,17 @@ filelog with 'linerange' and 'patch'
 


-  --- a/cThu Jan 01 00:00:00 1970 
+
-  +++ b/c Thu Jan 01 00:00:00 1970 
+
-  @@ -1,7 +1,7 @@
-   0
-   0
-   b
-  -c+
-  +c++
-   
-   a
-   a
+  --- a/c   Thu Jan 01 
00:00:00 1970 +
+  +++ b/cThu Jan 01 
00:00:00 1970 +
+  @@ -1,7 +1,7 @@
+   0
+   0
+   b
+  -c+
+  +c++
+   
+   a
+   a

 Thu, 01 Jan 1970 00:00:00 +
 test
@@ -1443,21 +1443,21 @@ filelog with 'linerange' and 'patch'
 


-  --- a/cThu Jan 01 00:00:00 1970 
+
-  +++ b/c Thu Jan 01 00:00:00 1970 
+
-  @@ -1,2 +1,11 @@
-  +0
-  +0
-   b
-  -c
-  +c+
-  +
-  +a
-  +a
-  +
-  +d
-  +e
-  +f
+  --- a/c   Thu Jan 01 
00:00:00 1970 +
+  +++ b/cThu Jan 01 
00:00:00 1970 +
+  @@ -1,2 +1,11 @@
+  +0
+  +0
+   b
+  -c
+  +c+
+  +
+  +a
+  +a
+  +
+  +d
+  +e
+  +f

 Thu, 01 Jan 1970 00:00:00 +
 test
@@ -1467,11 +1467,11 @@ filelog with 'linerange' and 'patch'
 


-  --- a/cThu Jan 01 00:00:00 1970 
+
-  +++ b/c Thu Jan 01 00:00:00 1970 
+
-  @@ -1,1 +1,2 @@
-   b
-  +c
+  --- a/c   Thu Jan 01 
00:00:00 1970 +
+  +++ b/cThu Jan 01 
00:00:00 1970 +
+  @@ -1,1 +1,2 @@
+   b
+  +c

 Thu, 01 Jan 1970 00:00:00 +
 test
@@ -1481,8 +1481,8 @@ filelog with 'linerange' and 'patch'
 


-  --- /dev/null  Thu Jan 01 00:00:00 
1970 +
-  +++ b/b Thu Jan 01 00:00:00 1970 
+
+  --- /dev/null Thu Jan 01 
00:00:00 1970