[PATCH 1 of 2] serve: add support for Mercurial subrepositories
# HG changeset patch # User Matt Harbison # Date 1486875517 18000 # Sat Feb 11 23:58:37 2017 -0500 # Node ID eb928f06946008029568abd1ef8491ded316fc31 # Parent a95fc01aaffe805bcc4c02a822b82a1162fa35b9 serve: add support for Mercurial subrepositories I've been using `hg serve --web-conf ...` with a simple '/=projects/**' [paths] configuration for awhile without issue. Let's ditch the need for the manual configuration in this case, and limit the repos served to the actual subrepos. This doesn't attempt to handle the case where a new subrepo appears while the server is running. That could probably be handled with a hook if somebody wants it. But it's such a rare case, it probably doesn't matter for the temporary serves. Unfortunately, the root of the webserver when serving multiple repos is the html index file. This makes the URL different for `hg serve` vs `hg serve -S`, because the top level repo then needs to be part of the path. That will be fixed next. The web.staticurl config is set, because the icons served up are already visible by default when -S isn't given. I assume this is a difference between hgweb and hgwebdir, but there's no reason for the user to be exposed to this. As an aside, the help for web.staticurl seems to wrongly describe the value of this setting. diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -2294,6 +2294,15 @@ bad.extend(f for f in rejected if f in match.files()) return bad +def addwebdirpath(repo, serverpath, webconf): +webconf[serverpath] = repo.root +repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root)) + +for r in repo.revs('filelog("path:.hgsub")'): +ctx = repo[r] +for subpath in ctx.substate: +ctx.sub(subpath).addwebdirpath(serverpath, webconf) + def forget(ui, repo, match, prefix, explicitonly): join = lambda f: os.path.join(prefix, f) bad = [] diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -5787,7 +5787,8 @@ ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')), ('', 'style', '', _('template style to use'), _('STYLE')), ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')), -('', 'certificate', '', _('SSL certificate file'), _('FILE'))], +('', 'certificate', '', _('SSL certificate file'), _('FILE'))] + + subrepoopts, _('[OPTION]...'), optionalrepo=True) def serve(ui, repo, **opts): diff --git a/mercurial/help/subrepos.txt b/mercurial/help/subrepos.txt --- a/mercurial/help/subrepos.txt +++ b/mercurial/help/subrepos.txt @@ -136,6 +136,11 @@ subrepository changes are available when referenced by top-level repositories. Push is a no-op for Subversion subrepositories. +:serve: serve does not recurse into subrepositories unless +-S/--subrepos is specified. Git and Subversion subrepositories +are currently silently ignored. Mercurial subrepositories with a +URL source are also silently ignored. + :status: status does not recurse into subrepositories unless -S/--subrepos is specified. Subrepository changes are displayed as regular Mercurial changes on the subrepository diff --git a/mercurial/server.py b/mercurial/server.py --- a/mercurial/server.py +++ b/mercurial/server.py @@ -16,6 +16,7 @@ from . import ( chgserver, +cmdutil, commandserver, error, hgweb, @@ -135,11 +136,31 @@ baseui = ui webconf = opts.get('web_conf') or opts.get('webdir_conf') if webconf: +if opts.get('subrepos'): +raise error.Abort(_('--web-conf cannot be used with --subrepos')) + # load server settings (e.g. web.port) to "copied" ui, which allows # hgwebdir to reload webconf cleanly servui = ui.copy() servui.readconfig(webconf, sections=['web']) alluis.add(servui) +elif opts.get('subrepos'): +servui = ui.copy() +alluis.add(servui) + +# If repo is None, hgweb.createapp() already raises a proper abort +# message as long as webconf is None. +if repo: +webconf = dict() +cmdutil.addwebdirpath(repo, repo.wvfs.basename(repo.root) + '/', + webconf) + +# The icons aren't rendered in a web browser without this. +# Unfortunately, the pages generated aren't sensitive to this +# config, so it can't be set to something else if there's a repo +
[PATCH 2 of 2] serve: make the URL the same for `hg serve` and `hg serve -S`
# HG changeset patch # User Matt Harbison # Date 1486877030 18000 # Sun Feb 12 00:23:50 2017 -0500 # Node ID d91a0fe8016deaca3134f119bd07f99cd96cf43d # Parent eb928f06946008029568abd1ef8491ded316fc31 serve: make the URL the same for `hg serve` and `hg serve -S` It's perfectly workable to serve up the parent repo without the -S for push and pull, as long as there are no subrepo changes are in play. Therefore, having a different URL for the main repo based on the presence of this option seems like it would get annoying. diff --git a/mercurial/hgweb/__init__.py b/mercurial/hgweb/__init__.py --- a/mercurial/hgweb/__init__.py +++ b/mercurial/hgweb/__init__.py @@ -85,9 +85,9 @@ def run(self): self.httpd.serve_forever() -def createapp(baseui, repo, webconf): +def createapp(baseui, repo, webconf, subrepos=False): if webconf: -return hgwebdir_mod.hgwebdir(webconf, baseui=baseui) +return hgwebdir_mod.hgwebdir(webconf, baseui=baseui, subrepos=subrepos) else: if not repo: raise error.RepoError(_("there is no Mercurial repository" diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -115,12 +115,13 @@ Instances are typically used as WSGI applications. """ -def __init__(self, conf, baseui=None): +def __init__(self, conf, baseui=None, subrepos=False): self.conf = conf self.baseui = baseui self.ui = None self.lastrefresh = 0 self.motd = None +self._subrepos = subrepos self.refresh() def refresh(self): @@ -254,7 +255,7 @@ return [] # top-level index -elif not virtual: +elif not virtual and not self._subrepos: req.respond(HTTP_OK, ctype) return self.makeindex(req, tmpl) @@ -262,8 +263,9 @@ repos = dict(self.repos) virtualrepo = virtual -while virtualrepo: -real = repos.get(virtualrepo) +real = repos.get(virtualrepo) + +while virtualrepo or self._subrepos: if real: req.env['REPO_NAME'] = virtualrepo try: @@ -280,6 +282,7 @@ if up < 0: break virtualrepo = virtualrepo[:up] +real = repos.get(virtualrepo) # browse subdirectories subdir = virtual + '/' diff --git a/mercurial/server.py b/mercurial/server.py --- a/mercurial/server.py +++ b/mercurial/server.py @@ -152,12 +152,11 @@ # message as long as webconf is None. if repo: webconf = dict() -cmdutil.addwebdirpath(repo, repo.wvfs.basename(repo.root) + '/', - webconf) +cmdutil.addwebdirpath(repo, "", webconf) # The icons aren't rendered in a web browser without this. # Unfortunately, the pages generated aren't sensitive to this -# config, so it can't be set to something else if there's a repo +# config, so it can't be set to something else if there's a subrepo # named 'static'. if 'static' not in webconf: baseui.setconfig('web', 'staticurl', 'static', source='serve') @@ -173,7 +172,7 @@ for u in alluis: u.setconfig("web", o, val, 'serve') -app = hgweb.createapp(baseui, repo, webconf) +app = hgweb.createapp(baseui, repo, webconf, opts.get('subrepos')) return hgweb.httpservice(servui, app, opts) def createservice(ui, repo, opts): diff --git a/tests/test-subrepo-deep-nested-change.t b/tests/test-subrepo-deep-nested-change.t --- a/tests/test-subrepo-deep-nested-change.t +++ b/tests/test-subrepo-deep-nested-change.t @@ -75,29 +75,29 @@ #if serve $ hg serve -R main --debug -S -p $HGPORT -d --pid-file=hg1.pid -E error.log -A access.log - adding main/ = $TESTTMP/main (glob) - adding sub1/ = $TESTTMP/main/sub1 (glob) - adding sub2/ = $TESTTMP/main/sub1/sub2 (glob) + adding = $TESTTMP/main (glob) + adding ../sub1/ = $TESTTMP/main/sub1 (glob) + adding ../sub2/ = $TESTTMP/main/sub1/sub2 (glob) listening at http://*:$HGPORT/ (bound to *:$HGPORT) (glob) - adding main/ = $TESTTMP/main (glob) - adding sub1/ = $TESTTMP/main/sub1 (glob) - adding sub2/ = $TESTTMP/main/sub1/sub2 (glob) + adding = $TESTTMP/main (glob) + adding ../sub1/ = $TESTTMP/main/sub1 (glob) + adding ../sub2/ = $TESTTMP/main/sub1/sub2 (glob) $ cat hg1.pid >> $DAEMON_PIDS - $ hg clone http://localhost:$HGPORT/main httpclone --config progress.disable=True + $ hg clone http://localhost:$HGPORT h
[PATCH 2 of 4 V2] clone: use the HTTP 301 location to record the default path
# HG changeset patch # User Matt Harbison # Date 1487087965 18000 # Tue Feb 14 10:59:25 2017 -0500 # Node ID 27a4bc77e8b8e50abc76c387f117082e5853c47e # Parent 4f2862487d789edc1f36b5687d828a2914e1dc32 clone: use the HTTP 301 location to record the default path This is needed to simplify making `hg serve -S` paths the same as `hg serve`. Since 301 is permanent and cachable, this is arguably the proper behavior anyway. For example, once Firefox sees a 301, it automatically forwards, without querying the original URL again. Code hosting software may make use of redirects. I only have access to SCM Manager. It uses 302 to access subrepos, so it isn't affected by this. My understanding of the python libraries being used is minimal, and this was inspired by http://www.diveintopython.net/http_web_services/redirects.html. Since `hg serve` doesn't issue redirects, the added tests aren't showing the new redirect functionality yet. But they set a baseline that won't change when redirects are issued. Check-commit complains about the methods with '_', but those names are defined by python. diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -621,6 +621,15 @@ destrepo = destpeer.local() if destrepo: +# Update for 301 redirects +endsrc = srcpeer.url() +if not islocal(endsrc): +abspath = endsrc + +# statichttprepository never sees the 'static-' prefix, so that +# need to be accounted for here. +if origsource.startswith('static-http'): +abspath = 'static-' + abspath template = uimod.samplehgrcs['cloned'] fp = destrepo.vfs("hgrc", "w", text=True) u = util.url(abspath) diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py --- a/mercurial/httppeer.py +++ b/mercurial/httppeer.py @@ -88,12 +88,12 @@ (u.query or u.fragment)) # urllib cannot handle URLs with embedded user or passwd -self._url, authinfo = u.authinfo() +self._url, self._authinfo = u.authinfo() self.ui = ui self.ui.debug('using %s\n' % self._url) -self.urlopener = url.opener(ui, authinfo) +self.urlopener = url.opener(ui, self._authinfo) self.requestbuilder = urlreq.request def __del__(self): @@ -230,6 +230,16 @@ if self._url.rstrip('/') != resp_url.rstrip('/'): if not self.ui.quiet: self.ui.warn(_('real URL is %s\n') % resp_url) +if resp.status == httplib.MOVED_PERMANENTLY: +u = util.url(resp_url.rstrip('/')) + +# The path has auth info on creation. Restore that here. +creds = self._authinfo +if creds: +u.user = creds[2] +u.passwd = creds[3] or None +self.path = str(u) + self._url = resp_url try: proto = resp.getheader('content-type') diff --git a/mercurial/pycompat.py b/mercurial/pycompat.py --- a/mercurial/pycompat.py +++ b/mercurial/pycompat.py @@ -227,6 +227,7 @@ "HTTPDigestAuthHandler", "HTTPHandler", "HTTPPasswordMgrWithDefaultRealm", +"HTTPRedirectHandler", "HTTPSHandler", "install_opener", "ProxyHandler", diff --git a/mercurial/url.py b/mercurial/url.py --- a/mercurial/url.py +++ b/mercurial/url.py @@ -272,6 +272,30 @@ return False +class httpredirecthandler(urlreq.httpredirecthandler): +def __init__(self): +self._permmoved = True + +def redirect_request(self, req, fp, code, msg, hdrs, newurl): +'''Called by all http_error_3xx() to monitor redirect types seen''' +# Avoid treating 302 -> 301 -> 200 or 301 -> 302 -> 200 as permanent +# redirects. +self._permmoved = self._permmoved and code == httplib.MOVED_PERMANENTLY + +impl = urlreq.httpredirecthandler.redirect_request +return impl(self, req, fp, code, msg, hdrs, newurl) + +def http_error_301(self, req, fp, code, msg, headers): +'''Capture the permanent redirect status for later access''' +impl = urlreq.httpredirecthandler.http_error_301 +result = impl(self, req, fp, code, msg, headers) + +# For an unbroken chain of 301, indicate 301 in the status. Otherwise, +# keep the 200 status. +if self._permmoved: +result.status = code +return result + class httphandler(keepalive.HTTPHandler): def http_open(self, req): return self.do_open(httpconnection, req) @@ -43
[PATCH 4 of 4 V2] serve: restore the index file for `hg serve -S`
# HG changeset patch # User Matt Harbison # Date 1487129917 18000 # Tue Feb 14 22:38:37 2017 -0500 # Node ID 3a0c0f139204e6fa86af22c1d54d8c1dd7a4aa2b # Parent 38babd487181374325f3d27c5bc081dadf31b9b9 serve: restore the index file for `hg serve -S` There's currently no integration of subrepos into the browsable directory listing for the parent repo, so this is a nice to have. The redirect is only necessary for a Mercurial client. The comment in mercurial.url.opener() seems to indicate that the 'Accept' header will always be around for BC. Another option to detect a Mercurial client is to check the Request URI for the capabilities command. diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -255,10 +255,11 @@ staticfile(static, fname, req) return [] -# top-level index +# top-level index, or HTTP_MOVED_PERMANENTLY for a Mercurial client +# when the server is invoked with --subrepos. elif not virtual: -if self._rootrepo: -# Redirect '/' to the main repo when -S is given. +accept = req.env.get('HTTP_ACCEPT', "") +if self._rootrepo and accept == 'application/mercurial-0.1': path = '/' + self._rootrepo if self.prefix: path = '/' + self.prefix + path diff --git a/tests/test-subrepo-recursion.t b/tests/test-subrepo-recursion.t --- a/tests/test-subrepo-recursion.t +++ b/tests/test-subrepo-recursion.t @@ -295,6 +295,10 @@ z2 z3 + $ wget -q http://localhost:$HGPORT + $ cat index.html | grep '' + Mercurial repositories index + $ cat access.log * "GET /?cmd=capabilities HTTP/1.1" 301 - (glob) * "GET /repo HTTP/1.1" 200 - (glob) @@ -308,9 +312,10 @@ * "GET /repo/foo/bar?cmd=capabilities HTTP/1.1" 200 - (glob) * "GET /repo/foo/bar?cmd=batch HTTP/1.1" 200 - * (glob) * "GET /repo/foo/bar?cmd=getbundle HTTP/1.1" 200 - * (glob) + * "GET / HTTP/1.0" 200 - (glob) $ killdaemons.py - $ rm hg1.pid error.log access.log + $ rm hg1.pid error.log access.log index.html $ cd repo #endif ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 4 V2] serve: add support for Mercurial subrepositories
# HG changeset patch # User Matt Harbison # Date 1486875517 18000 # Sat Feb 11 23:58:37 2017 -0500 # Node ID 4f2862487d789edc1f36b5687d828a2914e1dc32 # Parent afaf3c2b129c8940387fd9928ae4fdc28259d13c serve: add support for Mercurial subrepositories I've been using `hg serve --web-conf ...` with a simple '/=projects/**' [paths] configuration for awhile without issue. Let's ditch the need for the manual configuration in this case, and limit the repos served to the actual subrepos. This doesn't attempt to handle the case where a new subrepo appears while the server is running. That could probably be handled with a hook if somebody wants it. But it's such a rare case, it probably doesn't matter for the temporary serves. Unfortunately, the root of the webserver when serving multiple repos is the html index file. This makes the URL different for `hg serve` vs `hg serve -S`, because the top level repo then needs to be part of the path. That can be fixed later. diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -2294,6 +2294,15 @@ bad.extend(f for f in rejected if f in match.files()) return bad +def addwebdirpath(repo, serverpath, webconf): +webconf[serverpath] = repo.root +repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root)) + +for r in repo.revs('filelog("path:.hgsub")'): +ctx = repo[r] +for subpath in ctx.substate: +ctx.sub(subpath).addwebdirpath(serverpath, webconf) + def forget(ui, repo, match, prefix, explicitonly): join = lambda f: os.path.join(prefix, f) bad = [] diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -4607,7 +4607,8 @@ ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')), ('', 'style', '', _('template style to use'), _('STYLE')), ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')), -('', 'certificate', '', _('SSL certificate file'), _('FILE'))], +('', 'certificate', '', _('SSL certificate file'), _('FILE'))] + + subrepoopts, _('[OPTION]...'), optionalrepo=True) def serve(ui, repo, **opts): diff --git a/mercurial/help/subrepos.txt b/mercurial/help/subrepos.txt --- a/mercurial/help/subrepos.txt +++ b/mercurial/help/subrepos.txt @@ -136,6 +136,11 @@ subrepository changes are available when referenced by top-level repositories. Push is a no-op for Subversion subrepositories. +:serve: serve does not recurse into subrepositories unless +-S/--subrepos is specified. Git and Subversion subrepositories +are currently silently ignored. Mercurial subrepositories with a +URL source are also silently ignored. + :status: status does not recurse into subrepositories unless -S/--subrepos is specified. Subrepository changes are displayed as regular Mercurial changes on the subrepository diff --git a/mercurial/server.py b/mercurial/server.py --- a/mercurial/server.py +++ b/mercurial/server.py @@ -16,6 +16,7 @@ from . import ( chgserver, +cmdutil, commandserver, error, hgweb, @@ -135,11 +136,24 @@ baseui = ui webconf = opts.get('web_conf') or opts.get('webdir_conf') if webconf: +if opts.get('subrepos'): +raise error.Abort(_('--web-conf cannot be used with --subrepos')) + # load server settings (e.g. web.port) to "copied" ui, which allows # hgwebdir to reload webconf cleanly servui = ui.copy() servui.readconfig(webconf, sections=['web']) alluis.add(servui) +elif opts.get('subrepos'): +servui = ui.copy() +alluis.add(servui) + +# If repo is None, hgweb.createapp() already raises a proper abort +# message as long as webconf is None. +if repo: +webconf = dict() +cmdutil.addwebdirpath(repo, repo.wvfs.basename(repo.root) + '/', + webconf) else: servui = ui diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -438,6 +438,15 @@ self._ctx = ctx self._path = path +def addwebdirpath(self, serverpath, webconf): +"""Add the hgwebdir entries for this subrepo, and any of its subrepos. + +``serverpath`` is the path component of the URL for this repo. + +``webconf`` is the dictionary of hgwebdir entries. +""" +pass + def storeclean(self, path): ""
[PATCH 3 of 4 V2] serve: make the URL the same for `hg serve` and `hg serve -S`
# HG changeset patch # User Matt Harbison # Date 1486877030 18000 # Sun Feb 12 00:23:50 2017 -0500 # Node ID 38babd487181374325f3d27c5bc081dadf31b9b9 # Parent 27a4bc77e8b8e50abc76c387f117082e5853c47e serve: make the URL the same for `hg serve` and `hg serve -S` It's perfectly workable to serve up the parent repo without the -S for push and pull, as long as there are no subrepo changes are in play. Therefore, having a different URL for the main repo based on the presence of this option seems like it would get annoying. The first attempt at this was simply to trim the outer repo name from the paths when populating 'webconf', so that the root repository was actually hosted at '/'. That worked fine for `hg` operations, but had bad effects on the html, such as making the 'changeset' link on the left side simply 'rev/tip'. (The source html shows the link was '//rev/tip', since {repo} was subbed in as an empty string.) There were also issues rendering the subrepo pages that ended with 'tip', including missing icons. By forwarding the `hg` request for the outer repo, all of the actual repositories can remain in their normal places. The forward needs to be permanent, so that the actual address is stored in the hgrc file. This is crucial, because the .hgsub source paths are evaluated relative to the parent repo's source. This avoids having to figure out how to put in forwarding logic for each subrepository as well. diff --git a/mercurial/hgweb/__init__.py b/mercurial/hgweb/__init__.py --- a/mercurial/hgweb/__init__.py +++ b/mercurial/hgweb/__init__.py @@ -85,9 +85,13 @@ def run(self): self.httpd.serve_forever() -def createapp(baseui, repo, webconf): +def createapp(baseui, repo, webconf, subrepos=False): if webconf: -return hgwebdir_mod.hgwebdir(webconf, baseui=baseui) +rootrepo = None +if subrepos: +rootrepo = repo.wvfs.basename(repo.root) + +return hgwebdir_mod.hgwebdir(webconf, baseui=baseui, rootrepo=rootrepo) else: if not repo: raise error.RepoError(_("there is no Mercurial repository" diff --git a/mercurial/hgweb/common.py b/mercurial/hgweb/common.py --- a/mercurial/hgweb/common.py +++ b/mercurial/hgweb/common.py @@ -23,6 +23,7 @@ httpserver = util.httpserver HTTP_OK = 200 +HTTP_MOVED_PERMANENTLY = 301 HTTP_NOT_MODIFIED = 304 HTTP_BAD_REQUEST = 400 HTTP_UNAUTHORIZED = 401 diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -16,6 +16,7 @@ from .common import ( ErrorResponse, +HTTP_MOVED_PERMANENTLY, HTTP_NOT_FOUND, HTTP_OK, HTTP_SERVER_ERROR, @@ -115,12 +116,13 @@ Instances are typically used as WSGI applications. """ -def __init__(self, conf, baseui=None): +def __init__(self, conf, baseui=None, rootrepo=None): self.conf = conf self.baseui = baseui self.ui = None self.lastrefresh = 0 self.motd = None +self._rootrepo = rootrepo self.refresh() def refresh(self): @@ -255,6 +257,15 @@ # top-level index elif not virtual: +if self._rootrepo: +# Redirect '/' to the main repo when -S is given. +path = '/' + self._rootrepo +if self.prefix: +path = '/' + self.prefix + path +req.headers.append(('Location', path)) +html = 'Moved here.' +req.respond(HTTP_MOVED_PERMANENTLY, "text/html", body=html) +return [] req.respond(HTTP_OK, ctype) return self.makeindex(req, tmpl) diff --git a/mercurial/server.py b/mercurial/server.py --- a/mercurial/server.py +++ b/mercurial/server.py @@ -166,7 +166,7 @@ for u in alluis: u.setconfig("web", o, val, 'serve') -app = hgweb.createapp(baseui, repo, webconf) +app = hgweb.createapp(baseui, repo, webconf, opts.get('subrepos')) return hgweb.httpservice(servui, app, opts) def createservice(ui, repo, opts): diff --git a/tests/test-subrepo-deep-nested-change.t b/tests/test-subrepo-deep-nested-change.t --- a/tests/test-subrepo-deep-nested-change.t +++ b/tests/test-subrepo-deep-nested-change.t @@ -84,7 +84,8 @@ adding sub2/ = $TESTTMP/main/sub1/sub2 (glob) $ cat hg1.pid >> $DAEMON_PIDS - $ hg clone http://user@localhost:$HGPORT/main httpclone --config progress.disable=True + $ hg clone http://user@localhost:$HGPORT httpclone --config progress.disable=True + real URL is http://localhost:$HGPORT/main requesting all changes adding changesets adding manifests @@ -111,7 +112,10 @@
Re: [PATCH 2 of 4 V2] clone: use the HTTP 301 location to record the default path
On Mon, 20 Feb 2017 09:33:05 -0500, Yuya Nishihara wrote: On Thu, 16 Feb 2017 16:41:09 -0500, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1487087965 18000 # Tue Feb 14 10:59:25 2017 -0500 # Node ID 27a4bc77e8b8e50abc76c387f117082e5853c47e # Parent 4f2862487d789edc1f36b5687d828a2914e1dc32 clone: use the HTTP 301 location to record the default path @@ -230,6 +230,16 @@ if self._url.rstrip('/') != resp_url.rstrip('/'): if not self.ui.quiet: self.ui.warn(_('real URL is %s\n') % resp_url) +if resp.status == httplib.MOVED_PERMANENTLY: +u = util.url(resp_url.rstrip('/')) + +# The path has auth info on creation. Restore that here. +creds = self._authinfo +if creds: +u.user = creds[2] +u.passwd = creds[3] or None +self.path = str(u) I didn't carefully review this patch, but is it safe to reuse the credential for redirected server? Hmmm.. Maybe not. At least for the clone path, it isn't even necessary, because the password is removed before writing out the hgrc file. I didn't see that until after I added this, and then forgot to remove it. The username is stored in the hgrc file though. It looks like url.passwordmgr stores the username/password, but I don't have a handy setup that will password prompt and redirect to see if that info can easily be obtained here. I have no problem with dropping the 'if creds' (and related changes not shown here) bits. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 4 V2] serve: add support for Mercurial subrepositories
On Mon, 20 Feb 2017 09:27:44 -0500, Yuya Nishihara wrote: On Thu, 16 Feb 2017 16:41:08 -0500, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1486875517 18000 # Sat Feb 11 23:58:37 2017 -0500 # Node ID 4f2862487d789edc1f36b5687d828a2914e1dc32 # Parent afaf3c2b129c8940387fd9928ae4fdc28259d13c serve: add support for Mercurial subrepositories I've been using `hg serve --web-conf ...` with a simple '/=projects/**' [paths] configuration for awhile without issue. Let's ditch the need for the manual configuration in this case, and limit the repos served to the actual subrepos. This doesn't attempt to handle the case where a new subrepo appears while the server is running. That could probably be handled with a hook if somebody wants it. But it's such a rare case, it probably doesn't matter for the temporary serves. Unfortunately, the root of the webserver when serving multiple repos is the html index file. This makes the URL different for `hg serve` vs `hg serve -S`, because the top level repo then needs to be part of the path. That can be fixed later. I'm puzzled by this new version which extensively relies on somewhat magical HTTP redirection. Instead, can't we fix hgwebdir to be able to host hgweb at '/' URL, and add explicit URL to show the index page hidden by it? This patch is the same as the first in V1, except that I dropped forcing the web.staticurl config, and I globbed away a bunch of the http parameters in the tests, since only the URI and status is of interest. The first version did host the parent at '/', and the subrepos relative to it. I switched from that, not because of the index hiding, but because of all the problems I ran into. First were problems (I don't remember all of the details, but eventually managed to fix) with `hg` commands. And then I noticed that the initial repo view wasn't rendering properly in the browser. There was output from the server like this: 127.0.0.1 - - [20/Feb/2017 21:02:36] "GET / HTTP/1.1" 200 - 127.0.0.1 - - [20/Feb/2017 21:02:42] "GET /favicon.ico HTTP/1.1" 404 - That seemed to be fixed by the staticurl config. I was also able to load "http://localhost:8000/subrepo"; and get it to display properly, so I submitted it. But I waved Augie off because then I noticed more problems in the browser: - At http://localhost:8000, the links on the left side were corrupt (graph is simply 'graph/tip', tags is 'http://tags', etc.) The pattern seemed to be that things ending in 'tip' are relative URLs, and the rest get an http: prefix. It looks from the sources like it is just a matter of '/' not translating for the {repo} template. - At http://localhost:8000/subrepo, all of the links on the left look proper. But if you click on one that ends in 'tip' (like 'graph'), the page doesn't render properly (like when 'staticurl' wasn't set on the parent repo). It does properly render pages that don't end in 'tip', like 'branches'. I also had a different failed attempt at hosting the parent at '/' a few years ago, which had the same rendering issues. And I didn't check anything other than paper. All in all, a week or so of nonstop problems convinced me that I was going about this the wrong way. To me, the benefits of this series over the original is: 1) The repos aren't moved, and therefore don't incur these subtle bugs 2) These changes are totally isolated to subrepo serving, so there should be no risk to mainstream hgweb usage 3) This is completely compatible with existing serves with a simple '/=$projects_dir/**' config file, because the real repos are not anchored to '/'. That will be useful without subrepos. Currently we can't see the index page '/foo' if we have a repository '/foo' and '/foo/bar'. I actually wondered why there wasn't an explicit index.html handled where needed, and maybe a redirect to it. I don't think doing that is incompatible with this series though. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 3 of 4 V2] serve: make the URL the same for `hg serve` and `hg serve -S`
On Mon, 20 Feb 2017 09:38:13 -0500, Yuya Nishihara wrote: On Thu, 16 Feb 2017 16:41:10 -0500, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1486877030 18000 # Sun Feb 12 00:23:50 2017 -0500 # Node ID 38babd487181374325f3d27c5bc081dadf31b9b9 # Parent 27a4bc77e8b8e50abc76c387f117082e5853c47e serve: make the URL the same for `hg serve` and `hg serve -S` elif not virtual: +if self._rootrepo: +# Redirect '/' to the main repo when -S is given. +path = '/' + self._rootrepo +if self.prefix: +path = '/' + self.prefix + path +req.headers.append(('Location', path)) +html = 'Moved here.' +req.respond(HTTP_MOVED_PERMANENTLY, "text/html", body=html) +return [] Suppose "hg serve" is used for temporarily serving random repositories, 301 seems too strong. The temporary serve is the case that I'm interested in. It may not be clear from this snippet, but the redirect is only reachable when using `hg serve -S`, not random repos listed in a --web-conf file. I guess I didn't think it was too strong, because the repo never is at '/'. Once the `hg serve` process is killed, everything is gone. Everything goes away eventually. But until then, it's a permanent redirect. The temporary/permanent distinction is important, because there needs to be a trigger to update paths.default in hgrc without doing so for temporary redirects. The updated hgrc path is important, because the subrepo is cloned relative to the parent repo's paths.default value. (Keeping both the sub=sub and sub=../sub style paths working in the two new tests were one of the many headaches with this.) Since nothing other than hg clients should see the redirect, do you have a specific concern? (I haven't paid much attention to chg to know if it would somehow cache the URL and get directed wrong when `hg serve` is killed and something else is served. But the aggressive caching done by web browsers is why I limited the redirect as narrowly as possible.) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 3 of 4 V3] update: also suggest --merge when non-linear update is aborted
On Tue, 21 Feb 2017 11:08:05 -0500, Augie Fackler wrote: On Feb 20, 2017, at 05:38, Gábor STEFANIK wrote: On Wed, Feb 15, 2017 at 12:56:41PM -0800, Martin von Zweigbergk via Mercurial-devel wrote: # HG changeset patch # User Martin von Zweigbergk # Date 1487140898 28800 # Tue Feb 14 22:41:38 2017 -0800 # Node ID c6cd58d272aee6633fbad5eacdad742e2f9909cd # Parent 542a99ede6c3ac7cb4afccd3703fcc30e3d4c90d update: also suggest --merge when non-linear update is aborted This makes me a touch nervous, since the merge can leave the user in an state that's hard to recover from. Basically "hg resolve -au; hg resolve -at:local; hg update --merge -r$(head -c40 .hg/merge/state) -t:local"; but we need to expose a less hacky way of doing so. Not quite, because this isn't sure (I don't think) to get you back to exactly the pre-update-command state, as some files might have been merged behind your back? Crazy thought- what if `hg update` were to do the equivalent under the hood: $ hg ci --secret -m "backup for update" $ src=$(hg log -r . -T "{rev}") $ hg up $dest $ hg rebase -r $src -d . Rebase strips (or obsoletes), so the temp commit is gone. If things go awry, `hg update --abort` is the equivalent of: $ hg rebase --abort $ hg up -C $src^ $ hg revert --all -r $src $ hg strip --no-backup $src This would restore files merged behind your back too. Obviously it is only needed if a file changed in both branches between ancestor($src, $dest) -> $src and ancestor($src, $dest) -> $dest. I've been pondering how to do that calculation with filesets, so at least there's an easy way to tell if there's a potential conflict beforehand. Maybe a new 'changed(rev)' fileset, that works like `hg status --change`? "hg update --abort"? I'd be a big fan of having an update --abort that just takes you back to where you were before the conflicts. To date, nobody has been motivated enough to do the work (I'd love to do it, but it's unlikely to be near the top of my stack for months/years). ___ 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 1 of 4 V2] serve: add support for Mercurial subrepositories
Sorry for the delay- I was swamped the last few days. On Tue, 21 Feb 2017 09:33:58 -0500, Yuya Nishihara wrote: On Mon, 20 Feb 2017 22:00:20 -0500, Matt Harbison wrote: On Mon, 20 Feb 2017 09:27:44 -0500, Yuya Nishihara wrote: > On Thu, 16 Feb 2017 16:41:08 -0500, Matt Harbison wrote: >> # HG changeset patch >> # User Matt Harbison >> # Date 1486875517 18000 >> # Sat Feb 11 23:58:37 2017 -0500 >> # Node ID 4f2862487d789edc1f36b5687d828a2914e1dc32 >> # Parent afaf3c2b129c8940387fd9928ae4fdc28259d13c >> serve: add support for Mercurial subrepositories >> >> I've been using `hg serve --web-conf ...` with a simple '/=projects/**' >> [paths] >> configuration for awhile without issue. Let's ditch the need for the >> manual >> configuration in this case, and limit the repos served to the actual >> subrepos. >> >> This doesn't attempt to handle the case where a new subrepo appears >> while the >> server is running. That could probably be handled with a hook if >> somebody wants >> it. But it's such a rare case, it probably doesn't matter for the >> temporary >> serves. >> >> Unfortunately, the root of the webserver when serving multiple repos is >> the html >> index file. This makes the URL different for `hg serve` vs `hg serve >> -S`, >> because the top level repo then needs to be part of the path. That can >> be >> fixed later. > > I'm puzzled by this new version which extensively relies on somewhat > magical > HTTP redirection. Instead, can't we fix hgwebdir to be able to host > hgweb at > '/' URL, and add explicit URL to show the index page hidden by it? This patch is the same as the first in V1, except that I dropped forcing the web.staticurl config, and I globbed away a bunch of the http parameters in the tests, since only the URI and status is of interest. The first version did host the parent at '/', and the subrepos relative to it. Yes, that seems intuitive way to serve a repo and its subrepos behind. I thought there wasn't redirection magic as the parent repo was served at '/', was there? Correct. Redirection was only introduced in V2. - At http://localhost:8000, the links on the left side were corrupt (graph is simply 'graph/tip', tags is 'http://tags', etc.) The pattern seemed to be that things ending in 'tip' are relative URLs, and the rest get an http: prefix. It looks from the sources like it is just a matter of '/' not translating for the {repo} template. [snip] I saw some of these problems in V1. However, the standalone hgweb can host a repository at '/', so I don't think it's quite difficult to host the subrepo parent at '/'. That's a good point, so now I'm really puzzled over the subtle differences. It looks like when it finds a hosted repo, it just farms out to hgweb, like the single serve would do. To me, the benefits of this series over the original is: 1) The repos aren't moved, and therefore don't incur these subtle bugs 2) These changes are totally isolated to subrepo serving, so there should be no risk to mainstream hgweb usage 3) This is completely compatible with existing serves with a simple '/=$projects_dir/**' config file, because the real repos are not anchored to '/'. I think (2) and (3) are up to how we build a repository map. What I mean for (2) is that in V2, none of the code changes are hit without -S. That seems like a good thing, given the subtle breakage in V1. What I mean by (3) is that the transition for current clones is to simply drop --web-conf=.. and start using -S on the server side. Clients won't see a difference. I assume that the hardcoded web.staticurl in V1 also means that it won't be able to serve a subrepo named 'static'? (That's admittedly an edge case.) I only see the two ways to build the repo map, so I'm not sure what you are saying here. If a map has no '/' entry, hgweb would serve nothing at '/' and is compatible with the current behavior. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH] subrepo: run the repo decoders when archiving
# HG changeset patch # User Matt Harbison # Date 1488075239 18000 # Sat Feb 25 21:13:59 2017 -0500 # Node ID 5ce388a91851dc6c0dc1be0342a105da659e1d47 # Parent 88203f26ea57627cabd7cf9c4f7843661d6c43ae subrepo: run the repo decoders when archiving The decoders were already run by default for the main repo, so this seemed like an oversight. The extdiff extension has been using 'archive' since 68822b7cdd01 to support -S, and a colleague noticed that after diffing, making changes, and closing it, the line endings were wrong for the diff-tool modified files in the subrepository. (Files in the parent repo were correct, with the same .hgeol settings.) The editor (Visual Studio in this case) reloads the file, but doesn't notice the EOL change. It still adds new lines with the original EOL setting, and the file ends up inconsistent. Without this change, the first file `cat`d in the test prints '\r (esc)' EOL, but the second doesn't on Windows or Linux. diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py --- a/hgext/largefiles/overrides.py +++ b/hgext/largefiles/overrides.py @@ -993,9 +993,9 @@ archiver.done() -def hgsubrepoarchive(orig, repo, archiver, prefix, match=None): +def hgsubrepoarchive(orig, repo, archiver, prefix, match=None, decode=True): if not repo._repo.lfstatus: -return orig(repo, archiver, prefix, match) +return orig(repo, archiver, prefix, match, decode) repo._get(repo._state + ('hg',)) rev = repo._state[1] @@ -1010,6 +1010,8 @@ if match and not match(f): return data = getdata() +if decode: +data = repo._repo.wwritedata(name, data) archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data) @@ -1037,7 +1039,7 @@ sub = ctx.workingsub(subpath) submatch = matchmod.subdirmatcher(subpath, match) sub._repo.lfstatus = True -sub.archive(archiver, prefix + repo._path + '/', submatch) +sub.archive(archiver, prefix + repo._path + '/', submatch, decode) # If a largefile is modified, the change is not reflected in its # standin until a commit. cmdutil.bailifchanged() raises an exception diff --git a/mercurial/archival.py b/mercurial/archival.py --- a/mercurial/archival.py +++ b/mercurial/archival.py @@ -331,7 +331,7 @@ for subpath in sorted(ctx.substate): sub = ctx.workingsub(subpath) submatch = matchmod.subdirmatcher(subpath, matchfn) -total += sub.archive(archiver, prefix, submatch) +total += sub.archive(archiver, prefix, submatch, decode) if total == 0: raise error.Abort(_('no files match the archive pattern')) diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -542,8 +542,8 @@ """return filename iterator""" raise NotImplementedError -def filedata(self, name): -"""return file data""" +def filedata(self, name, decode): +"""return file data, optionally passed through repo decoders""" raise NotImplementedError def fileflags(self, name): @@ -558,7 +558,7 @@ """handle the files command for this subrepo""" return 1 -def archive(self, archiver, prefix, match=None): +def archive(self, archiver, prefix, match=None, decode=True): if match is not None: files = [f for f in self.files() if match(f)] else: @@ -572,7 +572,7 @@ mode = 'x' in flags and 0o755 or 0o644 symlink = 'l' in flags archiver.addfile(prefix + self._path + '/' + name, - mode, symlink, self.filedata(name)) + mode, symlink, self.filedata(name, decode)) self.ui.progress(_('archiving (%s)') % relpath, i + 1, unit=_('files'), total=total) self.ui.progress(_('archiving (%s)') % relpath, None) @@ -782,7 +782,7 @@ % (inst, subrelpath(self))) @annotatesubrepoerror -def archive(self, archiver, prefix, match=None): +def archive(self, archiver, prefix, match=None, decode=True): self._get(self._state + ('hg',)) total = abstractsubrepo.archive(self, archiver, prefix, match) rev = self._state[1] @@ -790,7 +790,8 @@ for subpath in ctx.substate: s = subrepo(ctx, subpath, True) submatch = matchmod.subdirmatcher(subpath, match) -total += s.archive(archiver, prefix + self._path + '/', submatch) +total += s.archive(archiver, prefix + self._path + '/', submatch, +
[PATCH] wix: include the help for pager
# HG changeset patch # User Matt Harbison # Date 1488077074 18000 # Sat Feb 25 21:44:34 2017 -0500 # Node ID f3af642d13d78e7fcdea4468c024958a5ce2a745 # Parent 5ce388a91851dc6c0dc1be0342a105da659e1d47 wix: include the help for pager Similar (I assume) to 65d2538ac993. diff --git a/contrib/wix/help.wxs b/contrib/wix/help.wxs --- a/contrib/wix/help.wxs +++ b/contrib/wix/help.wxs @@ -25,6 +25,7 @@ + diff --git a/tests/test-install.t b/tests/test-install.t --- a/tests/test-install.t +++ b/tests/test-install.t @@ -166,7 +166,6 @@ help/hg.1.txt help/hgignore.5.txt help/hgrc.5.txt -help/pager.txt Not tracked: $ python wixxml.py templates ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 9 pager v2] pager: move pager-initiating code into core
On Thu, 16 Feb 2017 11:59:10 -0500, Augie Fackler wrote: # HG changeset patch # User Augie Fackler # Date 1487198871 18000 # Wed Feb 15 17:47:51 2017 -0500 # Node ID cd19a77477bcd18d1f7ab4fa73ee0dbf3c7a4e46 # Parent 791b4e846a7b9a0783440b9504585438777fe2d2 pager: move pager-initiating code into core No functionality change. A previous version of this API had a category argument on ui.pager(). As I migrated the commands in core, I couldn't come up with good enough consistency in any categorization scheme so I just scrapped the whole idea. It may be worth revisiting in the future. diff --git a/hgext/pager.py b/hgext/pager.py --- a/hgext/pager.py +++ b/hgext/pager.py +# TODO: add a "system defaults" config section so this default +# of more(1) can be easily replaced with a global +# configuration file. For example, on OS X the sane default is +# less(1), not more(1), and on debian it's +# sensible-pager(1). We should probably also give the system +# default editor command similar treatment. +envpager = encoding.environ.get('PAGER', 'more') +pagercmd = self.config('pager', 'pager', envpager) Any thoughts on what this looks like? It seems like it might be distantly(?) related to something I tried a couple years ago [1], and the discussions around it. Does it seem reasonable to move the above to a method, similar to ui.editor()? I'd like to detect MSYS and default to `less`. IDK if we can pull that off with just a global config file. (The only way I see to detect MSYS is to look for 'MSYSTEM' in env.) In theory, the `less` command in GnuWin32 can be installed and made visible to cmd.exe too. I wonder if (on some platforms anyway), there should be a list of default choices, and the first one found in $PATH used. ui.editor() doesn't make sure the editor is valid, so I figured keeping that kind of check out of ui was purposeful. A bad editor will produce an error that tries to indicate the problem (though I missed it the first time in the OS error output): $ HGEDITOR=xzy ../hg ci 'xzy' is not recognized as an internal or external command, operable program or batch file. abort: edit failed: xzy exited with status 1 But not so much for the pager: hg>set PAGER=less hg>hg help filesets 'less' is not recognized as an internal or external command, operable program or batch file. I'm not sure if the right thing here is to error out, or to treat the pager as disabled. Especially if it is on by default, with an env knob that isn't as obvious as the example above. So it seems like we might need some sort of check, whether or not we try a list of defaults. [1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2015-March/067563.html ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 9 pager v2] pager: move pager-initiating code into core
On Sat, 25 Feb 2017 23:32:12 -0500, Augie Fackler wrote: On Feb 25, 2017, at 11:22 PM, Matt Harbison wrote: On Thu, 16 Feb 2017 11:59:10 -0500, Augie Fackler wrote: # HG changeset patch # User Augie Fackler # Date 1487198871 18000 # Wed Feb 15 17:47:51 2017 -0500 # Node ID cd19a77477bcd18d1f7ab4fa73ee0dbf3c7a4e46 # Parent 791b4e846a7b9a0783440b9504585438777fe2d2 pager: move pager-initiating code into core No functionality change. A previous version of this API had a category argument on ui.pager(). As I migrated the commands in core, I couldn't come up with good enough consistency in any categorization scheme so I just scrapped the whole idea. It may be worth revisiting in the future. diff --git a/hgext/pager.py b/hgext/pager.py --- a/hgext/pager.py +++ b/hgext/pager.py +# TODO: add a "system defaults" config section so this default +# of more(1) can be easily replaced with a global +# configuration file. For example, on OS X the sane default is +# less(1), not more(1), and on debian it's +# sensible-pager(1). We should probably also give the system +# default editor command similar treatment. +envpager = encoding.environ.get('PAGER', 'more') +pagercmd = self.config('pager', 'pager', envpager) Any thoughts on what this looks like? It seems like it might be distantly(?) related to something I tried a couple years ago [1], and the discussions around it. It’s pretty different from the previous round in my mind: it’d be a config section, only advertised for sysadmins and packagers, specifically intended for setting more-reasonable defaults, e.g.: (debian) [systemdefaults] editor = sensible-editor pager = sensible-pager (macOS) [systemdefaults] editor = nano pager = less (FreeBSD) [systemdefaults] editor = vi pager = less etc. Does it seem reasonable to move the above to a method, similar to ui.editor()? I'd like to detect MSYS and default to `less`. IDK if we can pull that off with just a global config file. (The only way I see to detect MSYS is to look for 'MSYSTEM' in env.) In line with the above, I’d expect an mays-backed package to set systemdefaults.pager to less (maybe that’s not a thing? I dunno.) I'm not thinking of an msys package, rather my personal usage. If I'm doing anything of any substance on the command line, I'll use msys. But TortoiseHg launches cmd.exe with a simple Ctrl + Shift + T, and sometimes that's good enough. Therefore, I can't just set a pager value in %HOME%/mercurial.ini. The hg.exe built from source and the one bundled with TortoiseHg are each visible to msys and cmd.exe, depending on what directory I'm in. So even if TortoiseHg picked one (and we ignore hg built from the dev repo), it may or may not use the best pager available without a little help. I’m extremely hesitant to add any kind of conditional logic in hgrc. Agreed. The conditional logic I'm thinking of is in python, similar to how plan9 sets its last-ditch editor to 'E' in ui.geteditor(). Based on the vision you've described, I don't see a list as useful. And because I can't think of any other OS with such a bad pager (and a better one so tantalizingly close), maybe a one-off python conditional is OK? Do you know of any other systems that use this kind of configuration approach but don’t have a scripting language as their config language? IDK what this means, so I'm gonna say no. :-) Note that systemdefaults (which is a name I came up with in the process of writing this mail, and probably isn’t what we should keep) would *not* overwrite environment variables, so if the user has EDITOR or PAGER set, that takes precedence over systemdefaults - this new config section is explicitly about helping packagers get the best possible “out of the box” experience without having to patch hg (which the debian package currently has to for sensible-editor). Makes sense. This would get rid of the special case editor for plan9, for packages anyway. It wouldn't for hg built from source, but that could presumably be set in ~/.hgrc. In theory, the `less` command in GnuWin32 can be installed and made visible to cmd.exe too. I wonder if (on some platforms anyway), there should be a list of default choices, and the first one found in $PATH used. ui.editor() doesn't make sure the editor is valid, so I figured keeping that kind of check out of ui was purposeful. A bad editor will produce an error that tries to indicate the problem (though I missed it the first time in the OS error output): $ HGEDITOR=xzy ../hg ci 'xzy' is not recognized as an internal or external command, operable program or batch file. abort: edit failed: xzy exited with status 1 But not so much for th
Re: [PATCH 1 of 4 V2] serve: add support for Mercurial subrepositories
On Sun, 26 Feb 2017 08:28:01 -0500, Yuya Nishihara wrote: On Sat, 25 Feb 2017 15:25:30 -0500, Matt Harbison wrote: On Tue, 21 Feb 2017 09:33:58 -0500, Yuya Nishihara wrote: >> - At http://localhost:8000, the links on the left side were corrupt >> (graph >> is simply 'graph/tip', tags is 'http://tags', etc.) The pattern seemed >> to >> be that things ending in 'tip' are relative URLs, and the rest get an >> http: prefix. It looks from the sources like it is just a matter of '/' >> not translating for the {repo} template. > > [snip] > > I saw some of these problems in V1. However, the standalone hgweb can > host > a repository at '/', so I don't think it's quite difficult to host the > subrepo > parent at '/'. That's a good point, so now I'm really puzzled over the subtle differences. It looks like when it finds a hosted repo, it just farms out to hgweb, like the single serve would do. Yes. hgwebdir is just a dispatcher except for generating an index page. This is a dirty hack to make hgwebdir serve a repo at '/'. diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py +++ b/mercurial/hgweb/hgweb_mod.py @@ -335,7 +335,7 @@ class hgweb(object): req.url = req.env['SCRIPT_NAME'] if not req.url.endswith('/'): req.url += '/' -if 'REPO_NAME' in req.env: +if req.env.get('REPO_NAME'): req.url += req.env['REPO_NAME'] + '/' if 'PATH_INFO' in req.env: diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -254,18 +254,19 @@ class hgwebdir(object): return [] # top-level index -elif not virtual: +elif False: req.respond(HTTP_OK, ctype) return self.makeindex(req, tmpl) # nested indexes and hgwebs repos = dict(self.repos) -virtualrepo = virtual -while virtualrepo: -real = repos.get(virtualrepo) +# XXX dirty hack to handle ''. IIRC, we have a helper function +virtualrepo = '/' + virtual +while True: +real = repos.get(virtualrepo[1:]) if real: -req.env['REPO_NAME'] = virtualrepo +req.env['REPO_NAME'] = virtualrepo[1:] try: # ensure caller gets private copy of ui repo = hg.repository(self.ui.copy(), real) Oh, nice! Thanks for this. Can you clarify what you mean by the hack? It seems like adding '/' to paths isn't all that uncommon (especially in subrepo code), and the closest I could find to a helper for removing '/' is hgwebdir_mod.cleannames(). But that takes a list and also does a util.pconvert(). Just a couple lines above this, 'virtual' is cleaned up with string.strip('/'). (That's interesting, because then I can't see how the "virtual.startswith('static/')" tests can ever be true. It looks like this was papered over in 74f65f44a9aa?) >> To me, the benefits of this series over the original is: >> >> 1) The repos aren't moved, and therefore don't incur these subtle bugs >> 2) These changes are totally isolated to subrepo serving, so there >> should >> be no risk to mainstream hgweb usage >> 3) This is completely compatible with existing serves with a simple >> '/=$projects_dir/**' config file, because the real repos are not >> anchored >> to '/'. > > I think (2) and (3) are up to how we build a repository map. What I mean for (2) is that in V2, none of the code changes are hit without -S. That seems like a good thing, given the subtle breakage in V1. What I mean by (3) is that the transition for current clones is to simply drop --web-conf=.. and start using -S on the server side. Clients won't see a difference. No code change is nice, but I don't buy it much since the redirection thing seemed unnecessarily complicated. I assume that the hardcoded web.staticurl in V1 also means that it won't be able to serve a subrepo named 'static'? (That's admittedly an edge case.) Yes. Also, you can't see /rev/ page if there's a subrepo named 'rev'. I only see the two ways to build the repo map, so I'm not sure what you are saying here. I meant we could delete the root repo from self.repos map on plain hgwebdir server if that's considered a behavior change. (otherwise the root index page would be replaced by the hgweb for the root repo.) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] internals: add some brief documentation about censor
On Mon, 27 Feb 2017 18:11:15 -0500, Augie Fackler wrote: # HG changeset patch # User Augie Fackler # Date 1485220644 18000 # Mon Jan 23 20:17:24 2017 -0500 # Node ID 065219350c9ce3c31a35d13fe97be0673e321e09 # Parent 3f8f53190d6afed0aca6c6527236edad28ce785c internals: add some brief documentation about censor This is needed to keep test-install.t happy: diff --git a/contrib/wix/help.wxs b/contrib/wix/help.wxs --- a/contrib/wix/help.wxs +++ b/contrib/wix/help.wxs @@ -38,6 +38,7 @@ Guid="$(var.help.internals.guid)" Win64='$(var.IsX64)'> KeyPath="yes" /> + /> /> ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 8 of 8] fileset: add a 'status(...)' predicate to control evaluation context
On Fri, 03 Mar 2017 08:40:45 -0500, Pierre-Yves David wrote: # HG changeset patch # User Pierre-Yves David # Date 1488546500 -3600 # Fri Mar 03 14:08:20 2017 +0100 # Node ID 3e95bf7ed38189f6f56de89571fffc667280bb56 # Parent 9d6e733046b9aa7e2ded8c4207625fedcc2a8c04 # EXP-Topic filesetrev-func # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ # hg pull https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 3e95bf7ed381 fileset: add a 'status(...)' predicate to control evaluation context This is awesome! It unlocks the "what merge conflicts might I run into?" pre update/rebase test that I mentioned last week. I did a test to see if the files listed for the 13bbcd56c57a merge agreed with TortoiseHg: $ ../hg files --rev 'ancestor(6483e49204ee, a91c62752d08)' "set:status('ancestor(6483e49204ee, a91c62752d08)', 6483e49204ee, added()+modified()+removed()) & status('ancestor(6483e49204ee, a91c62752d08)', a91c62752d08, added()+modified()+removed())" ..\mercurial\ui.py ..\mercurial\worker.py It does, but that's quite a mouthful. Granted, doing this for real pre-merge would likely use the branch names, but not necessarily. (Consider an anonymous branch after pulling.) I wonder if the parameters to this can have default values, to make it more concise, and more like the status command. For example, leaving out the 3rd parameter implies added()+modified()+removed()+missing() (status doesn't list clean or ignored by default). It seems like it would be convenient if one of the revisions (base?) defaulted to what --rev specified for the command. The second --rev for status defaults to wdir(). I know this is meant for aggregating files _across_ revisions, but then `hg status` and `hg files 'set:status()'` would agree, without ORing together the MAR! predicates. I did run into an oddity when testing with subrepos: diff --git a/tests/test-subrepo-deep-nested-change.t b/tests/test-subrepo-deep-nested-change.t --- a/tests/test-subrepo-deep-nested-change.t +++ b/tests/test-subrepo-deep-nested-change.t @@ -455,6 +455,17 @@ sub1/sub2/sub2 (glob) sub1/sub2/test.txt (glob) + $ hg files 'set:status(0, "wdir()", added()+modified()+removed())' + .hgsubstate + foo\bar\abc + + $ hg files -S 'set:status(0, tip, added()+modified()+removed())' + .hgsubstate + foo\bar\abc + sub1\.hgsubstate + sub1\foo + sub1\sub2\folder\bar + $ hg files sub1 sub1/.hgsub (glob) sub1/.hgsubstate (glob) I'd expect .hgsub to show up in the main repo. There may be some more missing in the subrepos for the second command, but I don't have any more time to investigate tonight. I'll see if I can figure it out over the weekend. When I quote 3rd parameter in those tests, the output is different. It's unfortunate that revsets in arg 1 or 2 requires quoting, but quoting is wrong for the 3rd arg. $ hg files 'set:status(0, "wdir()", "added()+modified()+removed()")' [1] $ hg files -S 'set:status(0, tip, "added()+modified()+removed()")' abort: added()+modified()+removed() not under root '$TESTTMP\cloned\sub1' (in subrepo sub1) (consider using '--cwd sub1') [255] If this is just because of the way the parser needs to be, mentioning it in the help may be sufficient. Same as 'revs', this predicate does not select files but switches the evaluation context. This allow to match file according arbitrary status call. We can now express the same query as 'hg status'. The API (two 'revsingle' class) have been picked instead of a single 'revs' revset for multiple reasons: * it is less confusing to express * it allow to express more query (eg: backward status, cross branch status) diff --git a/mercurial/fileset.py b/mercurial/fileset.py --- a/mercurial/fileset.py +++ b/mercurial/fileset.py @@ -463,6 +463,25 @@ def revs(mctx, x): result.append(f) return result +@predicate('status(base, rev, pattern)') +def status(mctx, x): +"""``status(base, rev, revspec)`` + +Evaluate predicate using status change between ``base`` and +``rev``. Examples: + +- ``status(3, 7, added())`` - matches files added from "3" to "7" +""" +repo = mctx.ctx.repo() +# i18n: "status" is a keyword +b, r, x = getargs(x, 3, 3, _("status takes three arguments")) +# i18n: "status" is a keyword +baserevspec = getstring(b, _("first argument to revs must be a revision")) +revspec = getstring(r, _("second argument to revs must be a revision")) +basectx = scmutil.revsingle(repo, baserevspec) +ctx = scmutil.revsingle(repo, revspec) +return getset(mctx.switch(ctx, _buildstatus(ctx, x, basectx=basectx)), x) + @predicate('subrepo([pattern])') def subrepo(mctx, x): """Subrepositories whose paths match the given pattern. @@ -538,6 +557,7 @@ class fullmatchctx(matchctx): # filesets using matchctx.switch() _switchcallers = [ 'revs', +'sta
Re: [PATCH 8 of 8] fileset: add a 'status(...)' predicate to control evaluation context
On Fri, 03 Mar 2017 23:35:04 -0500, Matt Harbison wrote: On Fri, 03 Mar 2017 08:40:45 -0500, Pierre-Yves David wrote: # HG changeset patch # User Pierre-Yves David # Date 1488546500 -3600 # Fri Mar 03 14:08:20 2017 +0100 # Node ID 3e95bf7ed38189f6f56de89571fffc667280bb56 # Parent 9d6e733046b9aa7e2ded8c4207625fedcc2a8c04 # EXP-Topic filesetrev-func # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ # hg pull https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 3e95bf7ed381 fileset: add a 'status(...)' predicate to control evaluation context This is awesome! It unlocks the "what merge conflicts might I run into?" pre update/rebase test that I mentioned last week. I did a test to see if the files listed for the 13bbcd56c57a merge agreed with TortoiseHg: $ ../hg files --rev 'ancestor(6483e49204ee, a91c62752d08)' "set:status('ancestor(6483e49204ee, a91c62752d08)', 6483e49204ee, added()+modified()+removed()) & status('ancestor(6483e49204ee, a91c62752d08)', a91c62752d08, added()+modified()+removed())" ..\mercurial\ui.py ..\mercurial\worker.py It does, but that's quite a mouthful. Granted, doing this for real pre-merge would likely use the branch names, but not necessarily. (Consider an anonymous branch after pulling.) I wonder if the parameters to this can have default values, to make it more concise, and more like the status command. For example, leaving out the 3rd parameter implies added()+modified()+removed()+missing() (status doesn't list clean or ignored by default). It seems like it would be convenient if one of the revisions (base?) defaulted to what --rev specified for the command. The second --rev for status defaults to wdir(). I know this is meant for aggregating files _across_ revisions, but then `hg status` and `hg files 'set:status()'` would agree, without ORing together the MAR! predicates. I did run into an oddity when testing with subrepos: diff --git a/tests/test-subrepo-deep-nested-change.t b/tests/test-subrepo-deep-nested-change.t --- a/tests/test-subrepo-deep-nested-change.t +++ b/tests/test-subrepo-deep-nested-change.t @@ -455,6 +455,17 @@ sub1/sub2/sub2 (glob) sub1/sub2/test.txt (glob) + $ hg files 'set:status(0, "wdir()", added()+modified()+removed())' + .hgsubstate + foo\bar\abc + + $ hg files -S 'set:status(0, tip, added()+modified()+removed())' + .hgsubstate + foo\bar\abc + sub1\.hgsubstate + sub1\foo + sub1\sub2\folder\bar + $ hg files sub1 sub1/.hgsub (glob) sub1/.hgsubstate (glob) I'd expect .hgsub to show up in the main repo. My misunderstanding on this one. `hg status --rev 0` agrees with this output. I read the doc saying "added from 3 to 7" as [3, 7], not (3, 7] as it actually is. .hgsub was only changed in rev 0. When I changed to null or , it showed as expected. (Using -1 here raises a parse error, and using "-1" causes nothing to match.) There may be some more missing in the subrepos for the second command, but I don't have any more time to investigate tonight. I'll see if I can figure it out over the weekend. Here's a test case: diff --git a/tests/test-subrepo-deep-nested-change.t b/tests/test-subrepo-deep-nested-change.t --- a/tests/test-subrepo-deep-nested-change.t +++ b/tests/test-subrepo-deep-nested-change.t @@ -455,6 +455,18 @@ sub1/sub2/sub2 (glob) sub1/sub2/test.txt (glob) + $ hg files -r 2 -S 'set:status(1, 2, added()+modified()+removed())' + .hgsubstate + sub1\.hgsubstate + sub1\sub2\folder\test.txt + sub1\sub2\test.txt + + $ hg status -S --rev 1 --rev 2 | sort -k2 + M .hgsubstate + M sub1/.hgsubstate + A sub1/sub2/folder/test.txt + A sub1/sub2/test.txt + $ hg files sub1 sub1/.hgsub (glob) sub1/.hgsubstate (glob) The fileset gets fully populated with what `hg status` shows. But if you drop the "-r 2" arg to `hg files`, the two *.txt files don't show. What's happening is the command is walking 'wdir()', and since those files don't exist, they aren't tested against the set. IOW, there's an implicit & with the files in the revision of the command against the fileset. That makes sense, but it initially surprised me. I'm not sure what words to use, but that should be documented somehow. I also think that's an argument for the command --rev and the base rev defaulting to the same value. (Is there a usecase for the command revision not being one or the other fileset revisions?) One cosmetic thing below that I missed the first time. When I quote 3rd parameter in those tests, the output is different. It's unfortunate that revsets in arg 1 or 2 requires quoting, but quoting is wrong for the 3rd arg.
[PATCH] hgwebdir: add support for explicit index files
# HG changeset patch # User Matt Harbison # Date 1488770552 18000 # Sun Mar 05 22:22:32 2017 -0500 # Node ID 3ff768dd4fe9faeca8ccba040fa6a085584063aa # Parent 023123a67b54d98bd4c8ef8ac8cfd7a96247519e hgwebdir: add support for explicit index files This is useful for when repositories are nested in --web-conf, and in the future with hosted subrepositories. The previous behavior was only to render an index at each virtual directory. There is now an explicit index.html for each virtual directory. Additionally, there is now an explicit index.html for every repository directory with a nested repository below it. This seems more consistent with each virtual directory hosting an index, and more discoverable than to only have an index for a directory that directly hosts a nested repository. I couldn't figure out how to close the loop and provide one in each directory without a deeper nested repository, without blocking a committed 'index.html'. Keeping that seems better than rendering an empty index. diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -254,34 +254,50 @@ return [] # top-level index -elif not virtual: +elif not virtual or virtual == 'index.html': +if virtual: +req.env['PATH_INFO'] = '/' + req.respond(HTTP_OK, ctype) return self.makeindex(req, tmpl) # nested indexes and hgwebs repos = dict(self.repos) -virtualrepo = virtual -while virtualrepo: -real = repos.get(virtualrepo) -if real: -req.env['REPO_NAME'] = virtualrepo -try: -# ensure caller gets private copy of ui -repo = hg.repository(self.ui.copy(), real) -return hgweb_mod.hgweb(repo).run_wsgi(req) -except IOError as inst: -msg = inst.strerror -raise ErrorResponse(HTTP_SERVER_ERROR, msg) -except error.RepoError as inst: -raise ErrorResponse(HTTP_SERVER_ERROR, str(inst)) -up = virtualrepo.rfind('/') -if up < 0: -break -virtualrepo = virtualrepo[:up] +def checkrepos(): +if not virtual.endswith('/index.html'): +return True + +pdir = virtual[:-len('index.html')] +return not any(r.startswith(pdir) for r in repos) + +if checkrepos(): +virtualrepo = virtual +while virtualrepo: +real = repos.get(virtualrepo) +if real: +req.env['REPO_NAME'] = virtualrepo +try: +# ensure caller gets private copy of ui +repo = hg.repository(self.ui.copy(), real) +return hgweb_mod.hgweb(repo).run_wsgi(req) +except IOError as inst: +msg = inst.strerror +raise ErrorResponse(HTTP_SERVER_ERROR, msg) +except error.RepoError as inst: +raise ErrorResponse(HTTP_SERVER_ERROR, str(inst)) + +up = virtualrepo.rfind('/') +if up < 0: +break +virtualrepo = virtualrepo[:up] # browse subdirectories +if virtual.endswith('/index.html'): +virtual = virtual[:-len('/index.html')] +req.env['PATH_INFO'] = '/' + virtual + subdir = virtual + '/' if [r for r in repos if r.startswith(subdir)]: req.respond(HTTP_OK, ctype) diff --git a/tests/test-hgwebdir.t b/tests/test-hgwebdir.t --- a/tests/test-hgwebdir.t +++ b/tests/test-hgwebdir.t @@ -1566,6 +1566,96 @@ /b/ /c/ + $ killdaemons.py + $ cat > paths.conf << EOF + > [paths] + > /dir1/a_repo = $root/a + > /dir1/a_repo/b_repo = $root/b + > EOF + $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf + $ cat hg.pid >> $DAEMON_PIDS + + $ echo 'index file' > $root/a/index.html + $ hg --cwd $root/a ci -Am 'add index file' + adding index.html + + $ get-with-headers.py localhost:$HGPORT1 '' | grep 'a_repo' + dir1/a_repo + + dir1/a_repo/b_repo + + + $ get-with-headers.py localhost:$HGPORT1 'index.html' | grep 'a_repo' + dir1/a_repo + + dir1/a_repo/b_rep
Re: stable ordering of test output
On Fri, 03 Mar 2017 17:45:56 -0500, Danek Duvall wrote: I frequently get failures like this: --- .../mercurial.hg/tests/test-bundle2-exchange.t +++ .../mercurial.hg/tests/test-bundle2-exchange.t.err @@ -1042,11 +1042,11 @@ $ hg --config devel.legacy.exchange=bundle1 clone ssh://user@dummy/bundle2onlyserver not-bundle2-ssh requesting all changes adding changesets - remote: abort: incompatible Mercurial client; bundle2 required - remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient) transaction abort! rollback completed abort: stream ended unexpectedly (got 0 bytes, expected 4) + remote: abort: incompatible Mercurial client; bundle2 required + remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient) [255] $ cat > bundle2onlyserver/.hg/hgrc << EOF ERROR: test-bundle2-exchange.t output changed It's usually fairly consistent, at least for a period of time, and then it goes away. Presumably it's some sort of fairly stable timing issue, and possibly unique to the environment I'm running in (at least, I assume that the official tests aren't showing this). The symptoms seem similar to what was happening on Windows a few years ago. https://www.mercurial-scm.org/repo/hg/rev/83f6c4733ecc https://www.mercurial-scm.org/repo/hg/rev/2abbf4750915 The commit referenced in the first link's message might also be of interest. I could patch the tests locally to reorder the lines, but if it's really an environmental issue, then that's guaranteed to work consistently even for me. Is this (ever? frequently?) an issue for anyone else? I can't think of any particularly satisfying solution to this, other than perhaps separating the remote lines from the local lines, and comparing each of those independently. Would that make sense? Thanks, Danek ___ 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
[PATCH V2] hgwebdir: add support for explicit index files
# HG changeset patch # User Matt Harbison # Date 1488770552 18000 # Sun Mar 05 22:22:32 2017 -0500 # Node ID d24cb60edbc782ea1ee4f5625accc83f9ec3e3ca # Parent 1c48a8278b2f015fca607dfc652823560a5ac580 hgwebdir: add support for explicit index files This is useful for when repositories are nested in --web-conf, and in the future with hosted subrepositories. The previous behavior was only to render an index at each virtual directory. There is now an explicit 'index' child for each virtual directory. The name was suggested by Yuya, for consistency with the other method names. Additionally, there is now an explicit 'index' child for every repository directory with a nested repository somewhere below it. This seems more consistent with each virtual directory hosting an index, and more discoverable than to only have an index for a directory that directly hosts a nested repository. I couldn't figure out how to close the loop and provide one in each directory without a deeper nested repository, without blocking a committed 'index' file. Keeping that seems better than rendering an empty index. diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -254,13 +254,21 @@ return [] # top-level index -elif not virtual: + +repos = dict(self.repos) + +if not virtual or (virtual == 'index' and virtual not in repos): req.respond(HTTP_OK, ctype) return self.makeindex(req, tmpl) # nested indexes and hgwebs -repos = dict(self.repos) +if virtual.endswith('/index') and virtual not in repos: +subdir = virtual[:-len('index')] +if any(r.startswith(subdir) for r in repos): +req.respond(HTTP_OK, ctype) +return self.makeindex(req, tmpl, subdir) + virtualrepo = virtual while virtualrepo: real = repos.get(virtualrepo) @@ -352,8 +360,7 @@ pass parts = [name] -if 'PATH_INFO' in req.env: -parts.insert(0, req.env['PATH_INFO'].rstrip('/')) +parts.insert(0, '/' + subdir.rstrip('/')) if req.env['SCRIPT_NAME']: parts.insert(0, req.env['SCRIPT_NAME']) url = re.sub(r'/+', '/', '/'.join(parts) + '/') diff --git a/tests/test-hgwebdir.t b/tests/test-hgwebdir.t --- a/tests/test-hgwebdir.t +++ b/tests/test-hgwebdir.t @@ -1566,6 +1566,119 @@ /b/ /c/ + $ killdaemons.py + $ cat > paths.conf << EOF + > [paths] + > /dir1/a_repo = $root/a + > /dir1/a_repo/b_repo = $root/b + > /dir1/dir2/index = $root/b + > EOF + $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf + $ cat hg.pid >> $DAEMON_PIDS + + $ echo 'index file' > $root/a/index + $ hg --cwd $root/a ci -Am 'add index file' + adding index + + $ get-with-headers.py localhost:$HGPORT1 '' | grep 'a_repo' + dir1/a_repo + + dir1/a_repo/b_repo + + + $ get-with-headers.py localhost:$HGPORT1 'index' | grep 'a_repo' + dir1/a_repo + + dir1/a_repo/b_repo + + + $ get-with-headers.py localhost:$HGPORT1 'dir1' | grep 'a_repo' + a_repo + + a_repo/b_repo + + + $ get-with-headers.py localhost:$HGPORT1 'dir1/index' | grep 'a_repo' + a_repo + + a_repo/b_repo + + + $ get-with-headers.py localhost:$HGPORT1 'dir1/a_repo' | grep 'a_repo' + + + + dir1/a_repo: log + href="/dir1/a_repo/atom-log" title="Atom feed for dir1/a_repo" /> + href="/dir1/a_repo/rss-log" title="RSS feed for dir1/a_repo" /> + + graph + tags + bookmarks + branches + changeset + browse + help + + + Mercurial > dir1 > a_repo + + number or hash, or revset expression. + less + more + | rev 1: (0) tip + add index file + a + less + more + | rev 1: (0) tip + '/dir1/a_repo/shortlog/%next%', + + $ get-with-headers.py localhost:$HGPORT1 'dir1/a_repo/index' | grep 'a_repo' + Mercurial > dir1 > a_repo + b_repo + + +Files named 'index' are not blocked + + $ get-with-headers.py localhost:$HGPORT1 'dir1/a_repo/raw-file/tip/index' + 200 Script output follows + + index file + +Repos named 'index' take precedence over the index file + + $ get-with-headers.py localhost:$HGPORT1 'dir1/dir2/index' | grep 'index' + + + + + dir1/dir2/
[PATCH evolve-ext] checks: correct the shebang line filtering for python files
# HG changeset patch # User Matt Harbison # Date 1489713417 14400 # Thu Mar 16 21:16:57 2017 -0400 # Node ID 6a3248558b6929378450b572bb27406afe703ffd # Parent e9d5f54765a27e09d35f48dda23db7e6f5b8320a checks: correct the shebang line filtering for python files As it is, the only related file is docs/test2rst.py, which was covered by **.py. Not sure if it matters, but most patterns in core tests are for "#!.*?python". (Though there are a couple "#!.*python" tests.) diff --git a/tests/test-check-flake8.t b/tests/test-check-flake8.t --- a/tests/test-check-flake8.t +++ b/tests/test-check-flake8.t @@ -14,5 +14,5 @@ run flake8 if it exists; if it doesn't, then just skip - $ hg files -0 'set:(**.py or grep("^!#.*python")) - removed()' 2>/dev/null \ + $ hg files -0 'set:(**.py or grep("^#!.*python")) - removed()' 2>/dev/null \ > | xargs -0 flake8 diff --git a/tests/test-check-pyflakes.t b/tests/test-check-pyflakes.t --- a/tests/test-check-pyflakes.t +++ b/tests/test-check-pyflakes.t @@ -7,5 +7,5 @@ run pyflakes on all tracked files ending in .py or without a file ending (skipping binary file random-seed) - $ hg locate 'set:(**.py or grep("^!#.*python")) - removed()' 2>/dev/null \ + $ hg locate 'set:(**.py or grep("^#!.*python")) - removed()' 2>/dev/null \ > | xargs pyflakes 2>/dev/null ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH evolve-ext] tests: add glob for Windows
# HG changeset patch # User Matt Harbison # Date 1489720627 14400 # Thu Mar 16 23:17:07 2017 -0400 # Node ID ab5c2bef148bfb60e1956a55de4b7ba00ebe1817 # Parent 6a3248558b6929378450b572bb27406afe703ffd tests: add glob for Windows diff --git a/tests/test-inhibit.t b/tests/test-inhibit.t --- a/tests/test-inhibit.t +++ b/tests/test-inhibit.t @@ -911,7 +911,7 @@ $ cd not-inhibit $ hg book -d foo $ hg pull - pulling from $TESTTMP/inhibit + pulling from $TESTTMP/inhibit (glob) searching for changes no changes found adding remote bookmark foo diff --git a/tests/test-stablesort.t b/tests/test-stablesort.t --- a/tests/test-stablesort.t +++ b/tests/test-stablesort.t @@ -138,7 +138,7 @@ updating to branch default 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg -R repo_B pull --rev 13 - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests @@ -146,7 +146,7 @@ added 4 changesets with 0 changes to 0 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) $ hg -R repo_B pull --rev 14 - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests @@ -154,7 +154,7 @@ added 1 changesets with 0 changes to 0 files (+1 heads) (run 'hg heads .' to see heads, 'hg merge' to merge) $ hg -R repo_B pull - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests @@ -204,7 +204,7 @@ updating to branch default 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg -R repo_C pull --rev 12 - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests @@ -212,7 +212,7 @@ added 2 changesets with 0 changes to 0 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) $ hg -R repo_C pull --rev 15 - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests @@ -220,7 +220,7 @@ added 4 changesets with 0 changes to 0 files (+1 heads) (run 'hg heads .' to see heads, 'hg merge' to merge) $ hg -R repo_C pull - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests @@ -270,7 +270,7 @@ updating to branch default 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg -R repo_D pull --rev 10 - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests @@ -278,7 +278,7 @@ added 5 changesets with 0 changes to 0 files (run 'hg update' to get a working copy) $ hg -R repo_D pull --rev 15 - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests @@ -286,7 +286,7 @@ added 4 changesets with 0 changes to 0 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) $ hg -R repo_D pull - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests @@ -404,7 +404,7 @@ updating to branch default 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg -R repo_E pull --rev e7d9710d9fc6 - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests @@ -420,7 +420,7 @@ updating to branch default 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg -R repo_F pull --rev d62d843c9a01 - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests @@ -436,7 +436,7 @@ updating to branch default 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg -R repo_G pull --rev 43227190fef8 - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests @@ -444,7 +444,7 @@ added 1 changesets with 0 changes to 0 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge) $ hg -R repo_G pull --rev 2702dd0c91e7 - pulling from $TESTTMP/repo_A + pulling from $TESTTMP/repo_A (glob) searching for changes adding changesets adding manifests diff --git a/tests/test-topic-dest.t b/tests/test-topic-dest.t --- a/tests/test-topic-dest.t +++ b/tests/test-topic-dest.t @@ -276,7 +276,7 @@ $ hg add other $ hg ci -m 'c_other' $ hg pull -r default --rebase - pulling from $TESTTMP/jungle + pulling from $TESTTMP/jungle (glob) searching for c
[PATCH] color: sync text attributes and buffered text output on Windows (issue5508)
# HG changeset patch # User Matt Harbison # Date 1489941885 14400 # Sun Mar 19 12:44:45 2017 -0400 # Node ID b1bebed54e9371708e1cd1eba63f0cedadfdf035 # Parent da7d19324b1e3d2ce0636bf73e76bf8f3d68ed27 color: sync text attributes and buffered text output on Windows (issue5508) I originally noticed that log output wasn't being colored after 3a4c0905f357, but there were other complications too. With a bunch of untracked files, only the first 1K of characters were colored pink, and the rest were normal white. A single modified file at the top would also be colored pink. Line buffering and full buffering are treated as the same thing in Windows [1], meaning the stream is either buffered or not. I can't find any explicit documentation to say stdout is unbuffered by default when attached to a console (but some internet postings indicated that is the case[2]). Therefore, it seems that explicit flushes are better than just not reopening stdout. NB: pager is now on by default, and needs to be disabled to see any color on Windows. [1] https://msdn.microsoft.com/en-us/library/86cebhfs(v=vs.140).aspx [2] https://sourceforge.net/p/mingw/mailman/message/27121137/ diff --git a/mercurial/color.py b/mercurial/color.py --- a/mercurial/color.py +++ b/mercurial/color.py @@ -463,9 +463,11 @@ for sattr in m.group(1).split(';'): if sattr: attr = mapcolor(int(sattr), attr) +ui.flush() _kernel32.SetConsoleTextAttribute(stdout, attr) writefunc(m.group(2), **opts) m = re.match(ansire, m.group(3)) finally: # Explicitly reset original attributes +ui.flush() _kernel32.SetConsoleTextAttribute(stdout, origattr) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH] test-check-help: fix to work on Windows
# HG changeset patch # User Matt Harbison # Date 1489948965 14400 # Sun Mar 19 14:42:45 2017 -0400 # Node ID f5f429a6300ef16a477ce175899088bd06a616b1 # Parent b1bebed54e9371708e1cd1eba63f0cedadfdf035 test-check-help: fix to work on Windows The initial problem was `hg files` prints paths with '\', which gets removed when piped (scanhelptopics.py failed to open 'hgext__init__.py'). Then, xargs was invoking `hg help` with 'backout\r (esc)', which setting binary mode prevents. diff --git a/tests/test-check-help.t b/tests/test-check-help.t --- a/tests/test-check-help.t +++ b/tests/test-check-help.t @@ -6,6 +6,9 @@ > from __future__ import absolute_import, print_function > import re > import sys + > if sys.platform == "win32": + > import os, msvcrt + > msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) > topics = set() > topicre = re.compile(r':hg:`help ([a-z0-9\-.]+)`') > for fname in sys.argv: @@ -20,6 +23,6 @@ Check if ":hg:`help TOPIC`" is valid: (use "xargs -n1 -t" to see which help commands are executed) - $ hg files 'glob:{hgext,mercurial}/**/*.py' \ + $ hg files 'glob:{hgext,mercurial}/**/*.py' | sed 's|\\|/|g' \ > | xargs python "$TESTTMP/scanhelptopics.py" \ > | xargs -n1 hg help > /dev/null ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 3] pager: fix the invocation of `more` on Windows
# HG changeset patch # User Matt Harbison # Date 1489983573 14400 # Mon Mar 20 00:19:33 2017 -0400 # Node ID a32b379ffe151b8b094dcd67ef5b6bd551203dbe # Parent b1bebed54e9371708e1cd1eba63f0cedadfdf035 pager: fix the invocation of `more` on Windows After 9335dc6b2a9c, invoking `more` no longer works. Instead, a warning is printed and the pager is disabled. Invoking `more.com` works. diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -839,7 +839,10 @@ # less(1), not more(1), and on debian it's # sensible-pager(1). We should probably also give the system # default editor command similar treatment. -envpager = encoding.environ.get('PAGER', 'more') +envpager = 'more' +if pycompat.osname == 'nt': +envpager = 'more.com' +envpager = encoding.environ.get('PAGER', envpager) pagercmd = self.config('pager', 'pager', envpager) if not pagercmd: return ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 3] [RFC] dispatch: setup color before pager
# HG changeset patch # User Matt Harbison # Date 1489985511 14400 # Mon Mar 20 00:51:51 2017 -0400 # Node ID 2a323109f8e7ec5548dd506c2cff05f27fa20c1e # Parent 6e72bb689e57c985b138c580acb4cad8053dc180 [RFC] dispatch: setup color before pager With the previous order, color was None for commands invoked with --pager=yes at the time the pager was spawned, which meant the switch over to ANSI mode on Windows didn't occur. That left the color.win32print() in 'auto' mode, which meant no color in the pager output. Non Windows platforms are capable of printing color with this option. diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -760,6 +760,13 @@ for ui_ in uis: ui_.setconfig('ui', 'interactive', 'off', '-y') +# setup color handling +coloropt = options['color'] +for ui_ in uis: +if coloropt: +ui_.setconfig('ui', 'color', coloropt, '--color') +color.setup(ui_) + if util.parsebool(options['pager']): ui.pager('internal-always-' + cmd) elif options['pager'] != 'auto': @@ -769,13 +776,6 @@ for ui_ in uis: ui_.insecureconnections = True -# setup color handling -coloropt = options['color'] -for ui_ in uis: -if coloropt: -ui_.setconfig('ui', 'color', coloropt, '--color') -color.setup(ui_) - if options['version']: return commands.version_(ui) if options['help']: ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 3] [RFC] color: allow color and pager to work on Windows with 'color.mode=auto'
# HG changeset patch # User Matt Harbison # Date 1489985292 14400 # Mon Mar 20 00:48:12 2017 -0400 # Node ID 6e72bb689e57c985b138c580acb4cad8053dc180 # Parent a32b379ffe151b8b094dcd67ef5b6bd551203dbe [RFC] color: allow color and pager to work on Windows with 'color.mode=auto' It took me awhile to figure out that '--config color.mode=ansi' would allow the MSYS pager to print color, even though the default config colors fine if the pager is disabled. This is a hacky attempt to improve 'auto'. The only thing that I can't figure out is why 'pager=no' causes the output to print a green background. It seems that the lack of the on-the-fly update causes this. Hopefully someone with more knowledge of color and pager knows, and/or can point out a better way. Previously, 'color.mode=auto' would color by setting console attributes, and then print the text. This doesn't help the pager at all. This will print with the ANSI color codes if a pager has been spawned, falling back to the previous method otherwise. Each of the built in `more` (more.com), python pager [1], and `less` from GnuWin32 print the raw ANSI color codes to the screen instead of colorizing. (The latter basically prints a blank screen if given '-R'.) The `less` that comes with MSYS on the other hand, will print color with or without '-R'. I expect that `more` and MSYS will be the most popular pagers, so this gives a better experience for them out of the box. If one of the more obscure pagers are used, setting color.pagermode will disable color for paged output. (As an aside, the fact that 'color.pagermode' is only consulted if the pager has been spawned [2] gave me the impression that color.setup() could be called multiple times, given that color is setup so early. But it actually is triggered when --pager=yes is given. The fact that this setting only works if paging is forced with --pager seems... surprising.) The _effects map is no longer updated directly because some values were getting overwritten with Win32 values on the first call to color.setup(), which prevented the color codes from being output when changing the ANSI when the pager is spawned. [1] https://pypi.python.org/pypi/pager [2] https://www.mercurial-scm.org/repo/hg/file/da7d19324b1e/mercurial/color.py#l205 diff --git a/mercurial/color.py b/mercurial/color.py --- a/mercurial/color.py +++ b/mercurial/color.py @@ -72,6 +72,8 @@ 'white_background': 47, } +_activeeffects = _effects.copy() + _defaultstyles = { 'grep.match': 'red bold', 'grep.linenumber': 'green', @@ -231,12 +233,14 @@ if mode == realmode and ui.formatted(): ui.warn(_('warning: failed to set color mode to %s\n') % mode) +_activeeffects = _effects.copy() + if realmode == 'win32': ui._terminfoparams.clear() if not w32effects: modewarn() return None -_effects.update(w32effects) +_activeeffects.update(w32effects) elif realmode == 'ansi': ui._terminfoparams.clear() elif realmode == 'terminfo': @@ -271,7 +275,7 @@ def valideffect(ui, effect): 'Determine if the effect is valid or not.' -return ((not ui._terminfoparams and effect in _effects) +return ((not ui._terminfoparams and effect in _activeeffects) or (effect in ui._terminfoparams or effect[:-11] in ui._terminfoparams)) @@ -305,9 +309,9 @@ for effect in ['none'] + effects.split()) stop = _effect_str(ui, 'none') else: -start = [str(_effects[e]) for e in ['none'] + effects.split()] +start = [str(_activeeffects[e]) for e in ['none'] + effects.split()] start = '\033[' + ';'.join(start) + 'm' -stop = '\033[' + str(_effects['none']) + 'm' +stop = '\033[' + str(_activeeffects['none']) + 'm' return ''.join([start, text, stop]) def colorlabel(ui, msg, label): diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -854,6 +854,12 @@ # auto-detection of things being formatted. self.setconfig('ui', 'formatted', self.formatted(), 'pager') self.setconfig('ui', 'interactive', False, 'pager') + +if self._colormode == 'win32' and not pagercmd.startswith('more.com'): +if not self.hasconfig('color', 'pagermode'): +self.setconfig('color', 'pagermode', 'ansi', source='pager') +color.setup(self) + if util.safehasattr(signal, "SIGPIPE"): signal.signal(signal.SIGPIPE, _catchterm) self._runpager(pagercmd) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 3] pager: fix the invocation of `more` on Windows
On Tue, 21 Mar 2017 17:40:58 -0400, Jun Wu wrote: Excerpts from Augie Fackler's message of 2017-03-21 17:34:39 -0400: On Mon, Mar 20, 2017 at 12:53:17AM -0400, Matt Harbison wrote: > pager: fix the invocation of `more` on Windows I've taken this one. And I'm sad. (Thanks! I blame windows for the sadness, not you.) This does not look like a complete fix. Users setting "pager.pager=more", or "pager.pager=somethingelse" will still have issues. You're correct about the former, but I don't understand the latter. It seems like *.com is the issue (I'm guessing cmd.exe handles it special, based on $PATHEXT). I tried with pager.pager=notepad, and pager.pager=C:\Progra~2\GnuWin32\bin\less, and it had no problem invoking either *.exe without the extension. A better fix seems to be disable shell=False for Windows. I dunno. If shell=True, you get a cryptic error and nothing else with a bad pager. If shell=False, a bad pager is simply disabled with a warning, and normal output. That seems more friendly. Since I think we are in agreement that there will be a special case here in _some_ form, what I should have done is to translate more -> more.com *after* getting the config on Windows, instead of setting the default value. I doubt there are any other *.com pagers, and I don't think anyone is trying to page through a *.bat file or anything like that. (And if they want to do something crazy with these odd "executables", pager.pager="cmd.exe /c more" worked for me, so I assume it works for *.bat, etc.) IDK how many Windows users would even bother to configure `more`, but we should be able to make it work. I'll send V2 tomorrow, if there aren't any other comments before then. > > After 9335dc6b2a9c, invoking `more` no longer works. Instead, a warning is > printed and the pager is disabled. Invoking `more.com` works. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 3 of 3] [RFC] dispatch: setup color before pager
(+CC: indygreg, since he added this functionality in 4e02418b4236) On Tue, 21 Mar 2017 17:36:29 -0400, Augie Fackler wrote: On Mon, Mar 20, 2017 at 12:53:19AM -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1489985511 14400 # Mon Mar 20 00:51:51 2017 -0400 # Node ID 2a323109f8e7ec5548dd506c2cff05f27fa20c1e # Parent 6e72bb689e57c985b138c580acb4cad8053dc180 [RFC] dispatch: setup color before pager Oy, these two I just dunno. I'll defer to other Windows experts. Heh. You have no idea how sad my Sunday was :-/ Just to be clear, these last two can't be taken as-is. The output on Windows without a pager is black text on a green background. I did a little more playing, and if we don't do something, this will be a regression. In 4.1, both of these commands colorize in MSYS: [extensions] color = [pager] pager = less $ hg log -l 5 --config extensions.pager= --config color.pagermode=ansi $ hg log -l 5 --config color.pagermode=ansi Now, neither of them do (both are now paged). You have to set '--pager=no' to get the color back, or add '--config color.mode=ansi'. But the latter breaks the output when disabling pager. And even if that magically worked, that doesn't help with switching between MSYS and cmd.exe, which is why I'd love to make 'auto' smarter. (I'd rather not resort to %include hacks). IIRC, the inter-operation between these two extensions was why the ability to register an afterload callback was added. I'll keep looking at this, but I suspect we need a color+pager expert more than a Windows expert. With the previous order, color was None for commands invoked with --pager=yes at the time the pager was spawned, which meant the switch over to ANSI mode on Windows didn't occur. That left the color.win32print() in 'auto' mode, which meant no color in the pager output. Non Windows platforms are capable of printing color with this option. diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -760,6 +760,13 @@ for ui_ in uis: ui_.setconfig('ui', 'interactive', 'off', '-y') +# setup color handling +coloropt = options['color'] +for ui_ in uis: +if coloropt: +ui_.setconfig('ui', 'color', coloropt, '--color') +color.setup(ui_) + if util.parsebool(options['pager']): ui.pager('internal-always-' + cmd) elif options['pager'] != 'auto': @@ -769,13 +776,6 @@ for ui_ in uis: ui_.insecureconnections = True -# setup color handling -coloropt = options['color'] -for ui_ in uis: -if coloropt: -ui_.setconfig('ui', 'color', coloropt, '--color') -color.setup(ui_) - if options['version']: return commands.version_(ui) if options['help']: ___ 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
[PATCH V2] pager: fix the invocation of `more` on Windows
# HG changeset patch # User Matt Harbison # Date 1489983573 14400 # Mon Mar 20 00:19:33 2017 -0400 # Node ID 8c2e2e2b2432bfa637ee569de11afcbc02b715b7 # Parent d0b9e9803caff5f87020688c49ac6cdf017039d7 pager: fix the invocation of `more` on Windows After 9335dc6b2a9c, with 'shell' being (mostly) set to False, invoking `more` no longer worked. Instead, a warning was printed and the pager was disabled. Invoking `more.com` works. Since a user may have configured 'pager.pager=more', do this substitution at the end. Surprisingly, `more` does allow for arguments, so those are preserved. This also allows `more` to work in MSYS. Setting 'shell=False' runs the executable via CreateProcess(), which has rather wonky rules for resolving an executable without an extension [1]. Resolving to *.com is not among them. Since 'shell=True' yields a cryptic error for a bad $PAGER, and a *.exe program will work without specifying the extension, sticking with current 'shell=False' seems like the right thing to do. I don't think there are any other *.com pagers out there, so this one special case seems OK. If somebody wants to do something crazy that requires cmd.exe, I was able to get normal paged output with 'pager.pager="cmd.exe /c more"'. I assume you can replace `more` with *.bat, *.vbs or various other creatures listed in $PATHEXT. [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -844,6 +844,13 @@ if not pagercmd: return +if pycompat.osname == 'nt': +# `more` cannot be invoked with shell=False, but `more.com` can. +# Hide this implementation detail from the user, so we can also get +# sane bad PAGER behavior. +if pagercmd == 'more' or pagercmd.startswith('more '): +pagercmd = 'more.com' + pagercmd[4:] + self.debug('starting pager for command %r\n' % command) self.flush() self.pageractive = True ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH evolve-ext] tests: add glob for Windows
> On Mar 23, 2017, at 3:13 AM, Pierre-Yves David > wrote: > > > >> On 03/21/2017 06:48 PM, Ryan McElroy wrote: >>> On 3/17/17 3:32 AM, Matt Harbison wrote: >>> # HG changeset patch >>> # User Matt Harbison >>> # Date 1489720627 14400 >>> # Thu Mar 16 23:17:07 2017 -0400 >>> # Node ID ab5c2bef148bfb60e1956a55de4b7ba00ebe1817 >>> # Parent 6a3248558b6929378450b572bb27406afe703ffd >>> tests: add glob for Windows >> >> This looks good to me. > > This one is pushed, thanks. > > Does this mean someone is actually running the evolve test on windows ? This is the first time I've run them in awhile. There's still something broke around pruning bookmarks. I was able to make it work a few years ago by calling invalidate(), but that seemed like a sledgehammer. I'll post more detail next time I have the repo in front of me. > -- > Pierre-Yves David ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH V3] pager: fix the invocation of `more` on Windows
# HG changeset patch # User Matt Harbison # Date 1489983573 14400 # Mon Mar 20 00:19:33 2017 -0400 # Node ID d0c2db2d9f13dca534c598de050eb1919ef79059 # Parent df82f375fa005b9c71b463182e6b54aa47fa5999 pager: fix the invocation of `more` on Windows After 9335dc6b2a9c, with 'shell' being (mostly) set to False, invoking `more` no longer worked. Instead, a warning was printed and the pager was disabled. Invoking `more.com` works. Since a user may have configured 'pager.pager=more', do this substitution at the end. Surprisingly, `more` does allow for arguments, so those are preserved. This also allows `more` to work in MSYS. Setting 'shell=False' runs the executable via CreateProcess(), which has rather wonky rules for resolving an executable without an extension [1]. Resolving to *.com is not among them. Since 'shell=True' yields a cryptic error for a bad $PAGER, and a *.exe program will work without specifying the extension, sticking with current 'shell=False' seems like the right thing to do. I don't think there are any other *.com pagers out there, so this one special case seems OK. If somebody wants to do something crazy that requires cmd.exe, I was able to get normal paged output with 'pager.pager="cmd.exe /c more"'. I assume you can replace `more` with *.bat, *.vbs or various other creatures listed in $PATHEXT. [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -844,6 +844,15 @@ if not pagercmd: return +if pycompat.osname == 'nt': +# `more` cannot be invoked with shell=False, but `more.com` can. +# Hide this implementation detail from the user, so we can also get +# sane bad PAGER behavior. If args are also given, the space in the +# command line forces shell=True, so that case doesn't need to be +# handled here. +if pagercmd == 'more': +pagercmd = 'more.com' + self.debug('starting pager for command %r\n' % command) self.flush() self.pageractive = True ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 3 of 3] [RFC] dispatch: setup color before pager
On Tue, 21 Mar 2017 23:10:36 -0400, Gregory Szorc wrote: On Tue, Mar 21, 2017 at 6:11 PM, Matt Harbison wrote: (+CC: indygreg, since he added this functionality in 4e02418b4236) On Tue, 21 Mar 2017 17:36:29 -0400, Augie Fackler wrote: On Mon, Mar 20, 2017 at 12:53:19AM -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1489985511 14400 # Mon Mar 20 00:51:51 2017 -0400 # Node ID 2a323109f8e7ec5548dd506c2cff05f27fa20c1e # Parent 6e72bb689e57c985b138c580acb4cad8053dc180 [RFC] dispatch: setup color before pager Oy, these two I just dunno. I'll defer to other Windows experts. Heh. You have no idea how sad my Sunday was :-/ Just to be clear, these last two can't be taken as-is. The output on Windows without a pager is black text on a green background. I did a little more playing, and if we don't do something, this will be a regression. In 4.1, both of these commands colorize in MSYS: [extensions] color = [pager] pager = less $ hg log -l 5 --config extensions.pager= --config color.pagermode=ansi $ hg log -l 5 --config color.pagermode=ansi Now, neither of them do (both are now paged). You have to set '--pager=no' to get the color back, or add '--config color.mode=ansi'. But the latter breaks the output when disabling pager. And even if that magically worked, that doesn't help with switching between MSYS and cmd.exe, which is why I'd love to make 'auto' smarter. (I'd rather not resort to %include hacks). So the whole reason behind 4e02418b4236 (as documented in the commit message) is that different pagers support different escape sequences. At the time, I couldn't figure out an elegant way to detect the pager's capabilities at run time. So, I added a config option that could be defined in certain environments (like a controlled msys environment where `less` was installed as the pager such as the one that Mozilla uses to build Firefox) so that pager+color would "just work" in both cmd.exe and an msys environment. More info at https://bugzilla.mozilla.org/show_bug.cgi?id=545432#c59 and below (search for my name). Core Mercurial should focus on behavior in a stock cmd.exe environment and be best-effort - but not broken - for cygwin, msys, etc. This is what a7d98606 aimed to achieve. If someone is running a non-cmd.exe terminal, I think it is up to the packager to enable a reasonable default (such as Mozilla setting color.pagermode in our MozillaBuild msys environment). That seems reasonable. But color.pagermode seems broken for auto pager, now that everything has transitioned to the core. It works on stable (if the color/pager load order is right). 4.1: 1) Color wrapped dispatch._runcommand() and pager wrapped color's wrapper. 2) Running a command will: a) Call the pager wrapper, set ui.pageractive, and spawn the pager if True b) Call the color wrapper, and examine ui.pageractive to see if it cares about color.pagermode c) Call the actual command Default branch: 1) Pager settings are forced on or off in dispatch. '--pager=on' fires up a pager; 'auto' pager mode defers spawning a pager. 2) Color is setup (examining ui.pageractive), and color.mode=auto is resolved 3) Run the command a) spawn a pager the pager, setting ui.pageractive=True I think this means that the process of spawning the pager needs to be able to call color.setup() again, so that it can reexamine ui.pageractive. Otherwise, the only way 'ui.pageractive' is ever true when color is getting setup is if --pager != 'auto|off'. IDK the implications of a second setup, and I'm perplexed by all of the various ui objects that exist. I didn't check yet to see if there's any possibility to output before the calls to ui.pager() now. (I wonder if there are instances in largefiles with all of its overrides.) Thoughts? Also, if you want a new challenge, the Windows console apparently supports 24-bit color ( https://blogs.msdn.microsoft.com/commandline/2016/09/22/24-bit-color-in-the-windows-console/) and ANSI+VT-100 escape sequences now. https://github.com/symfony/symfony/pull/18385 and https://github.com/Microsoft/BashOnWindows/issues/1173 are somewhat informative. We could likely detect the Windows version and active terminal to call SetConsoleMode with ENABLE_VIRTUAL_TERMINAL_PROCESSING. Then pager.color=ansi should "just work" on Windows. Thanks for the tip- I forgot about this. I'm not on Windows 10, so it isn't a high priority for me, but I'll look into it if I can find some spare time. IIRC, the inter-operation between these two extensions was why the ability to register an afterload callback was added. I'll keep looking at this, but I suspect we need a color+pager expert more than a Windows expert. I think that
Re: [PATCH V3] pager: fix the invocation of `more` on Windows
On Fri, 24 Mar 2017 10:17:46 -0400, Yuya Nishihara wrote: On Thu, 23 Mar 2017 21:57:50 -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1489983573 14400 # Mon Mar 20 00:19:33 2017 -0400 # Node ID d0c2db2d9f13dca534c598de050eb1919ef79059 # Parent df82f375fa005b9c71b463182e6b54aa47fa5999 pager: fix the invocation of `more` on Windows diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -844,6 +844,15 @@ if not pagercmd: return +if pycompat.osname == 'nt': +# `more` cannot be invoked with shell=False, but `more.com` can. +# Hide this implementation detail from the user, so we can also get +# sane bad PAGER behavior. If args are also given, the space in the +# command line forces shell=True, so that case doesn't need to be +# handled here. +if pagercmd == 'more': +pagercmd = 'more.com' Given MSYS nor MSYS2 doesn't provide more.exe by default, this seems fine. Can we document this hack in help just in case someone installed more.exe? I know this is an edge case, but instead of documenting how a user can't just say 'more' and spawn 'more.exe', what do you think about calling util.findexe() if pagercmd == 'more'? That finds 'more.com' too, so things should just work as if they were in cmd.exe. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH] pager: improve support for various flavors of `more` on Windows
# HG changeset patch # User Matt Harbison # Date 1490409608 14400 # Fri Mar 24 22:40:08 2017 -0400 # Node ID 6ee410f4af75125e9984c42100285ee70501655c # Parent 62728577ba63efee83460a09ef311b330a5fea13 pager: improve support for various flavors of `more` on Windows Hardcoding 'more' -> 'more.com' means that 'more.exe' from MSYS would need to be configured with its *.exe extension. This will resolve to either one, as cmd.exe would have done if the command ran through the shell. Something that's maybe problematic with this is it comes after 'pageractive' and various ui configs have been set by the calling method. But the other early exits in this method don't undo those changes either. diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -844,15 +844,6 @@ if not pagercmd: return -if pycompat.osname == 'nt': -# `more` cannot be invoked with shell=False, but `more.com` can. -# Hide this implementation detail from the user, so we can also get -# sane bad PAGER behavior. If args are also given, the space in the -# command line forces shell=True, so that case doesn't need to be -# handled here. -if pagercmd == 'more': -pagercmd = 'more.com' - self.debug('starting pager for command %r\n' % command) self.flush() self.pageractive = True @@ -879,6 +870,21 @@ # simple pager command configurations, we can degrade # gracefully and tell the user about their broken pager. shell = any(c in command for c in "|&;<>()$`\\\"' \t\n*?[#~=%") + +if pycompat.osname == 'nt' and not shell: +# Window's built-in `more` cannot be invoked with shell=False, but +# its `more.com` can. Hide this implementation detail from the +# user so we can also get sane bad PAGER behavior. MSYS has +# `more.exe`, so do a cmd.exe style resolution of the executable to +# determine which one to use. +fullcmd = util.findexe(command) +if not fullcmd: +self.warn(_("missing pager command '%s', skipping pager\n") + % command) +return + +command = fullcmd + try: pager = subprocess.Popen( command, shell=shell, bufsize=-1, ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH] repair: use context manager for lock management
# HG changeset patch # User Matt Harbison # Date 1490327243 14400 # Thu Mar 23 23:47:23 2017 -0400 # Node ID c053dc8a24afad24872397e5cd3f57411fc7d172 # Parent d0c2db2d9f13dca534c598de050eb1919ef79059 repair: use context manager for lock management If repo.lock() raised inside of the try block, 'tr' would have been None in the finally block where it tries to release(). Modernize the syntax instead of just winching the lock out of the try block. I found several other instances of acquiring the lock inside of the 'try', but those finally blocks handle None references. I also started switching some trivial try/finally blocks to context managers, but didn't get them all because indenting over 3x for lock, wlock and transaction would have spilled over 80 characters. That got me wondering if there should be a repo.rwlock(), to handle locking and unlocking in the proper order. It also looks like py27 supports supports multiple context managers for a single 'with' statement. Should I hold off on the rest until py26 is dropped? diff --git a/mercurial/repair.py b/mercurial/repair.py --- a/mercurial/repair.py +++ b/mercurial/repair.py @@ -214,15 +214,10 @@ for m in updatebm: bm[m] = repo[newbmtarget].node() -lock = tr = None -try: -lock = repo.lock() -tr = repo.transaction('repair') -bm.recordchange(tr) -tr.close() -finally: -tr.release() -lock.release() + +with repo.lock(): +with repo.transaction('repair') as tr: +bm.recordchange(tr) # remove undo files for undovfs, undofile in repo.undofiles(): ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 4] color: fix grammar in help text
# HG changeset patch # User Matt Harbison # Date 1490462963 14400 # Sat Mar 25 13:29:23 2017 -0400 # Node ID 22533c3af63d5a67d9210596eafd4b99ab9c7904 # Parent c60091fa1426892552dd6c0dd4b9c49e3c3da045 color: fix grammar in help text diff --git a/hgext/color.py b/hgext/color.py --- a/hgext/color.py +++ b/hgext/color.py @@ -7,7 +7,7 @@ '''enable Mercurial color mode (DEPRECATED) -This extensions enable Mercurial color mode. The feature is now directly +This extension enables Mercurial color mode. The feature is now directly available in Mercurial core. You can access it using:: [ui] ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 4 of 4] ui: rerun color.setup() once the pager has spawned to honor 'color.pagermode'
# HG changeset patch # User Matt Harbison # Date 1490483831 14400 # Sat Mar 25 19:17:11 2017 -0400 # Node ID 4713a38672f2d0790477b6c22180bd453f61851d # Parent 84bda5db69dbe3d550f45ccd6d6eda2aad760ee4 ui: rerun color.setup() once the pager has spawned to honor 'color.pagermode' Otherwise, ui.pageractive is False when color is setup in dispatch.py (without --pager=on), and this config option is ignored. diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -861,6 +861,12 @@ # auto-detection of things being formatted. self.setconfig('ui', 'formatted', wasformatted, 'pager') self.setconfig('ui', 'interactive', False, 'pager') + +# If pagermode differs from color.mode, reconfigure color now that +# pageractive is set. +cm = self._colormode +if cm != self.config('color', 'pagermode', cm): +color.setup(self) else: # If the pager can't be spawned in dispatch when --pager=on is # given, don't try again when the command runs, to avoid a duplicate ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 4] color: stop mutating the default effects map
# HG changeset patch # User Matt Harbison # Date 1490464217 14400 # Sat Mar 25 13:50:17 2017 -0400 # Node ID a263702b064a5a3ce1ca74b227e8e624e4b05874 # Parent 22533c3af63d5a67d9210596eafd4b99ab9c7904 color: stop mutating the default effects map A future change will make color.setup() callable a second time when the pager is spawned, in order to honor the 'color.pagermode' setting. The problem was that when 'color.mode=auto' was resolved to 'win32' in the first pass, the default ANSI effects were overwritten, making it impossible to honor 'pagermode=ansi'. Also, the two separate maps didn't have the same keys. The symmetric difference is 'dim' and 'italic' (from ANSI), and 'bold_background' (from win32). Thus, the update left entries that didn't belong for the current mode. As an added bonus, this now correctly enables color with MSYS `less` for a command like this, where pager is forced on: $ hg log --config color.pagermode=ansi --pager=yes Previously, the output was corrupted. The raw output, as seen through the ANSI blind `more.com` was: <-[-1;6mchangeset: 34840:50bcb95d40f5<-[-1m ... which MSYS `less -FRX` rendered as: 1;6mchangeset: 34840:50bcb95d40f51m ... (The two '<-' instances were actually an arrow character that TortoiseHg warned couldn't be encoded, and notepad++ translated to a single '?'.) diff --git a/mercurial/color.py b/mercurial/color.py --- a/mercurial/color.py +++ b/mercurial/color.py @@ -233,12 +233,14 @@ if mode == realmode and ui.formatted(): ui.warn(_('warning: failed to set color mode to %s\n') % mode) +ui._coloreffects = _effects.copy() + if realmode == 'win32': ui._terminfoparams.clear() if not w32effects: modewarn() return None -_effects.update(w32effects) +ui._coloreffects = w32effects.copy() elif realmode == 'ansi': ui._terminfoparams.clear() elif realmode == 'terminfo': @@ -273,7 +275,7 @@ def valideffect(ui, effect): 'Determine if the effect is valid or not.' -return ((not ui._terminfoparams and effect in _effects) +return ((not ui._terminfoparams and effect in ui._coloreffects) or (effect in ui._terminfoparams or effect[:-11] in ui._terminfoparams)) @@ -324,9 +326,9 @@ for effect in ['none'] + effects.split()) stop = _effect_str(ui, 'none') else: -start = [str(_effects[e]) for e in ['none'] + effects.split()] +start = [str(ui._coloreffects[e]) for e in ['none'] + effects.split()] start = '\033[' + ';'.join(start) + 'm' -stop = '\033[' + str(_effects['none']) + 'm' +stop = '\033[' + str(ui._coloreffects['none']) + 'm' return _mergeeffects(text, start, stop) _ansieffectre = re.compile(br'\x1b\[[0-9;]*m') diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -157,6 +157,7 @@ # Blocked time self.logblockedtimes = False # color mode: see mercurial/color.py for possible value +self._coloreffects = {} self._colormode = None self._terminfoparams = {} self._styles = {} @@ -176,6 +177,7 @@ self.environ = src.environ self.callhooks = src.callhooks self.insecureconnections = src.insecureconnections +self._coloreffects = src._coloreffects.copy() self._colormode = src._colormode self._terminfoparams = src._terminfoparams.copy() self._styles = src._styles.copy() ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 4] ui: defer setting pager related properties until the pager has spawned
# HG changeset patch # User Matt Harbison # Date 1490490720 14400 # Sat Mar 25 21:12:00 2017 -0400 # Node ID 84bda5db69dbe3d550f45ccd6d6eda2aad760ee4 # Parent a263702b064a5a3ce1ca74b227e8e624e4b05874 ui: defer setting pager related properties until the pager has spawned When --pager=on is given, dispatch.py spawns a pager before setting up color. If the pager failed to launch, ui.pageractive was left set to True, so color configured itself based on 'color.pagermode'. A typical MSYS setting would be 'color.mode=auto, color.pagermode=ansi'. In the failure case, this would print a warning, disable the pager, and then print the raw ANSI codes to the terminal. Care needs to be taken, because it appears that leaving ui.pageractive=True was the only thing that prevented an attempt at running the pager again from inside the command. This results in a double warning message, so pager is simply disabled on failure. I don't understand what chg is doing with pager, or how it signals a failure to spawn the pager. But this is no worse that the previous behavior. The ui config settings didn't need to be moved to fix this, but it seemed like the right thing to do for consistency. diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py --- a/mercurial/chgserver.py +++ b/mercurial/chgserver.py @@ -193,6 +193,7 @@ def _runpager(self, cmd): self._csystem(cmd, util.shellenviron(), type='pager', cmdtable={'attachio': attachio}) +return True return chgui(srcui) diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -850,15 +850,22 @@ self.debug('starting pager for command %r\n' % command) self.flush() -self.pageractive = True -# Preserve the formatted-ness of the UI. This is important -# because we mess with stdout, which might confuse -# auto-detection of things being formatted. -self.setconfig('ui', 'formatted', self.formatted(), 'pager') -self.setconfig('ui', 'interactive', False, 'pager') + +wasformatted = self.formatted() if util.safehasattr(signal, "SIGPIPE"): signal.signal(signal.SIGPIPE, _catchterm) -self._runpager(pagercmd) +if self._runpager(pagercmd): +self.pageractive = True +# Preserve the formatted-ness of the UI. This is important +# because we mess with stdout, which might confuse +# auto-detection of things being formatted. +self.setconfig('ui', 'formatted', wasformatted, 'pager') +self.setconfig('ui', 'interactive', False, 'pager') +else: +# If the pager can't be spawned in dispatch when --pager=on is +# given, don't try again when the command runs, to avoid a duplicate +# warning about a missing pager command. +self.disablepager() def _runpager(self, command): """Actually start the pager and set up file descriptors. @@ -868,7 +875,7 @@ """ if command == 'cat': # Save ourselves some work. -return +return False # If the command doesn't contain any of these characters, we # assume it's a binary and exec it directly. This means for # simple pager command configurations, we can degrade @@ -898,7 +905,7 @@ if e.errno == errno.ENOENT and not shell: self.warn(_("missing pager command '%s', skipping pager\n") % command) -return +return False raise # back up original file descriptors @@ -919,6 +926,8 @@ pager.stdin.close() pager.wait() +return True + def interface(self, feature): """what interface to use for interactive console features? ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 2 of 4] color: stop mutating the default effects map
On Sun, 26 Mar 2017 10:35:34 -0400, Yuya Nishihara wrote: On Sun, 26 Mar 2017 00:41:05 -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1490464217 14400 # Sat Mar 25 13:50:17 2017 -0400 # Node ID a263702b064a5a3ce1ca74b227e8e624e4b05874 # Parent 22533c3af63d5a67d9210596eafd4b99ab9c7904 color: stop mutating the default effects map I re-read the code, and noticed that both _effects and w32effects are mostly constants. Perhaps we can simply switch them by ui._colormode. if ui._colormode == 'win32': activeeffects = w32neffects else: activeeffects = _effects ... embed escape sequences by using activeeffects ... Will we get into trouble with each ui instance having a _colormode, but the activeeffects map effectively being global? I don't fully understand the purpose of all the separate ui objects. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 4 of 4] ui: rerun color.setup() once the pager has spawned to honor 'color.pagermode'
On Sun, 26 Mar 2017 10:44:01 -0400, Yuya Nishihara wrote: On Sun, 26 Mar 2017 00:41:07 -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1490483831 14400 # Sat Mar 25 19:17:11 2017 -0400 # Node ID 4713a38672f2d0790477b6c22180bd453f61851d # Parent 84bda5db69dbe3d550f45ccd6d6eda2aad760ee4 ui: rerun color.setup() once the pager has spawned to honor 'color.pagermode' Otherwise, ui.pageractive is False when color is setup in dispatch.py (without --pager=on), and this config option is ignored. diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -861,6 +861,12 @@ # auto-detection of things being formatted. self.setconfig('ui', 'formatted', wasformatted, 'pager') self.setconfig('ui', 'interactive', False, 'pager') + +# If pagermode differs from color.mode, reconfigure color now that +# pageractive is set. +cm = self._colormode +if cm != self.config('color', 'pagermode', cm): +color.setup(self) This also looks good. Maybe we can refactor color._modesetup() further so that we can do something like newmode = color.mode(self) if self._colormode != newmode: color.setup(self, newmode) Is a follow up OK? There are some warnings being printed in _modesetup() that I don't think we want firing more than once, so it may not be a trivial refactoring. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] repair: use context manager for lock management
On Sun, 26 Mar 2017 13:34:10 -0400, Gregory Szorc wrote: On Sun, Mar 26, 2017 at 4:20 AM, Yuya Nishihara wrote: On Fri, 24 Mar 2017 23:34:28 -0400, Matt Harbison wrote: > # HG changeset patch > # User Matt Harbison > # Date 1490327243 14400 > # Thu Mar 23 23:47:23 2017 -0400 > # Node ID c053dc8a24afad24872397e5cd3f57411fc7d172 > # Parent d0c2db2d9f13dca534c598de050eb1919ef79059 > repair: use context manager for lock management Sure. Queued this, thanks. > I found several other instances of acquiring the lock inside of the 'try', but > those finally blocks handle None references. I also started switching some > trivial try/finally blocks to context managers, but didn't get them all because > indenting over 3x for lock, wlock and transaction would have spilled over 80 > characters. That got me wondering if there should be a repo.rwlock(), to handle > locking and unlocking in the proper order. We have lockmod.release() helper. We also have util.ctxmanager(), but IMHO it doesn't improve code readability that much. > It also looks like py27 supports supports multiple context managers for a single > 'with' statement. Should I hold off on the rest until py26 is dropped? I think there is room for a helper context manager (like repo.rwlock()) that obtains multiple locks and/or a transaction. This would cut down on a lot of excessive indentation while simultaneously ensuring we're doing the correct thing with regards to locking and transaction semantics. The excessive indentation is why I raised the issue. I went looking for how to use util.ctxmanager, and can't find a single usage instance in the entire history. I went back to the ML, and it seems like mpm ruled out using it [1]. The referenced context manager series he mentioned taking 80% of seems to be something else [2]. I'm not sure if we want to revisit that decision, and even if so, I'm not sure if we want to start using a crutch for py26 if we are close to dumping it. I only got off on this tangent when I noticed the first-lock-inside-try construct while trying to figure out bookmark pruning test failures on Windows. So I don't have a strong opinion either way. [1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2016-January/078755.html [2] https://www.mercurial-scm.org/pipermail/mercurial-devel/2016-January/078262.html ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 2 V3] serve: make the URL the same for `hg serve` and `hg serve -S`
# HG changeset patch # User Matt Harbison # Date 1488146777 18000 # Sun Feb 26 17:06:17 2017 -0500 # Node ID d584ca4bc33bd2ebeaf9a7bd86440b3cdcecc138 # Parent 0ff9bef3e0f67422cf29c200fa4a671d861d060b serve: make the URL the same for `hg serve` and `hg serve -S` It's perfectly workable to serve up the parent repo without the -S for push and pull, as long as there are no subrepo changes in play. Therefore, having a different URL for the main repo based on the presence of this option seems like it would get annoying. diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py +++ b/mercurial/hgweb/hgweb_mod.py @@ -335,7 +335,7 @@ req.url = req.env['SCRIPT_NAME'] if not req.url.endswith('/'): req.url += '/' -if 'REPO_NAME' in req.env: +if req.env.get('REPO_NAME'): req.url += req.env['REPO_NAME'] + '/' if 'PATH_INFO' in req.env: diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -257,7 +257,7 @@ repos = dict(self.repos) -if not virtual or (virtual == 'index' and virtual not in repos): +if (not virtual or virtual == 'index') and virtual not in repos: req.respond(HTTP_OK, ctype) return self.makeindex(req, tmpl) @@ -269,8 +269,15 @@ req.respond(HTTP_OK, ctype) return self.makeindex(req, tmpl, subdir) -virtualrepo = virtual -while virtualrepo: +def _virtualdirs(): +yield virtual + +for p in util.finddirs(virtual): +yield p + +yield '' + +for virtualrepo in _virtualdirs(): real = repos.get(virtualrepo) if real: req.env['REPO_NAME'] = virtualrepo @@ -284,11 +291,6 @@ except error.RepoError as inst: raise ErrorResponse(HTTP_SERVER_ERROR, str(inst)) -up = virtualrepo.rfind('/') -if up < 0: -break -virtualrepo = virtualrepo[:up] - # browse subdirectories subdir = virtual + '/' if [r for r in repos if r.startswith(subdir)]: diff --git a/mercurial/server.py b/mercurial/server.py --- a/mercurial/server.py +++ b/mercurial/server.py @@ -147,8 +147,7 @@ # message as long as webconf is None. if repo: webconf = dict() -cmdutil.addwebdirpath(repo, repo.wvfs.basename(repo.root) + '/', - webconf) +cmdutil.addwebdirpath(repo, "", webconf) else: servui = ui diff --git a/tests/test-subrepo-deep-nested-change.t b/tests/test-subrepo-deep-nested-change.t --- a/tests/test-subrepo-deep-nested-change.t +++ b/tests/test-subrepo-deep-nested-change.t @@ -75,29 +75,29 @@ #if serve $ hg serve -R main --debug -S -p $HGPORT -d --pid-file=hg1.pid -E error.log -A access.log - adding main/ = $TESTTMP/main (glob) - adding sub1/ = $TESTTMP/main/sub1 (glob) - adding sub2/ = $TESTTMP/main/sub1/sub2 (glob) + adding = $TESTTMP/main (glob) + adding ../sub1/ = $TESTTMP/main/sub1 (glob) + adding ../sub2/ = $TESTTMP/main/sub1/sub2 (glob) listening at http://*:$HGPORT/ (bound to *:$HGPORT) (glob) - adding main/ = $TESTTMP/main (glob) - adding sub1/ = $TESTTMP/main/sub1 (glob) - adding sub2/ = $TESTTMP/main/sub1/sub2 (glob) + adding = $TESTTMP/main (glob) + adding ../sub1/ = $TESTTMP/main/sub1 (glob) + adding ../sub2/ = $TESTTMP/main/sub1/sub2 (glob) $ cat hg1.pid >> $DAEMON_PIDS - $ hg clone http://localhost:$HGPORT/main httpclone --config progress.disable=True + $ hg clone http://localhost:$HGPORT httpclone --config progress.disable=True requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 3 changes to 3 files updating to branch default - cloning subrepo sub1 from http://localhost:$HGPORT/sub1 + cloning subrepo sub1 from http://localhost:$HGPORT/../sub1 requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 3 changes to 3 files - cloning subrepo sub1/sub2 from http://localhost:$HGPORT/sub2 (glob) + cloning subrepo sub1/sub2 from http://localhost:$HGPORT/../sub2 (glob) requesting all changes adding changesets adding manifests @@ -106,15 +106,15 @@ 3 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cat access.log - * "GET /main?cmd=capabilities HTTP/1.1" 200 - (glob) - * "GET /main?cmd=batch HTTP/1.
[PATCH 1 of 2 V3] serve: add support for Mercurial subrepositories
# HG changeset patch # User Matt Harbison # Date 1488146743 18000 # Sun Feb 26 17:05:43 2017 -0500 # Node ID 0ff9bef3e0f67422cf29c200fa4a671d861d060b # Parent c60091fa1426892552dd6c0dd4b9c49e3c3da045 serve: add support for Mercurial subrepositories I've been using `hg serve --web-conf ...` with a simple '/=projects/**' [paths] configuration for awhile without issue. Let's ditch the need for the manual configuration in this case, and limit the repos served to the actual subrepos. This doesn't attempt to handle the case where a new subrepo appears while the server is running. That could probably be handled with a hook if somebody wants it. But it's such a rare case, it probably doesn't matter for the temporary serves. Unfortunately, the root of the webserver when serving multiple repos is the implicit html index file. This makes the URL different for `hg serve` vs `hg serve -S`, because the top level repo then needs to be part of the path. That will be fixed next. diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -2285,6 +2285,15 @@ bad.extend(f for f in rejected if f in match.files()) return bad +def addwebdirpath(repo, serverpath, webconf): +webconf[serverpath] = repo.root +repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root)) + +for r in repo.revs('filelog("path:.hgsub")'): +ctx = repo[r] +for subpath in ctx.substate: +ctx.sub(subpath).addwebdirpath(serverpath, webconf) + def forget(ui, repo, match, prefix, explicitonly): join = lambda f: os.path.join(prefix, f) bad = [] diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -4602,7 +4602,8 @@ ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')), ('', 'style', '', _('template style to use'), _('STYLE')), ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')), -('', 'certificate', '', _('SSL certificate file'), _('FILE'))], +('', 'certificate', '', _('SSL certificate file'), _('FILE'))] + + subrepoopts, _('[OPTION]...'), optionalrepo=True) def serve(ui, repo, **opts): diff --git a/mercurial/help/subrepos.txt b/mercurial/help/subrepos.txt --- a/mercurial/help/subrepos.txt +++ b/mercurial/help/subrepos.txt @@ -136,6 +136,11 @@ subrepository changes are available when referenced by top-level repositories. Push is a no-op for Subversion subrepositories. +:serve: serve does not recurse into subrepositories unless +-S/--subrepos is specified. Git and Subversion subrepositories +are currently silently ignored. Mercurial subrepositories with a +URL source are also silently ignored. + :status: status does not recurse into subrepositories unless -S/--subrepos is specified. Subrepository changes are displayed as regular Mercurial changes on the subrepository diff --git a/mercurial/server.py b/mercurial/server.py --- a/mercurial/server.py +++ b/mercurial/server.py @@ -15,6 +15,7 @@ from . import ( chgserver, +cmdutil, commandserver, error, hgweb, @@ -130,11 +131,24 @@ baseui = ui webconf = opts.get('web_conf') or opts.get('webdir_conf') if webconf: +if opts.get('subrepos'): +raise error.Abort(_('--web-conf cannot be used with --subrepos')) + # load server settings (e.g. web.port) to "copied" ui, which allows # hgwebdir to reload webconf cleanly servui = ui.copy() servui.readconfig(webconf, sections=['web']) alluis.add(servui) +elif opts.get('subrepos'): +servui = ui.copy() +alluis.add(servui) + +# If repo is None, hgweb.createapp() already raises a proper abort +# message as long as webconf is None. +if repo: +webconf = dict() +cmdutil.addwebdirpath(repo, repo.wvfs.basename(repo.root) + '/', + webconf) else: servui = ui diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -444,6 +444,15 @@ self._ctx = ctx self._path = path +def addwebdirpath(self, serverpath, webconf): +"""Add the hgwebdir entries for this subrepo, and any of its subrepos. + +``serverpath`` is the path component of the URL for this repo. + +``webconf`` is the dictionary of hgwebdir entries. +""" +pass + def storeclean(self, path): &qu
[PATCH 3 of 3 V2] ui: rerun color.setup() once the pager has spawned to honor 'color.pagermode'
# HG changeset patch # User Matt Harbison # Date 1490483831 14400 # Sat Mar 25 19:17:11 2017 -0400 # Node ID 3fa40378c88e3b9149054de48b9b880d93653488 # Parent 1c73c5cde39463e03c3c7be10b6fe1256a6e5143 ui: rerun color.setup() once the pager has spawned to honor 'color.pagermode' Otherwise, ui.pageractive is False when color is setup in dispatch.py (without --pager=on), and this config option is ignored. diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -859,6 +859,12 @@ # auto-detection of things being formatted. self.setconfig('ui', 'formatted', wasformatted, 'pager') self.setconfig('ui', 'interactive', False, 'pager') + +# If pagermode differs from color.mode, reconfigure color now that +# pageractive is set. +cm = self._colormode +if cm != self.config('color', 'pagermode', cm): +color.setup(self) else: # If the pager can't be spawned in dispatch when --pager=on is # given, don't try again when the command runs, to avoid a duplicate ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 3 V2] ui: defer setting pager related properties until the pager has spawned
# HG changeset patch # User Matt Harbison # Date 1490490720 14400 # Sat Mar 25 21:12:00 2017 -0400 # Node ID 1c73c5cde39463e03c3c7be10b6fe1256a6e5143 # Parent 2566b7eac73c4851edc21b73a833f86bf878285e ui: defer setting pager related properties until the pager has spawned When --pager=on is given, dispatch.py spawns a pager before setting up color. If the pager failed to launch, ui.pageractive was left set to True, so color configured itself based on 'color.pagermode'. A typical MSYS setting would be 'color.mode=auto, color.pagermode=ansi'. In the failure case, this would print a warning, disable the pager, and then print the raw ANSI codes to the terminal. Care needs to be taken, because it appears that leaving ui.pageractive=True was the only thing that prevented an attempt at running the pager again from inside the command. This results in a double warning message, so pager is simply disabled on failure. The ui config settings didn't need to be moved to fix this, but it seemed like the right thing to do for consistency. diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py --- a/mercurial/chgserver.py +++ b/mercurial/chgserver.py @@ -193,6 +193,7 @@ def _runpager(self, cmd): self._csystem(cmd, util.shellenviron(), type='pager', cmdtable={'attachio': attachio}) +return True return chgui(srcui) diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -848,15 +848,22 @@ self.debug('starting pager for command %r\n' % command) self.flush() -self.pageractive = True -# Preserve the formatted-ness of the UI. This is important -# because we mess with stdout, which might confuse -# auto-detection of things being formatted. -self.setconfig('ui', 'formatted', self.formatted(), 'pager') -self.setconfig('ui', 'interactive', False, 'pager') + +wasformatted = self.formatted() if util.safehasattr(signal, "SIGPIPE"): signal.signal(signal.SIGPIPE, _catchterm) -self._runpager(pagercmd) +if self._runpager(pagercmd): +self.pageractive = True +# Preserve the formatted-ness of the UI. This is important +# because we mess with stdout, which might confuse +# auto-detection of things being formatted. +self.setconfig('ui', 'formatted', wasformatted, 'pager') +self.setconfig('ui', 'interactive', False, 'pager') +else: +# If the pager can't be spawned in dispatch when --pager=on is +# given, don't try again when the command runs, to avoid a duplicate +# warning about a missing pager command. +self.disablepager() def _runpager(self, command): """Actually start the pager and set up file descriptors. @@ -866,7 +873,7 @@ """ if command == 'cat': # Save ourselves some work. -return +return False # If the command doesn't contain any of these characters, we # assume it's a binary and exec it directly. This means for # simple pager command configurations, we can degrade @@ -896,7 +903,7 @@ if e.errno == errno.ENOENT and not shell: self.warn(_("missing pager command '%s', skipping pager\n") % command) -return +return False raise # back up original file descriptors @@ -917,6 +924,8 @@ pager.stdin.close() pager.wait() +return True + def interface(self, feature): """what interface to use for interactive console features? ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 3 V2] color: stop mutating the default effects map
# HG changeset patch # User Matt Harbison # Date 1490464217 14400 # Sat Mar 25 13:50:17 2017 -0400 # Node ID 2566b7eac73c4851edc21b73a833f86bf878285e # Parent e86eb75e74ce1b0803c26d86a229b9b711f6d76a color: stop mutating the default effects map A future change will make color.setup() callable a second time when the pager is spawned, in order to honor the 'color.pagermode' setting. The problem was that when 'color.mode=auto' was resolved to 'win32' in the first pass, the default ANSI effects were overwritten, making it impossible to honor 'pagermode=ansi'. Also, the two separate maps didn't have the same keys. The symmetric difference is 'dim' and 'italic' (from ANSI), and 'bold_background' (from win32). Thus, the update left entries that didn't belong for the current mode. This bled through `hg debugcolor`, where the unsupported ANSI keys were listed in 'win32' mode. As an added bonus, this now correctly enables color with MSYS `less` for a command like this, where pager is forced on: $ hg log --config color.pagermode=ansi --pager=yes --color=auto Previously, the output was corrupted. The raw output, as seen through the ANSI blind `more.com` was: <-[-1;6mchangeset: 34840:3580d1197af9<-[-1m ... which MSYS `less -FRX` rendered as: 1;6mchangeset: 34840:3580d1197af91m ... (The two '<-' instances were actually an arrow character that TortoiseHg warned couldn't be encoded, and notepad++ translated to a single '?'.) Returning an empty map for 'ui._colormode == None' seems better that defaulting to '_effects' (since some keys are mode dependent), and is better than None, which blows up `hg debugcolor --color=never`. diff --git a/mercurial/color.py b/mercurial/color.py --- a/mercurial/color.py +++ b/mercurial/color.py @@ -238,7 +238,6 @@ if not w32effects: modewarn() return None -_effects.update(w32effects) elif realmode == 'ansi': ui._terminfoparams.clear() elif realmode == 'terminfo': @@ -271,9 +270,17 @@ % (e, status)) ui._styles[status] = ' '.join(good) +def _activeeffects(ui): +'''Return the effects map for the color mode set on the ui.''' +if ui._colormode == 'win32': +return w32effects +elif ui._colormode != None: +return _effects +return {} + def valideffect(ui, effect): 'Determine if the effect is valid or not.' -return ((not ui._terminfoparams and effect in _effects) +return ((not ui._terminfoparams and effect in _activeeffects(ui)) or (effect in ui._terminfoparams or effect[:-11] in ui._terminfoparams)) @@ -324,9 +331,10 @@ for effect in ['none'] + effects.split()) stop = _effect_str(ui, 'none') else: -start = [str(_effects[e]) for e in ['none'] + effects.split()] +activeeffects = _activeeffects(ui) +start = [str(activeeffects[e]) for e in ['none'] + effects.split()] start = '\033[' + ';'.join(start) + 'm' -stop = '\033[' + str(_effects['none']) + 'm' +stop = '\033[' + str(activeeffects['none']) + 'm' return _mergeeffects(text, start, stop) _ansieffectre = re.compile(br'\x1b\[[0-9;]*m') diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -360,7 +360,7 @@ def _debugdisplaycolor(ui): ui = ui.copy() ui._styles.clear() -for effect in color._effects.keys(): +for effect in color._activeeffects(ui).keys(): ui._styles[effect] = effect if ui._terminfoparams: for k, v in ui.configitems('color'): ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 2 V3] serve: add support for Mercurial subrepositories
On Tue, 28 Mar 2017 10:11:15 -0400, Yuya Nishihara wrote: On Sun, 26 Mar 2017 23:04:30 -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1488146743 18000 # Sun Feb 26 17:05:43 2017 -0500 # Node ID 0ff9bef3e0f67422cf29c200fa4a671d861d060b # Parent c60091fa1426892552dd6c0dd4b9c49e3c3da045 serve: add support for Mercurial subrepositories +def addwebdirpath(repo, serverpath, webconf): +webconf[serverpath] = repo.root +repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root)) + +for r in repo.revs('filelog("path:.hgsub")'): +ctx = repo[r] +for subpath in ctx.substate: +ctx.sub(subpath).addwebdirpath(serverpath, webconf) [...] --- a/mercurial/server.py +++ b/mercurial/server.py @@ -15,6 +15,7 @@ from . import ( chgserver, +cmdutil, commandserver, error, hgweb, @@ -130,11 +131,24 @@ baseui = ui webconf = opts.get('web_conf') or opts.get('webdir_conf') if webconf: +if opts.get('subrepos'): +raise error.Abort(_('--web-conf cannot be used with --subrepos')) + # load server settings (e.g. web.port) to "copied" ui, which allows # hgwebdir to reload webconf cleanly servui = ui.copy() servui.readconfig(webconf, sections=['web']) alluis.add(servui) +elif opts.get('subrepos'): +servui = ui.copy() +alluis.add(servui) No need to make a copy of ui since nothing loaded into servui. +@annotatesubrepoerror +def addwebdirpath(self, serverpath, webconf): +# The URL request contains the subrepo source path, not the local +# subrepo path. The distinction matters for 'foo = ../foo' type +# entries. It isn't possible to serve up 'foo = http://..' type +# entries, because the server path is relative to this local server. +src = self._state[0] +if util.url(src).islocal(): +path = util.normpath(serverpath + src) +cmdutil.addwebdirpath(self._repo, path + '/', webconf) What happens if src is '../../escape_from_web_root' ? I don't think it's correct to lay out subrepositories by peer URL since we're exporting a _local_ clone. If you do "hg clone sub1 sub2", you'll see sub1 in local-path layout. "hg serve -S" just allows us to see sub1 over http. That was actually how I first coded it, but switched it because it wasn't handling the test in test-subrepo-deep-nested-change.t properly. I forget what exactly the problem was. I'll take another look this weekend. Maybe it's okay to add all repositories found under repo.root to webconf. For strictness, we could check if a subrepo path exists in .hgsub of any revision. I'd like to avoid searching through the directory tree, if possible. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 2 of 2 V3] serve: make the URL the same for `hg serve` and `hg serve -S`
On Tue, 28 Mar 2017 10:02:34 -0400, Yuya Nishihara wrote: On Sun, 26 Mar 2017 23:04:31 -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1488146777 18000 # Sun Feb 26 17:06:17 2017 -0500 # Node ID d584ca4bc33bd2ebeaf9a7bd86440b3cdcecc138 # Parent 0ff9bef3e0f67422cf29c200fa4a671d861d060b serve: make the URL the same for `hg serve` and `hg serve -S` It's perfectly workable to serve up the parent repo without the -S for push and pull, as long as there are no subrepo changes in play. Therefore, having a different URL for the main repo based on the presence of this option seems like it would get annoying. This looks good, but more detailed commit message will help since some changes in hgweb/hgwebdir are really subtle. Other than noting that this change allows repos to be hosted at "", is there something else to mention on this one? ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH] sslutil: clarify internal documentation
# HG changeset patch # User Matt Harbison # Date 1490795674 14400 # Wed Mar 29 09:54:34 2017 -0400 # Node ID 9505a8771bb00e56230e4c4b265e8369e659a54f # Parent 2632df096fc0ac7582382b1f94ea4b9ad0bce8f2 sslutil: clarify internal documentation I ran into this python issue with an incomplete certificate chain on Windows recently, and this is the clarification that came from that experimenting. The comment I left on the bug tracker [1] with a reference to the CPython code [2] indicates that the original problem I had is a different bug, but happened to be mentioned under issue20916 on the Python bug tracker. [1] https://bz.mercurial-scm.org/show_bug.cgi?id=5313#c7 [2] https://hg.python.org/cpython/file/v2.7.12/Modules/_ssl.c#l628 diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py --- a/mercurial/sslutil.py +++ b/mercurial/sslutil.py @@ -414,8 +414,10 @@ # a hint to the user. # Only modern ssl module exposes SSLContext.get_ca_certs() so we can # only show this warning if modern ssl is available. -# The exception handler is here because of -# https://bugs.python.org/issue20916. +# The exception handler is here to handle bugs around cert attributes: +# https://bugs.python.org/issue20916#msg213479. (See issues5313.) +# When the main 20916 bug occurs, 'sslcontext.get_ca_certs()' is a +# non-empty list, but the following conditional is otherwise True. try: if (caloaded and settings['verifymode'] == ssl.CERT_REQUIRED and modernssl and not sslcontext.get_ca_certs()): ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH] templatefilter: add support for 'long' to json()
# HG changeset patch # User Matt Harbison # Date 1491020477 14400 # Sat Apr 01 00:21:17 2017 -0400 # Node ID a3d441253abc38df20c9890b207c1ab454bb691d # Parent 2632df096fc0ac7582382b1f94ea4b9ad0bce8f2 templatefilter: add support for 'long' to json() When disabling the '#requires serve' check in test-hgwebdir.t and running it on Windows, several 500 errors popped up when querying '?style=json', with the following in the error log: File "...\\mercurial\\templater.py", line 393, in runfilter "keyword '%s'") % (filt.func_name, dt)) Abort: template filter 'json' is not compatible with keyword 'lastchange' The swallowed exception at that point was: File "...\\mercurial\\templatefilters.py", line 242, in json raise TypeError('cannot encode type %s' % obj.__class__.__name__) TypeError: cannot encode type long This corresponds to 'lastchange' being populated by hgweb.common.get_stat(), which uses os.stat().st_mtime. os.stat_float_times() is being disabled in util, so the type for the times is 'long' on Windows, and 'int' on Linux. diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py --- a/mercurial/templatefilters.py +++ b/mercurial/templatefilters.py @@ -221,7 +221,8 @@ def json(obj): if obj is None or obj is False or obj is True: return {None: 'null', False: 'false', True: 'true'}[obj] -elif isinstance(obj, int) or isinstance(obj, float): +elif (isinstance(obj, int) or isinstance(obj, long) + or isinstance(obj, float)): return str(obj) elif isinstance(obj, str): return '"%s"' % encoding.jsonescape(obj, paranoid=True) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] templatefilter: add support for 'long' to json()
On Sat, 01 Apr 2017 14:06:24 -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1491020477 14400 # Sat Apr 01 00:21:17 2017 -0400 # Node ID a3d441253abc38df20c9890b207c1ab454bb691d # Parent 2632df096fc0ac7582382b1f94ea4b9ad0bce8f2 templatefilter: add support for 'long' to json() When disabling the '#requires serve' check in test-hgwebdir.t and running it on Windows, several 500 errors popped up when querying '?style=json', with the following in the error log: BTW, does anybody know why the 'serve' tests are disabled on Windows? hghave.has_serve() simply says "platform and python can manage 'hg serve -d'", and the commit that introduces it doesn't explain what the issues were. I made has_serve() return True unconditionally, and while there were errors in the newly run code, none looked like 'serve -d' were malfunctioning. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] templatefilter: add support for 'long' to json()
On Sat, 01 Apr 2017 15:20:02 -0400, Gregory Szorc wrote: On Sat, Apr 1, 2017 at 11:06 AM, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1491020477 14400 # Sat Apr 01 00:21:17 2017 -0400 # Node ID a3d441253abc38df20c9890b207c1ab454bb691d # Parent 2632df096fc0ac7582382b1f94ea4b9ad0bce8f2 templatefilter: add support for 'long' to json() When disabling the '#requires serve' check in test-hgwebdir.t and running it on Windows, several 500 errors popped up when querying '?style=json', with the following in the error log: File "...\\mercurial\\templater.py", line 393, in runfilter "keyword '%s'") % (filt.func_name, dt)) Abort: template filter 'json' is not compatible with keyword 'lastchange' The swallowed exception at that point was: File "...\\mercurial\\templatefilters.py", line 242, in json raise TypeError('cannot encode type %s' % obj.__class__.__name__) TypeError: cannot encode type long This corresponds to 'lastchange' being populated by hgweb.common.get_stat(), which uses os.stat().st_mtime. os.stat_float_times() is being disabled in util, so the type for the times is 'long' on Windows, and 'int' on Linux. diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py --- a/mercurial/templatefilters.py +++ b/mercurial/templatefilters.py @@ -221,7 +221,8 @@ def json(obj): if obj is None or obj is False or obj is True: return {None: 'null', False: 'false', True: 'true'}[obj] -elif isinstance(obj, int) or isinstance(obj, float): +elif (isinstance(obj, int) or isinstance(obj, long) + or isinstance(obj, float)): isinstance() accepts a tuple of types as its second argument. Let's use that to make this code shorter. (This could probably be done in flight.) Ah, thanks. I meant to look into if it did, but spent a lot of time tracking down the int vs float vs long part, and forgot. I've got a growing series of fixes for hg serve tests on Windows, so I'll just send a v2 if nobody does a fix-in-flight in the meantime. return str(obj) elif isinstance(obj, str): return '"%s"' % encoding.jsonescape(obj, paranoid=True) ___ 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
[PATCH 3 of 8] test-http: update output for Windows
# HG changeset patch # User Matt Harbison # Date 1491085851 14400 # Sat Apr 01 18:30:51 2017 -0400 # Node ID ade96da6680ba993018effdf73b391fc6bed0531 # Parent 54fd6d15228e8e2f8e735beac0db0930c60af9ad test-http: update output for Windows The http test simply wasn't updated in 161ab32b44a1 for Windows. It looks like the https test meant to glob away the error message in 3e2d8120528b, but forgot the '*', and was subsequently removed in 408f2202bd80. diff --git a/tests/test-http.t b/tests/test-http.t --- a/tests/test-http.t +++ b/tests/test-http.t @@ -19,7 +19,7 @@ #if windows $ hg serve -p $HGPORT1 2>&1 - abort: cannot start server at ':$HGPORT1': * (glob) + abort: cannot start server at 'localhost:$HGPORT1': * (glob) [255] #else $ hg serve -p $HGPORT1 2>&1 diff --git a/tests/test-https.t b/tests/test-https.t --- a/tests/test-https.t +++ b/tests/test-https.t @@ -36,7 +36,7 @@ #if windows $ hg serve -p $HGPORT --certificate=$PRIV 2>&1 - abort: cannot start server at 'localhost:$HGPORT': + abort: cannot start server at 'localhost:$HGPORT': * (glob) [255] #else $ hg serve -p $HGPORT --certificate=$PRIV 2>&1 ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 8] tests: add globs for Windows
# HG changeset patch # User Matt Harbison # Date 1491072519 14400 # Sat Apr 01 14:48:39 2017 -0400 # Node ID 46f601b676cecfcc318f6852fe6ab6962703d2be # Parent d1a1f21e86b2f976f5e968371f6cff145b98712a tests: add globs for Windows diff --git a/tests/test-bookmarks-pushpull.t b/tests/test-bookmarks-pushpull.t --- a/tests/test-bookmarks-pushpull.t +++ b/tests/test-bookmarks-pushpull.t @@ -581,12 +581,12 @@ be exchanged) $ hg -R repo1 incoming -B - comparing with $TESTTMP/bmcomparison/source + comparing with $TESTTMP/bmcomparison/source (glob) searching for changed bookmarks no changed bookmarks found [1] $ hg -R repo1 outgoing -B - comparing with $TESTTMP/bmcomparison/source + comparing with $TESTTMP/bmcomparison/source (glob) searching for changed bookmarks no changed bookmarks found [1] diff --git a/tests/test-https.t b/tests/test-https.t --- a/tests/test-https.t +++ b/tests/test-https.t @@ -97,11 +97,12 @@ [255] #endif -Specifying a per-host certificate file that doesn't exist will abort +Specifying a per-host certificate file that doesn't exist will abort. The full +C:/path/to/msysroot will print on Windows. $ hg --config hostsecurity.localhost:verifycertsfile=/does/not/exist clone https://localhost:$HGPORT/ warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?) - abort: path specified by hostsecurity.localhost:verifycertsfile does not exist: /does/not/exist + abort: path specified by hostsecurity.localhost:verifycertsfile does not exist: */does/not/exist (glob) [255] A malformed per-host certificate file will raise an error diff --git a/tests/test-largefiles-cache.t b/tests/test-largefiles-cache.t --- a/tests/test-largefiles-cache.t +++ b/tests/test-largefiles-cache.t @@ -223,7 +223,7 @@ $ hg push http://localhost:$HGPORT1 -f --config files.usercache=nocache pushing to http://localhost:$HGPORT1/ searching for changes - abort: remotestore: could not open file $TESTTMP/src/.hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020: HTTP Error 403: ssl required + abort: remotestore: could not open file $TESTTMP/src/.hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020: HTTP Error 403: ssl required (glob) [255] $ rm .hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020 diff --git a/tests/test-merge-criss-cross.t b/tests/test-merge-criss-cross.t --- a/tests/test-merge-criss-cross.t +++ b/tests/test-merge-criss-cross.t @@ -116,11 +116,11 @@ $ f --dump --recurse * d2: directory with 2 files - d2/f3: + d2/f3: (glob) >>> 0 base <<< - d2/f4: + d2/f4: (glob) >>> 0 base <<< @@ -222,11 +222,11 @@ $ f --dump --recurse * d2: directory with 2 files - d2/f3: + d2/f3: (glob) >>> 0 base <<< - d2/f4: + d2/f4: (glob) >>> 0 base <<< @@ -308,11 +308,11 @@ $ f --dump --recurse * d2: directory with 2 files - d2/f3: + d2/f3: (glob) >>> 0 base <<< - d2/f4: + d2/f4: (glob) >>> 0 base <<< diff --git a/tests/test-share.t b/tests/test-share.t --- a/tests/test-share.t +++ b/tests/test-share.t @@ -367,7 +367,7 @@ $ hg share -U thisdir/orig thisdir/abs $ hg share -U --relative thisdir/abs thisdir/rel $ cat thisdir/rel/.hg/sharedpath - ../../orig/.hg (no-eol) + ../../orig/.hg (no-eol) (glob) $ grep shared thisdir/*/.hg/requires thisdir/abs/.hg/requires:shared thisdir/rel/.hg/requires:shared @@ -377,22 +377,22 @@ $ cd thisdir $ hg -R rel root - $TESTTMP/thisdir/rel + $TESTTMP/thisdir/rel (glob) $ cd .. now test that relative paths really are relative, survive across renames and changes of PWD $ hg -R thisdir/abs root - $TESTTMP/thisdir/abs + $TESTTMP/thisdir/abs (glob) $ hg -R thisdir/rel root - $TESTTMP/thisdir/rel + $TESTTMP/thisdir/rel (glob) $ mv thisdir thatdir $ hg -R thatdir/abs root - abort: .hg/sharedpath points to nonexistent directory $TESTTMP/thisdir/orig/.hg! + abort: .hg/sharedpath points to nonexistent directory $TESTTMP/thisdir/orig/.hg! (glob) [255] $ hg -R thatdir/rel root - $TESTTMP/thatdir/rel + $TESTTMP/thatdir/rel (glob) test unshare relshared repo diff --git a/tests/test-status.t b/tests/test-status.t --- a/tests/test-status.t +++ b/tests/test-status.t @@ -121,11 +121,11 @@ ? ../b/in_b ? ../in_root $ HGPLAIN=1 hg status --cwd a - ? a/1/in_a_1 - ? a/in_a - ? b/1/in_b_1 - ? b/2/in_b_2 - ? b/in_b + ? a/1/in_a_1 (glob) + ? a/in_a (glob) + ? b/1/in_b_1 (glob) + ? b/2/in_b_2 (glob) + ? b/in_b (glob) ? in_root $ cd .. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 8 of 8] test-blackbox: glob away quoting differences on Windows
# HG changeset patch # User Matt Harbison # Date 1491114591 14400 # Sun Apr 02 02:29:51 2017 -0400 # Node ID a3ff64b0d0dedde5f2a5103083ad09e0bee7193e # Parent eb4094d2421a9fc49c8342ff244840a6c085697b test-blackbox: glob away quoting differences on Windows Windows uses double quotes in these places. diff --git a/tests/test-blackbox.t b/tests/test-blackbox.t --- a/tests/test-blackbox.t +++ b/tests/test-blackbox.t @@ -25,7 +25,7 @@ 1970/01/01 00:00:00 bob @ (5000)> add a 1970/01/01 00:00:00 bob @ (5000)> add a exited 0 after * seconds (glob) 1970/01/01 00:00:00 bob @+ (5000)> blackbox - 1970/01/01 00:00:00 bob @+ (5000)> blackbox --config 'blackbox.dirty=True' exited 0 after * seconds (glob) + 1970/01/01 00:00:00 bob @+ (5000)> blackbox --config *blackbox.dirty=True* exited 0 after * seconds (glob) 1970/01/01 00:00:00 bob @ (5000)> confuse 1970/01/01 00:00:00 bob @ (5000)> alias 'confuse' expands to 'log --limit 3' 1970/01/01 00:00:00 bob @ (5000)> confuse exited 0 after * seconds (glob) diff --git a/tests/test-devel-warnings.t b/tests/test-devel-warnings.t --- a/tests/test-devel-warnings.t +++ b/tests/test-devel-warnings.t @@ -139,7 +139,7 @@ $ hg blackbox -l 9 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> devel-warn: revset "oldstyle" uses list instead of smartset (compatibility will be dropped after Mercurial-3.9, update your code.) at: *mercurial/revset.py:* (mfunc) (glob) - 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> log -r 'oldstyle()' -T '{rev}\n' exited 0 after * seconds (glob) + 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> log -r *oldstyle()* -T *{rev}\n* exited 0 after * seconds (glob) 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> oldanddeprecated 1970/01/01 00:00:00 bob @cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b (5000)> devel-warn: foorbar is deprecated, go shopping (compatibility will be dropped after Mercurial-42.1337, update your code.) at: $TESTTMP/buggylocking.py:* (oldanddeprecated) (glob) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 4 of 8] test-serve: make the 'listening at *' lines optional
# HG changeset patch # User Matt Harbison # Date 1491109012 14400 # Sun Apr 02 00:56:52 2017 -0400 # Node ID b574417618632d500281b17ff0caf8cc78a3e2a0 # Parent ade96da6680ba993018effdf73b391fc6bed0531 test-serve: make the 'listening at *' lines optional The daemonized serve process doesn't print these lines out (see 448d0c452140). I was able to get it to with the following hack: diff --git a/mercurial/win32.py b/mercurial/win32.py --- a/mercurial/win32.py +++ b/mercurial/win32.py @@ -418,6 +418,11 @@ return str(ppid) def spawndetached(args): + +import subprocess +return subprocess.Popen(args, cwd=pycompat.getcwd(), env=encoding.environ, + creationflags=subprocess.CREATE_NEW_PROCESS_GROUP).pid + # No standard library function really spawns a fully detached # process under win32 because they allocate pipes or other objects # to handle standard streams communications. Passing these objects However, MSYS translates --prefixes starting with '/' to 'C:/MinGW/msys/1.0', which changes the output. The output isn't so important that I want to spend a bunch of time on this, and risk breaking some subtle behavior of `hg serve -d` with the more complicated code. diff --git a/tests/test-hgwebdir.t b/tests/test-hgwebdir.t --- a/tests/test-hgwebdir.t +++ b/tests/test-hgwebdir.t @@ -1421,7 +1421,7 @@ > EOF $ hg serve -d --pid-file=hg.pid --web-conf paths.conf \ > -A access-paths.log -E error-paths-9.log - listening at http://*:$HGPORT1/ (bound to *$LOCALIP*:$HGPORT1) (glob) + listening at http://*:$HGPORT1/ (bound to *$LOCALIP*:$HGPORT1) (glob) (?) $ cat hg.pid >> $DAEMON_PIDS $ get-with-headers.py localhost:$HGPORT1 '?style=raw' 200 Script output follows @@ -1433,7 +1433,7 @@ $ killdaemons.py $ hg serve -p $HGPORT2 -d -v --pid-file=hg.pid --web-conf paths.conf \ > -A access-paths.log -E error-paths-10.log - listening at http://*:$HGPORT2/ (bound to *$LOCALIP*:$HGPORT2) (glob) + listening at http://*:$HGPORT2/ (bound to *$LOCALIP*:$HGPORT2) (glob) (?) $ cat hg.pid >> $DAEMON_PIDS $ get-with-headers.py localhost:$HGPORT2 '?style=raw' 200 Script output follows diff --git a/tests/test-patchbomb-tls.t b/tests/test-patchbomb-tls.t --- a/tests/test-patchbomb-tls.t +++ b/tests/test-patchbomb-tls.t @@ -7,7 +7,7 @@ $ python "$TESTDIR/dummysmtpd.py" -p $HGPORT --pid-file a.pid -d \ > --tls smtps --certificate `pwd`/server.pem - listening at localhost:$HGPORT + listening at localhost:$HGPORT (?) $ cat a.pid >> $DAEMON_PIDS Set up repository: diff --git a/tests/test-serve.t b/tests/test-serve.t --- a/tests/test-serve.t +++ b/tests/test-serve.t @@ -34,13 +34,13 @@ With -v $ hgserve - listening at http://localhost/ (bound to *$LOCALIP*:HGPORT1) (glob) + listening at http://localhost/ (bound to *$LOCALIP*:HGPORT1) (glob) (?) % errors With -v and -p HGPORT2 $ hgserve -p "$HGPORT2" - listening at http://localhost/ (bound to *$LOCALIP*:HGPORT2) (glob) + listening at http://localhost/ (bound to *$LOCALIP*:HGPORT2) (glob) (?) % errors With -v and -p daytime (should fail because low port) @@ -57,25 +57,25 @@ With --prefix foo $ hgserve --prefix foo - listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) + listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) (?) % errors With --prefix /foo $ hgserve --prefix /foo - listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) + listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) (?) % errors With --prefix foo/ $ hgserve --prefix foo/ - listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) + listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) (?) % errors With --prefix /foo/ $ hgserve --prefix /foo/ - listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) + listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) (?) % errors $ cd .. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 8] tests: quote paths in shell script hooks
# HG changeset patch # User Matt Harbison # Date 1491074606 14400 # Sat Apr 01 15:23:26 2017 -0400 # Node ID 54fd6d15228e8e2f8e735beac0db0930c60af9ad # Parent 46f601b676cecfcc318f6852fe6ab6962703d2be tests: quote paths in shell script hooks Without the quoting, MSYS will remove the '\' directory separators, and the repo can't be opened. diff --git a/tests/test-bookmarks.t b/tests/test-bookmarks.t --- a/tests/test-bookmarks.t +++ b/tests/test-bookmarks.t @@ -924,9 +924,9 @@ $ cat > $TESTTMP/checkpending.sh < echo "@repo" - > hg -R $TESTTMP/repo bookmarks + > hg -R "$TESTTMP/repo" bookmarks > echo "@unrelated" - > hg -R $TESTTMP/unrelated bookmarks + > hg -R "$TESTTMP/unrelated" bookmarks > exit 1 # to avoid adding new bookmark for subsequent tests > EOF diff --git a/tests/test-hook.t b/tests/test-hook.t --- a/tests/test-hook.t +++ b/tests/test-hook.t @@ -857,9 +857,9 @@ $ cat > $TESTTMP/checkpending.sh < echo '@a' - > hg -R $TESTTMP/a tip -q + > hg -R "$TESTTMP/a" tip -q > echo '@a/nested' - > hg -R $TESTTMP/a/nested tip -q + > hg -R "$TESTTMP/a/nested" tip -q > exit 1 # to avoid adding new revision for subsequent tests > EOF $ hg init nested diff --git a/tests/test-phases.t b/tests/test-phases.t --- a/tests/test-phases.t +++ b/tests/test-phases.t @@ -609,9 +609,9 @@ $ cat > $TESTTMP/checkpending.sh < echo '@initialrepo' - > hg -R $TESTTMP/initialrepo phase 7 + > hg -R "$TESTTMP/initialrepo" phase 7 > echo '@push-dest' - > hg -R $TESTTMP/push-dest phase 6 + > hg -R "$TESTTMP/push-dest" phase 6 > exit 1 # to avoid changing phase for subsequent tests > EOF $ cd ../initialrepo diff --git a/tests/test-share.t b/tests/test-share.t --- a/tests/test-share.t +++ b/tests/test-share.t @@ -168,11 +168,11 @@ $ cat > $TESTTMP/checkbookmarks.sh < echo "@repo1" - > hg -R $TESTTMP/repo1 bookmarks + > hg -R "$TESTTMP/repo1" bookmarks > echo "@repo2" - > hg -R $TESTTMP/repo2 bookmarks + > hg -R "$TESTTMP/repo2" bookmarks > echo "@repo3" - > hg -R $TESTTMP/repo3 bookmarks + > hg -R "$TESTTMP/repo3" bookmarks > exit 1 # to avoid adding new bookmark for subsequent tests > EOF ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 7 of 8] test-subrepo: update output for Windows
# HG changeset patch # User Matt Harbison # Date 1491114249 14400 # Sun Apr 02 02:24:09 2017 -0400 # Node ID eb4094d2421a9fc49c8342ff244840a6c085697b # Parent f2df1dcd45d44a7cb79663fdc22054797703385a test-subrepo: update output for Windows diff --git a/tests/test-subrepo.t b/tests/test-subrepo.t --- a/tests/test-subrepo.t +++ b/tests/test-subrepo.t @@ -311,6 +311,7 @@ branchmerge: True, force: False, partial: False ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198 preserving t for resolve of t + starting 4 threads for background file closing (?) t: versions differ -> m (premerge) picked tool ':merge' for t (binary False symlink False changedelete False) merging t ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 5 of 8] test-serve: kill daemons before deleting the access and error logs
# HG changeset patch # User Matt Harbison # Date 1491110885 14400 # Sun Apr 02 01:28:05 2017 -0400 # Node ID 3196a52c528f537c04a9fdc61d6ee0f75ffb3223 # Parent b574417618632d500281b17ff0caf8cc78a3e2a0 test-serve: kill daemons before deleting the access and error logs On Windows, `rm` will fail with 'Permission denied' if another process has it open. It looks like the rollback test was missing the kill entirely. diff --git a/tests/test-largefiles-wireproto.t b/tests/test-largefiles-wireproto.t --- a/tests/test-largefiles-wireproto.t +++ b/tests/test-largefiles-wireproto.t @@ -441,7 +441,7 @@ 1 largefiles updated, 0 removed 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ killdaemons.py $ rm hg.pid access.log - $ killdaemons.py #endif diff --git a/tests/test-rollback.t b/tests/test-rollback.t --- a/tests/test-rollback.t +++ b/tests/test-rollback.t @@ -148,6 +148,8 @@ working directory now based on revision 0 $ hg id default 791dd2169706 + + $ killdaemons.py #endif update to older changeset and then refuse rollback, because ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 6 of 8] test-serve: disable unfixable tests on Windows
# HG changeset patch # User Matt Harbison # Date 1491112267 14400 # Sun Apr 02 01:51:07 2017 -0400 # Node ID f2df1dcd45d44a7cb79663fdc22054797703385a # Parent 3196a52c528f537c04a9fdc61d6ee0f75ffb3223 test-serve: disable unfixable tests on Windows These tests would run if hghave.has_serve() were enabled on Windows. Windows has no issue allowing an unpriviledged process to open port 13, so it doesn't abort. The other tests are related to how MSYS tries to be helpful and converts Unix constructs to the Windows equivalent. There isn't any way to disable this behavior, though it supposedly doesn't happen if the exe is linked against the MSYS library. diff --git a/tests/test-hgweb-commands.t b/tests/test-hgweb-commands.t --- a/tests/test-hgweb-commands.t +++ b/tests/test-hgweb-commands.t @@ -2216,6 +2216,11 @@ $ cat errors.log +MSYS changes environment variables starting with '/' into 'C:/MinGW/msys/1.0', +which changes the status line to '400 no such method: C:'. + +#if no-msys + bookmarks view doesn't choke on bookmarks on secret changesets (issue3774) $ hg phase -fs 4 @@ -2381,7 +2386,7 @@ node:(0, 6) (color 1) - +#endif $ cd .. diff --git a/tests/test-pull.t b/tests/test-pull.t --- a/tests/test-pull.t +++ b/tests/test-pull.t @@ -88,7 +88,11 @@ abort: file:// URLs can only refer to localhost [255] +MSYS changes 'file:' into 'file;' + +#if no-msys $ hg pull -q file:../test # no-msys +#endif It's tricky to make file:// URLs working on every platform with regular shell commands. diff --git a/tests/test-serve.t b/tests/test-serve.t --- a/tests/test-serve.t +++ b/tests/test-serve.t @@ -45,7 +45,7 @@ With -v and -p daytime (should fail because low port) -#if no-root +#if no-root no-windows $ KILLQUIETLY=Y $ hgserve -p daytime abort: cannot start server at 'localhost:13': Permission denied ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 2 of 8] tests: quote paths in shell script hooks
On Sun, 02 Apr 2017 20:41:29 -0400, Jun Wu wrote: Excerpts from Matt Harbison's message of 2017-04-02 19:12:48 -0400: # HG changeset patch # User Matt Harbison # Date 1491074606 14400 # Sat Apr 01 15:23:26 2017 -0400 # Node ID 54fd6d15228e8e2f8e735beac0db0930c60af9ad # Parent 46f601b676cecfcc318f6852fe6ab6962703d2be tests: quote paths in shell script hooks Without the quoting, MSYS will remove the '\' directory separators, and the repo can't be opened. diff --git a/tests/test-bookmarks.t b/tests/test-bookmarks.t --- a/tests/test-bookmarks.t +++ b/tests/test-bookmarks.t @@ -924,9 +924,9 @@ $ cat > $TESTTMP/checkpending.sh < echo "@repo" - > hg -R $TESTTMP/repo bookmarks + > hg -R "$TESTTMP/repo" bookmarks > echo "@unrelated" - > hg -R $TESTTMP/unrelated bookmarks + > hg -R "$TESTTMP/unrelated" bookmarks Maybe this is worth a check-code rule. It would definitely be nice, but I'm not sure how to do that and limit the scope. Not every instance of $TESTTMP/.. needs quoting- just the ones in things that will be executed by the shell. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 8] tests: add globs for Windows
On Mon, 03 Apr 2017 05:09:39 -0400, Kostia Balytskyi wrote: What is stopping us from making run-tests match these things without globs? Can we just always match smth1.replace('\', '//') vs smth2.replace('\', '//') if ran on Windows? I'm guessing it was just to be extra careful. It might be a little more complicated though. For example, without the glob, this diff occurs (note the double '\', and line ending difference. I'm not sure where the string compare is done vs adding the escaping '\' to the string.): --- c:/Users/Matt/Projects/hg/tests/test-merge-criss-cross.t +++ c:/Users/Matt/Projects/hg/tests/test-merge-criss-cross.t.err @@ -116,11 +116,11 @@ $ f --dump --recurse * d2: directory with 2 files - d2/f3: - >>> - 0 base - <<< - d2/f4: + d2\\f3:\r (esc) + >>> + 0 base + <<< + d2\\f4:\r (esc) >>> 0 base <<< It might also help for tests like this, where you can't put a glob IIRC: diff --git a/tests/test-trusted.py.out b/tests/test-trusted.py.out --- a/tests/test-trusted.py.out +++ b/tests/test-trusted.py.out @@ -184,7 +184,7 @@ # suboptions, trusted and untrusted (None, []) ('main', [('one', 'one'), ('two', 'two')]) # path, trusted and untrusted -None .hg/monty/python +None .hg\monty/python # bool, trusted and untrusted False True # int, trusted and untrusted I can send a patch if people think this is a good idea. I'd be interested in trying that. FWIW, in the past several years I've been playing whack-a-mole with this, the test runner never appended a (glob) inappropriately, so the logic must be in there already. -Original Message- From: Mercurial-devel [mailto:mercurial-devel-boun...@mercurial-scm.org] On Behalf Of Matt Harbison Sent: Monday, 3 April, 2017 00:13 To: mercurial-devel@mercurial-scm.org Subject: [PATCH 1 of 8] tests: add globs for Windows # HG changeset patch # User Matt Harbison # Date 1491072519 14400 # Sat Apr 01 14:48:39 2017 -0400 # Node ID 46f601b676cecfcc318f6852fe6ab6962703d2be # Parent d1a1f21e86b2f976f5e968371f6cff145b98712a tests: add globs for Windows diff --git a/tests/test-bookmarks-pushpull.t b/tests/test-bookmarks-pushpull.t --- a/tests/test-bookmarks-pushpull.t +++ b/tests/test-bookmarks-pushpull.t @@ -581,12 +581,12 @@ be exchanged) $ hg -R repo1 incoming -B - comparing with $TESTTMP/bmcomparison/source + comparing with $TESTTMP/bmcomparison/source (glob) searching for changed bookmarks no changed bookmarks found [1] $ hg -R repo1 outgoing -B - comparing with $TESTTMP/bmcomparison/source + comparing with $TESTTMP/bmcomparison/source (glob) searching for changed bookmarks no changed bookmarks found [1] diff --git a/tests/test-https.t b/tests/test-https.t --- a/tests/test-https.t +++ b/tests/test-https.t @@ -97,11 +97,12 @@ [255] #endif -Specifying a per-host certificate file that doesn't exist will abort +Specifying a per-host certificate file that doesn't exist will abort. +The full C:/path/to/msysroot will print on Windows. $ hg --config hostsecurity.localhost:verifycertsfile=/does/not/exist clone https://urldefense.proofpoint.com/v2/url?u=https-3A__localhost-3A-24HGPORT_&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=Pp-gQYFgs4tKlSFPF5kfCw&m=fkrqwBluYFCGdESYJYi8xhAZhP2kV1dBW30IT06QPIc&s=hiM2bF33c6k7YO7L2hPmdgCwx0RL-6mJn8xZTkJAdWU&e= warning: connecting to localhost using legacy security technology (TLS 1.0); see https://urldefense.proofpoint.com/v2/url?u=https-3A__mercurial-2Dscm.org_wiki_SecureConnections&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=Pp-gQYFgs4tKlSFPF5kfCw&m=fkrqwBluYFCGdESYJYi8xhAZhP2kV1dBW30IT06QPIc&s=ovg3Pxm76NuFsItFtCq16Mp53e7D5LsyYF2r_yJcGQE&e= for more info (?) - abort: path specified by hostsecurity.localhost:verifycertsfile does not exist: /does/not/exist + abort: path specified by hostsecurity.localhost:verifycertsfile does + not exist: */does/not/exist (glob) [255] A malformed per-host certificate file will raise an error diff --git a/tests/test-largefiles-cache.t b/tests/test-largefiles-cache.t --- a/tests/test-largefiles-cache.t +++ b/tests/test-largefiles-cache.t @@ -223,7 +223,7 @@ $ hg push https://urldefense.proofpoint.com/v2/url?u=http-3A__localhost-3A-24HGPORT1&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=Pp-gQYFgs4tKlSFPF5kfCw&m=fkrqwBluYFCGdESYJYi8xhAZhP2kV1dBW30IT06QPIc&s=ju5I1GImXMqktvYrqwpmCDXdgiKm0RuiHYcrjUY_frw&e= -f --config files.usercache=nocache pushing to https://urldefense.proofpoint.com/v2/url?u=http-3A__localhost-3A-24HGPORT1_&d=DwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=Pp-gQYFgs4tKlSFPF5kfCw&m=fkrqwBluYFCGdESYJYi8xhAZhP2kV1dBW30IT06QPIc&s=4xcqfRg-K4IM5qtnN75gCmlA8bWdZY27a8gBV712RpY&e= searching
Re: [PATCH 4 of 6] hgweb: introduce staticimmutable web command
On Sat, 01 Apr 2017 03:29:08 -0400, Gregory Szorc wrote: # HG changeset patch # User Gregory Szorc # Date 1491021501 25200 # Fri Mar 31 21:38:21 2017 -0700 # Node ID 0b8be3d244585f5a2874821418fce41bf7631f6c # Parent 4cec8e88d09775ee6478e307e9dde94af5b9fcfd hgweb: introduce staticimmutable web command Should these caching related patches be sensitive to '--config web.cache=False'? I can't imagine why you wouldn't want to cache in a production environment. It has been useful for development testing, but it's not documented as experimental/developer only. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH RFC] run-tests: support per-line conditional output in tests
# HG changeset patch # User Matt Harbison # Date 1491275149 14400 # Mon Apr 03 23:05:49 2017 -0400 # Node ID cfefdb4546a3a38918303ed43447ebe93051de51 # Parent 81abd0d12c8641df666d356f6033d84cd55977a8 run-tests: support per-line conditional output in tests Duplicating entire tests just because the output is different is both error prone and can make the tests harder to read. This harnesses the existing '(?)' infrastructure, both to improve readability, and because it seemed like the path of least resistance. I think this syntax seems natural. For example, this: 2 r4/.hg/cache/checkisexec (execbit ?) pretty naturally reads as "checkisexec, if execbit". In some ways though, this inverts the meaning of '?'. For '(?)', the line is purely optional. In the example, it is mandatory iff execbit. Otherwise, it is carried forward as optional, to preserve the test output. I tried it the other way, (listing 'no-exec' in the example), but that is too confusing to read. The only thing that I haven't figured out yet is why the '(glob)' interferes in the first hardlink.t hunk. If it is kept, that line falls to the bottom of the (xxx ?) sequence on Windows. As it is, this test runs cleanly on Linux. diff --git a/tests/run-tests.py b/tests/run-tests.py --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -497,6 +497,9 @@ # sans \t, \n and \r CDATA_EVIL = re.compile(br"[\000-\010\013\014\016-\037]") +#optline = re.compile(b'(.*) \(([a-z0-9 +.]*) \?\)\n$') +optline = re.compile(b'(.+) \((.+?) \?\)\n$') + def cdatasafe(data): """Make a string safe to include in a CDATA block. @@ -1271,8 +1274,19 @@ if r: els.pop(i) break -if el and el.endswith(b" (?)\n"): -optional.append(i) +if el: +if el.endswith(b" (?)\n"): +optional.append(i) +else: +m = optline.match(el) +if m: +conditions = [c for c in m.group(2).split(' ')] + +if self._hghave(conditions)[0]: +lout = el +else: +optional.append(i) + i += 1 if r: @@ -1298,8 +1312,10 @@ # clean up any optional leftovers while expected.get(pos, None): el = expected[pos].pop(0) -if el and not el.endswith(b" (?)\n"): -break +if el: +if (not optline.match(el) +and not el.endswith(b" (?)\n")): +break postout.append(b' ' + el) if lcmd: @@ -1371,6 +1387,12 @@ if el.endswith(b" (?)\n"): retry = "retry" el = el[:-5] + b"\n" +else: +m = optline.match(el) +if m: +el = m.group(1) + b"\n" +retry = "retry" + if el.endswith(b" (esc)\n"): if PYTHON3: el = el[:-7].decode('unicode_escape') + '\n' diff --git a/tests/test-clone.t b/tests/test-clone.t --- a/tests/test-clone.t +++ b/tests/test-clone.t @@ -31,10 +31,10 @@ default 10:a7949464abda $ ls .hg/cache branch2-served - checkisexec - checklink - checklink-target - checknoexec + checkisexec (execbit ?) + checklink (symlink ?) + checklink-target (symlink ?) + checknoexec (execbit ?) rbc-names-v1 rbc-revs-v1 @@ -49,9 +49,9 @@ $ ls .hg/cache branch2-served - checkisexec - checklink - checklink-target + checkisexec (execbit ?) + checklink (symlink ?) + checklink-target (symlink ?) $ cat a a diff --git a/tests/test-fileset.t b/tests/test-fileset.t --- a/tests/test-fileset.t +++ b/tests/test-fileset.t @@ -441,10 +441,10 @@ M b2 A 1k A 2k - A b2link + A b2link (no-windows ?) A bin A c1 - A con.xml + A con.xml (no-windows ?) R a2 $ hg status --change 2 M b2 @@ -452,10 +452,10 @@ M b2 A 1k A 2k - A b2link + A b2link (no-windows ?) A bin A c1 - A con.xml + A con.xml (no-windows ?) R a2 $ hg status --change 4 A .hgsub @@ -464,7 +464,7 @@ A dos A mac A mixed - R con.xml + R con.xml (no-windows ?) ! a1 ? b2.orig ? c3 @@ -551,9 +551,9 @@ $ hg status --removed --rev 4 - R con.xml + R con.xml (no-windows ?) $ fileset "status(4, 'wdir(
Re: [PATCH 2 of 8] tests: quote paths in shell script hooks
On Tue, 04 Apr 2017 13:39:54 -0400, FUJIWARA Katsunori wrote: At Sun, 02 Apr 2017 20:45:58 -0400, Matt Harbison wrote: On Sun, 02 Apr 2017 20:41:29 -0400, Jun Wu wrote: > Excerpts from Matt Harbison's message of 2017-04-02 19:12:48 -0400: >> # HG changeset patch >> # User Matt Harbison >> # Date 1491074606 14400 >> # Sat Apr 01 15:23:26 2017 -0400 >> # Node ID 54fd6d15228e8e2f8e735beac0db0930c60af9ad >> # Parent 46f601b676cecfcc318f6852fe6ab6962703d2be >> tests: quote paths in shell script hooks >> >> Without the quoting, MSYS will remove the '\' directory separators, and >> the repo >> can't be opened. >> >> diff --git a/tests/test-bookmarks.t b/tests/test-bookmarks.t >> --- a/tests/test-bookmarks.t >> +++ b/tests/test-bookmarks.t >> @@ -924,9 +924,9 @@ >> >>$ cat > $TESTTMP/checkpending.sh <>> echo "@repo" >> - > hg -R $TESTTMP/repo bookmarks >> + > hg -R "$TESTTMP/repo" bookmarks >>> echo "@unrelated" >> - > hg -R $TESTTMP/unrelated bookmarks >> + > hg -R "$TESTTMP/unrelated" bookmarks > > Maybe this is worth a check-code rule. It would definitely be nice, but I'm not sure how to do that and limit the scope. Not every instance of $TESTTMP/.. needs quoting- just the ones in things that will be executed by the shell. With current check-code implementation, all here-doc fragments in *.t script are completely ignored, because all non-whitespace letters in here-doc are replaced with 'x' by rephere() at filtering stage of checkfile(). https://www.mercurial-scm.org/repo/hg/file/68f263f52d2e/contrib/check-code.py#l96 This ignorance may cause overlooking outdated here-doc python code in *.t script, too. In fact, I have a suspending series to check here-doc fragments in *.t script. I'll finish it in a hurry! OK, thanks! No rush from me though. There are still more than a handful of broken tests on Windows, so I'm not too worried about this case. ___ 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 RFC] run-tests: support per-line conditional output in tests
On Tue, 04 Apr 2017 00:01:55 -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1491275149 14400 # Mon Apr 03 23:05:49 2017 -0400 # Node ID cfefdb4546a3a38918303ed43447ebe93051de51 # Parent 81abd0d12c8641df666d356f6033d84cd55977a8 run-tests: support per-line conditional output in tests Duplicating entire tests just because the output is different is both error prone and can make the tests harder to read. This harnesses the existing '(?)' infrastructure, both to improve readability, and because it seemed like the path of least resistance. I think this syntax seems natural. For example, this: 2 r4/.hg/cache/checkisexec (execbit ?) pretty naturally reads as "checkisexec, if execbit". In some ways though, this inverts the meaning of '?'. For '(?)', the line is purely optional. In the example, it is mandatory iff execbit. Otherwise, it is carried forward as optional, to preserve the test output. I tried it the other way, (listing 'no-exec' in the example), but that is too confusing to read. The only thing that I haven't figured out yet is why the '(glob)' interferes in the first hardlink.t hunk. If it is kept, that line falls to the bottom of the (xxx ?) sequence on Windows. As it is, this test runs cleanly on Linux. Actually, this is an existing problem with '(?)' too. Changing (xxx ?) to (?) without the *.py changes yields the same behavior. diff --git a/tests/run-tests.py b/tests/run-tests.py --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -497,6 +497,9 @@ # sans \t, \n and \r CDATA_EVIL = re.compile(br"[\000-\010\013\014\016-\037]") +#optline = re.compile(b'(.*) \(([a-z0-9 +.]*) \?\)\n$') +optline = re.compile(b'(.+) \((.+?) \?\)\n$') + def cdatasafe(data): """Make a string safe to include in a CDATA block. @@ -1271,8 +1274,19 @@ if r: els.pop(i) break -if el and el.endswith(b" (?)\n"): -optional.append(i) +if el: +if el.endswith(b" (?)\n"): +optional.append(i) +else: +m = optline.match(el) +if m: +conditions = [c for c in m.group(2).split(' ')] + +if self._hghave(conditions)[0]: +lout = el +else: +optional.append(i) + i += 1 if r: @@ -1298,8 +1312,10 @@ # clean up any optional leftovers while expected.get(pos, None): el = expected[pos].pop(0) -if el and not el.endswith(b" (?)\n"): -break +if el: +if (not optline.match(el) +and not el.endswith(b" (?)\n")): +break postout.append(b' ' + el) if lcmd: @@ -1371,6 +1387,12 @@ if el.endswith(b" (?)\n"): retry = "retry" el = el[:-5] + b"\n" +else: +m = optline.match(el) +if m: +el = m.group(1) + b"\n" +retry = "retry" + if el.endswith(b" (esc)\n"): if PYTHON3: el = el[:-7].decode('unicode_escape') + '\n' diff --git a/tests/test-clone.t b/tests/test-clone.t --- a/tests/test-clone.t +++ b/tests/test-clone.t @@ -31,10 +31,10 @@ default 10:a7949464abda $ ls .hg/cache branch2-served - checkisexec - checklink - checklink-target - checknoexec + checkisexec (execbit ?) + checklink (symlink ?) + checklink-target (symlink ?) + checknoexec (execbit ?) rbc-names-v1 rbc-revs-v1 @@ -49,9 +49,9 @@ $ ls .hg/cache branch2-served - checkisexec - checklink - checklink-target + checkisexec (execbit ?) + checklink (symlink ?) + checklink-target (symlink ?) $ cat a a diff --git a/tests/test-fileset.t b/tests/test-fileset.t --- a/tests/test-fileset.t +++ b/tests/test-fileset.t @@ -441,10 +441,10 @@ M b2 A 1k A 2k - A b2link + A b2link (no-windows ?) A bin A c1 - A con.xml + A con.xml (no-windows ?) R a2 $ hg status --change 2 M b2 @@ -452,10 +452,10 @@ M b2 A 1k A 2k - A b2link + A b2link (no-windows ?) A bin A c1 - A con.xml + A con.xml (no-windows ?) R a2 $ hg status --change 4 A .hgsub @@ -464,7 +464,7 @@ A dos A mac A mixed - R co
Re: [PATCH RFC] run-tests: support per-line conditional output in tests
On Thu, 06 Apr 2017 18:27:31 -0400, Jun Wu wrote: Excerpts from Matt Harbison's message of 2017-04-04 00:01:55 -0400: The only thing that I haven't figured out yet is why the '(glob)' interferes in the first hardlink.t hunk. If it is kept, that line falls to the bottom of the (xxx ?) sequence on Windows. As it is, this test runs cleanly on Linux. From 6a672c3b7860, it seems we may be able to just say 2 there: - ? r4/.hg/cache/checklink-target (glob) + 2 r4/.hg/cache/checklink-target Interesting. That's the commit that changed it from a number to the glob, so I assumed that it was important. I did manage to fix the issue, and don't have OS X in front of me, so I'll leave that alone for now. I like this feature. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 4 V2] run-tests: prevent a (glob) declaration from reordering (?) lines
# HG changeset patch # User Matt Harbison # Date 1491444033 14400 # Wed Apr 05 22:00:33 2017 -0400 # Node ID c0789426514615cd841a31f60688516f2cdeaae0 # Parent 81abd0d12c8641df666d356f6033d84cd55977a8 run-tests: prevent a (glob) declaration from reordering (?) lines Previously, if a series of optional output lines marked with '(?)' had a (glob) in one of the first lines, the output would be reordered such that it came last if none of the lines were output. The (re) declaration wasn't affected, which was helpful in figuring this out. There were no tests for '(re) (?)' so add that to make sure everything plays nice. diff --git a/tests/run-tests.py b/tests/run-tests.py --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -1385,7 +1385,7 @@ # ignore '(glob)' added to l by 'replacements' if l.endswith(b" (glob)\n"): l = l[:-8] + b"\n" -return TTest.globmatch(el[:-8], l) +return TTest.globmatch(el[:-8], l) or retry if os.altsep and l.replace(b'\\', b'/') == el: return b'+glob' return retry diff --git a/tests/test-run-tests.t b/tests/test-run-tests.t --- a/tests/test-run-tests.t +++ b/tests/test-run-tests.t @@ -55,7 +55,10 @@ > $ echo babar > babar > $ echo xyzzy + > dont_print (?) + > nothing[42]line (re) (?) > never*happens (glob) (?) + > more_nothing (?) > xyzzy > nor this (?) > $ printf 'abc\ndef\nxyz\n' @@ -326,14 +329,14 @@ *SALT* 2 0 (glob) + echo xyzzy xyzzy - + echo *SALT* 6 0 (glob) - *SALT* 6 0 (glob) + + echo *SALT* 9 0 (glob) + *SALT* 9 0 (glob) + printf *abc\ndef\nxyz\n* (glob) abc def xyz - + echo *SALT* 12 0 (glob) - *SALT* 12 0 (glob) + + echo *SALT* 15 0 (glob) + *SALT* 15 0 (glob) . # Ran 2 tests, 0 skipped, 0 warned, 0 failed. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 4 V2] test-run-tests: pad the failure test to preserve the run order
# HG changeset patch # User Matt Harbison # Date 1491447584 14400 # Wed Apr 05 22:59:44 2017 -0400 # Node ID 7c5e861f39fbffdfae0e31d1edba419a62391afe # Parent c0789426514615cd841a31f60688516f2cdeaae0 test-run-tests: pad the failure test to preserve the run order Test size seems to dictate the order in which the tests are run, and the next patch will add to test-success.t. Similar to c0cecc153d25. diff --git a/tests/test-run-tests.t b/tests/test-run-tests.t --- a/tests/test-run-tests.t +++ b/tests/test-run-tests.t @@ -107,6 +107,10 @@ > this test is still more bytes than success. > pad pad pad pad > pad pad pad pad + > pad pad pad pad + > pad pad pad pad + > pad pad pad pad + > pad pad pad pad > EOF >>> fh = open('test-failure-unicode.t', 'wb') @@ -319,8 +323,8 @@ *SALT* 0 0 (glob) + echo babar babar - + echo *SALT* 6 0 (glob) - *SALT* 6 0 (glob) + + echo *SALT* 10 0 (glob) + *SALT* 10 0 (glob) *+ echo *SALT* 0 0 (glob) *SALT* 0 0 (glob) + echo babar @@ -415,6 +419,10 @@ this test is still more bytes than success. pad pad pad pad pad pad pad pad + pad pad pad pad + pad pad pad pad + pad pad pad pad + pad pad pad pad Interactive with custom view @@ -452,13 +460,15 @@ --- $TESTTMP/test-failure.t +++ $TESTTMP/test-failure.t.err - @@ -1,11 +1,11 @@ + @@ -1,5 +1,5 @@ $ echo babar - rataxes + babar This is a noop statement so that this test is still more bytes than success. pad pad pad pad + @@ -9,7 +9,7 @@ + pad pad pad pad pad pad pad pad $ echo 'saved backup bundle to $TESTTMP/foo.hg' - saved backup bundle to $TESTTMP/foo.hg @@ -476,6 +486,10 @@ this test is still more bytes than success. pad pad pad pad pad pad pad pad + pad pad pad pad + pad pad pad pad + pad pad pad pad + pad pad pad pad $ echo 'saved backup bundle to $TESTTMP/foo.hg' saved backup bundle to $TESTTMP/foo.hg (glob)< $ echo 'saved backup bundle to $TESTTMP/foo.hg' ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 4 of 4 V2] tests: add per-line output conditionals for Windows
# HG changeset patch # User Matt Harbison # Date 1491450262 14400 # Wed Apr 05 23:44:22 2017 -0400 # Node ID 8ccde224a46cd70f1586fcc769ff65a80ddbf354 # Parent 8e3cf915084723551d0b68094cede7e65f49cf39 tests: add per-line output conditionals for Windows diff --git a/tests/test-clone.t b/tests/test-clone.t --- a/tests/test-clone.t +++ b/tests/test-clone.t @@ -31,10 +31,10 @@ default 10:a7949464abda $ ls .hg/cache branch2-served - checkisexec - checklink - checklink-target - checknoexec + checkisexec (execbit !) + checklink (symlink !) + checklink-target (symlink !) + checknoexec (execbit !) rbc-names-v1 rbc-revs-v1 @@ -49,9 +49,9 @@ $ ls .hg/cache branch2-served - checkisexec - checklink - checklink-target + checkisexec (execbit !) + checklink (symlink !) + checklink-target (symlink !) $ cat a a diff --git a/tests/test-fileset.t b/tests/test-fileset.t --- a/tests/test-fileset.t +++ b/tests/test-fileset.t @@ -441,10 +441,10 @@ M b2 A 1k A 2k - A b2link + A b2link (no-windows !) A bin A c1 - A con.xml + A con.xml (no-windows !) R a2 $ hg status --change 2 M b2 @@ -452,10 +452,10 @@ M b2 A 1k A 2k - A b2link + A b2link (no-windows !) A bin A c1 - A con.xml + A con.xml (no-windows !) R a2 $ hg status --change 4 A .hgsub @@ -464,7 +464,7 @@ A dos A mac A mixed - R con.xml + R con.xml (no-windows !) ! a1 ? b2.orig ? c3 @@ -551,9 +551,9 @@ $ hg status --removed --rev 4 - R con.xml + R con.xml (no-windows !) $ fileset "status(4, 'wdir()', removed())" - con.xml + con.xml (no-windows !) $ hg status --removed --rev 2 R a2 @@ -585,19 +585,19 @@ A .hgsubstate A 1k A 2k - A b2link + A b2link (no-windows !) A bin A c1 - A con.xml + A con.xml (no-windows !) $ fileset "status('0:1', '3:4', added())" .hgsub .hgsubstate 1k 2k - b2link + b2link (no-windows !) bin c1 - con.xml + con.xml (no-windows !) tests with empty value -- diff --git a/tests/test-hardlinks.t b/tests/test-hardlinks.t --- a/tests/test-hardlinks.t +++ b/tests/test-hardlinks.t @@ -211,10 +211,10 @@ 2 r4/.hg/00changelog.i 2 r4/.hg/branch 2 r4/.hg/cache/branch2-served - 2 r4/.hg/cache/checkisexec + 2 r4/.hg/cache/checkisexec (execbit !) 3 r4/.hg/cache/checklink (?) - ? r4/.hg/cache/checklink-target (glob) - 2 r4/.hg/cache/checknoexec + ? r4/.hg/cache/checklink-target (glob) (symlink !) + 2 r4/.hg/cache/checknoexec (execbit !) 2 r4/.hg/cache/rbc-names-v1 2 r4/.hg/cache/rbc-revs-v1 2 r4/.hg/dirstate @@ -251,9 +251,9 @@ 2 r4/.hg/00changelog.i 1 r4/.hg/branch 2 r4/.hg/cache/branch2-served - 2 r4/.hg/cache/checkisexec - 2 r4/.hg/cache/checklink-target - 2 r4/.hg/cache/checknoexec + 2 r4/.hg/cache/checkisexec (execbit !) + 2 r4/.hg/cache/checklink-target (symlink !) + 2 r4/.hg/cache/checknoexec (execbit !) 2 r4/.hg/cache/rbc-names-v1 2 r4/.hg/cache/rbc-revs-v1 1 r4/.hg/dirstate diff --git a/tests/test-tags.t b/tests/test-tags.t --- a/tests/test-tags.t +++ b/tests/test-tags.t @@ -672,9 +672,9 @@ $ ls tagsclient/.hg/cache branch2-served - checkisexec - checklink - checklink-target + checkisexec (execbit !) + checklink (symlink !) + checklink-target (symlink !) hgtagsfnodes1 rbc-names-v1 rbc-revs-v1 @@ -699,9 +699,9 @@ $ ls tagsclient/.hg/cache branch2-served - checkisexec - checklink - checklink-target + checkisexec (execbit !) + checklink (symlink !) + checklink-target (symlink !) hgtagsfnodes1 rbc-names-v1 rbc-revs-v1 ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 4 V2] run-tests: support per-line conditional output in tests
# HG changeset patch # User Matt Harbison # Date 1491448647 14400 # Wed Apr 05 23:17:27 2017 -0400 # Node ID 8e3cf915084723551d0b68094cede7e65f49cf39 # Parent 7c5e861f39fbffdfae0e31d1edba419a62391afe run-tests: support per-line conditional output in tests Duplicating entire tests just because the output is different is both error prone and can make the tests harder to read. This harnesses the existing '(?)' infrastructure, both to improve readability, and because it seemed like the path of least resistance. The form is: $ test_cmd output (hghave-feature !) # required if hghave.has_feature(), else optional out2 (no-hghave-feature2 !) # req if not hghave.has_feature2(), else optional I originally extended the '(?)' syntax. For example, this: 2 r4/.hg/cache/checkisexec (execbit ?) pretty naturally reads as "checkisexec, if execbit". In some ways though, this inverts the meaning of '?'. For '(?)', the line is purely optional. In the example, it is mandatory iff execbit. Otherwise, it is carried forward as optional, to preserve the test output. I tried it the other way, (listing 'no-exec' in the example), but that is too confusing to read. Kostia suggested using '!', and that seems fine. diff --git a/tests/run-tests.py b/tests/run-tests.py --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -497,6 +497,12 @@ # sans \t, \n and \r CDATA_EVIL = re.compile(br"[\000-\010\013\014\016-\037]") +# Match feature conditionalized output lines in the form, capturing the feature +# list in group 2, and the preceeding line output in group 1: +# +# output..output (feature !)\n +optline = re.compile(b'(.+) \((.+?) !\)\n$') + def cdatasafe(data): """Make a string safe to include in a CDATA block. @@ -1271,8 +1277,19 @@ if r: els.pop(i) break -if el and el.endswith(b" (?)\n"): -optional.append(i) +if el: +if el.endswith(b" (?)\n"): +optional.append(i) +else: +m = optline.match(el) +if m: +conditions = [c for c in m.group(2).split(' ')] + +if self._hghave(conditions)[0]: +lout = el +else: +optional.append(i) + i += 1 if r: @@ -1298,8 +1315,10 @@ # clean up any optional leftovers while expected.get(pos, None): el = expected[pos].pop(0) -if el and not el.endswith(b" (?)\n"): -break +if el: +if (not optline.match(el) +and not el.endswith(b" (?)\n")): +break postout.append(b' ' + el) if lcmd: @@ -1371,6 +1390,12 @@ if el.endswith(b" (?)\n"): retry = "retry" el = el[:-5] + b"\n" +else: +m = optline.match(el) +if m: +el = m.group(1) + b"\n" +retry = "retry" + if el.endswith(b" (esc)\n"): if PYTHON3: el = el[:-7].decode('unicode_escape') + '\n' diff --git a/tests/test-run-tests.t b/tests/test-run-tests.t --- a/tests/test-run-tests.t +++ b/tests/test-run-tests.t @@ -39,6 +39,19 @@ $ rm hg #endif +Features for testing optional lines +=== + + $ cat > hghaveaddon.py < import hghave + > @hghave.check("custom", "custom hghave feature") + > def has_custom(): + > return True + > @hghave.check("missing", "missing hghave feature") + > def has_missing(): + > return False + > EOF + an empty test === @@ -67,6 +80,13 @@ > def (?) > 456 (?) > xyz + > $ printf 'zyx\nwvu\ntsr\n' + > abc (?) + > zyx (custom !) + > wvu + > no_print (no-custom !) + > tsr (no-missing !) + > missing (missing !) > EOF $ rt @@ -341,6 +361,12 @@ xyz + echo *SALT* 15 0 (glob) *SALT* 15 0 (glob) + + printf 'zyx\nwvu\ntsr\n' + zyx + wvu + tsr + + echo *SALT* 22 0 (glob) + *SALT* 22 0 (glob) . # Ran 2 tests, 0 skipped, 0 warned, 0 failed. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 07 of 10 V5] rcutil: let environ override system configs (BC)
On Mon, 27 Mar 2017 02:02:06 -0400, Jun Wu wrote: # HG changeset patch # User Jun Wu # Date 1490589217 25200 # Sun Mar 26 21:33:37 2017 -0700 # Node ID 38572bb2cffd815526a727bc6f3aacdca2902f4f # Parent 9b0aa30bf151b6c0e999b017fd328e29440bd447 # Available At https://bitbucket.org/quark-zju/hg-draft # hg pull https://bitbucket.org/quark-zju/hg-draft -r 38572bb2cffd rcutil: let environ override system configs (BC) This is BC because system configs won't be able to override $EDITOR, $PAGER. The new behavior is arguably more rational. I'm not sure if this is a broader concern than just the test suite with env-based config, but I bisected a new Windows failure back to this change. --- c:/Users/Matt/Projects/hg/tests/test-check-code.t +++ c:/Users/Matt/Projects/hg/tests/test-check-code.t.err @@ -9,34 +9,7 @@ $ hg locate -X contrib/python-zstandard -X hgext/fsmonitor/pywatchman | > sed 's-\\-/-g' | xargs "$check_code" --warnings --per-file=0 || false - Skipping i18n/polib.py it has no-che?k-code (glob) - mercurial/demandimport.py:312: - > if os.environ.get('HGDEMANDIMPORT') != 'disable': - use encoding.environ instead (py3) - mercurial/encoding.py:54: - > environ = os.environ - use encoding.environ instead (py3) - mercurial/encoding.py:56: - > environ = os.environb - use encoding.environ instead (py3) - mercurial/encoding.py:61: - >for k, v in os.environ.items()) - use encoding.environ instead (py3) - mercurial/encoding.py:221: - >for k, v in os.environ.items()) - use encoding.environ instead (py3) - Skipping mercurial/httpclient/__init__.py it has no-che?k-code (glob) - Skipping mercurial/httpclient/_readers.py it has no-che?k-code (glob) - mercurial/policy.py:46: - > if 'HGMODULEPOLICY' in os.environ: - use encoding.environ instead (py3) - mercurial/policy.py:47: - > policy = os.environ['HGMODULEPOLICY'].encode('utf-8') - use encoding.environ instead (py3) - mercurial/policy.py:49: - > policy = os.environ.get('HGMODULEPOLICY', policy) - use encoding.environ instead (py3) - Skipping mercurial/statprof.py it has no-che?k-code (glob) + /usr/bin/env: python: Bad file number [1] @commands in debugcommands.py should be in alphabetical order. diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -1807,4 +1807,6 @@ def config(ui, repo, *values, **opts): if t == 'path': ui.debug('read config from: %s\n' % f) +elif t == 'items': +pass else: raise error.ProgrammingError('unknown rctype: %s' % t) diff --git a/mercurial/rcutil.py b/mercurial/rcutil.py --- a/mercurial/rcutil.py +++ b/mercurial/rcutil.py @@ -77,8 +77,12 @@ def rccomponents(): name, value, source) that should fill the config directly. ''' +envrc = ('items', envrcitems()) + global _rccomponents if _rccomponents is None: if 'HGRCPATH' in encoding.environ: -_rccomponents = [] +# assume HGRCPATH is all about user configs so environments can be +# overridden. +_rccomponents = [envrc] for p in encoding.environ['HGRCPATH'].split(pycompat.ospathsep): if not p: @@ -86,5 +90,8 @@ def rccomponents(): _rccomponents.extend(('path', p) for p in _expandrcpath(p)) else: -paths = defaultrcpath() + systemrcpath() + userrcpath() +paths = defaultrcpath() + systemrcpath() _rccomponents = [('path', os.path.normpath(p)) for p in paths] +_rccomponents.append(envrc) +paths = userrcpath() +_rccomponents.extend(('path', os.path.normpath(p)) for p in paths) return _rccomponents diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -212,8 +212,18 @@ class ui(object): """Create a ui and load global and user configs""" u = cls() -# we always trust global config files +# we always trust global config files and environment variables for t, f in rcutil.rccomponents(): if t == 'path': u.readconfig(f, trust=True) +elif t == 'items': +sections = set() +for section, name, value, source in f: +# do not set u._ocfg +# XXX clean this up once immutable config object is a thing +u._tcfg.set(section, name, value, source) +u._ucfg.set(section, name, value, source) +sections.add(section) +for section in sections: +u.fixconfig(section=section) else: raise error.ProgrammingError('unknown rctype: %s' % t) diff --git a/tests/test-config-env.py b/tests/test-config-env.py new fil
Re: [PATCH RFC] run-tests: support per-line conditional output in tests
On Thu, 06 Apr 2017 20:15:41 -0400, Jun Wu wrote: Excerpts from Matt Harbison's message of 2017-04-06 20:06:02 -0400: On Thu, 06 Apr 2017 18:27:31 -0400, Jun Wu wrote: > Excerpts from Matt Harbison's message of 2017-04-04 00:01:55 -0400: >> The only thing that I haven't figured out yet is why the '(glob)' >> interferes >> in the first hardlink.t hunk. If it is kept, that line falls to the >> bottom of >> the (xxx ?) sequence on Windows. As it is, this test runs cleanly on >> Linux. > > From 6a672c3b7860, it seems we may be able to just say 2 there: > > - ? r4/.hg/cache/checklink-target (glob) > + 2 r4/.hg/cache/checklink-target Interesting. That's the commit that changed it from a number to the glob, so I assumed that it was important. I did manage to fix the issue, and don't have OS X in front of me, so I'll leave that alone for now. The minus and plus signs are the change I think we can make, not the patch introduced. Yep. I misread original commit. 6a672c3b7860 is inconsistent about "checklink-target" it added to the test. One of them uses "?", the other uses "2". So I think we can change it to "2" without issues. If that's true, then I guess the 'checklink (?)' line is unnecessary too, because it isn't in the later test either. I don't have access to Solaris, but I'll try to check on OS X tomorrow if I remember. > I like this feature. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 07 of 10 V5] rcutil: let environ override system configs (BC)
On Thu, 06 Apr 2017 23:50:31 -0400, Jun Wu wrote: Excerpts from Matt Harbison's message of 2017-04-06 23:14:50 -0400: On Mon, 27 Mar 2017 02:02:06 -0400, Jun Wu wrote: > # HG changeset patch > # User Jun Wu > # Date 1490589217 25200 > # Sun Mar 26 21:33:37 2017 -0700 > # Node ID 38572bb2cffd815526a727bc6f3aacdca2902f4f > # Parent 9b0aa30bf151b6c0e999b017fd328e29440bd447 > # Available At https://bitbucket.org/quark-zju/hg-draft > # hg pull https://bitbucket.org/quark-zju/hg-draft -r > 38572bb2cffd > rcutil: let environ override system configs (BC) > > This is BC because system configs won't be able to override $EDITOR, > $PAGER. > The new behavior is arguably more rational. I'm not sure if this is a broader concern than just the test suite with env-based config, but I bisected a new Windows failure back to this change. How did you run tests under Windows? I couldn't reproduce this using cygwin. (and I have difficulty with "sh" when using the MSVC compiler) I have MinGW installed, and from the tests directory just run "./run-tests --local test-check-code.t". I have MSVC 2008 installed, which I assume is what is used. --- c:/Users/Matt/Projects/hg/tests/test-check-code.t +++ c:/Users/Matt/Projects/hg/tests/test-check-code.t.err @@ -9,34 +9,7 @@ $ hg locate -X contrib/python-zstandard -X hgext/fsmonitor/pywatchman | > sed 's-\\-/-g' | xargs "$check_code" --warnings --per-file=0 || false - Skipping i18n/polib.py it has no-che?k-code (glob) - mercurial/demandimport.py:312: - > if os.environ.get('HGDEMANDIMPORT') != 'disable': - use encoding.environ instead (py3) - mercurial/encoding.py:54: - > environ = os.environ - use encoding.environ instead (py3) - mercurial/encoding.py:56: - > environ = os.environb - use encoding.environ instead (py3) - mercurial/encoding.py:61: - >for k, v in os.environ.items()) - use encoding.environ instead (py3) - mercurial/encoding.py:221: - >for k, v in os.environ.items()) - use encoding.environ instead (py3) - Skipping mercurial/httpclient/__init__.py it has no-che?k-code (glob) - Skipping mercurial/httpclient/_readers.py it has no-che?k-code (glob) - mercurial/policy.py:46: - > if 'HGMODULEPOLICY' in os.environ: - use encoding.environ instead (py3) - mercurial/policy.py:47: - > policy = os.environ['HGMODULEPOLICY'].encode('utf-8') - use encoding.environ instead (py3) - mercurial/policy.py:49: - > policy = os.environ.get('HGMODULEPOLICY', policy) - use encoding.environ instead (py3) - Skipping mercurial/statprof.py it has no-che?k-code (glob) + /usr/bin/env: python: Bad file number [1] @commands in debugcommands.py should be in alphabetical order. > diff --git a/mercurial/commands.py b/mercurial/commands.py > --- a/mercurial/commands.py > +++ b/mercurial/commands.py > @@ -1807,4 +1807,6 @@ def config(ui, repo, *values, **opts): > if t == 'path': > ui.debug('read config from: %s\n' % f) > +elif t == 'items': > +pass > else: > raise error.ProgrammingError('unknown rctype: %s' % t) > diff --git a/mercurial/rcutil.py b/mercurial/rcutil.py > --- a/mercurial/rcutil.py > +++ b/mercurial/rcutil.py > @@ -77,8 +77,12 @@ def rccomponents(): > name, value, source) that should fill the config directly. > ''' > +envrc = ('items', envrcitems()) > + > global _rccomponents > if _rccomponents is None: > if 'HGRCPATH' in encoding.environ: > -_rccomponents = [] > +# assume HGRCPATH is all about user configs so environments > can be > +# overridden. > +_rccomponents = [envrc] > for p in > encoding.environ['HGRCPATH'].split(pycompat.ospathsep): > if not p: > @@ -86,5 +90,8 @@ def rccomponents(): > _rccomponents.extend(('path', p) for p in > _expandrcpath(p)) > else: > -paths = defaultrcpath() + systemrcpath() + userrcpath() > +paths = defaultrcpath() + systemrcpath() > _rccomponents = [('path', os.path.normpath(p)) for p in > paths] > +_rccomponents.append(envrc) > +paths = userrcpath() > +_rccomponents.extend(('path', os.path.normpath(p)) for p in > paths) > return _rccomponents > diff --git a/mercurial/ui.py b/mercurial/ui.py > --- a/mercurial/ui.py > +++ b/mercurial/ui.py > @@ -212,8 +212,18 @@ class ui(object): > """Create a ui and load global and user configs""" > u = cls() > -# we always trust global config files > +# we always trust global config files and environment variables > for t, f in rcutil.rccomponents(): > if t == 'path': > u.readconfig(f, trust=True) > +elif t == 'items': > +sections = set() > +for section, name
Re: [PATCH 07 of 10 V5] rcutil: let environ override system configs (BC)
On Fri, 07 Apr 2017 00:25:03 -0400, Jun Wu wrote: Excerpts from Matt Harbison's message of 2017-04-07 00:09:54 -0400: On Thu, 06 Apr 2017 23:50:31 -0400, Jun Wu wrote: > Excerpts from Matt Harbison's message of 2017-04-06 23:14:50 -0400: >> On Mon, 27 Mar 2017 02:02:06 -0400, Jun Wu wrote: >> >> > # HG changeset patch >> > # User Jun Wu >> > # Date 1490589217 25200 >> > # Sun Mar 26 21:33:37 2017 -0700 >> > # Node ID 38572bb2cffd815526a727bc6f3aacdca2902f4f >> > # Parent 9b0aa30bf151b6c0e999b017fd328e29440bd447 >> > # Available At https://bitbucket.org/quark-zju/hg-draft >> > # hg pull https://bitbucket.org/quark-zju/hg-draft -r >> > 38572bb2cffd >> > rcutil: let environ override system configs (BC) >> > >> > This is BC because system configs won't be able to override $EDITOR, >> > $PAGER. >> > The new behavior is arguably more rational. >> >> I'm not sure if this is a broader concern than just the test suite with >> env-based config, but I bisected a new Windows failure back to this >> change. > > How did you run tests under Windows? I couldn't reproduce this using > cygwin. > (and I have difficulty with "sh" when using the MSVC compiler) I have MinGW installed, and from the tests directory just run "./run-tests --local test-check-code.t". I have MSVC 2008 installed, which I assume is what is used. Just to confirm: if you run "make local", it will say "cl.exe ..." instead of "gcc ..." (where gcc could come from MinGW). Yep. $ make local | grep cl.exe c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN\amd64\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -Ic:\Python27\include -Ic:\Python27\PC /Tcmercurial/bdiff.c /Fobuild\temp.win-amd64-2.7\Release\mercurial/bdiff.obj ... And you are using Python for Windows, not some cygwin or mingw Python. Correct. 2.7.13, from the python.org Windows installer. And the shell is provided by MinGW. I've never had cygwin or anything else installed. The titlebar says "MINGW32", and $SHELL is /bin/sh. Not sure if there's something specific I should check here. >> >> --- c:/Users/Matt/Projects/hg/tests/test-check-code.t >> +++ c:/Users/Matt/Projects/hg/tests/test-check-code.t.err >> @@ -9,34 +9,7 @@ >> >> $ hg locate -X contrib/python-zstandard -X >> hgext/fsmonitor/pywatchman | >> > sed 's-\\-/-g' | xargs "$check_code" --warnings --per-file=0 || >> false >> - Skipping i18n/polib.py it has no-che?k-code (glob) >> - mercurial/demandimport.py:312: >> - > if os.environ.get('HGDEMANDIMPORT') != 'disable': >> - use encoding.environ instead (py3) >> - mercurial/encoding.py:54: >> - > environ = os.environ >> - use encoding.environ instead (py3) >> - mercurial/encoding.py:56: >> - > environ = os.environb >> - use encoding.environ instead (py3) >> - mercurial/encoding.py:61: >> - >for k, v in os.environ.items()) >> - use encoding.environ instead (py3) >> - mercurial/encoding.py:221: >> - >for k, v in os.environ.items()) >> - use encoding.environ instead (py3) >> - Skipping mercurial/httpclient/__init__.py it has no-che?k-code (glob) >> - Skipping mercurial/httpclient/_readers.py it has no-che?k-code (glob) >> - mercurial/policy.py:46: >> - > if 'HGMODULEPOLICY' in os.environ: >> - use encoding.environ instead (py3) >> - mercurial/policy.py:47: >> - > policy = os.environ['HGMODULEPOLICY'].encode('utf-8') >> - use encoding.environ instead (py3) >> - mercurial/policy.py:49: >> - > policy = os.environ.get('HGMODULEPOLICY', policy) >> - use encoding.environ instead (py3) >> - Skipping mercurial/statprof.py it has no-che?k-code (glob) >> + /usr/bin/env: python: Bad file number >> [1] >> >> @commands in debugcommands.py should be in alphabetical order. >> >> > diff --git a/mercurial/commands.py b/mercurial/commands.py >> > --- a/mercurial/commands.py >> > +++ b/mercurial/commands.py >> > @@ -1807,4 +1807,6 @@ def config(ui, repo, *values, **opts): >> > if t == 'path': >> > ui.debug('read config from: %s\n' % f) >> > +elif t == 'items': >> > +pass >> > else: >> > raise error.ProgrammingError('unknown rctype: %s' % t) >> > diff --git a/mercurial/rcutil.py b/mercurial/rcutil.py >> > --- a/mercurial/rcutil.py >> > +++ b/mercurial/rcutil.py >> > @@ -77,8 +77,12 @@ def rccomponents(): >> > name, value, source) that should fill the config directly. >> > ''' >> > +envrc = ('items', envrcitems()) >> > + >> > global _rccomponents >> > if _rccomponents is None: >> > if 'HGRCPATH' in encoding.environ: >> > -_rccomponents = [] >> > +# assume HGRCPATH is all about user configs so >> environments >> > can be >> > +# overridden. >> > +_rccomponents = [envrc] >> > for p in >> > encoding.environ['HGRCPATH'].split(pycompat.ospathsep): >> >
Re: [PATCH 3 of 4 V2] run-tests: support per-line conditional output in tests
> On Apr 7, 2017, at 5:23 AM, Ryan McElroy wrote: > >> On 4/7/17 2:11 AM, Matt Harbison wrote: >> # HG changeset patch >> # User Matt Harbison >> # Date 1491448647 14400 >> # Wed Apr 05 23:17:27 2017 -0400 >> # Node ID 8e3cf915084723551d0b68094cede7e65f49cf39 >> # Parent 7c5e861f39fbffdfae0e31d1edba419a62391afe >> run-tests: support per-line conditional output in tests > > This series looks like a huge win for test de-duplication! Thanks for working > on it. > >> >> Duplicating entire tests just because the output is different is both error >> prone and can make the tests harder to read. This harnesses the existing >> '(?)' >> infrastructure, both to improve readability, and because it seemed like the >> path >> of least resistance. >> >> The form is: >> >> $ test_cmd >> output (hghave-feature !) # required if hghave.has_feature(), else optional >> out2 (no-hghave-feature2 !) # req if not hghave.has_feature2(), else >> optional > > My only question is: why is it optional if the feature is not present? It > seems like maybe we should have two things: > > ! = must be present iff feature > !? = must be present if feature > > (NOTE: that the first is two-f "iff" -- as in "if and only if" -- so if the > feature is not present, and the line is still there, that would be a failure. > The second one is the one-f "if", as in, "optional if not true".) It's an inherent property of the (?) infrastructure that was used, rather than a design goal. I have no problem with someone refining it like you propose. But I think that splitting will only prevent cruft from accumulating (which isn't a bad thing). I'm struggling to come up with a scenario where we want to fail the iff case other than because the condition is unnecessary. > Regardless, I think this could be done as a follow-up and I only if it's a > good idea. I've marked this series as pre-reviewed in patchwork. > >> >> I originally extended the '(?)' syntax. For example, this: >> >> 2 r4/.hg/cache/checkisexec (execbit ?) >> >> pretty naturally reads as "checkisexec, if execbit". In some ways though, >> this >> inverts the meaning of '?'. For '(?)', the line is purely optional. In the >> example, it is mandatory iff execbit. Otherwise, it is carried forward as >> optional, to preserve the test output. I tried it the other way, (listing >> 'no-exec' in the example), but that is too confusing to read. Kostia >> suggested >> using '!', and that seems fine. >> >> diff --git a/tests/run-tests.py b/tests/run-tests.py >> --- a/tests/run-tests.py >> +++ b/tests/run-tests.py >> @@ -497,6 +497,12 @@ >> # sans \t, \n and \r >> CDATA_EVIL = re.compile(br"[\000-\010\013\014\016-\037]") >> +# Match feature conditionalized output lines in the form, capturing the >> feature >> +# list in group 2, and the preceeding line output in group 1: >> +# >> +# output..output (feature !)\n >> +optline = re.compile(b'(.+) \((.+?) !\)\n$') >> + >> def cdatasafe(data): >> """Make a string safe to include in a CDATA block. >> @@ -1271,8 +1277,19 @@ >> if r: >> els.pop(i) >> break >> -if el and el.endswith(b" (?)\n"): >> -optional.append(i) >> +if el: >> +if el.endswith(b" (?)\n"): >> +optional.append(i) >> +else: >> +m = optline.match(el) >> +if m: >> +conditions = [c for c in m.group(2).split(' >> ')] >> + >> +if self._hghave(conditions)[0]: >> +lout = el >> +else: >> +optional.append(i) >> + >> i += 1 >>if r: >> @@ -1298,8 +1315,10 @@ >> # clean up any optional leftovers >> while expected.get(pos, None): >> el = expected[pos].pop(0) >> -if el and not el.endswith(b" (?)\n"): >> -break >> +if el: >>
Re: [PATCH 07 of 10 V5] rcutil: let environ override system configs (BC)
On Fri, 07 Apr 2017 01:13:20 -0400, Jun Wu wrote: Excerpts from Matt Harbison's message of 2017-04-07 00:35:42 -0400: > Just to confirm: if you run "make local", it will say "cl.exe ..." > instead > of "gcc ..." (where gcc could come from MinGW). Yep. $ make local | grep cl.exe c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN\amd64\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -Ic:\Python27\include -Ic:\Python27\PC /Tcmercurial/bdiff.c /Fobuild\temp.win-amd64-2.7\Release\mercurial/bdiff.obj ... > And you are using Python for > Windows, not some cygwin or mingw Python. Correct. 2.7.13, from the python.org Windows installer. > And the shell is provided by MinGW. I've never had cygwin or anything else installed. The titlebar says "MINGW32", and $SHELL is /bin/sh. Not sure if there's something specific I should check here. Thanks. I have sent a fix. That did the trick, thanks. Out of curiosity, how did you figure you the problem from that error message? xargs would have been the last thing I would have suspected. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] setup: use setuptools on Windows (issue5400)
On Thu, 09 Mar 2017 23:06:34 -0500, Gregory Szorc wrote: # HG changeset patch # User Gregory Szorc # Date 1489118392 28800 # Thu Mar 09 19:59:52 2017 -0800 # Node ID b51f9adb41e68d9f3d88582f044d2742ae29ce09 # Parent cd29673cebdbe2d998009322e4c3657389d6aed0 setup: use setuptools on Windows (issue5400) We've had a long, complicated history with setuptools. We want to make it the universal default. But when we do, it breaks things. `python setup.py build` is broken on Windows today. Forcing the use of setuptools via FORCE_SETUPTOOLS=1 unbreaks things. Since the previous bustage with making setuptools the default was on !Windows, it seems safe to move ahead with the setuptools transition on Windows. So this patch does that. I'm not sure why, or what we should do about it, but test-hghave.t fails with this on Windows. I can get a similar failure on Linux with FORCE_SETUPTOOLS=1. Is this an expected diff with setuptools (and deserving a '(glob) (?)'? --- c:/Users/Matt/Projects/hg/tests/test-hghave.t +++ c:/Users/Matt/Projects/hg/tests/test-hghave.t.err @@ -19,7 +19,11 @@ > foo > EOF $ run-tests.py $HGTEST_RUN_TESTS_PURE test-hghaveaddon.t + warning: Testing with unexpected mercurial lib: C:\Users\Matt\AppData\Local\Temp\hgtests.ie8k3minstall\lib\python\mercurial-4.1.1-py2.7-win-amd64.egg\mercurial + (expected C:\Users\Matt\AppData\Local\Temp\hgtests.ie8k3m\install\lib\python\mercurial) . + warning: Tested with unexpected mercurial lib: C:\Users\Matt\AppData\Local\Temp\hgtests.ie8k3minstall\lib\python\mercurial-4.1.1-py2.7-win-amd64.egg\mercurial + (expected C:\Users\Matt\AppData\Local\Temp\hgtests.ie8k3m\install\lib\python\mercurial) # Ran 1 tests, 0 skipped, 0 warned, 0 failed. diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -63,7 +63,10 @@ import re import shutil import tempfile from distutils import log -if 'FORCE_SETUPTOOLS' in os.environ: +# We have issues with setuptools on some platforms and builders. Until +# those are resolved, setuptools is opt-in except for platforms where +# we don't have issues. +if os.name == 'nt' or 'FORCE_SETUPTOOLS' in os.environ: from setuptools import setup else: from distutils.core import setup ___ 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
[PATCH 4 of 4] test-http-proxy: add the Windows variant of "connection refused"
# HG changeset patch # User Matt Harbison # Date 1491678405 14400 # Sat Apr 08 15:06:45 2017 -0400 # Node ID 42c7df6da065e310c5685fbba2799ffe77d73afd # Parent 651cf90e65f6c5f5717caa9779f268319e2bc676 test-http-proxy: add the Windows variant of "connection refused" The full error is "No connection could be made because the target machine actively refused it". diff --git a/tests/test-http-proxy.t b/tests/test-http-proxy.t --- a/tests/test-http-proxy.t +++ b/tests/test-http-proxy.t @@ -87,7 +87,7 @@ misconfigured hosts) $ http_proxy=localhost:$HGPORT2 hg clone --config http_proxy.always=True http://localhost:$HGPORT/ f - abort: error: (Connection refused|Protocol not supported) (re) + abort: error: (Connection refused|Protocol not supported|.* actively refused it) (re) [255] do not use the proxy if it is in the no list ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 4] test-bundle: glob away a URL protocol separator
# HG changeset patch # User Matt Harbison # Date 1491677199 14400 # Sat Apr 08 14:46:39 2017 -0400 # Node ID c6379326f01a27b12a8bd6c90c6a5995dfe70edf # Parent c39e7c4b535c654d5b2f7790efebff2909986a04 test-bundle: glob away a URL protocol separator MSYS thinks the ':' is a Unix path separator, and replaces it with ';'. diff --git a/tests/test-bundle.t b/tests/test-bundle.t --- a/tests/test-bundle.t +++ b/tests/test-bundle.t @@ -232,7 +232,7 @@ adding manifests adding file changes added 9 changesets with 7 changes to 4 files (+1 heads) - changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=bundle:../full.hg + changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=bundle*../full.hg (glob) (run 'hg heads' to see heads, 'hg merge' to merge) Rollback empty ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 4] test-fileset: eliminate a duplicate test that was conditionalized for output
# HG changeset patch # User Matt Harbison # Date 1491678109 14400 # Sat Apr 08 15:01:49 2017 -0400 # Node ID 651cf90e65f6c5f5717caa9779f268319e2bc676 # Parent d236dca9355d6af70f20ba7966ccf903657a61c8 test-fileset: eliminate a duplicate test that was conditionalized for output diff --git a/tests/test-fileset.t b/tests/test-fileset.t --- a/tests/test-fileset.t +++ b/tests/test-fileset.t @@ -348,7 +348,6 @@ Test safety of 'encoding' on removed files -#if symlink $ fileset 'encoding("ascii")' dos mac @@ -359,23 +358,9 @@ 2k b1 b2 - b2link + b2link (symlink !) bin c1 -#else - $ fileset 'encoding("ascii")' - dos - mac - mixed - .hgsub - .hgsubstate - 1k - 2k - b1 - b2 - bin - c1 -#endif Test detection of unintentional 'matchctx.existing()' invocation ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 4] test-fileset: glob away hash differences
# HG changeset patch # User Matt Harbison # Date 1491677744 14400 # Sat Apr 08 14:55:44 2017 -0400 # Node ID d236dca9355d6af70f20ba7966ccf903657a61c8 # Parent c6379326f01a27b12a8bd6c90c6a5995dfe70edf test-fileset: glob away hash differences There are various files committed above that can't be used on Windows because of the name, or being a symlink. diff --git a/tests/test-fileset.t b/tests/test-fileset.t --- a/tests/test-fileset.t +++ b/tests/test-fileset.t @@ -403,15 +403,15 @@ small reminder of the repository state $ hg log -G - @ changeset: 4:160936123545 + @ changeset: 4:* (glob) | tag: tip | user:test | date:Thu Jan 01 00:00:00 1970 + | summary: subrepo | - ochangeset: 3:9d594e11b8c9 + ochangeset: 3:* (glob) |\ parent: 2:55b05bdebf36 - | | parent: 1:830839835f98 + | | parent: 1:* (glob) | | user:test | | date:Thu Jan 01 00:00:00 1970 + | | summary: merge @@ -422,7 +422,7 @@ | | date:Thu Jan 01 00:00:00 1970 + | | summary: diverging | | - o | changeset: 1:830839835f98 + o | changeset: 1:* (glob) |/ user:test |date:Thu Jan 01 00:00:00 1970 + |summary: manychanges ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH] templatekw: clarify the result of {latesttag} when no tag exists
# HG changeset patch # User Matt Harbison # Date 1491711054 14400 # Sun Apr 09 00:10:54 2017 -0400 # Node ID 8b5a325adc7a011fbbed18886290684793ff8a35 # Parent 42c7df6da065e310c5685fbba2799ffe77d73afd templatekw: clarify the result of {latesttag} when no tag exists My initial expectation was that the list would be empty, and therefore detectable with {if()}. The map for {latesttag()} is populated with real values in this case (except {tag}), so it probably doesn't make any sense to change this to an empty list. diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py --- a/mercurial/templatekw.py +++ b/mercurial/templatekw.py @@ -432,7 +432,8 @@ @templatekeyword('latesttag') def showlatesttag(**args): """List of strings. The global tags on the most recent globally -tagged ancestor of this changeset. +tagged ancestor of this changeset. If no such tags exist, the list +consists of the single string "null". """ return showlatesttags(None, **args) diff --git a/mercurial/templater.py b/mercurial/templater.py --- a/mercurial/templater.py +++ b/mercurial/templater.py @@ -719,7 +719,9 @@ @templatefunc('latesttag([pattern])') def latesttag(context, mapping, args): """The global tags matching the given pattern on the -most recent globally tagged ancestor of this changeset.""" +most recent globally tagged ancestor of this changeset. +If no such tags exist, the "{tag}" template resolves to +the string "null".""" if len(args) > 1: # i18n: "latesttag" is a keyword raise error.ParseError(_("latesttag expects at most one argument")) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] setup: use setuptools on Windows (issue5400)
On Sun, 09 Apr 2017 09:28:04 -0400, Yuya Nishihara wrote: On Sat, 08 Apr 2017 20:30:53 -0400, Matt Harbison wrote: On Thu, 09 Mar 2017 23:06:34 -0500, Gregory Szorc wrote: > # HG changeset patch > # User Gregory Szorc > # Date 1489118392 28800 > # Thu Mar 09 19:59:52 2017 -0800 > # Node ID b51f9adb41e68d9f3d88582f044d2742ae29ce09 > # Parent cd29673cebdbe2d998009322e4c3657389d6aed0 > setup: use setuptools on Windows (issue5400) > > We've had a long, complicated history with setuptools. We want to > make it the universal default. But when we do, it breaks things. > > `python setup.py build` is broken on Windows today. Forcing > the use of setuptools via FORCE_SETUPTOOLS=1 unbreaks things. > > Since the previous bustage with making setuptools the default > was on !Windows, it seems safe to move ahead with the setuptools > transition on Windows. So this patch does that. I'm not sure why, or what we should do about it, but test-hghave.t fails with this on Windows. I can get a similar failure on Linux with FORCE_SETUPTOOLS=1. Is this an expected diff with setuptools (and deserving a '(glob) (?)'? --- c:/Users/Matt/Projects/hg/tests/test-hghave.t +++ c:/Users/Matt/Projects/hg/tests/test-hghave.t.err @@ -19,7 +19,11 @@ > foo > EOF $ run-tests.py $HGTEST_RUN_TESTS_PURE test-hghaveaddon.t + warning: Testing with unexpected mercurial lib: C:\Users\Matt\AppData\Local\Temp\hgtests.ie8k3minstall\lib\python\mercurial-4.1.1-py2.7-win-amd64.egg\mercurial + (expected C:\Users\Matt\AppData\Local\Temp\hgtests.ie8k3m\install\lib\python\mercurial) Perhaps this assumption isn't true for setuptools. https://www.mercurial-scm.org/repo/hg/file/4.1.2/tests/run-tests.py#l2469 I have no idea if setuptools can be configured to use simple installation layout. That's a good tip, thanks. The output above is from the original patch, but it is simpler for @ committed: + warning: Testing with unexpected mercurial lib: c:\Users\Matt\Projects\hg\mercurial + (expected C:\Users\Matt\AppData\Local\Temp\hgtests.q1ldmg\install\lib\python\mercurial) Without setuptools: expecthg: C:\Users\Matt\AppData\Local\Temp\hgtests.kshzjl\install\lib\python\mercurial actualhg: C:\Users\Matt\AppData\Local\Temp\hgtests.kshzjl\install\lib\python\mercurial bindir: C:\Users\Matt\AppData\Local\Temp\hgtests.kshzjl\install\bin pydir: C:\Users\Matt\AppData\Local\Temp\hgtests.kshzjl\install\lib\python tmpdir: C:\Users\Matt\AppData\Local\Temp\hgtests.kshzjl\install\bin With setuptools: expecthg: C:\Users\Matt\AppData\Local\Temp\hgtests.q1ldmg\install\lib\python\mercurial actualhg: c:\Users\Matt\Projects\hg\mercurial bindir: C:\Users\Matt\AppData\Local\Temp\hgtests.q1ldmg\install\bin pydir: C:\Users\Matt\AppData\Local\Temp\hgtests.q1ldmg\install\lib\python tmpdir: C:\Users\Matt\AppData\Local\Temp\hgtests.q1ldmg\install\bin So it seems like the test is importing the 'hg' module that the main test runner is using? It looks like test-run-tests.t papers over this by invoking run-tests.py with '--with-hg=`which hg`', which also works here. But someone who understands the underlying issue should take a look before doing that. The function you referenced bails in this case, so it feels like subverting a valid check. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 2] test-patchbomb: convert the pretendmail program from *.sh to *.py
# HG changeset patch # User Matt Harbison # Date 1491785368 14400 # Sun Apr 09 20:49:28 2017 -0400 # Node ID 1de38b5ca1886aa41844dc7a80c1b92b65a8171e # Parent 9259cf823690e4fcd34a4d2ecd57ced2060d2b3d test-patchbomb: convert the pretendmail program from *.sh to *.py Windows doesn't know how to execute *.sh, so tests were failing with: abort: 'pretendmail.py' specified as email transport, but not in PATH I was able to create a *.bat file to do the same thing, but neither the *.py nor *.bat were able to read from stdin[1] and write to stdout on Windows, like `cat` was doing in the shell script. The *.py script is infinitely more readable. It isn't possible to specify 'method = python `pwd`/*.py', because everything specified on the RHS ends up quoted, because of the space. Therefore, $PATHEXT is modified to include *.py, which causes a registry lookup and Windows to figure out that it should open *.py with python.exe. Unlike the python installer, the MSYS installer doesn't add registry entries for *.sh, so it isn't possible to execute shell scripts directly. [1] https://stackoverflow.com/questions/6979747/read-stdin-stream-in-a-batch-file diff --git a/tests/test-patchbomb.t b/tests/test-patchbomb.t --- a/tests/test-patchbomb.t +++ b/tests/test-patchbomb.t @@ -2849,15 +2849,31 @@ Set up a fake sendmail program - $ cat > pretendmail.sh << 'EOF' - > #!/bin/sh - > echo "$@" - > cat + $ cat > pretendmail.py << 'EOF' + > #!/usr/bin/env python + > + > from __future__ import print_function + > import sys + > + > print(sys.argv) + > + > for line in sys.stdin: + > print(line.rstrip()) + > exit(0) > EOF - $ chmod +x pretendmail.sh + +Make it possible to execute *.py directly in cmd.exe for this test + +#if windows + $ export PATHEXT='.COM;.EXE;.BAT;.CMD;.PY' +#endif + +#if execbit + $ chmod +x pretendmail.py +#endif $ echo '[email]' >> $HGRCPATH - $ echo "method=`pwd`/pretendmail.sh" >> $HGRCPATH + $ echo "method=`pwd`/pretendmail.py" >> $HGRCPATH Test introduction configuration = @@ -2950,7 +2966,7 @@ warning: invalid patchbomb.intro value "mpmwearaclownnose" (should be one of always, never, auto) - -f test foo + ['$TESTTMP/t2/pretendmail.py', '-f', 'test', 'foo'] Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit @@ -2982,7 +2998,7 @@ +d sending [PATCH] test ... - sending mail: $TESTTMP/t2/pretendmail.sh -f test foo + sending mail: $TESTTMP/t2/pretendmail.py -f test foo Test pull url header = ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 2] test-patchbomb: disable a failing test on Windows
# HG changeset patch # User Matt Harbison # Date 1491787400 14400 # Sun Apr 09 21:23:20 2017 -0400 # Node ID 548c1c174b937b1512ea689661c591dcf778ebe1 # Parent 1de38b5ca1886aa41844dc7a80c1b92b65a8171e test-patchbomb: disable a failing test on Windows It's unknown where or why the patch content is being lost. Echoing into the same script from inside cmd.exe (not MSYS) will print out the echoed strings. diff --git a/tests/test-patchbomb.t b/tests/test-patchbomb.t --- a/tests/test-patchbomb.t +++ b/tests/test-patchbomb.t @@ -2960,6 +2960,23 @@ single rev +For reasons unknown, pretendmail isn't transferring stdin to stdout on Windows, +so the mail content is lost. + +#if windows + + $ hg email --date '1980-1-1 0:1' -v -t foo -s test -r '10' + From [test]: test + this patch series consists of 1 patches. + + warning: invalid patchbomb.intro value "mpmwearaclownnose" + (should be one of always, never, auto) + + sending [PATCH] test ... + sending mail: $TESTTMP/t2/pretendmail.py -f test foo + +#else + $ hg email --date '1980-1-1 0:1' -v -t foo -s test -r '10' From [test]: test this patch series consists of 1 patches. @@ -3000,6 +3017,8 @@ sending [PATCH] test ... sending mail: $TESTTMP/t2/pretendmail.py -f test foo +#endif + Test pull url header = ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH] tests: print Unix style paths in *.py tests
# HG changeset patch # User Matt Harbison # Date 1491790767 14400 # Sun Apr 09 22:19:27 2017 -0400 # Node ID f5ea3f4ee8206f99c7038814e87b34ae3124be98 # Parent 548c1c174b937b1512ea689661c591dcf778ebe1 tests: print Unix style paths in *.py tests These tests don't support (glob). I didn't audit all tests, but these ones were failing. diff --git a/tests/test-config-env.py b/tests/test-config-env.py --- a/tests/test-config-env.py +++ b/tests/test-config-env.py @@ -8,6 +8,7 @@ encoding, rcutil, ui as uimod, +util, ) testtmp = encoding.environ['TESTTMP'] @@ -40,7 +41,7 @@ ui = uimod.ui.load() for section, name, value in ui.walkconfig(): source = ui.configsource(section, name) -print('%s.%s=%s # %s' % (section, name, value, source)) +print('%s.%s=%s # %s' % (section, name, value, util.pconvert(source))) print('') # environment variable overrides diff --git a/tests/test-trusted.py b/tests/test-trusted.py --- a/tests/test-trusted.py +++ b/tests/test-trusted.py @@ -74,14 +74,14 @@ return u print('trusted') for name, path in u.configitems('paths'): -print(' ', name, '=', path) +print(' ', name, '=', util.pconvert(path)) print('untrusted') for name, path in u.configitems('paths', untrusted=True): print('.', end=' ') u.config('paths', name) # warning with debug=True print('.', end=' ') u.config('paths', name, untrusted=True) # no warnings -print(name, '=', path) +print(name, '=', util.pconvert(path)) print() return u @@ -217,6 +217,12 @@ list=spam,ham,eggs ''') u = testui(user='abc', group='def', cuser='foo', silent=True) +def configpath(section, name, default=None, untrusted=False): +path = u.configpath(section, name, default, untrusted) +if path is None: +return None +return util.pconvert(path) + print('# suboptions, trusted and untrusted') trusted = u.configsuboptions('foo', 'sub') untrusted = u.configsuboptions('foo', 'sub', untrusted=True) @@ -224,7 +230,7 @@ (trusted[0], sorted(trusted[1].items())), (untrusted[0], sorted(untrusted[1].items( print('# path, trusted and untrusted') -print(u.configpath('foo', 'path'), u.configpath('foo', 'path', untrusted=True)) +print(configpath('foo', 'path'), configpath('foo', 'path', untrusted=True)) print('# bool, trusted and untrusted') print(u.configbool('foo', 'bool'), u.configbool('foo', 'bool', untrusted=True)) print('# int, trusted and untrusted') ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
SSL troubleshooting on Windows
I had a little adventure a couple of weeks ago, changing a certificate on the server. I'm not sure if it's worth doing anything, or if this just serves as a heads up to others using Windows. We use SCM Manager (which uses tomcat) on CentOS, with Mercurial 4.0.2. The certificate had expired over the weekend. So the admin imported the new certificate into the tomcat keystore, saw that the main page loaded in a web browser (probably Chrome, and I think I subsequently tried FireFox), and declared victory. But Mercurial was still failing the verification. After a bit of fiddling around, he eventually imported the root and intermediate certificates for the chain into the keystore as well, and then Mercurial clients worked. Except for one Windows machine. (I'm a bit puzzled that the web browsers were OK with this config, but not Mercurial.) I was able to get the one failing machine working by temporarily setting the fingerprint. After awhile of debugging, I realized that this is a python bug [1]. Basically, Windows doesn't ship with a full set of certificates, and instead downloads them on demand. But python isn't triggering the download. In this case, Windows had the root certificate and the leaf certificate from the website, but was missing the intermediate certificate. So the "fix" was to load the main web page in Internet Explorer, which silently builds the certificate chain on Windows, and then Mercurial works. An additional problem is that the error message is the same for both this failure, and a real certificate problem. I started adding code to: 1) Detect and fix this without Internet Explorer via a debug function that calls CertGetCertificateChain() 2) Detect the problem when connecting, and print out a message pointing to the debug command 3) Just fix the problem when connecting, so that the debug command isn't necessary The problem is that you need to successfully connect to the server in order to get the certificate to pass to the Win32 function. Since the connection fails if verification is on, a second (non verifying) connection needs to be established to get the certificate, and then a third (verifying) connection to retry the original. Ugh. I tried turning off SSL verification on Windows, so that only the first connection is needed. It looks like there are Win32 functions that can also verify the certificate chain, so we shouldn't be missing any functionality. But python doesn't return the non-binary certificate when verification is off, so another check we do fails [2]. I assume the chance of landing this hacky code is about 0. The other alternative seems to be to package certifi or similar in the binary Windows installers. That was mentioned when Greg overhauled the SSL stuff last year, but I think it was deferred because there wasn't any real reason to when python can access the Windows certificate store. Maybe this is a reason? [1] https://bugs.python.org/issue20916 [2] https://www.mercurial-scm.org/repo/hg/file/e0dc40530c5a/mercurial/sslutil.py#l623 ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 2] test-patchbomb: convert the pretendmail program from *.sh to *.py
On Mon, 10 Apr 2017 08:52:52 -0400, Yuya Nishihara wrote: On Sun, 09 Apr 2017 21:52:30 -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1491785368 14400 # Sun Apr 09 20:49:28 2017 -0400 # Node ID 1de38b5ca1886aa41844dc7a80c1b92b65a8171e # Parent 9259cf823690e4fcd34a4d2ecd57ced2060d2b3d test-patchbomb: convert the pretendmail program from *.sh to *.py Windows doesn't know how to execute *.sh, so tests were failing with: abort: 'pretendmail.py' specified as email transport, but not in PATH I was able to create a *.bat file to do the same thing, but neither the *.py nor *.bat were able to read from stdin[1] and write to stdout on Windows, like `cat` was doing in the shell script. The *.py script is infinitely more readable. It isn't possible to specify 'method = python `pwd`/*.py', because everything specified on the RHS ends up quoted, because of the space. Therefore, $PATHEXT is modified to include *.py, which causes a registry lookup and Windows to figure out that it should open *.py with python.exe. Unlike the python installer, the MSYS installer doesn't add registry entries for *.sh, so it isn't possible to execute shell scripts directly. Does it mean there's still a risk the test will fail? e.g. because .py is associated with python3, or not associated at all. It seems like a small risk to be associated with something other than python, but not impossible. If it was associated with python3, that seems OK since it's just reading stdin and writing to stdout (assuming this is valid py3 code- I didn't try that). I'm fine with disabling the tests though. I think it's okay to disable the sendmail test at all on Windows because sendmail is a Unix thing. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH V2] test-patchbomb: disable sendmail tests on Windows
# HG changeset patch # User Matt Harbison # Date 1491873174 14400 # Mon Apr 10 21:12:54 2017 -0400 # Node ID bfa323bbeebb534f3540e9198648f1bd317b059a # Parent 08fbc97d1364b08b53d538efc33b3ed41cea51a0 test-patchbomb: disable sendmail tests on Windows These tests were failing, and there isn't a trivial way to execute a script on Windows [1]. [1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2017-April/096497.html diff --git a/tests/test-patchbomb.t b/tests/test-patchbomb.t --- a/tests/test-patchbomb.t +++ b/tests/test-patchbomb.t @@ -2846,6 +2846,7 @@ @@ -0,0 +1,1 @@ +d +#if no-windows Set up a fake sendmail program @@ -3026,3 +3027,4 @@ (use 'hg push $TESTTMP/t3 -r ff2c9fa2018b -r 3b6f1ec9dde9') [255] +#endif ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 2] windows: add context manager support to mixedfilemodewrapper
# HG changeset patch # User Matt Harbison # Date 1491961091 14400 # Tue Apr 11 21:38:11 2017 -0400 # Node ID ef3aa25da8e5b3137b917e9a1756df7a7eac5c3a # Parent 7b6f5632f09d85b96b2f986961576eb165d44cbf windows: add context manager support to mixedfilemodewrapper I stumbled into this in the next patch. The difference between getting a context manager capable object or not from vfs classes was as subtle as adding a '+' to the file mode. diff --git a/mercurial/windows.py b/mercurial/windows.py --- a/mercurial/windows.py +++ b/mercurial/windows.py @@ -64,6 +64,12 @@ object.__setattr__(self, r'_fp', fp) object.__setattr__(self, r'_lastop', 0) +def __enter__(self): +return self._fp.__enter__() + +def __exit__(self, exc_type, exc_val, exc_tb): +self._fp.__exit__(exc_type, exc_val, exc_tb) + def __getattr__(self, name): return getattr(self._fp, name) ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 2] largefiles: set the extension as enabled locally after a share requiring it
# HG changeset patch # User Matt Harbison # Date 1491958490 14400 # Tue Apr 11 20:54:50 2017 -0400 # Node ID 9b4202740173227e232659964725c4152d87e469 # Parent ef3aa25da8e5b3137b917e9a1756df7a7eac5c3a largefiles: set the extension as enabled locally after a share requiring it This has been done for clone since e1dbe0b215ae, so it makes sense here for the same reasons. diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py --- a/hgext/largefiles/overrides.py +++ b/hgext/largefiles/overrides.py @@ -903,6 +903,14 @@ return result +def hgpostshare(orig, sourcerepo, destrepo, bookmarks=True, defaultpath=None): +orig(sourcerepo, destrepo, bookmarks, defaultpath) + +# If largefiles is required for this repo, permanently enable it locally +if 'largefiles' in destrepo.requirements: +with destrepo.vfs('hgrc', 'a+', text=True) as fp: +fp.write('\n[extensions]\nlargefiles=\n') + def overriderebase(orig, ui, repo, **opts): if not util.safehasattr(repo, '_largefilesenabled'): return orig(ui, repo, **opts) diff --git a/hgext/largefiles/uisetup.py b/hgext/largefiles/uisetup.py --- a/hgext/largefiles/uisetup.py +++ b/hgext/largefiles/uisetup.py @@ -120,6 +120,7 @@ _('download all versions of all largefiles'))] entry[1].extend(cloneopt) entry = extensions.wrapfunction(hg, 'clone', overrides.hgclone) +entry = extensions.wrapfunction(hg, 'postshare', overrides.hgpostshare) entry = extensions.wrapcommand(commands.table, 'cat', overrides.overridecat) diff --git a/tests/test-largefiles-misc.t b/tests/test-largefiles-misc.t --- a/tests/test-largefiles-misc.t +++ b/tests/test-largefiles-misc.t @@ -212,6 +212,18 @@ date:Thu Jan 01 00:00:00 1970 + summary: add files +sharing a largefile repo automatically enables largefiles on the share + + $ hg share --config extensions.share= . ../shared_lfrepo + updating working directory + getting changed largefiles + 1 largefiles updated, 0 removed + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cat ../shared_lfrepo/.hg/hgrc + + [extensions] + largefiles= + verify that large files in subrepos handled properly $ hg init subrepo $ echo "subrepo = subrepo" > .hgsub diff --git a/tests/test-share.t b/tests/test-share.t --- a/tests/test-share.t +++ b/tests/test-share.t @@ -240,6 +240,14 @@ bm3 4:62f4ded848e4 $ cd .. +non largefiles repos won't enable largefiles + + $ hg share --config extensions.largefiles= repo3 sharedrepo + updating working directory + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ [ -f sharedrepo/.hg/hgrc ] + [1] + test pushing bookmarks works $ hg clone repo3 repo4 ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: stable ordering of test output
On Thu, 13 Apr 2017 16:17:34 -0400, Augie Fackler wrote: On Thu, Apr 13, 2017 at 3:55 PM, Augie Fackler wrote: On Wed, Mar 8, 2017 at 10:44 AM, Yuya Nishihara wrote: On Tue, 7 Mar 2017 17:56:58 +0100, Pierre-Yves David wrote: On the other hand, this is probably not so bundle2 specific. We have some "select" logic to read stdout and stderr as soon as possible. This is the main suspect as it is possible that this logic behave different under linux and other unix (not too much effort have been put into it). posix.poll() waits every type of operation no matter if fd is e.g. writable or not. IIRC, this doesn't always work on FreeBSD since the underlying resource of read/write ends might be shared in the kernel. But I don't think this is the source of the unstable output. I've had a little time today between things to try and debug this. What I've found so far: 1) when the test passes, the remote: output is printed by the _forwardoutput method in sshpeer, presumably since stderr makes it to the client before the close of stdout. 2) When the test fails (as on BSD, and I guess Solaris), the client notices that stdout closed before stderr. It then aborts the transaction and sshpeer.cleanup() notices some data chilling on stderr and ensures it gets read and printed. I'm not really sure why BSD systems would be quicker at communicating the closed FD than other systems. I'm poking at dummyssh now to see if maybe it's weirdness from there... Here's a patch that seems to work. I'm not happy about it, but it makes the behavior consistent, and it looks mostly harmless. This fixes it for Windows too. Thanks! # HG changeset patch # User Augie Fackler # Date 1492114180 14400 # Thu Apr 13 16:09:40 2017 -0400 # Node ID ec81fd7580f3e31aa92e8834ffbcf2a8e80e72e3 # Parent 35afb54dbb4df2975dbbf0e1525b98611f18ba85 sshpeer: try harder to snag stderr when stdout closes unexpectedly Resolves test failures on FreeBSD, but I'm not happy about the fix. diff --git a/mercurial/sshpeer.py b/mercurial/sshpeer.py --- a/mercurial/sshpeer.py +++ b/mercurial/sshpeer.py @@ -110,9 +110,17 @@ class doublepipe(object): if mainready: meth = getattr(self._main, methname) if data is None: -return meth() +r = meth() else: -return meth(data) +r = meth(data) +if not r and data != 0: +# We've observed a condition that indicates the +# stdout closed unexpectedly. Check stderr one +# more time and snag anything that's there before +# letting anyone know the main part of the pipe +# closed prematurely. +_forwardoutput(self._ui, self._side) +return r def close(self): return self._main.close() ___ 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 1 of 2 V3] serve: add support for Mercurial subrepositories
On Thu, 30 Mar 2017 21:19:01 -0400, Matt Harbison wrote: On Tue, 28 Mar 2017 10:11:15 -0400, Yuya Nishihara wrote: On Sun, 26 Mar 2017 23:04:30 -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1488146743 18000 # Sun Feb 26 17:05:43 2017 -0500 # Node ID 0ff9bef3e0f67422cf29c200fa4a671d861d060b # Parent c60091fa1426892552dd6c0dd4b9c49e3c3da045 serve: add support for Mercurial subrepositories +def addwebdirpath(repo, serverpath, webconf): +webconf[serverpath] = repo.root +repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root)) + +for r in repo.revs('filelog("path:.hgsub")'): +ctx = repo[r] +for subpath in ctx.substate: +ctx.sub(subpath).addwebdirpath(serverpath, webconf) [...] --- a/mercurial/server.py +++ b/mercurial/server.py @@ -15,6 +15,7 @@ from . import ( chgserver, +cmdutil, commandserver, error, hgweb, @@ -130,11 +131,24 @@ baseui = ui webconf = opts.get('web_conf') or opts.get('webdir_conf') if webconf: +if opts.get('subrepos'): +raise error.Abort(_('--web-conf cannot be used with --subrepos')) + # load server settings (e.g. web.port) to "copied" ui, which allows # hgwebdir to reload webconf cleanly servui = ui.copy() servui.readconfig(webconf, sections=['web']) alluis.add(servui) +elif opts.get('subrepos'): +servui = ui.copy() +alluis.add(servui) No need to make a copy of ui since nothing loaded into servui. +@annotatesubrepoerror +def addwebdirpath(self, serverpath, webconf): +# The URL request contains the subrepo source path, not the local +# subrepo path. The distinction matters for 'foo = ../foo' type +# entries. It isn't possible to serve up 'foo = http://..' type +# entries, because the server path is relative to this local server. +src = self._state[0] +if util.url(src).islocal(): +path = util.normpath(serverpath + src) +cmdutil.addwebdirpath(self._repo, path + '/', webconf) What happens if src is '../../escape_from_web_root' ? I don't think it's correct to lay out subrepositories by peer URL since we're exporting a _local_ clone. If you do "hg clone sub1 sub2", you'll see sub1 in local-path layout. "hg serve -S" just allows us to see sub1 over http. That was actually how I first coded it, but switched it because it wasn't handling the test in test-subrepo-deep-nested-change.t properly. I forget what exactly the problem was. I'll take another look this weekend. I finally got back to this, now that I've got the serve tests working on Windows. The problem I had run into is that in test-subrepo-deep-nested-change.t, the repos exist in the filesystem as: main sub1 sub2 If you clone `hg clone main` right after the "main import" commit around line 74, it builds a tree like: cloning subrepo sub1 from $TESTTMP/sub1 cloning subrepo sub1\sub2 from $TESTTMP/sub2 The fact that you can locally clone the original 'main' strongly suggests that we should be able to serve the original main, and be able to clone from it too. The subsequent test I added there does that. It took using the peer layout to do this. (Though it really isn't a peer- it's what is in the local filesystem where the serve is happening.) It's easy enough to setup the dictionary such that the repos would be served up as: / /sub1 /sub1/sub2 But clone seems to want to follow the peer layout specified in .hgsub of the parent. (I can see "GET /../sub1?cmd=capabilities ..." in access.log, which is where clone is dying with a 404.) I know that escaping '/' is generally a security concern. But I'm not sure that it is here, since the only thing served above '/' is something explicitly in the repository (via .hgsub). So it can't be anything else that is potentially sensitive. I don't care too much about this case. I'd rather have the functionality for the recommended nested subrepo case, than not at all. But I don't want to sneak something in that is broken, with no obvious way to fix if somebody complains. Thoughts? Maybe it's okay to add all repositories found under repo.root to webconf. For strictness, we could check if a subrepo path exists in .hgsub of any revision. I'd like to avoid searching through the directory tree, if possible. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH V4] hgwebdir: allow a repository to be hosted at "/"
# HG changeset patch # User Matt Harbison # Date 1491015641 14400 # Fri Mar 31 23:00:41 2017 -0400 # Node ID 3fd50d5f9314a96f43eb73480763f224c4d05831 # Parent 4c2c30bc38b4f84ce8f215146bbf158e299065b3 hgwebdir: allow a repository to be hosted at "/" This can be useful in general, but will also be useful for hosting subrepos, with the main repo at /. diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py +++ b/mercurial/hgweb/hgweb_mod.py @@ -335,7 +335,7 @@ req.url = req.env['SCRIPT_NAME'] if not req.url.endswith('/'): req.url += '/' -if 'REPO_NAME' in req.env: +if req.env.get('REPO_NAME'): req.url += req.env['REPO_NAME'] + '/' if 'PATH_INFO' in req.env: diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -257,7 +257,7 @@ repos = dict(self.repos) -if not virtual or (virtual == 'index' and virtual not in repos): +if (not virtual or virtual == 'index') and virtual not in repos: req.respond(HTTP_OK, ctype) return self.makeindex(req, tmpl) @@ -269,8 +269,17 @@ req.respond(HTTP_OK, ctype) return self.makeindex(req, tmpl, subdir) -virtualrepo = virtual -while virtualrepo: +def _virtualdirs(): +# Check the full virtual path, each parent, and the root ('') +if virtual != '': +yield virtual + +for p in util.finddirs(virtual): +yield p + +yield '' + +for virtualrepo in _virtualdirs(): real = repos.get(virtualrepo) if real: req.env['REPO_NAME'] = virtualrepo @@ -284,11 +293,6 @@ except error.RepoError as inst: raise ErrorResponse(HTTP_SERVER_ERROR, str(inst)) -up = virtualrepo.rfind('/') -if up < 0: -break -virtualrepo = virtualrepo[:up] - # browse subdirectories subdir = virtual + '/' if [r for r in repos if r.startswith(subdir)]: diff --git a/tests/test-hgwebdir.t b/tests/test-hgwebdir.t --- a/tests/test-hgwebdir.t +++ b/tests/test-hgwebdir.t @@ -1680,6 +1680,22 @@ $ killdaemons.py + $ cat > paths.conf << EOF + > [paths] + > / = $root/a + > EOF + $ hg serve -p $HGPORT1 -d --pid-file hg.pid --webdir-conf paths.conf + $ cat hg.pid >> $DAEMON_PIDS + + $ hg id http://localhost:$HGPORT1 + 71a89161f014 + + $ get-with-headers.py localhost:$HGPORT1 '' | grep 'index' + + add index file + + $ killdaemons.py + paths errors 1 $ cat error-paths-1.log ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 2 V3] serve: add support for Mercurial subrepositories
On Sat, 15 Apr 2017 15:04:32 -0400, Matt Harbison wrote: On Thu, 30 Mar 2017 21:19:01 -0400, Matt Harbison wrote: On Tue, 28 Mar 2017 10:11:15 -0400, Yuya Nishihara wrote: On Sun, 26 Mar 2017 23:04:30 -0400, Matt Harbison wrote: # HG changeset patch # User Matt Harbison # Date 1488146743 18000 # Sun Feb 26 17:05:43 2017 -0500 # Node ID 0ff9bef3e0f67422cf29c200fa4a671d861d060b # Parent c60091fa1426892552dd6c0dd4b9c49e3c3da045 serve: add support for Mercurial subrepositories +def addwebdirpath(repo, serverpath, webconf): +webconf[serverpath] = repo.root +repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root)) + +for r in repo.revs('filelog("path:.hgsub")'): +ctx = repo[r] +for subpath in ctx.substate: +ctx.sub(subpath).addwebdirpath(serverpath, webconf) [...] --- a/mercurial/server.py +++ b/mercurial/server.py @@ -15,6 +15,7 @@ from . import ( chgserver, +cmdutil, commandserver, error, hgweb, @@ -130,11 +131,24 @@ baseui = ui webconf = opts.get('web_conf') or opts.get('webdir_conf') if webconf: +if opts.get('subrepos'): +raise error.Abort(_('--web-conf cannot be used with --subrepos')) + # load server settings (e.g. web.port) to "copied" ui, which allows # hgwebdir to reload webconf cleanly servui = ui.copy() servui.readconfig(webconf, sections=['web']) alluis.add(servui) +elif opts.get('subrepos'): +servui = ui.copy() +alluis.add(servui) No need to make a copy of ui since nothing loaded into servui. +@annotatesubrepoerror +def addwebdirpath(self, serverpath, webconf): +# The URL request contains the subrepo source path, not the local +# subrepo path. The distinction matters for 'foo = ../foo' type +# entries. It isn't possible to serve up 'foo = http://..' type +# entries, because the server path is relative to this local server. +src = self._state[0] +if util.url(src).islocal(): +path = util.normpath(serverpath + src) +cmdutil.addwebdirpath(self._repo, path + '/', webconf) What happens if src is '../../escape_from_web_root' ? I don't think it's correct to lay out subrepositories by peer URL since we're exporting a _local_ clone. If you do "hg clone sub1 sub2", you'll see sub1 in local-path layout. "hg serve -S" just allows us to see sub1 over http. That was actually how I first coded it, but switched it because it wasn't handling the test in test-subrepo-deep-nested-change.t properly. I forget what exactly the problem was. I'll take another look this weekend. I finally got back to this, now that I've got the serve tests working on Windows. The problem I had run into is that in test-subrepo-deep-nested-change.t, the repos exist in the filesystem as: main sub1 sub2 If you clone `hg clone main` right after the "main import" commit around line 74, it builds a tree like: cloning subrepo sub1 from $TESTTMP/sub1 cloning subrepo sub1\sub2 from $TESTTMP/sub2 The fact that you can locally clone the original 'main' strongly suggests that we should be able to serve the original main, and be able to clone from it too. The subsequent test I added there does that. It took using the peer layout to do this. (Though it really isn't a peer- it's what is in the local filesystem where the serve is happening.) Ugh, nevermind. I see now that the extra copies of the subrepos allow the local cloning to work: main main/sub1 main/sub1/sub2 sub1 sub2 The nested repos are used for commits, but not `hg clone`. And that's what allows the filesystem clone to work. I thought you could only clone foo=../foo type hierarchies once, but I was able to clone a clone in this test. Until I renamed the top level sub{1,2} repos, and then it doesn't even work once. So I guess it's not a big deal that you can't clone this setup over http. I wonder what else these extra copies are masking in the tests... It's easy enough to setup the dictionary such that the repos would be served up as: / /sub1 /sub1/sub2 But clone seems to want to follow the peer layout specified in .hgsub of the parent. (I can see "GET /../sub1?cmd=capabilities ..." in access.log, which is where clone is dying with a 404.) I know that escaping '/' is generally a security concern. But I'm not sure that it is here, since the only thing served above '/' is something explicitly in the repository (via .hgsub). So it can't be anything else that is potentially sensitive. I