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