##// END OF EJS Templates
url: refactor util.drop_scheme() and hg.localpath() into url.localpath()...
url: refactor util.drop_scheme() and hg.localpath() into url.localpath() This replaces util.drop_scheme() with url.localpath(), using url.url for parsing instead of doing it on its own. The function is moved from util to url to avoid an import cycle. hg.localpath() is removed in favor of using url.localpath(). This provides more consistent behavior between "hg clone" and other commands. To preserve backwards compatibility, URLs like bundle://../foo still refer to ../foo, not /foo. If a URL contains a scheme, percent-encoded entities are decoded. When there's no scheme, all characters are left untouched. Comparison of old and new behaviors: URL drop_scheme() hg.localpath() url.localpath() === ============= ============== =============== file://foo/foo /foo foo/foo /foo file://localhost:80/foo /foo localhost:80/foo /foo file://localhost:/foo /foo localhost:/foo /foo file://localhost/foo /foo /foo /foo file:///foo /foo /foo /foo file://foo (empty string) foo / file:/foo /foo /foo /foo file:foo foo foo foo file:foo%23bar foo%23bar foo%23bar foo#bar foo%23bar foo%23bar foo%23bar foo%23bar /foo /foo /foo /foo Windows-related paths on Windows: URL drop_scheme() hg.localpath() url.localpath() === ============= ============== =============== file:///C:/foo C:/C:/foo /C:/foo C:/foo file:///D:/foo C:/D:/foo /D:/foo D:/foo file://C:/foo C:/foo C:/foo C:/foo file://D:/foo C:/foo D:/foo D:/foo file:////foo/bar //foo/bar //foo/bar //foo/bar //foo/bar //foo/bar //foo/bar //foo/bar \\foo\bar //foo/bar //foo/bar \\foo\bar Windows-related paths on other platforms: file:///C:/foo C:/C:/foo /C:/foo C:/foo file:///D:/foo C:/D:/foo /D:/foo D:/foo file://C:/foo C:/foo C:/foo C:/foo file://D:/foo C:/foo D:/foo D:/foo file:////foo/bar //foo/bar //foo/bar //foo/bar //foo/bar //foo/bar //foo/bar //foo/bar \\foo\bar //foo/bar //foo/bar \\foo\bar For more information about file:// URL handling, see: http://www-archive.mozilla.org/quality/networking/testing/filetests.html Related issues: - issue1153: File URIs aren't handled correctly in windows This patch should preserve the fix implemented in 2770d03ae49f. However, it goes a step further and "promotes" Windows-style drive letters from being interpreted as host names to being part of the path. - issue2154: Cannot escape '#' in Mercurial URLs (#1172 in THG) The fragment is still interpreted as a revision or a branch, even in paths to bundles. However, when file: is used, percent-encoded entities are decoded, so file:test%23bundle.hg can refer to test#bundle.hg ond isk.

File last commit:

