##// END OF EJS Templates
posix: move a global fcntl import to keep it from breaking jython...
Ronny Pfannschmidt -
r10757:ab378245 default
parent child Browse files
Show More
@@ -1,266 +1,267
1 # posix.py - Posix utility function implementations for Mercurial
1 # posix.py - Posix utility function implementations for Mercurial
2 #
2 #
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from i18n import _
8 from i18n import _
9 import osutil
9 import osutil
10 import os, sys, errno, stat, getpass, pwd, grp, fcntl
10 import os, sys, errno, stat, getpass, pwd, grp
11
11
12 posixfile = open
12 posixfile = open
13 nulldev = '/dev/null'
13 nulldev = '/dev/null'
14 normpath = os.path.normpath
14 normpath = os.path.normpath
15 samestat = os.path.samestat
15 samestat = os.path.samestat
16 rename = os.rename
16 rename = os.rename
17 expandglobs = False
17 expandglobs = False
18
18
19 umask = os.umask(0)
19 umask = os.umask(0)
20 os.umask(umask)
20 os.umask(umask)
21
21
22 def openhardlinks():
22 def openhardlinks():
23 '''return true if it is safe to hold open file handles to hardlinks'''
23 '''return true if it is safe to hold open file handles to hardlinks'''
24 return True
24 return True
25
25
26 def rcfiles(path):
26 def rcfiles(path):
27 rcs = [os.path.join(path, 'hgrc')]
27 rcs = [os.path.join(path, 'hgrc')]
28 rcdir = os.path.join(path, 'hgrc.d')
28 rcdir = os.path.join(path, 'hgrc.d')
29 try:
29 try:
30 rcs.extend([os.path.join(rcdir, f)
30 rcs.extend([os.path.join(rcdir, f)
31 for f, kind in osutil.listdir(rcdir)
31 for f, kind in osutil.listdir(rcdir)
32 if f.endswith(".rc")])
32 if f.endswith(".rc")])
33 except OSError:
33 except OSError:
34 pass
34 pass
35 return rcs
35 return rcs
36
36
37 def system_rcpath():
37 def system_rcpath():
38 path = []
38 path = []
39 # old mod_python does not set sys.argv
39 # old mod_python does not set sys.argv
40 if len(getattr(sys, 'argv', [])) > 0:
40 if len(getattr(sys, 'argv', [])) > 0:
41 path.extend(rcfiles(os.path.dirname(sys.argv[0]) +
41 path.extend(rcfiles(os.path.dirname(sys.argv[0]) +
42 '/../etc/mercurial'))
42 '/../etc/mercurial'))
43 path.extend(rcfiles('/etc/mercurial'))
43 path.extend(rcfiles('/etc/mercurial'))
44 return path
44 return path
45
45
46 def user_rcpath():
46 def user_rcpath():
47 return [os.path.expanduser('~/.hgrc')]
47 return [os.path.expanduser('~/.hgrc')]
48
48
49 def parse_patch_output(output_line):
49 def parse_patch_output(output_line):
50 """parses the output produced by patch and returns the filename"""
50 """parses the output produced by patch and returns the filename"""
51 pf = output_line[14:]
51 pf = output_line[14:]
52 if os.sys.platform == 'OpenVMS':
52 if os.sys.platform == 'OpenVMS':
53 if pf[0] == '`':
53 if pf[0] == '`':
54 pf = pf[1:-1] # Remove the quotes
54 pf = pf[1:-1] # Remove the quotes
55 else:
55 else:
56 if pf.startswith("'") and pf.endswith("'") and " " in pf:
56 if pf.startswith("'") and pf.endswith("'") and " " in pf:
57 pf = pf[1:-1] # Remove the quotes
57 pf = pf[1:-1] # Remove the quotes
58 return pf
58 return pf
59
59
60 def sshargs(sshcmd, host, user, port):
60 def sshargs(sshcmd, host, user, port):
61 '''Build argument list for ssh'''
61 '''Build argument list for ssh'''
62 args = user and ("%s@%s" % (user, host)) or host
62 args = user and ("%s@%s" % (user, host)) or host
63 return port and ("%s -p %s" % (args, port)) or args
63 return port and ("%s -p %s" % (args, port)) or args
64
64
65 def is_exec(f):
65 def is_exec(f):
66 """check whether a file is executable"""
66 """check whether a file is executable"""
67 return (os.lstat(f).st_mode & 0100 != 0)
67 return (os.lstat(f).st_mode & 0100 != 0)
68
68
69 def set_flags(f, l, x):
69 def set_flags(f, l, x):
70 s = os.lstat(f).st_mode
70 s = os.lstat(f).st_mode
71 if l:
71 if l:
72 if not stat.S_ISLNK(s):
72 if not stat.S_ISLNK(s):
73 # switch file to link
73 # switch file to link
74 data = open(f).read()
74 data = open(f).read()
75 os.unlink(f)
75 os.unlink(f)
76 try:
76 try:
77 os.symlink(data, f)
77 os.symlink(data, f)
78 except:
78 except:
79 # failed to make a link, rewrite file
79 # failed to make a link, rewrite file
80 open(f, "w").write(data)
80 open(f, "w").write(data)
81 # no chmod needed at this point
81 # no chmod needed at this point
82 return
82 return
83 if stat.S_ISLNK(s):
83 if stat.S_ISLNK(s):
84 # switch link to file
84 # switch link to file
85 data = os.readlink(f)
85 data = os.readlink(f)
86 os.unlink(f)
86 os.unlink(f)
87 open(f, "w").write(data)
87 open(f, "w").write(data)
88 s = 0666 & ~umask # avoid restatting for chmod
88 s = 0666 & ~umask # avoid restatting for chmod
89
89
90 sx = s & 0100
90 sx = s & 0100
91 if x and not sx:
91 if x and not sx:
92 # Turn on +x for every +r bit when making a file executable
92 # Turn on +x for every +r bit when making a file executable
93 # and obey umask.
93 # and obey umask.
94 os.chmod(f, s | (s & 0444) >> 2 & ~umask)
94 os.chmod(f, s | (s & 0444) >> 2 & ~umask)
95 elif not x and sx:
95 elif not x and sx:
96 # Turn off all +x bits
96 # Turn off all +x bits
97 os.chmod(f, s & 0666)
97 os.chmod(f, s & 0666)
98
98
99 def set_binary(fd):
99 def set_binary(fd):
100 pass
100 pass
101
101
102 def pconvert(path):
102 def pconvert(path):
103 return path
103 return path
104
104
105 def localpath(path):
105 def localpath(path):
106 return path
106 return path
107
107
108 def samefile(fpath1, fpath2):
108 def samefile(fpath1, fpath2):
109 """Returns whether path1 and path2 refer to the same file. This is only
109 """Returns whether path1 and path2 refer to the same file. This is only
110 guaranteed to work for files, not directories."""
110 guaranteed to work for files, not directories."""
111 return os.path.samefile(fpath1, fpath2)
111 return os.path.samefile(fpath1, fpath2)
112
112
113 def samedevice(fpath1, fpath2):
113 def samedevice(fpath1, fpath2):
114 """Returns whether fpath1 and fpath2 are on the same device. This is only
114 """Returns whether fpath1 and fpath2 are on the same device. This is only
115 guaranteed to work for files, not directories."""
115 guaranteed to work for files, not directories."""
116 st1 = os.lstat(fpath1)
116 st1 = os.lstat(fpath1)
117 st2 = os.lstat(fpath2)
117 st2 = os.lstat(fpath2)
118 return st1.st_dev == st2.st_dev
118 return st1.st_dev == st2.st_dev
119
119
120 if sys.platform == 'darwin':
120 if sys.platform == 'darwin':
121 import fcntl # only needed on darwin, missing on jython
121 def realpath(path):
122 def realpath(path):
122 '''
123 '''
123 Returns the true, canonical file system path equivalent to the given
124 Returns the true, canonical file system path equivalent to the given
124 path.
125 path.
125
126
126 Equivalent means, in this case, resulting in the same, unique
127 Equivalent means, in this case, resulting in the same, unique
127 file system link to the path. Every file system entry, whether a file,
128 file system link to the path. Every file system entry, whether a file,
128 directory, hard link or symbolic link or special, will have a single
129 directory, hard link or symbolic link or special, will have a single
129 path preferred by the system, but may allow multiple, differing path
130 path preferred by the system, but may allow multiple, differing path
130 lookups to point to it.
131 lookups to point to it.
131
132
132 Most regular UNIX file systems only allow a file system entry to be
133 Most regular UNIX file systems only allow a file system entry to be
133 looked up by its distinct path. Obviously, this does not apply to case
134 looked up by its distinct path. Obviously, this does not apply to case
134 insensitive file systems, whether case preserving or not. The most
135 insensitive file systems, whether case preserving or not. The most
135 complex issue to deal with is file systems transparently reencoding the
136 complex issue to deal with is file systems transparently reencoding the
136 path, such as the non-standard Unicode normalisation required for HFS+
137 path, such as the non-standard Unicode normalisation required for HFS+
137 and HFSX.
138 and HFSX.
138 '''
139 '''
139 # Constants copied from /usr/include/sys/fcntl.h
140 # Constants copied from /usr/include/sys/fcntl.h
140 F_GETPATH = 50
141 F_GETPATH = 50
141 O_SYMLINK = 0x200000
142 O_SYMLINK = 0x200000
142
143
143 try:
144 try:
144 fd = os.open(path, O_SYMLINK)
145 fd = os.open(path, O_SYMLINK)
145 except OSError, err:
146 except OSError, err:
146 if err.errno is errno.ENOENT:
147 if err.errno is errno.ENOENT:
147 return path
148 return path
148 raise
149 raise
149
150
150 try:
151 try:
151 return fcntl.fcntl(fd, F_GETPATH, '\0' * 1024).rstrip('\0')
152 return fcntl.fcntl(fd, F_GETPATH, '\0' * 1024).rstrip('\0')
152 finally:
153 finally:
153 os.close(fd)
154 os.close(fd)
154 else:
155 else:
155 # Fallback to the likely inadequate Python builtin function.
156 # Fallback to the likely inadequate Python builtin function.
156 realpath = os.path.realpath
157 realpath = os.path.realpath
157
158
158 def shellquote(s):
159 def shellquote(s):
159 if os.sys.platform == 'OpenVMS':
160 if os.sys.platform == 'OpenVMS':
160 return '"%s"' % s
161 return '"%s"' % s
161 else:
162 else:
162 return "'%s'" % s.replace("'", "'\\''")
163 return "'%s'" % s.replace("'", "'\\''")
163
164
164 def quotecommand(cmd):
165 def quotecommand(cmd):
165 return cmd
166 return cmd
166
167
167 def popen(command, mode='r'):
168 def popen(command, mode='r'):
168 return os.popen(command, mode)
169 return os.popen(command, mode)
169
170
170 def testpid(pid):
171 def testpid(pid):
171 '''return False if pid dead, True if running or not sure'''
172 '''return False if pid dead, True if running or not sure'''
172 if os.sys.platform == 'OpenVMS':
173 if os.sys.platform == 'OpenVMS':
173 return True
174 return True
174 try:
175 try:
175 os.kill(pid, 0)
176 os.kill(pid, 0)
176 return True
177 return True
177 except OSError, inst:
178 except OSError, inst:
178 return inst.errno != errno.ESRCH
179 return inst.errno != errno.ESRCH
179
180
180 def explain_exit(code):
181 def explain_exit(code):
181 """return a 2-tuple (desc, code) describing a subprocess status
182 """return a 2-tuple (desc, code) describing a subprocess status
182 (codes from kill are negative - not os.system/wait encoding)"""
183 (codes from kill are negative - not os.system/wait encoding)"""
183 if code >= 0:
184 if code >= 0:
184 return _("exited with status %d") % code, code
185 return _("exited with status %d") % code, code
185 return _("killed by signal %d") % -code, -code
186 return _("killed by signal %d") % -code, -code
186
187
187 def isowner(st):
188 def isowner(st):
188 """Return True if the stat object st is from the current user."""
189 """Return True if the stat object st is from the current user."""
189 return st.st_uid == os.getuid()
190 return st.st_uid == os.getuid()
190
191
191 def find_exe(command):
192 def find_exe(command):
192 '''Find executable for command searching like which does.
193 '''Find executable for command searching like which does.
193 If command is a basename then PATH is searched for command.
194 If command is a basename then PATH is searched for command.
194 PATH isn't searched if command is an absolute or relative path.
195 PATH isn't searched if command is an absolute or relative path.
195 If command isn't found None is returned.'''
196 If command isn't found None is returned.'''
196 if sys.platform == 'OpenVMS':
197 if sys.platform == 'OpenVMS':
197 return command
198 return command
198
199
199 def findexisting(executable):
200 def findexisting(executable):
200 'Will return executable if existing file'
201 'Will return executable if existing file'
201 if os.path.exists(executable):
202 if os.path.exists(executable):
202 return executable
203 return executable
203 return None
204 return None
204
205
205 if os.sep in command:
206 if os.sep in command:
206 return findexisting(command)
207 return findexisting(command)
207
208
208 for path in os.environ.get('PATH', '').split(os.pathsep):
209 for path in os.environ.get('PATH', '').split(os.pathsep):
209 executable = findexisting(os.path.join(path, command))
210 executable = findexisting(os.path.join(path, command))
210 if executable is not None:
211 if executable is not None:
211 return executable
212 return executable
212 return None
213 return None
213
214
214 def set_signal_handler():
215 def set_signal_handler():
215 pass
216 pass
216
217
217 def statfiles(files):
218 def statfiles(files):
218 'Stat each file in files and yield stat or None if file does not exist.'
219 'Stat each file in files and yield stat or None if file does not exist.'
219 lstat = os.lstat
220 lstat = os.lstat
220 for nf in files:
221 for nf in files:
221 try:
222 try:
222 st = lstat(nf)
223 st = lstat(nf)
223 except OSError, err:
224 except OSError, err:
224 if err.errno not in (errno.ENOENT, errno.ENOTDIR):
225 if err.errno not in (errno.ENOENT, errno.ENOTDIR):
225 raise
226 raise
226 st = None
227 st = None
227 yield st
228 yield st
228
229
229 def getuser():
230 def getuser():
230 '''return name of current user'''
231 '''return name of current user'''
231 return getpass.getuser()
232 return getpass.getuser()
232
233
233 def expand_glob(pats):
234 def expand_glob(pats):
234 '''On Windows, expand the implicit globs in a list of patterns'''
235 '''On Windows, expand the implicit globs in a list of patterns'''
235 return list(pats)
236 return list(pats)
236
237
237 def username(uid=None):
238 def username(uid=None):
238 """Return the name of the user with the given uid.
239 """Return the name of the user with the given uid.
239
240
240 If uid is None, return the name of the current user."""
241 If uid is None, return the name of the current user."""
241
242
242 if uid is None:
243 if uid is None:
243 uid = os.getuid()
244 uid = os.getuid()
244 try:
245 try:
245 return pwd.getpwuid(uid)[0]
246 return pwd.getpwuid(uid)[0]
246 except KeyError:
247 except KeyError:
247 return str(uid)
248 return str(uid)
248
249
249 def groupname(gid=None):
250 def groupname(gid=None):
250 """Return the name of the group with the given gid.
251 """Return the name of the group with the given gid.
251
252
252 If gid is None, return the name of the current group."""
253 If gid is None, return the name of the current group."""
253
254
254 if gid is None:
255 if gid is None:
255 gid = os.getgid()
256 gid = os.getgid()
256 try:
257 try:
257 return grp.getgrgid(gid)[0]
258 return grp.getgrgid(gid)[0]
258 except KeyError:
259 except KeyError:
259 return str(gid)
260 return str(gid)
260
261
261 def spawndetached(args):
262 def spawndetached(args):
262 return os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
263 return os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
263 args[0], args)
264 args[0], args)
264
265
265 def gethgcmd():
266 def gethgcmd():
266 return sys.argv[:1]
267 return sys.argv[:1]
General Comments 0
You need to be logged in to leave comments. Login now