##// END OF EJS Templates
hghave: handle Windows raising on popen() failure
Patrick Mezard -
r8213:ac9c4049 default
parent child Browse files
Show More
@@ -1,264 +1,268 b''
1 1 #!/usr/bin/env python
2 2 """Test the running system for features availability. Exit with zero
3 3 if all features are there, non-zero otherwise. If a feature name is
4 4 prefixed with "no-", the absence of feature is tested.
5 5 """
6 6 import optparse
7 7 import os
8 8 import re
9 9 import sys
10 10 import tempfile
11 11
12 12 tempprefix = 'hg-hghave-'
13 13
14 14 def matchoutput(cmd, regexp, ignorestatus=False):
15 15 """Return True if cmd executes successfully and its output
16 16 is matched by the supplied regular expression.
17 17 """
18 18 r = re.compile(regexp)
19 19 fh = os.popen(cmd)
20 20 s = fh.read()
21 try:
21 22 ret = fh.close()
23 except IOError:
24 # Happen in Windows test environment
25 ret = 1
22 26 return (ignorestatus or ret is None) and r.search(s)
23 27
24 28 def has_baz():
25 29 return matchoutput('baz --version 2>&1', r'baz Bazaar version')
26 30
27 31 def has_bzr():
28 32 try:
29 33 import bzrlib
30 34 return bzrlib.__doc__ != None
31 35 except ImportError:
32 36 return False
33 37
34 38 def has_bzr114():
35 39 try:
36 40 import bzrlib
37 41 return (bzrlib.__doc__ != None
38 42 and bzrlib.version_info[:2] == (1, 14))
39 43 except ImportError:
40 44 return False
41 45
42 46 def has_cvs():
43 47 re = r'Concurrent Versions System.*?server'
44 48 return matchoutput('cvs --version 2>&1', re)
45 49
46 50 def has_cvsps():
47 51 return matchoutput('cvsps -h -q 2>&1', r'cvsps version', True)
48 52
49 53 def has_darcs():
50 54 return matchoutput('darcs', r'darcs version', True)
51 55
52 56 def has_mtn():
53 57 return matchoutput('mtn --version', r'monotone', True) and not matchoutput(
54 58 'mtn --version', r'monotone 0\.(\d|[12]\d|3[01])[^\d]', True)
55 59
56 60 def has_eol_in_paths():
57 61 try:
58 62 fd, path = tempfile.mkstemp(prefix=tempprefix, suffix='\n\r')
59 63 os.close(fd)
60 64 os.remove(path)
61 65 return True
62 66 except:
63 67 return False
64 68
65 69 def has_executablebit():
66 70 fd, path = tempfile.mkstemp(prefix=tempprefix)
67 71 os.close(fd)
68 72 try:
69 73 s = os.lstat(path).st_mode
70 74 os.chmod(path, s | 0100)
71 75 return (os.lstat(path).st_mode & 0100 != 0)
72 76 finally:
73 77 os.remove(path)
74 78
75 79 def has_icasefs():
76 80 # Stolen from mercurial.util
77 81 fd, path = tempfile.mkstemp(prefix=tempprefix)
78 82 os.close(fd)
79 83 try:
80 84 s1 = os.stat(path)
81 85 d, b = os.path.split(path)
82 86 p2 = os.path.join(d, b.upper())
83 87 if path == p2:
84 88 p2 = os.path.join(d, b.lower())
85 89 try:
86 90 s2 = os.stat(p2)
87 91 return s2 == s1
88 92 except:
89 93 return False
90 94 finally:
91 95 os.remove(path)
92 96
93 97 def has_inotify():
94 98 try:
95 99 import hgext.inotify.linux.watcher
96 100 return True
97 101 except ImportError:
98 102 return False
99 103
100 104 def has_fifo():
101 105 return hasattr(os, "mkfifo")
102 106
103 107 def has_hotshot():
104 108 try:
105 109 # hotshot.stats tests hotshot and many problematic dependencies
106 110 # like profile.
107 111 import hotshot.stats
108 112 return True
109 113 except ImportError:
110 114 return False
111 115
112 116 def has_lsprof():
113 117 try:
114 118 import _lsprof
115 119 return True
116 120 except ImportError:
117 121 return False
118 122
119 123 def has_git():
120 124 return matchoutput('git --version 2>&1', r'^git version')
121 125
122 126 def has_svn():
123 127 return matchoutput('svn --version 2>&1', r'^svn, version') and \
124 128 matchoutput('svnadmin --version 2>&1', r'^svnadmin, version')
125 129
126 130 def has_svn_bindings():
127 131 try:
128 132 import svn.core
129 133 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
130 134 if version < (1, 4):
131 135 return False
132 136 return True
133 137 except ImportError:
134 138 return False
135 139
136 140 def has_p4():
137 141 return matchoutput('p4 -V', r'Rev\. P4/') and matchoutput('p4d -V', r'Rev\. P4D/')
138 142
139 143 def has_symlink():
140 144 return hasattr(os, "symlink")
141 145
142 146 def has_tla():
143 147 return matchoutput('tla --version 2>&1', r'The GNU Arch Revision')
144 148
145 149 def has_unix_permissions():
146 150 d = tempfile.mkdtemp(prefix=tempprefix, dir=".")
147 151 try:
148 152 fname = os.path.join(d, 'foo')
149 153 for umask in (077, 007, 022):
150 154 os.umask(umask)
151 155 f = open(fname, 'w')
152 156 f.close()
153 157 mode = os.stat(fname).st_mode
154 158 os.unlink(fname)
155 159 if mode & 0777 != ~umask & 0666:
156 160 return False
157 161 return True
158 162 finally:
159 163 os.rmdir(d)
160 164
161 165 def has_pygments():
162 166 try:
163 167 import pygments
164 168 return True
165 169 except ImportError:
166 170 return False
167 171
168 172 def has_outer_repo():
169 173 return matchoutput('hg root 2>&1', r'')
170 174
171 175 checks = {
172 176 "baz": (has_baz, "GNU Arch baz client"),
173 177 "bzr": (has_bzr, "Canonical's Bazaar client"),
174 178 "bzr114": (has_bzr114, "Canonical's Bazaar client >= 1.14"),
175 179 "cvs": (has_cvs, "cvs client/server"),
176 180 "cvsps": (has_cvsps, "cvsps utility"),
177 181 "darcs": (has_darcs, "darcs client"),
178 182 "eol-in-paths": (has_eol_in_paths, "end-of-lines in paths"),
179 183 "execbit": (has_executablebit, "executable bit"),
180 184 "fifo": (has_fifo, "named pipes"),
181 185 "git": (has_git, "git command line client"),
182 186 "hotshot": (has_hotshot, "python hotshot module"),
183 187 "icasefs": (has_icasefs, "case insensitive file system"),
184 188 "inotify": (has_inotify, "inotify extension support"),
185 189 "lsprof": (has_lsprof, "python lsprof module"),
186 190 "mtn": (has_mtn, "monotone client (> 0.31)"),
187 191 "outer-repo": (has_outer_repo, "outer repo"),
188 192 "p4": (has_p4, "Perforce server and client"),
189 193 "pygments": (has_pygments, "Pygments source highlighting library"),
190 194 "svn": (has_svn, "subversion client and admin tools"),
191 195 "svn-bindings": (has_svn_bindings, "subversion python bindings"),
192 196 "symlink": (has_symlink, "symbolic links"),
193 197 "tla": (has_tla, "GNU Arch tla client"),
194 198 "unix-permissions": (has_unix_permissions, "unix-style permissions"),
195 199 }
196 200
197 201 def list_features():
198 202 for name, feature in checks.iteritems():
199 203 desc = feature[1]
200 204 print name + ':', desc
201 205
202 206 def test_features():
203 207 failed = 0
204 208 for name, feature in checks.iteritems():
205 209 check, _ = feature
206 210 try:
207 211 check()
208 212 except Exception, e:
209 213 print "feature %s failed: %s" % (name, e)
210 214 failed += 1
211 215 return failed
212 216
213 217 parser = optparse.OptionParser("%prog [options] [features]")
214 218 parser.add_option("--test-features", action="store_true",
215 219 help="test available features")
216 220 parser.add_option("--list-features", action="store_true",
217 221 help="list available features")
218 222 parser.add_option("-q", "--quiet", action="store_true",
219 223 help="check features silently")
220 224
221 225 if __name__ == '__main__':
222 226 options, args = parser.parse_args()
223 227 if options.list_features:
224 228 list_features()
225 229 sys.exit(0)
226 230
227 231 if options.test_features:
228 232 sys.exit(test_features())
229 233
230 234 quiet = options.quiet
231 235
232 236 failures = 0
233 237
234 238 def error(msg):
235 239 global failures
236 240 if not quiet:
237 241 sys.stderr.write(msg + '\n')
238 242 failures += 1
239 243
240 244 for feature in args:
241 245 negate = feature.startswith('no-')
242 246 if negate:
243 247 feature = feature[3:]
244 248
245 249 if feature not in checks:
246 250 error('skipped: unknown feature: ' + feature)
247 251 continue
248 252
249 253 check, desc = checks[feature]
250 254 try:
251 255 available = check()
252 256 except Exception, e:
253 257 error('hghave check failed: ' + feature)
254 258 continue
255 259
256 260 if not negate and not available:
257 261 error('skipped: missing feature: ' + desc)
258 262 elif negate and available:
259 263 error('skipped: system supports %s' % desc)
260 264
261 265 if failures != 0:
262 266 sys.exit(1)
263 267
264 268
General Comments 0
You need to be logged in to leave comments. Login now