##// END OF EJS Templates
share-safe: fix an abort message that references the experimental requirement...
share-safe: fix an abort message that references the experimental requirement Differential Revision: https://phab.mercurial-scm.org/D9851

File last commit:

r43355:eef9a2d6 default
r47088:085294a8 stable
Show More
server.py
235 lines | 7.0 KiB | text/x-python | PythonLexer
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 # server.py - utility and factory of server
#
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
import os
from .i18n import _
Gregory Szorc
py3: manually import pycompat.open into files that need it...
r43355 from .pycompat import open
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506
from . import (
Yuya Nishihara
chgserver: make it a core module and drop extension flags...
r30513 chgserver,
Matt Harbison
serve: add support for Mercurial subrepositories...
r32005 cmdutil,
Yuya Nishihara
server: move service table and factory from commandserver...
r30507 commandserver,
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 error,
Yuya Nishihara
server: move service factory from hgweb
r30509 hgweb,
Augie Fackler
server: use pycompat to get argv
r32530 pycompat,
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 util,
)
Augie Fackler
formatting: blacken the codebase...
r43346 from .utils import procutil
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137
Augie Fackler
formatting: blacken the codebase...
r43346 def runservice(
opts,
parentfn=None,
initfn=None,
runfn=None,
logfile=None,
runargs=None,
appendpid=False,
):
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 '''Run a command as a service.'''
Matt Harbison
server: refactor 'daemon_postexec' instructions into a dictionary
r37232 postexecargs = {}
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts[b'daemon_postexec']:
for inst in opts[b'daemon_postexec']:
if inst.startswith(b'unlink:'):
postexecargs[b'unlink'] = inst[7:]
elif inst.startswith(b'chdir:'):
postexecargs[b'chdir'] = inst[6:]
elif inst != b'none':
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'invalid value for --daemon-postexec: %s') % inst
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Harbison
server: refactor 'daemon_postexec' instructions into a dictionary
r37232
Matt Harbison
server: add an error feedback mechanism for when the daemon fails to launch...
r37229 # When daemonized on Windows, redirect stdout/stderr to the lockfile (which
# gets cleaned up after the child is up and running), so that the parent can
# read and print the error if this child dies early. See 594dd384803c. On
# other platforms, the child can write to the parent's stdio directly, until
# it is redirected prior to runfn().
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if pycompat.iswindows and opts[b'daemon_postexec']:
if b'unlink' in postexecargs and os.path.exists(
postexecargs[b'unlink']
):
Matt Harbison
server: refactor 'daemon_postexec' instructions into a dictionary
r37232 procutil.stdout.flush()
procutil.stderr.flush()
Matt Harbison
server: add an error feedback mechanism for when the daemon fails to launch...
r37229
Augie Fackler
formatting: blacken the codebase...
r43346 fd = os.open(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 postexecargs[b'unlink'], os.O_WRONLY | os.O_APPEND | os.O_BINARY
Augie Fackler
formatting: blacken the codebase...
r43346 )
Matt Harbison
server: refactor 'daemon_postexec' instructions into a dictionary
r37232 try:
Matt Harbison
server: minor code cleanup...
r37233 os.dup2(fd, procutil.stdout.fileno())
os.dup2(fd, procutil.stderr.fileno())
Matt Harbison
server: refactor 'daemon_postexec' instructions into a dictionary
r37232 finally:
os.close(fd)
Matt Harbison
server: add an error feedback mechanism for when the daemon fails to launch...
r37229
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 def writepid(pid):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts[b'pid_file']:
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 if appendpid:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 mode = b'ab'
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 mode = b'wb'
fp = open(opts[b'pid_file'], mode)
fp.write(b'%d\n' % pid)
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 fp.close()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts[b'daemon'] and not opts[b'daemon_postexec']:
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 # Signal child process startup with file removal
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 lockfd, lockpath = pycompat.mkstemp(prefix=b'hg-service-')
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 os.close(lockfd)
try:
if not runargs:
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 runargs = procutil.hgcmd() + pycompat.sysargv[1:]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 runargs.append(b'--daemon-postexec=unlink:%s' % lockpath)
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 # Don't pass --cwd to the child process, because we've already
# changed directory.
Gregory Szorc
global: use pycompat.xrange()...
r38806 for i in pycompat.xrange(1, len(runargs)):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if runargs[i].startswith(b'--cwd='):
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 del runargs[i]
break
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif runargs[i].startswith(b'--cwd'):
Augie Fackler
formatting: blacken the codebase...
r43346 del runargs[i : i + 2]
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 break
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 def condfn():
return not os.path.exists(lockpath)
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 pid = procutil.rundetached(runargs, condfn)
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 if pid < 0:
Matt Harbison
server: add an error feedback mechanism for when the daemon fails to launch...
r37229 # If the daemonized process managed to write out an error msg,
# report it.
if pycompat.iswindows and os.path.exists(lockpath):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 with open(lockpath, b'rb') as log:
Matt Harbison
server: add an error feedback mechanism for when the daemon fails to launch...
r37229 for line in log:
procutil.stderr.write(line)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'child process failed to start'))
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 writepid(pid)
finally:
Ryan McElroy
server: use tryunlink
r31548 util.tryunlink(lockpath)
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 if parentfn:
return parentfn(pid)
else:
return
if initfn:
initfn()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not opts[b'daemon']:
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 writepid(procutil.getpid())
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts[b'daemon_postexec']:
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 try:
os.setsid()
except AttributeError:
pass
Matt Harbison
server: add an error feedback mechanism for when the daemon fails to launch...
r37229
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'chdir' in postexecargs:
os.chdir(postexecargs[b'chdir'])
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 procutil.hidewindow()
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137 procutil.stdout.flush()
procutil.stderr.flush()
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506
nullfd = os.open(os.devnull, os.O_RDWR)
logfilefd = nullfd
if logfile:
Augie Fackler
formatting: blacken the codebase...
r43346 logfilefd = os.open(
logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND, 0o666
)
Matt Harbison
server: minor code cleanup...
r37233 os.dup2(nullfd, procutil.stdin.fileno())
os.dup2(logfilefd, procutil.stdout.fileno())
os.dup2(logfilefd, procutil.stderr.fileno())
Augie Fackler
formatting: blacken the codebase...
r43346 stdio = (
procutil.stdin.fileno(),
procutil.stdout.fileno(),
procutil.stderr.fileno(),
)
Matt Harbison
server: minor code cleanup...
r37233 if nullfd not in stdio:
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 os.close(nullfd)
Matt Harbison
server: minor code cleanup...
r37233 if logfile and logfilefd not in stdio:
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 os.close(logfilefd)
Matt Harbison
server: add an error feedback mechanism for when the daemon fails to launch...
r37229 # Only unlink after redirecting stdout/stderr, so Windows doesn't
# complain about a sharing violation.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'unlink' in postexecargs:
os.unlink(postexecargs[b'unlink'])
Matt Harbison
server: add an error feedback mechanism for when the daemon fails to launch...
r37229
Yuya Nishihara
server: move cmdutil.service() to new module (API)...
r30506 if runfn:
return runfn()
Yuya Nishihara
server: move service table and factory from commandserver...
r30507
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
server: move service table and factory from commandserver...
r30507 _cmdservicemap = {
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'chgunix': chgserver.chgunixservice,
b'pipe': commandserver.pipeservice,
b'unix': commandserver.unixforkingservice,
Yuya Nishihara
server: move service table and factory from commandserver...
r30507 }
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
server: add public function to select either cmdserver or hgweb
r30510 def _createcmdservice(ui, repo, opts):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 mode = opts[b'cmdserver']
Yuya Nishihara
server: move service table and factory from commandserver...
r30507 try:
Yuya Nishihara
commandserver: enable logging when server process started...
r40858 servicefn = _cmdservicemap[mode]
Yuya Nishihara
server: move service table and factory from commandserver...
r30507 except KeyError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'unknown mode %s') % mode)
Yuya Nishihara
commandserver: install logger to record server events through canonical API...
r40859 commandserver.setuplogging(ui, repo)
Yuya Nishihara
commandserver: enable logging when server process started...
r40858 return servicefn(ui, repo, opts)
Yuya Nishihara
server: move service factory from hgweb
r30509
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
server: add public function to select either cmdserver or hgweb
r30510 def _createhgwebservice(ui, repo, opts):
Yuya Nishihara
server: move service factory from hgweb
r30509 # this way we can check if something was given in the command-line
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts.get(b'port'):
opts[b'port'] = util.getport(opts.get(b'port'))
Yuya Nishihara
server: move service factory from hgweb
r30509
Martin von Zweigbergk
cleanup: use set literals...
r32291 alluis = {ui}
Yuya Nishihara
server: move service factory from hgweb
r30509 if repo:
baseui = repo.baseui
alluis.update([repo.baseui, repo.ui])
else:
baseui = ui
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 webconf = opts.get(b'web_conf') or opts.get(b'webdir_conf')
Yuya Nishihara
server: move service factory from hgweb
r30509 if webconf:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts.get(b'subrepos'):
raise error.Abort(_(b'--web-conf cannot be used with --subrepos'))
Matt Harbison
serve: add support for Mercurial subrepositories...
r32005
Yuya Nishihara
server: move service factory from hgweb
r30509 # load server settings (e.g. web.port) to "copied" ui, which allows
# hgwebdir to reload webconf cleanly
servui = ui.copy()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 servui.readconfig(webconf, sections=[b'web'])
Yuya Nishihara
server: move service factory from hgweb
r30509 alluis.add(servui)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif opts.get(b'subrepos'):
Matt Harbison
serve: add support for Mercurial subrepositories...
r32005 servui = ui
# If repo is None, hgweb.createapp() already raises a proper abort
# message as long as webconf is None.
if repo:
webconf = dict()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cmdutil.addwebdirpath(repo, b"", webconf)
Yuya Nishihara
server: move service factory from hgweb
r30509 else:
servui = ui
Augie Fackler
formatting: blacken the codebase...
r43346 optlist = (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"name templates style address port prefix ipv6"
b" accesslog errorlog certificate encoding"
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
server: move service factory from hgweb
r30509 for o in optlist.split():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 val = opts.get(o, b'')
if val in (None, b''): # should check against default options instead
Yuya Nishihara
server: move service factory from hgweb
r30509 continue
for u in alluis:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 u.setconfig(b"web", o, val, b'serve')
Yuya Nishihara
server: move service factory from hgweb
r30509
app = hgweb.createapp(baseui, repo, webconf)
return hgweb.httpservice(servui, app, opts)
Yuya Nishihara
server: add public function to select either cmdserver or hgweb
r30510
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
server: add public function to select either cmdserver or hgweb
r30510 def createservice(ui, repo, opts):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if opts[b"cmdserver"]:
Yuya Nishihara
server: add public function to select either cmdserver or hgweb
r30510 return _createcmdservice(ui, repo, opts)
else:
return _createhgwebservice(ui, repo, opts)