Re: [PATCH] revset: introduce the summary predicate
On Mon, 09 Jan 2017 05:49:23 -0500, Pierre-Yves Davidwrote: On 01/08/2017 09:34 PM, Matt Harbison wrote: On Sun, 08 Jan 2017 07:59:36 -0500, Pierre-Yves David wrote: (ha, I wrote my previous reply in a train and it got sent when I connected again (and received that one). I'm going to try to adress the new content in this email and sometime repeat some of my other reply content for clarity) On 01/08/2017 04:23 AM, Matt Harbison wrote: On Sat, 07 Jan 2017 02:56:48 -0500, Yuya Nishihara wrote: On Fri, 6 Jan 2017 21:29:43 -0500, Matt Harbison wrote: > On Jan 6, 2017, at 11:19 AM, Pierre-Yves David wrote: >> On 01/04/2017 07:04 PM, Matt Harbison wrote: >> # HG changeset patch >> # User Matt Harbison >> # Date 1483550016 18000 >> # Wed Jan 04 12:13:36 2017 -0500 >> # Node ID 76d95ab94b9e206363629059fb7824002e19a9e5 >> # Parent 0064a1eb28e246ded9b726c696d048143d1b23f1 >> revset: introduce the summary predicate >> Perhaps stringmatcher can have 3 types, icase literal, literal, and re, and the default of desc() is icase literal for backward compatibility. You can build a case-insensitive regexp object from a literal pattern. https://docs.python.org/2/library/re.html#re.I Yep, that's the API I was thinking of. I'm confused by the rest of your comments. When I first skimmed your message, adding support for 'icasere:' using this API popped into my mind. And that could support a case insensitive literal, because 'icasere:foo' should be equivalent to looking for the substring 'foo' (leaving aside efficiency, how discoverable that is, and that stringmatcher matches the whole string for literals). But you seem to be suggesting adding 'icaseliteral:'. I'm not 100% sure of what Yuya actually has in mind but here is my understanding of the situation and how we could move forward. Currently: -- desc(X) → X is customly matched as a case insensitive litteral, We have a "generic" pattern definition syntax used by various other reveset (implemented in "stringmatcher") foo(X) → X is matched as a case sensitive litteral foo('literal:X') → X is matched as a case sensitive literal (same as the above) food('re:X') → X is matched as a regular expression (case sensitive) Proposal: (might be what yuya says) - extend the string matcher to foo('literal:X') → X is matched as a case sensitive literal See the comment in the new patch I sent about 'user()' already lowercasing 'literal:' and 're:'. I'd consider it a bug, but it's been in since mid 2012. Attempting to channel Matt, I'm guessing we are stuck with that since it is so old, but wanted to see what others think. 1) Yep, we are stuck with whatever existing behavior we have for existing predicate because of BC. (but we can augment it) 2) Congratulation you seems to have unearthed an area where we have many predicated with close but slightly different behavior. At that point I'll ask you an inventory of what we currently have so that we can devise a sound and as consistent as possible way forward. Can you provide us with a table that at least keep track of: * predicate * default behavior * support 'rich' stringmatcher ? * are 'literal:' case sensitive ? * are 're:' case sensitive (and supported at all) ? TL;DR: desc, grep, keyword, and author/user are the oddballs. grep and keyword are the regex and literal halves respectively, of the same search. After stripping out non string predicates, we basically end up with 4 groups: - util.stringmatcher based: Predicate:Case Sensitive? "author" N "user" N "bookmark" Y "branch" Y "extra"Y "named"Y "subrepo" [1] Y "tag" Y These all support 'literal:' and 're:'. Case sensitivity applies the same to both prefixes, and raw pattern. [1] Not documented to support 'literal:' or 're:' prefixes. - Local method implementation based: Predicate:Case Sensitive? "desc" N "grep" Y "keyword" N None of these support prefixes. The grep param is a regex without 're:', so it doesn't make a lot of sense to support stringmatcher here- what stringmatcher thinks is literal is really regex. If we internally bolt on 're:', it still can't support literal matches. - match.py based (not relevant, but for completeness): "adds", "contains", "file", "filelog", "follow", "followlines", "modifies", "removes" - "bisect" (I can't see how 're:' support here would be meaningful.) From there we'll be able to see if a pattern emerge and pick the best way to move forward. The following thoughts
Re: The donation link don't work
On Wed, Dec 07, 2016 at 04:54:46PM -0500, Xavier Corredor Llano wrote: > Hi Mercurial developers, > > I tried to make a donation but the donation link: https://www.selenic.com/ > mercurial/donations.html don't work. https://www.mercurial-scm.org/donate will work for you. Sorry for the delay in this response. > > Thanks for the amazing VCS! > > Regards > ___ > 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] hgweb: generate archive links in order
On Sat, Jan 07, 2017 at 07:08:08PM -0800, Sean Farley wrote: > Anton Shestakovwrites: > > > # HG changeset patch > > # User Anton Shestakov > > # Date 1483807974 -28800 > > # Sun Jan 08 00:52:54 2017 +0800 > > # Node ID cfd14b0508ddf8edf156d202e2c5d07b259c2f46 > > # Parent 3cecf85b42c6cf3e2d81ff5d69e9328bb204d209 > > hgweb: generate archive links in order > > > > It would be nice for archive links to always be in a certain commonly used > > order, such as 'zip', 'bz', 'gzip2'. Repo index page (hgwebdir_mod) already > > shows archive links in this order, let's do the same in hgweb_mod. > > > > Sadly, archivespecs is a regular unordered dict, and > > collections.OrderedDict is > > new in 2.7. But requestcontext.archives is a tuple of archive types, so it > > can > > be used as an index to archivespecs. > > Sure, this looks good to me. Queued, thanks. > ___ > 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 5 of 8] pager: use super class's _runpager if possible
Excerpts from Jun Wu's message of 2017-01-10 07:12:25 +0800: > # HG changeset patch > # User Jun Wu> # Date 1484002766 -28800 > # Tue Jan 10 06:59:26 2017 +0800 > # Node ID 24ebef0f19843c6b1b8fbf32d99a7e8dba2fb734 > # Parent 483eabc8ccbbdfabed7f0f0abd74fb131adcd3c3 > # Available At https://bitbucket.org/quark-zju/hg-draft > # hg pull https://bitbucket.org/quark-zju/hg-draft -r > 24ebef0f1984 > pager: use super class's _runpager if possible > > The ui class is currently pagerui(chgui(ui)), so chgui's _runpager will be > overrided by pagerui. Detect it and use chgui's _runpager, in pager.py. > > In the future, when pager is moved to core, pagerui will no longer exist and > ui.py has _runpager implemented directly, and we can just call ui._runpager > without any check. > > diff --git a/hgext/pager.py b/hgext/pager.py > --- a/hgext/pager.py > +++ b/hgext/pager.py > @@ -121,5 +121,6 @@ def uisetup(ui): > class pagerui(ui.__class__): > def _runpager(self, pagercmd): > -_runpager(self, pagercmd) > +runpager = getattr(super(pagerui, self), '_runpager', _runpager) I realized that this is wrong (super(...) is not a class but an instance). Fortunately it seems that this patch could be just dropped without affecting correctness because how chg works currently. > +runpager(self, pagercmd) > > ui.__class__ = pagerui ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 8] chg: handle pager request client-side
# HG changeset patch # User Jun Wu# Date 1484002743 -28800 # Tue Jan 10 06:59:03 2017 +0800 # Node ID 97e3f81b69bc7bc670459c62056f706c2b6ff941 # Parent 603c1d614690ab594f240f4daf198f34c1714f62 # Available At https://bitbucket.org/quark-zju/hg-draft # hg pull https://bitbucket.org/quark-zju/hg-draft -r 97e3f81b69bc chg: handle pager request client-side This patch implements the simple S-channel pager handling at chg client-side. Note: It does not deal with environ and cwd currently for simplicity, which will be fixed later. diff --git a/contrib/chg/Makefile b/contrib/chg/Makefile --- a/contrib/chg/Makefile +++ b/contrib/chg/Makefile @@ -26,5 +26,5 @@ all: $(TARGET) chg.o: hgclient.h procutil.h util.h -hgclient.o: hgclient.h util.h +hgclient.o: hgclient.h procutil.h util.h procutil.o: procutil.h util.h util.o: util.h diff --git a/contrib/chg/hgclient.c b/contrib/chg/hgclient.c --- a/contrib/chg/hgclient.c +++ b/contrib/chg/hgclient.c @@ -24,4 +24,5 @@ #include "hgclient.h" +#include "procutil.h" #include "util.h" @@ -72,4 +73,6 @@ struct hgclient_tag_ { static const size_t defaultdatasize = 4096; +static void attachio(hgclient_t *hgc); + static void initcontext(context_t *ctx) { @@ -249,4 +252,11 @@ static void handlesystemrequest(hgclient ctx->datasize = sizeof(r_n); writeblock(hgc); + } else if (strcmp(args[0], "pager") == 0) { + setuppager(args[1]); + if (hgc->capflags & CAP_ATTACHIO) + attachio(hgc); + /* unblock the server */ + static const char emptycmd[] = "\n"; + sendall(hgc->sockfd, emptycmd, sizeof(emptycmd) - 1); } else { abortmsg("unknown type in system request: %s", args[0]); ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 4 of 8] chgserver: make S channel support pager request
# HG changeset patch # User Jun Wu# Date 1484002761 -28800 # Tue Jan 10 06:59:21 2017 +0800 # Node ID 483eabc8ccbbdfabed7f0f0abd74fb131adcd3c3 # Parent 97e3f81b69bc7bc670459c62056f706c2b6ff941 # Available At https://bitbucket.org/quark-zju/hg-draft # hg pull https://bitbucket.org/quark-zju/hg-draft -r 483eabc8ccbb chgserver: make S channel support pager request This patch adds the "pager" support for the S channel. The pager API allows running some subcommands, namely attachio, and waiting for the client to be properly synchronized. diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py --- a/mercurial/chgserver.py +++ b/mercurial/chgserver.py @@ -288,4 +288,8 @@ class channeledsystem(object): exitcode length (unsigned int), exitcode (int) + +if type == 'pager', repetitively waits for a command name ending with '\n' +and executes it defined by cmdtable, or exits the loop if the command name +is empty. """ def __init__(self, in_, out, channel): @@ -294,5 +298,5 @@ class channeledsystem(object): self.channel = channel -def __call__(self, cmd, environ, cwd, type='system'): +def __call__(self, cmd, environ, cwd=None, type='system', cmdtable=None): args = [type, util.quotecommand(cmd), os.path.abspath(cwd or '.')] args.extend('%s=%s' % (k, v) for k, v in environ.iteritems()) @@ -309,4 +313,14 @@ class channeledsystem(object): rc, = struct.unpack('>i', self.in_.read(4)) return rc +elif type == 'pager': +while True: +cmd = self.in_.readline()[:-1] +if not cmd: +break +if cmdtable and cmd in cmdtable: +_log('pager subcommand: %s' % cmd) +cmdtable[cmd]() +else: +raise error.Abort(_('unexpected command: %s') % cmd) else: raise error.ProgrammingError('invalid S channel type: %s' % type) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 5 of 8] pager: use super class's _runpager if possible
# HG changeset patch # User Jun Wu# Date 1484002766 -28800 # Tue Jan 10 06:59:26 2017 +0800 # Node ID 24ebef0f19843c6b1b8fbf32d99a7e8dba2fb734 # Parent 483eabc8ccbbdfabed7f0f0abd74fb131adcd3c3 # Available At https://bitbucket.org/quark-zju/hg-draft # hg pull https://bitbucket.org/quark-zju/hg-draft -r 24ebef0f1984 pager: use super class's _runpager if possible The ui class is currently pagerui(chgui(ui)), so chgui's _runpager will be overrided by pagerui. Detect it and use chgui's _runpager, in pager.py. In the future, when pager is moved to core, pagerui will no longer exist and ui.py has _runpager implemented directly, and we can just call ui._runpager without any check. diff --git a/hgext/pager.py b/hgext/pager.py --- a/hgext/pager.py +++ b/hgext/pager.py @@ -121,5 +121,6 @@ def uisetup(ui): class pagerui(ui.__class__): def _runpager(self, pagercmd): -_runpager(self, pagercmd) +runpager = getattr(super(pagerui, self), '_runpager', _runpager) +runpager(self, pagercmd) ui.__class__ = pagerui ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 7 of 8] chg: remove getpager support
# HG changeset patch # User Jun Wu# Date 1484002779 -28800 # Tue Jan 10 06:59:39 2017 +0800 # Node ID 24c7b11cecd12762d8238ec96c748131877054be # Parent e44b1d6deadb67908b43909ad920572e3efa38e6 # Available At https://bitbucket.org/quark-zju/hg-draft # hg pull https://bitbucket.org/quark-zju/hg-draft -r 24c7b11cecd1 chg: remove getpager support We have enough bits to switch to the new chg pager code path in runcommand. So just remove the legacy getpager support. This is a red-only patch, and will break chg's pager support temporarily. diff --git a/contrib/chg/chg.c b/contrib/chg/chg.c --- a/contrib/chg/chg.c +++ b/contrib/chg/chg.c @@ -430,8 +430,4 @@ int main(int argc, const char *argv[], c setupsignalhandler(hgc_peerpid(hgc), hgc_peerpgid(hgc)); - const char *pagercmd = hgc_getpager(hgc, argv + 1, argc - 1); - pid_t pagerpid = setuppager(pagercmd); - if (pagerpid) - hgc_attachio(hgc); /* reattach to pager */ int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1); restoresignalhandler(); diff --git a/contrib/chg/hgclient.c b/contrib/chg/hgclient.c --- a/contrib/chg/hgclient.c +++ b/contrib/chg/hgclient.c @@ -33,5 +33,4 @@ enum { CAP_ATTACHIO = 0x0100, CAP_CHDIR = 0x0200, - CAP_GETPAGER = 0x0400, CAP_SETENV = 0x0800, CAP_SETUMASK = 0x1000, @@ -49,5 +48,4 @@ static const cappair_t captable[] = { {"attachio", CAP_ATTACHIO}, {"chdir", CAP_CHDIR}, - {"getpager", CAP_GETPAGER}, {"setenv", CAP_SETENV}, {"setumask", CAP_SETUMASK}, @@ -594,29 +592,4 @@ void hgc_attachio(hgclient_t *hgc) /*! - * Get pager command for the given Mercurial command args - * - * If no pager enabled, returns NULL. The return value becomes invalid - * once you run another request to hgc. - */ -const char *hgc_getpager(hgclient_t *hgc, const char *const args[], -size_t argsize) -{ - assert(hgc); - - if (!(hgc->capflags & CAP_GETPAGER)) - return NULL; - - packcmdargs(>ctx, args, argsize); - writeblockrequest(hgc, "getpager"); - handleresponse(hgc); - - if (hgc->ctx.datasize < 1 || hgc->ctx.data[0] == '\0') - return NULL; - enlargecontext(>ctx, hgc->ctx.datasize + 1); - hgc->ctx.data[hgc->ctx.datasize] = '\0'; - return hgc->ctx.data; -} - -/*! * Update server's environment variables * diff --git a/contrib/chg/hgclient.h b/contrib/chg/hgclient.h --- a/contrib/chg/hgclient.h +++ b/contrib/chg/hgclient.h @@ -26,6 +26,4 @@ const char **hgc_validate(hgclient_t *hg int hgc_runcommand(hgclient_t *hgc, const char *const args[], size_t argsize); void hgc_attachio(hgclient_t *hgc); -const char *hgc_getpager(hgclient_t *hgc, const char *const args[], -size_t argsize); void hgc_setenv(hgclient_t *hgc, const char *const envp[]); diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py --- a/mercurial/chgserver.py +++ b/mercurial/chgserver.py @@ -17,7 +17,4 @@ change current directory -'getpager' command -checks if pager is enabled and which pager should be executed - 'setenv' command replace os.environ completely @@ -46,5 +43,4 @@ import inspect import os import re -import signal import struct import time @@ -53,5 +49,4 @@ from .i18n import _ from . import ( -cmdutil, commandserver, encoding, @@ -173,43 +168,4 @@ class hashstate(object): return hashstate(confighash, mtimehash, mtimepaths) -# copied from hgext/pager.py:uisetup() -def _setuppagercmd(ui, options, cmd): -from . import commands # avoid cycle - -if not ui.formatted(): -return - -p = ui.config("pager", "pager", encoding.environ.get("PAGER")) -usepager = False -always = util.parsebool(options['pager']) -auto = options['pager'] == 'auto' - -if not p: -pass -elif always: -usepager = True -elif not auto: -usepager = False -else: -attended = ['annotate', 'cat', 'diff', 'export', 'glog', 'log', 'qdiff'] -attend = ui.configlist('pager', 'attend', attended) -ignore = ui.configlist('pager', 'ignore') -cmds, _ = cmdutil.findcmd(cmd, commands.table) - -for cmd in cmds: -var = 'attend-%s' % cmd -if ui.config('pager', var): -usepager = ui.configbool('pager', var) -break -if (cmd in attend or -(cmd not in ignore and not attend)): -usepager = True -break - -if usepager: -ui.setconfig('ui', 'formatted', ui.formatted(), 'pager') -ui.setconfig('ui', 'interactive', False, 'pager') -return p - def _newchgui(srcui, csystem, attachio): class chgui(srcui.__class__): @@ -485,35 +441,4 @@ class chgcmdserver(commandserver.server) os.umask(mask) -def getpager(self): -"""Read
[PATCH 8 of 8] pager: do not special case chg
# HG changeset patch # User Jun Wu# Date 1484002789 -28800 # Tue Jan 10 06:59:49 2017 +0800 # Node ID 38c6cb64c8d08e8b4c19338010578f69f58ef705 # Parent 24c7b11cecd12762d8238ec96c748131877054be # Available At https://bitbucket.org/quark-zju/hg-draft # hg pull https://bitbucket.org/quark-zju/hg-draft -r 38c6cb64c8d0 pager: do not special case chg Since chg has its own _runpager implementation, it's no longer necessary to special-case chg in the pager extension. This will effectively enable the new chg pager code path that runs inside runcommand. diff --git a/hgext/pager.py b/hgext/pager.py --- a/hgext/pager.py +++ b/hgext/pager.py @@ -126,9 +126,4 @@ def uisetup(ui): ui.__class__ = pagerui -# chg has its own pager implementation -argv = sys.argv[:] -if 'chgunix' in dispatch._earlygetopt(['--cmdserver'], argv): -return - def pagecmd(orig, ui, options, cmd, cmdfunc): p = ui.config("pager", "pager", encoding.environ.get("PAGER")) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 6 of 8] chgserver: implement chgui._runpager
# HG changeset patch # User Jun Wu# Date 1484002771 -28800 # Tue Jan 10 06:59:31 2017 +0800 # Node ID e44b1d6deadb67908b43909ad920572e3efa38e6 # Parent 24ebef0f19843c6b1b8fbf32d99a7e8dba2fb734 # Available At https://bitbucket.org/quark-zju/hg-draft # hg pull https://bitbucket.org/quark-zju/hg-draft -r e44b1d6deadb chgserver: implement chgui._runpager This patch implements chgui._runpager in a relatively simple way. A more clean way is to move the core logic of "attachio" to "ui", which will be done later after chg runs uisetup per request. diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py --- a/mercurial/chgserver.py +++ b/mercurial/chgserver.py @@ -212,5 +212,5 @@ def _setuppagercmd(ui, options, cmd): return p -def _newchgui(srcui, csystem): +def _newchgui(srcui, csystem, attachio): class chgui(srcui.__class__): def __init__(self, src=None): @@ -242,4 +242,8 @@ def _newchgui(srcui, csystem): return rc +def _runpager(self, cmd): +self._csystem(cmd, util.shellenviron(), type='pager', + cmdtable={'attachio': attachio}) + return chgui(srcui) @@ -336,5 +340,6 @@ class chgcmdserver(commandserver.server) def __init__(self, ui, repo, fin, fout, sock, hashstate, baseaddress): super(chgcmdserver, self).__init__( -_newchgui(ui, channeledsystem(fin, fout, 'S')), repo, fin, fout) +_newchgui(ui, channeledsystem(fin, fout, 'S'), self.attachio), +repo, fin, fout) self.clientsock = sock self._oldios = [] # original (self.ch, ui.fp, fd) before "attachio" ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 8] util: extract the logic calculating environment variables
# HG changeset patch # User Jun Wu# Date 1484002682 -28800 # Tue Jan 10 06:58:02 2017 +0800 # Node ID 25760899b0ad12660b6a9e8c7b928dd2c334ec80 # Parent 7438cb35979a81e3d0aca5be9a6e4397186a509e # Available At https://bitbucket.org/quark-zju/hg-draft # hg pull https://bitbucket.org/quark-zju/hg-draft -r 25760899b0ad util: extract the logic calculating environment variables The method will be reused in chgserver. Move it out so it can be reused. diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -975,4 +975,19 @@ def _isstdout(f): return fileno and fileno() == sys.__stdout__.fileno() +def shellenviron(environ=None): +"""return environ with optional override, useful for shelling out""" +def py2shell(val): +'convert python object into string that is useful to shell' +if val is None or val is False: +return '0' +if val is True: +return '1' +return str(val) +env = dict(encoding.environ) +if environ: +env.update((k, py2shell(v)) for k, v in environ.iteritems()) +env['HG'] = hgexecutable() +return env + def system(cmd, environ=None, cwd=None, onerr=None, errprefix=None, out=None): '''enhanced shell command execution. @@ -984,17 +999,8 @@ def system(cmd, environ=None, cwd=None, if out is specified, it is assumed to be a file-like object that has a write() method. stdout and stderr will be redirected to out.''' -if environ is None: -environ = {} try: stdout.flush() except Exception: pass -def py2shell(val): -'convert python object into string that is useful to shell' -if val is None or val is False: -return '0' -if val is True: -return '1' -return str(val) origcmd = cmd cmd = quotecommand(cmd) @@ -1007,7 +1013,5 @@ def system(cmd, environ=None, cwd=None, rc = os.system(cmd) else: -env = dict(encoding.environ) -env.update((k, py2shell(v)) for k, v in environ.iteritems()) -env['HG'] = hgexecutable() +env = shellenviron(environ) if out is None or _isstdout(out): rc = subprocess.call(cmd, shell=True, close_fds=closefds, ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 8] chgserver: use util.shellenviron
# HG changeset patch # User Jun Wu# Date 1484002731 -28800 # Tue Jan 10 06:58:51 2017 +0800 # Node ID 603c1d614690ab594f240f4daf198f34c1714f62 # Parent 25760899b0ad12660b6a9e8c7b928dd2c334ec80 # Available At https://bitbucket.org/quark-zju/hg-draft # hg pull https://bitbucket.org/quark-zju/hg-draft -r 603c1d614690 chgserver: use util.shellenviron This avoids code duplication. diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py --- a/mercurial/chgserver.py +++ b/mercurial/chgserver.py @@ -232,17 +232,6 @@ def _newchgui(srcui, csystem): return super(chgui, self).system(cmd, environ, cwd, onerr, errprefix) -# copied from mercurial/util.py:system() self.flush() -def py2shell(val): -if val is None or val is False: -return '0' -if val is True: -return '1' -return str(val) -env = encoding.environ.copy() -if environ: -env.update((k, py2shell(v)) for k, v in environ.iteritems()) -env['HG'] = util.hgexecutable() -rc = self._csystem(cmd, env, cwd) +rc = self._csystem(cmd, util.shellenviron(environ), cwd) if rc and onerr: errmsg = '%s %s' % (os.path.basename(cmd.split(None, 1)[0]), ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 5 of 5] test-obsolete: stabilize output on platforms without 'serve' support
On Sun, Jan 08, 2017 at 02:55:43PM -0500, Matt Harbison wrote: > # HG changeset patch > # User Matt Harbison> # Date 1483904264 18000 > # Sun Jan 08 14:37:44 2017 -0500 > # Node ID 85ffb7609d2730d8f602200549040856662e57ee > # Parent e37bd2d8a98e95e26c506ab00908f718f0e31ac0 > test-obsolete: stabilize output on platforms without 'serve' support Queued, thanks. > > The conditional was updating the repository, which wasn't reflected in > subsequent logs on Windows, so the conditional is narrowed to just the serve > commands. The serve operation generates log files, so those are deleted to > keep > the output of summary consistent. > > diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t > --- a/tests/test-obsolete.t > +++ b/tests/test-obsolete.t > @@ -719,8 +719,6 @@ >$ hg debugobsolete -r6 -T '{flag} {get(metadata, "user")}\n' >0 test > > -#if serve > - > Test the debug output for exchange > -- > > @@ -746,6 +744,8 @@ >$ hg up tip >2 files updated, 0 files merged, 0 files removed, 0 files unresolved > > +#if serve > + >$ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E > errors.log >$ cat hg.pid >> $DAEMON_PIDS > > @@ -796,6 +796,7 @@ >$ echo '[experimental]' >> $HGRCPATH >$ echo "evolution=createmarkers,exchange" >> $HGRCPATH > > + $ rm hg.pid access.log errors.log > #endif > > Several troubles on the same changeset (create an unstable and bumped > changeset) > @@ -833,7 +834,7 @@ >parent: 7:50c51b361e60 (unstable, bumped) > add babar >branch: default > - commit: 3 unknown (clean) > + commit: (clean) >update: 2 new changesets (update) >phases: 4 draft >unstable: 2 changesets > ___ > 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] revset: introduce the summary predicate
On Sun, Jan 08, 2017 at 03:34:13PM -0500, Matt Harbison wrote: > On Sun, 08 Jan 2017 07:59:36 -0500, Pierre-Yves David >wrote: > > > (ha, I wrote my previous reply in a train and it got sent when I > > connected again (and received that one). I'm going to try to adress the > > new content in this email and sometime repeat some of my other reply > > content for clarity) > > > > On 01/08/2017 04:23 AM, Matt Harbison wrote: [...] > > I'm not 100% sure of what Yuya actually has in mind but here is my > > understanding of the situation and how we could move forward. > > > > Currently: > > -- > > > >desc(X) → X is customly matched as a case insensitive litteral, > > > >We have a "generic" pattern definition syntax used by various other > > reveset (implemented in "stringmatcher") > > > > foo(X) > >→ X is matched as a case sensitive litteral > > foo('literal:X') > >→ X is matched as a case sensitive literal (same as the above) > > food('re:X') > >→ X is matched as a regular expression (case sensitive) > > > > Proposal: (might be what yuya says) > > - > > > > extend the string matcher to > > > >foo('literal:X') > > → X is matched as a case sensitive literal > > See the comment in the new patch I sent about 'user()' already lowercasing > 'literal:' and 're:'. I'd consider it a bug, but it's been in since mid > 2012. Attempting to channel Matt, I'm guessing we are stuck with that since > it is so old, but wanted to see what others think. Guessing at motivations for user() lowercasing: most email hosts are case-insensitive for the user part, even though rfc(2)822 doesn't require it. (Mostly stating this so that there's some trail of pondering if this ever comes up in the future.) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 5 of 8 git-diff] similar: move score function to module level
# HG changeset patch # User Sean Farley# Date 1483850877 28800 # Sat Jan 07 20:47:57 2017 -0800 # Node ID 8561e240f25e851476abde452b850fc09a7fdf06 # Parent 9af4ef2f80a8c5cb69ad4ff5d291ce81a35e4f39 similar: move score function to module level Future patches will use this to report the similarity of a rename / copy in the patch output. diff --git a/mercurial/similar.py b/mercurial/similar.py --- a/mercurial/similar.py +++ b/mercurial/similar.py @@ -41,10 +41,31 @@ def _findexactmatches(repo, added, remov yield (hashes[h], fctx) # Done repo.ui.progress(_('searching for exact renames'), None) +@util.cachefunc +def _ctxdata(fctx): +# lazily load text +orig = fctx.data() +return orig, mdiff.splitnewlines(orig) + +@util.cachefunc +def score(fctx1, fctx2): +text = fctx1.data() +orig, lines = _ctxdata(fctx2) +# bdiff.blocks() returns blocks of matching lines +# count the number of bytes in each +equal = 0 +matches = bdiff.blocks(text, orig) +for x1, x2, y1, y2 in matches: +for line in lines[y1:y2]: +equal += len(line) + +lengths = len(text) + len(orig) +return equal * 2.0 / lengths + def _findsimilarmatches(repo, added, removed, threshold): '''find potentially renamed files based on similar file content Takes a list of new filectxs and a list of removed filectxs, and yields (before, after, score) tuples of partial matches. @@ -52,32 +73,13 @@ def _findsimilarmatches(repo, added, rem copies = {} for i, r in enumerate(removed): repo.ui.progress(_('searching for similar files'), i, total=len(removed), unit=_('files')) -# lazily load text -@util.cachefunc -def data(): -orig = r.data() -return orig, mdiff.splitnewlines(orig) - -def score(text): -orig, lines = data() -# bdiff.blocks() returns blocks of matching lines -# count the number of bytes in each -equal = 0 -matches = bdiff.blocks(text, orig) -for x1, x2, y1, y2 in matches: -for line in lines[y1:y2]: -equal += len(line) - -lengths = len(text) + len(orig) -return equal * 2.0 / lengths - for a in added: bestscore = copies.get(a, (None, threshold))[1] -myscore = score(a.data()) +myscore = score(a, r) if myscore >= bestscore: copies[a] = (r, myscore) repo.ui.progress(_('searching'), None) for dest, v in copies.iteritems(): ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 8 of 8 git-diff] patch: add label for coloring the similarity extended header
# HG changeset patch # User Sean Farley# Date 1483988505 28800 # Mon Jan 09 11:01:45 2017 -0800 # Node ID 0ac83cc1715c18537e3f8087d32544db25cd29d0 # Parent 57b97693c687ab32b57bd3a75311237106992de9 patch: add label for coloring the similarity extended header Just like the summary says, this will colorize the: similarity index 88% line in the diff output. diff --git a/mercurial/patch.py b/mercurial/patch.py --- a/mercurial/patch.py +++ b/mercurial/patch.py @@ -2348,10 +2348,11 @@ def difflabel(func, *args, **kw): ('rename', 'diff.extended'), ('old', 'diff.extended'), ('new', 'diff.extended'), ('deleted', 'diff.extended'), ('index', 'diff.extended'), +('similarity', 'diff.extended'), ('---', 'diff.file_a'), ('+++', 'diff.file_b')] textprefixes = [('@', 'diff.hunk'), ('-', 'diff.deleted'), ('+', 'diff.inserted')] ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 8 git-diff] patch: add config knob for displaying the index header
# HG changeset patch # User Sean Farley# Date 1483989227 28800 # Mon Jan 09 11:13:47 2017 -0800 # Node ID f83be3a6c9e0e39efee95c1e4059030733a0371e # Parent ee47e951c6f9dbe6aceeb10d2f4acbc998a27bd3 patch: add config knob for displaying the index header This config knob can take an integer between 0 and 40 or a keyword ('none', 'short', 'full') to control the length of hash to output. It will display diffs with the git index header as such, diff --git a/mercurial/mdiff.py b/mercurial/mdiff.py index 112edf7..d6b52c5 100644 We'll put this in the experimental section for now. diff --git a/mercurial/mdiff.py b/mercurial/mdiff.py --- a/mercurial/mdiff.py +++ b/mercurial/mdiff.py @@ -50,10 +50,11 @@ class diffopts(object): 'showfunc': False, 'git': False, 'nodates': False, 'nobinary': False, 'noprefix': False, +'index': 0, 'ignorews': False, 'ignorewsamount': False, 'ignoreblanklines': False, 'upgrade': False, } diff --git a/mercurial/patch.py b/mercurial/patch.py --- a/mercurial/patch.py +++ b/mercurial/patch.py @@ -2166,10 +2166,35 @@ def difffeatureopts(ui, opts=None, untru 'context': get('unified', getter=ui.config), } if git: buildopts['git'] = get('git') + +# need to inspect the ui object instead of using get() since we want to +# test for an int +hconf = ui.config('experimental', 'extendedheader.index') +if hconf is not None: +hlen = None +try: +# the hash config could be an integer (for length of hash) or a +# word (e.g. short, full, none) +hlen = int(hconf) +except ValueError: +# default value +if hconf == 'short' or hconf == '': +hlen = 12 +elif hconf == 'full': +hlen = 40 +elif hconf != 'none': +msg = _("invalid value for extendedheader.index: '%s'\n") +ui.warn(msg % hconf) +finally: +if hlen < 0 or hlen > 40: +msg = _("invalid length for extendedheader.index: '%d'\n") +ui.warn(msg % hlen) +buildopts['index'] = hlen + if whitespace: buildopts['ignorews'] = get('ignore_all_space', 'ignorews') buildopts['ignorewsamount'] = get('ignore_space_change', 'ignorewsamount') buildopts['ignoreblanklines'] = get('ignore_blank_lines', ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 6 of 8 git-diff] patch: add similarity config knob in experimental section
# HG changeset patch # User Sean Farley# Date 1483987904 28800 # Mon Jan 09 10:51:44 2017 -0800 # Node ID f755adaeac8d325dbb99f759929e88a342368ed2 # Parent 8561e240f25e851476abde452b850fc09a7fdf06 patch: add similarity config knob in experimental section This config knob will control whether or not to show the similarity calculation in the diff output: diff --git a/README.md b/foo.md similarity index 88% rename from README.md rename to foo.md --- a/README.md +++ b/foo.md diff --git a/mercurial/mdiff.py b/mercurial/mdiff.py --- a/mercurial/mdiff.py +++ b/mercurial/mdiff.py @@ -55,10 +55,11 @@ class diffopts(object): 'index': 0, 'ignorews': False, 'ignorewsamount': False, 'ignoreblanklines': False, 'upgrade': False, +'showsimilarity': False, } def __init__(self, **opts): for k in self.defaults.keys(): v = opts.get(k) diff --git a/mercurial/patch.py b/mercurial/patch.py --- a/mercurial/patch.py +++ b/mercurial/patch.py @@ -2167,10 +2167,15 @@ def difffeatureopts(ui, opts=None, untru } if git: buildopts['git'] = get('git') +# since this is in the experimental section, we need to call +# ui.configbool directory +buildopts['showsimilarity'] = ui.configbool('experimental', + 'extendedheader.similarity') + # need to inspect the ui object instead of using get() since we want to # test for an int hconf = ui.config('experimental', 'extendedheader.index') if hconf is not None: hlen = None ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 8 git-diff] patch: add index line for diff output
# HG changeset patch # User Sean Farley# Date 1483220517 21600 # Sat Dec 31 15:41:57 2016 -0600 # Node ID 95c9da9342914bda2208138af58a38eeaed859b4 # Parent f83be3a6c9e0e39efee95c1e4059030733a0371e patch: add index line for diff output This helps highlighting in third-party diff coloring (which assumes git output) and maintains pedantic correctness with diff --git. Tests will be added at the end of the series. diff --git a/mercurial/patch.py b/mercurial/patch.py --- a/mercurial/patch.py +++ b/mercurial/patch.py @@ -2524,10 +2524,19 @@ def trydiff(repo, revs, ctx1, ctx2, modi text = mdiff.b85diff(content1, content2) if text: header.append('index %s..%s' % (gitindex(content1), gitindex(content2))) else: +if opts.git and opts.index > 0: +flag = flag1 +if flag is None: +flag = flag2 +header.append('index %s..%s %s' % + (gitindex(content1)[0:opts.index], + gitindex(content2)[0:opts.index], + gitmode[flag])) + text = mdiff.unidiff(content1, date1, content2, date2, path1, path2, opts=opts) if header and (text or len(header) > 1): yield '\n'.join(header) + '\n' ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 8 git-diff] patch: add label for coloring the index extended header
# HG changeset patch # User Sean Farley# Date 1483988385 28800 # Mon Jan 09 10:59:45 2017 -0800 # Node ID 8799dd0f3c4849ab5f468f2343af4c108ed22e72 # Parent 95c9da9342914bda2208138af58a38eeaed859b4 patch: add label for coloring the index extended header Just like the summary says, this will colorize the: index 3d3ba4b65e11..57274a0f46b2 100644 line in the diff output. diff --git a/mercurial/patch.py b/mercurial/patch.py --- a/mercurial/patch.py +++ b/mercurial/patch.py @@ -2341,10 +2341,11 @@ def difflabel(func, *args, **kw): ('copy', 'diff.extended'), ('rename', 'diff.extended'), ('old', 'diff.extended'), ('new', 'diff.extended'), ('deleted', 'diff.extended'), +('index', 'diff.extended'), ('---', 'diff.file_a'), ('+++', 'diff.file_b')] textprefixes = [('@', 'diff.hunk'), ('-', 'diff.deleted'), ('+', 'diff.inserted')] ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 4 of 8 git-diff] similar: rename local variable to not collide with previous
# HG changeset patch # User Sean Farley# Date 1483850629 28800 # Sat Jan 07 20:43:49 2017 -0800 # Node ID 9af4ef2f80a8c5cb69ad4ff5d291ce81a35e4f39 # Parent 8799dd0f3c4849ab5f468f2343af4c108ed22e72 similar: rename local variable to not collide with previous Future patches will move the score function to the module level, so let's not shadow that. diff --git a/mercurial/similar.py b/mercurial/similar.py --- a/mercurial/similar.py +++ b/mercurial/similar.py @@ -79,12 +79,12 @@ def _findsimilarmatches(repo, added, rem if myscore >= bestscore: copies[a] = (r, myscore) repo.ui.progress(_('searching'), None) for dest, v in copies.iteritems(): -source, score = v -yield source, dest, score +source, bscore = v +yield source, dest, bscore def findrenames(repo, added, removed, threshold): '''find renamed files -- yields (before, after, score) tuples''' parentctx = repo['.'] workingctx = repo[None] ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 7 of 8 git-diff] patch: use opt.showsimilarity to calculate and show the similarity
# HG changeset patch # User Sean Farley# Date 1483989858 28800 # Mon Jan 09 11:24:18 2017 -0800 # Node ID 57b97693c687ab32b57bd3a75311237106992de9 # Parent f755adaeac8d325dbb99f759929e88a342368ed2 patch: use opt.showsimilarity to calculate and show the similarity Tests have been added. diff --git a/mercurial/patch.py b/mercurial/patch.py --- a/mercurial/patch.py +++ b/mercurial/patch.py @@ -33,10 +33,11 @@ from . import ( error, mail, mdiff, pathutil, scmutil, +similar, util, ) stringio = util.stringio gitre = re.compile('diff --git a/(.*) b/(.*)') @@ -2519,10 +2520,13 @@ def trydiff(repo, revs, ctx1, ctx2, modi mode1, mode2 = gitmode[flag1], gitmode[flag2] if mode1 != mode2: header.append('old mode %s' % mode1) header.append('new mode %s' % mode2) if copyop is not None: +if opts.showsimilarity: +sim = similar.score(ctx1[path1], ctx2[path2]) * 100 +header.append('similarity index %d%%' % sim) header.append('%s from %s' % (copyop, path1)) header.append('%s to %s' % (copyop, path2)) elif revs and not repo.ui.quiet: header.append(diffline(path1, revs)) diff --git a/tests/test-diff-unified.t b/tests/test-diff-unified.t --- a/tests/test-diff-unified.t +++ b/tests/test-diff-unified.t @@ -227,10 +227,24 @@ Git diff, adding space +++ b/f 1 @@ -1,1 +1,1 @@ -a +b +Git diff, adding extended headers + + $ hg diff --git --config experimental.extendedheader.index=7 --config experimental.extendedheader.similarity=True + diff --git a/f1 b/f 1 + similarity index 0% + rename from f1 + rename to f 1 + index 7898192..6178079 100644 + --- a/f1 + +++ b/f 1 + @@ -1,1 +1,1 @@ + -a + +b + Git diff with noprefix $ hg --config diff.noprefix=True diff --git --nodates diff --git f1 f 1 rename from f1 ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [LAST CALL] Picking a date for Mercurial 4.2 sprint (California, February-March)
On 01/08/2017 09:45 PM, Gregory Szorc wrote: On Sun, Jan 8, 2017 at 10:01 AM, Martin von Zweigbergk> wrote: On Sun, Jan 8, 2017, 05:19 Pierre-Yves David > wrote: On 01/06/2017 08:46 PM, Martin von Zweigbergk wrote: > Still only 9 people signed up. The signup table on the wiki only > mentioned the weekend dates until just now, but I can't remember > deciding that we only do it on Saturday to Sunday, so it's still > presumably Friday to Sunday. Oops, looks like a small mistake on my part when I created the page. Yep, Friday to Sunday is still the plan here. > The wiki is now updated accordingly, and > hopefully people's availability is still accurate now that the dates > include Friday. The people who have signed up so far are all available > March 17th-19th, so that's what I'll try to find a conference room for > now. I'll assume we'll be ~30 people. Yep, 30 peoples seems our current average. Having small rooms for discussion helps a lot can you make sure we have a couple of them available? Yes, I was hoping to get 4 rooms for 5-10 people each, in addition to a big room. \o/ Thanks a lot for looking into this. It is getting urgent to freeze a date so that people can start planning travel. March 10th-12th is a bit earlier in the cycle so it might be preferable but Gregory Szorc attendance is less likely :-/. From a recent discussion with Greg it seemed like it was unclear he could make any of the sprint dates. So I'll let him jump in and clarify his preference (CCed him to make sure he sees that). It's already getting close, which is a reason to do the later date, so I'd rather stick with that until we have a more important reason to change. I personally don't care which date it is, but especially for all those who have to book flights, I imagine a later date is better. My attendance information in the wiki is accurate. The later the better for me. Given that everyone is available on March 10 and March 17 weekends and given that more time to prepare travel can't hurt, I think we should go with one of those weekends. As there is a higher odd to have you on the 17th, I would says we should stick to the 17th (the month of review between that sprint and the freeze will be "fun"). Let us aims are putting a final stamp one sprint date by Tuesday January 10th. What do you think? Sure, I think that's enough time to wait. I'd even be tempted to say the if someone has already booked a flight ticket, then that's reason enough to say to anyone else who has not yet signed up and for whom the date does not work, that "sorry, X has already booked a flight, it's too late to change". But yes, let's say January 10, mostly so those who need to book flights know that we're not changing the date, so they can book their flights on Jan 11. My main concern here is to avoid a sudden "Hey picked that date", I tend to give a 48h heads up to people before freezing decision. Especially since people are slow to react during the holiday seasons (as the low number of people registered on the page shown). As far as I'm concerned, feel free to declare a sprint date final tomorrow morning with the data you have in hand). Cheers, -- Pierre-Yves David ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 3 of 4 flagprocessor v8] revlog: flag processor
On 01/08/2017 10:42 PM, Gregory Szorc wrote: On Thu, Jan 5, 2017 at 9:42 AM, Remi Chaintron> wrote: # HG changeset patch # User Remi Chaintron > # Date 1483636648 0 # Thu Jan 05 17:17:28 2017 + # Node ID 8701df1c04340e9951481dc4c366ba550b4e790f # Parent a93b1ff78332f4f78e77ec9aaa2c63f7f975399c revlog: flag processor Add the ability for revlog objects to process revision flags and apply registered transforms on read/write operations. This patch introduces: - the 'revlog._processflags()' method that looks at revision flags and applies flag processors registered on them. Due to the need to handle non-commutative operations, flag transforms are applied in stable order but the order in which the transforms are applied is reversed between read and write operations. - the 'addflagprocessor()' method allowing to register processors on flags. Flag processors are defined as a 3-tuple of (read, write, raw) functions to be applied depending on the operation being performed. - an update on 'revlog.addrevision()' behavior. The current flagprocessor design relies on extensions to wrap around 'addrevision()' to set flags on revision data, and on the flagprocessor to perform the actual transformation of its contents. In the lfs case, this means we need to process flags before we meet the 2GB size check, leading to performing some operations before it happens: - if flags are set on the revision data, we assume some extensions might be modifying the contents using the flag processor next, and we compute the node for the original revision data (still allowing extension to override the node by wrapping around 'addrevision()'). - we then invoke the flag processor to apply registered transforms (in lfs's case, drastically reducing the size of large blobs). - finally, we proceed with the 2GB size check. Note: In the case a cachedelta is passed to 'addrevision()' and we detect the flag processor modified the revision data, we chose to trust the flag processor and drop the cachedelta. I've only been casually following this series, so apologies if my feedback below has been addressed already. From an architecture perspective, I really like this series. But one thing that is rubbing me the wrong way is the reserved USR flags. Actually, these USR flag have been dropped of the official and are now used in the tests. (so not part of BC). The test should probably use explicit name to make this clearer. The official approach regarding new flags is for people with new flag usecase to "quickly" contact upstream to reserve one of the available flag. Upstream do need to have actual support but act as a central registry for flags meaning. Rémi said he will follow up with some internal documentation about that. (note, if someone want to make as case for USR flag, he can do it independently once the case series is in) I like the idea of reserving flags for future use. However, for features that aren't in core, a simple bit is not sufficient to identify behavior. For example, extension "fbext" authored by Facebook and extension "mozext" authored by Mozilla could both use USR0 for different things. If someone at Facebook running "fbext" clones a Mozilla-hosted repo, their USR0 processor will do a completely different thing from what "mozext" intended. Chaos ensues. There are a number of ways to solve problems like this. One way is a central registry of transforms. But we only have 4 bits so that won't scale. Another is to use strings, probably with prefixes to "namespace" extensions. But we don't have an easy way to inject strings into revisions (although we could use a bit flag to indicate additional flags are at the beginning of the revlog chunk data in string format, kinda like how filelogs store copy/rename metadata). Another idea is repo requirements. You could add a requirement like "revlogusr0=fbext" to indicate that the USR0 flag is associated with "fbext." That way if another loaded extension providing USR0 is present, the repo will fail to open. But even the repo requirements solution has problems. What about `hg clone`? The remote server isn't advertising what the USR flags are doing. So, a client will happily start receiving changegroup data with flags having behavior defined by another extension. When they go to actually read that revision, things blow up. So for repos relying on USR flags, we need the client and/or server to advertise which USR flags they support and for what purpose and to fail fast if support isn't present. This means that a repo needs to know what USR flags are in use. This could be implemented as a repo requirement. I think it is fine to reserve a few bits for user flags.
Re: [PATCH 1 of 4 flagprocessor v8] revlog: add 'raw' argument to revision and _addrevision
On 01/05/2017 06:42 PM, Remi Chaintron wrote: # HG changeset patch # User Remi Chaintron# Date 1483636567 0 # Thu Jan 05 17:16:07 2017 + # Node ID 8c12adc05b5b1c564eb068d5ad893b33aadd4f76 # Parent 8385310370d0c472373ca9eb8aec59d50218d7e1 revlog: add 'raw' argument to revision and _addrevision That one looks good, with very small fix on a docstring. I'm not super happy with the patch order as that docstring reference content from two patches later but that's minor and I don't have a better slicing idea so lets move forward. (that also why I'm not taking patch 1-2 without 3) […] diff --git a/mercurial/revlog.py b/mercurial/revlog.py --- a/mercurial/revlog.py +++ b/mercurial/revlog.py […] @@ -1412,13 +1414,16 @@ return True def _addrevision(self, node, text, transaction, link, p1, p2, flags, - cachedelta, ifh, dfh, alwayscache=False): + cachedelta, ifh, dfh, alwayscache=False, raw=False): """internal function to add revisions to the log see addrevision for argument descriptions. invariants: - text is optional (can be None); if not set, cachedelta must be set. if both are set, they must correspond to each other. +- raw is optional; if set to True, it indicates the revision data is to + be treated by processflags() as raw. It is usually set by changegroup + generation and debug commands. s/processflags/_processflags/ That would prevent a small hunk to fix it in patch 3. """ btext = [text] def buildtext(): @@ -1438,8 +1443,9 @@ fh = ifh else: fh = dfh -basetext = self.revision(self.node(baserev), _df=fh) +basetext = self.revision(self.node(baserev), _df=fh, raw=raw) btext[0] = mdiff.patch(basetext, delta) + try: self.checkhash(btext[0], node, p1=p1, p2=p2) if flags & REVIDX_ISCENSORED: @@ -1668,10 +1674,14 @@ # the added revision, which will require a call to # revision(). revision() will fast path if there is a cache # hit. So, we tell _addrevision() to always cache in this case. +# We're only using addgroup() in the context of changegroup +# generation so the revision data can always be handled as raw +# by the flagprocessor. chain = self._addrevision(node, None, transaction, link, p1, p2, flags, (baserev, delta), ifh, dfh, - alwayscache=bool(addrevisioncb)) + alwayscache=bool(addrevisioncb), + raw=True) if addrevisioncb: addrevisioncb(self, chain) […] -- Pierre-Yves David ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 3] parser: make buildargsdict() precompute position where keyword args start
# HG changeset patch # User Yuya Nishihara# Date 1483942521 -32400 # Mon Jan 09 15:15:21 2017 +0900 # Node ID 95725b2c0e04033fbe0a54e1884fd347fdff18b2 # Parent c2bd2f77965b7d23d05575596e4b30c04d5d5adf parser: make buildargsdict() precompute position where keyword args start This prepares for adding *varargs support. See the next patch. diff --git a/mercurial/parser.py b/mercurial/parser.py --- a/mercurial/parser.py +++ b/mercurial/parser.py @@ -96,17 +96,18 @@ def buildargsdict(trees, funcname, keys, Invalid keywords or too many positional arguments are rejected, but missing arguments are just omitted. """ +kwstart = next((i for i, x in enumerate(trees) if x[0] == keyvaluenode), + len(trees)) if len(trees) > len(keys): raise error.ParseError(_("%(func)s takes at most %(nargs)d arguments") % {'func': funcname, 'nargs': len(keys)}) args = {} # consume positional arguments -for k, x in zip(keys, trees): -if x[0] == keyvaluenode: -break +for k, x in zip(keys, trees[:kwstart]): args[k] = x +assert len(args) == kwstart # remainder should be keyword arguments -for x in trees[len(args):]: +for x in trees[kwstart:]: if x[0] != keyvaluenode or x[1][0] != keynode: raise error.ParseError(_("%(func)s got an invalid argument") % {'func': funcname}) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 3] parser: extend buildargsdict() to support variable-length positional args
# HG changeset patch # User Yuya Nishihara# Date 1483943152 -32400 # Mon Jan 09 15:25:52 2017 +0900 # Node ID dff59b00d9a326d894244add8cf2b1bab99295a6 # Parent 95725b2c0e04033fbe0a54e1884fd347fdff18b2 parser: extend buildargsdict() to support variable-length positional args This can simplify the argument parsing of followlines(). Tests are added by the next patch. diff --git a/mercurial/parser.py b/mercurial/parser.py --- a/mercurial/parser.py +++ b/mercurial/parser.py @@ -90,22 +90,61 @@ class parser(object): return self.eval(t) return t -def buildargsdict(trees, funcname, keys, keyvaluenode, keynode): +def splitargspec(spec): +"""Parse spec of function arguments into (poskeys, varkey, keys) + +>>> splitargspec('') +([], None, []) +>>> splitargspec('foo bar') +([], None, ['foo', 'bar']) +>>> splitargspec('foo *bar baz') +(['foo'], 'bar', ['baz']) +>>> splitargspec('*foo') +([], 'foo', []) +""" +pre, sep, post = spec.partition('*') +pres = pre.split() +posts = post.split() +if sep: +if not posts: +raise error.ProgrammingError('no *varkey name provided') +return pres, posts[0], posts[1:] +return [], None, pres + +def buildargsdict(trees, funcname, argspec, keyvaluenode, keynode): """Build dict from list containing positional and keyword arguments -Invalid keywords or too many positional arguments are rejected, but -missing arguments are just omitted. +Arguments are specified by a tuple of ``(poskeys, varkey, keys)`` where + +- ``poskeys``: list of names of positional arguments +- ``varkey``: optional argument name that takes up remainder +- ``keys``: list of names that can be either positional or keyword arguments + +If ``varkey`` specified, all ``keys`` must be given as keyword arguments. + +Invalid keywords, too few positional arguments, or too many positional +arguments are rejected, but missing keyword arguments are just omitted. """ +poskeys, varkey, keys = argspec kwstart = next((i for i, x in enumerate(trees) if x[0] == keyvaluenode), len(trees)) -if len(trees) > len(keys): +if kwstart < len(poskeys): +raise error.ParseError(_("%(func)s takes at least %(nargs)d positional " + "arguments") + % {'func': funcname, 'nargs': len(poskeys)}) +if not varkey and len(trees) > len(poskeys) + len(keys): raise error.ParseError(_("%(func)s takes at most %(nargs)d arguments") - % {'func': funcname, 'nargs': len(keys)}) + % {'func': funcname, + 'nargs': len(poskeys) + len(keys)}) args = {} # consume positional arguments -for k, x in zip(keys, trees[:kwstart]): +for k, x in zip(poskeys, trees[:kwstart]): args[k] = x -assert len(args) == kwstart +if varkey: +args[varkey] = trees[len(args):kwstart] +else: +for k, x in zip(keys, trees[len(args):kwstart]): +args[k] = x # remainder should be keyword arguments for x in trees[kwstart:]: if x[0] != keyvaluenode or x[1][0] != keynode: diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -326,7 +326,7 @@ def getargs(x, min, max, err): return l def getargsdict(x, funcname, keys): -return parser.buildargsdict(getlist(x), funcname, keys.split(), +return parser.buildargsdict(getlist(x), funcname, parser.splitargspec(keys), keyvaluenode='keyvalue', keynode='symbol') def getset(repo, subset, x): ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 3] revset: parse variable-length arguments of followlines() by getargsdict()
# HG changeset patch # User Yuya Nishihara# Date 1483945376 -32400 # Mon Jan 09 16:02:56 2017 +0900 # Node ID 77a94bdad2684df83e0a5fc3646f144e03337c8c # Parent dff59b00d9a326d894244add8cf2b1bab99295a6 revset: parse variable-length arguments of followlines() by getargsdict() diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -1078,19 +1078,19 @@ def followlines(repo, subset, x): """ from . import context # avoid circular import issues -args = getargs(x, 3, 4, _("followlines takes at least three arguments")) +args = getargsdict(x, 'followlines', 'file *lines rev') +if len(args['lines']) != 2: +raise error.ParseError(_("followlines takes at least three arguments")) rev = '.' -if len(args) == 4: -revarg = getargsdict(args[3], 'followlines', 'rev') -if 'rev' in revarg: -revs = getset(repo, fullreposet(repo), revarg['rev']) -if len(revs) != 1: -raise error.ParseError( -_("followlines expects exactly one revision")) -rev = revs.last() - -pat = getstring(args[0], _("followlines requires a pattern")) +if 'rev' in args: +revs = getset(repo, fullreposet(repo), args['rev']) +if len(revs) != 1: +raise error.ParseError( +_("followlines expects exactly one revision")) +rev = revs.last() + +pat = getstring(args['file'], _("followlines requires a pattern")) if not matchmod.patkind(pat): fname = pathutil.canonpath(repo.root, repo.getcwd(), pat) else: @@ -1101,7 +1101,7 @@ def followlines(repo, subset, x): fname = files[0] try: -fromline, toline = [int(getsymbol(a)) for a in args[1:3]] +fromline, toline = [int(getsymbol(a)) for a in args['lines']] except ValueError: raise error.ParseError(_("line range bounds must be integers")) if toline - fromline < 0: diff --git a/tests/test-annotate.t b/tests/test-annotate.t --- a/tests/test-annotate.t +++ b/tests/test-annotate.t @@ -582,6 +582,15 @@ merge $ hg up 23 --quiet check error cases + $ hg log -r 'followlines()' + hg: parse error: followlines takes at least 1 positional arguments + [255] + $ hg log -r 'followlines(baz)' + hg: parse error: followlines takes at least three arguments + [255] + $ hg log -r 'followlines(baz, 1)' + hg: parse error: followlines takes at least three arguments + [255] $ hg log -r 'followlines(baz, 1, 2, rev=desc("b"))' hg: parse error: followlines expects exactly one revision [255] ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] zstd: fix compilation with Solaris Studio
On Mon, 9 Jan 2017 11:26:23 +0100, Pierre-Yves David wrote: > On 11/23/2016 03:45 AM, Yuya Nishihara wrote: > > On Tue, 22 Nov 2016 14:07:51 -0800, Gregory Szorc wrote: > >> On Tue, Nov 22, 2016 at 1:34 PM,wrote: > >>> # HG changeset patch > >>> # User Danek Duvall > >>> # Date 1479850325 28800 > >>> # Tue Nov 22 13:32:05 2016 -0800 > >>> # Node ID b09fb7f66e9e680358b8fb359be24a14fd6b3cfb > >>> # Parent 8836f13e3c5b8eae765372708b659c55a044cbb4 > >>> zstd: fix compilation with Solaris Studio > >>> > >>> Without these changes, Solaris Studio (12.4) gives us "syntax error: empty > >>> declaration" on these two lines. > >> > >> Doh. > >> > >> This patch LGTM. I've applied this upstream as well and it will be in the > >> next python-zstandard release. The canonical upstream is > >> https://github.com/indygreg/python-zstandard by the way (although I haven't > >> pushed the fix there yet). > > > > Queued this, thanks. > > > > Just for reference, this kind of error can be found by CFLAGS=-pedantic with > > gcc. > > Should we run our continuous integration build (or even default build) > with that option to catch such errors earlier? This wasn't actually an error so the CI might help catching compiler warnings but it wouldn't that important. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 3 of 3] chg: check type read from S channel
On Fri, 06 Jan 2017 11:22:32 -0800, Sean Farley wrote: > Jun Wuwrites: > > # HG changeset patch > > # User Jun Wu > > # Date 1483719292 0 > > # Fri Jan 06 16:14:52 2017 + > > # Node ID 779b9e867ff7f6e0c0b12e700195dff97408a16d > > # Parent 703fee4099efac592f6ae1c48bfebf806dfd95bf > > # Available At https://bitbucket.org/quark-zju/hg-draft > > # hg pull https://bitbucket.org/quark-zju/hg-draft -r > > 779b9e867ff7 > > chg: check type read from S channel > > > > The previous patch added the check server-side. This patch added it > > client-side. > > This seems like a good and fairly straight-forward refactor to me. > Thanks! Yeah, queued these, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] pager: wrap ui._runpager
On Mon, 9 Jan 2017 05:04:21 +, Jun Wu wrote: > Excerpts from Yuya Nishihara's message of 2017-01-08 09:02:13 +0900: > > On Fri, 6 Jan 2017 17:08:24 +, Jun Wu wrote: > > > # HG changeset patch > > > # User Jun Wu> > > # Date 1482711944 0 > > > # Mon Dec 26 00:25:44 2016 + > > > # Node ID 8e614304b040537dbc735acb6c3999a05efd258c > > > # Parent 011122b3b1c42374fb0489d107418e1be3665ca6 > > > # Available At https://bitbucket.org/quark-zju/hg-draft > > > # hg pull https://bitbucket.org/quark-zju/hg-draft -r > > > 8e614304b040 > > > pager: wrap ui._runpager > > > > > > As discussed at [1], ui._runpager will be the new low-level API accepting > > > a > > > pager command to actually run the pager. And ui.pager is the high-level > > > API > > > which reads config directly from self. > > > > > > This change is necessary for chgserver to override _runpager cleanly. > > > > > > > > > diff --git a/hgext/pager.py b/hgext/pager.py > > > --- a/hgext/pager.py > > > +++ b/hgext/pager.py > > > @@ -119,4 +119,10 @@ def uisetup(ui): > > > return > > > > > > +class pagerui(ui.__class__): > > > +def _runpager(self, pagercmd): > > > +_runpager(self, pagercmd) > > > + > > > +ui.__class__ = pagerui > > > > The change looks okay, but I should note that there might be a uisetup() > > battle > > if we're planning to delay uisetup() and extsetup() until the 2nd dispatch() > > called by chgserver.runcommand(), where ui._runpager() would be overridden > > by > > chg beforehand. > > The plan is as follows: > > 1. For the current situation (pager is not in core), > pager will be aware of chg wrapped ui - which means pager will not > wrap ui if it sees hasattr(ui, '_runpager'). > 2. In the future, when _runpager is defined in ui.py, no special if > condition will be needed. Ah, sounds good. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] revset: introduce the summary predicate
On 01/08/2017 09:34 PM, Matt Harbison wrote: On Sun, 08 Jan 2017 07:59:36 -0500, Pierre-Yves Davidwrote: (ha, I wrote my previous reply in a train and it got sent when I connected again (and received that one). I'm going to try to adress the new content in this email and sometime repeat some of my other reply content for clarity) On 01/08/2017 04:23 AM, Matt Harbison wrote: On Sat, 07 Jan 2017 02:56:48 -0500, Yuya Nishihara wrote: On Fri, 6 Jan 2017 21:29:43 -0500, Matt Harbison wrote: > On Jan 6, 2017, at 11:19 AM, Pierre-Yves David wrote: >> On 01/04/2017 07:04 PM, Matt Harbison wrote: >> # HG changeset patch >> # User Matt Harbison >> # Date 1483550016 18000 >> # Wed Jan 04 12:13:36 2017 -0500 >> # Node ID 76d95ab94b9e206363629059fb7824002e19a9e5 >> # Parent 0064a1eb28e246ded9b726c696d048143d1b23f1 >> revset: introduce the summary predicate >> Perhaps stringmatcher can have 3 types, icase literal, literal, and re, and the default of desc() is icase literal for backward compatibility. You can build a case-insensitive regexp object from a literal pattern. https://docs.python.org/2/library/re.html#re.I Yep, that's the API I was thinking of. I'm confused by the rest of your comments. When I first skimmed your message, adding support for 'icasere:' using this API popped into my mind. And that could support a case insensitive literal, because 'icasere:foo' should be equivalent to looking for the substring 'foo' (leaving aside efficiency, how discoverable that is, and that stringmatcher matches the whole string for literals). But you seem to be suggesting adding 'icaseliteral:'. I'm not 100% sure of what Yuya actually has in mind but here is my understanding of the situation and how we could move forward. Currently: -- desc(X) → X is customly matched as a case insensitive litteral, We have a "generic" pattern definition syntax used by various other reveset (implemented in "stringmatcher") foo(X) → X is matched as a case sensitive litteral foo('literal:X') → X is matched as a case sensitive literal (same as the above) food('re:X') → X is matched as a regular expression (case sensitive) Proposal: (might be what yuya says) - extend the string matcher to foo('literal:X') → X is matched as a case sensitive literal See the comment in the new patch I sent about 'user()' already lowercasing 'literal:' and 're:'. I'd consider it a bug, but it's been in since mid 2012. Attempting to channel Matt, I'm guessing we are stuck with that since it is so old, but wanted to see what others think. 1) Yep, we are stuck with whatever existing behavior we have for existing predicate because of BC. (but we can augment it) 2) Congratulation you seems to have unearthed an area where we have many predicated with close but slightly different behavior. At that point I'll ask you an inventory of what we currently have so that we can devise a sound and as consistent as possible way forward. Can you provide us with a table that at least keep track of: * predicate * default behavior * support 'rich' stringmatcher ? * are 'literal:' case sensitive ? * are 're:' case sensitive (and supported at all) ? From there we'll be able to see if a pattern emerge and pick the best way to move forward. foo('icase-literal:X') → X is matched as a case insensitive literal food('re:X') → X is matched as a regular expression (case sensitive) Then, desc move to use string matcher (default to "icase-literal"). We do not need a 'icase-re:' spec, because one can easily achieve it using 're:(?i)foo' Ah! I missed the part in the docs where flags could be set in the string with (?). I thought you needed to compile with re.FLAG. When he said string literal, my mind went right to the 'literal:' prefix. Agreed, no need for 'icase-re:'. Someone getting slightly confused with regular expression? Impossible! ;-) […] I'm about to submit a patch to add the current 're:' support to 'desc' in the meantime, to hopefully move this along. Great! I'd also be curious if you have thoughts on how to conditionally limit this predicate to the first line, without limiting future functionality. So having digged the regexp part a bit more, it seems like one could just use 're:^.*issue1337' to match "issue1337" on the first line ('.' does not match new-line by default). Thanks for looking at that. It's way less horrible than I thought it would be. I'm curious what Sean thinks, since he mentioned {firstline} being put in as a substitute for a complex regex. I'd be fine with skipping the firstline=True param if this case is mentioned in the help for desc(). I've missed that '{firstline}' proposal from Sean, can you point me at it? (or summarize it ?) Thanks a lot for looking into this! Cheers, -- Pierre-Yves David
Re: [PATCH V3] rebase: fail-fast the pull if working dir is not clean (BC)
On 01/09/2017 05:27 AM, timeless wrote: Gregory Szorc wrote: Your reasoning about users wanting extra context to help them debug is sound. But I'm surprised nobody mentioned that the "error.Abort" exception takes an optional keyword "hint" argument that prints an extra message to provide that context. When we know why an abort occurred and/or what actions can be taken to prevent it, the "hint" message should provide that context. +1 Actually, I did mention we should augment 'checkunfinished()' and 'bailifchanged()' to be able to provide more context ;-) So +1 for improving these too (but as mentioned in my initial reply, that's a scope bloat so I too the debug version for now). (third paragraph of https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-January/092041.html ) Cheers, -- Pierre-Yves David ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] zstd: fix compilation with Solaris Studio
On 11/23/2016 03:45 AM, Yuya Nishihara wrote: On Tue, 22 Nov 2016 14:07:51 -0800, Gregory Szorc wrote: On Tue, Nov 22, 2016 at 1:34 PM,wrote: # HG changeset patch # User Danek Duvall # Date 1479850325 28800 # Tue Nov 22 13:32:05 2016 -0800 # Node ID b09fb7f66e9e680358b8fb359be24a14fd6b3cfb # Parent 8836f13e3c5b8eae765372708b659c55a044cbb4 zstd: fix compilation with Solaris Studio Without these changes, Solaris Studio (12.4) gives us "syntax error: empty declaration" on these two lines. Doh. This patch LGTM. I've applied this upstream as well and it will be in the next python-zstandard release. The canonical upstream is https://github.com/indygreg/python-zstandard by the way (although I haven't pushed the fix there yet). Queued this, thanks. Just for reference, this kind of error can be found by CFLAGS=-pedantic with gcc. Should we run our continuous integration build (or even default build) with that option to catch such errors earlier? Cheers, -- Pierre-Yves David ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel