##// END OF EJS Templates
Make makelock and readlock work on filesystems without symlink support....
Thomas Arendsen Hein -
r704:5ca319a6 default
parent child Browse files
Show More
@@ -1,49 +1,49 b''
1 # lock.py - simple locking scheme for mercurial
1 # lock.py - simple locking scheme for mercurial
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import os, time
8 import os, time
9 import util
9 import util
10
10
11 class LockHeld(Exception):
11 class LockHeld(Exception):
12 pass
12 pass
13
13
14 class lock:
14 class lock:
15 def __init__(self, file, wait = 1):
15 def __init__(self, file, wait = 1):
16 self.f = file
16 self.f = file
17 self.held = 0
17 self.held = 0
18 self.wait = wait
18 self.wait = wait
19 self.lock()
19 self.lock()
20
20
21 def __del__(self):
21 def __del__(self):
22 self.release()
22 self.release()
23
23
24 def lock(self):
24 def lock(self):
25 while 1:
25 while 1:
26 try:
26 try:
27 self.trylock()
27 self.trylock()
28 return 1
28 return 1
29 except LockHeld, inst:
29 except LockHeld, inst:
30 if self.wait:
30 if self.wait:
31 time.sleep(1)
31 time.sleep(1)
32 continue
32 continue
33 raise inst
33 raise inst
34
34
35 def trylock(self):
35 def trylock(self):
36 pid = os.getpid()
36 pid = os.getpid()
37 try:
37 try:
38 util.makelock(str(pid), self.f)
38 util.makelock(str(pid), self.f)
39 self.held = 1
39 self.held = 1
40 except:
40 except (OSError, IOError):
41 raise LockHeld(util.readlock(self.f))
41 raise LockHeld(util.readlock(self.f))
42
42
43 def release(self):
43 def release(self):
44 if self.held:
44 if self.held:
45 self.held = 0
45 self.held = 0
46 try:
46 try:
47 os.unlink(self.f)
47 os.unlink(self.f)
48 except: pass
48 except: pass
49
49
@@ -1,111 +1,126 b''
1 # util.py - utility functions and platform specfic implementations
1 # util.py - utility functions and platform specfic implementations
2 #
2 #
3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
3 # Copyright 2005 K. Thananchayan <thananck@yahoo.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import os
8 import os, errno
9
9
10 def unique(g):
10 def unique(g):
11 seen = {}
11 seen = {}
12 for f in g:
12 for f in g:
13 if f not in seen:
13 if f not in seen:
14 seen[f] = 1
14 seen[f] = 1
15 yield f
15 yield f
16
16
17 class CommandError(Exception): pass
17 class CommandError(Exception): pass
18
18
19 def explain_exit(code):
19 def explain_exit(code):
20 """return a 2-tuple (desc, code) describing a process's status"""
20 """return a 2-tuple (desc, code) describing a process's status"""
21 if os.WIFEXITED(code):
21 if os.WIFEXITED(code):
22 val = os.WEXITSTATUS(code)
22 val = os.WEXITSTATUS(code)
23 return "exited with status %d" % val, val
23 return "exited with status %d" % val, val
24 elif os.WIFSIGNALED(code):
24 elif os.WIFSIGNALED(code):
25 val = os.WTERMSIG(code)
25 val = os.WTERMSIG(code)
26 return "killed by signal %d" % val, val
26 return "killed by signal %d" % val, val
27 elif os.WIFSTOPPED(code):
27 elif os.WIFSTOPPED(code):
28 val = os.WSTOPSIG(code)
28 val = os.WSTOPSIG(code)
29 return "stopped by signal %d" % val, val
29 return "stopped by signal %d" % val, val
30 raise ValueError("invalid exit code")
30 raise ValueError("invalid exit code")
31
31
32 def system(cmd, errprefix=None):
32 def system(cmd, errprefix=None):
33 """execute a shell command that must succeed"""
33 """execute a shell command that must succeed"""
34 rc = os.system(cmd)
34 rc = os.system(cmd)
35 if rc:
35 if rc:
36 errmsg = "%s %s" % (os.path.basename(cmd.split(None, 1)[0]),
36 errmsg = "%s %s" % (os.path.basename(cmd.split(None, 1)[0]),
37 explain_exit(rc)[0])
37 explain_exit(rc)[0])
38 if errprefix:
38 if errprefix:
39 errmsg = "%s: %s" % (errprefix, errmsg)
39 errmsg = "%s: %s" % (errprefix, errmsg)
40 raise CommandError(errmsg)
40 raise CommandError(errmsg)
41
41
42 def rename(src, dst):
42 def rename(src, dst):
43 try:
43 try:
44 os.rename(src, dst)
44 os.rename(src, dst)
45 except:
45 except:
46 os.unlink(dst)
46 os.unlink(dst)
47 os.rename(src, dst)
47 os.rename(src, dst)
48
48
49 def copytree(src, dst, copyfile):
49 def copytree(src, dst, copyfile):
50 """Copy a directory tree, files are copied using 'copyfile'."""
50 """Copy a directory tree, files are copied using 'copyfile'."""
51 names = os.listdir(src)
51 names = os.listdir(src)
52 os.mkdir(dst)
52 os.mkdir(dst)
53
53
54 for name in names:
54 for name in names:
55 srcname = os.path.join(src, name)
55 srcname = os.path.join(src, name)
56 dstname = os.path.join(dst, name)
56 dstname = os.path.join(dst, name)
57 if os.path.isdir(srcname):
57 if os.path.isdir(srcname):
58 copytree(srcname, dstname, copyfile)
58 copytree(srcname, dstname, copyfile)
59 elif os.path.isfile(srcname):
59 elif os.path.isfile(srcname):
60 copyfile(srcname, dstname)
60 copyfile(srcname, dstname)
61 else:
61 else:
62 raise IOError("Not a regular file: %r" % srcname)
62 raise IOError("Not a regular file: %r" % srcname)
63
63
64 def _makelock_file(info, pathname):
65 ld = os.open(pathname, os.O_CREAT | os.O_WRONLY | os.O_EXCL)
66 os.write(ld, info)
67 os.close(ld)
68
69 def _readlock_file(pathname):
70 return file(pathname).read()
71
64 # Platfor specific varients
72 # Platfor specific varients
65 if os.name == 'nt':
73 if os.name == 'nt':
66 nulldev = 'NUL:'
74 nulldev = 'NUL:'
67
75
68 def is_exec(f, last):
76 def is_exec(f, last):
69 return last
77 return last
70
78
71 def set_exec(f, mode):
79 def set_exec(f, mode):
72 pass
80 pass
73
81
74 def pconvert(path):
82 def pconvert(path):
75 return path.replace("\\", "/")
83 return path.replace("\\", "/")
76
84
77 def makelock(info, pathname):
85 makelock = _makelock_file
78 ld = os.open(pathname, os.O_CREAT | os.O_WRONLY | os.O_EXCL)
86 readlock = _readlock_file
79 os.write(ld, info)
80 os.close(ld)
81
82 def readlock(pathname):
83 return file(pathname).read()
84
87
85 else:
88 else:
86 nulldev = '/dev/null'
89 nulldev = '/dev/null'
87
90
88 def is_exec(f, last):
91 def is_exec(f, last):
89 return (os.stat(f).st_mode & 0100 != 0)
92 return (os.stat(f).st_mode & 0100 != 0)
90
93
91 def set_exec(f, mode):
94 def set_exec(f, mode):
92 s = os.stat(f).st_mode
95 s = os.stat(f).st_mode
93 if (s & 0100 != 0) == mode:
96 if (s & 0100 != 0) == mode:
94 return
97 return
95 if mode:
98 if mode:
96 # Turn on +x for every +r bit when making a file executable
99 # Turn on +x for every +r bit when making a file executable
97 # and obey umask.
100 # and obey umask.
98 umask = os.umask(0)
101 umask = os.umask(0)
99 os.umask(umask)
102 os.umask(umask)
100 os.chmod(f, s | (s & 0444) >> 2 & ~umask)
103 os.chmod(f, s | (s & 0444) >> 2 & ~umask)
101 else:
104 else:
102 os.chmod(f, s & 0666)
105 os.chmod(f, s & 0666)
103
106
104 def pconvert(path):
107 def pconvert(path):
105 return path
108 return path
106
109
107 def makelock(info, pathname):
110 def makelock(info, pathname):
108 os.symlink(info, pathname)
111 try:
112 os.symlink(info, pathname)
113 except OSError, why:
114 if why.errno == errno.EEXIST:
115 raise
116 else:
117 _makelock_file(info, pathname)
109
118
110 def readlock(pathname):
119 def readlock(pathname):
111 return os.readlink(pathname)
120 try:
121 return os.readlink(pathname)
122 except OSError, why:
123 if why.errno == errno.EINVAL:
124 return _readlock_file(pathname)
125 else:
126 raise
General Comments 0
You need to be logged in to leave comments. Login now