D3852: namespaces: let namespaces override singlenode() definition
martinvonz updated this revision to Diff 9333. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3852?vs=9331&id=9333 REVISION DETAIL https://phab.mercurial-scm.org/D3852 AFFECTED FILES mercurial/namespaces.py CHANGE DETAILS diff --git a/mercurial/namespaces.py b/mercurial/namespaces.py --- a/mercurial/namespaces.py +++ b/mercurial/namespaces.py @@ -95,21 +95,16 @@ def singlenode(self, repo, name): """ -Return the 'best' node for the given name. Best means the first node -in the first nonempty list returned by a name-to-nodes mapping function -in the defined precedence order. +Return the 'best' node for the given name. What's best is defined +by the namespace's singlenode() function. The first match returned by +a namespace in the defined precedence order is used. Raises a KeyError if there is no such node. """ for ns, v in self._names.iteritems(): -n = v.namemap(repo, name) +n = v.singlenode(repo, name) if n: -# return max revision number -if len(n) > 1: -cl = repo.changelog -maxrev = max(cl.rev(node) for node in n) -return cl.node(maxrev) -return n[0] +return n raise KeyError(_('no such name: %s') % name) class namespace(object): @@ -142,7 +137,7 @@ def __init__(self, name, templatename=None, logname=None, colorname=None, logfmt=None, listnames=None, namemap=None, nodemap=None, - deprecated=None, builtin=False): + deprecated=None, builtin=False, singlenode=None): """create a namespace name: the namespace to be registered (in plural form) @@ -158,6 +153,7 @@ nodemap: function that inputs a node, output name(s) deprecated: set of names to be masked for ordinary use builtin: whether namespace is implemented by core Mercurial +singlenode: function that inputs a name, output best node (or None) """ self.name = name self.templatename = templatename @@ -167,6 +163,18 @@ self.listnames = listnames self.namemap = namemap self.nodemap = nodemap +if not singlenode: +def singlenode(repo, name): +n = self.namemap(repo, name) +if n: +# return max revision number +if len(n) > 1: +cl = repo.changelog +maxrev = max(cl.rev(node) for node in n) +return cl.node(maxrev) +return n[0] +return None +self.singlenode = singlenode # if logname is not specified, use the template name as backup if self.logname is None: To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3851: tests: pass "rev" argument to commands.update() as string
martinvonz updated this revision to Diff 9332. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3851?vs=9330&id=9332 REVISION DETAIL https://phab.mercurial-scm.org/D3851 AFFECTED FILES tests/test-basic.t CHANGE DETAILS diff --git a/tests/test-basic.t b/tests/test-basic.t --- a/tests/test-basic.t +++ b/tests/test-basic.t @@ -64,7 +64,7 @@ > from mercurial import ui, hg, commands > myui = ui.ui.load() > repo = hg.repository(myui, path=b'.') - > commands.update(myui, repo, rev=0) + > commands.update(myui, repo, rev="0") > EOF $ hg up null 0 files updated, 0 files merged, 1 files removed, 0 files unresolved To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3852: namespaces: let namespaces override singlenode() definition
martinvonz created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY Some namespaces have multiple nodes per name (meaning that their namemap() returns multiple nodes). One such namespace is the "topics" namespace (from the evolve repo). We also have our own internal namespace at Google (for review units) that has multiple nodes per name. These namespaces may not want to use the default "pick highest revnum" resolution that we currently use when resolving a name to a single node. As an example, they may decide that `hg co ` should check out a commit that's last in some sense even if an earlier commit had just been amended and thus had a higher revnum [1]. This patch gives the namespace the option to continue to return multiple nodes and to override how the best node is picked. Allowing namespaces to override that may also be useful as an optimization (it may be cheaper for the namespace to find just that node). I have been arguing (in https://phab.mercurial-scm.org/D3715) for using all the nodes returned from namemap() when resolving the symbol to a revset, so e.g. `hg log -r stable` would resolve to *all* nodes on stable, not just the one with the highest revnum (except that I don't actually think we should change it for the branch namespace because of BC). Most people seem opposed to that. If we decide not to do it, I think we can deprecate the namemap() function in favor of the new singlenode() (I find it weird to have namespaces, like the branch namespace, where namemap() isn't nodemap()'s inverse). I therefore think this patch makes sense regardless of what we decide on that issue. [1] Actually, even the branch namespace would have wanted to override singlenode() if it had supported multiple nodes. That's because closes branch heads are mostly ignored, so "hg co default" will not check out the highest-revnum node if that's a closed head. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3852 AFFECTED FILES mercurial/namespaces.py CHANGE DETAILS diff --git a/mercurial/namespaces.py b/mercurial/namespaces.py --- a/mercurial/namespaces.py +++ b/mercurial/namespaces.py @@ -95,21 +95,16 @@ def singlenode(self, repo, name): """ -Return the 'best' node for the given name. Best means the first node -in the first nonempty list returned by a name-to-nodes mapping function -in the defined precedence order. +Return the 'best' node for the given name. What's best is defined +by the namespace's singlenode() function. The first match returned by +a namespace in the defined precedence order is used. Raises a KeyError if there is no such node. """ for ns, v in self._names.iteritems(): -n = v.namemap(repo, name) +n = v.singlenode(repo, name) if n: -# return max revision number -if len(n) > 1: -cl = repo.changelog -maxrev = max(cl.rev(node) for node in n) -return cl.node(maxrev) -return n[0] +return n raise KeyError(_('no such name: %s') % name) class namespace(object): @@ -142,7 +137,7 @@ def __init__(self, name, templatename=None, logname=None, colorname=None, logfmt=None, listnames=None, namemap=None, nodemap=None, - deprecated=None, builtin=False): + deprecated=None, builtin=False, singlenode=None): """create a namespace name: the namespace to be registered (in plural form) @@ -158,6 +153,7 @@ nodemap: function that inputs a node, output name(s) deprecated: set of names to be masked for ordinary use builtin: whether namespace is implemented by core Mercurial +singlenode: function that inputs a name, output best node (or None) """ self.name = name self.templatename = templatename @@ -167,6 +163,18 @@ self.listnames = listnames self.namemap = namemap self.nodemap = nodemap +if not singlenode: +def singlenode(repo, name): +n = self.namemap(repo, name) +if n: +# return max revision number +if len(n) > 1: +cl = repo.changelog +maxrev = max(cl.rev(node) for node in n) +return cl.node(maxrev) +return n[0] +return None +self.singlenode = singlenode # if logname is not specified, use the template name as backup if self.logname is None: To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.me
D3851: tests: pass "rev" argument to commands.update() as string
martinvonz created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY commands.update() normally gets its "rev" argument as a string, but test-basic.t was passing an integer. That happened to work, but we shouldn't rely on it. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3851 AFFECTED FILES tests/test-basic.t CHANGE DETAILS diff --git a/tests/test-basic.t b/tests/test-basic.t --- a/tests/test-basic.t +++ b/tests/test-basic.t @@ -64,7 +64,7 @@ > from mercurial import ui, hg, commands > myui = ui.ui.load() > repo = hg.repository(myui, path=b'.') - > commands.update(myui, repo, rev=0) + > commands.update(myui, repo, rev="0") > EOF $ hg up null 0 files updated, 0 files merged, 1 files removed, 0 files unresolved To: martinvonz, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH STABLE v2] hghave: don't claim we have `tic` if it's NetBSD's binary (issue5698)
also looks good On Wed, Jun 27, 2018 at 8:50 AM, Augie Fackler wrote: > # HG changeset patch > # User Augie Fackler > # Date 1529932907 14400 > # Mon Jun 25 09:21:47 2018 -0400 > # Branch stable > # Node ID af7d21e1e44c1bb756af28b5978d3f7ee7d50eda > # Parent 0b63a6743010dfdbf8a8154186e119949bdaa1cc > hghave: don't claim we have `tic` if it's NetBSD's binary (issue5698) > > test-status-color.t fails with different output because of mismatches > between how `tic` behaves from NetBSD's base system and ncurses' > verison (if I understand the bug right). The bug suggested using -V to > avoid the issue, so we'll do that. > > diff --git a/tests/hghave.py b/tests/hghave.py > --- a/tests/hghave.py > +++ b/tests/hghave.py > @@ -545,7 +545,11 @@ def has_tic(): > try: > import curses > curses.COLOR_BLUE > -return matchoutput('test -x "`which tic`"', br'') > +if not matchoutput('test -x "`which tic`"', br''): > +return False > +# We have a tic, but make sure it's not the NetBSD system one > +# which doesn't pass test-status-color.t. > +return not matchoutput('tic -V 2>&1', br'unknown option') > except ImportError: > return False > > ___ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel > ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 2 of 2] revlog: do inclusive descendant testing (API)
On Mon, Jun 25, 2018 at 9:54 AM Paul Morelle wrote: > On 21/06/18 18:30, Martin von Zweigbergk wrote: > > On Thu, Jun 21, 2018 at 7:24 AM Paul Morelle > wrote: > >> # HG changeset patch >> # User Boris Feld >> # Date 1529585081 -3600 >> # Thu Jun 21 13:44:41 2018 +0100 >> # Node ID 59fea52e54e014722486f7c049e192fa505032d8 >> # Parent 8d20b1b4b6a0297e7f9640d285b15a5d6647369e >> # EXP-Topic descendant >> # Available At https://bitbucket.org/octobus/mercurial-devel/ >> # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r >> 59fea52e54e0 >> revlog: do inclusive descendant testing (API) >> >> In many other places, a revision is considered a descendant of itself. >> We update the behavior of `revlog.descendant()` to match this. >> >> No test breaks, so it seems safe to do so. >> >> diff -r 8d20b1b4b6a0 -r 59fea52e54e0 mercurial/revlog.py >> --- a/mercurial/revlog.py Thu Jun 21 13:32:07 2018 +0100 >> +++ b/mercurial/revlog.py Thu Jun 21 13:44:41 2018 +0100 >> @@ -1378,7 +1378,7 @@ >> def descendant(self, start, end): >> if start == nullrev: >> return True >> -return start in self.ancestors([end]) >> +return start in self.ancestors([end], inclusive=True) >> > > Is this now equivalent to self.isancestor(start, end)? That method relies > on commonancestorsheads instead of lazyancestors. What are the performance > trade-offs? Equivalent both when there are many ancestors and when there > are many descendants? > > Hello Martin, > > Interestingly, it turns out that we have the following flock of functions: > >- ancestors: commonancestorsheads(parent_func, *revs) > - uses revnum > - any number of arguments > - written in Python >- cext/revlog.c: revlog.index.commonancestorsheads(*revs) > - uses revnum > - any number of arguments > - written in C >- revlog: revlog.commonancestorsheads(node-a, node-b) > - uses nodes > - takes exactly two nodes > - Calls either self.index.c…a…heads or ancestors.c…a…heads >- revlog: revlog.isancestor(anc, desc) > - uses nodes > - calls revlog.commonancestorsheads >- revlog: revlog.descendant(rev-a, rev-b) > - uses revs > - has it own very slow code >- revlog: revlog.descendant(rev-a, rev-b) > - uses revs > - has it own very slow code > - non-inclusive >- context: context.descendant(other) > - uses contexts > - calls revlog.descendant > - non-inclusive > > At the algorithm level, `anc in ancestors(desc)` will be faster when anc > is not an ancestor of desc (or they are many gca), since it will finish > sooner. However given `commonancestorheads` benefits from a C > implementation, it is currently the fastest option. > > In short terms, I think the following actions would make sense: > >1. Extract a lower level `revlog._commonancestorheads(*revs)` from >`revlog.commonancestorsheads` > > What would the new function do? commonancestorsheads is already pretty short. Do you mean to just make it work on revnums instead of nodeids? Or do you mean for making it optionally inclusive? > >1. Use it in `revlog.descendant` >2. Make `revlog.isancestor` use `revlog.descendant` > > Why is that better than making descendant call isancestor? Does this seems sensible to you? > > -- > Paul Morelle > ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH STABLE v2] hghave: don't claim we have `tic` if it's NetBSD's binary (issue5698)
# HG changeset patch # User Augie Fackler # Date 1529932907 14400 # Mon Jun 25 09:21:47 2018 -0400 # Branch stable # Node ID af7d21e1e44c1bb756af28b5978d3f7ee7d50eda # Parent 0b63a6743010dfdbf8a8154186e119949bdaa1cc hghave: don't claim we have `tic` if it's NetBSD's binary (issue5698) test-status-color.t fails with different output because of mismatches between how `tic` behaves from NetBSD's base system and ncurses' verison (if I understand the bug right). The bug suggested using -V to avoid the issue, so we'll do that. diff --git a/tests/hghave.py b/tests/hghave.py --- a/tests/hghave.py +++ b/tests/hghave.py @@ -545,7 +545,11 @@ def has_tic(): try: import curses curses.COLOR_BLUE -return matchoutput('test -x "`which tic`"', br'') +if not matchoutput('test -x "`which tic`"', br''): +return False +# We have a tic, but make sure it's not the NetBSD system one +# which doesn't pass test-status-color.t. +return not matchoutput('tic -V 2>&1', br'unknown option') except ImportError: return False ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3716: ui: add an uninterruptable context manager that can block SIGINT
durin42 added a comment. I'm not in love with uninterruptible as a name (I think unsafeoperation is more explicit) but I don't feel strongly. The rest of the suggestions I liked, so the series is updated and ready for another look. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3716 To: durin42, #hg-reviewers, indygreg Cc: spectral, indygreg, yuja, martinvonz, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3716: ui: add an uninterruptable context manager that can block SIGINT
durin42 updated this revision to Diff 9326. durin42 edited the summary of this revision. durin42 retitled this revision from "ui: add an unsafeoperation context manager that can block SIGINT" to "ui: add an uninterruptable context manager that can block SIGINT". REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3716?vs=9033&id=9326 REVISION DETAIL https://phab.mercurial-scm.org/D3716 AFFECTED FILES mercurial/configitems.py mercurial/ui.py mercurial/utils/procutil.py tests/test-nointerrupt.t CHANGE DETAILS diff --git a/tests/test-nointerrupt.t b/tests/test-nointerrupt.t new file mode 100644 --- /dev/null +++ b/tests/test-nointerrupt.t @@ -0,0 +1,83 @@ +Dummy extension simulating unsafe long running command + $ cat > sleepext.py < import time + > import itertools + > + > from mercurial import registrar + > from mercurial.i18n import _ + > + > cmdtable = {} + > command = registrar.command(cmdtable) + > + > @command(b'sleep', [], _(b'TIME'), norepo=True) + > def sleep(ui, sleeptime=b"1", **opts): + > with ui.uninterruptable(): + > for _i in itertools.repeat(None, int(sleeptime)): + > time.sleep(1) + > ui.warn(b"end of unsafe operation\n") + > ui.warn(b"%s second(s) passed\n" % sleeptime) + > EOF + +Kludge to emulate timeout(1) which is not generally available. + $ cat > timeout.py < from __future__ import print_function + > import argparse + > import signal + > import subprocess + > import sys + > import time + > + > ap = argparse.ArgumentParser() + > ap.add_argument('-s', nargs=1, default='SIGTERM') + > ap.add_argument('duration', nargs=1, type=int) + > ap.add_argument('argv', nargs='*') + > opts = ap.parse_args() + > try: + > sig = int(opts.s[0]) + > except ValueError: + > sname = opts.s[0] + > if not sname.startswith('SIG'): + > sname = 'SIG' + sname + > sig = getattr(signal, sname) + > proc = subprocess.Popen(opts.argv) + > time.sleep(opts.duration[0]) + > proc.poll() + > if proc.returncode is None: + > proc.send_signal(sig) + > proc.wait() + > sys.exit(124) + > EOF + +Set up repository + $ hg init repo + $ cd repo + $ cat >> $HGRCPATH << EOF + > [extensions] + > sleepext = ../sleepext.py + > EOF + +Test ctrl-c + $ python $TESTTMP/timeout.py -s INT 1 hg sleep 2 + interrupted! + [124] + + $ cat >> $HGRCPATH << EOF + > [experimental] + > nointerrupt = yes + > EOF + + $ python $TESTTMP/timeout.py -s INT 1 hg sleep 2 + interrupted! + [124] + + $ cat >> $HGRCPATH << EOF + > [experimental] + > nointerrupt-interactiveonly = False + > EOF + + $ python $TESTTMP/timeout.py -s INT 1 hg sleep 2 + shutting down cleanly + press ^C again to terminate immediately (dangerous) + end of unsafe operation + interrupted! + [124] diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py --- a/mercurial/utils/procutil.py +++ b/mercurial/utils/procutil.py @@ -408,3 +408,36 @@ finally: if prevhandler is not None: signal.signal(signal.SIGCHLD, prevhandler) + +@contextlib.contextmanager +def uninterruptable(warn): +"""Inhibit SIGINT handling on a region of code. + +Note that if this is called in a non-main thread, it turns into a no-op. + +Args: + warn: A callable which takes no arguments, and returns True if the +previous signal handling should be restored. +""" + +oldsiginthandler = [signal.getsignal(signal.SIGINT)] +shouldbail = [] + +def disabledsiginthandler(*args): +if warn(): +signal.signal(signal.SIGINT, oldsiginthandler[0]) +del oldsiginthandler[0] +shouldbail.append(True) + +try: +try: +signal.signal(signal.SIGINT, disabledsiginthandler) +except ValueError: +# wrong thread, oh well, we tried +del oldsiginthandler[0] +yield +finally: +if oldsiginthandler: +signal.signal(signal.SIGINT, oldsiginthandler[0]) +if shouldbail: +raise KeyboardInterrupt diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -224,6 +224,7 @@ self._colormode = None self._terminfoparams = {} self._styles = {} +self._uninterruptible = False if src: self.fout = src.fout @@ -334,6 +335,37 @@ self._blockedtimes[key + '_blocked'] += \ (util.timer() - starttime) * 1000 +@contextlib.contextmanager +def uninterruptable(self): +"""Mark an operation as unsafe. + +Most operations on a repository are safe to interrupt, but a +few are risky (for example repair.strip). This context manager +lets you advise Mercurial that something risky is happening so +that control-C etc can be blocked if desired. +""" +enabled = self.configbool('experimental', 'noi
D3719: narrowbundle2: when we handle a widen, mark the operation as unsafe
durin42 updated this revision to Diff 9329. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3719?vs=9026&id=9329 REVISION DETAIL https://phab.mercurial-scm.org/D3719 AFFECTED FILES hgext/narrow/narrowbundle2.py CHANGE DETAILS diff --git a/hgext/narrow/narrowbundle2.py b/hgext/narrow/narrowbundle2.py --- a/hgext/narrow/narrowbundle2.py +++ b/hgext/narrow/narrowbundle2.py @@ -408,6 +408,8 @@ topic='widen') repo._bookmarks = bmstore if chgrpfile: +op._widen_uninterr = repo.ui.uninterruptable() +op._widen_uninterr.__enter__() # presence of _widen_bundle attribute activates widen handler later op._widen_bundle = chgrpfile # Set the new narrowspec if we're widening. The setnewnarrowpats() method @@ -455,6 +457,7 @@ (undovfs.join(undofile), stringutil.forcebytestr(e))) # Remove partial backup only if there were no exceptions +op._widen_uninterr.__exit__(None, None, None) vfs.unlink(chgrpfile) def setup(): To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3717: repair: mark the critical section of strip() as unsafe
durin42 updated this revision to Diff 9327. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3717?vs=9024&id=9327 REVISION DETAIL https://phab.mercurial-scm.org/D3717 AFFECTED FILES mercurial/repair.py CHANGE DETAILS diff --git a/mercurial/repair.py b/mercurial/repair.py --- a/mercurial/repair.py +++ b/mercurial/repair.py @@ -186,76 +186,77 @@ tmpbundlefile = backupbundle(repo, savebases, saveheads, node, 'temp', compress=False, obsolescence=False) -try: -with repo.transaction("strip") as tr: -offset = len(tr.entries) +with ui.uninterruptable(): +try: +with repo.transaction("strip") as tr: +offset = len(tr.entries) -tr.startgroup() -cl.strip(striprev, tr) -stripmanifest(repo, striprev, tr, files) - -for fn in files: -repo.file(fn).strip(striprev, tr) -tr.endgroup() +tr.startgroup() +cl.strip(striprev, tr) +stripmanifest(repo, striprev, tr, files) -for i in xrange(offset, len(tr.entries)): -file, troffset, ignore = tr.entries[i] -with repo.svfs(file, 'a', checkambig=True) as fp: -fp.truncate(troffset) -if troffset == 0: -repo.store.markremoved(file) +for fn in files: +repo.file(fn).strip(striprev, tr) +tr.endgroup() -deleteobsmarkers(repo.obsstore, stripobsidx) -del repo.obsstore -repo.invalidatevolatilesets() -repo._phasecache.filterunknown(repo) +for i in xrange(offset, len(tr.entries)): +file, troffset, ignore = tr.entries[i] +with repo.svfs(file, 'a', checkambig=True) as fp: +fp.truncate(troffset) +if troffset == 0: +repo.store.markremoved(file) + +deleteobsmarkers(repo.obsstore, stripobsidx) +del repo.obsstore +repo.invalidatevolatilesets() +repo._phasecache.filterunknown(repo) -if tmpbundlefile: -ui.note(_("adding branch\n")) -f = vfs.open(tmpbundlefile, "rb") -gen = exchange.readbundle(ui, f, tmpbundlefile, vfs) -if not repo.ui.verbose: -# silence internal shuffling chatter -repo.ui.pushbuffer() -tmpbundleurl = 'bundle:' + vfs.join(tmpbundlefile) -txnname = 'strip' -if not isinstance(gen, bundle2.unbundle20): -txnname = "strip\n%s" % util.hidepassword(tmpbundleurl) -with repo.transaction(txnname) as tr: -bundle2.applybundle(repo, gen, tr, source='strip', -url=tmpbundleurl) -if not repo.ui.verbose: -repo.ui.popbuffer() -f.close() +if tmpbundlefile: +ui.note(_("adding branch\n")) +f = vfs.open(tmpbundlefile, "rb") +gen = exchange.readbundle(ui, f, tmpbundlefile, vfs) +if not repo.ui.verbose: +# silence internal shuffling chatter +repo.ui.pushbuffer() +tmpbundleurl = 'bundle:' + vfs.join(tmpbundlefile) +txnname = 'strip' +if not isinstance(gen, bundle2.unbundle20): +txnname = "strip\n%s" % util.hidepassword(tmpbundleurl) +with repo.transaction(txnname) as tr: +bundle2.applybundle(repo, gen, tr, source='strip', +url=tmpbundleurl) +if not repo.ui.verbose: +repo.ui.popbuffer() +f.close() -with repo.transaction('repair') as tr: -bmchanges = [(m, repo[newbmtarget].node()) for m in updatebm] -bm.applychanges(repo, tr, bmchanges) +with repo.transaction('repair') as tr: +bmchanges = [(m, repo[newbmtarget].node()) for m in updatebm] +bm.applychanges(repo, tr, bmchanges) -# remove undo files -for undovfs, undofile in repo.undofiles(): -try: -undovfs.unlink(undofile) -except OSError as e: -if e.errno != errno.ENOENT: -ui.warn(_('error removing %s: %s\n') % -(undovfs.join(undofile), - stringutil.forcebytestr(e))) +# remove undo files +for undovfs, undofile in repo.undofiles(): +try: +undovfs.unlink(undofile) +except OSError as e: +if e.errno != errno.ENOENT: +u
D3718: narrow: mark the critical chunks of narrowing/widening as unsafe
durin42 updated this revision to Diff 9328. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3718?vs=9025&id=9328 REVISION DETAIL https://phab.mercurial-scm.org/D3718 AFFECTED FILES hgext/narrow/narrowcommands.py CHANGE DETAILS diff --git a/hgext/narrow/narrowcommands.py b/hgext/narrow/narrowcommands.py --- a/hgext/narrow/narrowcommands.py +++ b/hgext/narrow/narrowcommands.py @@ -203,50 +203,51 @@ hint=_('use --force-delete-local-changes to ' 'ignore')) -if revstostrip: -tostrip = [unfi.changelog.node(r) for r in revstostrip] -if repo['.'].node() in tostrip: -# stripping working copy, so move to a different commit first -urev = max(repo.revs('(::%n) - %ln + null', - repo['.'].node(), visibletostrip)) -hg.clean(repo, urev) -repair.strip(ui, unfi, tostrip, topic='narrow') +with ui.uninterruptable(): +if revstostrip: +tostrip = [unfi.changelog.node(r) for r in revstostrip] +if repo['.'].node() in tostrip: +# stripping working copy, so move to a different commit first +urev = max(repo.revs('(::%n) - %ln + null', + repo['.'].node(), visibletostrip)) +hg.clean(repo, urev) +repair.strip(ui, unfi, tostrip, topic='narrow') -todelete = [] -for f, f2, size in repo.store.datafiles(): -if f.startswith('data/'): -file = f[5:-2] -if not newmatch(file): -todelete.append(f) -elif f.startswith('meta/'): -dir = f[5:-13] -dirs = ['.'] + sorted(util.dirs({dir})) + [dir] -include = True -for d in dirs: -visit = newmatch.visitdir(d) -if not visit: -include = False -break -if visit == 'all': -break -if not include: -todelete.append(f) +todelete = [] +for f, f2, size in repo.store.datafiles(): +if f.startswith('data/'): +file = f[5:-2] +if not newmatch(file): +todelete.append(f) +elif f.startswith('meta/'): +dir = f[5:-13] +dirs = ['.'] + sorted(util.dirs({dir})) + [dir] +include = True +for d in dirs: +visit = newmatch.visitdir(d) +if not visit: +include = False +break +if visit == 'all': +break +if not include: +todelete.append(f) -repo.destroying() +repo.destroying() -with repo.transaction("narrowing"): -for f in todelete: -ui.status(_('deleting %s\n') % f) -util.unlinkpath(repo.svfs.join(f)) -repo.store.markremoved(f) +with repo.transaction("narrowing"): +for f in todelete: +ui.status(_('deleting %s\n') % f) +util.unlinkpath(repo.svfs.join(f)) +repo.store.markremoved(f) -for f in repo.dirstate: -if not newmatch(f): -repo.dirstate.drop(f) -repo.wvfs.unlinkpath(f) -repo.setnarrowpats(newincludes, newexcludes) +for f in repo.dirstate: +if not newmatch(f): +repo.dirstate.drop(f) +repo.wvfs.unlinkpath(f) +repo.setnarrowpats(newincludes, newexcludes) -repo.destroyed() +repo.destroyed() def _widen(ui, repo, remote, commoninc, newincludes, newexcludes): newmatch = narrowspec.match(repo.root, newincludes, newexcludes) @@ -269,28 +270,29 @@ repo.setnarrowpats(newincludes, newexcludes) repo.setnewnarrowpats = setnewnarrowpats -ds = repo.dirstate -p1, p2 = ds.p1(), ds.p2() -with ds.parentchange(): -ds.setparents(node.nullid, node.nullid) -common = commoninc[0] -with wrappedextraprepare: -exchange.pull(repo, remote, heads=common) -with ds.parentchange(): -ds.setparents(p1, p2) +with ui.uninterruptable(): +ds = repo.dirstate +p1, p2 = ds.p1(), ds.p2() +with ds.parentchange(): +ds.setparents(node.nullid, node.nullid) +common = commoninc[0] +with wrappedextraprepare: +exchange.pull(repo, remote, heads=common) +with ds.parentchange(): +ds.setparents(p1, p2) -actions = {k: [] for k in 'a am f g cd dc r dm dg m e k p pr'.split()} -addgaction = actions['g'].append +actions = {k: [] for k in 'a am f g cd dc r dm dg m e k p pr'.split()} +addgaction = actions['g'].append -mf
Re: [PATCH 2 of 2] revset: fix heads() order to always follow the input set (BC)
On Wed, Jun 27, 2018 at 7:53 AM Yuya Nishihara wrote: > # HG changeset patch > # User Yuya Nishihara > # Date 1530110381 -32400 > # Wed Jun 27 23:39:41 2018 +0900 > # Node ID 542ca250795430ee77aeb5e5558f36f60dab3ca1 > # Parent 5aee640e2a99a305dc6f5219c35d2140180169a1 > revset: fix heads() order to always follow the input set (BC) > Queuing this, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
mercurial@38476: 15 new changesets
15 new changesets in mercurial: https://www.mercurial-scm.org/repo/hg/rev/61e4cf1be5b2 changeset: 38462:61e4cf1be5b2 user:Boris Feld date:Mon May 28 18:15:21 2018 +0200 summary: shelve: directly handle the abort process https://www.mercurial-scm.org/repo/hg/rev/f4776f8b98e0 changeset: 38463:f4776f8b98e0 user:Boris Feld date:Tue May 29 00:13:48 2018 +0200 summary: shelve: directly handle `--continue` https://www.mercurial-scm.org/repo/hg/rev/920f69c0b549 changeset: 38464:920f69c0b549 user:Boris Feld date:Tue May 29 00:12:35 2018 +0200 summary: shelve: actually test corrupted shelve state https://www.mercurial-scm.org/repo/hg/rev/a8f99334ae31 changeset: 38465:a8f99334ae31 user:Boris Feld date:Tue May 29 00:15:44 2018 +0200 summary: shelve: stop testing missing rebase state file https://www.mercurial-scm.org/repo/hg/rev/2c2e82469b89 changeset: 38466:2c2e82469b89 user:Yuya Nishihara date:Sat Jun 23 19:23:53 2018 +0900 summary: convert: don't pass --no-files to "darcs show repo" command https://www.mercurial-scm.org/repo/hg/rev/09b09fe7ee90 changeset: 38467:09b09fe7ee90 user:Martin von Zweigbergk date:Mon Jun 25 11:01:11 2018 -0700 summary: terse: add tests of running from subdirectory https://www.mercurial-scm.org/repo/hg/rev/854c2ccc800e changeset: 38468:854c2ccc800e user:Martin von Zweigbergk date:Mon Jun 25 11:04:17 2018 -0700 summary: terse: pass "clean" and "unknown" booleans by name for clarity https://www.mercurial-scm.org/repo/hg/rev/9ef9884e5d50 changeset: 38469:9ef9884e5d50 user:Pulkit Goyal <7895pul...@gmail.com> date:Tue Jun 26 00:37:02 2018 +0530 summary: py3: make tests/test-diff-antipatience.t work with python 3 https://www.mercurial-scm.org/repo/hg/rev/4c358bdaada8 changeset: 38470:4c358bdaada8 user:Pulkit Goyal <7895pul...@gmail.com> date:Tue Jun 26 01:08:47 2018 +0530 summary: py3: add b'' prefixes in tests/test-bundle2-pushback.t https://www.mercurial-scm.org/repo/hg/rev/91228d9ae7c8 changeset: 38471:91228d9ae7c8 user:Pulkit Goyal <7895pul...@gmail.com> date:Tue Jun 26 02:04:17 2018 +0530 summary: patchbomb: use email.mime.multipart instead of email.MIMEMultipart https://www.mercurial-scm.org/repo/hg/rev/d17d1ee1d602 changeset: 38472:d17d1ee1d602 user:Pulkit Goyal <7895pul...@gmail.com> date:Tue Jun 26 02:05:11 2018 +0530 summary: patchbomb: use email.mime.base instead of email.MIMEBase https://www.mercurial-scm.org/repo/hg/rev/622f79e3a1cb changeset: 38473:622f79e3a1cb user:Sushil khanchi date:Tue Jun 26 16:14:02 2018 +0530 summary: graft: add no-commit mode (issue5631) https://www.mercurial-scm.org/repo/hg/rev/96f65bdf0bf4 changeset: 38474:96f65bdf0bf4 user:Augie Fackler date:Tue Jun 26 10:33:52 2018 -0400 summary: stringutil: add a new function to do minimal regex escaping https://www.mercurial-scm.org/repo/hg/rev/67dc32d4e790 changeset: 38475:67dc32d4e790 user:Augie Fackler date:Tue Jun 26 10:36:23 2018 -0400 summary: cleanup: migrate from re.escape to stringutil.reescape https://www.mercurial-scm.org/repo/hg/rev/b4cfd803b3f2 changeset: 38476:b4cfd803b3f2 bookmark:@ tag: tip user:Augie Fackler date:Tue Jun 26 11:38:58 2018 -0400 summary: tests: fix up some lax escaping in test-template-basic.t -- Repository URL: https://www.mercurial-scm.org/repo/hg ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 2] revset: fix heads() order to always follow the input set (BC)
# HG changeset patch # User Yuya Nishihara # Date 1530110381 -32400 # Wed Jun 27 23:39:41 2018 +0900 # Node ID 542ca250795430ee77aeb5e5558f36f60dab3ca1 # Parent 5aee640e2a99a305dc6f5219c35d2140180169a1 revset: fix heads() order to always follow the input set (BC) An argument expression should never affect the order of the result set. That's the rule of the revset predicates. diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -1129,11 +1129,14 @@ def head(repo, subset, x): hs.update(cl.rev(h) for h in ls) return subset & baseset(hs) -@predicate('heads(set)', safe=True) -def heads(repo, subset, x): +@predicate('heads(set)', safe=True, takeorder=True) +def heads(repo, subset, x, order): """Members of set with no children in set. """ -s = getset(repo, subset, x) +# argument set should never define order +if order == defineorder: +order = followorder +s = getset(repo, subset, x, order=order) ps = parents(repo, subset, x) return s - ps diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -1376,20 +1376,20 @@ Test heads , set([0, 1, 2, 3, 4, 5, 6, 8])>>> 9 - BROKEN: but should follow the order of the subset + but should follow the order of the subset $ log 'heads(all())' 7 9 $ log 'heads(tip:0)' + 7 9 - 7 $ log 'tip:0 & heads(all())' 9 7 $ log 'tip:0 & heads(0:tip)' + 9 7 - 9 $ log 'keyword(issue)' 6 ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 2] test-revset: show that order of heads() can be wrong
# HG changeset patch # User Yuya Nishihara # Date 1530110037 -32400 # Wed Jun 27 23:33:57 2018 +0900 # Node ID 5aee640e2a99a305dc6f5219c35d2140180169a1 # Parent b4cfd803b3f2697928be9b3a96787bcee3447c7e test-revset: show that order of heads() can be wrong diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -1357,8 +1357,40 @@ test author 6 7 9 + +Test heads + $ log 'heads(6::)' 7 + + heads() can be computed in subset '9:' + + $ hg debugrevspec -s '9: & heads(all())' + * set: + , + >, +, set([0, 1, 2, 3, 4, 5, 6, 8])>>> + 9 + + BROKEN: but should follow the order of the subset + + $ log 'heads(all())' + 7 + 9 + $ log 'heads(tip:0)' + 9 + 7 + $ log 'tip:0 & heads(all())' + 9 + 7 + $ log 'tip:0 & heads(0:tip)' + 7 + 9 + $ log 'keyword(issue)' 6 $ log 'keyword("test a")' ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
mercurial-devel@mercurial-scm.org
This revision was automatically updated to reflect the committed changes. Closed by commit rHGde275ab362cb: stringutil: update list of re-special characters to include &~ (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3850?vs=9323&id=9325 REVISION DETAIL https://phab.mercurial-scm.org/D3850 AFFECTED FILES mercurial/utils/stringutil.py CHANGE DETAILS diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py --- a/mercurial/utils/stringutil.py +++ b/mercurial/utils/stringutil.py @@ -25,7 +25,7 @@ # regex special chars pulled from https://bugs.python.org/issue29995 # which was part of Python 3.7. -_respecial = pycompat.bytestr(b'()[]{}?*+-|^$\\.# \t\n\r\v\f') +_respecial = pycompat.bytestr(b'()[]{}?*+-|^$\\.&~# \t\n\r\v\f') _regexescapemap = {ord(i): (b'\\' + i).decode('latin1') for i in _respecial} def reescape(pat): To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3849: rebase: refactor dryrun implementation
khanchi97 updated this revision to Diff 9324. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3849?vs=9321&id=9324 REVISION DETAIL https://phab.mercurial-scm.org/D3849 AFFECTED FILES hgext/rebase.py CHANGE DETAILS diff --git a/hgext/rebase.py b/hgext/rebase.py --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -818,19 +818,23 @@ opts[r'dest'] = '_destautoorphanrebase(SRC)' if dryrun: +leaveunfinished = True +inmemory = True +rbsrt = rebaseruntime(repo, ui, inmemory, opts) try: overrides = {('rebase', 'singletransaction'): True} with ui.configoverride(overrides, 'rebase'): -_origrebase(ui, repo, inmemory=True, leaveunfinished=True, -**opts) +_origrebase(ui, repo, inmemory=True, rbsrt=rbsrt, +leaveunfinished=leaveunfinished, **opts) except error.InMemoryMergeConflictsError: ui.status(_('hit a merge conflict\n')) return 1 else: ui.status(_('there will be no conflict, you can rebase\n')) return 0 finally: -_origrebase(ui, repo, abort=True) +with repo.wlock(), repo.lock(): +rbsrt._prepareabortorcontinue(isabort=True) elif inmemory: try: # in-memory merge doesn't support conflicts, so if we hit any, abort @@ -846,9 +850,11 @@ else: return _origrebase(ui, repo, **opts) -def _origrebase(ui, repo, inmemory=False, leaveunfinished=False, **opts): +def _origrebase(ui, repo, inmemory=False, leaveunfinished=False, rbsrt=None, +**opts): opts = pycompat.byteskwargs(opts) -rbsrt = rebaseruntime(repo, ui, inmemory, opts) +if not rbsrt: +rbsrt = rebaseruntime(repo, ui, inmemory, opts) with repo.wlock(), repo.lock(): # Validate input and define rebasing points To: khanchi97, #hg-reviewers Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3841: stringutil: add a new function to do minimal regex escaping
durin42 added a comment. In https://phab.mercurial-scm.org/D3841#60110, @yuja wrote: > > +# regex special chars pulled from https://bugs.python.org/issue29995 > > +# which was part of Python 3.7. > > +_respecial = pycompat.bytestr(b'()[]{}?*+-|^$\\.# \t\n\r\v\f') > > +_regexescapemap = {ord(i): (b'\\' + i).decode('latin1') for i in _respecial} > > The Py3.7 version also includes '&' and '~'. > > https://github.com/python/cpython/blob/v3.7.0rc1/Lib/re.py#L248 Nice catch, mailed https://phab.mercurial-scm.org/D3850 as a follow-up. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3841 To: durin42, #hg-reviewers, pulkit Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
mercurial-devel@mercurial-scm.org
durin42 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY I missed this because I was looking at the change that refactored re.escape, and these characters were added in https://github.com/python/cpython/commit/05cb728d68a278d11466f9a6c8258d914135c96c. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3850 AFFECTED FILES mercurial/utils/stringutil.py CHANGE DETAILS diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py --- a/mercurial/utils/stringutil.py +++ b/mercurial/utils/stringutil.py @@ -25,7 +25,7 @@ # regex special chars pulled from https://bugs.python.org/issue29995 # which was part of Python 3.7. -_respecial = pycompat.bytestr(b'()[]{}?*+-|^$\\.# \t\n\r\v\f') +_respecial = pycompat.bytestr(b'()[]{}?*+-|^$\\.&~# \t\n\r\v\f') _regexescapemap = {ord(i): (b'\\' + i).decode('latin1') for i in _respecial} def reescape(pat): To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
mercurial@38461: 5 new changesets
5 new changesets in mercurial: https://www.mercurial-scm.org/repo/hg/rev/11eda1f1b6e7 changeset: 38457:11eda1f1b6e7 user:Gregory Szorc date:Sat May 12 15:51:37 2018 -0700 summary: packaging: consistently create build user in Dockerfiles https://www.mercurial-scm.org/repo/hg/rev/e5916f1236f3 changeset: 38458:e5916f1236f3 user:Gregory Szorc date:Sat May 12 17:03:47 2018 -0700 summary: packaging: replace dockerlib.sh with a Python script https://www.mercurial-scm.org/repo/hg/rev/c8ef9d897e14 changeset: 38459:c8ef9d897e14 user:Gregory Szorc date:Sat May 12 14:41:48 2018 -0700 summary: packaging: don't write files for templatized Dockerfiles https://www.mercurial-scm.org/repo/hg/rev/7f738edc4a27 changeset: 38460:7f738edc4a27 user:Gregory Szorc date:Sat May 12 18:44:03 2018 -0700 summary: packaging: dynamically define make targets https://www.mercurial-scm.org/repo/hg/rev/8459e8d2f729 changeset: 38461:8459e8d2f729 bookmark:@ tag: tip user:Boris Feld date:Mon May 28 20:51:20 2018 +0200 summary: shelve: check the actual shelvestate in morestatus -- Repository URL: https://www.mercurial-scm.org/repo/hg ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: D3841: stringutil: add a new function to do minimal regex escaping
> +# regex special chars pulled from https://bugs.python.org/issue29995 > +# which was part of Python 3.7. > +_respecial = pycompat.bytestr(b'()[]{}?*+-|^$\\.# \t\n\r\v\f') > +_regexescapemap = {ord(i): (b'\\' + i).decode('latin1') for i in _respecial} The Py3.7 version also includes '&' and '~'. https://github.com/python/cpython/blob/v3.7.0rc1/Lib/re.py#L248 ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3841: stringutil: add a new function to do minimal regex escaping
yuja added a comment. > +# regex special chars pulled from https://bugs.python.org/issue29995 > +# which was part of Python 3.7. > +_respecial = pycompat.bytestr(b'()[]{}?*+-|^$\\.# \t\n\r\v\f') > +_regexescapemap = {ord(i): (b'\\' + i).decode('latin1') for i in _respecial} The Py3.7 version also includes '&' and '~'. https://github.com/python/cpython/blob/v3.7.0rc1/Lib/re.py#L248 REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3841 To: durin42, #hg-reviewers, pulkit Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: D3849: rebase: refactor dryrun implementation
> @yuja In this patch rebaseruntime is instantiated two times, one in > _dryrunrebase and second in _origrebase, I don't know if it could make any > problem although all tests are passing. Maybe _origrebase() also need some > refactoring. Perhaps. I don't know if that really matters, but it's better to not keep two separate rbsrt objects alive. Can you reorder this as follows? 1. extract _dryrunrebase() with no code change 2. pass in rbsrt to _origrebase() (or new function extracted from _origrebase()) 3. replace _origrebase(abort=True) with rbsrt call > +def _abortunfinishedrebase(self, backup=False, suppwarns=True): > +repo = self.repo > +with repo.wlock(), repo.lock(): > +retcode = self._prepareabortorcontinue(isabort=True) > +return retcode If this is just calling _prepareabortorcontinue(), we wouldn't need a new function. And I think the lock should be held by the caller. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3849: rebase: refactor dryrun implementation
yuja added a comment. > @yuja In this patch rebaseruntime is instantiated two times, one in > _dryrunrebase and second in _origrebase, I don't know if it could make any > problem although all tests are passing. Maybe _origrebase() also need some > refactoring. Perhaps. I don't know if that really matters, but it's better to not keep two separate rbsrt objects alive. Can you reorder this as follows? 1. extract _dryrunrebase() with no code change 2. pass in rbsrt to _origrebase() (or new function extracted from _origrebase()) 3. replace _origrebase(abort=True) with rbsrt call > +def _abortunfinishedrebase(self, backup=False, suppwarns=True): > +repo = self.repo > +with repo.wlock(), repo.lock(): > +retcode = self._prepareabortorcontinue(isabort=True) > +return retcode If this is just calling _prepareabortorcontinue(), we wouldn't need a new function. And I think the lock should be held by the caller. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3849 To: khanchi97, #hg-reviewers Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: D3639: remotenames: add paths argument to remotenames revset
> +@revsetpredicate('remotenames([path, ...])') My proposal was `remotenames([pattern])`, just like bookmark(), tag(), branch(), etc. If we want a convenient way to specify path prefix, we can add it to the stringmatcher (e.g. 'remotenames("path:server2")'.) And multiple paths can be specified as 'remotenames(x) + remotenames(y)', though it isn't exactly the same as 'remotenames("re:|")'. Does it make sense? ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3639: remotenames: add paths argument to remotenames revset
yuja added a comment. > +@revsetpredicate('remotenames([path, ...])') My proposal was `remotenames([pattern])`, just like bookmark(), tag(), branch(), etc. If we want a convenient way to specify path prefix, we can add it to the stringmatcher (e.g. 'remotenames("path:server2")'.) And multiple paths can be specified as 'remotenames(x) + remotenames(y)', though it isn't exactly the same as 'remotenames("re:|")'. Does it make sense? REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3639 To: pulkit, #hg-reviewers Cc: durin42, yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3843: tests: fix up some lax escaping in test-template-basic.t
This revision was automatically updated to reflect the committed changes. Closed by commit rHGb4cfd803b3f2: tests: fix up some lax escaping in test-template-basic.t (authored by durin42, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D3843?vs=9310&id=9322 REVISION DETAIL https://phab.mercurial-scm.org/D3843 AFFECTED FILES tests/test-template-basic.t CHANGE DETAILS diff --git a/tests/test-template-basic.t b/tests/test-template-basic.t --- a/tests/test-template-basic.t +++ b/tests/test-template-basic.t @@ -835,11 +835,11 @@ -o perso- $ hg log -R a -r 2 --template '{sub(r"\\x6e", "-", desc)}\n' no person - $ hg log -R a -r 2 --template '{sub("n", r"\x2d", desc)}\n' + $ hg log -R a -r 2 --template '{sub("n", r"\\x2d", desc)}\n' \x2do perso\x2d $ hg log -R a -r 2 --template '{sub("n", "\x2d", "no perso\x6e")}\n' -o perso- - $ hg log -R a -r 2 --template '{sub("n", r"\x2d", r"no perso\x6e")}\n' + $ hg log -R a -r 2 --template '{sub("n", r"\\x2d", r"no perso\x6e")}\n' \x2do perso\x6e $ hg log -R a -r 8 --template '{files % "{file}\n"}' To: durin42, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 2] hooks: allow Unix style environment variables on external Windows hooks
# HG changeset patch # User Matt Harbison # Date 1498969929 14400 # Sun Jul 02 00:32:09 2017 -0400 # Node ID 6d206e4742d6f31246d0e234add03436ac429ebf # Parent 7ac9de5a8826fc95864ee4ba844eb8b5c9e71332 hooks: allow Unix style environment variables on external Windows hooks This will help making common hooks between Windows and non-Windows platforms. Having to build the shellenviron dict here and in procutil.system() is a bit unfortunate, but the only other option is to fix up the command inside procutil.system(). It seems more important that the note about the hook being run reflects what is actually run. The patch from last summer added the hooks on the command line, but it looks like HG_ARGS has since learned about --config args, and the output was just confusing. Therefore, it's now loaded from a file in the histedit test for clarity. diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt --- a/mercurial/help/config.txt +++ b/mercurial/help/config.txt @@ -886,6 +886,12 @@ They contain the type of hook which trig of the hook in the config, respectively. In the example above, this will be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``. +.. container:: windows + + Some basic Unix syntax is supported for portability, including ``$VAR`` + and ``${VAR}`` style variables. To use a literal ``$``, it must be + escaped with a back slash or inside of a strong quote. + ``changegroup`` Run after a changegroup has been added via push, pull or unbundle. The ID of the first new changeset is in ``$HG_NODE`` and last is in ``$HG_NODE_LAST``. diff --git a/mercurial/hook.py b/mercurial/hook.py --- a/mercurial/hook.py +++ b/mercurial/hook.py @@ -120,8 +120,6 @@ def pythonhook(ui, repo, htype, hname, f return r, False def _exthook(ui, repo, htype, name, cmd, args, throw): -ui.note(_("running hook %s: %s\n") % (name, cmd)) - starttime = util.timer() env = {} @@ -141,6 +139,12 @@ def _exthook(ui, repo, htype, name, cmd, v = stringutil.pprint(v) env['HG_' + k.upper()] = v +if pycompat.iswindows: +environ = procutil.shellenviron(env) +cmd = util.platform.shelltocmdexe(cmd, environ) + +ui.note(_("running hook %s: %s\n") % (name, cmd)) + if repo: cwd = repo.root else: diff --git a/tests/test-histedit-fold.t b/tests/test-histedit-fold.t --- a/tests/test-histedit-fold.t +++ b/tests/test-histedit-fold.t @@ -478,14 +478,7 @@ This is an excuse to test hook with hist 1:199b6bb90248 b 0:6c795aa153cb a -Setup the proper environment variable symbol for the platform, to be subbed -into the hook command. -#if windows - $ NODE="%HG_NODE%" -#else - $ NODE="\$HG_NODE" -#endif - $ hg histedit 6c795aa153cb --config hooks.commit="echo commit $NODE" --commands - 2>&1 << EOF | fixbundle + $ hg histedit 6c795aa153cb --config hooks.commit='echo commit $HG_NODE' --commands - 2>&1 << EOF | fixbundle > pick 199b6bb90248 b > fold a1a953ffb4b0 c > pick 6c795aa153cb a @@ -496,8 +489,24 @@ into the hook command. 1:9599899f62c0 a 0:79b99e9c8e49 b +Test unix -> windows style variable substitution in external hooks. + + $ cat > $TESTTMP/tmp.hgrc <<'EOF' + > [hooks] + > pre-add = echo no variables + > post-add = echo ran $HG_ARGS, literal \$non-var, 'also $non-var', $HG_RESULT + > EOF + +TODO: Windows should output double quotes around "also $non-var" $ echo "foo" > amended.txt - $ hg add amended.txt + $ HGRCPATH=$TESTTMP/tmp.hgrc hg add -v amended.txt + running hook pre-add: echo no variables + no variables + adding amended.txt + running hook post-add: echo ran %HG_ARGS%, literal $non-var, 'also $non-var', %HG_RESULT% (windows !) + running hook post-add: echo ran $HG_ARGS, literal \$non-var, 'also $non-var', $HG_RESULT (no-windows !) + ran add -v amended.txt, literal $non-var, 'also $non-var', 0 (windows !) + ran add -v amended.txt, literal $non-var, also $non-var, 0 (no-windows !) $ hg ci -q --config extensions.largefiles= --amend -I amended.txt The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !) diff --git a/tests/test-rebase-interruptions.t b/tests/test-rebase-interruptions.t --- a/tests/test-rebase-interruptions.t +++ b/tests/test-rebase-interruptions.t @@ -333,12 +333,7 @@ Test rebase interrupted by hooks $ cp -R a3 hook-pretxncommit $ cd hook-pretxncommit -#if windows - $ NODE="%HG_NODE%" -#else - $ NODE="\$HG_NODE" -#endif - $ hg rebase --source 2 --dest 5 --tool internal:other --config "hooks.pretxncommit=hg log -r $NODE | grep \"summary: C\"" + $ hg rebase --source 2 --dest 5 --tool internal:other --config 'hooks.pretxncommit=hg log -r $HG_NODE | grep "summary: C"' rebasing 2:965c486023db "C" summary: C rebasing 6:a0b2430ebfb8 "F" (tip) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.merc
[PATCH 1 of 2] windows: add a method to convert Unix style command lines to Windows style
# HG changeset patch # User Matt Harbison # Date 1529817189 14400 # Sun Jun 24 01:13:09 2018 -0400 # Node ID 7ac9de5a8826fc95864ee4ba844eb8b5c9e71332 # Parent 2c2e82469b8915c8153979cd89a970b7317f882d windows: add a method to convert Unix style command lines to Windows style This started as a copy/paste of `os.path.expandvars()`, but limited to a given dictionary of variables, converting `foo = foo + bar` to `foo += bar`, and adding 'b' string prefixes. Then code was added to make sure that a value being substituted in wouldn't itself be expanded by cmd.exe. But that left inconsistent results between `$var1` and `%var1%` when its value was '%foo%'- since neither were touched, `$var1` wouldn't expand but `%var1%` would. So instead, this just converts the Unix style to Windows style (if the variable exists, because Windows will leave `%missing%` as-is), and lets cmd.exe do its thing. I then dropped the %% -> % conversion (because Windows doesn't do this), and added the ability to escape the '$' with '\'. The escape character is dropped, for consistency with shell handling. After everything seemed stable and working, running the whole test suite flagged a problem near the end of test-bookmarks.t:1069. The problem is cmd.exe won't pass empty variables to its child, so defined but empty variables are now skipped. I can't think of anything better, and it seems like a pre-existing violation of the documentation, which calls out that HG_OLDNODE is empty on bookmark creation. Future additions could potentially be replacing strong quotes with double quotes (cmd.exe doesn't know what to do with the former), escaping a double quote, and some tilde expansion via os.path.expanduser(). I've got some doubts about replacing the strong quotes in case sh.exe is run, but it seems like the right thing to do the vast majority of the time. The original form of this was discussed about a year ago[1]. [1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-July/100735.html diff --git a/mercurial/windows.py b/mercurial/windows.py --- a/mercurial/windows.py +++ b/mercurial/windows.py @@ -12,6 +12,7 @@ import msvcrt import os import re import stat +import string import sys from .i18n import _ @@ -253,6 +254,108 @@ normcasefallback = encoding.upperfallbac def samestat(s1, s2): return False +def shelltocmdexe(path, env): +r"""Convert shell variables in the form $var and ${var} inside ``path`` +to %var% form. Existing Windows style variables are left unchanged. + +The variables are limited to the given environment. Unknown variables are +left unchanged. + +>>> e = {b'var1': b'v1', b'var2': b'v2', b'var3': b'v3'} +>>> # Only valid values are expanded +>>> shelltocmdexe(b'cmd $var1 ${var2} %var3% $missing ${missing} %missing%', +... e) +'cmd %var1% %var2% %var3% $missing ${missing} %missing%' +>>> # Single quote prevents expansion, as does \$ escaping +>>> shelltocmdexe(b"cmd '$var1 ${var2} %var3%' \$var1 \${var2} \\", e) +"cmd '$var1 ${var2} %var3%' $var1 ${var2} \\" +>>> # $$ -> $, %% is not special, but can be the end and start of variables +>>> shelltocmdexe(b"cmd $$ %% %var1%%var2%", e) +'cmd $ %% %var1%%var2%' +>>> # No double substitution +>>> shelltocmdexe(b"$var1 %var1%", {b'var1': b'%var2%', b'var2': b'boom'}) +'%var1% %var1%' +""" +if b'$' not in path: +return path + +varchars = pycompat.sysbytes(string.ascii_letters + string.digits) + b'_-' + +res = b'' +index = 0 +pathlen = len(path) +while index < pathlen: +c = path[index] +if c == b'\'': # no expansion within single quotes +path = path[index + 1:] +pathlen = len(path) +try: +index = path.index(b'\'') +res += b'\'' + path[:index + 1] +except ValueError: +res += c + path +index = pathlen - 1 +elif c == b'%': # variable +path = path[index + 1:] +pathlen = len(path) +try: +index = path.index(b'%') +except ValueError: +res += b'%' + path +index = pathlen - 1 +else: +var = path[:index] +res += b'%' + var + b'%' +elif c == b'$': # variable or '$$' +if path[index + 1:index + 2] == b'$': +res += c +index += 1 +elif path[index + 1:index + 2] == b'{': +path = path[index + 2:] +pathlen = len(path) +try: +index = path.index(b'}') +var = path[:index] + +# See below for why empty variables are handled specially +if env.get(var, '') != '': +res += b'%' + var + b'%' +else: +res += b'${' + var +
Re: [PATCH 2 of 3 gca-revset V2] revset: add optimization for heads(commonancestors())
On Tue, 26 Jun 2018 15:40:38 -0700, Sean Farley wrote: > # HG changeset patch > # User Sean Farley > # Date 1530051981 25200 > # Tue Jun 26 15:26:21 2018 -0700 > # Branch gca-revset > # Node ID 0bab83973dbaecf03167801ddc4550c4b8b581f1 > # Parent 6034db436af9b15237bb87f82405eb039dfb > revset: add optimization for heads(commonancestors()) > +from .ancestor import commonancestorsheads symbol import isn't allowed. > +# for internal use > +@predicate('_commonancestorheads(set)', safe=True) > +def _commonancestorheads(repo, subset, x): > +"""Returns all greatest common ancestors of the changesets. > + > +This is an internal method is for quickly calculating "heads(::x and > ::y)" > + > +These greatest common ancestors are the same ones that the consesus bid > +merge will find. > +""" This has to be a comment. All docstrings are visible in the revset help. > +h = heads(repo, subset, x) ^^ fullreposet(repo) heads may be out of the subset. > + > +try: > +ancs = repo.changelog.index.commonancestorsheads(*list(h)) > +return subset & baseset(ancs) > +except (AttributeError, OverflowError): # C implementation failed > +return subset & commonancestorsheads(repo.changelog.parentrevs, > + *list(h)) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 3 gca-revset V2] revsets: add commonancestors revset
On Tue, 26 Jun 2018 15:40:37 -0700, Sean Farley wrote: > # HG changeset patch > # User Sean Farley > # Date 1529376114 25200 > # Mon Jun 18 19:41:54 2018 -0700 > # Branch gca-revset > # Node ID 6034db436af9b15237bb87f82405eb039dfb > # Parent 2f5c622fcb739aed795c9ab51ea69c3b46436054 > revsets: add commonancestors revset > +@predicate('commonancestors(set)', safe=True) > +def commonancestors(repo, subset, x): > +"""Returns all common ancestors of the set. > + > +This method is for calculating "::x and ::y" (i.e. all the ancestors that > +are common to both x and y) in an easy and optimized way. We can't quite > +use "::head()" but that revset returns "::x + ::y + ..." for each head in > +the repo (whereas we want "::x *and* ::y"). > + > +""" > +# only wants the heads of the set passed in > +h = heads(repo, subset, x) ^^ Perhaps it should be fullreposet(repo) since the subset has to be filtered by any heads which may be out of the subset. > +commonrevs = repo.revs(" and ".join(["::%s"] * len(h), *h)) ^^^ Bad parens. And this wouldn't work if h is empty. Instead, we can chain ancestor revisions. for r in heads(...): subset &= dagop.revancestors(repo, baseset([r])) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3849: rebase: refactor dryrun implementation
khanchi97 added a subscriber: yuja. khanchi97 added a comment. @yuja In this patch rebaseruntime is instantiated two times, one in _dryrunrebase and second in _origrebase, I don't know if it could make any problem although all tests are passing. Maybe _origrebase() also need some refactoring. See if this refactoring is good or if this can be improved, then please give some suggestions. Thanks :) REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3849 To: khanchi97, #hg-reviewers Cc: yuja, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D3849: rebase: refactor dryrun implementation
khanchi97 created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY This patch refactor dry-run code to make it easy to add additional functionality in dryrun. Otherwise we had to add every functionality through _origrebase() which does not seem a good implementation. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D3849 AFFECTED FILES hgext/rebase.py CHANGE DETAILS diff --git a/hgext/rebase.py b/hgext/rebase.py --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -644,6 +644,12 @@ repo['.'].node() == repo._bookmarks[self.activebookmark]): bookmarks.activate(repo, self.activebookmark) +def _abortunfinishedrebase(self, backup=False, suppwarns=True): +repo = self.repo +with repo.wlock(), repo.lock(): +retcode = self._prepareabortorcontinue(isabort=True) +return retcode + @command('rebase', [('s', 'source', '', _('rebase the specified changeset and descendants'), _('REV')), @@ -818,19 +824,7 @@ opts[r'dest'] = '_destautoorphanrebase(SRC)' if dryrun: -try: -overrides = {('rebase', 'singletransaction'): True} -with ui.configoverride(overrides, 'rebase'): -_origrebase(ui, repo, inmemory=True, leaveunfinished=True, -**opts) -except error.InMemoryMergeConflictsError: -ui.status(_('hit a merge conflict\n')) -return 1 -else: -ui.status(_('there will be no conflict, you can rebase\n')) -return 0 -finally: -_origrebase(ui, repo, abort=True) +return _dryrunrebase(ui, repo, **opts) elif inmemory: try: # in-memory merge doesn't support conflicts, so if we hit any, abort @@ -846,6 +840,24 @@ else: return _origrebase(ui, repo, **opts) +def _dryrunrebase(ui, repo, **opts): +leaveunfinished = True +inmemory = True +rbsrt = rebaseruntime(repo, ui, inmemory, opts) +try: +overrides = {('rebase', 'singletransaction'): True} +with ui.configoverride(overrides, 'rebase'): +_origrebase(ui, repo, inmemory=True, +leaveunfinished=leaveunfinished, **opts) +except error.InMemoryMergeConflictsError: +ui.status(_('hit a merge conflict\n')) +return 1 +else: +ui.status(_('there will be no conflict, you can rebase\n')) +return 0 +finally: +rbsrt._abortunfinishedrebase() + def _origrebase(ui, repo, inmemory=False, leaveunfinished=False, **opts): opts = pycompat.byteskwargs(opts) rbsrt = rebaseruntime(repo, ui, inmemory, opts) To: khanchi97, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel