Mercurial > hg
view contrib/hgclient.py @ 36900:219b23359f4c
hgweb: support constructing URLs from an alternate base URL
The web.baseurl config option allows server operators to define a
custom URL for hosted content.
The way it works today is that hgwebdir parses this config
option into URL components then updates the appropriate
WSGI environment variables so the request "lies" about its
details. For example, SERVER_NAME is updated to reflect the
alternate base URL's hostname.
The WSGI environment should not be modified because WSGI
applications may want to know the original request details (for
debugging, etc).
This commit teaches our request parser about the existence of
an alternate base URL. If defined, the advertised URL and other
self-reflected paths will take the alternate base URL into account.
The hgweb WSGI application didn't use web.baseurl. But hgwebdir
did. We update hgwebdir to alter the environment parsing
accordingly. The old code around environment manipulation
has been removed.
With this change, parserequestfromenv() has grown to a bit
unwieldy. Now that practically everyone is using it, it is
obvious that there is some unused features that can be trimmed.
So look for this in follow-up commits.
Differential Revision: https://phab.mercurial-scm.org/D2822
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sun, 11 Mar 2018 15:33:56 -0700 |
parents | 3f45488d70df |
children | 73c2b9c9cd3c |
line wrap: on
line source
# A minimal client for Mercurial's command server from __future__ import absolute_import, print_function import os import signal import socket import struct import subprocess import sys import time try: import cStringIO as io stringio = io.StringIO except ImportError: import io stringio = io.StringIO def connectpipe(path=None): cmdline = ['hg', 'serve', '--cmdserver', 'pipe'] if path: cmdline += ['-R', path] server = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE) return server class unixconnection(object): def __init__(self, sockpath): self.sock = sock = socket.socket(socket.AF_UNIX) sock.connect(sockpath) self.stdin = sock.makefile('wb') self.stdout = sock.makefile('rb') def wait(self): self.stdin.close() self.stdout.close() self.sock.close() class unixserver(object): def __init__(self, sockpath, logpath=None, repopath=None): self.sockpath = sockpath cmdline = ['hg', 'serve', '--cmdserver', 'unix', '-a', sockpath] if repopath: cmdline += ['-R', repopath] if logpath: stdout = open(logpath, 'a') stderr = subprocess.STDOUT else: stdout = stderr = None self.server = subprocess.Popen(cmdline, stdout=stdout, stderr=stderr) # wait for listen() while self.server.poll() is None: if os.path.exists(sockpath): break time.sleep(0.1) def connect(self): return unixconnection(self.sockpath) def shutdown(self): os.kill(self.server.pid, signal.SIGTERM) self.server.wait() def writeblock(server, data): server.stdin.write(struct.pack('>I', len(data))) server.stdin.write(data) server.stdin.flush() def readchannel(server): data = server.stdout.read(5) if not data: raise EOFError channel, length = struct.unpack('>cI', data) if channel in 'IL': return channel, length else: return channel, server.stdout.read(length) def sep(text): return text.replace('\\', '/') def runcommand(server, args, output=sys.stdout, error=sys.stderr, input=None, outfilter=lambda x: x): print('*** runcommand', ' '.join(args)) sys.stdout.flush() server.stdin.write('runcommand\n') writeblock(server, '\0'.join(args)) if not input: input = stringio() while True: ch, data = readchannel(server) if ch == 'o': output.write(outfilter(data)) output.flush() elif ch == 'e': error.write(data) error.flush() elif ch == 'I': writeblock(server, input.read(data)) elif ch == 'L': writeblock(server, input.readline(data)) elif ch == 'r': ret, = struct.unpack('>i', data) if ret != 0: print(' [%d]' % ret) return ret else: print("unexpected channel %c: %r" % (ch, data)) if ch.isupper(): return def check(func, connect=connectpipe): sys.stdout.flush() server = connect() try: return func(server) finally: server.stdin.close() server.wait()