Mercurial > hg
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 |