diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -10,7 +10,6 @@ from __future__ import absolute_import import errno import os import re -import sys import tempfile from .i18n import _ @@ -821,93 +820,6 @@ def copy(ui, repo, pats, opts, rename=Fa return errors != 0 -def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None, - runargs=None, appendpid=False): - '''Run a command as a service.''' - - def writepid(pid): - if opts['pid_file']: - if appendpid: - mode = 'a' - else: - mode = 'w' - fp = open(opts['pid_file'], mode) - fp.write(str(pid) + '\n') - fp.close() - - if opts['daemon'] and not opts['daemon_postexec']: - # Signal child process startup with file removal - lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-') - os.close(lockfd) - try: - if not runargs: - runargs = util.hgcmd() + sys.argv[1:] - runargs.append('--daemon-postexec=unlink:%s' % lockpath) - # Don't pass --cwd to the child process, because we've already - # changed directory. - for i in xrange(1, len(runargs)): - if runargs[i].startswith('--cwd='): - del runargs[i] - break - elif runargs[i].startswith('--cwd'): - del runargs[i:i + 2] - break - def condfn(): - return not os.path.exists(lockpath) - pid = util.rundetached(runargs, condfn) - if pid < 0: - raise error.Abort(_('child process failed to start')) - writepid(pid) - finally: - try: - os.unlink(lockpath) - except OSError as e: - if e.errno != errno.ENOENT: - raise - if parentfn: - return parentfn(pid) - else: - return - - if initfn: - initfn() - - if not opts['daemon']: - writepid(util.getpid()) - - if opts['daemon_postexec']: - try: - os.setsid() - except AttributeError: - pass - for inst in opts['daemon_postexec']: - if inst.startswith('unlink:'): - lockpath = inst[7:] - os.unlink(lockpath) - elif inst.startswith('chdir:'): - os.chdir(inst[6:]) - elif inst != 'none': - raise error.Abort(_('invalid value for --daemon-postexec: %s') - % inst) - util.hidewindow() - util.stdout.flush() - util.stderr.flush() - - nullfd = os.open(os.devnull, os.O_RDWR) - logfilefd = nullfd - if logfile: - logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND) - os.dup2(nullfd, 0) - os.dup2(logfilefd, 1) - os.dup2(logfilefd, 2) - if nullfd not in (0, 1, 2): - os.close(nullfd) - if logfile and logfilefd not in (0, 1, 2): - os.close(logfilefd) - - if runfn: - return runfn() - ## facility to let extension process additional data into an import patch # list of identifier to be executed in order extrapreimport = [] # run before commit diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -67,6 +67,7 @@ from . import ( revlog, revset, scmutil, + server, setdiscovery, sshserver, sslutil, @@ -6301,7 +6302,7 @@ def serve(ui, repo, **opts): service = commandserver.createservice(ui, repo, opts) else: service = hgweb.createservice(ui, repo, opts) - return cmdutil.service(opts, initfn=service.init, runfn=service.run) + return server.runservice(opts, initfn=service.init, runfn=service.run) @command('^status|st', [('A', 'all', None, _('show status of all files')), diff --git a/mercurial/server.py b/mercurial/server.py new file mode 100644 --- /dev/null +++ b/mercurial/server.py @@ -0,0 +1,107 @@ +# server.py - utility and factory of server +# +# Copyright 2005-2007 Matt Mackall +# +# 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 errno +import os +import sys +import tempfile + +from .i18n import _ + +from . import ( + error, + util, +) + +def runservice(opts, parentfn=None, initfn=None, runfn=None, logfile=None, + runargs=None, appendpid=False): + '''Run a command as a service.''' + + def writepid(pid): + if opts['pid_file']: + if appendpid: + mode = 'a' + else: + mode = 'w' + fp = open(opts['pid_file'], mode) + fp.write(str(pid) + '\n') + fp.close() + + if opts['daemon'] and not opts['daemon_postexec']: + # Signal child process startup with file removal + lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-') + os.close(lockfd) + try: + if not runargs: + runargs = util.hgcmd() + sys.argv[1:] + runargs.append('--daemon-postexec=unlink:%s' % lockpath) + # Don't pass --cwd to the child process, because we've already + # changed directory. + for i in xrange(1, len(runargs)): + if runargs[i].startswith('--cwd='): + del runargs[i] + break + elif runargs[i].startswith('--cwd'): + del runargs[i:i + 2] + break + def condfn(): + return not os.path.exists(lockpath) + pid = util.rundetached(runargs, condfn) + if pid < 0: + raise error.Abort(_('child process failed to start')) + writepid(pid) + finally: + try: + os.unlink(lockpath) + except OSError as e: + if e.errno != errno.ENOENT: + raise + if parentfn: + return parentfn(pid) + else: + return + + if initfn: + initfn() + + if not opts['daemon']: + writepid(util.getpid()) + + if opts['daemon_postexec']: + try: + os.setsid() + except AttributeError: + pass + for inst in opts['daemon_postexec']: + if inst.startswith('unlink:'): + lockpath = inst[7:] + os.unlink(lockpath) + elif inst.startswith('chdir:'): + os.chdir(inst[6:]) + elif inst != 'none': + raise error.Abort(_('invalid value for --daemon-postexec: %s') + % inst) + util.hidewindow() + util.stdout.flush() + util.stderr.flush() + + nullfd = os.open(os.devnull, os.O_RDWR) + logfilefd = nullfd + if logfile: + logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND) + os.dup2(nullfd, 0) + os.dup2(logfilefd, 1) + os.dup2(logfilefd, 2) + if nullfd not in (0, 1, 2): + os.close(nullfd) + if logfile and logfilefd not in (0, 1, 2): + os.close(logfilefd) + + if runfn: + return runfn() diff --git a/tests/dumbhttp.py b/tests/dumbhttp.py --- a/tests/dumbhttp.py +++ b/tests/dumbhttp.py @@ -11,7 +11,7 @@ import signal import sys from mercurial import ( - cmdutil, + server, util, ) @@ -51,5 +51,5 @@ if __name__ == '__main__': 'daemon': not options.foreground, 'daemon_postexec': options.daemon_postexec} service = simplehttpservice(options.host, options.port) - cmdutil.service(opts, initfn=service.init, runfn=service.run, - runargs=[sys.executable, __file__] + sys.argv[1:]) + server.runservice(opts, initfn=service.init, runfn=service.run, + runargs=[sys.executable, __file__] + sys.argv[1:]) diff --git a/tests/dummysmtpd.py b/tests/dummysmtpd.py --- a/tests/dummysmtpd.py +++ b/tests/dummysmtpd.py @@ -11,7 +11,7 @@ import ssl import sys from mercurial import ( - cmdutil, + server, sslutil, ui as uimod, ) @@ -75,8 +75,8 @@ def main(): dummysmtpsecureserver(addr, opts.certificate) log('listening at %s:%d\n' % addr) - cmdutil.service(vars(opts), initfn=init, runfn=run, - runargs=[sys.executable, __file__] + sys.argv[1:]) + server.runservice(vars(opts), initfn=init, runfn=run, + runargs=[sys.executable, __file__] + sys.argv[1:]) if __name__ == '__main__': main()