##// END OF EJS Templates
add HGRCPATH env var, list of places to look for hgrc files....
add HGRCPATH env var, list of places to look for hgrc files. if set, override default hgrc search path. if empty, only .hg/hgrc of current repo read. for each element, if directory, all entries in directory with end in ".rc" are added to path. else, element is added to path. big thing about this change is that user "~/.hgrc" and system hgrc not longer breaks tests. run-tests makes HGRCPATH empty now.

File last commit:

r1877:d314a89f default
r1951:696230e5 default
Show More
lock.py
108 lines | 3.1 KiB | text/x-python | PythonLexer
# lock.py - simple locking scheme for mercurial
#
# Copyright 2005 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
from demandload import *
demandload(globals(), 'errno os socket time util')
class LockException(Exception):
pass
class LockHeld(LockException):
pass
class LockUnavailable(LockException):
pass
class lock(object):
# lock is symlink on platforms that support it, file on others.
# symlink is used because create of directory entry and contents
# are atomic even over nfs.
# old-style lock: symlink to pid
# new-style lock: symlink to hostname:pid
def __init__(self, file, timeout=-1, releasefn=None):
self.f = file
self.held = 0
self.timeout = timeout
self.releasefn = releasefn
self.id = None
self.host = None
self.pid = None
self.lock()
def __del__(self):
self.release()
def lock(self):
timeout = self.timeout
while 1:
try:
self.trylock()
return 1
except LockHeld, inst:
if timeout != 0:
time.sleep(1)
if timeout > 0:
timeout -= 1
continue
raise inst
def trylock(self):
if self.id is None:
self.host = socket.gethostname()
self.pid = os.getpid()
self.id = '%s:%s' % (self.host, self.pid)
while not self.held:
try:
util.makelock(self.id, self.f)
self.held = 1
except (OSError, IOError), why:
if why.errno == errno.EEXIST:
locker = self.testlock()
if locker:
raise LockHeld(locker)
else:
raise LockUnavailable(why)
def testlock(self):
'''return id of locker if lock is valid, else None.'''
# if old-style lock, we cannot tell what machine locker is on.
# with new-style lock, if locker is on this machine, we can
# see if locker is alive. if locker is on this machine but
# not alive, we can safely break lock.
locker = util.readlock(self.f)
c = locker.find(':')
if c == -1:
return locker
host = locker[:c]
if host != self.host:
return locker
try:
pid = int(locker[c+1:])
except:
return locker
if util.testpid(pid):
return locker
# if locker dead, break lock. must do this with another lock
# held, or can race and break valid lock.
try:
l = lock(self.f + '.break')
l.trylock()
os.unlink(self.f)
l.release()
except (LockHeld, LockUnavailable):
return locker
def release(self):
if self.held:
self.held = 0
if self.releasefn:
self.releasefn()
try:
os.unlink(self.f)
except: pass