Re: [PATCH V7] hgweb: expose a followlines UI in filerevision view
On Fri, Mar 31, 2017 at 4:47 AM, Denis Laxaldewrote: > # 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)
[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
# 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
# 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
# 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'
# 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
# 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'
# 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
# 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
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)
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
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
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
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
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
# 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()
# 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)
# 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
# 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)
# 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()
# 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)
# 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
# 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
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()
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))
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
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
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
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
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`
On Thu, 30 Mar 2017 21:21:27 -0400, Matt Harbison wrote: > On Tue, 28 Mar 2017 10:02:34 -0400, Yuya Nishiharawrote: > > > 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
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 BalytskyiCc: 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
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
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
# 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
# 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'
# 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
# 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'
# 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
# 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
# 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
# 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
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
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
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)
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
# 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