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