comparison mercurial/posix.py @ 7890:e710f0f592b2

util: split out posix, windows, and win32 modules
author Matt Mackall <mpm@selenic.com>
date Thu, 26 Mar 2009 13:54:44 -0500
parents
children c0dc1f15b30d
comparison
equal deleted inserted replaced
7889:5ac1a72e5b74 7890:e710f0f592b2
1 """
2 posix.py - Posix utility function implementations for Mercurial
3
4 Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
5
6 This software may be used and distributed according to the terms of
7 the GNU General Public License version 2, incorporated herein by
8 reference.
9 """
10
11 from i18n import _
12 import os, sys, osutil, errno, stat, getpass
13
14 posixfile = file
15 nulldev = '/dev/null'
16 normpath = os.path.normpath
17 samestat = os.path.samestat
18
19 umask = os.umask(0)
20 os.umask(umask)
21
22 def openhardlinks():
23 '''return true if it is safe to hold open file handles to hardlinks'''
24 return True
25
26 def rcfiles(path):
27 rcs = [os.path.join(path, 'hgrc')]
28 rcdir = os.path.join(path, 'hgrc.d')
29 try:
30 rcs.extend([os.path.join(rcdir, f)
31 for f, kind in osutil.listdir(rcdir)
32 if f.endswith(".rc")])
33 except OSError:
34 pass
35 return rcs
36
37 def system_rcpath():
38 path = []
39 # old mod_python does not set sys.argv
40 if len(getattr(sys, 'argv', [])) > 0:
41 path.extend(rcfiles(os.path.dirname(sys.argv[0]) +
42 '/../etc/mercurial'))
43 path.extend(rcfiles('/etc/mercurial'))
44 return path
45
46 def user_rcpath():
47 return [os.path.expanduser('~/.hgrc')]
48
49 def parse_patch_output(output_line):
50 """parses the output produced by patch and returns the file name"""
51 pf = output_line[14:]
52 if os.sys.platform == 'OpenVMS':
53 if pf[0] == '`':
54 pf = pf[1:-1] # Remove the quotes
55 else:
56 if pf.startswith("'") and pf.endswith("'") and " " in pf:
57 pf = pf[1:-1] # Remove the quotes
58 return pf
59
60 def sshargs(sshcmd, host, user, port):
61 '''Build argument list for ssh'''
62 args = user and ("%s@%s" % (user, host)) or host
63 return port and ("%s -p %s" % (args, port)) or args
64
65 def is_exec(f):
66 """check whether a file is executable"""
67 return (os.lstat(f).st_mode & 0100 != 0)
68
69 def set_flags(f, l, x):
70 s = os.lstat(f).st_mode
71 if l:
72 if not stat.S_ISLNK(s):
73 # switch file to link
74 data = file(f).read()
75 os.unlink(f)
76 try:
77 os.symlink(data, f)
78 except:
79 # failed to make a link, rewrite file
80 file(f, "w").write(data)
81 # no chmod needed at this point
82 return
83 if stat.S_ISLNK(s):
84 # switch link to file
85 data = os.readlink(f)
86 os.unlink(f)
87 file(f, "w").write(data)
88 s = 0666 & ~umask # avoid restatting for chmod
89
90 sx = s & 0100
91 if x and not sx:
92 # Turn on +x for every +r bit when making a file executable
93 # and obey umask.
94 os.chmod(f, s | (s & 0444) >> 2 & ~umask)
95 elif not x and sx:
96 # Turn off all +x bits
97 os.chmod(f, s & 0666)
98
99 def set_binary(fd):
100 pass
101
102 def pconvert(path):
103 return path
104
105 def localpath(path):
106 return path
107
108 def shellquote(s):
109 if os.sys.platform == 'OpenVMS':
110 return '"%s"' % s
111 else:
112 return "'%s'" % s.replace("'", "'\\''")
113
114 def quotecommand(cmd):
115 return cmd
116
117 def popen(command, mode='r'):
118 return os.popen(command, mode)
119
120 def testpid(pid):
121 '''return False if pid dead, True if running or not sure'''
122 if os.sys.platform == 'OpenVMS':
123 return True
124 try:
125 os.kill(pid, 0)
126 return True
127 except OSError, inst:
128 return inst.errno != errno.ESRCH
129
130 def explain_exit(code):
131 """return a 2-tuple (desc, code) describing a process's status"""
132 if os.WIFEXITED(code):
133 val = os.WEXITSTATUS(code)
134 return _("exited with status %d") % val, val
135 elif os.WIFSIGNALED(code):
136 val = os.WTERMSIG(code)
137 return _("killed by signal %d") % val, val
138 elif os.WIFSTOPPED(code):
139 val = os.WSTOPSIG(code)
140 return _("stopped by signal %d") % val, val
141 raise ValueError(_("invalid exit code"))
142
143 def isowner(fp, st=None):
144 """Return True if the file object f belongs to the current user.
145
146 The return value of a util.fstat(f) may be passed as the st argument.
147 """
148 if st is None:
149 st = fstat(fp)
150 return st.st_uid == os.getuid()
151
152 def find_exe(command):
153 '''Find executable for command searching like which does.
154 If command is a basename then PATH is searched for command.
155 PATH isn't searched if command is an absolute or relative path.
156 If command isn't found None is returned.'''
157 if sys.platform == 'OpenVMS':
158 return command
159
160 def findexisting(executable):
161 'Will return executable if existing file'
162 if os.path.exists(executable):
163 return executable
164 return None
165
166 if os.sep in command:
167 return findexisting(command)
168
169 for path in os.environ.get('PATH', '').split(os.pathsep):
170 executable = findexisting(os.path.join(path, command))
171 if executable is not None:
172 return executable
173 return None
174
175 def set_signal_handler():
176 pass
177
178 def statfiles(files):
179 'Stat each file in files and yield stat or None if file does not exist.'
180 lstat = os.lstat
181 for nf in files:
182 try:
183 st = lstat(nf)
184 except OSError, err:
185 if err.errno not in (errno.ENOENT, errno.ENOTDIR):
186 raise
187 st = None
188 yield st
189
190 def getuser():
191 '''return name of current user'''
192 return getpass.getuser()
193
194 def expand_glob(pats):
195 '''On Windows, expand the implicit globs in a list of patterns'''
196 return list(pats)
197
198 def username(uid=None):
199 """Return the name of the user with the given uid.
200
201 If uid is None, return the name of the current user."""
202
203 if uid is None:
204 uid = os.getuid()
205 try:
206 return pwd.getpwuid(uid)[0]
207 except KeyError:
208 return str(uid)
209
210 def groupname(gid=None):
211 """Return the name of the group with the given gid.
212
213 If gid is None, return the name of the current group."""
214
215 if gid is None:
216 gid = os.getgid()
217 try:
218 return grp.getgrgid(gid)[0]
219 except KeyError:
220 return str(gid)
221
222