Gentoo Archives: gentoo-portage-dev

From: Mike Frysinger <vapier@g.o>
To: gentoo-portage-dev@l.g.o
Subject: [gentoo-portage-dev] [PATCH] repoman: add a mini framework for checking eclasses, and fill it out
Date: Wed, 23 May 2012 21:23:50
Message-Id: 1337800911-17630-1-git-send-email-vapier@gentoo.org
1 Rather than copying & pasting the same behavior for the different eclass
2 checks, add a common class for them to extend. This makes adding more
3 eclass checks trivial, and keeps down bitrot.
4
5 This does abuse the checking interface slightly -- the eclass will change
6 its category between unused and missing based on the checks.
7
8 URL: https://bugs.gentoo.org/417159
9 URL: https://bugs.gentoo.org/417231
10 Signed-off-by: Mike Frysinger <vapier@g.o>
11 ---
12 bin/repoman | 6 +-
13 pym/repoman/checks.py | 143 ++++++++++++++++++++++++++++++++-----------------
14 pym/repoman/errors.py | 1 -
15 3 files changed, 97 insertions(+), 53 deletions(-)
16
17 diff --git a/bin/repoman b/bin/repoman
18 index 3697403..d7ffcdd 100755
19 --- a/bin/repoman
20 +++ b/bin/repoman
21 @@ -315,8 +315,9 @@ qahelp={
22 "file.size.fatal":"Files in the files directory must be under 60 KiB",
23 "file.name":"File/dir name must be composed of only the following chars: %s " % allowed_filename_chars,
24 "file.UTF8":"File is not UTF8 compliant",
25 - "inherit.autotools":"Ebuild inherits autotools but does not call eautomake, eautoconf or eautoreconf",
26 "inherit.deprecated":"Ebuild inherits a deprecated eclass",
27 + "inherit.missing":"Ebuild uses functions from an eclass but does not inherit it",
28 + "inherit.unused":"Ebuild inherits an eclass but does not use it",
29 "java.eclassesnotused":"With virtual/jdk in DEPEND you must inherit a java eclass",
30 "wxwidgets.eclassnotused":"Ebuild DEPENDs on x11-libs/wxGTK without inheriting wxwidgets.eclass",
31 "KEYWORDS.dropped":"Ebuilds that appear to have dropped KEYWORDS for some arch",
32 @@ -382,7 +383,6 @@ qahelp={
33 "ebuild.majorsyn":"This ebuild has a major syntax error that may cause the ebuild to fail partially or fully",
34 "ebuild.minorsyn":"This ebuild has a minor syntax error that contravenes gentoo coding style",
35 "ebuild.badheader":"This ebuild has a malformed header",
36 - "eprefixify.defined":"The ebuild uses eprefixify, but does not inherit the prefix eclass",
37 "manifest.bad":"Manifest has missing or incorrect digests",
38 "metadata.missing":"Missing metadata.xml files",
39 "metadata.bad":"Bad metadata.xml files",
40 @@ -425,7 +425,7 @@ qawarnings = set((
41 "ebuild.badheader",
42 "ebuild.patches",
43 "file.size",
44 -"inherit.autotools",
45 +"inherit.unused",
46 "inherit.deprecated",
47 "java.eclassesnotused",
48 "wxwidgets.eclassnotused",
49 diff --git a/pym/repoman/checks.py b/pym/repoman/checks.py
50 index 77df603..088a916 100644
51 --- a/pym/repoman/checks.py
52 +++ b/pym/repoman/checks.py
53 @@ -331,24 +331,6 @@ class EbuildQuotedA(LineCheck):
54 if match:
55 return "Quoted \"${A}\" on line: %d"
56
57 -class EprefixifyDefined(LineCheck):
58 - """ Check that prefix.eclass is inherited if needed"""
59 -
60 - repoman_check_name = 'eprefixify.defined'
61 -
62 - _eprefixify_re = re.compile(r'\beprefixify\b')
63 - _inherit_prefix_re = re.compile(r'^\s*inherit\s(.*\s)?prefix\b')
64 -
65 - def new(self, pkg):
66 - self._prefix_inherited = False
67 -
68 - def check(self, num, line):
69 - if self._eprefixify_re.search(line) is not None:
70 - if not self._prefix_inherited:
71 - return errors.EPREFIXIFY_MISSING_INHERIT
72 - elif self._inherit_prefix_re.search(line) is not None:
73 - self._prefix_inherited = True
74 -
75 class NoOffsetWithHelpers(LineCheck):
76 """ Check that the image location, the alternate root offset, and the
77 offset prefix (D, ROOT, ED, EROOT and EPREFIX) are not used with
78 @@ -464,43 +446,104 @@ class InheritDeprecated(LineCheck):
79 (eclass, replacement)
80 del self._indirect_deprecated
81
82 -class InheritAutotools(LineCheck):
83 - """
84 - Make sure appropriate functions are called in
85 - ebuilds that inherit autotools.eclass.
86 +class InheritEclass(LineCheck):
87 """
88 + Base class for checking for missing inherits, as well as excess inherits.
89
90 - repoman_check_name = 'inherit.autotools'
91 - _inherit_autotools_re = re.compile(r'^\s*inherit\s(.*\s)?autotools(\s|$)')
92 - _autotools_funcs = (
93 - "eaclocal", "eautoconf", "eautoheader",
94 - "eautomake", "eautoreconf", "_elibtoolize")
95 - _autotools_func_re = re.compile(r'\b(' + \
96 - "|".join(_autotools_funcs) + r')\b')
97 - # Exempt eclasses:
98 - # git - An EGIT_BOOTSTRAP variable may be used to call one of
99 - # the autotools functions.
100 - # subversion - An ESVN_BOOTSTRAP variable may be used to call one of
101 - # the autotools functions.
102 - _exempt_eclasses = frozenset(["git", "subversion"])
103 + Args:
104 + _eclass: Set to the name of your eclass.
105 + _funcs: A tuple of functions that this eclass provides.
106 + _comprehensive: Is the list of functions complete?
107 + _exempt_eclasses: If these eclasses are inherited, disable the missing
108 + inherit check.
109 + """
110
111 def new(self, pkg):
112 - self._inherit_autotools = None
113 - self._autotools_func_call = None
114 - self._disabled = self._exempt_eclasses.intersection(pkg.inherited)
115 + self.repoman_check_name = 'inherit.missing'
116 + self._inherit_re = re.compile(r'^\s*inherit\s(.*\s)?%s(\s|$)' % self._eclass)
117 + self._func_re = re.compile(r'\b(' + '|'.join(self._funcs) + r')\b')
118 + # We can't use pkg.inherited because that tells us all the eclass that
119 + # have been inherited and not just the ones we inherit directly.
120 + self._inherit = False
121 + self._func_call = False
122 + if '_exempt_eclasses' in dir(self):
123 + self._disabled = self._exempt_eclasses.intersection(pkg.inherited)
124 + else:
125 + self._disabled = False
126
127 def check(self, num, line):
128 - if self._disabled:
129 - return
130 - if self._inherit_autotools is None:
131 - self._inherit_autotools = self._inherit_autotools_re.match(line)
132 - if self._inherit_autotools is not None and \
133 - self._autotools_func_call is None:
134 - self._autotools_func_call = self._autotools_func_re.search(line)
135 + if not self._inherit:
136 + self._inherit = self._inherit_re.match(line)
137 + if not self._inherit:
138 + if self._disabled:
139 + return
140 + s = self._func_re.search(line)
141 + if s:
142 + self._func_call = True
143 + return '%s.eclass is not inherited, but "%s" found at line: %s' % \
144 + (self._eclass, s.group(0), '%d')
145 + elif not self._func_call:
146 + self._func_call = self._func_re.search(line)
147
148 def end(self):
149 - if self._inherit_autotools and self._autotools_func_call is None:
150 - yield 'no eauto* function called'
151 + if self._comprehensive and self._inherit and not self._func_call:
152 + self.repoman_check_name = 'inherit.unused'
153 + yield 'no function called from %s.eclass; please drop' % self._eclass
154 +
155 +class InheritAutotools(InheritEclass):
156 + _eclass = 'autotools'
157 + _funcs = (
158 + 'eaclocal', 'eautoconf', 'eautoheader',
159 + 'eautomake', 'eautoreconf', '_elibtoolize',
160 + 'eautopoint'
161 + )
162 + _comprehensive = True
163 +
164 + # Exempt eclasses:
165 + # git - An EGIT_BOOTSTRAP variable may be used to call one of
166 + # the autotools functions.
167 + # subversion - An ESVN_BOOTSTRAP variable may be used to call one of
168 + # the autotools functions.
169 + _exempt_eclasses = frozenset(['git', 'subversion'])
170 +
171 +class InheritEutils(InheritEclass):
172 + _eclass = 'eutils'
173 + _funcs = (
174 + 'estack_push', 'estack_pop', 'eshopts_push', 'eshopts_pop',
175 + 'eumask_push', 'eumask_pop', 'epatch', 'epatch_user',
176 + 'emktemp', 'edos2unix', 'in_iuse', 'use_if_iuse', 'usex',
177 + 'makeopts_jobs'
178 + )
179 + _comprehensive = False
180 +
181 +class InheritLibtool(InheritEclass):
182 + _eclass = 'libtool'
183 + _funcs = (
184 + 'elibtoolize',
185 + )
186 + _comprehensive = True
187 +
188 +class InheritPrefix(InheritEclass):
189 + _eclass = 'prefix'
190 + _funcs = (
191 + 'eprefixify',
192 + )
193 + _comprehensive = True
194 +
195 +class InheritToolchainFuncs(InheritEclass):
196 + _eclass = 'toolchain-funcs'
197 + _funcs = (
198 + 'gen_usr_ldscript',
199 + )
200 + _comprehensive = True
201 +
202 +class InheritUser(InheritEclass):
203 + _eclass = 'user'
204 + _funcs = (
205 + 'enewuser', 'enewgroup',
206 + 'egetent', 'egethome', 'egetshell'
207 + )
208 + _comprehensive = True
209
210 class IUseUndefined(LineCheck):
211 """
212 @@ -679,8 +722,10 @@ _constant_checks = tuple((c() for c in (
213 EbuildHeader, EbuildWhitespace, EbuildBlankLine, EbuildQuote,
214 EbuildAssignment, Eapi3EbuildAssignment, EbuildUselessDodoc,
215 EbuildUselessCdS, EbuildNestedDie,
216 - EbuildPatches, EbuildQuotedA, EapiDefinition, EprefixifyDefined,
217 - ImplicitRuntimeDeps, InheritAutotools, InheritDeprecated, IUseUndefined,
218 + EbuildPatches, EbuildQuotedA, EapiDefinition,
219 + ImplicitRuntimeDeps, InheritAutotools, InheritDeprecated, InheritEutils,
220 + InheritLibtool, InheritPrefix, InheritToolchainFuncs, InheritUser,
221 + IUseUndefined,
222 EMakeParallelDisabled, EMakeParallelDisabledViaMAKEOPTS, NoAsNeeded,
223 DeprecatedBindnowFlags, SrcUnpackPatches, WantAutoDefaultValue,
224 SrcCompileEconf, Eapi3DeprecatedFuncs, NoOffsetWithHelpers,
225 diff --git a/pym/repoman/errors.py b/pym/repoman/errors.py
226 index 3209243..c515502 100644
227 --- a/pym/repoman/errors.py
228 +++ b/pym/repoman/errors.py
229 @@ -19,7 +19,6 @@ EAPI_DEFINED_AFTER_INHERIT = 'EAPI defined after inherit on line: %d'
230 NO_AS_NEEDED = 'Upstream asneeded linking bug (no-as-needed on line: %d)'
231 PRESERVE_OLD_LIB = 'Upstream ABI change workaround on line: %d'
232 BUILT_WITH_USE = 'built_with_use on line: %d'
233 -EPREFIXIFY_MISSING_INHERIT = "prefix.eclass is not inherited, but eprefixify is used on line: %d"
234 NO_OFFSET_WITH_HELPERS = "Helper function is used with D, ROOT, ED, EROOT or EPREFIX on line :%d"
235 SANDBOX_ADDPREDICT = 'Ebuild calls addpredict on line: %d'
236 USEQ_ERROR = 'Ebuild calls deprecated useq function on line: %d'
237 --
238 1.7.8.6

Replies