mercurial/cmdutil.py
changeset 30506 d9d8d78e6bc9
parent 30497 002fa4d79466
child 30519 20a42325fdef
equal deleted inserted replaced
30505:158b41842fd2 30506:d9d8d78e6bc9
     8 from __future__ import absolute_import
     8 from __future__ import absolute_import
     9 
     9 
    10 import errno
    10 import errno
    11 import os
    11 import os
    12 import re
    12 import re
    13 import sys
       
    14 import tempfile
    13 import tempfile
    15 
    14 
    16 from .i18n import _
    15 from .i18n import _
    17 from .node import (
    16 from .node import (
    18     bin,
    17     bin,
   818 
   817 
   819     if errors:
   818     if errors:
   820         ui.warn(_('(consider using --after)\n'))
   819         ui.warn(_('(consider using --after)\n'))
   821 
   820 
   822     return errors != 0
   821     return errors != 0
   823 
       
   824 def service(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
       
   825     runargs=None, appendpid=False):
       
   826     '''Run a command as a service.'''
       
   827 
       
   828     def writepid(pid):
       
   829         if opts['pid_file']:
       
   830             if appendpid:
       
   831                 mode = 'a'
       
   832             else:
       
   833                 mode = 'w'
       
   834             fp = open(opts['pid_file'], mode)
       
   835             fp.write(str(pid) + '\n')
       
   836             fp.close()
       
   837 
       
   838     if opts['daemon'] and not opts['daemon_postexec']:
       
   839         # Signal child process startup with file removal
       
   840         lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
       
   841         os.close(lockfd)
       
   842         try:
       
   843             if not runargs:
       
   844                 runargs = util.hgcmd() + sys.argv[1:]
       
   845             runargs.append('--daemon-postexec=unlink:%s' % lockpath)
       
   846             # Don't pass --cwd to the child process, because we've already
       
   847             # changed directory.
       
   848             for i in xrange(1, len(runargs)):
       
   849                 if runargs[i].startswith('--cwd='):
       
   850                     del runargs[i]
       
   851                     break
       
   852                 elif runargs[i].startswith('--cwd'):
       
   853                     del runargs[i:i + 2]
       
   854                     break
       
   855             def condfn():
       
   856                 return not os.path.exists(lockpath)
       
   857             pid = util.rundetached(runargs, condfn)
       
   858             if pid < 0:
       
   859                 raise error.Abort(_('child process failed to start'))
       
   860             writepid(pid)
       
   861         finally:
       
   862             try:
       
   863                 os.unlink(lockpath)
       
   864             except OSError as e:
       
   865                 if e.errno != errno.ENOENT:
       
   866                     raise
       
   867         if parentfn:
       
   868             return parentfn(pid)
       
   869         else:
       
   870             return
       
   871 
       
   872     if initfn:
       
   873         initfn()
       
   874 
       
   875     if not opts['daemon']:
       
   876         writepid(util.getpid())
       
   877 
       
   878     if opts['daemon_postexec']:
       
   879         try:
       
   880             os.setsid()
       
   881         except AttributeError:
       
   882             pass
       
   883         for inst in opts['daemon_postexec']:
       
   884             if inst.startswith('unlink:'):
       
   885                 lockpath = inst[7:]
       
   886                 os.unlink(lockpath)
       
   887             elif inst.startswith('chdir:'):
       
   888                 os.chdir(inst[6:])
       
   889             elif inst != 'none':
       
   890                 raise error.Abort(_('invalid value for --daemon-postexec: %s')
       
   891                                   % inst)
       
   892         util.hidewindow()
       
   893         util.stdout.flush()
       
   894         util.stderr.flush()
       
   895 
       
   896         nullfd = os.open(os.devnull, os.O_RDWR)
       
   897         logfilefd = nullfd
       
   898         if logfile:
       
   899             logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
       
   900         os.dup2(nullfd, 0)
       
   901         os.dup2(logfilefd, 1)
       
   902         os.dup2(logfilefd, 2)
       
   903         if nullfd not in (0, 1, 2):
       
   904             os.close(nullfd)
       
   905         if logfile and logfilefd not in (0, 1, 2):
       
   906             os.close(logfilefd)
       
   907 
       
   908     if runfn:
       
   909         return runfn()
       
   910 
   822 
   911 ## facility to let extension process additional data into an import patch
   823 ## facility to let extension process additional data into an import patch
   912 # list of identifier to be executed in order
   824 # list of identifier to be executed in order
   913 extrapreimport = []  # run before commit
   825 extrapreimport = []  # run before commit
   914 extrapostimport = [] # run after commit
   826 extrapostimport = [] # run after commit