r13281:95de08ff default
r13826:e574207e default
Show More
lock.py
137 lines | 4.2 KiB | text/x-python | PythonLexer
Greg Ward
localrepo: document the locking scheme a little better...
r9309 # lock.py - simple advisory locking scheme for mercurial
mpm@selenic.com
Simply repository locking...
r161 #
Vadim Gelfer
update copyrights.
r2859 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
mpm@selenic.com
Simply repository locking...
r161 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
mpm@selenic.com
Simply repository locking...
r161
Simon Heimberg
separate import lines from mercurial and general python modules
r8312 import util, error
import errno, os, socket, time
Ronny Pfannschmidt
add a deprecation warning for gc based lock releasing
r8113 import warnings
mpm@selenic.com
Simply repository locking...
r161
Eric Hopper
Convert all classes to new-style classes by deriving them from object.
r1559 class lock(object):
Greg Ward
localrepo: document the locking scheme a little better...
r9309 '''An advisory lock held by one process to control access to a set
of files. Non-cooperating processes or incorrectly written scripts
can ignore Mercurial's locking scheme and stomp all over the
repository, so don't do that.
Typically used via localrepository.lock() to lock the repository
store (.hg/store/) or localrepository.wlock() to lock everything
else under .hg/.'''
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 # 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
Bryan O'Sullivan
lock.py: cache hostname, but not pid, in case we fork
r4947 _host = None
Vadim Gelfer
fix backtrace printed when cannot get lock....
r2016 def __init__(self, file, timeout=-1, releasefn=None, desc=None):
mpm@selenic.com
Simply repository locking...
r161 self.f = file
self.held = 0
Benoit Boissinot
add a timeout when a lock is held (default 1024 sec)...
r1787 self.timeout = timeout
Benoit Boissinot
add a releasefn keyword to lock.lock...
r1530 self.releasefn = releasefn
Vadim Gelfer
fix backtrace printed when cannot get lock....
r2016 self.desc = desc
mpm@selenic.com
Simply repository locking...
r161 self.lock()
def __del__(self):
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 if self.held:
Ronny Pfannschmidt
add a deprecation warning for gc based lock releasing
r8113 warnings.warn("use lock.release instead of del lock",
category=DeprecationWarning,
stacklevel=2)
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 # ensure the lock will be removed
# even if recursive locking did occur
self.held = 1
mpm@selenic.com
Simply repository locking...
r161 self.release()
def lock(self):
Benoit Boissinot
add a timeout when a lock is held (default 1024 sec)...
r1787 timeout = self.timeout
mpm@selenic.com
Simply repository locking...
r161 while 1:
try:
self.trylock()
return 1
Matt Mackall
error: move lock errors...
r7640 except error.LockHeld, inst:
Benoit Boissinot
add a timeout when a lock is held (default 1024 sec)...
r1787 if timeout != 0:
mpm@selenic.com
Simply repository locking...
r161 time.sleep(1)
Benoit Boissinot
add a timeout when a lock is held (default 1024 sec)...
r1787 if timeout > 0:
timeout -= 1
mpm@selenic.com
Simply repository locking...
r161 continue
Matt Mackall
error: move lock errors...
r7640 raise error.LockHeld(errno.ETIMEDOUT, inst.filename, self.desc,
inst.locker)
mpm@selenic.com
Whitespace cleanups...
r515
mpm@selenic.com
Simply repository locking...
r161 def trylock(self):
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 if self.held:
self.held += 1
return
Bryan O'Sullivan
lock.py: cache hostname, but not pid, in case we fork
r4947 if lock._host is None:
lock._host = socket.gethostname()
Thomas Arendsen Hein
Use format string for lockname again (was changed by 3e25a6eb5c9a)
r4959 lockname = '%s:%s' % (lock._host, os.getpid())
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 while not self.held:
try:
Bryan O'Sullivan
lock.py: cache hostname, but not pid, in case we fork
r4947 util.makelock(lockname, self.f)
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 self.held = 1
except (OSError, IOError), why:
if why.errno == errno.EEXIST:
locker = self.testlock()
Thomas Arendsen Hein
Don't step into an endless loop when lock file is empty.
r3686 if locker is not None:
Matt Mackall
error: move lock errors...
r7640 raise error.LockHeld(errno.EAGAIN, self.f, self.desc,
locker)
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 else:
Matt Mackall
error: move lock errors...
r7640 raise error.LockUnavailable(why.errno, why.strerror,
why.filename, self.desc)
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877
def testlock(self):
Thomas Arendsen Hein
Don't step into an endless loop when lock file is empty.
r3686 """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.
The lock file is only deleted when None is returned.
"""
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 locker = util.readlock(self.f)
Benoit Boissinot
use __contains__, index or split instead of str.find...
r2579 try:
host, pid = locker.split(":", 1)
except ValueError:
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 return locker
Bryan O'Sullivan
lock.py: cache hostname, but not pid, in case we fork
r4947 if host != lock._host:
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 return locker
mpm@selenic.com
Simply repository locking...
r161 try:
Benoit Boissinot
use __contains__, index or split instead of str.find...
r2579 pid = int(pid)
Benoit Boissinot
lock: catch specific exceptions
r9685 except ValueError:
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 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:
Benoit Boissinot
lock: the correct way to do a trylock() is to use a timeout of 0
r9858 l = lock(self.f + '.break', timeout=0)
Adrian Buehlmann
lock: use util.unlink (issue2537)
r13281 util.unlink(self.f)
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 l.release()
Matt Mackall
error: move lock errors...
r7640 except error.LockError:
Vadim Gelfer
change lock format to let us detect and break stale locks....
r1877 return locker
mpm@selenic.com
Simply repository locking...
r161
def release(self):
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 if self.held > 1:
self.held -= 1
Benoit Boissinot
lock: use '==' instead of 'is' for integer equality ('is' may not work)
r9680 elif self.held == 1:
mpm@selenic.com
Simply repository locking...
r161 self.held = 0
Benoit Boissinot
add a releasefn keyword to lock.lock...
r1530 if self.releasefn:
self.releasefn()
mpm@selenic.com
Fix troubles with clone and exception handling...
r503 try:
Adrian Buehlmann
lock: use util.unlink (issue2537)
r13281 util.unlink(self.f)
Benoit Boissinot
lock: catch specific exceptions
r9685 except OSError:
pass
mpm@selenic.com
Simply repository locking...
r161
Ronny Pfannschmidt
made repo locks recursive and deprecate refcounting based lock releasing...
r8108 def release(*locks):
for lock in locks:
if lock is not None:
lock.release()