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