##// END OF EJS Templates
hghave: wrap command in 'sh -c "..."' for has_pyflakes()...
Adrian Buehlmann -
r16872:40d93084 default
parent child Browse files
Show More
@@ -1,345 +1,345
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, stat
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 21 try:
22 22 ret = fh.close()
23 23 except IOError:
24 24 # Happen in Windows test environment
25 25 ret = 1
26 26 return (ignorestatus or ret is None) and r.search(s)
27 27
28 28 def has_baz():
29 29 return matchoutput('baz --version 2>&1', r'baz Bazaar version')
30 30
31 31 def has_bzr():
32 32 try:
33 33 import bzrlib
34 34 return bzrlib.__doc__ is not None
35 35 except ImportError:
36 36 return False
37 37
38 38 def has_bzr114():
39 39 try:
40 40 import bzrlib
41 41 return (bzrlib.__doc__ is not None
42 42 and bzrlib.version_info[:2] >= (1, 14))
43 43 except ImportError:
44 44 return False
45 45
46 46 def has_cvs():
47 47 re = r'Concurrent Versions System.*?server'
48 48 return matchoutput('cvs --version 2>&1', re) and not has_msys()
49 49
50 50 def has_darcs():
51 51 return matchoutput('darcs --version', r'2\.[2-9]', True)
52 52
53 53 def has_mtn():
54 54 return matchoutput('mtn --version', r'monotone', True) and not matchoutput(
55 55 'mtn --version', r'monotone 0\.', True)
56 56
57 57 def has_eol_in_paths():
58 58 try:
59 59 fd, path = tempfile.mkstemp(prefix=tempprefix, suffix='\n\r')
60 60 os.close(fd)
61 61 os.remove(path)
62 62 return True
63 63 except (IOError, OSError):
64 64 return False
65 65
66 66 def has_executablebit():
67 67 try:
68 68 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
69 69 fh, fn = tempfile.mkstemp(dir=".", prefix='hg-checkexec-')
70 70 try:
71 71 os.close(fh)
72 72 m = os.stat(fn).st_mode & 0777
73 73 new_file_has_exec = m & EXECFLAGS
74 74 os.chmod(fn, m ^ EXECFLAGS)
75 75 exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0777) == m)
76 76 finally:
77 77 os.unlink(fn)
78 78 except (IOError, OSError):
79 79 # we don't care, the user probably won't be able to commit anyway
80 80 return False
81 81 return not (new_file_has_exec or exec_flags_cannot_flip)
82 82
83 83 def has_icasefs():
84 84 # Stolen from mercurial.util
85 85 fd, path = tempfile.mkstemp(prefix=tempprefix, dir='.')
86 86 os.close(fd)
87 87 try:
88 88 s1 = os.stat(path)
89 89 d, b = os.path.split(path)
90 90 p2 = os.path.join(d, b.upper())
91 91 if path == p2:
92 92 p2 = os.path.join(d, b.lower())
93 93 try:
94 94 s2 = os.stat(p2)
95 95 return s2 == s1
96 96 except OSError:
97 97 return False
98 98 finally:
99 99 os.remove(path)
100 100
101 101 def has_inotify():
102 102 try:
103 103 import hgext.inotify.linux.watcher
104 104 return True
105 105 except ImportError:
106 106 return False
107 107
108 108 def has_fifo():
109 109 return getattr(os, "mkfifo", None) is not None
110 110
111 111 def has_cacheable_fs():
112 112 from mercurial import util
113 113
114 114 fd, path = tempfile.mkstemp(prefix=tempprefix)
115 115 os.close(fd)
116 116 try:
117 117 return util.cachestat(path).cacheable()
118 118 finally:
119 119 os.remove(path)
120 120
121 121 def has_lsprof():
122 122 try:
123 123 import _lsprof
124 124 return True
125 125 except ImportError:
126 126 return False
127 127
128 128 def has_gettext():
129 129 return matchoutput('msgfmt --version', 'GNU gettext-tools')
130 130
131 131 def has_git():
132 132 return matchoutput('git --version 2>&1', r'^git version')
133 133
134 134 def has_docutils():
135 135 try:
136 136 from docutils.core import publish_cmdline
137 137 return True
138 138 except ImportError:
139 139 return False
140 140
141 141 def getsvnversion():
142 142 m = matchoutput('svn --version 2>&1', r'^svn,\s+version\s+(\d+)\.(\d+)')
143 143 if not m:
144 144 return (0, 0)
145 145 return (int(m.group(1)), int(m.group(2)))
146 146
147 147 def has_svn15():
148 148 return getsvnversion() >= (1, 5)
149 149
150 150 def has_svn13():
151 151 return getsvnversion() >= (1, 3)
152 152
153 153 def has_svn():
154 154 return matchoutput('svn --version 2>&1', r'^svn, version') and \
155 155 matchoutput('svnadmin --version 2>&1', r'^svnadmin, version')
156 156
157 157 def has_svn_bindings():
158 158 try:
159 159 import svn.core
160 160 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
161 161 if version < (1, 4):
162 162 return False
163 163 return True
164 164 except ImportError:
165 165 return False
166 166
167 167 def has_p4():
168 168 return (matchoutput('p4 -V', r'Rev\. P4/') and
169 169 matchoutput('p4d -V', r'Rev\. P4D/'))
170 170
171 171 def has_symlink():
172 172 if getattr(os, "symlink", None) is None:
173 173 return False
174 174 name = tempfile.mktemp(dir=".", prefix='hg-checklink-')
175 175 try:
176 176 os.symlink(".", name)
177 177 os.unlink(name)
178 178 return True
179 179 except (OSError, AttributeError):
180 180 return False
181 181
182 182 def has_tla():
183 183 return matchoutput('tla --version 2>&1', r'The GNU Arch Revision')
184 184
185 185 def has_gpg():
186 186 return matchoutput('gpg --version 2>&1', r'GnuPG')
187 187
188 188 def has_unix_permissions():
189 189 d = tempfile.mkdtemp(prefix=tempprefix, dir=".")
190 190 try:
191 191 fname = os.path.join(d, 'foo')
192 192 for umask in (077, 007, 022):
193 193 os.umask(umask)
194 194 f = open(fname, 'w')
195 195 f.close()
196 196 mode = os.stat(fname).st_mode
197 197 os.unlink(fname)
198 198 if mode & 0777 != ~umask & 0666:
199 199 return False
200 200 return True
201 201 finally:
202 202 os.rmdir(d)
203 203
204 204 def has_pyflakes():
205 return matchoutput('echo "import re" 2>&1 | pyflakes',
205 return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"",
206 206 r"<stdin>:1: 're' imported but unused",
207 207 True)
208 208
209 209 def has_pygments():
210 210 try:
211 211 import pygments
212 212 return True
213 213 except ImportError:
214 214 return False
215 215
216 216 def has_outer_repo():
217 217 return matchoutput('hg root 2>&1', r'')
218 218
219 219 def has_ssl():
220 220 try:
221 221 import ssl
222 222 import OpenSSL
223 223 OpenSSL.SSL.Context
224 224 return True
225 225 except ImportError:
226 226 return False
227 227
228 228 def has_windows():
229 229 return os.name == 'nt'
230 230
231 231 def has_system_sh():
232 232 return os.name != 'nt'
233 233
234 234 def has_serve():
235 235 return os.name != 'nt' # gross approximation
236 236
237 237 def has_tic():
238 238 return matchoutput('test -x "`which tic`"', '')
239 239
240 240 def has_msys():
241 241 return os.getenv('MSYSTEM')
242 242
243 243 checks = {
244 244 "baz": (has_baz, "GNU Arch baz client"),
245 245 "bzr": (has_bzr, "Canonical's Bazaar client"),
246 246 "bzr114": (has_bzr114, "Canonical's Bazaar client >= 1.14"),
247 247 "cacheable": (has_cacheable_fs, "cacheable filesystem"),
248 248 "cvs": (has_cvs, "cvs client/server"),
249 249 "darcs": (has_darcs, "darcs client"),
250 250 "docutils": (has_docutils, "Docutils text processing library"),
251 251 "eol-in-paths": (has_eol_in_paths, "end-of-lines in paths"),
252 252 "execbit": (has_executablebit, "executable bit"),
253 253 "fifo": (has_fifo, "named pipes"),
254 254 "gettext": (has_gettext, "GNU Gettext (msgfmt)"),
255 255 "git": (has_git, "git command line client"),
256 256 "gpg": (has_gpg, "gpg client"),
257 257 "icasefs": (has_icasefs, "case insensitive file system"),
258 258 "inotify": (has_inotify, "inotify extension support"),
259 259 "lsprof": (has_lsprof, "python lsprof module"),
260 260 "mtn": (has_mtn, "monotone client (>= 1.0)"),
261 261 "outer-repo": (has_outer_repo, "outer repo"),
262 262 "p4": (has_p4, "Perforce server and client"),
263 263 "pyflakes": (has_pyflakes, "Pyflakes python linter"),
264 264 "pygments": (has_pygments, "Pygments source highlighting library"),
265 265 "serve": (has_serve, "platform and python can manage 'hg serve -d'"),
266 266 "ssl": (has_ssl, "python >= 2.6 ssl module and python OpenSSL"),
267 267 "svn": (has_svn, "subversion client and admin tools"),
268 268 "svn13": (has_svn13, "subversion client and admin tools >= 1.3"),
269 269 "svn15": (has_svn15, "subversion client and admin tools >= 1.5"),
270 270 "svn-bindings": (has_svn_bindings, "subversion python bindings"),
271 271 "symlink": (has_symlink, "symbolic links"),
272 272 "system-sh": (has_system_sh, "system() uses sh"),
273 273 "tic": (has_tic, "terminfo compiler"),
274 274 "tla": (has_tla, "GNU Arch tla client"),
275 275 "unix-permissions": (has_unix_permissions, "unix-style permissions"),
276 276 "windows": (has_windows, "Windows"),
277 277 "msys": (has_msys, "Windows with MSYS"),
278 278 }
279 279
280 280 def list_features():
281 281 for name, feature in checks.iteritems():
282 282 desc = feature[1]
283 283 print name + ':', desc
284 284
285 285 def test_features():
286 286 failed = 0
287 287 for name, feature in checks.iteritems():
288 288 check, _ = feature
289 289 try:
290 290 check()
291 291 except Exception, e:
292 292 print "feature %s failed: %s" % (name, e)
293 293 failed += 1
294 294 return failed
295 295
296 296 parser = optparse.OptionParser("%prog [options] [features]")
297 297 parser.add_option("--test-features", action="store_true",
298 298 help="test available features")
299 299 parser.add_option("--list-features", action="store_true",
300 300 help="list available features")
301 301 parser.add_option("-q", "--quiet", action="store_true",
302 302 help="check features silently")
303 303
304 304 if __name__ == '__main__':
305 305 options, args = parser.parse_args()
306 306 if options.list_features:
307 307 list_features()
308 308 sys.exit(0)
309 309
310 310 if options.test_features:
311 311 sys.exit(test_features())
312 312
313 313 quiet = options.quiet
314 314
315 315 failures = 0
316 316
317 317 def error(msg):
318 318 global failures
319 319 if not quiet:
320 320 sys.stderr.write(msg + '\n')
321 321 failures += 1
322 322
323 323 for feature in args:
324 324 negate = feature.startswith('no-')
325 325 if negate:
326 326 feature = feature[3:]
327 327
328 328 if feature not in checks:
329 329 error('skipped: unknown feature: ' + feature)
330 330 continue
331 331
332 332 check, desc = checks[feature]
333 333 try:
334 334 available = check()
335 335 except Exception, e:
336 336 error('hghave check failed: ' + feature)
337 337 continue
338 338
339 339 if not negate and not available:
340 340 error('skipped: missing feature: ' + desc)
341 341 elif negate and available:
342 342 error('skipped: system supports %s' % desc)
343 343
344 344 if failures != 0:
345 345 sys.exit(1)
General Comments 0
You need to be logged in to leave comments. Login now