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