1 |
Author: zmedico |
2 |
Date: 2009-06-28 08:08:54 +0000 (Sun, 28 Jun 2009) |
3 |
New Revision: 13717 |
4 |
|
5 |
Modified: |
6 |
main/trunk/pym/repoman/checks.py |
7 |
Log: |
8 |
* Add new abstract PhaseCheck class for ebuild phase-specific checks. |
9 |
* Reimplement SrcUnpackPatches using PhaseCheck. |
10 |
* Add new SrcCompileEconf, Eapi3IncompatibleFuncs, and Eapi3GoneVars checks. |
11 |
Thanks to Markus Meier <maekke@g.o> for this patch. |
12 |
|
13 |
|
14 |
Modified: main/trunk/pym/repoman/checks.py |
15 |
=================================================================== |
16 |
--- main/trunk/pym/repoman/checks.py 2009-06-27 19:39:46 UTC (rev 13716) |
17 |
+++ main/trunk/pym/repoman/checks.py 2009-06-28 08:08:54 UTC (rev 13717) |
18 |
@@ -19,6 +19,10 @@ |
19 |
def new(self, pkg): |
20 |
pass |
21 |
|
22 |
+ def check_eapi(self, eapi): |
23 |
+ """ returns if the check should be run in the given EAPI (default is True) """ |
24 |
+ return True |
25 |
+ |
26 |
def check(self, num, line): |
27 |
"""Run the check on line and return error if there is one""" |
28 |
if self.re.match(line): |
29 |
@@ -198,7 +202,7 @@ |
30 |
class EbuildUselessCdS(LineCheck): |
31 |
"""Check for redundant cd ${S} statements""" |
32 |
repoman_check_name = 'ebuild.minorsyn' |
33 |
- method_re = re.compile(r'^\s*src_(compile|install|test)\s*\(\)') |
34 |
+ method_re = re.compile(r'^\s*src_(prepare|configure|compile|install|test)\s*\(\)') |
35 |
cds_re = re.compile(r'^\s*cd\s+("\$(\{S\}|S)"|\$(\{S\}|S))\s') |
36 |
|
37 |
def __init__(self): |
38 |
@@ -229,39 +233,6 @@ |
39 |
elif self.inherit_re.match(line) is not None: |
40 |
self.inherit_line = line |
41 |
|
42 |
-class SrcUnpackPatches(LineCheck): |
43 |
- repoman_check_name = 'ebuild.minorsyn' |
44 |
- |
45 |
- ignore_line = re.compile(r'(^\s*#)') |
46 |
- src_unpack_re = re.compile(r'^src_unpack\(\)') |
47 |
- func_end_re = re.compile(r'^\}$') |
48 |
- src_prepare_tools_re = re.compile(r'\s(e?patch|sed)\s') |
49 |
- |
50 |
- def new(self, pkg): |
51 |
- if pkg.metadata['EAPI'] not in ('0', '1'): |
52 |
- self.eapi = pkg.metadata['EAPI'] |
53 |
- else: |
54 |
- self.eapi = None |
55 |
- self.in_src_unpack = None |
56 |
- |
57 |
- def check(self, num, line): |
58 |
- |
59 |
- if self.eapi is not None: |
60 |
- |
61 |
- if self.in_src_unpack is None and \ |
62 |
- self.src_unpack_re.match(line) is not None: |
63 |
- self.in_src_unpack = True |
64 |
- |
65 |
- if self.in_src_unpack is True and \ |
66 |
- self.func_end_re.match(line) is not None: |
67 |
- self.in_src_unpack = False |
68 |
- |
69 |
- if self.in_src_unpack: |
70 |
- m = self.src_prepare_tools_re.search(line) |
71 |
- if m is not None: |
72 |
- return ("'%s'" % m.group(1)) + \ |
73 |
- " call should be moved to src_prepare from line: %d" |
74 |
- |
75 |
class EbuildPatches(LineCheck): |
76 |
"""Ensure ebuilds use bash arrays for PATCHES to ensure white space safety""" |
77 |
repoman_check_name = 'ebuild.patches' |
78 |
@@ -285,10 +256,14 @@ |
79 |
since this triggers implicit RDEPEND=$DEPEND assignment. |
80 |
""" |
81 |
|
82 |
- repoman_check_name = 'RDEPEND.implicit' |
83 |
_assignment_re = re.compile(r'^\s*(R?DEPEND)=') |
84 |
|
85 |
def new(self, pkg): |
86 |
+ # RDEPEND=DEPEND is no longer available in EAPI=3 |
87 |
+ if pkg.metadata['EAPI'] in ('0', '1', '2'): |
88 |
+ self.repoman_check_name = 'RDEPEND.implicit' |
89 |
+ else: |
90 |
+ self.repoman_check_name = 'EAPI.incompatible' |
91 |
self._rdepend = False |
92 |
self._depend = False |
93 |
|
94 |
@@ -394,6 +369,107 @@ |
95 |
return 'WANT_AUTO' + m.group(1) + \ |
96 |
' redundantly set to default value "latest" on line: %d' |
97 |
|
98 |
+class PhaseCheck(LineCheck): |
99 |
+ """ basic class for function detection """ |
100 |
+ |
101 |
+ ignore_line = re.compile(r'(^\s*#)') |
102 |
+ func_end_re = re.compile(r'^\}$') |
103 |
+ in_phase = '' |
104 |
+ |
105 |
+ def __init__(self): |
106 |
+ self.phases = ('pkg_setup', 'pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm', 'pkg_pretend', |
107 |
+ 'src_unpack', 'src_prepare', 'src_compile', 'src_test', 'src_install') |
108 |
+ phase_re = '(' |
109 |
+ for phase in self.phases: |
110 |
+ phase_re += phase + '|' |
111 |
+ phase_re = phase_re[:-1] + ')' |
112 |
+ self.phases_re = re.compile(phase_re) |
113 |
+ |
114 |
+ def check(self, num, line): |
115 |
+ m = self.phases_re.match(line) |
116 |
+ if m is not None: |
117 |
+ self.in_phase = m.group(1) |
118 |
+ if self.in_phase != '' and \ |
119 |
+ self.func_end_re.match(line) is not None: |
120 |
+ self.in_phase = '' |
121 |
+ |
122 |
+ return self.phase_check(num, line) |
123 |
+ |
124 |
+ def phase_check(self, num, line): |
125 |
+ """ override this function for your checks """ |
126 |
+ pass |
127 |
+ |
128 |
+class SrcCompileEconf(PhaseCheck): |
129 |
+ repoman_check_name = 'ebuild.minorsyn' |
130 |
+ configure_re = re.compile(r'\s(econf|./configure)') |
131 |
+ |
132 |
+ def check_eapi(self, eapi): |
133 |
+ return eapi not in ('0', '1') |
134 |
+ |
135 |
+ def phase_check(self, num, line): |
136 |
+ if self.in_phase == 'src_compile': |
137 |
+ m = self.configure_re.match(line) |
138 |
+ if m is not None: |
139 |
+ return ("'%s'" % m.group(1)) + \ |
140 |
+ " call should be moved to src_configure from line: %d" |
141 |
+ |
142 |
+class SrcUnpackPatches(PhaseCheck): |
143 |
+ repoman_check_name = 'ebuild.minorsyn' |
144 |
+ src_prepare_tools_re = re.compile(r'\s(e?patch|sed)\s') |
145 |
+ |
146 |
+ def new(self, pkg): |
147 |
+ if pkg.metadata['EAPI'] not in ('0', '1'): |
148 |
+ self.eapi = pkg.metadata['EAPI'] |
149 |
+ else: |
150 |
+ self.eapi = None |
151 |
+ self.in_src_unpack = None |
152 |
+ |
153 |
+ def check_eapi(self, eapi): |
154 |
+ return eapi not in ('0', '1') |
155 |
+ |
156 |
+ def phase_check(self, num, line): |
157 |
+ if self.in_phase == 'src_unpack': |
158 |
+ m = self.src_prepare_tools_re.search(line) |
159 |
+ if m is not None: |
160 |
+ return ("'%s'" % m.group(1)) + \ |
161 |
+ " call should be moved to src_prepare from line: %d" |
162 |
+ |
163 |
+# EAPI-3 checks |
164 |
+class Eapi3IncompatibleFuncs(LineCheck): |
165 |
+ repoman_check_name = 'EAPI.incompatible' |
166 |
+ ignore_line = re.compile(r'(^\s*#)') |
167 |
+ banned_commands_re = re.compile(r'^\s*(dosed|dohard)') |
168 |
+ |
169 |
+ def new(self, pkg): |
170 |
+ self.eapi = pkg.metadata['EAPI'] |
171 |
+ |
172 |
+ def check_eapi(self, eapi): |
173 |
+ return self.eapi not in ('0', '1', '2') |
174 |
+ |
175 |
+ def check(self, num, line): |
176 |
+ m = self.banned_commands_re.match(line) |
177 |
+ if m is not None: |
178 |
+ return ("'%s'" % m.group(1)) + \ |
179 |
+ " has been banned in EAPI=3 on line: %d" |
180 |
+ |
181 |
+class Eapi3GoneVars(LineCheck): |
182 |
+ repoman_check_name = 'EAPI.incompatible' |
183 |
+ ignore_line = re.compile(r'(^\s*#)') |
184 |
+ undefined_vars_re = re.compile(r'.*\$(\{(AA|KV)\}|(AA|KV))') |
185 |
+ |
186 |
+ def new(self, pkg): |
187 |
+ self.eapi = pkg.metadata['EAPI'] |
188 |
+ |
189 |
+ def check_eapi(self, eapi): |
190 |
+ return self.eapi not in ('0', '1', '2') |
191 |
+ |
192 |
+ def check(self, num, line): |
193 |
+ m = self.undefined_vars_re.match(line) |
194 |
+ if m is not None: |
195 |
+ return ("variable '$%s'" % m.group(1)) + \ |
196 |
+ " is gone in EAPI=3 on line: %d" |
197 |
+ |
198 |
+ |
199 |
_constant_checks = tuple((c() for c in ( |
200 |
EbuildHeader, EbuildWhitespace, EbuildQuote, |
201 |
EbuildAssignment, EbuildUselessDodoc, |
202 |
@@ -401,7 +477,8 @@ |
203 |
EbuildPatches, EbuildQuotedA, EapiDefinition, |
204 |
IUseUndefined, ImplicitRuntimeDeps, InheritAutotools, |
205 |
EMakeParallelDisabled, EMakeParallelDisabledViaMAKEOPTS, |
206 |
- DeprecatedBindnowFlags, SrcUnpackPatches, WantAutoDefaultValue))) |
207 |
+ DeprecatedBindnowFlags, SrcUnpackPatches, WantAutoDefaultValue, |
208 |
+ SrcCompileEconf, Eapi3IncompatibleFuncs, Eapi3GoneVars))) |
209 |
|
210 |
_here_doc_re = re.compile(r'.*\s<<[-]?(\w+)$') |
211 |
|
212 |
@@ -425,11 +502,12 @@ |
213 |
if here_doc_delim is None: |
214 |
# We're not in a here-document. |
215 |
for lc in checks: |
216 |
- ignore = lc.ignore_line |
217 |
- if not ignore or not ignore.match(line): |
218 |
- e = lc.check(num, line) |
219 |
- if e: |
220 |
- yield lc.repoman_check_name, e % (num + 1) |
221 |
+ if lc.check_eapi(pkg.metadata['EAPI']): |
222 |
+ ignore = lc.ignore_line |
223 |
+ if not ignore or not ignore.match(line): |
224 |
+ e = lc.check(num, line) |
225 |
+ if e: |
226 |
+ yield lc.repoman_check_name, e % (num + 1) |
227 |
|
228 |
for lc in checks: |
229 |
i = lc.end() |