Gentoo Archives: gentoo-commits

From: Matt Turner <mattst88@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: repoman/lib/repoman/modules/linechecks/depend/, repoman/lib/repoman/modules/, ...
Date: Mon, 02 May 2022 18:45:32
Message-Id: 1651517091.3ec97d8f0cd427b7b9874b05f55d1aec5a1df8b0.mattst88@gentoo
1 commit: 3ec97d8f0cd427b7b9874b05f55d1aec5a1df8b0
2 Author: Matt Turner <mattst88 <AT> gentoo <DOT> org>
3 AuthorDate: Mon Feb 21 20:59:34 2022 +0000
4 Commit: Matt Turner <mattst88 <AT> gentoo <DOT> org>
5 CommitDate: Mon May 2 18:44:51 2022 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=3ec97d8f
7
8 repoman: Remove
9
10 RepoMan sez: So long and thanks for all the fish! I'll be enjoying my
11 retirement now. Haven't I done enough to deserve that?
12
13 Bug: https://bugs.gentoo.org/835013
14 Signed-off-by: Matt Turner <mattst88 <AT> gentoo.org>
15
16 .github/workflows/black.yml | 2 +-
17 .gitignore | 2 -
18 cnf/make.globals | 2 +-
19 lib/_emerge/Package.py | 5 +-
20 lib/_emerge/depgraph.py | 2 +-
21 lib/portage/dbapi/__init__.py | 12 -
22 lib/portage/dbapi/porttree.py | 6 +-
23 .../test_lazy_import_portage_baseline.py | 2 +-
24 lib/portage/tests/resolver/ResolverPlayground.py | 10 -
25 man/ebuild.5 | 6 +-
26 man/make.conf.5 | 8 +-
27 man/portage.5 | 42 +-
28 repoman/.repoman_not_installed | 0
29 repoman/MANIFEST.in | 4 -
30 repoman/NEWS | 14 -
31 repoman/README | 49 --
32 repoman/RELEASE-NOTES | 213 ------
33 repoman/TEST-NOTES | 45 --
34 repoman/bin/repoman | 56 --
35 repoman/cnf/linechecks/linechecks.yaml | 34 -
36 repoman/cnf/metadata.xsd | 548 --------------
37 repoman/cnf/qa_data/qa_data.yaml | 139 ----
38 repoman/cnf/repository/linechecks.yaml | 248 ------
39 repoman/cnf/repository/qa_data.yaml | 163 ----
40 repoman/cnf/repository/repository.yaml | 76 --
41 repoman/lib/repoman/__init__.py | 103 ---
42 repoman/lib/repoman/_portage.py | 26 -
43 repoman/lib/repoman/_subprocess.py | 58 --
44 repoman/lib/repoman/actions.py | 828 ---------------------
45 repoman/lib/repoman/argparser.py | 388 ----------
46 repoman/lib/repoman/check_missingslot.py | 39 -
47 repoman/lib/repoman/checks/__init__.py | 0
48 repoman/lib/repoman/config.py | 172 -----
49 repoman/lib/repoman/copyrights.py | 143 ----
50 repoman/lib/repoman/errors.py | 21 -
51 repoman/lib/repoman/gpg.py | 73 --
52 repoman/lib/repoman/main.py | 255 -------
53 repoman/lib/repoman/metadata.py | 89 ---
54 repoman/lib/repoman/modules/__init__.py | 0
55 repoman/lib/repoman/modules/commit/__init__.py | 0
56 repoman/lib/repoman/modules/commit/manifest.py | 122 ---
57 repoman/lib/repoman/modules/commit/repochecks.py | 44 --
58 repoman/lib/repoman/modules/linechecks/__init__.py | 0
59 .../modules/linechecks/assignment/__init__.py | 27 -
60 .../modules/linechecks/assignment/assignment.py | 38 -
61 repoman/lib/repoman/modules/linechecks/base.py | 115 ---
62 repoman/lib/repoman/modules/linechecks/config.py | 149 ----
63 .../lib/repoman/modules/linechecks/controller.py | 164 ----
64 .../repoman/modules/linechecks/depend/__init__.py | 21 -
65 .../repoman/modules/linechecks/depend/implicit.py | 38 -
66 .../modules/linechecks/deprecated/__init__.py | 46 --
67 .../modules/linechecks/deprecated/deprecated.py | 35 -
68 .../modules/linechecks/deprecated/inherit.py | 67 --
69 .../lib/repoman/modules/linechecks/do/__init__.py | 21 -
70 repoman/lib/repoman/modules/linechecks/do/dosym.py | 20 -
71 .../repoman/modules/linechecks/eapi/__init__.py | 51 --
72 .../lib/repoman/modules/linechecks/eapi/checks.py | 79 --
73 .../repoman/modules/linechecks/eapi/definition.py | 35 -
74 .../repoman/modules/linechecks/emake/__init__.py | 27 -
75 .../lib/repoman/modules/linechecks/emake/emake.py | 25 -
76 .../modules/linechecks/gentoo_header/__init__.py | 21 -
77 .../modules/linechecks/gentoo_header/header.py | 56 --
78 .../repoman/modules/linechecks/helpers/__init__.py | 21 -
79 .../repoman/modules/linechecks/helpers/offset.py | 21 -
80 .../repoman/modules/linechecks/nested/__init__.py | 21 -
81 .../repoman/modules/linechecks/nested/nested.py | 14 -
82 .../repoman/modules/linechecks/nested/nesteddie.py | 9 -
83 .../repoman/modules/linechecks/patches/__init__.py | 21 -
84 .../repoman/modules/linechecks/patches/patches.py | 22 -
85 .../repoman/modules/linechecks/phases/__init__.py | 40 -
86 .../lib/repoman/modules/linechecks/phases/phase.py | 188 -----
87 .../repoman/modules/linechecks/portage/__init__.py | 27 -
88 .../repoman/modules/linechecks/portage/internal.py | 32 -
89 .../repoman/modules/linechecks/quotes/__init__.py | 27 -
90 .../repoman/modules/linechecks/quotes/quoteda.py | 15 -
91 .../repoman/modules/linechecks/quotes/quotes.py | 92 ---
92 .../lib/repoman/modules/linechecks/uri/__init__.py | 21 -
93 repoman/lib/repoman/modules/linechecks/uri/uri.py | 30 -
94 .../lib/repoman/modules/linechecks/use/__init__.py | 21 -
95 .../repoman/modules/linechecks/use/builtwith.py | 9 -
96 .../repoman/modules/linechecks/useless/__init__.py | 27 -
97 .../lib/repoman/modules/linechecks/useless/cd.py | 24 -
98 .../repoman/modules/linechecks/useless/dodoc.py | 17 -
99 .../modules/linechecks/whitespace/__init__.py | 27 -
100 .../repoman/modules/linechecks/whitespace/blank.py | 24 -
101 .../modules/linechecks/whitespace/whitespace.py | 20 -
102 .../modules/linechecks/workaround/__init__.py | 21 -
103 .../modules/linechecks/workaround/workarounds.py | 11 -
104 repoman/lib/repoman/modules/scan/__init__.py | 0
105 .../lib/repoman/modules/scan/depend/__init__.py | 43 --
106 .../repoman/modules/scan/depend/_depend_checks.py | 260 -------
107 .../lib/repoman/modules/scan/depend/_gen_arches.py | 67 --
108 repoman/lib/repoman/modules/scan/depend/profile.py | 427 -----------
109 .../repoman/modules/scan/directories/__init__.py | 53 --
110 .../lib/repoman/modules/scan/directories/files.py | 99 ---
111 .../lib/repoman/modules/scan/directories/mtime.py | 30 -
112 repoman/lib/repoman/modules/scan/eapi/__init__.py | 28 -
113 repoman/lib/repoman/modules/scan/eapi/eapi.py | 50 --
114 .../lib/repoman/modules/scan/ebuild/__init__.py | 66 --
115 repoman/lib/repoman/modules/scan/ebuild/ebuild.py | 263 -------
116 .../lib/repoman/modules/scan/ebuild/multicheck.py | 62 --
117 .../lib/repoman/modules/scan/eclasses/__init__.py | 49 --
118 repoman/lib/repoman/modules/scan/eclasses/live.py | 77 --
119 repoman/lib/repoman/modules/scan/eclasses/ruby.py | 49 --
120 repoman/lib/repoman/modules/scan/fetch/__init__.py | 37 -
121 repoman/lib/repoman/modules/scan/fetch/fetches.py | 205 -----
122 .../lib/repoman/modules/scan/keywords/__init__.py | 37 -
123 .../lib/repoman/modules/scan/keywords/keywords.py | 179 -----
124 .../lib/repoman/modules/scan/manifest/__init__.py | 34 -
125 .../lib/repoman/modules/scan/manifest/manifests.py | 56 --
126 .../lib/repoman/modules/scan/metadata/__init__.py | 89 ---
127 .../repoman/modules/scan/metadata/description.py | 44 --
128 .../modules/scan/metadata/ebuild_metadata.py | 84 ---
129 .../repoman/modules/scan/metadata/pkgmetadata.py | 221 ------
130 .../lib/repoman/modules/scan/metadata/restrict.py | 58 --
131 .../lib/repoman/modules/scan/metadata/use_flags.py | 103 ---
132 repoman/lib/repoman/modules/scan/module.py | 127 ----
133 .../lib/repoman/modules/scan/options/__init__.py | 28 -
134 .../lib/repoman/modules/scan/options/options.py | 27 -
135 repoman/lib/repoman/modules/scan/scan.py | 67 --
136 repoman/lib/repoman/modules/scan/scanbase.py | 79 --
137 repoman/lib/repoman/modules/vcs/None/__init__.py | 32 -
138 repoman/lib/repoman/modules/vcs/None/changes.py | 50 --
139 repoman/lib/repoman/modules/vcs/None/status.py | 52 --
140 repoman/lib/repoman/modules/vcs/__init__.py | 12 -
141 repoman/lib/repoman/modules/vcs/bzr/__init__.py | 32 -
142 repoman/lib/repoman/modules/vcs/bzr/changes.py | 77 --
143 repoman/lib/repoman/modules/vcs/bzr/status.py | 72 --
144 repoman/lib/repoman/modules/vcs/changes.py | 170 -----
145 repoman/lib/repoman/modules/vcs/cvs/__init__.py | 32 -
146 repoman/lib/repoman/modules/vcs/cvs/changes.py | 134 ----
147 repoman/lib/repoman/modules/vcs/cvs/status.py | 134 ----
148 repoman/lib/repoman/modules/vcs/git/__init__.py | 32 -
149 repoman/lib/repoman/modules/vcs/git/changes.py | 145 ----
150 repoman/lib/repoman/modules/vcs/git/status.py | 80 --
151 repoman/lib/repoman/modules/vcs/hg/__init__.py | 32 -
152 repoman/lib/repoman/modules/vcs/hg/changes.py | 109 ---
153 repoman/lib/repoman/modules/vcs/hg/status.py | 68 --
154 repoman/lib/repoman/modules/vcs/settings.py | 113 ---
155 repoman/lib/repoman/modules/vcs/svn/__init__.py | 32 -
156 repoman/lib/repoman/modules/vcs/svn/changes.py | 156 ----
157 repoman/lib/repoman/modules/vcs/svn/status.py | 151 ----
158 repoman/lib/repoman/modules/vcs/vcs.py | 145 ----
159 repoman/lib/repoman/profile.py | 94 ---
160 repoman/lib/repoman/qa_data.py | 210 ------
161 repoman/lib/repoman/qa_tracker.py | 46 --
162 repoman/lib/repoman/repos.py | 377 ----------
163 repoman/lib/repoman/scanner.py | 484 ------------
164 .../06B3A311BD775C280D22A9305D90EA06352177F6.rev | 37 -
165 .../8DEDA2CDED49C8809287B89D8812797DDF1DD192.rev | 37 -
166 .../273B030399E7BEA66A9AD42216DE7CA17BA5D42E.key | Bin 2055 -> 0 bytes
167 .../C99796FB85B0C3DF03314A11B5850C51167D6282.key | Bin 2055 -> 0 bytes
168 repoman/lib/repoman/tests/.gnupg/pubring.kbx | Bin 2774 -> 0 bytes
169 repoman/lib/repoman/tests/.gnupg/trustdb.gpg | Bin 1360 -> 0 bytes
170 repoman/lib/repoman/tests/__init__.py | 328 --------
171 repoman/lib/repoman/tests/__test__.py | 0
172 repoman/lib/repoman/tests/changelog/__init__.py | 2 -
173 repoman/lib/repoman/tests/changelog/__test__.py | 0
174 .../lib/repoman/tests/changelog/test_echangelog.py | 169 -----
175 repoman/lib/repoman/tests/commit/__init__.py | 2 -
176 repoman/lib/repoman/tests/commit/__test__.py | 0
177 repoman/lib/repoman/tests/commit/test_commitmsg.py | 155 ----
178 repoman/lib/repoman/tests/runTests.py | 85 ---
179 repoman/lib/repoman/tests/simple/__init__.py | 2 -
180 repoman/lib/repoman/tests/simple/__test__.py | 0
181 repoman/lib/repoman/tests/simple/test_simple.py | 512 -------------
182 repoman/lib/repoman/utilities.py | 590 ---------------
183 repoman/man/repoman.1 | 478 ------------
184 repoman/runtests | 189 -----
185 repoman/setup.py | 523 -------------
186 tox.ini | 3 +-
187 171 files changed, 32 insertions(+), 15135 deletions(-)
188
189 diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml
190 index d3c3fa3e1..1d6f1378c 100644
191 --- a/.github/workflows/black.yml
192 +++ b/.github/workflows/black.yml
193 @@ -11,7 +11,7 @@ jobs:
194 id: stragglers
195 run: |
196 echo "::set-output name=missed::$(
197 - find bin repoman runtests -type f -not -name '*.py' -not -name '*.sh' | \
198 + find bin runtests -type f -not -name '*.py' -not -name '*.sh' | \
199 xargs grep -l '#!/usr/bin/env python' | tr $'\n' ' ')"
200 - uses: psf/black@stable
201 with:
202
203 diff --git a/.gitignore b/.gitignore
204 index a9f772c4c..c04a22a0b 100644
205 --- a/.gitignore
206 +++ b/.gitignore
207 @@ -6,5 +6,3 @@ __pycache__/
208 /tags
209 /.tox/
210 setup.cfg
211 -
212 -repoman/build
213
214 diff --git a/cnf/make.globals b/cnf/make.globals
215 index f42cffe8b..f951bb317 100644
216 --- a/cnf/make.globals
217 +++ b/cnf/make.globals
218 @@ -147,7 +147,7 @@ PORTAGE_ELOG_MAILURI="root"
219 PORTAGE_ELOG_MAILSUBJECT="[portage] ebuild log for \${PACKAGE} on \${HOST}"
220 PORTAGE_ELOG_MAILFROM="portage@localhost"
221
222 -# Signing command used by repoman
223 +# Signing command used by egencache
224 PORTAGE_GPG_SIGNING_COMMAND="gpg --sign --digest-algo SHA256 --clearsign --yes --default-key \"\${PORTAGE_GPG_KEY}\" --homedir \"\${PORTAGE_GPG_DIR}\" \"\${FILE}\""
225
226 # btrfs.* attributes are irrelevant, see bug #527636.
227
228 diff --git a/lib/_emerge/Package.py b/lib/_emerge/Package.py
229 index db42d836e..a19904113 100644
230 --- a/lib/_emerge/Package.py
231 +++ b/lib/_emerge/Package.py
232 @@ -136,10 +136,7 @@ class Package(Task):
233 # sync metadata with validated repo (may be UNKNOWN_REPO)
234 self._metadata["repository"] = self.cpv.repo
235
236 - if self.root_config.settings.local_config:
237 - implicit_match = db._iuse_implicit_cnstr(self.cpv, self._metadata)
238 - else:
239 - implicit_match = db._repoman_iuse_implicit_cnstr(self.cpv, self._metadata)
240 + implicit_match = db._iuse_implicit_cnstr(self.cpv, self._metadata)
241 self.iuse = self._iuse(
242 self, self._metadata["IUSE"].split(), implicit_match, self.eapi
243 )
244
245 diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
246 index c3f872c43..79fa1f3df 100644
247 --- a/lib/_emerge/depgraph.py
248 +++ b/lib/_emerge/depgraph.py
249 @@ -9048,7 +9048,7 @@ class depgraph:
250 ):
251 # Make sure that portage always has all of its
252 # RDEPENDs installed first, but ignore uninstalls
253 - # (these occur when new portage blocks older repoman).
254 + # (these occur when new portage blocks an older package version).
255 return False
256 selected_nodes.add(node)
257 for child in mygraph.child_nodes(node, ignore_priority=ignore_priority):
258
259 diff --git a/lib/portage/dbapi/__init__.py b/lib/portage/dbapi/__init__.py
260 index 43c3283e8..f52329c90 100644
261 --- a/lib/portage/dbapi/__init__.py
262 +++ b/lib/portage/dbapi/__init__.py
263 @@ -219,18 +219,6 @@ class dbapi:
264
265 yield cpv
266
267 - def _repoman_iuse_implicit_cnstr(self, pkg, metadata):
268 - """
269 - In repoman's version of _iuse_implicit_cnstr, account for modifications
270 - of the self.settings reference between calls.
271 - """
272 - eapi_attrs = _get_eapi_attrs(metadata["EAPI"])
273 - if eapi_attrs.iuse_effective:
274 - iuse_implicit_match = lambda flag: self.settings._iuse_effective_match(flag)
275 - else:
276 - iuse_implicit_match = lambda flag: self.settings._iuse_implicit_match(flag)
277 - return iuse_implicit_match
278 -
279 def _iuse_implicit_cnstr(self, pkg, metadata):
280 """
281 Construct a callable that checks if a given USE flag should
282
283 diff --git a/lib/portage/dbapi/porttree.py b/lib/portage/dbapi/porttree.py
284 index 93f3fee2f..cd919ba31 100644
285 --- a/lib/portage/dbapi/porttree.py
286 +++ b/lib/portage/dbapi/porttree.py
287 @@ -359,9 +359,9 @@ class portdbapi(dbapi):
288
289 def _set_porttrees(self, porttrees):
290 """
291 - Consumers, such as repoman and emirrordist, may modify the porttrees
292 - attribute in order to modify the effective set of repositories for
293 - all portdbapi operations.
294 + Consumers, such as emirrordist, may modify the porttrees attribute in
295 + order to modify the effective set of repositories for all portdbapi
296 + operations.
297
298 @param porttrees: list of repo locations, in ascending order by
299 repo priority
300
301 diff --git a/lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py b/lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py
302 index cf239240c..8cc248db9 100644
303 --- a/lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py
304 +++ b/lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py
305 @@ -14,7 +14,7 @@ from _emerge.SpawnProcess import SpawnProcess
306
307 class LazyImportPortageBaselineTestCase(TestCase):
308
309 - _module_re = re.compile(r"^(portage|repoman|_emerge)\.")
310 + _module_re = re.compile(r"^(portage|_emerge)\.")
311
312 _baseline_imports = frozenset(
313 [
314
315 diff --git a/lib/portage/tests/resolver/ResolverPlayground.py b/lib/portage/tests/resolver/ResolverPlayground.py
316 index 8811354b5..ec69ee068 100644
317 --- a/lib/portage/tests/resolver/ResolverPlayground.py
318 +++ b/lib/portage/tests/resolver/ResolverPlayground.py
319 @@ -35,11 +35,6 @@ from _emerge.DependencyArg import DependencyArg
320 from _emerge.depgraph import backtrack_depgraph
321 from _emerge.RootConfig import RootConfig
322
323 -try:
324 - from repoman.tests import cnf_path_repoman
325 -except ImportError:
326 - cnf_path_repoman = None
327 -
328
329 class ResolverPlayground:
330 """
331 @@ -664,11 +659,6 @@ class ResolverPlayground:
332 for line in lines:
333 f.write("%s\n" % line)
334
335 - if cnf_path_repoman is not None:
336 - # Create /usr/share/repoman
337 - repoman_share_dir = os.path.join(self.eroot, "usr", "share", "repoman")
338 - os.symlink(cnf_path_repoman, repoman_share_dir)
339 -
340 def _create_world(self, world, world_sets):
341 # Create /var/lib/portage/world
342 var_lib_portage = os.path.join(self.eroot, "var", "lib", "portage")
343
344 diff --git a/man/ebuild.5 b/man/ebuild.5
345 index 3a3982738..8402d667b 100644
346 --- a/man/ebuild.5
347 +++ b/man/ebuild.5
348 @@ -554,9 +554,9 @@ EAPI value then it will mask the package and refuse to perform any
349 operations with it since this means that a newer version of portage
350 needs to be installed first. For maximum backward compatiblity, a
351 package should conform to the lowest possible EAPI. Note that anyone
352 -who uses the \fBebuild\fR(1) and \fBrepoman\fR(1) commands with this
353 -package will be required to have a version of portage that recognizes
354 -the EAPI to which this package conforms.
355 +who uses the \fBebuild\fR(1) command with this package will be
356 +required to have a version of portage that recognizes the EAPI to
357 +which this package conforms.
358 .TP
359 .B SRC_URI\fR = \fI"https://example.com/path/${P}.tar.gz"
360 Contains a list of URIs for the required source files. It can contain
361
362 diff --git a/man/make.conf.5 b/man/make.conf.5
363 index fc4a018c5..8c77eda2e 100644
364 --- a/man/make.conf.5
365 +++ b/man/make.conf.5
366 @@ -457,9 +457,9 @@ enabled by default.
367 .TP
368 .B digest
369 Autogenerate digests for packages when running the
370 -\fBemerge\fR(1), \fBebuild\fR(1), or \fBrepoman\fR(1) commands. If
371 -the \fIassume\-digests\fR feature is also enabled then existing SRC_URI digests
372 -will be reused whenever they are available.
373 +\fBemerge\fR(1) or \fBebuild\fR(1) commands. If the
374 +\fIassume\-digests\fR feature is also enabled then existing SRC_URI
375 +digests will be reused whenever they are available.
376 .TP
377 .B distcc
378 Enable portage support for the distcc package.
379 @@ -1051,7 +1051,7 @@ when \fBsign\fR is in \fBFEATURES\fR. In order to sign commits with
380 to be configured by \fI`git config user.signingkey key_id`\fR.
381 .TP
382 .B PORTAGE_GPG_SIGNING_COMMAND
383 -The command used by \fBrepoman\fR(1) to sign manifests when \fBsign\fR is
384 +The command used by \fBegencache\fR(1) to sign manifests when \fBsign\fR is
385 in \fBFEATURES\fR.
386 .TP
387 \fBPORTAGE_GRPNAME\fR = \fI[group]\fR
388
389 diff --git a/man/portage.5 b/man/portage.5
390 index 50f20454c..f42564664 100644
391 --- a/man/portage.5
392 +++ b/man/portage.5
393 @@ -944,14 +944,13 @@ Setting this attribute is generally not recommended since resulting changes
394 in eclass inheritance may trigger performance issues due to invalidation
395 of metadata cache.
396 .br
397 -When 'force = eclass\-overrides' attribute is not set, \fBegencache\fR(1),
398 -\fBemirrordist\fR(1) and \fBrepoman\fR(1) ignore this attribute,
399 -since operations performed by these tools are inherently
400 -\fBnot\fR \fIsite\-specific\fR.
401 +When 'force = eclass\-overrides' attribute is not set, \fBegencache\fR(1)
402 +and \fBemirrordist\fR(1) ignore this attribute, since operations
403 +performed by these tools are inherently \fBnot\fR \fIsite\-specific\fR.
404 .TP
405 .B force
406 Specifies names of attributes, which should be forcefully respected by
407 -\fBegencache\fR(1), \fBemirrordist\fR(1) and \fBrepoman\fR(1).
408 +\fBegencache\fR(1) and \fBemirrordist\fR(1).
409 .br
410 Valid values: aliases, eclass\-overrides, masters
411 .RE
412 @@ -966,10 +965,9 @@ Setting this attribute is generally not recommended since resulting changes
413 in eclass inheritance may trigger performance issues due to invalidation
414 of metadata cache.
415 .br
416 -When 'force = aliases' attribute is not set, \fBegencache\fR(1),
417 -\fBemirrordist\fR(1) and \fBrepoman\fR(1) ignore this attribute,
418 -since operations performed by these tools are inherently
419 -\fBnot\fR \fIsite\-specific\fR.
420 +When 'force = aliases' attribute is not set, \fBegencache\fR(1) and
421 +\fBemirrordist\fR(1) ignore this attribute, since operations performed by
422 +these tools are inherently \fBnot\fR \fIsite\-specific\fR.
423 .TP
424 .B auto\-sync = yes|no|true|false
425 This setting determines if the repo will be synced during "\fBemerge \-\-sync\fR" or
426 @@ -990,14 +988,13 @@ Setting this attribute is generally not recommended since resulting changes
427 in eclass inheritance may trigger performance issues due to invalidation
428 of metadata cache.
429 .br
430 -When 'force = eclass\-overrides' attribute is not set, \fBegencache\fR(1),
431 -\fBemirrordist\fR(1) and \fBrepoman\fR(1) ignore this attribute,
432 -since operations performed by these tools are inherently
433 -\fBnot\fR \fIsite\-specific\fR.
434 +When 'force = eclass\-overrides' attribute is not set, \fBegencache\fR(1)
435 +and \fBemirrordist\fR(1) ignore this attribute, since operations
436 +performed by these tools are inherently \fBnot\fR \fIsite\-specific\fR.
437 .TP
438 .B force
439 Specifies names of attributes, which should be forcefully respected by
440 -\fBegencache\fR(1), \fBemirrordist\fR(1) and \fBrepoman\fR(1).
441 +\fBegencache\fR(1) and \fBemirrordist\fR(1).
442 .br
443 Valid values: aliases, eclass\-overrides, masters
444 .TP
445 @@ -1011,10 +1008,9 @@ Setting this attribute is generally not recommended since resulting changes
446 in eclass inheritance may trigger performance issues due to invalidation
447 of metadata cache.
448 .br
449 -When 'force = masters' attribute is not set, \fBegencache\fR(1),
450 -\fBemirrordist\fR(1) and \fBrepoman\fR(1) ignore this attribute,
451 -since operations performed by these tools are inherently
452 -\fBnot\fR \fIsite\-specific\fR.
453 +When 'force = masters' attribute is not set, \fBegencache\fR(1) and
454 +\fBemirrordist\fR(1) ignore this attribute, since operations performed by
455 +these tools are inherently \fBnot\fR \fIsite\-specific\fR.
456 .TP
457 .B priority
458 Specifies priority of given repository.
459 @@ -1423,7 +1419,7 @@ Specifies information about the repository layout.
460 \fISite-specific\fR overrides to \fBlayout.conf\fR settings may be specified in
461 \fB/etc/portage/repos.conf\fR.
462 Settings in \fBrepos.conf\fR take precedence over settings in
463 -\fBlayout.conf\fR, except tools such as \fBrepoman\fR(1) and \fBegencache\fR(1)
464 +\fBlayout.conf\fR, except tools such as \fBegencache\fR(1)
465 ignore "aliases", "eclass-overrides" and "masters" attributes set in
466 \fBrepos.conf\fR since their operations are inherently \fBnot\fR
467 \fIsite\-specific\fR.
468 @@ -1485,9 +1481,6 @@ here are not present in the Manifest, Portage will refetch all distfiles
469 and update the respective entries to include them. Must be a subset
470 of manifest\-hashes. If not specified, defaults to all manifest\-hashes.
471 .TP
472 -.BR update\-changelog " = [true|" false "]"
473 -The default setting for repoman's --echangelog option.
474 -.TP
475 .BR cache\-formats " = [pms] [md5-dict]"
476 The cache formats supported in the metadata tree. There is the old "pms" format
477 and the newer/faster "md5-dict" format. Default is to detect dirs.
478 @@ -1553,9 +1546,6 @@ use\-manifests = strict
479 # customize the set of hashes generated for Manifest entries
480 manifest\-hashes = SHA256 SHA512 WHIRLPOOL
481
482 -# indicate that this repo enables repoman's --echangelog=y option automatically
483 -update\-changelog = false
484 -
485 # indicate that this repo contains the md5-dict cache format,
486 # which may be generated by egencache(1)
487 cache\-formats = md5-dict
488 @@ -1700,7 +1690,7 @@ package has been masked and WHO is doing the masking.
489 .TP
490 .BR profiles.desc
491 List all the current stable and development profiles. If a profile is listed
492 -here, then it will be checked by repoman.
493 +here, then it will be checked by pkgcheck.
494 .I Format:
495 .nf
496 \- comments begin with # (no inline comments)
497
498 diff --git a/repoman/.repoman_not_installed b/repoman/.repoman_not_installed
499 deleted file mode 100644
500 index e69de29bb..000000000
501
502 diff --git a/repoman/MANIFEST.in b/repoman/MANIFEST.in
503 deleted file mode 100644
504 index d9ef2aee0..000000000
505 --- a/repoman/MANIFEST.in
506 +++ /dev/null
507 @@ -1,4 +0,0 @@
508 -
509 -# for the tests
510 -include cnf/metadata.xsd
511 -include .repoman_not_installed
512
513 diff --git a/repoman/NEWS b/repoman/NEWS
514 deleted file mode 100644
515 index c8d22d024..000000000
516 --- a/repoman/NEWS
517 +++ /dev/null
518 @@ -1,14 +0,0 @@
519 -News (mainly features/major bug fixes)
520 -
521 -repoman 2.3.8
522 -=====================
523 -- Support for plugin module systems, see
524 - https://wiki.gentoo.org/wiki/Project:Portage/Repoman-Module-specs
525 -
526 -repoman 2.3.0
527 -=====================
528 -- Final release
529 -
530 -repoman 2.3.0_rc1
531 -=====================
532 -- First test release
533
534 diff --git a/repoman/README b/repoman/README
535 deleted file mode 100644
536 index f0976e841..000000000
537 --- a/repoman/README
538 +++ /dev/null
539 @@ -1,49 +0,0 @@
540 -About Portage
541 -=============
542 -
543 -Portage is a package management system based on ports collections. The
544 -Package Manager Specification Project (PMS) standardises and documents
545 -the behaviour of Portage so that ebuild repositories can be used by other
546 -package managers.
547 -
548 -
549 -Dependencies
550 -============
551 -
552 -Python and Bash should be the only hard dependencies. Python 2.7 is the
553 -minimum supported version.
554 -
555 -
556 -Licensing and Legalese
557 -=======================
558 -
559 -Portage is free software; you can redistribute it and/or
560 -modify it under the terms of the GNU General Public License
561 -version 2 as published by the Free Software Foundation.
562 -
563 -Portage is distributed in the hope that it will be useful,
564 -but WITHOUT ANY WARRANTY; without even the implied warranty of
565 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
566 -GNU General Public License for more details.
567 -
568 -You should have received a copy of the GNU General Public License
569 -along with Portage; if not, write to the Free Software
570 -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
571 -02110-1301, USA.
572 -
573 -
574 -More information
575 -================
576 -
577 --DEVELOPING contains some code guidelines.
578 --LICENSE contains the GNU General Public License version 2.
579 --NEWS contains new features/major bug fixes for each version.
580 --RELEASE NOTES contains mainly upgrade information for each version.
581 --TEST-NOTES contains Portage unit test information.
582 -
583 -
584 -Links
585 -=====
586 -Gentoo project page: <https://wiki.gentoo.org/wiki/Project:Portage>
587 -PMS: <https://dev.gentoo.org/~ulm/pms/head/pms.html>
588 -PMS git repo: <https://gitweb.gentoo.org/proj/pms.git/>
589
590 diff --git a/repoman/RELEASE-NOTES b/repoman/RELEASE-NOTES
591 deleted file mode 100644
592 index df34803cc..000000000
593 --- a/repoman/RELEASE-NOTES
594 +++ /dev/null
595 @@ -1,213 +0,0 @@
596 -Release Notes; upgrade information mainly.
597 -Features/major bugfixes are listed in NEWS
598 -
599 -repoman-3.0.3
600 -==================================
601 -* Bug Fixes:
602 - - Bug 608664 variable.phase check like pkgcheck VariableScopeCheck
603 - - Bug 692486 Change message for preserve_old_lib
604 -
605 -repoman-3.0.2
606 -==================================
607 -* Bug Fixes:
608 - - Bug 748144 Make file.size fatal for files larger than 20 KiB
609 -
610 -repoman-3.0.1
611 -==================================
612 -* Bug Fixes:
613 - - Bug 737698 Update repoman for compatibility with portage-3.0.4.
614 -
615 -repoman-3.0.0
616 -==================================
617 -* Bug Fixes:
618 - - Bug 448462 Add --jobs and --load-average options which allow
619 - dependency checks for multiple profiles to run in parallel.
620 -
621 -repoman-2.3.23
622 -==================================
623 -* Bug Fixes:
624 - - Bug 637824 Deprecate netsurf.eclass
625 -
626 -repoman-2.3.22
627 -==================================
628 -* Bug Fixes:
629 - - Bug 712106 only stage changes in index for commit mode
630 -
631 -repoman-2.3.21
632 -==================================
633 -* Bug Fixes:
634 - - Bug 712106 prevent spurious copyright header updates
635 -
636 -
637 -repoman-2.3.20
638 -==================================
639 -* Bug Fixes:
640 - - Bug 541076 repoman commit: ignore unadded hidden files
641 - - Bug 702100 repoman: support profiles/package.deprecated
642 -
643 -
644 -repoman-2.3.19
645 -==================================
646 -* Bug Fixes:
647 - - Bug 667432 Rename DCO_SIGNED_OFF_BY config variable to SIGNED_OFF_BY.
648 - - Bug 700456 Add --include-profiles=PROFILES
649 -
650 -
651 -repoman-2.3.18
652 -==================================
653 -* Bug Fixes:
654 - - Bug 690786 Support metadata/layout.conf restrict-allowed
655 - - Bug 699514 Detect dosym absolute paths starting with ${D}, ${ED} etc.
656 - - Bug 699508 Fix unsafe string interpolation.
657 -
658 -
659 -repoman-2.3.17
660 -==================================
661 -* Bug Fixes:
662 - - Bug 233589 Support PROPERTIES="live"
663 -
664 -
665 -repoman-2.3.16
666 -==================================
667 -* Bug Fixes:
668 - - Bug 687420 Allow empty LICENSE in acct-* packages for GLEP 81
669 -
670 -
671 -repoman-2.3.15
672 -==================================
673 -* Bug Fixes:
674 - - Bug 688278 Accept 'Gentoo Foundation' copyright for old ebuilds
675 -
676 -
677 -repoman-2.3.14
678 -==================================
679 -* Bug Fixes:
680 - - Bug 666330 Update for new copyright policy
681 -
682 -
683 -repoman-2.3.13
684 -==================================
685 -* Bug Fixes:
686 - - Bug 686074 report error for unknown arguments
687 -
688 -
689 -repoman-2.3.12
690 -==================================
691 -* Bug Fixes:
692 - - Bug 588752 fix exit code for manifest mode
693 -
694 -
695 -repoman-2.3.11
696 -==================================
697 -* Bug Fixes:
698 - - Bug 666330 support new 'Gentoo Authors' copyright policy and
699 - automatically apply the new policy when updating copyright headers.
700 - Earlier versions of repoman will report an ebuild.badheader warning
701 - for the new copyright headers. Users of earlier versions of repoman
702 - should be advised to simply ignore the ebuild.badheader warning, or
703 - else upgrade to the latest version of repoman.
704 -
705 -
706 -repoman-2.3.10
707 -==================================
708 -* Bug Fixes:
709 - - Bug 649482 warn about = deps without revision
710 - - Bug 660982 populate implicit IUSE for empty profile
711 -
712 -
713 -repoman-2.3.8
714 -==================================
715 -* The --experimental-repository-modules=<y|n> option enables a new
716 - plugin modules system:
717 - https://wiki.gentoo.org/wiki/Project:Portage/Repoman-Module-specs
718 -
719 -
720 -repoman-2.3.7
721 -==================================
722 -* Bug Fixes:
723 - - Bug 552720 allow https for metadata.dtd URI
724 -
725 -
726 -repoman-2.3.6
727 -==================================
728 -* Bug Fixes:
729 - - Bug 637460 Fix import paths for unit tests
730 -
731 -
732 -repoman-2.3.5
733 -==================================
734 -* Repository metadata/layout.conf supports manifest-required-hashes
735 - attribute (default value is SHA512).
736 -
737 -
738 -repoman-2.3.4
739 -==================================
740 -* Support two new options: --bug (-b) and --closes (-c)
741 -
742 -
743 -repoman-2.3.3
744 -==================================
745 -* Bug Fixes:
746 - - Bug 571546 Change how the tmp file for the commit msg is made
747 -* flag URIs using http:// when https:// is available
748 -* Add a check for relative dosym candidates
749 -* Make all shebangs prefix friendly
750 -* Mark ruby-2.0 as deprecated
751 -* Detect inconsistent metadata.xml indentation
752 -* Warn about dropped keywords only for latest in SLOT.
753 -
754 -
755 -repoman-2.3.2
756 -==================================
757 -* Bug Fixes:
758 - - Bug 544938 add dev-qt/linguist-tools to RDEPEND.suspect set
759 - - Bug 602002 make unused local USE flags an error
760 - - Bug 533554 add HOMEPAGE.missingurischeme check
761 - - Bug 610414 use regular expression to detect line continuations
762 - - Bug 610954 Warn about stale CVS keywords in ebuild header
763 - - Bug 611296 Don't update years in non-Gentoo copyright lines
764 -* Add virtual/linuxtv-dvb-headers to RDEPEND.suspect set
765 -* Add virtual/os-headers to RDEPEND.suspect set
766 -* Add gentoo to remote-id type
767 -* Define long for python3 Fixes: 006b168c1bb6
768 -* Commit footer improvements
769 -* Check for empty files in filesdir
770 -* Deprecate gpe.eclass, confutils.eclass
771 -
772 -
773 -repoman-2.3.1
774 -==================================
775 -* Bug Fixes:
776 - - Bug 586864 skip QA checks in manifest mode
777 - - Bug 591184 fix erroneous LICENSE.syntax
778 - - use https to fetch metadata.xsd
779 - - update links to https
780 - - Make LIVEVCS.* checks fatal
781 - - fix _depend_checks baddepsyntax accounting
782 - - Fix commitmessage assignment not being done
783 - - Add cat/pkg: substtution in the commitsgfile text
784 - - Disable SRC_URI.mirror warnings when there is only 1 mirror
785 - - Fix version output string to say Repoman, fix live versioning,
786 - add portage version to --version output.
787 - - Add repoman version to "Package manager:" commit footer
788 -
789 -repoman-2.3.0
790 -==================================
791 -* Bug Fixes:
792 - - Bug 584786 Add support for .git as a file when --separate-git-dir is used
793 - - Bug 585864 fix missing vcs_files_to_cps repodir argument
794 - - Bug 585388 fix KeyError during manifest generation
795 -* New QA error: slot operator under '||' alternative
796 -
797 -repoman-2.3.0_rc1
798 -==================================
799 -* Initial test release
800 -* Bug Fixes:
801 - - Bug 579460 Disable the $ID header check
802 - - Bug 546010 Handle removed packages in vcs_files_to_cps
803 - - Bug 581594 Fix commit 8e7971169c2 missing self in func() parameters
804 - - Bug 581598 Add InvalidPackageName exception trap
805 - - Bug 405017 Fix copyright update
806 -* Includes the stage2 re-writes, the checks are now in a modular system
807 - which is not yet fully plug-in capable. Becoming fully plug-in capable and
808 - configurable is to be done in the stage3 rewites.
809
810 diff --git a/repoman/TEST-NOTES b/repoman/TEST-NOTES
811 deleted file mode 100644
812 index 8be5f9cf3..000000000
813 --- a/repoman/TEST-NOTES
814 +++ /dev/null
815 @@ -1,45 +0,0 @@
816 -UnitTests
817 ----------
818 -
819 -Portage has some tests that use the unittest framework that ships with python (2.3-2.4ish)
820 -Tests have a specific naming convention.
821 -
822 -in lib/portage/tests/ there is a runTest script that invokes lib/portage/tests/__init__.py
823 -
824 -This init looks at a hardcoded list of test dirs to search for tests.
825 -If you add a new dir and don't see your new tests, make sure that the dir is in this list.
826 -
827 -On the subject of adding more directories; the layout is basically 1 directory per portage
828 -file at this point (we have few files, and even fewer large files). Inside of the dir
829 -you should have files of the form test_${function}.py.
830 -
831 -So if I was to write a vercmp test, and vercmp is in portage_versions.
832 -
833 -lib/portage/tests/portage_versions/test_vercmp.py
834 -
835 -would be the filename.
836 -
837 -The __init__.py file now does recursive tests, but you need to tell it so. For example, if
838 -you had cache tests the dir format would be something like...
839 -
840 -lib/portage/tests/cache/flat_hash/test_foo.py
841 -
842 -and you would put "cache/flat_hash" into the testDirs variable in __init__.py.
843 -
844 -
845 -Skipping
846 ---------
847 -
848 -Please use the portage.tests.* classes as they support throwing a SkipException for
849 -tests that are known to fail. Normally one uses testing to do Test Driven Development
850 -(TDD); however we do not do that here. Therefore there are times when legitimate tests
851 -exist but fail due to code in trunk. We would still like the suite to pass in some instances
852 -because the suite is built around two things, testing functionality in the current code as
853 -well as poking holes in the current code (isvalidatom is an example). So sometimes we desire
854 -a test to point out that "this needs fixing" but it doesn't affect portage's overall
855 -functionality. You should raise portage.tests.SkipException in that case.
856 -
857 -emerge
858 -------
859 -
860 -The emerge namespace currently has 0 tests (and no runner)
861
862 diff --git a/repoman/bin/repoman b/repoman/bin/repoman
863 deleted file mode 100755
864 index beaf8147a..000000000
865 --- a/repoman/bin/repoman
866 +++ /dev/null
867 @@ -1,56 +0,0 @@
868 -#!/usr/bin/env python
869 -# Copyright 1999-2021 Gentoo Authors
870 -# Distributed under the terms of the GNU General Public License v2
871 -
872 -"""Ebuild and tree health checks and maintenance utilities.
873 -"""
874 -
875 -import sys
876 -import errno
877 -
878 -# This block ensures that ^C interrupts are handled quietly.
879 -try:
880 - import signal
881 -
882 - def exithandler(signum, _frame):
883 - signal.signal(signal.SIGINT, signal.SIG_IGN)
884 - signal.signal(signal.SIGTERM, signal.SIG_IGN)
885 - sys.exit(128 + signum)
886 -
887 - signal.signal(signal.SIGINT, exithandler)
888 - signal.signal(signal.SIGTERM, exithandler)
889 - signal.signal(signal.SIGPIPE, signal.SIG_DFL)
890 -
891 -except KeyboardInterrupt:
892 - sys.exit(1)
893 -
894 -from os import path as osp
895 -
896 -here = osp.realpath(__file__)
897 -if osp.isfile(osp.join(osp.dirname(osp.dirname(here)), ".repoman_not_installed")):
898 - # Add the repoman subpkg
899 - pym_path = osp.join(osp.dirname(osp.dirname(here)), "lib")
900 - sys.path.insert(0, pym_path)
901 - if osp.isfile(
902 - osp.join(osp.dirname(osp.dirname(osp.dirname(here))), ".portage_not_installed")
903 - ):
904 - # Add the base portage pkg
905 - pym_path = osp.join(osp.dirname(osp.dirname(osp.dirname(here))), "lib")
906 - sys.path.insert(0, pym_path)
907 -
908 -import portage
909 -
910 -portage._internal_caller = True
911 -from portage.util._eventloop.global_event_loop import global_event_loop
912 -from repoman.main import repoman_main
913 -
914 -try:
915 - sys.exit(repoman_main(sys.argv))
916 -except IOError as e:
917 - if e.errno == errno.EACCES:
918 - print("\nRepoman: Need user access")
919 - sys.exit(1)
920 - else:
921 - raise
922 -finally:
923 - global_event_loop().close()
924
925 diff --git a/repoman/cnf/linechecks/linechecks.yaml b/repoman/cnf/linechecks/linechecks.yaml
926 deleted file mode 100644
927 index c6c72ab26..000000000
928 --- a/repoman/cnf/linechecks/linechecks.yaml
929 +++ /dev/null
930 @@ -1,34 +0,0 @@
931 ----
932 -# linecheck_help.yaml
933 -
934 -# Repoman API version (do not edit)
935 -version: 1
936 -# minimum
937 -repoman_version: 2.3.3
938 -
939 -# configuration file for the LineCheck plugins run via the multicheck
940 -# scan module
941 -errors:
942 - COPYRIGHT_ERROR: 'Invalid Copyright'
943 - LICENSE_ERROR: 'Invalid Gentoo/GPL License'
944 - ID_HEADER_ERROR: 'Stale CVS header'
945 - NO_BLANK_LINE_ERROR: 'Non-blank line after header'
946 - LEADING_SPACES_ERROR: 'Ebuild contains leading spaces'
947 - TRAILING_WHITESPACE_ERROR: 'Trailing whitespace error'
948 - READONLY_ASSIGNMENT_ERROR: 'Ebuild contains assignment to read-only variable'
949 - MISSING_QUOTES_ERROR: 'Unquoted Variable'
950 - NESTED_DIE_ERROR: 'Ebuild calls die in a subshell'
951 - PATCHES_ERROR: 'PATCHES is not a bash array'
952 - REDUNDANT_CD_S_ERROR: 'Ebuild has redundant cd ${S} statement'
953 - EMAKE_PARALLEL_DISABLED: 'Upstream parallel compilation bug (ebuild calls emake -j1)'
954 - EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS: 'Upstream parallel compilation bug (MAKEOPTS=-j1)'
955 - DEPRECATED_BINDNOW_FLAGS: 'Deprecated bindnow-flags call'
956 - EAPI_DEFINED_AFTER_INHERIT: 'EAPI defined after inherit'
957 - NO_AS_NEEDED: 'Upstream asneeded linking bug (no-as-needed)'
958 - PRESERVE_OLD_LIB: 'Ebuild calls preserve_old_lib function reserved for system packages'
959 - BUILT_WITH_USE: 'built_with_use'
960 - NO_OFFSET_WITH_HELPERS: 'Helper function is used with D, ROOT, ED, EROOT or EPREFIX'
961 - USEQ_ERROR: 'Ebuild calls deprecated useq function'
962 - HASQ_ERROR: 'Ebuild calls deprecated hasq function'
963 - URI_HTTPS: 'Ebuild uses http:// but should use https://'
964 -
965
966 diff --git a/repoman/cnf/metadata.xsd b/repoman/cnf/metadata.xsd
967 deleted file mode 100644
968 index 33ff58eac..000000000
969 --- a/repoman/cnf/metadata.xsd
970 +++ /dev/null
971 @@ -1,548 +0,0 @@
972 -<?xml version='1.0' encoding='UTF-8'?>
973 -
974 -<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
975 - <!-- top-level variants -->
976 - <xs:element name='pkgmetadata' type='pkgMetadataType'>
977 - <!-- note: restrict uniquity rules are simplified
978 - the spec says: one for each matched package
979 - we can only do: one for each restrict rule -->
980 - <xs:unique name='longDescUniquityConstraint'>
981 - <xs:selector xpath='longdescription'/>
982 - <xs:field xpath='@lang'/>
983 - <xs:field xpath='@restrict'/>
984 - </xs:unique>
985 - <xs:unique name='maintainerUniquityConstraint'>
986 - <xs:selector xpath='maintainer'/>
987 - <xs:field xpath='email'/>
988 - <xs:field xpath='@restrict'/>
989 - </xs:unique>
990 - <xs:unique name='slotsUniquityConstraint'>
991 - <xs:selector xpath='slots'/>
992 - <xs:field xpath='@lang'/>
993 - </xs:unique>
994 - <xs:unique name='upstreamSingleConstraint'>
995 - <xs:selector xpath='upstream'/>
996 - <xs:field xpath='@fake-only-once'/>
997 - </xs:unique>
998 - <xs:unique name='useUniquityConstraint'>
999 - <xs:selector xpath='use'/>
1000 - <xs:field xpath='@lang'/>
1001 - </xs:unique>
1002 - </xs:element>
1003 - <xs:element name='catmetadata' type='catMetadataType'>
1004 - <xs:unique name='catLongDescUniquityConstraint'>
1005 - <xs:selector xpath='longdescription'/>
1006 - <xs:field xpath='@lang'/>
1007 - </xs:unique>
1008 - </xs:element>
1009 -
1010 - <!-- global elements -->
1011 - <xs:complexType name='pkgMetadataType'>
1012 - <xs:choice minOccurs='0' maxOccurs='unbounded'>
1013 - <xs:element name='longdescription' type='longDescType'/>
1014 - <xs:element name='maintainer' type='maintainerType'>
1015 - <xs:unique name='maintainerDescUniquityConstraint'>
1016 - <xs:selector xpath='description'/>
1017 - <xs:field xpath='@lang'/>
1018 - </xs:unique>
1019 - </xs:element>
1020 - <xs:element name='slots' type='slotsType'>
1021 - <xs:unique name='slotUniquityConstraint'>
1022 - <xs:selector xpath='slot'/>
1023 - <xs:field xpath='@name'/>
1024 - </xs:unique>
1025 - <xs:unique name='subslotsSingleConstraint'>
1026 - <xs:selector xpath='subslots'/>
1027 - <xs:field xpath='@fake-only-once'/>
1028 - </xs:unique>
1029 - </xs:element>
1030 - <xs:element name='upstream' type='upstreamType'>
1031 - <xs:unique name='bugsToSingleConstraint'>
1032 - <xs:selector xpath='bugs-to'/>
1033 - <xs:field xpath='@fake-only-once'/>
1034 - </xs:unique>
1035 - <xs:unique name='changelogSingleConstraint'>
1036 - <xs:selector xpath='changelog'/>
1037 - <xs:field xpath='@fake-only-once'/>
1038 - </xs:unique>
1039 - <!-- prevent accidentally repeating the same remote -->
1040 - <xs:unique name='upstreamRemoteIdRepetitionConstraint'>
1041 - <xs:selector xpath='remote-id'/>
1042 - <xs:field xpath='@type'/>
1043 - <xs:field xpath='.'/>
1044 - </xs:unique>
1045 - <xs:unique name='upstreamDocUniquityConstraint'>
1046 - <xs:selector xpath='doc'/>
1047 - <xs:field xpath='@lang'/>
1048 - </xs:unique>
1049 - </xs:element>
1050 - <xs:element name='use' type='useType'>
1051 - <xs:unique name='flagUniquityConstraint'>
1052 - <xs:selector xpath='flag'/>
1053 - <xs:field xpath='@name'/>
1054 - <xs:field xpath='@restrict'/>
1055 - </xs:unique>
1056 - </xs:element>
1057 - </xs:choice>
1058 - </xs:complexType>
1059 -
1060 - <xs:complexType name='catMetadataType'>
1061 - <xs:choice minOccurs='0' maxOccurs='unbounded'>
1062 - <xs:element name='longdescription' type='catLongDescType'/>
1063 - </xs:choice>
1064 - </xs:complexType>
1065 -
1066 - <!-- the huge <upstream/> structure -->
1067 - <xs:complexType name='upstreamType'>
1068 - <xs:choice minOccurs='0' maxOccurs='unbounded'>
1069 - <xs:element name='maintainer' type='upstreamMaintainerType'>
1070 - <xs:unique name='upstreamMaintainerUniquityConstraint'>
1071 - <xs:selector xpath='maintainer'/>
1072 - <xs:field xpath='name'/>
1073 - </xs:unique>
1074 - </xs:element>
1075 - <xs:element name='changelog' type='urlOnceType'/>
1076 - <xs:element name='doc' type='upstreamDocType'/>
1077 - <xs:element name='bugs-to' type='urlOnceType'/>
1078 - <xs:element name='remote-id' type='upstreamRemoteIdType'/>
1079 - </xs:choice>
1080 - <xs:attribute name='fake-only-once'
1081 - fixed='there can be at most one &lt;upstream/&gt; element'/>
1082 - </xs:complexType>
1083 -
1084 - <!-- maintainer in two variants -->
1085 - <xs:complexType name='maintainerType'>
1086 - <xs:all>
1087 - <xs:element name='email' type='emailType'
1088 - minOccurs='1'/>
1089 - <xs:element name='name' type='xs:token'
1090 - minOccurs='0'/>
1091 - <xs:element name='description' type='maintainerDescType'
1092 - minOccurs='0'/>
1093 - </xs:all>
1094 - <xs:attribute name='type' type='maintainerTypeAttrType'
1095 - use='required'/>
1096 - <xs:attribute name='restrict' type='restrictAttrType'/>
1097 - </xs:complexType>
1098 -
1099 - <xs:simpleType name='maintainerTypeAttrType'>
1100 - <xs:restriction base='xs:token'>
1101 - <xs:enumeration value='person'/>
1102 - <xs:enumeration value='project'/>
1103 - </xs:restriction>
1104 - </xs:simpleType>
1105 -
1106 - <xs:complexType name='upstreamMaintainerType'>
1107 - <xs:all>
1108 - <xs:element name='email' type='emailType'
1109 - minOccurs='0'/>
1110 - <xs:element name='name' type='xs:token'
1111 - minOccurs='0'/>
1112 - </xs:all>
1113 - <xs:attribute name='status' type='upstreamMaintainerStatusAttrType'
1114 - default='unknown'/>
1115 - </xs:complexType>
1116 -
1117 - <xs:simpleType name='upstreamMaintainerStatusAttrType'>
1118 - <xs:restriction base='xs:token'>
1119 - <xs:enumeration value='active'/>
1120 - <xs:enumeration value='inactive'/>
1121 - <xs:enumeration value='unknown'/>
1122 - </xs:restriction>
1123 - </xs:simpleType>
1124 -
1125 - <xs:complexType name='maintainerDescType'>
1126 - <xs:simpleContent>
1127 - <xs:extension base="xs:token">
1128 - <xs:attribute name='lang' type='langAttrType' default='en'/>
1129 - </xs:extension>
1130 - </xs:simpleContent>
1131 - </xs:complexType>
1132 -
1133 - <!-- long description -->
1134 - <xs:complexType name='longDescType' mixed='true'>
1135 - <xs:choice minOccurs='0' maxOccurs='unbounded'>
1136 - <xs:element name='pkg' type='pkgType'/>
1137 - <xs:element name='cat' type='catType'/>
1138 - </xs:choice>
1139 - <xs:attribute name='lang' type='langAttrType' default='en'/>
1140 - <xs:attribute name='restrict' type='restrictAttrType'/>
1141 - </xs:complexType>
1142 -
1143 - <xs:complexType name='catLongDescType' mixed='true'>
1144 - <xs:choice minOccurs='0' maxOccurs='unbounded'>
1145 - <xs:element name='pkg' type='pkgType'/>
1146 - <xs:element name='cat' type='catType'/>
1147 - </xs:choice>
1148 - <xs:attribute name='lang' type='langAttrType' default='en'/>
1149 - </xs:complexType>
1150 -
1151 - <!-- slots -->
1152 - <xs:complexType name='slotsType'>
1153 - <xs:choice minOccurs='0' maxOccurs='unbounded'>
1154 - <xs:element name='slot' type='slotType'/>
1155 - <xs:element name='subslots' type='tokenOnceType'/>
1156 - </xs:choice>
1157 - <xs:attribute name='lang' type='langAttrType' default='en'/>
1158 - </xs:complexType>
1159 -
1160 - <xs:complexType name='slotType'>
1161 - <xs:simpleContent>
1162 - <xs:extension base="xs:token">
1163 - <xs:attribute name='name' type='slotNameAttrType'
1164 - use='required'/>
1165 - </xs:extension>
1166 - </xs:simpleContent>
1167 - </xs:complexType>
1168 -
1169 - <xs:simpleType name='slotNameAttrType'>
1170 - <xs:restriction base='xs:token'>
1171 - <!-- PMS 3.1.3 Slot Names + special value '*' -->
1172 - <xs:pattern value="[A-Za-z0-9_][A-Za-z0-9+_.-]*|[*]"/>
1173 - </xs:restriction>
1174 - </xs:simpleType>
1175 -
1176 - <!-- use flags -->
1177 - <xs:complexType name='useType'>
1178 - <xs:choice minOccurs='0' maxOccurs='unbounded'>
1179 - <xs:element name='flag' type='flagType'/>
1180 - </xs:choice>
1181 - <xs:attribute name='lang' type='langAttrType' default='en'/>
1182 - </xs:complexType>
1183 -
1184 - <xs:complexType name='flagType' mixed='true'>
1185 - <xs:choice minOccurs='0' maxOccurs='unbounded'>
1186 - <xs:element name='cat' type='catType'/>
1187 - <xs:element name='pkg' type='pkgType'/>
1188 - </xs:choice>
1189 - <xs:attribute name='name' type='flagNameAttrType'
1190 - use='required'/>
1191 - <xs:attribute name='restrict' type='restrictAttrType'
1192 - default=''/>
1193 - </xs:complexType>
1194 -
1195 - <xs:simpleType name='flagNameAttrType'>
1196 - <xs:restriction base='xs:token'>
1197 - <!-- PMS 3.1.4 USE Flag Names -->
1198 - <xs:pattern value="[A-Za-z0-9][A-Za-z0-9+_@-]*"/>
1199 - </xs:restriction>
1200 - </xs:simpleType>
1201 -
1202 - <!-- upstream-specific types -->
1203 - <xs:complexType name='upstreamDocType'>
1204 - <xs:simpleContent>
1205 - <xs:extension base="urlType">
1206 - <xs:attribute name='lang' type='langAttrType' default='en'/>
1207 - </xs:extension>
1208 - </xs:simpleContent>
1209 - </xs:complexType>
1210 -
1211 - <xs:complexType name='upstreamRemoteIdType'>
1212 - <xs:simpleContent>
1213 - <xs:extension base="xs:token">
1214 - <xs:attribute name='type' type='upstreamRemoteIdTypeAttrType'
1215 - use='required'/>
1216 - </xs:extension>
1217 - </xs:simpleContent>
1218 - </xs:complexType>
1219 -
1220 - <xs:simpleType name='upstreamRemoteIdTypeAttrType'>
1221 - <xs:restriction base='xs:token'>
1222 - <xs:enumeration value='bitbucket'/>
1223 - <xs:enumeration value='cpan'/>
1224 - <xs:enumeration value='cpan-module'/>
1225 - <xs:enumeration value='cpe'/>
1226 - <xs:enumeration value='cran'/>
1227 - <xs:enumeration value='ctan'/>
1228 - <xs:enumeration value='freecode'/>
1229 - <xs:enumeration value='freshmeat'/>
1230 - <xs:enumeration value='gentoo'/>
1231 - <xs:enumeration value='github'/>
1232 - <xs:enumeration value='gitlab'/>
1233 - <xs:enumeration value='gitorious'/>
1234 - <xs:enumeration value='google-code'/>
1235 - <xs:enumeration value='launchpad'/>
1236 - <xs:enumeration value='pear'/>
1237 - <xs:enumeration value='pecl'/>
1238 - <xs:enumeration value='pypi'/>
1239 - <xs:enumeration value='rubyforge'/>
1240 - <xs:enumeration value='rubygems'/>
1241 - <xs:enumeration value='sourceforge'/>
1242 - <xs:enumeration value='sourceforge-jp'/>
1243 - <xs:enumeration value='vim'/>
1244 - </xs:restriction>
1245 - </xs:simpleType>
1246 -
1247 - <!-- creepy mixed-text types -->
1248 - <xs:simpleType name='catType'>
1249 - <xs:restriction base='xs:token'>
1250 - <!-- PMS 3.1.1 Category Names -->
1251 - <xs:pattern value="[A-Za-z0-9_][A-Za-z0-9+_.-]*"/>
1252 - </xs:restriction>
1253 - </xs:simpleType>
1254 - <xs:simpleType name='pkgType'>
1255 - <xs:restriction base='xs:token'>
1256 - <!-- PMS 3.1.1 Category Names + 3.1.2 Package Names -->
1257 - <!-- note: this does not enforce the 'anything matching
1258 - the version syntax' requirement -->
1259 - <xs:pattern
1260 - value="[A-Za-z0-9_][A-Za-z0-9+_.-]*/[A-Za-z0-9_][A-Za-z0-9+_-]*"/>
1261 - </xs:restriction>
1262 - </xs:simpleType>
1263 -
1264 - <!-- common attributes -->
1265 - <xs:simpleType name='langAttrType'>
1266 - <xs:restriction base='xs:token'>
1267 - <!-- ISO 639-1 language codes -->
1268 - <xs:enumeration value='aa'/>
1269 - <xs:enumeration value='ab'/>
1270 - <xs:enumeration value='ae'/>
1271 - <xs:enumeration value='af'/>
1272 - <xs:enumeration value='ak'/>
1273 - <xs:enumeration value='am'/>
1274 - <xs:enumeration value='an'/>
1275 - <xs:enumeration value='ar'/>
1276 - <xs:enumeration value='as'/>
1277 - <xs:enumeration value='av'/>
1278 - <xs:enumeration value='ay'/>
1279 - <xs:enumeration value='az'/>
1280 - <xs:enumeration value='ba'/>
1281 - <xs:enumeration value='be'/>
1282 - <xs:enumeration value='bg'/>
1283 - <xs:enumeration value='bh'/>
1284 - <xs:enumeration value='bi'/>
1285 - <xs:enumeration value='bm'/>
1286 - <xs:enumeration value='bn'/>
1287 - <xs:enumeration value='bo'/>
1288 - <xs:enumeration value='bo'/>
1289 - <xs:enumeration value='br'/>
1290 - <xs:enumeration value='bs'/>
1291 - <xs:enumeration value='ca'/>
1292 - <xs:enumeration value='ce'/>
1293 - <xs:enumeration value='ch'/>
1294 - <xs:enumeration value='co'/>
1295 - <xs:enumeration value='cr'/>
1296 - <xs:enumeration value='cs'/>
1297 - <xs:enumeration value='cs'/>
1298 - <xs:enumeration value='cu'/>
1299 - <xs:enumeration value='cv'/>
1300 - <xs:enumeration value='cy'/>
1301 - <xs:enumeration value='cy'/>
1302 - <xs:enumeration value='da'/>
1303 - <xs:enumeration value='de'/>
1304 - <xs:enumeration value='de'/>
1305 - <xs:enumeration value='dv'/>
1306 - <xs:enumeration value='dz'/>
1307 - <xs:enumeration value='ee'/>
1308 - <xs:enumeration value='el'/>
1309 - <xs:enumeration value='el'/>
1310 - <xs:enumeration value='en'/>
1311 - <xs:enumeration value='eo'/>
1312 - <xs:enumeration value='es'/>
1313 - <xs:enumeration value='et'/>
1314 - <xs:enumeration value='eu'/>
1315 - <xs:enumeration value='eu'/>
1316 - <xs:enumeration value='fa'/>
1317 - <xs:enumeration value='fa'/>
1318 - <xs:enumeration value='ff'/>
1319 - <xs:enumeration value='fi'/>
1320 - <xs:enumeration value='fj'/>
1321 - <xs:enumeration value='fo'/>
1322 - <xs:enumeration value='fr'/>
1323 - <xs:enumeration value='fr'/>
1324 - <xs:enumeration value='fy'/>
1325 - <xs:enumeration value='ga'/>
1326 - <xs:enumeration value='ga'/>
1327 - <xs:enumeration value='Ga'/>
1328 - <xs:enumeration value='gd'/>
1329 - <xs:enumeration value='gl'/>
1330 - <xs:enumeration value='gn'/>
1331 - <xs:enumeration value='gu'/>
1332 - <xs:enumeration value='gv'/>
1333 - <xs:enumeration value='ha'/>
1334 - <xs:enumeration value='he'/>
1335 - <xs:enumeration value='hi'/>
1336 - <xs:enumeration value='ho'/>
1337 - <xs:enumeration value='hr'/>
1338 - <xs:enumeration value='ht'/>
1339 - <xs:enumeration value='hu'/>
1340 - <xs:enumeration value='hy'/>
1341 - <xs:enumeration value='hy'/>
1342 - <xs:enumeration value='hz'/>
1343 - <xs:enumeration value='ia'/>
1344 - <xs:enumeration value='id'/>
1345 - <xs:enumeration value='ie'/>
1346 - <xs:enumeration value='ig'/>
1347 - <xs:enumeration value='ii'/>
1348 - <xs:enumeration value='ik'/>
1349 - <xs:enumeration value='io'/>
1350 - <xs:enumeration value='is'/>
1351 - <xs:enumeration value='is'/>
1352 - <xs:enumeration value='it'/>
1353 - <xs:enumeration value='iu'/>
1354 - <xs:enumeration value='ja'/>
1355 - <xs:enumeration value='jv'/>
1356 - <xs:enumeration value='ka'/>
1357 - <xs:enumeration value='ka'/>
1358 - <xs:enumeration value='kg'/>
1359 - <xs:enumeration value='ki'/>
1360 - <xs:enumeration value='kj'/>
1361 - <xs:enumeration value='kk'/>
1362 - <xs:enumeration value='kl'/>
1363 - <xs:enumeration value='km'/>
1364 - <xs:enumeration value='kn'/>
1365 - <xs:enumeration value='ko'/>
1366 - <xs:enumeration value='kr'/>
1367 - <xs:enumeration value='ks'/>
1368 - <xs:enumeration value='ku'/>
1369 - <xs:enumeration value='kv'/>
1370 - <xs:enumeration value='kw'/>
1371 - <xs:enumeration value='ky'/>
1372 - <xs:enumeration value='la'/>
1373 - <xs:enumeration value='lb'/>
1374 - <xs:enumeration value='lg'/>
1375 - <xs:enumeration value='li'/>
1376 - <xs:enumeration value='ln'/>
1377 - <xs:enumeration value='lo'/>
1378 - <xs:enumeration value='lt'/>
1379 - <xs:enumeration value='lu'/>
1380 - <xs:enumeration value='lv'/>
1381 - <xs:enumeration value='mg'/>
1382 - <xs:enumeration value='mh'/>
1383 - <xs:enumeration value='mi'/>
1384 - <xs:enumeration value='mi'/>
1385 - <xs:enumeration value='mk'/>
1386 - <xs:enumeration value='mk'/>
1387 - <xs:enumeration value='ml'/>
1388 - <xs:enumeration value='mn'/>
1389 - <xs:enumeration value='mr'/>
1390 - <xs:enumeration value='ms'/>
1391 - <xs:enumeration value='ms'/>
1392 - <xs:enumeration value='mt'/>
1393 - <xs:enumeration value='my'/>
1394 - <xs:enumeration value='my'/>
1395 - <xs:enumeration value='na'/>
1396 - <xs:enumeration value='nb'/>
1397 - <xs:enumeration value='nd'/>
1398 - <xs:enumeration value='ne'/>
1399 - <xs:enumeration value='ng'/>
1400 - <xs:enumeration value='nl'/>
1401 - <xs:enumeration value='nl'/>
1402 - <xs:enumeration value='nn'/>
1403 - <xs:enumeration value='no'/>
1404 - <xs:enumeration value='nr'/>
1405 - <xs:enumeration value='nv'/>
1406 - <xs:enumeration value='ny'/>
1407 - <xs:enumeration value='oc'/>
1408 - <xs:enumeration value='oj'/>
1409 - <xs:enumeration value='om'/>
1410 - <xs:enumeration value='or'/>
1411 - <xs:enumeration value='os'/>
1412 - <xs:enumeration value='pa'/>
1413 - <xs:enumeration value='pi'/>
1414 - <xs:enumeration value='pl'/>
1415 - <xs:enumeration value='ps'/>
1416 - <xs:enumeration value='pt'/>
1417 - <xs:enumeration value='qu'/>
1418 - <xs:enumeration value='rm'/>
1419 - <xs:enumeration value='rn'/>
1420 - <xs:enumeration value='ro'/>
1421 - <xs:enumeration value='ro'/>
1422 - <xs:enumeration value='ru'/>
1423 - <xs:enumeration value='rw'/>
1424 - <xs:enumeration value='sa'/>
1425 - <xs:enumeration value='sc'/>
1426 - <xs:enumeration value='sd'/>
1427 - <xs:enumeration value='se'/>
1428 - <xs:enumeration value='sg'/>
1429 - <xs:enumeration value='si'/>
1430 - <xs:enumeration value='sk'/>
1431 - <xs:enumeration value='sk'/>
1432 - <xs:enumeration value='sl'/>
1433 - <xs:enumeration value='sm'/>
1434 - <xs:enumeration value='sn'/>
1435 - <xs:enumeration value='so'/>
1436 - <xs:enumeration value='sq'/>
1437 - <xs:enumeration value='sq'/>
1438 - <xs:enumeration value='sr'/>
1439 - <xs:enumeration value='ss'/>
1440 - <xs:enumeration value='st'/>
1441 - <xs:enumeration value='su'/>
1442 - <xs:enumeration value='sv'/>
1443 - <xs:enumeration value='sw'/>
1444 - <xs:enumeration value='ta'/>
1445 - <xs:enumeration value='te'/>
1446 - <xs:enumeration value='tg'/>
1447 - <xs:enumeration value='th'/>
1448 - <xs:enumeration value='ti'/>
1449 - <xs:enumeration value='tk'/>
1450 - <xs:enumeration value='tl'/>
1451 - <xs:enumeration value='tn'/>
1452 - <xs:enumeration value='to'/>
1453 - <xs:enumeration value='tr'/>
1454 - <xs:enumeration value='ts'/>
1455 - <xs:enumeration value='tt'/>
1456 - <xs:enumeration value='tw'/>
1457 - <xs:enumeration value='ty'/>
1458 - <xs:enumeration value='ug'/>
1459 - <xs:enumeration value='uk'/>
1460 - <xs:enumeration value='ur'/>
1461 - <xs:enumeration value='uz'/>
1462 - <xs:enumeration value='ve'/>
1463 - <xs:enumeration value='vi'/>
1464 - <xs:enumeration value='vo'/>
1465 - <xs:enumeration value='wa'/>
1466 - <xs:enumeration value='wo'/>
1467 - <xs:enumeration value='xh'/>
1468 - <xs:enumeration value='yi'/>
1469 - <xs:enumeration value='yo'/>
1470 - <xs:enumeration value='za'/>
1471 - <xs:enumeration value='zh'/>
1472 - <xs:enumeration value='zh'/>
1473 - <xs:enumeration value='zu'/>
1474 - </xs:restriction>
1475 - </xs:simpleType>
1476 -
1477 - <xs:simpleType name='restrictAttrType'>
1478 - <xs:restriction base='xs:token'>
1479 - <!-- simplified package dependency syntax -->
1480 - <!-- note: 'pure' package atom is technically valid too
1481 - but not really meaningful -->
1482 - <xs:pattern
1483 - value="(([&lt;&gt;]=?|[=~])[A-Za-z0-9_][A-Za-z0-9+_.-]*/[A-Za-z0-9_][A-Za-z0-9+_-]*-[0-9]+(\.[0-9]+)*[a-z]?((_alpha|_beta|_pre|_rc|_p)[0-9]*)*(-r[0-9]+)?\*?)?"/>
1484 - </xs:restriction>
1485 - </xs:simpleType>
1486 -
1487 - <!-- generic types -->
1488 - <xs:simpleType name='emailType'>
1489 - <xs:restriction base='xs:token'>
1490 - <!-- minimal safe regex -->
1491 - <xs:pattern value="[^@]+@[^.]+\..+"/>
1492 - </xs:restriction>
1493 - </xs:simpleType>
1494 -
1495 - <xs:complexType name='tokenOnceType'>
1496 - <xs:simpleContent>
1497 - <xs:extension base="xs:token">
1498 - <xs:attribute name='fake-only-once'
1499 - fixed='there can be at most one element of this type'/>
1500 - </xs:extension>
1501 - </xs:simpleContent>
1502 - </xs:complexType>
1503 -
1504 - <xs:simpleType name='urlType'>
1505 - <xs:restriction base='xs:token'>
1506 - <!-- TODO: something better? -->
1507 - <xs:pattern value="(mailto:[^@]+@[^.]+\..+|https?://.+)"/>
1508 - </xs:restriction>
1509 - </xs:simpleType>
1510 -
1511 - <xs:complexType name='urlOnceType'>
1512 - <xs:simpleContent>
1513 - <xs:extension base="urlType">
1514 - <xs:attribute name='fake-only-once'
1515 - fixed='there can be at most one element of this type'/>
1516 - </xs:extension>
1517 - </xs:simpleContent>
1518 - </xs:complexType>
1519 -</xs:schema>
1520
1521 diff --git a/repoman/cnf/qa_data/qa_data.yaml b/repoman/cnf/qa_data/qa_data.yaml
1522 deleted file mode 100644
1523 index 530c8c806..000000000
1524 --- a/repoman/cnf/qa_data/qa_data.yaml
1525 +++ /dev/null
1526 @@ -1,139 +0,0 @@
1527 ----
1528 -# qa_help.yaml
1529 -
1530 -# configuration file for the LineCheck plugins run via the multicheck
1531 -# scan module
1532 -
1533 -# Repoman API version (do not edit)
1534 -version: 1
1535 -# minimum
1536 -repoman_version: 2.3.3
1537 -
1538 -# qahelp: Primary QA help messages to describe the errors or warnings
1539 -# Dictionary
1540 -qahelp:
1541 - Entries:
1542 - IO_error: "Attempting to commit, and an IO error was encountered access the Entries file"
1543 - changelog:
1544 - ebuildadded: "An ebuild was added but the ChangeLog was not modified"
1545 - missing: "Missing ChangeLog files"
1546 - notadded: "ChangeLogs that exist but have not been added to cvs"
1547 - dependency:
1548 - bad: "User-visible ebuilds with unsatisfied dependencies (matched against *visible* ebuilds)"
1549 - badmasked: "Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds)"
1550 - badindev: "User-visible ebuilds with unsatisfied dependencies (matched against *visible* ebuilds) in developing arch"
1551 - badmaskedindev: "Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds) in developing arch"
1552 - badinexp: "User-visible ebuilds with unsatisfied dependencies (matched against *visible* ebuilds) in experimental arch"
1553 - badmaskedinexp: "Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds) in experimental arch"
1554 - badtilde: "Uses the ~ dep operator with a non-zero revision part, which is useless (the revision is ignored)"
1555 - deprecated: "Ebuild has a dependency that refers to a deprecated package"
1556 - equalsversion: "Suspicious =-dependency with a specific version and no rev. Please either use ~ if any revision is acceptable, or append -r0 to silence the warning."
1557 - missingslot: "RDEPEND matches more than one SLOT but does not specify a slot and/or use the := or :* slot operator"
1558 - perlcore: "This ebuild directly depends on a package in perl-core; it should use the corresponding virtual instead."
1559 - syntax: "Syntax error in dependency string (usually an extra/missing space/parenthesis)"
1560 - unknown: "Ebuild has a dependency that refers to an unknown package (which may be valid if it is a blocker for a renamed/removed package, or is an alternative choice provided by an overlay)"
1561 - badslotop: "RDEPEND contains ':=' slot operator under '||' dependency."
1562 - DESCRIPTION:
1563 - missing: "Ebuilds that have a missing or empty DESCRIPTION variable"
1564 - toolong: "DESCRIPTION is over %d characters"
1565 - digest:
1566 - assumed: "Existing digest must be assumed correct (Package level only)"
1567 - missing: "Some files listed in SRC_URI aren't referenced in the Manifest"
1568 - unused: "Some files listed in the Manifest aren't referenced in SRC_URI"
1569 - EAPI:
1570 - definition: "EAPI definition does not conform to PMS section 7.3.1 (first non-comment, non-blank line)"
1571 - deprecated: "Ebuilds that use features that are deprecated in the current EAPI"
1572 - incompatible: "Ebuilds that use features that are only available with a different EAPI"
1573 - unsupported: "Ebuilds that have an unsupported EAPI version (you must upgrade portage)"
1574 - ebuild:
1575 - absdosym: "This ebuild uses absolute target to dosym where relative symlink could be used instead"
1576 - badheader: "This ebuild has a malformed header"
1577 - invalidname: "Ebuild files with a non-parseable or syntactically incorrect name (or using 2.1 versioning extensions)"
1578 - majorsyn: "This ebuild has a major syntax error that may cause the ebuild to fail partially or fully"
1579 - minorsyn: "This ebuild has a minor syntax error that contravenes gentoo coding style"
1580 - namenomatch: "Ebuild files that do not have the same name as their parent directory"
1581 - notadded: "Ebuilds that exist but have not been added to the vcs"
1582 - nesteddie: "Placing 'die' inside ( ) prints an error, but doesn't stop the ebuild."
1583 - output: "A simple sourcing of the ebuild produces output; this breaks ebuild policy."
1584 - patches: "PATCHES variable should be a bash array to ensure white space safety"
1585 - syntax: "Error generating cache entry for ebuild; typically caused by ebuild syntax error or digest verification failure"
1586 - file:
1587 - executable: "Ebuilds, digests, metadata.xml, Manifest, and ChangeLog do not need the executable bit"
1588 - size: "Files in the files directory must be under 20 KiB"
1589 - empty: "Empty file in the files directory"
1590 - name: "File/dir name must be composed of only the following chars: %s "
1591 - UTF8: "File is not UTF8 compliant"
1592 - HOMEPAGE:
1593 - missing: "Ebuilds that have a missing or empty HOMEPAGE variable"
1594 - virtual: "Virtuals that have a non-empty HOMEPAGE variable"
1595 - missingurischeme: "HOMEPAGE is missing an URI scheme"
1596 - inherit:
1597 - deprecated: "Ebuild inherits a deprecated eclass"
1598 - missing: "Ebuild uses functions from an eclass but does not inherit it"
1599 - unused: "Ebuild inherits an eclass but does not use it"
1600 - IUSE:
1601 - invalid: "This ebuild has a variable in IUSE that is not in the use.desc or its metadata.xml file"
1602 - missing: "This ebuild has a USE conditional which references a flag that is not listed in IUSE"
1603 - rubydeprecated: "The ebuild has set a ruby interpreter in USE_RUBY, that is not available as a ruby target anymore"
1604 - java:
1605 - eclassesnotused: "With virtual/jdk in DEPEND you must inherit a java eclass"
1606 - KEYWORDS:
1607 - dropped: "Ebuilds that appear to have dropped KEYWORDS for some arch"
1608 - invalid: "This ebuild contains KEYWORDS that are not listed in profiles/arch.list or for which no valid profile was found"
1609 - missing: "Ebuilds that have a missing or empty KEYWORDS variable"
1610 - stable: "Ebuilds that have been added directly with stable KEYWORDS"
1611 - stupid: "Ebuilds that use KEYWORDS=-* instead of package.mask"
1612 - unsorted: "Ebuilds that contain KEYWORDS which are not sorted alphabetically."
1613 - LICENSE:
1614 - deprecated: "This ebuild is listing a deprecated license."
1615 - invalid: "This ebuild is listing a license that doesnt exist in portages license/ dir."
1616 - missing: "Ebuilds that have a missing or empty LICENSE variable"
1617 - syntax: "Syntax error in LICENSE (usually an extra/missing space/parenthesis)"
1618 - virtual: "Virtuals that have a non-empty LICENSE variable"
1619 - LIVEVCS:
1620 - stable: "This ebuild is a live checkout from a VCS but has stable keywords."
1621 - unmasked: "This ebuild is a live checkout from a VCS but has keywords and is not masked in the global package.mask."
1622 - manifest:
1623 - bad: "Manifest has missing or incorrect digests"
1624 - metadata:
1625 - bad: "Bad metadata.xml files"
1626 - missing: "Missing metadata.xml files"
1627 - warning: "Warnings in metadata.xml files"
1628 - PDEPEND:
1629 - suspect: "PDEPEND contains a package that usually only belongs in DEPEND."
1630 - portage:
1631 - internal: "The ebuild uses an internal Portage function or variable"
1632 - PROPERTIES:
1633 - syntax: "Syntax error in PROPERTIES (usually an extra/missing space/parenthesis)"
1634 - RDEPEND:
1635 - implicit: "RDEPEND is unset in the ebuild which triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4)"
1636 - suspect: "RDEPEND contains a package that usually only belongs in DEPEND."
1637 - repo:
1638 - eapi-banned: "The ebuild uses an EAPI which is banned by the repository's metadata/layout.conf settings"
1639 - eapi-deprecated: "The ebuild uses an EAPI which is deprecated by the repository's metadata/layout.conf settings"
1640 - RESTRICT:
1641 - invalid: "This ebuild contains invalid RESTRICT values."
1642 - syntax: "Syntax error in RESTRICT (usually an extra/missing space/parenthesis)"
1643 - REQUIRED_USE:
1644 - syntax: "Syntax error in REQUIRED_USE (usually an extra/missing space/parenthesis)"
1645 - SLOT:
1646 - invalid: "Ebuilds that have a missing or invalid SLOT variable value"
1647 - SRC_URI:
1648 - syntax: "Syntax error in SRC_URI (usually an extra/missing space/parenthesis)"
1649 - mirror: "A uri listed in profiles/thirdpartymirrors is found in SRC_URI"
1650 - upstream:
1651 - workaround: "The ebuild works around an upstream bug, an upstream bug should be filed and tracked in bugs.gentoo.org"
1652 - uri:
1653 - https: "URI uses http:// but should use https://"
1654 - usage:
1655 - obsolete: "The ebuild makes use of an obsolete construct"
1656 - variable:
1657 - invalidchar: "A variable contains an invalid character that is not part of the ASCII character set"
1658 - phase: "Variable referenced found within scope of incorrect ebuild phase as specified by PMS"
1659 - readonly: "Assigning a readonly variable"
1660 - usedwithhelpers: "Ebuild uses D, ROOT, BROOT, ED, EROOT or EPREFIX with helpers"
1661 - virtual:
1662 - suspect: "Ebuild contains a package that usually should be pulled via virtual/, not directly."
1663 - wxwidgets:
1664 - eclassnotused: "Ebuild DEPENDs on x11-libs/wxGTK without inheriting wxwidgets.eclass"
1665 -
1666
1667 diff --git a/repoman/cnf/repository/linechecks.yaml b/repoman/cnf/repository/linechecks.yaml
1668 deleted file mode 100644
1669 index 528fdd99c..000000000
1670 --- a/repoman/cnf/repository/linechecks.yaml
1671 +++ /dev/null
1672 @@ -1,248 +0,0 @@
1673 ----
1674 -# linecheck.yaml
1675 -
1676 -# configuration file for the LineCheck plugins run via the multicheck
1677 -# scan module
1678 -# no random drive-by commits please
1679 -# Please obtain authorization from the portage team
1680 -#
1681 -# Overlay maintainers override/add/negate checks at your discression
1682 -# but support for third party module will be limited to the plugin API
1683 -#
1684 -
1685 -# Repoman API version (do not edit)
1686 -version: 1
1687 -# minimum
1688 -repoman_version: 2.3.3
1689 -
1690 -eclass_export_functions:
1691 - - ant-tasks
1692 - - apache-2
1693 - - apache-module
1694 - - aspell-dict
1695 - - autotools-utils
1696 - - base
1697 - - bsdmk
1698 - - cannadic
1699 - - clutter
1700 - - cmake-utils
1701 - - db
1702 - - distutils
1703 - - elisp
1704 - - embassy
1705 - - emboss
1706 - - emul-linux-x86
1707 - - enlightenment
1708 - - font-ebdftopcf
1709 - - font
1710 - - fox
1711 - - freebsd
1712 - - freedict
1713 - - games
1714 - - games-ggz
1715 - - games-mods
1716 - - gdesklets
1717 - - gems
1718 - - gkrellm-plugin
1719 - - gnatbuild
1720 - - gnat
1721 - - gnome2
1722 - - gnome-python-common
1723 - - gnustep-base
1724 - - go-mono
1725 - - gpe
1726 - - gst-plugins-bad
1727 - - gst-plugins-base
1728 - - gst-plugins-good
1729 - - gst-plugins-ugly
1730 - - gtk-sharp-module
1731 - - haskell-cabal
1732 - - horde
1733 - - java-ant-2
1734 - - java-pkg-2
1735 - - java-pkg-simple
1736 - - java-virtuals-2
1737 - - kde4-base
1738 - - kde4-meta
1739 - - kernel-2
1740 - - latex-package
1741 - - linux-mod
1742 - - mozlinguas
1743 - - myspell
1744 - - myspell-r2
1745 - - mysql
1746 - - mysql-v2
1747 - - mythtv-plugins
1748 - - oasis
1749 - - obs-service
1750 - - office-ext
1751 - - perl-app
1752 - - perl-module
1753 - - php-ext-base-r1
1754 - - php-ext-pecl-r2
1755 - - php-ext-source-r2
1756 - - php-lib-r1
1757 - - php-pear-lib-r1
1758 - - php-pear-r1
1759 - - python-distutils-ng
1760 - - python
1761 - - qt4-build
1762 - - qt4-r2
1763 - - rox-0install
1764 - - rox
1765 - - ruby
1766 - - ruby-ng
1767 - - scsh
1768 - - selinux-policy-2
1769 - - sgml-catalog
1770 - - stardict
1771 - - sword-module
1772 - - tetex-3
1773 - - tetex
1774 - - texlive-module
1775 - - toolchain-binutils
1776 - - toolchain
1777 - - twisted
1778 - - vdr-plugin-2
1779 - - vdr-plugin
1780 - - vim
1781 - - vim-plugin
1782 - - vim-spell
1783 - - virtuoso
1784 - - vmware
1785 - - vmware-mod
1786 - - waf-utils
1787 - - webapp
1788 - - xemacs-elisp
1789 - - xemacs-packages
1790 - - xfconf
1791 - - x-modular
1792 - - xorg-2
1793 - - zproduct
1794 -
1795 -eclass_info_experimental_inherit:
1796 - autotools:
1797 - funcs:
1798 - - eaclocal
1799 - - eautoconf
1800 - - eautoheader
1801 - - eautomake
1802 - - eautoreconf
1803 - - _elibtoolize
1804 - - eautopoint
1805 - comprehensive: true
1806 - # Exempt eclasses:
1807 - # git - An EGIT_BOOTSTRAP variable may be used to call one of
1808 - # the autotools functions.
1809 - # subversion - An ESVN_BOOTSTRAP variable may be used to call one of
1810 - # the autotools functions.
1811 - exempt_eclasses:
1812 - - git
1813 - - git-2
1814 - - subversion
1815 - - autotools-utils
1816 - eutils:
1817 - funcs:
1818 - - estack_push
1819 - - estack_pop
1820 - - eshopts_push
1821 - - eshopts_pop
1822 - - eumask_push
1823 - - eumask_pop
1824 - - epatch
1825 - - epatch_user
1826 - - emktemp
1827 - - edos2unix
1828 - - in_iuse
1829 - - use_if_iuse
1830 - - usex
1831 - comprehensive: false
1832 - flag-o-matic:
1833 - funcs:
1834 - - 'filter-(ld)?flags'
1835 - - 'strip-flags'
1836 - - 'strip-unsupported-flags'
1837 - - 'append-((ld|c(pp|xx)?))?flags'
1838 - - 'append-libs'
1839 - comprehensive: false
1840 - libtool:
1841 - funcs:
1842 - - elibtoolize
1843 - comprehensive: true
1844 - exempt_eclasses:
1845 - - autotools
1846 - multilib:
1847 - funcs:
1848 - - get_libdir
1849 - # These are "eclasses are the whole ebuild" type thing.
1850 - exempt_eclasses:
1851 - - autotools
1852 - - libtool
1853 - - multilib-minimal
1854 - comprehensive: false
1855 - multiprocessing:
1856 - funcs:
1857 - - makeopts_jobs
1858 - comprehensive: false
1859 - prefix:
1860 - funcs:
1861 - - eprefixify
1862 - comprehensive: true
1863 - toolchain-funcs:
1864 - funcs:
1865 - - gen_usr_ldscript
1866 - comprehensive: false
1867 - user:
1868 - funcs:
1869 - - enewuser
1870 - - enewgroup
1871 - - egetent
1872 - - egethome
1873 - - egetshell
1874 - - esethome
1875 - comprehensive: true
1876 -
1877 -# non experimental_inherit
1878 -eclass_info:
1879 - autotools:
1880 - funcs:
1881 - - eaclocal
1882 - - eautoconf
1883 - - eautoheader
1884 - - eautomake
1885 - - eautoreconf
1886 - - _elibtoolize
1887 - - eautopoint
1888 - comprehensive: true
1889 - ignore_missing: true
1890 - # Exempt eclasses:
1891 - # git - An EGIT_BOOTSTRAP variable may be used to call one of
1892 - # the autotools functions.
1893 - # subversion - An ESVN_BOOTSTRAP variable may be used to call one of
1894 - # the autotools functions.
1895 - exempt_eclasses:
1896 - - git
1897 - - git-2
1898 - - subversion
1899 - - autotools-utils
1900 - prefix:
1901 - funcs:
1902 - - eprefixify
1903 - comprehensive: true
1904 -
1905 -usex_supported_eapis:
1906 - - "0"
1907 - - "1"
1908 - - "2"
1909 - - "3"
1910 - - "4"
1911 - - "4-slot-abi"
1912 -
1913 -in_iuse_supported_eapis:
1914 - - "0"
1915 - - "1"
1916 - - "2"
1917 - - "3"
1918 - - "4"
1919 - - "4-slot-abi"
1920 - - "5"
1921
1922 diff --git a/repoman/cnf/repository/qa_data.yaml b/repoman/cnf/repository/qa_data.yaml
1923 deleted file mode 100644
1924 index 2249000c3..000000000
1925 --- a/repoman/cnf/repository/qa_data.yaml
1926 +++ /dev/null
1927 @@ -1,163 +0,0 @@
1928 ----
1929 -# This yaml syntax file holds various configuration data for
1930 -# the Quality-Assurance checks performed.
1931 -
1932 -# no random drive-by commits please
1933 -# Please obtain authorization from the portage team
1934 -#
1935 -# Overlay maintainers override/add/negate checks at your discression
1936 -# but support for third party module will be limited to the plugin API
1937 -#
1938 -
1939 -# Repoman API version (do not edit)
1940 -version: 1
1941 -# minimum
1942 -repoman_version: 2.3.3
1943 -
1944 -
1945 -allowed_filename_chars: "a-zA-Z0-9._-+:"
1946 -max_description_length: 80
1947 -
1948 -# missingvars check: Mandatory (non-defaulted) ebuild variables
1949 -# list
1950 -missingvars:
1951 - - KEYWORDS
1952 - - LICENSE
1953 - - DESCRIPTION
1954 - - HOMEPAGE
1955 -
1956 -# file.executable check, non executable files
1957 -# list
1958 -no_exec_files:
1959 - - Manifest
1960 - - ChangeLog
1961 - - metadata.xml
1962 -
1963 -# qawarnings: Non-fatal warnings,
1964 -# all values in here MUST have a corresponding qahelp entry
1965 -# list
1966 -qawarnings:
1967 - - changelog.missing
1968 - - changelog.notadded
1969 - - dependency.unknown
1970 - - dependency.badmasked
1971 - - dependency.badindev
1972 - - dependency.badmaskedindev
1973 - - dependency.badtilde
1974 - - dependency.deprecated
1975 - - dependency.equalsversion
1976 - - dependency.missingslot
1977 - - dependency.perlcore
1978 - - DESCRIPTION.toolong
1979 - - digest.assumed
1980 - - digest.unused
1981 - - EAPI.deprecated
1982 - - ebuild.notadded
1983 - - ebuild.nesteddie
1984 - - ebuild.absdosym
1985 - - ebuild.minorsyn
1986 - - ebuild.badheader
1987 - - ebuild.patches
1988 - - file.empty
1989 - - HOMEPAGE.virtual
1990 - - inherit.unused
1991 - - inherit.deprecated
1992 - - IUSE.rubydeprecated
1993 - - java.eclassesnotused
1994 - - KEYWORDS.dropped
1995 - - KEYWORDS.stupid
1996 - - KEYWORDS.missing
1997 - - KEYWORDS.unsorted
1998 - - LICENSE.deprecated
1999 - - LICENSE.virtual
2000 - - metadata.warning
2001 - - PDEPEND.suspect
2002 - - portage.internal
2003 - - RDEPEND.implicit
2004 - - RDEPEND.suspect
2005 - - repo.eapi-deprecated
2006 - - RESTRICT.invalid
2007 - - usage.obsolete
2008 - - upstream.workaround
2009 - - uri.https
2010 - - variable.phase
2011 - - virtual.suspect
2012 - - wxwidgets.eclassnotused
2013 -
2014 -# ruby_deprecated: Deprecated ruby targets
2015 -# list
2016 -ruby_deprecated:
2017 - - ruby_targets_ruby18
2018 - - ruby_targets_ruby19
2019 - - ruby_targets_ruby20
2020 -
2021 -# suspect_rdepend: Common build only Dependencies
2022 -# not usually run time dependencies
2023 -# list
2024 -suspect_rdepend:
2025 - - app-arch/cabextract
2026 - - app-arch/rpm2targz
2027 - - app-doc/doxygen
2028 - - dev-lang/nasm
2029 - - dev-lang/swig
2030 - - dev-lang/yasm
2031 - - dev-perl/extutils-pkgconfig
2032 - - dev-qt/linguist-tools
2033 - - dev-util/byacc
2034 - - dev-util/cmake
2035 - - dev-util/ftjam
2036 - - dev-util/gperf
2037 - - dev-util/gtk-doc
2038 - - dev-util/gtk-doc-am
2039 - - dev-util/intltool
2040 - - dev-util/jam
2041 - - dev-util/pkg-config-lite
2042 - - dev-util/pkgconf
2043 - - dev-util/pkgconfig
2044 - - dev-util/pkgconfig-openbsd
2045 - - dev-util/scons
2046 - - dev-util/unifdef
2047 - - dev-util/yacc
2048 - - media-gfx/ebdftopcf
2049 - - sys-apps/help2man
2050 - - sys-devel/autoconf
2051 - - sys-devel/automake
2052 - - sys-devel/bin86
2053 - - sys-devel/bison
2054 - - sys-devel/dev86
2055 - - sys-devel/flex
2056 - - sys-devel/m4
2057 - - sys-devel/pmake
2058 - - virtual/linux-sources
2059 - - virtual/linuxtv-dvb-headers
2060 - - virtual/os-headers
2061 - - virtual/pkgconfig
2062 - - x11-misc/bdftopcf
2063 - - x11-misc/imake
2064 -
2065 -# suspect_virtual: Dependencies that should usually be made to the virtual
2066 -# Not to the final target library
2067 -# dictionary
2068 -suspect_virtual:
2069 - dev-libs/libusb: virtual/libusb
2070 - dev-libs/libusb-compat: virtual/libusb
2071 - dev-libs/libusbx: virtual/libusb
2072 - dev-util/pkg-config-lite: virtual/pkgconfig
2073 - dev-util/pkgconf: virtual/pkgconfig
2074 - dev-util/pkgconfig: virtual/pkgconfig
2075 - dev-util/pkgconfig-openbsd: virtual/pkgconfig
2076 -
2077 -# valid_restrict: ???
2078 -# list
2079 -valid_restrict:
2080 - - binchecks
2081 - - bindist
2082 - - fetch
2083 - - installsources
2084 - - mirror
2085 - - preserve-libs
2086 - - primaryuri
2087 - - splitdebug
2088 - - strip
2089 - - test
2090 - - userpriv
2091
2092 diff --git a/repoman/cnf/repository/repository.yaml b/repoman/cnf/repository/repository.yaml
2093 deleted file mode 100644
2094 index dbc1decaa..000000000
2095 --- a/repoman/cnf/repository/repository.yaml
2096 +++ /dev/null
2097 @@ -1,76 +0,0 @@
2098 ----
2099 -# repository-modules.yaml
2100 -#
2101 -# This is the repository configuration file for repoman modules
2102 -#
2103 -# no random drive-by commits please
2104 -# Please obtain authorization from the portage team
2105 -#
2106 -# Overlay maintainers override/add/negate checks at your discression
2107 -# but support for third party module will be limited to the plugin API
2108 -#
2109 -
2110 -# Repoman API version (do not edit)
2111 -version: 1
2112 -# minimum
2113 -repoman_version: 2.3.3
2114 -
2115 -# NOTE: for non-gentoo repos, any custom modules added will need their
2116 -# module names to the modules list in order for them to run.
2117 -
2118 -# These are the non-mandatory modules that can be disabled/enabled.
2119 -# use -foo notation to disable, just like use flags
2120 -# Add custom modules to enable them too
2121 -scan_modules:
2122 - description
2123 - eapi
2124 - ebuild_metadata
2125 - fetches
2126 - files
2127 - keywords
2128 - live
2129 - manifests
2130 - multicheck
2131 - pkgmetadata
2132 - profile
2133 - restrict
2134 - ruby
2135 -
2136 -linechecks_modules:
2137 - assignment
2138 - eapi3assignment
2139 - implicitdepend
2140 - hasq
2141 - useq
2142 - preservelib
2143 - bindnow
2144 - inherit
2145 - dosym
2146 - definition
2147 - srcprepare
2148 - eapi3deprecated
2149 - pkgpretend
2150 - eapi4incompatible
2151 - eapi4gonevars
2152 - paralleldisabled
2153 - autodefault
2154 - gentooheader
2155 - nooffset
2156 - nesteddie
2157 - patches
2158 - emakeparallel
2159 - srccompileeconf
2160 - srcunpackpatches
2161 - pmsvariablerefphasescope
2162 - portageinternal
2163 - portageinternalvariableassignment
2164 - quote
2165 - quoteda
2166 - httpsuri
2167 - builtwith
2168 - uselesscds
2169 - uselessdodoc
2170 - whitespace
2171 - blankline
2172 - noasneeded
2173 -
2174
2175 diff --git a/repoman/lib/repoman/__init__.py b/repoman/lib/repoman/__init__.py
2176 deleted file mode 100644
2177 index b3690c07d..000000000
2178 --- a/repoman/lib/repoman/__init__.py
2179 +++ /dev/null
2180 @@ -1,103 +0,0 @@
2181 -import os.path
2182 -import subprocess
2183 -import sys
2184 -import time
2185 -
2186 -try:
2187 - import portage.const
2188 - import portage.proxy as proxy
2189 - from portage import _encodings, _shell_quote, _unicode_encode, _unicode_decode
2190 - from portage.const import PORTAGE_BASE_PATH, BASH_BINARY
2191 -except ImportError as e:
2192 - sys.stderr.write("\n\n")
2193 - sys.stderr.write(
2194 - "!!! Failed to complete portage imports. There are internal modules for\n"
2195 - )
2196 - sys.stderr.write(
2197 - "!!! portage and failure here indicates that you have a problem with your\n"
2198 - )
2199 - sys.stderr.write(
2200 - "!!! installation of portage. Please try a rescue portage located in the ebuild\n"
2201 - )
2202 - sys.stderr.write(
2203 - "!!! repository under '/var/db/repos/gentoo/sys-apps/portage/files/' (default).\n"
2204 - )
2205 - sys.stderr.write(
2206 - "!!! There is a README.RESCUE file that details the steps required to perform\n"
2207 - )
2208 - sys.stderr.write("!!! a recovery of portage.\n")
2209 - sys.stderr.write(" " + str(e) + "\n\n")
2210 - raise
2211 -
2212 -
2213 -VERSION = "HEAD"
2214 -
2215 -REPOMAN_BASE_PATH = os.path.join(
2216 - os.sep, os.sep.join(os.path.realpath(__file__.rstrip("co")).split(os.sep)[:-3])
2217 -)
2218 -
2219 -_not_installed = os.path.isfile(
2220 - os.path.join(REPOMAN_BASE_PATH, ".repoman_not_installed")
2221 -)
2222 -
2223 -if VERSION == "HEAD":
2224 -
2225 - class _LazyVersion(proxy.objectproxy.ObjectProxy):
2226 - def _get_target(self):
2227 - global VERSION
2228 - if VERSION is not self:
2229 - return VERSION
2230 - if os.path.isdir(os.path.join(PORTAGE_BASE_PATH, ".git")):
2231 - encoding = _encodings["fs"]
2232 - cmd = [
2233 - BASH_BINARY,
2234 - "-c",
2235 - (
2236 - "cd %s ; git describe --match 'repoman-*' || exit $? ; "
2237 - + 'if [ -n "`git diff-index --name-only --diff-filter=M HEAD`" ] ; '
2238 - + "then echo modified ; git rev-list --format=%%ct -n 1 HEAD ; fi ; "
2239 - + "exit 0"
2240 - )
2241 - % _shell_quote(PORTAGE_BASE_PATH),
2242 - ]
2243 - cmd = [
2244 - _unicode_encode(x, encoding=encoding, errors="strict") for x in cmd
2245 - ]
2246 - proc = subprocess.Popen(
2247 - cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
2248 - )
2249 - output = _unicode_decode(proc.communicate()[0], encoding=encoding)
2250 - status = proc.wait()
2251 - if os.WIFEXITED(status) and os.WEXITSTATUS(status) == os.EX_OK:
2252 - output_lines = output.splitlines()
2253 - if output_lines:
2254 - version_split = output_lines[0].split("-")
2255 - if len(version_split) > 1:
2256 - VERSION = version_split[1]
2257 - patchlevel = False
2258 - if len(version_split) > 2:
2259 - patchlevel = True
2260 - VERSION = "%s_p%s" % (VERSION, version_split[2])
2261 - if len(output_lines) > 1 and output_lines[1] == "modified":
2262 - head_timestamp = None
2263 - if len(output_lines) > 3:
2264 - try:
2265 - head_timestamp = int(output_lines[3])
2266 - except ValueError:
2267 - pass
2268 - timestamp = int(time.time())
2269 - if (
2270 - head_timestamp is not None
2271 - and timestamp > head_timestamp
2272 - ):
2273 - timestamp = timestamp - head_timestamp
2274 - if not patchlevel:
2275 - VERSION = "%s_p0" % (VERSION,)
2276 - VERSION = "%s_p%d" % (VERSION, timestamp)
2277 - return VERSION
2278 - else:
2279 - print("NO output lines :(")
2280 - VERSION = "HEAD"
2281 - return VERSION
2282 -
2283 - VERSION = _LazyVersion()
2284
2285 diff --git a/repoman/lib/repoman/_portage.py b/repoman/lib/repoman/_portage.py
2286 deleted file mode 100644
2287 index 01a2a4cf5..000000000
2288 --- a/repoman/lib/repoman/_portage.py
2289 +++ /dev/null
2290 @@ -1,26 +0,0 @@
2291 -"""repoman/_portage.py
2292 -Central location for the portage import.
2293 -There were problems when portage was imported by submodules
2294 -due to the portage instance was somehow different that the
2295 -initial portage import in main.py. The later portage imports
2296 -did not contain the repo it was working on. That repo was my cvs tree
2297 -and not listed in those subsequent portage imports.
2298 -
2299 -All modules should import portage from this one
2300 -
2301 -from repoman._portage import portage
2302 -
2303 -Then continue to import the remaining portage modules needed
2304 -"""
2305 -
2306 -import sys
2307 -
2308 -from os import path as osp
2309 -
2310 -pym_path = osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))))
2311 -sys.path.insert(0, pym_path)
2312 -
2313 -import portage
2314 -
2315 -portage._internal_caller = True
2316 -portage._disable_legacy_globals()
2317
2318 diff --git a/repoman/lib/repoman/_subprocess.py b/repoman/lib/repoman/_subprocess.py
2319 deleted file mode 100644
2320 index 08ee9e748..000000000
2321 --- a/repoman/lib/repoman/_subprocess.py
2322 +++ /dev/null
2323 @@ -1,58 +0,0 @@
2324 -# -*- coding:utf-8 -*-
2325 -
2326 -
2327 -import codecs
2328 -import subprocess
2329 -
2330 -# import our initialized portage instance
2331 -from repoman._portage import portage
2332 -from portage import _encodings, _unicode_encode
2333 -
2334 -
2335 -def repoman_getstatusoutput(cmd):
2336 - """
2337 - Implements an interface similar to getstatusoutput(), but with
2338 - customized unicode handling (see bug #310789) and without the shell.
2339 - """
2340 - args = portage.util.shlex_split(cmd)
2341 -
2342 - encoding = _encodings["fs"]
2343 - args = [_unicode_encode(x, encoding=encoding, errors="strict") for x in args]
2344 - proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
2345 - output = portage._unicode_decode(
2346 - proc.communicate()[0], encoding=encoding, errors="strict"
2347 - )
2348 - if output and output[-1] == "\n":
2349 - # getstatusoutput strips one newline
2350 - output = output[:-1]
2351 - return (proc.wait(), output)
2352 -
2353 -
2354 -class repoman_popen(portage.proxy.objectproxy.ObjectProxy):
2355 - """
2356 - Implements an interface similar to os.popen(), but with customized
2357 - unicode handling (see bug #310789) and without the shell.
2358 - """
2359 -
2360 - __slots__ = ("_proc", "_stdout")
2361 -
2362 - def __init__(self, cmd):
2363 - args = portage.util.shlex_split(cmd)
2364 -
2365 - encoding = _encodings["fs"]
2366 - args = [_unicode_encode(x, encoding=encoding, errors="strict") for x in args]
2367 - proc = subprocess.Popen(args, stdout=subprocess.PIPE)
2368 - object.__setattr__(self, "_proc", proc)
2369 - object.__setattr__(
2370 - self, "_stdout", codecs.getreader(encoding)(proc.stdout, "strict")
2371 - )
2372 -
2373 - def _get_target(self):
2374 - return object.__getattribute__(self, "_stdout")
2375 -
2376 - __enter__ = _get_target
2377 -
2378 - def __exit__(self, exc_type, exc_value, traceback):
2379 - proc = object.__getattribute__(self, "_proc")
2380 - proc.wait()
2381 - proc.stdout.close()
2382
2383 diff --git a/repoman/lib/repoman/actions.py b/repoman/lib/repoman/actions.py
2384 deleted file mode 100644
2385 index 920f0e97a..000000000
2386 --- a/repoman/lib/repoman/actions.py
2387 +++ /dev/null
2388 @@ -1,828 +0,0 @@
2389 -# -*- coding:utf-8 -*-
2390 -# Copyright 1999-2021 Gentoo Authors
2391 -# Distributed under the terms of the GNU General Public License v2
2392 -
2393 -import errno
2394 -import io
2395 -import logging
2396 -import platform
2397 -import re
2398 -import shutil
2399 -import signal
2400 -import sys
2401 -import tempfile
2402 -import time
2403 -from itertools import chain
2404 -
2405 -try:
2406 - from urllib.parse import parse_qs, urlsplit, urlunsplit
2407 -except ImportError:
2408 - from urlparse import parse_qs, urlsplit, urlunsplit
2409 -
2410 -from _emerge.UserQuery import UserQuery
2411 -
2412 -from repoman._portage import portage
2413 -from portage import os
2414 -from portage import _encodings
2415 -from portage import _unicode_encode
2416 -from portage.output import bold, create_color_func, green, red
2417 -from portage.package.ebuild.digestgen import digestgen
2418 -from portage.util import writemsg_level
2419 -
2420 -# pylint: disable=ungrouped-imports
2421 -from repoman.copyrights import update_copyright
2422 -from repoman.gpg import gpgsign, need_signature
2423 -from repoman import utilities
2424 -from repoman.modules.vcs.vcs import vcs_files_to_cps
2425 -from repoman import VERSION
2426 -
2427 -bad = create_color_func("BAD")
2428 -
2429 -
2430 -class Actions:
2431 - """Handles post check result output and performs
2432 - the various vcs activities for committing the results"""
2433 -
2434 - def __init__(self, repo_settings, options, scanner, vcs_settings):
2435 - self.repo_settings = repo_settings
2436 - self.options = options
2437 - self.scanner = scanner
2438 - self.vcs_settings = vcs_settings
2439 - self.repoman_settings = repo_settings.repoman_settings
2440 - self.suggest = {
2441 - "ignore_masked": False,
2442 - "include_dev": False,
2443 - }
2444 - if scanner.have["pmasked"] and not (
2445 - options.without_mask or options.ignore_masked
2446 - ):
2447 - self.suggest["ignore_masked"] = True
2448 - if scanner.have["dev_keywords"] and not options.include_dev:
2449 - self.suggest["include_dev"] = True
2450 -
2451 - def inform(self, can_force, result):
2452 - """Inform the user of all the problems found"""
2453 - if (
2454 - self.suggest["ignore_masked"] or self.suggest["include_dev"]
2455 - ) and not self.options.quiet:
2456 - self._suggest()
2457 - if self.options.mode != "commit":
2458 - self._non_commit(result)
2459 - return False
2460 - else:
2461 - self._fail(result, can_force)
2462 - if self.options.pretend:
2463 - utilities.repoman_sez('"So, you want to play it safe. Good call."\n')
2464 - return True
2465 -
2466 - def perform(self, qa_output):
2467 - myautoadd = self._vcs_autoadd()
2468 -
2469 - self._vcs_deleted()
2470 -
2471 - changes = self.get_vcs_changed()
2472 -
2473 - mynew, mychanged, myremoved, no_expansion, expansion = changes
2474 -
2475 - # Manifests need to be regenerated after all other commits, so don't commit
2476 - # them now even if they have changed.
2477 - mymanifests = set()
2478 - myupdates = set()
2479 - for f in mychanged + mynew:
2480 - if "Manifest" == os.path.basename(f):
2481 - mymanifests.add(f)
2482 - else:
2483 - myupdates.add(f)
2484 - myupdates.difference_update(myremoved)
2485 - myupdates = list(myupdates)
2486 - mymanifests = list(mymanifests)
2487 - myheaders = []
2488 -
2489 - commitmessage = self.options.commitmsg
2490 - if self.options.commitmsgfile:
2491 - try:
2492 - f = io.open(
2493 - _unicode_encode(
2494 - self.options.commitmsgfile,
2495 - encoding=_encodings["fs"],
2496 - errors="strict",
2497 - ),
2498 - mode="r",
2499 - encoding=_encodings["content"],
2500 - errors="replace",
2501 - )
2502 - commitmessage = f.read()
2503 - f.close()
2504 - del f
2505 - except (IOError, OSError) as e:
2506 - if e.errno == errno.ENOENT:
2507 - portage.writemsg(
2508 - "!!! File Not Found:"
2509 - " --commitmsgfile='%s'\n" % self.options.commitmsgfile
2510 - )
2511 - else:
2512 - raise
2513 - if commitmessage[:9].lower() in ("cat/pkg: ",):
2514 - commitmessage = self.msg_prefix() + commitmessage[9:]
2515 -
2516 - if commitmessage is not None and commitmessage.strip():
2517 - res, expl = self.verify_commit_message(commitmessage)
2518 - if not res:
2519 - print(bad("RepoMan does not like your commit message:"))
2520 - print(expl)
2521 - if self.options.force:
2522 - print("(but proceeding due to --force)")
2523 - else:
2524 - sys.exit(1)
2525 - else:
2526 - commitmessage = None
2527 - msg_qa_output = qa_output
2528 - initial_message = None
2529 - while True:
2530 - commitmessage = self.get_new_commit_message(
2531 - msg_qa_output, commitmessage
2532 - )
2533 - res, expl = self.verify_commit_message(commitmessage)
2534 - if res:
2535 - break
2536 - else:
2537 - full_expl = (
2538 - """Issues with the commit message were found. Please fix it or remove
2539 -the whole commit message to abort.
2540 -
2541 -"""
2542 - + expl
2543 - )
2544 - msg_qa_output = [
2545 - " %s\n" % x for x in full_expl.splitlines()
2546 - ] + qa_output
2547 -
2548 - commitmessage = commitmessage.rstrip()
2549 -
2550 - # Update copyright for new and changed files
2551 - year = time.strftime("%Y", time.gmtime())
2552 - updated_copyright = []
2553 - for fn in chain(mynew, mychanged):
2554 - if fn.endswith(".diff") or fn.endswith(".patch"):
2555 - continue
2556 - if update_copyright(fn, year, pretend=self.options.pretend):
2557 - updated_copyright.append(fn)
2558 -
2559 - if updated_copyright and not (
2560 - self.options.pretend or self.repo_settings.repo_config.thin_manifest
2561 - ):
2562 - for cp in sorted(self._vcs_files_to_cps(iter(updated_copyright))):
2563 - self._manifest_gen(cp)
2564 -
2565 - myupdates, broken_changelog_manifests = self.changelogs(
2566 - myupdates,
2567 - mymanifests,
2568 - myremoved,
2569 - mychanged,
2570 - myautoadd,
2571 - mynew,
2572 - commitmessage,
2573 - )
2574 -
2575 - lines = commitmessage.splitlines()
2576 - lastline = lines[-1]
2577 - if len(lines) == 1 or re.match(r"^\S+:\s", lastline) is None:
2578 - commitmessage += "\n"
2579 -
2580 - commit_footer = self.get_commit_footer()
2581 - commitmessage += commit_footer
2582 -
2583 - print("* %s files being committed..." % green(str(len(myupdates))), end=" ")
2584 -
2585 - if not self.vcs_settings.needs_keyword_expansion:
2586 - # With some VCS types there's never any keyword expansion, so
2587 - # there's no need to regenerate manifests and all files will be
2588 - # committed in one big commit at the end.
2589 - logging.debug("VCS type doesn't need keyword expansion")
2590 - print()
2591 - elif not self.repo_settings.repo_config.thin_manifest:
2592 - logging.debug("perform: Calling thick_manifest()")
2593 - self.vcs_settings.changes.thick_manifest(
2594 - myupdates, myheaders, no_expansion, expansion
2595 - )
2596 -
2597 - logging.info("myupdates: %s", myupdates)
2598 - logging.info("myheaders: %s", myheaders)
2599 -
2600 - uq = UserQuery(self.options)
2601 - if self.options.ask and uq.query("Commit changes?", True) != "Yes":
2602 - print("* aborting commit.")
2603 - sys.exit(128 + signal.SIGINT)
2604 -
2605 - # Handle the case where committed files have keywords which
2606 - # will change and need a priming commit before the Manifest
2607 - # can be committed.
2608 - if (myupdates or myremoved) and myheaders:
2609 - self.priming_commit(myupdates, myremoved, commitmessage)
2610 -
2611 - # When files are removed and re-added, the cvs server will put /Attic/
2612 - # inside the $Header path. This code detects the problem and corrects it
2613 - # so that the Manifest will generate correctly. See bug #169500.
2614 - # Use binary mode in order to avoid potential character encoding issues.
2615 - self.vcs_settings.changes.clear_attic(myheaders)
2616 -
2617 - if self.scanner.repolevel == 1:
2618 - utilities.repoman_sez(
2619 - "\"You're rather crazy... " 'doing the entire repository."\n'
2620 - )
2621 -
2622 - self.vcs_settings.changes.digest_regen(
2623 - myupdates, myremoved, mymanifests, self.scanner, broken_changelog_manifests
2624 - )
2625 -
2626 - if self.repo_settings.sign_manifests:
2627 - self.sign_manifest(myupdates, myremoved, mymanifests)
2628 -
2629 - self.vcs_settings.changes.update_index(mymanifests, myupdates)
2630 -
2631 - self.add_manifest(mymanifests, myheaders, myupdates, myremoved, commitmessage)
2632 -
2633 - if self.options.quiet:
2634 - return
2635 - print()
2636 - if self.vcs_settings.vcs:
2637 - print("Commit complete.")
2638 - else:
2639 - print(
2640 - "repoman was too scared"
2641 - " by not seeing any familiar version control file"
2642 - " that he forgot to commit anything"
2643 - )
2644 - utilities.repoman_sez('"If everyone were like you, I\'d be out of business!"\n')
2645 - return
2646 -
2647 - def _vcs_files_to_cps(self, vcs_file_iter):
2648 - """
2649 - Iterate over the given modified file paths returned from the vcs,
2650 - and return a frozenset containing category/pn strings for each
2651 - modified package.
2652 -
2653 - @param vcs_file_iter: file paths from vcs module
2654 - @type iter
2655 - @rtype: frozenset
2656 - @return: category/pn strings for each package.
2657 - """
2658 - return vcs_files_to_cps(
2659 - vcs_file_iter,
2660 - self.repo_settings.repodir,
2661 - self.scanner.repolevel,
2662 - self.scanner.reposplit,
2663 - self.scanner.categories,
2664 - )
2665 -
2666 - def _manifest_gen(self, cp):
2667 - """
2668 - Generate manifest for a cp.
2669 -
2670 - @param cp: category/pn string
2671 - @type str
2672 - @rtype: bool
2673 - @return: True if successful, False otherwise
2674 - """
2675 - self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, cp)
2676 - return bool(
2677 - digestgen(
2678 - mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb
2679 - )
2680 - )
2681 -
2682 - def _suggest(self):
2683 - print()
2684 - if self.suggest["ignore_masked"]:
2685 - print(
2686 - bold(
2687 - "Note: use --without-mask to check "
2688 - "KEYWORDS on dependencies of masked packages"
2689 - )
2690 - )
2691 -
2692 - if self.suggest["include_dev"]:
2693 - print(
2694 - bold(
2695 - "Note: use --include-dev (-d) to check "
2696 - "dependencies for 'dev' profiles"
2697 - )
2698 - )
2699 - print()
2700 -
2701 - def _non_commit(self, result):
2702 - if result["full"]:
2703 - print(bold('Note: type "repoman full" for a complete listing.'))
2704 - if result["warn"] and not result["fail"]:
2705 - if self.options.quiet:
2706 - print(bold("Non-Fatal QA errors found"))
2707 - else:
2708 - utilities.repoman_sez(
2709 - "\"You're only giving me a partial QA payment?\n"
2710 - " I'll take it this time, but I'm not happy.\""
2711 - )
2712 - elif not result["fail"]:
2713 - if self.options.quiet:
2714 - print("No QA issues found")
2715 - else:
2716 - utilities.repoman_sez(
2717 - '"If everyone were like you, I\'d be out of business!"'
2718 - )
2719 - elif result["fail"]:
2720 - print(bad("Please fix these important QA issues first."))
2721 - if not self.options.quiet:
2722 - utilities.repoman_sez(
2723 - '"Make your QA payment on time'
2724 - " and you'll never see the likes of me.\"\n"
2725 - )
2726 -
2727 - def _fail(self, result, can_force):
2728 - if (
2729 - result["fail"]
2730 - and can_force
2731 - and self.options.force
2732 - and not self.options.pretend
2733 - ):
2734 - utilities.repoman_sez(
2735 - ' "You want to commit even with these QA issues?\n'
2736 - " I'll take it this time, but I'm not happy.\"\n"
2737 - )
2738 - elif result["fail"]:
2739 - if self.options.force and not can_force:
2740 - print(
2741 - bad(
2742 - "The --force option has been disabled"
2743 - " due to extraordinary issues."
2744 - )
2745 - )
2746 - print(bad("Please fix these important QA issues first."))
2747 - utilities.repoman_sez(
2748 - '"Make your QA payment on time'
2749 - " and you'll never see the likes of me.\"\n"
2750 - )
2751 - sys.exit(1)
2752 -
2753 - def _vcs_autoadd(self):
2754 - myunadded = self.vcs_settings.changes.unadded
2755 - myautoadd = []
2756 - if myunadded:
2757 - for x in range(len(myunadded) - 1, -1, -1):
2758 - xs = myunadded[x].split("/")
2759 - if (
2760 - any(token.startswith(".") and token != "." for token in xs)
2761 - or self.repo_settings.repo_config.find_invalid_path_char(
2762 - myunadded[x]
2763 - )
2764 - != -1
2765 - ):
2766 - # The Manifest excludes this file,
2767 - # so it's safe to ignore.
2768 - del myunadded[x]
2769 - elif xs[-1] == "files":
2770 - print("!!! files dir is not added! Please correct this.")
2771 - sys.exit(-1)
2772 - elif xs[-1] == "Manifest":
2773 - # It's a manifest... auto add
2774 - myautoadd += [myunadded[x]]
2775 - del myunadded[x]
2776 -
2777 - if myunadded:
2778 - print(
2779 - red(
2780 - "!!! The following files are in your local tree"
2781 - " but are not added to the master"
2782 - )
2783 - )
2784 - print(
2785 - red(
2786 - "!!! tree. Please remove them from the local tree"
2787 - " or add them to the master tree."
2788 - )
2789 - )
2790 - for x in myunadded:
2791 - print(" ", x)
2792 - print()
2793 - print()
2794 - sys.exit(1)
2795 - return myautoadd
2796 -
2797 - def _vcs_deleted(self):
2798 - if self.vcs_settings.changes.has_deleted:
2799 - print(
2800 - red(
2801 - "!!! The following files are removed manually"
2802 - " from your local tree but are not"
2803 - )
2804 - )
2805 - print(
2806 - red(
2807 - "!!! removed from the repository."
2808 - ' Please remove them, using "%s remove [FILES]".'
2809 - % self.vcs_settings.vcs
2810 - )
2811 - )
2812 - for x in self.vcs_settings.changes.deleted:
2813 - print(" ", x)
2814 - print()
2815 - print()
2816 - sys.exit(1)
2817 -
2818 - def get_vcs_changed(self):
2819 - """Holding function which calls the approriate VCS module for the data"""
2820 - changes = self.vcs_settings.changes
2821 - # re-run the scan to pick up a newly modified Manifest file
2822 - logging.debug("RE-scanning for changes...")
2823 - changes.scan()
2824 -
2825 - if not changes.has_changes:
2826 - utilities.repoman_sez('"Doing nothing is not always good for QA."')
2827 - print()
2828 - print("(Didn't find any changed files...)")
2829 - print()
2830 - sys.exit(1)
2831 - return (
2832 - changes.new,
2833 - changes.changed,
2834 - changes.removed,
2835 - changes.no_expansion,
2836 - changes.expansion,
2837 - )
2838 -
2839 - https_bugtrackers = frozenset(
2840 - [
2841 - "bitbucket.org",
2842 - "bugs.gentoo.org",
2843 - "github.com",
2844 - "gitlab.com",
2845 - ]
2846 - )
2847 -
2848 - def get_commit_footer(self):
2849 - portage_version = getattr(portage, "VERSION", None)
2850 - gpg_key = self.repoman_settings.get("PORTAGE_GPG_KEY", "")
2851 - signoff = self.repoman_settings.get("SIGNED_OFF_BY", "")
2852 - report_options = []
2853 - if self.options.force:
2854 - report_options.append("--force")
2855 - if self.options.ignore_arches:
2856 - report_options.append("--ignore-arches")
2857 - if self.scanner.include_arches is not None:
2858 - report_options.append(
2859 - '--include-arches="%s"' % " ".join(sorted(self.scanner.include_arches))
2860 - )
2861 - if self.scanner.include_profiles is not None:
2862 - report_options.append(
2863 - '--include-profiles="%s"'
2864 - % " ".join(sorted(self.scanner.include_profiles))
2865 - )
2866 -
2867 - if portage_version is None:
2868 - sys.stderr.write("Failed to insert portage version in message!\n")
2869 - sys.stderr.flush()
2870 - portage_version = "Unknown"
2871 -
2872 - # Common part of commit footer
2873 - commit_footer = ""
2874 - for tag, bug in chain(
2875 - (("Bug", x) for x in self.options.bug),
2876 - (("Closes", x) for x in self.options.closes),
2877 - ):
2878 - # case 1: pure number NNNNNN
2879 - if bug.isdigit():
2880 - bug = "https://bugs.gentoo.org/%s" % (bug,)
2881 - else:
2882 - purl = urlsplit(bug)
2883 - qs = parse_qs(purl.query)
2884 - # case 2: long Gentoo bugzilla URL to shorten
2885 - if (
2886 - purl.netloc == "bugs.gentoo.org"
2887 - and purl.path == "/show_bug.cgi"
2888 - and tuple(qs.keys()) == ("id",)
2889 - ):
2890 - bug = urlunsplit(
2891 - ("https", purl.netloc, qs["id"][-1], "", purl.fragment)
2892 - )
2893 - # case 3: bug tracker w/ http -> https
2894 - elif purl.scheme == "http" and purl.netloc in self.https_bugtrackers:
2895 - bug = urlunsplit(("https",) + purl[1:])
2896 - commit_footer += "\n%s: %s" % (tag, bug)
2897 -
2898 - # Use new footer only for git (see bug #438364).
2899 - if self.vcs_settings.vcs in ["git"]:
2900 - commit_footer += "\nPackage-Manager: Portage-%s, Repoman-%s" % (
2901 - portage.VERSION,
2902 - VERSION,
2903 - )
2904 - if report_options:
2905 - commit_footer += "\nRepoMan-Options: " + " ".join(report_options)
2906 - if self.repo_settings.sign_manifests:
2907 - commit_footer += "\nManifest-Sign-Key: %s" % (gpg_key,)
2908 - else:
2909 - unameout = platform.system() + " "
2910 - if platform.system() in ["Darwin", "SunOS"]:
2911 - unameout += platform.processor()
2912 - else:
2913 - unameout += platform.machine()
2914 - commit_footer += "\n(Portage version: %s/%s/%s" % (
2915 - portage_version,
2916 - self.vcs_settings.vcs,
2917 - unameout,
2918 - )
2919 - if report_options:
2920 - commit_footer += ", RepoMan options: " + " ".join(report_options)
2921 - if self.repo_settings.sign_manifests:
2922 - commit_footer += ", signed Manifest commit with key %s" % (gpg_key,)
2923 - else:
2924 - commit_footer += ", unsigned Manifest commit"
2925 - commit_footer += ")"
2926 -
2927 - if signoff:
2928 - commit_footer += "\nSigned-off-by: %s" % (signoff,)
2929 -
2930 - return commit_footer
2931 -
2932 - def changelogs(
2933 - self,
2934 - myupdates,
2935 - mymanifests,
2936 - myremoved,
2937 - mychanged,
2938 - myautoadd,
2939 - mynew,
2940 - changelog_msg,
2941 - ):
2942 - broken_changelog_manifests = []
2943 - if self.options.echangelog in ("y", "force"):
2944 - logging.info("checking for unmodified ChangeLog files")
2945 - committer_name = utilities.get_committer_name(env=self.repoman_settings)
2946 - for x in sorted(
2947 - vcs_files_to_cps(
2948 - chain(myupdates, mymanifests, myremoved),
2949 - self.repo_settings.repodir,
2950 - self.scanner.repolevel,
2951 - self.scanner.reposplit,
2952 - self.scanner.categories,
2953 - )
2954 - ):
2955 - catdir, pkgdir = x.split("/")
2956 - checkdir = self.repo_settings.repodir + "/" + x
2957 - checkdir_relative = ""
2958 - if self.scanner.repolevel < 3:
2959 - checkdir_relative = os.path.join(pkgdir, checkdir_relative)
2960 - if self.scanner.repolevel < 2:
2961 - checkdir_relative = os.path.join(catdir, checkdir_relative)
2962 - checkdir_relative = os.path.join(".", checkdir_relative)
2963 -
2964 - changelog_path = os.path.join(checkdir_relative, "ChangeLog")
2965 - changelog_modified = changelog_path in self.scanner.changed.changelogs
2966 - if changelog_modified and self.options.echangelog != "force":
2967 - continue
2968 -
2969 - # get changes for this package
2970 - cdrlen = len(checkdir_relative)
2971 - check_relative = lambda e: e.startswith(checkdir_relative)
2972 - split_relative = lambda e: e[cdrlen:]
2973 - clnew = list(map(split_relative, filter(check_relative, mynew)))
2974 - clremoved = list(map(split_relative, filter(check_relative, myremoved)))
2975 - clchanged = list(map(split_relative, filter(check_relative, mychanged)))
2976 -
2977 - # Skip ChangeLog generation if only the Manifest was modified,
2978 - # as discussed in bug #398009.
2979 - nontrivial_cl_files = set()
2980 - nontrivial_cl_files.update(clnew, clremoved, clchanged)
2981 - nontrivial_cl_files.difference_update(["Manifest"])
2982 - if not nontrivial_cl_files and self.options.echangelog != "force":
2983 - continue
2984 -
2985 - new_changelog = utilities.UpdateChangeLog(
2986 - checkdir_relative,
2987 - committer_name,
2988 - changelog_msg,
2989 - os.path.join(self.repo_settings.repodir, "skel.ChangeLog"),
2990 - catdir,
2991 - pkgdir,
2992 - new=clnew,
2993 - removed=clremoved,
2994 - changed=clchanged,
2995 - pretend=self.options.pretend,
2996 - )
2997 - if new_changelog is None:
2998 - writemsg_level(
2999 - "!!! Updating the ChangeLog failed\n",
3000 - level=logging.ERROR,
3001 - noiselevel=-1,
3002 - )
3003 - sys.exit(1)
3004 -
3005 - # if the ChangeLog was just created, add it to vcs
3006 - if new_changelog:
3007 - myautoadd.append(changelog_path)
3008 - # myautoadd is appended to myupdates below
3009 - else:
3010 - myupdates.append(changelog_path)
3011 -
3012 - if self.options.ask and not self.options.pretend:
3013 - # regenerate Manifest for modified ChangeLog (bug #420735)
3014 - self.repoman_settings["O"] = checkdir
3015 - digestgen(
3016 - mysettings=self.repoman_settings,
3017 - myportdb=self.repo_settings.portdb,
3018 - )
3019 - else:
3020 - broken_changelog_manifests.append(x)
3021 -
3022 - if myautoadd:
3023 - print(">>> Auto-Adding missing Manifest/ChangeLog file(s)...")
3024 - self.vcs_settings.changes.add_items(myautoadd)
3025 - myupdates += myautoadd
3026 - return myupdates, broken_changelog_manifests
3027 -
3028 - def add_manifest(self, mymanifests, myheaders, myupdates, myremoved, commitmessage):
3029 - myfiles = mymanifests[:]
3030 - # If there are no header (SVN/CVS keywords) changes in
3031 - # the files, this Manifest commit must include the
3032 - # other (yet uncommitted) files.
3033 - if not myheaders:
3034 - myfiles += myupdates
3035 - myfiles += myremoved
3036 - myfiles.sort()
3037 -
3038 - commitmessagedir = tempfile.mkdtemp(".repoman.msg")
3039 - commitmessagefile = os.path.join(commitmessagedir, "COMMIT_EDITMSG")
3040 - with open(commitmessagefile, "wb") as mymsg:
3041 - mymsg.write(_unicode_encode(commitmessage))
3042 -
3043 - retval = self.vcs_settings.changes.commit(myfiles, commitmessagefile)
3044 - # cleanup the commit message before possibly exiting
3045 - try:
3046 - shutil.rmtree(commitmessagedir)
3047 - except OSError:
3048 - pass
3049 - if retval != os.EX_OK:
3050 - writemsg_level(
3051 - "!!! Exiting on %s (shell) "
3052 - "error code: %s\n" % (self.vcs_settings.vcs, retval),
3053 - level=logging.ERROR,
3054 - noiselevel=-1,
3055 - )
3056 - sys.exit(retval)
3057 -
3058 - def priming_commit(self, myupdates, myremoved, commitmessage):
3059 - myfiles = myupdates + myremoved
3060 - commitmessagedir = tempfile.mkdtemp(".repoman.msg")
3061 - commitmessagefile = os.path.join(commitmessagedir, "COMMIT_EDITMSG")
3062 - with open(commitmessagefile, "wb") as mymsg:
3063 - mymsg.write(_unicode_encode(commitmessage))
3064 -
3065 - separator = "-" * 78
3066 -
3067 - print()
3068 - print(green("Using commit message:"))
3069 - print(green(separator))
3070 - print(commitmessage)
3071 - print(green(separator))
3072 - print()
3073 -
3074 - # Having a leading ./ prefix on file paths can trigger a bug in
3075 - # the cvs server when committing files to multiple directories,
3076 - # so strip the prefix.
3077 - myfiles = [f.lstrip("./") for f in myfiles]
3078 -
3079 - retval = self.vcs_settings.changes.commit(myfiles, commitmessagefile)
3080 - # cleanup the commit message before possibly exiting
3081 - try:
3082 - shutil.rmtree(commitmessagedir)
3083 - except OSError:
3084 - pass
3085 - if retval != os.EX_OK:
3086 - writemsg_level(
3087 - "!!! Exiting on %s (shell) "
3088 - "error code: %s\n" % (self.vcs_settings.vcs, retval),
3089 - level=logging.ERROR,
3090 - noiselevel=-1,
3091 - )
3092 - sys.exit(retval)
3093 -
3094 - def sign_manifest(self, myupdates, myremoved, mymanifests):
3095 - try:
3096 - for x in sorted(
3097 - vcs_files_to_cps(
3098 - chain(myupdates, myremoved, mymanifests),
3099 - self.scanner.repo_settings.repodir,
3100 - self.scanner.repolevel,
3101 - self.scanner.reposplit,
3102 - self.scanner.categories,
3103 - )
3104 - ):
3105 - self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
3106 - manifest_path = os.path.join(self.repoman_settings["O"], "Manifest")
3107 - if not need_signature(manifest_path):
3108 - continue
3109 - gpgsign(manifest_path, self.repoman_settings, self.options)
3110 - except portage.exception.PortageException as e:
3111 - portage.writemsg("!!! %s\n" % str(e))
3112 - portage.writemsg("!!! Disabled FEATURES='sign'\n")
3113 - self.repo_settings.sign_manifests = False
3114 -
3115 - def msg_prefix(self):
3116 - prefix = ""
3117 - if self.scanner.repolevel > 1:
3118 - prefix = "/".join(self.scanner.reposplit[1:]) + ": "
3119 - return prefix
3120 -
3121 - def get_new_commit_message(self, qa_output, old_message=None):
3122 - msg_prefix = old_message or self.msg_prefix()
3123 - try:
3124 - editor = os.environ.get("EDITOR")
3125 - if editor and utilities.editor_is_executable(editor):
3126 - commitmessage = utilities.get_commit_message_with_editor(
3127 - editor, message=qa_output, prefix=msg_prefix
3128 - )
3129 - else:
3130 - print(
3131 - "EDITOR is unset or invalid. Please set EDITOR to your preferred editor."
3132 - )
3133 - print(bad("* no EDITOR found for commit message, aborting commit."))
3134 - sys.exit(1)
3135 - except KeyboardInterrupt:
3136 - logging.fatal("Interrupted; exiting...")
3137 - sys.exit(1)
3138 - if (
3139 - not commitmessage
3140 - or not commitmessage.strip()
3141 - or commitmessage.strip() == msg_prefix
3142 - ):
3143 - print("* no commit message? aborting commit.")
3144 - sys.exit(1)
3145 - return commitmessage
3146 -
3147 - @staticmethod
3148 - def verify_commit_message(msg):
3149 - """
3150 - Check whether the message roughly complies with GLEP66. Returns
3151 - (True, None) if it does, (False, <explanation>) if it does not.
3152 - """
3153 -
3154 - problems = []
3155 - paras = msg.strip().split("\n\n")
3156 - summary = paras.pop(0)
3157 -
3158 - if ":" not in summary:
3159 - problems.append(
3160 - 'summary line must start with a logical unit name, e.g. "cat/pkg:"'
3161 - )
3162 - if "\n" in summary.strip():
3163 - problems.append(
3164 - "commit message must start with a *single* line of summary, followed by empty line"
3165 - )
3166 - # accept 69 overall or unit+50, in case of very long package names
3167 - elif len(summary.strip()) > 69 and len(summary.split(":", 1)[-1]) > 50:
3168 - problems.append("summary line is too long (max 69 characters)")
3169 -
3170 - multiple_footers = False
3171 - gentoo_bug_used = False
3172 - bug_closes_without_url = False
3173 - body_too_long = False
3174 -
3175 - footer_re = re.compile(r"^[\w-]+:")
3176 -
3177 - found_footer = False
3178 - for p in paras:
3179 - lines = p.splitlines()
3180 - # if all lines look like footer material, we assume it's footer
3181 - # else, we assume it's body text
3182 - if all(footer_re.match(l) for l in lines if l.strip()):
3183 - # multiple footer-like blocks?
3184 - if found_footer:
3185 - multiple_footers = True
3186 - found_footer = True
3187 - for l in lines:
3188 - if l.startswith("Gentoo-Bug"):
3189 - gentoo_bug_used = True
3190 - elif l.startswith("Bug:") or l.startswith("Closes:"):
3191 - if "http://" not in l and "https://" not in l:
3192 - bug_closes_without_url = True
3193 - else:
3194 - for l in lines:
3195 - # we recommend wrapping at 72 but accept up to 80;
3196 - # do not complain if we have single word (usually
3197 - # it means very long URL)
3198 - if len(l.strip()) > 80 and len(l.split()) > 1:
3199 - body_too_long = True
3200 -
3201 - if multiple_footers:
3202 - problems.append(
3203 - "multiple footer-style blocks found, please combine them into one"
3204 - )
3205 - if gentoo_bug_used:
3206 - problems.append(
3207 - "please replace Gentoo-Bug with GLEP 66-compliant Bug/Closes"
3208 - )
3209 - if bug_closes_without_url:
3210 - problems.append("Bug/Closes footers require full URL")
3211 - if body_too_long:
3212 - problems.append("body lines should be wrapped at 72 (max 80) characters")
3213 -
3214 - if problems:
3215 - return (False, "\n".join("- %s" % x for x in problems))
3216 - return (True, None)
3217
3218 diff --git a/repoman/lib/repoman/argparser.py b/repoman/lib/repoman/argparser.py
3219 deleted file mode 100644
3220 index 019c7381b..000000000
3221 --- a/repoman/lib/repoman/argparser.py
3222 +++ /dev/null
3223 @@ -1,388 +0,0 @@
3224 -# repoman: Argument parser
3225 -# Copyright 2007-2021 Gentoo Authors
3226 -# Distributed under the terms of the GNU General Public License v2
3227 -
3228 -"""This module contains functions used in Repoman to parse CLI arguments."""
3229 -
3230 -import argparse
3231 -import logging
3232 -
3233 -# import our initialized portage instance
3234 -from repoman._portage import portage
3235 -
3236 -from portage import _unicode_decode
3237 -from portage import util
3238 -
3239 -
3240 -def parse_args(argv, repoman_default_opts):
3241 - """Use a customized optionParser to parse command line arguments for repoman
3242 - Args:
3243 - argv - a sequence of command line arguments
3244 - Returns:
3245 - (opts, args), just like a call to parser.parse_args()
3246 - """
3247 -
3248 - argv = portage._decode_argv(argv)
3249 -
3250 - modes = {
3251 - "commit": "Run a scan then commit changes",
3252 - "ci": "Run a scan then commit changes",
3253 - "fix": "Fix simple QA issues (stray digests, missing digests)",
3254 - "full": "Scan directory tree and print all issues (not a summary)",
3255 - "help": "Show this screen",
3256 - "manifest": "Generate a Manifest (fetches files if necessary)",
3257 - "manifest-check": "Check Manifests for missing or incorrect digests",
3258 - "scan": "Scan directory tree for QA issues",
3259 - }
3260 -
3261 - output_choices = {
3262 - "default": "The normal output format",
3263 - "column": "Columnar output suitable for use with grep",
3264 - }
3265 -
3266 - mode_keys = list(modes)
3267 - mode_keys.sort()
3268 -
3269 - output_keys = sorted(output_choices)
3270 -
3271 - parser = argparse.ArgumentParser(
3272 - usage="repoman [options] [mode]",
3273 - description="Modes: %s" % " | ".join(mode_keys),
3274 - epilog="For more help consult the man page.",
3275 - )
3276 -
3277 - parser.add_argument(
3278 - "-a",
3279 - "--ask",
3280 - dest="ask",
3281 - action="store_true",
3282 - default=False,
3283 - help="Request a confirmation before commiting",
3284 - )
3285 -
3286 - parser.add_argument(
3287 - "-b",
3288 - "--bug",
3289 - dest="bug",
3290 - action="append",
3291 - metavar="<BUG-NO|BUG-URL>",
3292 - default=[],
3293 - help=(
3294 - "Mention a Gentoo or upstream bug in the commit footer; "
3295 - "takes either Gentoo bug number or full bug URL"
3296 - ),
3297 - )
3298 -
3299 - parser.add_argument(
3300 - "-c",
3301 - "--closes",
3302 - dest="closes",
3303 - action="append",
3304 - metavar="<PR-NO|PR-URL>",
3305 - default=[],
3306 - help=(
3307 - "Adds a Closes footer to close GitHub pull request (or compatible); "
3308 - "takes either GitHub PR number or full PR URL"
3309 - ),
3310 - )
3311 -
3312 - parser.add_argument(
3313 - "-m",
3314 - "--commitmsg",
3315 - dest="commitmsg",
3316 - help="specify a commit message on the command line",
3317 - )
3318 -
3319 - parser.add_argument(
3320 - "-M",
3321 - "--commitmsgfile",
3322 - dest="commitmsgfile",
3323 - help="specify a path to a file that contains a commit message",
3324 - )
3325 -
3326 - parser.add_argument(
3327 - "--digest",
3328 - choices=("y", "n"),
3329 - metavar="<y|n>",
3330 - help="Automatically update Manifest digests for modified files",
3331 - )
3332 -
3333 - parser.add_argument(
3334 - "-p",
3335 - "--pretend",
3336 - dest="pretend",
3337 - default=False,
3338 - action="store_true",
3339 - help="don't commit or fix anything; just show what would be done",
3340 - )
3341 -
3342 - parser.add_argument(
3343 - "-q",
3344 - "--quiet",
3345 - dest="quiet",
3346 - action="count",
3347 - default=0,
3348 - help="do not print unnecessary messages",
3349 - )
3350 -
3351 - parser.add_argument(
3352 - "--echangelog",
3353 - choices=("y", "n", "force"),
3354 - metavar="<y|n|force>",
3355 - help=(
3356 - "for commit mode, call echangelog if ChangeLog is unmodified (or "
3357 - "regardless of modification if 'force' is specified)"
3358 - ),
3359 - )
3360 -
3361 - parser.add_argument(
3362 - "--experimental-inherit",
3363 - choices=("y", "n"),
3364 - metavar="<y|n>",
3365 - default="n",
3366 - help=(
3367 - "Enable experimental inherit.missing checks which may misbehave"
3368 - " when the internal eclass database becomes outdated"
3369 - ),
3370 - )
3371 -
3372 - parser.add_argument(
3373 - "--experimental-repository-modules",
3374 - choices=("y", "n"),
3375 - metavar="<y|n>",
3376 - default="n",
3377 - help="Enable experimental repository modules",
3378 - )
3379 -
3380 - parser.add_argument(
3381 - "-f",
3382 - "--force",
3383 - dest="force",
3384 - action="store_true",
3385 - default=False,
3386 - help="Commit with QA violations",
3387 - )
3388 -
3389 - parser.add_argument(
3390 - "-S",
3391 - "--straight-to-stable",
3392 - dest="straight_to_stable",
3393 - default=False,
3394 - action="store_true",
3395 - help="Allow committing straight to stable",
3396 - )
3397 -
3398 - parser.add_argument(
3399 - "--vcs", dest="vcs", help="Force using specific VCS instead of autodetection"
3400 - )
3401 -
3402 - parser.add_argument(
3403 - "-v",
3404 - "--verbose",
3405 - dest="verbosity",
3406 - action="count",
3407 - help="be very verbose in output",
3408 - default=0,
3409 - )
3410 -
3411 - parser.add_argument(
3412 - "-V", "--version", dest="version", action="store_true", help="show version info"
3413 - )
3414 -
3415 - parser.add_argument(
3416 - "-x",
3417 - "--xmlparse",
3418 - dest="xml_parse",
3419 - action="store_true",
3420 - default=False,
3421 - help="forces the metadata.xml parse check to be carried out",
3422 - )
3423 -
3424 - parser.add_argument(
3425 - "--if-modified",
3426 - choices=("y", "n"),
3427 - default="n",
3428 - metavar="<y|n>",
3429 - help="only check packages that have uncommitted modifications",
3430 - )
3431 -
3432 - parser.add_argument(
3433 - "-i",
3434 - "--ignore-arches",
3435 - dest="ignore_arches",
3436 - action="store_true",
3437 - default=False,
3438 - help="ignore arch-specific failures (where arch != host)",
3439 - )
3440 -
3441 - parser.add_argument(
3442 - "--ignore-default-opts",
3443 - action="store_true",
3444 - help="do not use the REPOMAN_DEFAULT_OPTS environment variable",
3445 - )
3446 -
3447 - parser.add_argument(
3448 - "-I",
3449 - "--ignore-masked",
3450 - dest="ignore_masked",
3451 - action="store_true",
3452 - default=False,
3453 - help="ignore masked packages (not allowed with commit mode)",
3454 - )
3455 -
3456 - parser.add_argument(
3457 - "--include-arches",
3458 - dest="include_arches",
3459 - metavar="ARCHES",
3460 - action="append",
3461 - help=(
3462 - "A space separated list of arches used to "
3463 - "filter the selection of profiles for dependency checks"
3464 - ),
3465 - )
3466 -
3467 - parser.add_argument(
3468 - "--include-profiles",
3469 - dest="include_profiles",
3470 - metavar="PROFILES",
3471 - action="append",
3472 - help=(
3473 - "A space separated list of profiles used to "
3474 - "define the selection of profiles for dependency checks"
3475 - ),
3476 - )
3477 -
3478 - parser.add_argument(
3479 - "-d",
3480 - "--include-dev",
3481 - dest="include_dev",
3482 - action="store_true",
3483 - default=False,
3484 - help="include dev profiles in dependency checks",
3485 - )
3486 -
3487 - parser.add_argument(
3488 - "-e",
3489 - "--include-exp-profiles",
3490 - choices=("y", "n"),
3491 - metavar="<y|n>",
3492 - default=False,
3493 - help="include exp profiles in dependency checks",
3494 - )
3495 -
3496 - parser.add_argument(
3497 - "--unmatched-removal",
3498 - dest="unmatched_removal",
3499 - action="store_true",
3500 - default=False,
3501 - help=(
3502 - "enable strict checking of package.mask and package.unmask files"
3503 - " for unmatched removal atoms"
3504 - ),
3505 - )
3506 -
3507 - parser.add_argument(
3508 - "--without-mask",
3509 - dest="without_mask",
3510 - action="store_true",
3511 - default=False,
3512 - help=(
3513 - "behave as if no package.mask entries exist"
3514 - " (not allowed with commit mode)"
3515 - ),
3516 - )
3517 -
3518 - parser.add_argument(
3519 - "--output-style",
3520 - dest="output_style",
3521 - choices=output_keys,
3522 - help="select output type",
3523 - default="default",
3524 - )
3525 -
3526 - parser.add_argument(
3527 - "-j",
3528 - "--jobs",
3529 - dest="jobs",
3530 - action="store",
3531 - type=int,
3532 - default=1,
3533 - help="Specifies the number of jobs (processes) to run simultaneously.",
3534 - )
3535 -
3536 - parser.add_argument(
3537 - "-l",
3538 - "--load-average",
3539 - dest="load_average",
3540 - action="store",
3541 - type=float,
3542 - default=None,
3543 - help="Specifies that no new jobs (processes) should be started if there are others "
3544 - "jobs running and the load average is at least load (a floating-point number).",
3545 - )
3546 -
3547 - parser.add_argument(
3548 - "--mode",
3549 - dest="mode",
3550 - choices=mode_keys,
3551 - help="specify which mode repoman will run in (default=full)",
3552 - )
3553 -
3554 - # Modes help is included earlier, in the parser description.
3555 - parser.add_argument(
3556 - "mode_positional",
3557 - nargs="?",
3558 - metavar="mode",
3559 - choices=mode_keys,
3560 - help=argparse.SUPPRESS,
3561 - )
3562 -
3563 - opts = parser.parse_args(argv[1:])
3564 -
3565 - if not opts.ignore_default_opts:
3566 - default_opts = util.shlex_split(repoman_default_opts)
3567 - if default_opts:
3568 - opts = parser.parse_args(default_opts + argv[1:])
3569 -
3570 - args = []
3571 - if opts.mode is not None:
3572 - args.append(opts.mode)
3573 - if opts.mode_positional is not None:
3574 - args.append(opts.mode_positional)
3575 -
3576 - if len(set(args)) > 1:
3577 - parser.error("multiple modes specified: %s" % " ".join(args))
3578 -
3579 - opts.mode = args[0] if args else None
3580 -
3581 - if opts.mode == "help":
3582 - parser.print_help()
3583 - parser.exit()
3584 -
3585 - if not opts.mode:
3586 - opts.mode = "full"
3587 -
3588 - if opts.mode == "ci":
3589 - opts.mode = "commit" # backwards compat shortcut
3590 -
3591 - # Use verbosity and quiet options to appropriately fiddle with the loglevel
3592 - for val in range(opts.verbosity):
3593 - logger = logging.getLogger()
3594 - logger.setLevel(logger.getEffectiveLevel() - 10)
3595 -
3596 - for val in range(opts.quiet):
3597 - logger = logging.getLogger()
3598 - logger.setLevel(logger.getEffectiveLevel() + 10)
3599 -
3600 - if opts.mode == "commit" and opts.commitmsg:
3601 - opts.commitmsg = _unicode_decode(opts.commitmsg)
3602 -
3603 - if opts.mode == "commit" and not (opts.force or opts.pretend):
3604 - if opts.ignore_masked:
3605 - opts.ignore_masked = False
3606 - logging.warn("Commit mode automatically disables --ignore-masked")
3607 - if opts.without_mask:
3608 - opts.without_mask = False
3609 - logging.warn("Commit mode automatically disables --without-mask")
3610 -
3611 - return (opts, args)
3612
3613 diff --git a/repoman/lib/repoman/check_missingslot.py b/repoman/lib/repoman/check_missingslot.py
3614 deleted file mode 100644
3615 index 4d2d7676b..000000000
3616 --- a/repoman/lib/repoman/check_missingslot.py
3617 +++ /dev/null
3618 @@ -1,39 +0,0 @@
3619 -# -*- coding:utf-8 -*-
3620 -# repoman: missing slot check
3621 -# Copyright 2014 Gentoo Foundation
3622 -# Distributed under the terms of the GNU General Public License v2
3623 -
3624 -"""This module contains the check used to find missing slot values
3625 -in dependencies."""
3626 -
3627 -from portage.eapi import eapi_has_slot_operator
3628 -
3629 -
3630 -def check_missingslot(atom, mytype, eapi, portdb, qatracker, relative_path, my_aux):
3631 - # If no slot or slot operator is specified in RDEP...
3632 - if (
3633 - not atom.blocker
3634 - and not atom.slot
3635 - and not atom.slot_operator
3636 - and mytype == "RDEPEND"
3637 - and eapi_has_slot_operator(eapi)
3638 - ):
3639 - # Check whether it doesn't match more than one.
3640 - atom_matches = portdb.xmatch("match-all", atom)
3641 - dep_slots = frozenset(
3642 - portdb.aux_get(cpv, ["SLOT"])[0].split("/")[0] for cpv in atom_matches
3643 - )
3644 -
3645 - if len(dep_slots) > 1:
3646 - # See if it is a DEPEND as well. It's a very simple & dumb
3647 - # check but should suffice for catching it.
3648 - depend = my_aux["DEPEND"].split()
3649 - if atom not in depend:
3650 - return
3651 -
3652 - qatracker.add_error(
3653 - "dependency.missingslot",
3654 - relative_path
3655 - + ": %s: '%s' matches more than one slot, please specify an explicit slot and/or use the := or :* slot operator"
3656 - % (mytype, atom),
3657 - )
3658
3659 diff --git a/repoman/lib/repoman/checks/__init__.py b/repoman/lib/repoman/checks/__init__.py
3660 deleted file mode 100644
3661 index e69de29bb..000000000
3662
3663 diff --git a/repoman/lib/repoman/config.py b/repoman/lib/repoman/config.py
3664 deleted file mode 100644
3665 index 621143de4..000000000
3666 --- a/repoman/lib/repoman/config.py
3667 +++ /dev/null
3668 @@ -1,172 +0,0 @@
3669 -# -*- coding:utf-8 -*-
3670 -
3671 -import copy
3672 -import itertools
3673 -import json
3674 -import os
3675 -import stat
3676 -
3677 -try:
3678 - import yaml
3679 -except ImportError:
3680 - yaml = None
3681 -
3682 -
3683 -class ConfigError(Exception):
3684 - """Raised when a config file fails to load"""
3685 -
3686 - pass
3687 -
3688 -
3689 -def merge_config(base, head):
3690 - """
3691 - Merge two JSON or YAML documents into a single object. Arrays are
3692 - merged by extension. If dissimilar types are encountered, then the
3693 - head value overwrites the base value.
3694 - """
3695 -
3696 - if isinstance(head, dict):
3697 - if not isinstance(base, dict):
3698 - return copy.deepcopy(head)
3699 -
3700 - result = {}
3701 - for k in itertools.chain(head, base):
3702 - try:
3703 - result[k] = merge_config(base[k], head[k])
3704 - except KeyError:
3705 - try:
3706 - result[k] = copy.deepcopy(head[k])
3707 - except KeyError:
3708 - result[k] = copy.deepcopy(base[k])
3709 -
3710 - elif isinstance(head, list):
3711 - result = []
3712 - if not isinstance(base, list):
3713 - result.extend(copy.deepcopy(x) for x in head)
3714 - else:
3715 - if any(isinstance(x, (dict, list)) for x in itertools.chain(head, base)):
3716 - # merge items with identical indexes
3717 - for x, y in zip(base, head):
3718 - if isinstance(x, (dict, list)):
3719 - result.append(merge_config(x, y))
3720 - else:
3721 - # head overwrites base (preserving index)
3722 - result.append(copy.deepcopy(y))
3723 - # copy remaining items from the longer list
3724 - if len(base) != len(head):
3725 - if len(base) > len(head):
3726 - result.extend(copy.deepcopy(x) for x in base[len(head) :])
3727 - else:
3728 - result.extend(copy.deepcopy(x) for x in head[len(base) :])
3729 - else:
3730 - result.extend(copy.deepcopy(x) for x in base)
3731 - result.extend(copy.deepcopy(x) for x in head)
3732 -
3733 - else:
3734 - result = copy.deepcopy(head)
3735 -
3736 - return result
3737 -
3738 -
3739 -def _yaml_load(filename):
3740 - """
3741 - Load filename as YAML and return a dict. Raise ConfigError if
3742 - it fails to load.
3743 - """
3744 - if yaml is None:
3745 - raise ImportError("Please install pyyaml in order to read yaml files")
3746 -
3747 - with open(filename, "rt") as f:
3748 - try:
3749 - return yaml.safe_load(f)
3750 - except yaml.parser.ParserError as e:
3751 - raise ConfigError("{}: {}".format(filename, e))
3752 -
3753 -
3754 -def _json_load(filename):
3755 - """
3756 - Load filename as JSON and return a dict. Raise ConfigError if
3757 - it fails to load.
3758 - """
3759 - with open(filename, "rt") as f:
3760 - try:
3761 - return json.load(f) # nosec
3762 - except ValueError as e:
3763 - raise ConfigError("{}: {}".format(filename, e))
3764 -
3765 -
3766 -def iter_files(files_dirs):
3767 - """
3768 - Iterate over nested file paths in lexical order.
3769 - """
3770 - stack = list(reversed(files_dirs))
3771 - while stack:
3772 - location = stack.pop()
3773 - try:
3774 - st = os.stat(location)
3775 - except FileNotFoundError:
3776 - continue
3777 -
3778 - if stat.S_ISDIR(st.st_mode):
3779 - stack.extend(
3780 - os.path.join(location, x)
3781 - for x in sorted(os.listdir(location), reverse=True)
3782 - )
3783 -
3784 - elif stat.S_ISREG(st.st_mode):
3785 - yield location
3786 -
3787 -
3788 -def load_config(conf_dirs, file_extensions=None, valid_versions=None):
3789 - """
3790 - Load JSON and/or YAML files from a directories, and merge them together
3791 - into a single object.
3792 -
3793 - @param conf_dirs: ordered iterable of directories to load the config from
3794 - @param file_extensions: Optional list of file extension types to load
3795 - @param valid_versions: list of compatible file versions allowed
3796 - @returns: the stacked config
3797 - """
3798 -
3799 - result = {}
3800 - for filename in iter_files(conf_dirs):
3801 - if file_extensions is not None and not filename.endswith(file_extensions):
3802 - continue
3803 -
3804 - loaders = []
3805 - extension = filename.rsplit(".", 1)[1]
3806 - if extension in ["json"]:
3807 - loaders.append(_json_load)
3808 - elif extension in ["yml", "yaml"]:
3809 - loaders.append(_yaml_load)
3810 -
3811 - config = None
3812 - exception = None
3813 - for loader in loaders:
3814 - try:
3815 - config = loader(filename) or {}
3816 - except ConfigError as e:
3817 - exception = e
3818 - else:
3819 - break
3820 -
3821 - if config is None:
3822 - print("Repoman.config.load_config(), Error loading file: %s" % filename)
3823 - print(" Aborting...")
3824 - raise exception
3825 -
3826 - if config:
3827 - if config["version"] not in valid_versions:
3828 - raise ConfigError(
3829 - "Invalid file version: %s in: %s\nPlease upgrade to "
3830 - ">=app-portage/repoman-%s, current valid API versions: %s"
3831 - % (
3832 - config["version"],
3833 - filename,
3834 - config["repoman_version"],
3835 - valid_versions,
3836 - )
3837 - )
3838 - result = merge_config(result, config)
3839 -
3840 - return result
3841
3842 diff --git a/repoman/lib/repoman/copyrights.py b/repoman/lib/repoman/copyrights.py
3843 deleted file mode 100644
3844 index 199f5efbf..000000000
3845 --- a/repoman/lib/repoman/copyrights.py
3846 +++ /dev/null
3847 @@ -1,143 +0,0 @@
3848 -# -*- coding:utf-8 -*-
3849 -
3850 -
3851 -import difflib
3852 -import io
3853 -import re
3854 -from tempfile import mkstemp
3855 -
3856 -from portage import _encodings
3857 -from portage import _unicode_decode
3858 -from portage import _unicode_encode
3859 -from portage import os
3860 -from portage import shutil
3861 -from portage import util
3862 -
3863 -
3864 -_copyright_re1 = re.compile(
3865 - rb"^(# Copyright \d\d\d\d)-\d\d\d\d( Gentoo (Foundation|Authors))\b"
3866 -)
3867 -_copyright_re2 = re.compile(
3868 - rb"^(# Copyright )(\d\d\d\d)( Gentoo (Foundation|Authors))\b"
3869 -)
3870 -
3871 -
3872 -class _copyright_repl:
3873 - __slots__ = ("year",)
3874 -
3875 - def __init__(self, year):
3876 - self.year = year
3877 -
3878 - def __call__(self, matchobj):
3879 - if matchobj.group(2) == self.year:
3880 - return matchobj.group(0)
3881 - else:
3882 - return (
3883 - matchobj.group(1)
3884 - + matchobj.group(2)
3885 - + b"-"
3886 - + self.year
3887 - + b" Gentoo Authors"
3888 - )
3889 -
3890 -
3891 -def update_copyright_year(year, line):
3892 - """
3893 - These two regexes are taken from echangelog
3894 - update_copyright(), except that we don't hardcode
3895 - 1999 here (in order to be more generic).
3896 - """
3897 - is_bytes = isinstance(line, bytes)
3898 - if is_bytes:
3899 - if not line.startswith(b"# Copyright "):
3900 - return line
3901 - else:
3902 - if not line.startswith("# Copyright "):
3903 - return line
3904 -
3905 - year = _unicode_encode(year)
3906 - line = _unicode_encode(line)
3907 -
3908 - line = _copyright_re1.sub(rb"\1-" + year + b" Gentoo Authors", line)
3909 - line = _copyright_re2.sub(_copyright_repl(year), line)
3910 - if not is_bytes:
3911 - line = _unicode_decode(line)
3912 - return line
3913 -
3914 -
3915 -def update_copyright(fn_path, year, pretend=False):
3916 - """
3917 - Check file for a Copyright statement, and update its year. The
3918 - patterns used for replacing copyrights are taken from echangelog.
3919 - Only the first lines of each file that start with a hash ('#') are
3920 - considered, until a line is found that doesn't start with a hash.
3921 - Files are read and written in binary mode, so that this function
3922 - will work correctly with files encoded in any character set, as
3923 - long as the copyright statements consist of plain ASCII.
3924 -
3925 - @param fn_path: file path
3926 - @type str
3927 - @param year: current year
3928 - @type str
3929 - @param pretend: pretend mode
3930 - @type bool
3931 - @rtype: bool
3932 - @return: True if copyright update was needed, False otherwise
3933 - """
3934 -
3935 - try:
3936 - fn_hdl = io.open(
3937 - _unicode_encode(fn_path, encoding=_encodings["fs"], errors="strict"),
3938 - mode="rb",
3939 - )
3940 - except EnvironmentError:
3941 - return
3942 -
3943 - orig_header = []
3944 - new_header = []
3945 -
3946 - for line in fn_hdl:
3947 - line_strip = line.strip()
3948 - orig_header.append(line)
3949 - if not line_strip or line_strip[:1] != b"#":
3950 - new_header.append(line)
3951 - break
3952 -
3953 - line = update_copyright_year(year, line)
3954 - new_header.append(line)
3955 -
3956 - difflines = 0
3957 - for diffline in difflib.unified_diff(
3958 - [_unicode_decode(diffline) for diffline in orig_header],
3959 - [_unicode_decode(diffline) for diffline in new_header],
3960 - fromfile=fn_path,
3961 - tofile=fn_path,
3962 - n=0,
3963 - ):
3964 - util.writemsg_stdout(diffline, noiselevel=-1)
3965 - difflines += 1
3966 - util.writemsg_stdout("\n", noiselevel=-1)
3967 -
3968 - # unified diff has three lines to start with
3969 - if difflines > 3 and not pretend:
3970 - # write new file with changed header
3971 - f, fnnew_path = mkstemp()
3972 - f = io.open(f, mode="wb")
3973 - for line in new_header:
3974 - f.write(line)
3975 - for line in fn_hdl:
3976 - f.write(line)
3977 - f.close()
3978 - try:
3979 - fn_stat = os.stat(fn_path)
3980 - except OSError:
3981 - fn_stat = None
3982 -
3983 - shutil.move(fnnew_path, fn_path)
3984 -
3985 - if fn_stat is None:
3986 - util.apply_permissions(fn_path, mode=0o644)
3987 - else:
3988 - util.apply_stat_permissions(fn_path, fn_stat)
3989 - fn_hdl.close()
3990 - return difflines > 3
3991
3992 diff --git a/repoman/lib/repoman/errors.py b/repoman/lib/repoman/errors.py
3993 deleted file mode 100644
3994 index c3ee92d37..000000000
3995 --- a/repoman/lib/repoman/errors.py
3996 +++ /dev/null
3997 @@ -1,21 +0,0 @@
3998 -# -*- coding:utf-8 -*-
3999 -
4000 -import sys
4001 -
4002 -
4003 -def warn(txt):
4004 - print("repoman: " + txt)
4005 -
4006 -
4007 -def err(txt):
4008 - warn(txt)
4009 - sys.exit(1)
4010 -
4011 -
4012 -def caterror(catdir, repodir):
4013 - err(
4014 - "%s is not an official category."
4015 - " Skipping QA checks in this directory.\n"
4016 - "Please ensure that you add %s to %s/profiles/categories\n"
4017 - "if it is a new category." % (catdir, catdir, repodir)
4018 - )
4019
4020 diff --git a/repoman/lib/repoman/gpg.py b/repoman/lib/repoman/gpg.py
4021 deleted file mode 100644
4022 index 10e884e52..000000000
4023 --- a/repoman/lib/repoman/gpg.py
4024 +++ /dev/null
4025 @@ -1,73 +0,0 @@
4026 -# -*- coding:utf-8 -*-
4027 -
4028 -import errno
4029 -import logging
4030 -import subprocess
4031 -
4032 -import portage
4033 -from portage import os
4034 -from portage import _encodings
4035 -from portage import _unicode_encode
4036 -from portage.exception import MissingParameter
4037 -
4038 -
4039 -# Setup the GPG commands
4040 -def gpgsign(filename, repoman_settings, options):
4041 - gpgcmd = repoman_settings.get("PORTAGE_GPG_SIGNING_COMMAND")
4042 - if gpgcmd in [None, ""]:
4043 - raise MissingParameter(
4044 - "PORTAGE_GPG_SIGNING_COMMAND is unset!" " Is make.globals missing?"
4045 - )
4046 - if "${PORTAGE_GPG_KEY}" in gpgcmd and "PORTAGE_GPG_KEY" not in repoman_settings:
4047 - raise MissingParameter("PORTAGE_GPG_KEY is unset!")
4048 - if "${PORTAGE_GPG_DIR}" in gpgcmd:
4049 - if "PORTAGE_GPG_DIR" not in repoman_settings:
4050 - repoman_settings["PORTAGE_GPG_DIR"] = os.path.expanduser("~/.gnupg")
4051 - logging.info(
4052 - "Automatically setting PORTAGE_GPG_DIR to '%s'"
4053 - % repoman_settings["PORTAGE_GPG_DIR"]
4054 - )
4055 - else:
4056 - repoman_settings["PORTAGE_GPG_DIR"] = os.path.expanduser(
4057 - repoman_settings["PORTAGE_GPG_DIR"]
4058 - )
4059 - if not os.access(repoman_settings["PORTAGE_GPG_DIR"], os.X_OK):
4060 - raise portage.exception.InvalidLocation(
4061 - "Unable to access directory: PORTAGE_GPG_DIR='%s'"
4062 - % repoman_settings["PORTAGE_GPG_DIR"]
4063 - )
4064 - gpgvars = {"FILE": filename}
4065 - for k in ("PORTAGE_GPG_DIR", "PORTAGE_GPG_KEY"):
4066 - v = repoman_settings.get(k)
4067 - if v is not None:
4068 - gpgvars[k] = v
4069 - gpgcmd = portage.util.varexpand(gpgcmd, mydict=gpgvars)
4070 - if options.pretend:
4071 - print("(" + gpgcmd + ")")
4072 - else:
4073 - # Encode unicode manually for bug #310789.
4074 - gpgcmd = portage.util.shlex_split(gpgcmd)
4075 -
4076 - gpgcmd = [
4077 - _unicode_encode(arg, encoding=_encodings["fs"], errors="strict")
4078 - for arg in gpgcmd
4079 - ]
4080 - rValue = subprocess.call(gpgcmd)
4081 - if rValue == os.EX_OK:
4082 - os.rename(filename + ".asc", filename)
4083 - else:
4084 - raise portage.exception.PortageException(
4085 - "!!! gpg exited with '" + str(rValue) + "' status"
4086 - )
4087 -
4088 -
4089 -def need_signature(filename):
4090 - try:
4091 - with open(
4092 - _unicode_encode(filename, encoding=_encodings["fs"], errors="strict"), "rb"
4093 - ) as f:
4094 - return b"BEGIN PGP SIGNED MESSAGE" not in f.readline()
4095 - except IOError as e:
4096 - if e.errno in (errno.ENOENT, errno.ESTALE):
4097 - return False
4098 - raise
4099
4100 diff --git a/repoman/lib/repoman/main.py b/repoman/lib/repoman/main.py
4101 deleted file mode 100755
4102 index 1cfe86e8d..000000000
4103 --- a/repoman/lib/repoman/main.py
4104 +++ /dev/null
4105 @@ -1,255 +0,0 @@
4106 -#!/usr/bin/env python
4107 -# -*- coding:utf-8 -*-
4108 -# Copyright 1999-2021 Gentoo Authors
4109 -# Distributed under the terms of the GNU General Public License v2
4110 -
4111 -import collections
4112 -import io
4113 -import logging
4114 -import sys
4115 -
4116 -# import our centrally initialized portage instance
4117 -from repoman._portage import portage
4118 -
4119 -portage._internal_caller = True
4120 -portage._disable_legacy_globals()
4121 -
4122 -
4123 -from portage import os
4124 -import portage.checksum
4125 -import portage.const
4126 -import portage.repository.config
4127 -from portage.output import create_color_func, nocolor
4128 -from portage.output import ConsoleStyleFile, StyleWriter
4129 -from portage.util import formatter
4130 -from portage.util.futures.extendedfutures import (
4131 - ExtendedFuture,
4132 -)
4133 -
4134 -# pylint: disable=ungrouped-imports
4135 -from repoman.actions import Actions
4136 -from repoman.argparser import parse_args
4137 -from repoman.qa_data import QAData
4138 -from repoman.qa_data import format_qa_output, format_qa_output_column
4139 -from repoman.repos import RepoSettings
4140 -from repoman.scanner import Scanner
4141 -from repoman import utilities
4142 -from repoman.modules.vcs.settings import VCSSettings
4143 -from repoman import VERSION
4144 -
4145 -
4146 -bad = create_color_func("BAD")
4147 -
4148 -# A sane umask is needed for files that portage creates.
4149 -os.umask(0o22)
4150 -
4151 -LOGLEVEL = logging.WARNING
4152 -portage.util.initialize_logger(LOGLEVEL)
4153 -
4154 -VALID_VERSIONS = [
4155 - 1,
4156 -]
4157 -
4158 -_repoman_main_vars = collections.namedtuple(
4159 - "_repoman_main_vars",
4160 - (
4161 - "can_force",
4162 - "exitcode",
4163 - "options",
4164 - "qadata",
4165 - "repo_settings",
4166 - "scanner",
4167 - "vcs_settings",
4168 - ),
4169 -)
4170 -
4171 -
4172 -def repoman_main(argv):
4173 - repoman_vars = _repoman_init(argv)
4174 - if repoman_vars.exitcode is not None:
4175 - return repoman_vars.exitcode
4176 - result = _repoman_scan(*repoman_vars)
4177 - return _handle_result(*repoman_vars, result)
4178 -
4179 -
4180 -def _repoman_init(argv):
4181 - config_root = os.environ.get("PORTAGE_CONFIGROOT")
4182 - repoman_settings = portage.config(config_root=config_root, local_config=False)
4183 - repoman_settings.valid_versions = VALID_VERSIONS
4184 -
4185 - if (
4186 - repoman_settings.get("NOCOLOR", "").lower() in ("yes", "true")
4187 - or repoman_settings.get("TERM") == "dumb"
4188 - or not sys.stdout.isatty()
4189 - ):
4190 - nocolor()
4191 -
4192 - options, arguments = parse_args(
4193 - argv, repoman_settings.get("REPOMAN_DEFAULT_OPTS", "")
4194 - )
4195 -
4196 - if options.version:
4197 - print("Repoman", VERSION, "(portage-%s)" % portage.VERSION)
4198 - return _repoman_main_vars(None, 0, None, None, None, None, None)
4199 -
4200 - logger = logging.getLogger()
4201 -
4202 - if options.verbosity > 0:
4203 - logger.setLevel(LOGLEVEL - 10 * options.verbosity)
4204 - else:
4205 - logger.setLevel(LOGLEVEL)
4206 -
4207 - # Set this to False when an extraordinary issue (generally
4208 - # something other than a QA issue) makes it impossible to
4209 - # commit (like if Manifest generation fails).
4210 - can_force = ExtendedFuture(True)
4211 - repo_settings, vcs_settings, scanner, qadata = _create_scanner(
4212 - options, can_force, config_root, repoman_settings
4213 - )
4214 - return _repoman_main_vars(
4215 - can_force, None, options, qadata, repo_settings, scanner, vcs_settings
4216 - )
4217 -
4218 -
4219 -def _create_scanner(options, can_force, config_root, repoman_settings):
4220 -
4221 - portdir, portdir_overlay, mydir = utilities.FindPortdir(repoman_settings)
4222 - if portdir is None:
4223 - return (None, None, None, None)
4224 -
4225 - myreporoot = os.path.basename(portdir_overlay)
4226 - myreporoot += mydir[len(portdir_overlay) :]
4227 -
4228 - # avoid a circular parameter repo_settings
4229 - vcs_settings = VCSSettings(options, repoman_settings)
4230 - qadata = QAData()
4231 -
4232 - logging.debug("repoman_main: RepoSettings init")
4233 - repo_settings = RepoSettings(
4234 - config_root,
4235 - portdir,
4236 - portdir_overlay,
4237 - repoman_settings,
4238 - vcs_settings,
4239 - options,
4240 - qadata,
4241 - )
4242 - repoman_settings = repo_settings.repoman_settings
4243 - repoman_settings.valid_versions = VALID_VERSIONS
4244 -
4245 - # Now set repo_settings
4246 - vcs_settings.repo_settings = repo_settings
4247 - # set QATracker qacats, qawarnings
4248 - vcs_settings.qatracker.qacats = repo_settings.qadata.qacats
4249 - vcs_settings.qatracker.qawarnings = repo_settings.qadata.qawarnings
4250 - logging.debug("repoman_main: vcs_settings done")
4251 - logging.debug("repoman_main: qadata: %s", repo_settings.qadata)
4252 -
4253 - if "digest" in repoman_settings.features and options.digest != "n":
4254 - options.digest = "y"
4255 -
4256 - logging.debug("vcs: %s" % (vcs_settings.vcs,))
4257 - logging.debug("repo config: %s" % (repo_settings.repo_config,))
4258 - logging.debug("options: %s" % (options,))
4259 -
4260 - # It's confusing if these warnings are displayed without the user
4261 - # being told which profile they come from, so disable them.
4262 - env = os.environ.copy()
4263 - env["FEATURES"] = env.get("FEATURES", "") + " -unknown-features-warn"
4264 -
4265 - # Perform the main checks
4266 - scanner = Scanner(
4267 - repo_settings, myreporoot, config_root, options, vcs_settings, mydir, env
4268 - )
4269 - return repo_settings, vcs_settings, scanner, qadata
4270 -
4271 -
4272 -def _repoman_scan(
4273 - can_force, exitcode, options, qadata, repo_settings, scanner, vcs_settings
4274 -):
4275 - scanner.scan_pkgs(can_force)
4276 -
4277 - if options.if_modified == "y" and len(scanner.effective_scanlist) < 1:
4278 - logging.warning(
4279 - "--if-modified is enabled, but no modified packages were found!"
4280 - )
4281 -
4282 - result = {
4283 - # fail will be true if we have failed in at least one non-warning category
4284 - "fail": 0,
4285 - # warn will be true if we tripped any warnings
4286 - "warn": 0,
4287 - # full will be true if we should print a "repoman full" informational message
4288 - "full": options.mode != "full",
4289 - }
4290 -
4291 - for x in qadata.qacats:
4292 - if x not in vcs_settings.qatracker.fails:
4293 - continue
4294 - result["warn"] = 1
4295 - if x not in qadata.qawarnings:
4296 - result["fail"] = 1
4297 -
4298 - if result["fail"] or (
4299 - result["warn"] and not (options.quiet or options.mode == "scan")
4300 - ):
4301 - result["full"] = 0
4302 -
4303 - return result
4304 -
4305 -
4306 -def _handle_result(
4307 - can_force, exitcode, options, qadata, repo_settings, scanner, vcs_settings, result
4308 -):
4309 - commitmessage = None
4310 - if options.commitmsg:
4311 - commitmessage = options.commitmsg
4312 - elif options.commitmsgfile:
4313 - # we don't need the actual text of the commit message here
4314 - # the filename will do for the next code block
4315 - commitmessage = options.commitmsgfile
4316 -
4317 - # Save QA output so that it can be conveniently displayed
4318 - # in $EDITOR while the user creates a commit message.
4319 - # Otherwise, the user would not be able to see this output
4320 - # once the editor has taken over the screen.
4321 - qa_output = io.StringIO()
4322 - style_file = ConsoleStyleFile(sys.stdout)
4323 - if options.mode == "commit" and (not commitmessage or not commitmessage.strip()):
4324 - style_file.write_listener = qa_output
4325 - console_writer = StyleWriter(file=style_file, maxcol=9999)
4326 - console_writer.style_listener = style_file.new_styles
4327 -
4328 - f = formatter.AbstractFormatter(console_writer)
4329 -
4330 - format_outputs = {"column": format_qa_output_column, "default": format_qa_output}
4331 -
4332 - format_output = format_outputs.get(options.output_style, format_outputs["default"])
4333 - format_output(
4334 - f,
4335 - vcs_settings.qatracker.fails,
4336 - result["full"],
4337 - result["fail"],
4338 - options,
4339 - qadata.qawarnings,
4340 - )
4341 -
4342 - style_file.flush()
4343 - del console_writer, f, style_file
4344 -
4345 - # early out for manifest generation
4346 - if options.mode == "manifest":
4347 - return 1 if result["fail"] else 0
4348 -
4349 - qa_output = qa_output.getvalue()
4350 - qa_output = qa_output.splitlines(True)
4351 -
4352 - # output the results
4353 - actions = Actions(repo_settings, options, scanner, vcs_settings)
4354 - if actions.inform(can_force.get(), result):
4355 - # perform any other actions
4356 - actions.perform(qa_output)
4357 - elif result["fail"]:
4358 - return 1
4359 -
4360 - return 0
4361
4362 diff --git a/repoman/lib/repoman/metadata.py b/repoman/lib/repoman/metadata.py
4363 deleted file mode 100644
4364 index 5dc44b119..000000000
4365 --- a/repoman/lib/repoman/metadata.py
4366 +++ /dev/null
4367 @@ -1,89 +0,0 @@
4368 -# -*- coding:utf-8 -*-
4369 -
4370 -import errno
4371 -import logging
4372 -import time
4373 -
4374 -# import our initialized portage instance
4375 -from repoman._portage import portage
4376 -
4377 -from portage import os
4378 -from portage.output import green
4379 -from portage.package.ebuild.fetch import fetch
4380 -
4381 -
4382 -# Note: This URI is hardcoded in all metadata.xml files. We can't
4383 -# change it without updating all the xml files in the tree.
4384 -metadata_dtd_uri = "https://www.gentoo.org/dtd/metadata.dtd"
4385 -metadata_xsd_uri = "https://www.gentoo.org/xml-schema/metadata.xsd"
4386 -# force refetch if the local copy creation time is older than this
4387 -metadata_xsd_ctime_interval = 60 * 60 * 24 * 7 # 7 days
4388 -
4389 -
4390 -def fetch_metadata_xsd(metadata_xsd, repoman_settings):
4391 - """
4392 - Fetch metadata.xsd if it doesn't exist or the ctime is older than
4393 - metadata_xsd_ctime_interval.
4394 - @rtype: bool
4395 - @return: True if successful, otherwise False
4396 - """
4397 -
4398 - must_fetch = True
4399 - metadata_xsd_st = None
4400 - current_time = int(time.time())
4401 - try:
4402 - metadata_xsd_st = os.stat(metadata_xsd)
4403 - except EnvironmentError as e:
4404 - if e.errno not in (errno.ENOENT, errno.ESTALE):
4405 - raise
4406 - del e
4407 - else:
4408 - # Trigger fetch if metadata.xsd mtime is old or clock is wrong.
4409 - if abs(current_time - metadata_xsd_st.st_ctime) < metadata_xsd_ctime_interval:
4410 - must_fetch = False
4411 -
4412 - if must_fetch:
4413 - print()
4414 - print(
4415 - "%s the local copy of metadata.xsd "
4416 - "needs to be refetched, doing that now" % green("***")
4417 - )
4418 - print()
4419 -
4420 - if not fetch([metadata_xsd_uri], repoman_settings, force=1, try_mirrors=0):
4421 - logging.error("failed to fetch metadata.xsd from '%s'" % metadata_xsd_uri)
4422 - return False
4423 -
4424 - try:
4425 - portage.util.apply_secpass_permissions(
4426 - metadata_xsd, gid=portage.data.portage_gid, mode=0o664, mask=0o2
4427 - )
4428 - except portage.exception.PortageException:
4429 - pass
4430 -
4431 - return True
4432 -
4433 -
4434 -def get_metadata_xsd(repo_settings):
4435 - """Locate and or fetch the metadata.xsd file
4436 -
4437 - @param repo_settings: RepoSettings instance
4438 - @returns: path to the metadata.xsd file
4439 - """
4440 - metadata_xsd = None
4441 - paths = list(repo_settings.repo_config.eclass_db.porttrees)
4442 - paths.reverse()
4443 - # add the test copy
4444 - paths.append("/usr/lib/portage/cnf/")
4445 - for path in paths:
4446 - path = os.path.join(path, "metadata/xml-schema/metadata.xsd")
4447 - if os.path.exists(path):
4448 - metadata_xsd = path
4449 - break
4450 - if metadata_xsd is None:
4451 - metadata_xsd = os.path.join(
4452 - repo_settings.repoman_settings["DISTDIR"], "metadata.xsd"
4453 - )
4454 -
4455 - fetch_metadata_xsd(metadata_xsd, repo_settings.repoman_settings)
4456 - return metadata_xsd
4457
4458 diff --git a/repoman/lib/repoman/modules/__init__.py b/repoman/lib/repoman/modules/__init__.py
4459 deleted file mode 100644
4460 index e69de29bb..000000000
4461
4462 diff --git a/repoman/lib/repoman/modules/commit/__init__.py b/repoman/lib/repoman/modules/commit/__init__.py
4463 deleted file mode 100644
4464 index e69de29bb..000000000
4465
4466 diff --git a/repoman/lib/repoman/modules/commit/manifest.py b/repoman/lib/repoman/modules/commit/manifest.py
4467 deleted file mode 100644
4468 index e282ad406..000000000
4469 --- a/repoman/lib/repoman/modules/commit/manifest.py
4470 +++ /dev/null
4471 @@ -1,122 +0,0 @@
4472 -# -*- coding:utf-8 -*-
4473 -
4474 -import logging
4475 -
4476 -# import our initialized portage instance
4477 -from repoman._portage import portage
4478 -
4479 -from portage import os
4480 -from portage.package.ebuild.digestgen import digestgen
4481 -from portage.util import writemsg_level
4482 -
4483 -
4484 -class Manifest:
4485 - """Creates as well as checks pkg Manifest entries/files"""
4486 -
4487 - def __init__(self, **kwargs):
4488 - """Class init
4489 -
4490 - @param options: the run time cli options
4491 - @param portdb: portdb instance
4492 - @param repo_settings: repository settings instance
4493 - """
4494 - self.options = kwargs.get("options")
4495 - self.portdb = kwargs.get("portdb")
4496 - self.repoman_settings = kwargs.get("repo_settings").repoman_settings
4497 - self.generated_manifest = False
4498 -
4499 - def update_manifest(self, checkdir):
4500 - """Perform a manifest generation for the pkg
4501 -
4502 - @param checkdir: the current package directory
4503 - @rtype: bool
4504 - @return: True if successful, False otherwise
4505 - """
4506 - self.generated_manifest = False
4507 - failed = False
4508 - self.auto_assumed = set()
4509 - fetchlist_dict = portage.FetchlistDict(
4510 - checkdir, self.repoman_settings, self.portdb
4511 - )
4512 - if self.options.mode == "manifest" and self.options.force:
4513 - self._discard_dist_digests(checkdir, fetchlist_dict)
4514 - self.repoman_settings["O"] = checkdir
4515 - try:
4516 - self.generated_manifest = digestgen(
4517 - mysettings=self.repoman_settings, myportdb=self.portdb
4518 - )
4519 - except portage.exception.PermissionDenied as e:
4520 - self.generated_manifest = False
4521 - writemsg_level(
4522 - "!!! Permission denied: '%s'\n" % (e,),
4523 - level=logging.ERROR,
4524 - noiselevel=-1,
4525 - )
4526 -
4527 - if not self.generated_manifest:
4528 - writemsg_level(
4529 - "!!! Unable to generate manifest for '%s'.\n" % (checkdir,),
4530 - level=logging.ERROR,
4531 - noiselevel=-1,
4532 - )
4533 - failed = True
4534 -
4535 - if self.options.mode == "manifest":
4536 - if (
4537 - not failed
4538 - and self.options.force
4539 - and self.auto_assumed
4540 - and "assume-digests" in self.repoman_settings.features
4541 - ):
4542 - # Show which digests were assumed despite the --force option
4543 - # being given. This output will already have been shown by
4544 - # digestgen() if assume-digests is not enabled, so only show
4545 - # it here if assume-digests is enabled.
4546 - pkgs = list(fetchlist_dict)
4547 - pkgs.sort()
4548 - portage.writemsg_stdout(
4549 - " digest.assumed %s"
4550 - % portage.output.colorize(
4551 - "WARN", str(len(self.auto_assumed)).rjust(18)
4552 - )
4553 - + "\n"
4554 - )
4555 - for cpv in pkgs:
4556 - fetchmap = fetchlist_dict[cpv]
4557 - pf = portage.catsplit(cpv)[1]
4558 - for distfile in sorted(fetchmap):
4559 - if distfile in self.auto_assumed:
4560 - portage.writemsg_stdout(" %s::%s\n" % (pf, distfile))
4561 - return not failed
4562 -
4563 - def _discard_dist_digests(self, checkdir, fetchlist_dict):
4564 - """Discard DIST digests for files that exist in DISTDIR
4565 -
4566 - This method is intended to be called prior to digestgen, only for
4567 - manifest mode with the --force option, in order to discard DIST
4568 - digests that we intend to update. This is necessary because
4569 - digestgen never replaces existing digests, since otherwise it
4570 - would be too easy for ebuild developers to accidentally corrupt
4571 - existing DIST digests.
4572 -
4573 - @param checkdir: the directory to generate the Manifest in
4574 - @param fetchlist_dict: dictionary of files to fetch and/or include
4575 - in the manifest
4576 - """
4577 - portage._doebuild_manifest_exempt_depend += 1
4578 - try:
4579 - distdir = self.repoman_settings["DISTDIR"]
4580 - mf = self.repoman_settings.repositories.get_repo_for_location(
4581 - os.path.dirname(os.path.dirname(checkdir))
4582 - )
4583 - mf = mf.load_manifest(checkdir, distdir, fetchlist_dict=fetchlist_dict)
4584 - mf.create(requiredDistfiles=None, assumeDistHashesAlways=True)
4585 - for distfiles in fetchlist_dict.values():
4586 - for distfile in distfiles:
4587 - if os.path.isfile(os.path.join(distdir, distfile)):
4588 - mf.fhashdict["DIST"].pop(distfile, None)
4589 - else:
4590 - self.auto_assumed.add(distfile)
4591 - mf.write()
4592 - finally:
4593 - portage._doebuild_manifest_exempt_depend -= 1
4594
4595 diff --git a/repoman/lib/repoman/modules/commit/repochecks.py b/repoman/lib/repoman/modules/commit/repochecks.py
4596 deleted file mode 100644
4597 index 32466021e..000000000
4598 --- a/repoman/lib/repoman/modules/commit/repochecks.py
4599 +++ /dev/null
4600 @@ -1,44 +0,0 @@
4601 -# -*- coding:utf-8 -*-
4602 -
4603 -from portage.output import red
4604 -
4605 -from repoman.errors import err
4606 -
4607 -
4608 -def commit_check(repolevel, reposplit):
4609 - # Check if it's in $PORTDIR/$CATEGORY/$PN , otherwise bail if commiting.
4610 - # Reason for this is if they're trying to commit in just $FILESDIR/*,
4611 - # the Manifest needs updating.
4612 - # This check ensures that repoman knows where it is,
4613 - # and the manifest recommit is at least possible.
4614 - if repolevel not in [1, 2, 3]:
4615 - print(
4616 - red("***")
4617 - + (
4618 - " Commit attempts *must* be from within a vcs checkout,"
4619 - " category, or package directory."
4620 - )
4621 - )
4622 - print(
4623 - red("***")
4624 - + (
4625 - " Attempting to commit from a packages files directory"
4626 - " will be blocked for instance."
4627 - )
4628 - )
4629 - print(
4630 - red("***")
4631 - + (
4632 - " This is intended behaviour,"
4633 - " to ensure the manifest is recommitted for a package."
4634 - )
4635 - )
4636 - print(red("***"))
4637 - err(
4638 - "Unable to identify level we're commiting from for %s" % "/".join(reposplit)
4639 - )
4640 -
4641 -
4642 -def conflict_check(vcs_settings, options):
4643 - if vcs_settings.vcs:
4644 - conflicts = vcs_settings.status.detect_conflicts(options)
4645
4646 diff --git a/repoman/lib/repoman/modules/linechecks/__init__.py b/repoman/lib/repoman/modules/linechecks/__init__.py
4647 deleted file mode 100644
4648 index e69de29bb..000000000
4649
4650 diff --git a/repoman/lib/repoman/modules/linechecks/assignment/__init__.py b/repoman/lib/repoman/modules/linechecks/assignment/__init__.py
4651 deleted file mode 100644
4652 index df2844cf5..000000000
4653 --- a/repoman/lib/repoman/modules/linechecks/assignment/__init__.py
4654 +++ /dev/null
4655 @@ -1,27 +0,0 @@
4656 -# Copyright 2015-2021 Gentoo Authors
4657 -# Distributed under the terms of the GNU General Public License v2
4658 -
4659 -doc = """Assignment plug-in module for repoman LineChecks.
4660 -Performs assignments checks on ebuilds."""
4661 -__doc__ = doc[:]
4662 -
4663 -
4664 -module_spec = {
4665 - "name": "assignment",
4666 - "description": doc,
4667 - "provides": {
4668 - "assignment-check": {
4669 - "name": "assignment",
4670 - "sourcefile": "assignment",
4671 - "class": "EbuildAssignment",
4672 - "description": doc,
4673 - },
4674 - "eapi3-check": {
4675 - "name": "eapi3assignment",
4676 - "sourcefile": "assignment",
4677 - "class": "Eapi3EbuildAssignment",
4678 - "description": doc,
4679 - },
4680 - },
4681 - "version": 1,
4682 -}
4683
4684 diff --git a/repoman/lib/repoman/modules/linechecks/assignment/assignment.py b/repoman/lib/repoman/modules/linechecks/assignment/assignment.py
4685 deleted file mode 100644
4686 index 2fbdef7ae..000000000
4687 --- a/repoman/lib/repoman/modules/linechecks/assignment/assignment.py
4688 +++ /dev/null
4689 @@ -1,38 +0,0 @@
4690 -import re
4691 -
4692 -from portage.eapi import eapi_supports_prefix, eapi_has_broot
4693 -from repoman.modules.linechecks.base import LineCheck
4694 -
4695 -
4696 -class EbuildAssignment(LineCheck):
4697 - """Ensure ebuilds don't assign to readonly variables."""
4698 -
4699 - repoman_check_name = "variable.readonly"
4700 - read_only_vars = "A|CATEGORY|P|P[VNRF]|PVR|D|WORKDIR|FILESDIR|FEATURES|USE"
4701 - readonly_assignment = re.compile(r"^\s*(export\s+)?(%s)=" % read_only_vars)
4702 -
4703 - def check(self, num, line):
4704 - match = self.readonly_assignment.match(line)
4705 - e = None
4706 - if match is not None:
4707 - e = self.errors["READONLY_ASSIGNMENT_ERROR"]
4708 - return e
4709 -
4710 -
4711 -class Eapi3EbuildAssignment(EbuildAssignment):
4712 - """Ensure ebuilds don't assign to readonly EAPI 3-introduced variables."""
4713 -
4714 - read_only_vars = "ED|EPREFIX|EROOT"
4715 - readonly_assignment = re.compile(r"\s*(export\s+)?(%s)=" % read_only_vars)
4716 -
4717 - def check_eapi(self, eapi):
4718 - return eapi_supports_prefix(eapi)
4719 -
4720 -
4721 -class Eapi7EbuildAssignment(EbuildAssignment):
4722 - """Ensure ebuilds don't assign to readonly EAPI 7-introduced variables."""
4723 -
4724 - readonly_assignment = re.compile(r"\s*(export\s+)?BROOT=")
4725 -
4726 - def check_eapi(self, eapi):
4727 - return eapi_has_broot(eapi)
4728
4729 diff --git a/repoman/lib/repoman/modules/linechecks/base.py b/repoman/lib/repoman/modules/linechecks/base.py
4730 deleted file mode 100644
4731 index 851057940..000000000
4732 --- a/repoman/lib/repoman/modules/linechecks/base.py
4733 +++ /dev/null
4734 @@ -1,115 +0,0 @@
4735 -import logging
4736 -import re
4737 -
4738 -
4739 -class LineCheck:
4740 - """Run a check on a line of an ebuild."""
4741 -
4742 - """A regular expression to determine whether to ignore the line"""
4743 - ignore_line = False
4744 - """True if lines containing nothing more than comments with optional
4745 - leading whitespace should be ignored"""
4746 - ignore_comment = True
4747 -
4748 - def __init__(self, errors):
4749 - self.errors = errors
4750 -
4751 - def new(self, pkg):
4752 - pass
4753 -
4754 - def check_eapi(self, eapi):
4755 - """Returns if check should be run in the given EAPI (default: True)"""
4756 - return True
4757 -
4758 - def check(self, num, line):
4759 - """Run the check on line and return error if there is one"""
4760 - if self.re.match(line):
4761 - return self.errors[self.error]
4762 -
4763 - def end(self):
4764 - pass
4765 -
4766 -
4767 -class InheritEclass(LineCheck):
4768 - """
4769 - Base class for checking for missing inherits, as well as excess inherits.
4770 -
4771 - Args:
4772 - eclass: Set to the name of your eclass.
4773 - funcs: A tuple of functions that this eclass provides.
4774 - comprehensive: Is the list of functions complete?
4775 - exempt_eclasses: If these eclasses are inherited, disable the missing
4776 - inherit check.
4777 - """
4778 -
4779 - def __init__(
4780 - self,
4781 - eclass,
4782 - eclass_eapi_functions,
4783 - errors,
4784 - funcs=None,
4785 - comprehensive=False,
4786 - exempt_eclasses=None,
4787 - ignore_missing=False,
4788 - **kwargs
4789 - ):
4790 - self._eclass = eclass
4791 - self._comprehensive = comprehensive
4792 - self._exempt_eclasses = exempt_eclasses
4793 - self._ignore_missing = ignore_missing
4794 - self.errors = errors
4795 - inherit_re = eclass
4796 - self._eclass_eapi_functions = eclass_eapi_functions
4797 - self._inherit_re = re.compile(
4798 - r"^(\s*|.*[|&]\s*)\binherit\s(.*\s)?%s(\s|$)" % inherit_re
4799 - )
4800 - # Match when the function is preceded only by leading whitespace, a
4801 - # shell operator such as (, {, |, ||, or &&, or optional variable
4802 - # setting(s). This prevents false positives in things like elog
4803 - # messages, as reported in bug #413285.
4804 - logging.debug("InheritEclass, eclass: %s, funcs: %s", eclass, funcs)
4805 - self._func_re = re.compile(
4806 - r"(^|[|&{(])\s*(\w+=.*)?\b(" + r"|".join(funcs) + r")\b"
4807 - )
4808 -
4809 - def new(self, pkg):
4810 - self.repoman_check_name = "inherit.missing"
4811 - # We can't use pkg.inherited because that tells us all the eclasses that
4812 - # have been inherited and not just the ones we inherit directly.
4813 - self._inherit = False
4814 - self._func_call = False
4815 - if self._exempt_eclasses is not None:
4816 - inherited = pkg.inherited
4817 - self._disabled = any(x in inherited for x in self._exempt_eclasses)
4818 - else:
4819 - self._disabled = False
4820 - self._eapi = pkg.eapi
4821 -
4822 - def check(self, num, line):
4823 - if not self._inherit:
4824 - self._inherit = self._inherit_re.match(line)
4825 - if not self._inherit:
4826 - if self._disabled or self._ignore_missing:
4827 - return
4828 - s = self._func_re.search(line)
4829 - if s is not None:
4830 - func_name = s.group(3)
4831 - eapi_func = self._eclass_eapi_functions.get(func_name)
4832 - if eapi_func is None or not eapi_func(self._eapi):
4833 - self._func_call = True
4834 - return '%s.eclass not inherited, but "%s" called' % (
4835 - self._eclass,
4836 - func_name,
4837 - )
4838 - elif not self._func_call:
4839 - self._func_call = self._func_re.search(line)
4840 -
4841 - def end(self):
4842 - if (
4843 - not self._disabled
4844 - and self._comprehensive
4845 - and self._inherit
4846 - and not self._func_call
4847 - ):
4848 - self.repoman_check_name = "inherit.unused"
4849 - yield "no function called from %s.eclass; please drop" % self._eclass
4850
4851 diff --git a/repoman/lib/repoman/modules/linechecks/config.py b/repoman/lib/repoman/modules/linechecks/config.py
4852 deleted file mode 100644
4853 index e4275f5cc..000000000
4854 --- a/repoman/lib/repoman/modules/linechecks/config.py
4855 +++ /dev/null
4856 @@ -1,149 +0,0 @@
4857 -# -*- coding:utf-8 -*-
4858 -# repoman: Checks
4859 -# Copyright 2007-2017 Gentoo Foundation
4860 -# Distributed under the terms of the GNU General Public License v2
4861 -
4862 -"""This module contains functions used in Repoman to ascertain the quality
4863 -and correctness of an ebuild."""
4864 -
4865 -import collections
4866 -import logging
4867 -import os
4868 -from copy import deepcopy
4869 -
4870 -from repoman._portage import portage
4871 -from repoman.config import load_config
4872 -from repoman import _not_installed
4873 -
4874 -# Avoid a circular import issue in py2.7
4875 -portage.proxy.lazyimport.lazyimport(
4876 - globals(),
4877 - "portage.util:stack_lists",
4878 -)
4879 -
4880 -
4881 -def merge(dict1, dict2):
4882 - """Return a new dictionary by merging two dictionaries recursively."""
4883 -
4884 - result = deepcopy(dict1)
4885 -
4886 - for key, value in dict2.items():
4887 - if isinstance(value, collections.Mapping):
4888 - result[key] = merge(result.get(key, {}), value)
4889 - else:
4890 - result[key] = deepcopy(dict2[key])
4891 -
4892 - return result
4893 -
4894 -
4895 -class LineChecksConfig:
4896 - """Holds our LineChecks configuration data and operation functions"""
4897 -
4898 - def __init__(self, repo_settings):
4899 - """Class init
4900 -
4901 - @param repo_settings: RepoSettings instance
4902 - @param configpaths: ordered list of filepaths to load
4903 - """
4904 - self.repo_settings = repo_settings
4905 - self.infopaths = None
4906 - self.info_config = None
4907 - self._config = None
4908 - self.usex_supported_eapis = None
4909 - self.in_iuse_supported_eapis = None
4910 - self.get_libdir_supported_eapis = None
4911 - self.eclass_eapi_functions = {}
4912 - self.eclass_export_functions = None
4913 - self.eclass_info = {}
4914 - self.eclass_info_experimental_inherit = {}
4915 - self.errors = {}
4916 - self.set_infopaths()
4917 - self.load_checks_info()
4918 -
4919 - def set_infopaths(self):
4920 - if _not_installed:
4921 - cnfdir = os.path.realpath(
4922 - os.path.join(
4923 - os.path.dirname(
4924 - os.path.dirname(
4925 - os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
4926 - )
4927 - ),
4928 - "cnf/linechecks",
4929 - )
4930 - )
4931 - else:
4932 - cnfdir = os.path.join(
4933 - portage.const.EPREFIX or "/", "usr/share/repoman/linechecks"
4934 - )
4935 - repomanpaths = [os.path.join(cnfdir, _file_) for _file_ in os.listdir(cnfdir)]
4936 - logging.debug("LineChecksConfig; repomanpaths: %s", repomanpaths)
4937 - repopaths = [
4938 - os.path.join(path, "linechecks.yaml")
4939 - for path in self.repo_settings.masters_list
4940 - ]
4941 - self.infopaths = repomanpaths + repopaths
4942 - logging.debug("LineChecksConfig; configpaths: %s", self.infopaths)
4943 -
4944 - def load_checks_info(self, infopaths=None):
4945 - """load the config files in order
4946 -
4947 - @param infopaths: ordered list of filepaths to load
4948 - """
4949 - if infopaths:
4950 - self.infopaths = infopaths
4951 - elif not self.infopaths:
4952 - logging.error("LineChecksConfig; Error: No linechecks.yaml files defined")
4953 -
4954 - configs = load_config(
4955 - self.infopaths, "yaml", self.repo_settings.repoman_settings.valid_versions
4956 - )
4957 - if configs == {}:
4958 - logging.error(
4959 - "LineChecksConfig: Failed to load a valid 'linechecks.yaml' file at paths: %s",
4960 - self.infopaths,
4961 - )
4962 - return False
4963 - logging.debug("LineChecksConfig: linechecks.yaml configs: %s", configs)
4964 - self.info_config = configs
4965 -
4966 - self.errors = self.info_config["errors"]
4967 - self.usex_supported_eapis = self.info_config.get("usex_supported_eapis", [])
4968 - self.in_iuse_supported_eapis = self.info_config.get(
4969 - "in_iuse_supported_eapis", []
4970 - )
4971 - self.eclass_info_experimental_inherit = self.info_config.get(
4972 - "eclass_info_experimental_inherit", []
4973 - )
4974 - self.get_libdir_supported_eapis = self.in_iuse_supported_eapis
4975 - self.eclass_eapi_functions = {
4976 - "usex": lambda eapi: eapi not in self.usex_supported_eapis,
4977 - "in_iuse": lambda eapi: eapi not in self.in_iuse_supported_eapis,
4978 - "get_libdir": lambda eapi: eapi not in self.get_libdir_supported_eapis,
4979 - }
4980 -
4981 - # eclasses that export ${ECLASS}_src_(compile|configure|install)
4982 - self.eclass_export_functions = self.info_config.get(
4983 - "eclass_export_functions", []
4984 - )
4985 -
4986 - self.eclass_info_experimental_inherit = self.info_config.get(
4987 - "eclass_info_experimental_inherit", {}
4988 - )
4989 - # These are "eclasses are the whole ebuild" type thing.
4990 - try:
4991 - self.eclass_info_experimental_inherit["eutils"][
4992 - "exempt_eclasses"
4993 - ] = self.eclass_export_functions
4994 - except KeyError:
4995 - pass
4996 - try:
4997 - self.eclass_info_experimental_inherit["multilib"][
4998 - "exempt_eclasses"
4999 - ] = self.eclass_export_functions + [
5000 - "autotools",
5001 - "libtool",
5002 - "multilib-minimal",
5003 - ]
5004 - except KeyError:
5005 - pass
5006
5007 diff --git a/repoman/lib/repoman/modules/linechecks/controller.py b/repoman/lib/repoman/modules/linechecks/controller.py
5008 deleted file mode 100644
5009 index f4cfe2aca..000000000
5010 --- a/repoman/lib/repoman/modules/linechecks/controller.py
5011 +++ /dev/null
5012 @@ -1,164 +0,0 @@
5013 -import logging
5014 -import operator
5015 -import os
5016 -import re
5017 -
5018 -from repoman.modules.linechecks.base import InheritEclass
5019 -from repoman.modules.linechecks.config import LineChecksConfig
5020 -from repoman._portage import portage
5021 -
5022 -# Avoid a circular import issue in py2.7
5023 -portage.proxy.lazyimport.lazyimport(
5024 - globals(),
5025 - "portage.module:Modules",
5026 -)
5027 -
5028 -MODULES_PATH = os.path.dirname(__file__)
5029 -# initial development debug info
5030 -logging.debug("LineChecks module path: %s", MODULES_PATH)
5031 -
5032 -
5033 -class LineCheckController:
5034 - """Initializes and runs the LineCheck checks"""
5035 -
5036 - def __init__(self, repo_settings, linechecks):
5037 - """Class init
5038 -
5039 - @param repo_settings: RepoSettings instance
5040 - """
5041 - self.repo_settings = repo_settings
5042 - self.linechecks = linechecks
5043 - self.config = LineChecksConfig(repo_settings)
5044 -
5045 - self.controller = Modules(
5046 - path=MODULES_PATH, namepath="repoman.modules.linechecks"
5047 - )
5048 - logging.debug(
5049 - "LineCheckController; module_names: %s", self.controller.module_names
5050 - )
5051 -
5052 - self._constant_checks = None
5053 -
5054 - self._here_doc_re = re.compile(r".*<<[-]?(\w+)\s*(>\s*\S+\s*)?$")
5055 - self._ignore_comment_re = re.compile(r"^\s*#")
5056 - self._continuation_re = re.compile(r"(\\)*$")
5057 -
5058 - def checks_init(self, experimental_inherit=False):
5059 - """Initialize the main variables
5060 -
5061 - @param experimental_inherit boolean
5062 - """
5063 - if not experimental_inherit:
5064 - # Emulate the old eprefixify.defined and inherit.autotools checks.
5065 - self._eclass_info = self.config.eclass_info
5066 - else:
5067 - self._eclass_info = self.config.eclass_info_experimental_inherit
5068 -
5069 - self._constant_checks = []
5070 - logging.debug("LineCheckController; modules: %s", self.linechecks)
5071 - # Add in the pluggable modules
5072 - for mod in self.linechecks:
5073 - mod_class = self.controller.get_class(mod)
5074 - logging.debug(
5075 - "LineCheckController; module_name: %s, class: %s",
5076 - mod,
5077 - mod_class.__name__,
5078 - )
5079 - self._constant_checks.append(mod_class(self.config.errors))
5080 - # Add in the InheritEclass checks
5081 - logging.debug(
5082 - "LineCheckController; eclass_info.items(): %s",
5083 - list(self.config.eclass_info),
5084 - )
5085 - for k, kwargs in self.config.eclass_info.items():
5086 - logging.debug("LineCheckController; k: %s, kwargs: %s", k, kwargs)
5087 - self._constant_checks.append(
5088 - InheritEclass(
5089 - k, self.config.eclass_eapi_functions, self.config.errors, **kwargs
5090 - )
5091 - )
5092 -
5093 - def run_checks(self, contents, pkg):
5094 - """Run the configured linechecks
5095 -
5096 - @param contents: the ebuild contents to check
5097 - @param pkg: the package being checked
5098 - """
5099 - if self._constant_checks is None:
5100 - self.checks_init()
5101 - checks = self._constant_checks
5102 - here_doc_delim = None
5103 - multiline = None
5104 -
5105 - for lc in checks:
5106 - lc.new(pkg)
5107 -
5108 - multinum = 0
5109 - for num, line in enumerate(contents):
5110 -
5111 - # Check if we're inside a here-document.
5112 - if here_doc_delim is not None:
5113 - if here_doc_delim.match(line):
5114 - here_doc_delim = None
5115 - if here_doc_delim is None:
5116 - here_doc = self._here_doc_re.match(line)
5117 - if here_doc is not None:
5118 - here_doc_delim = re.compile(r"^\s*%s$" % here_doc.group(1))
5119 - if here_doc_delim is not None:
5120 - continue
5121 -
5122 - # Unroll multiline escaped strings so that we can check things:
5123 - # inherit foo bar \
5124 - # moo \
5125 - # cow
5126 - # This will merge these lines like so:
5127 - # inherit foo bar moo cow
5128 - # A line ending with an even number of backslashes does not count,
5129 - # because the last backslash is escaped. Therefore, search for an
5130 - # odd number of backslashes.
5131 - line_escaped = (
5132 - operator.sub(*self._continuation_re.search(line).span()) % 2 == 1
5133 - )
5134 - if multiline:
5135 - # Chop off the \ and \n bytes from the previous line.
5136 - multiline = multiline[:-2] + line
5137 - if not line_escaped:
5138 - line = multiline
5139 - num = multinum
5140 - multiline = None
5141 - else:
5142 - continue
5143 - else:
5144 - if line_escaped:
5145 - multinum = num
5146 - multiline = line
5147 - continue
5148 -
5149 - if not line.endswith("#nowarn\n"):
5150 - # Finally we have a full line to parse.
5151 - is_comment = self._ignore_comment_re.match(line) is not None
5152 - for lc in checks:
5153 - if is_comment and lc.ignore_comment:
5154 - continue
5155 - if lc.check_eapi(pkg.eapi):
5156 - ignore = lc.ignore_line
5157 - if not ignore or not ignore.match(line):
5158 - errors = lc.check(num, line)
5159 - if errors:
5160 - if isinstance(errors, (tuple, list)):
5161 - for error in errors:
5162 - yield lc.repoman_check_name, "line %d: %s" % (
5163 - num + 1,
5164 - error,
5165 - )
5166 - else:
5167 - yield lc.repoman_check_name, "line %d: %s" % (
5168 - num + 1,
5169 - errors,
5170 - )
5171 -
5172 - for lc in checks:
5173 - i = lc.end()
5174 - if i is not None:
5175 - for e in i:
5176 - yield lc.repoman_check_name, e
5177
5178 diff --git a/repoman/lib/repoman/modules/linechecks/depend/__init__.py b/repoman/lib/repoman/modules/linechecks/depend/__init__.py
5179 deleted file mode 100644
5180 index 7fe35f968..000000000
5181 --- a/repoman/lib/repoman/modules/linechecks/depend/__init__.py
5182 +++ /dev/null
5183 @@ -1,21 +0,0 @@
5184 -# Copyright 2015-2021 Gentoo Authors
5185 -# Distributed under the terms of the GNU General Public License v2
5186 -
5187 -doc = """Depend plug-in module for repoman LineChecks.
5188 -Performs dependency checks on ebuilds."""
5189 -__doc__ = doc[:]
5190 -
5191 -
5192 -module_spec = {
5193 - "name": "depend",
5194 - "description": doc,
5195 - "provides": {
5196 - "implicit-check": {
5197 - "name": "implicitdepend",
5198 - "sourcefile": "implicit",
5199 - "class": "ImplicitRuntimeDeps",
5200 - "description": doc,
5201 - },
5202 - },
5203 - "version": 1,
5204 -}
5205
5206 diff --git a/repoman/lib/repoman/modules/linechecks/depend/implicit.py b/repoman/lib/repoman/modules/linechecks/depend/implicit.py
5207 deleted file mode 100644
5208 index 5f4c06618..000000000
5209 --- a/repoman/lib/repoman/modules/linechecks/depend/implicit.py
5210 +++ /dev/null
5211 @@ -1,38 +0,0 @@
5212 -import re
5213 -
5214 -from portage.eapi import eapi_has_implicit_rdepend
5215 -from repoman.modules.linechecks.base import LineCheck
5216 -
5217 -
5218 -class ImplicitRuntimeDeps(LineCheck):
5219 - """
5220 - Detect the case where DEPEND is set and RDEPEND is unset in the ebuild,
5221 - since this triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4).
5222 - """
5223 -
5224 - repoman_check_name = "RDEPEND.implicit"
5225 - _assignment_re = re.compile(r"^\s*(R?DEPEND)\+?=")
5226 -
5227 - def new(self, pkg):
5228 - self._rdepend = False
5229 - self._depend = False
5230 -
5231 - def check_eapi(self, eapi):
5232 - # Beginning with EAPI 4, there is no
5233 - # implicit RDEPEND=$DEPEND assignment
5234 - # to be concerned with.
5235 - return eapi_has_implicit_rdepend(eapi)
5236 -
5237 - def check(self, num, line):
5238 - if not self._rdepend:
5239 - m = self._assignment_re.match(line)
5240 - if m is None:
5241 - pass
5242 - elif m.group(1) == "RDEPEND":
5243 - self._rdepend = True
5244 - elif m.group(1) == "DEPEND":
5245 - self._depend = True
5246 -
5247 - def end(self):
5248 - if self._depend and not self._rdepend:
5249 - yield "RDEPEND is not explicitly assigned"
5250
5251 diff --git a/repoman/lib/repoman/modules/linechecks/deprecated/__init__.py b/repoman/lib/repoman/modules/linechecks/deprecated/__init__.py
5252 deleted file mode 100644
5253 index 593bc1d3f..000000000
5254 --- a/repoman/lib/repoman/modules/linechecks/deprecated/__init__.py
5255 +++ /dev/null
5256 @@ -1,46 +0,0 @@
5257 -# Copyright 2015-2021 Gentoo Authors
5258 -# Distributed under the terms of the GNU General Public License v2
5259 -
5260 -doc = """Deprecated plug-in module for repoman LineChecks.
5261 -Performs miscelaneous deprecation checks on ebuilds not covered by
5262 -specialty modules."""
5263 -__doc__ = doc[:]
5264 -
5265 -
5266 -module_spec = {
5267 - "name": "deprecated",
5268 - "description": doc,
5269 - "provides": {
5270 - "useq-check": {
5271 - "name": "useq",
5272 - "sourcefile": "deprecated",
5273 - "class": "DeprecatedUseq",
5274 - "description": doc,
5275 - },
5276 - "hasq-check": {
5277 - "name": "hasq",
5278 - "sourcefile": "deprecated",
5279 - "class": "DeprecatedHasq",
5280 - "description": doc,
5281 - },
5282 - "preserve-check": {
5283 - "name": "preservelib",
5284 - "sourcefile": "deprecated",
5285 - "class": "PreserveOldLib",
5286 - "description": doc,
5287 - },
5288 - "bindnow-check": {
5289 - "name": "bindnow",
5290 - "sourcefile": "deprecated",
5291 - "class": "DeprecatedBindnowFlags",
5292 - "description": doc,
5293 - },
5294 - "inherit-check": {
5295 - "name": "inherit",
5296 - "sourcefile": "inherit",
5297 - "class": "InheritDeprecated",
5298 - "description": doc,
5299 - },
5300 - },
5301 - "version": 1,
5302 -}
5303
5304 diff --git a/repoman/lib/repoman/modules/linechecks/deprecated/deprecated.py b/repoman/lib/repoman/modules/linechecks/deprecated/deprecated.py
5305 deleted file mode 100644
5306 index abf7dbf42..000000000
5307 --- a/repoman/lib/repoman/modules/linechecks/deprecated/deprecated.py
5308 +++ /dev/null
5309 @@ -1,35 +0,0 @@
5310 -import re # pylint: disable=unused-import
5311 -
5312 -from repoman.modules.linechecks.base import LineCheck
5313 -
5314 -
5315 -class DeprecatedUseq(LineCheck):
5316 - """Checks for use of the deprecated useq function"""
5317 -
5318 - repoman_check_name = "ebuild.minorsyn"
5319 - re = re.compile(r"(^|.*\b)useq\b")
5320 - error = "USEQ_ERROR"
5321 -
5322 -
5323 -class DeprecatedHasq(LineCheck):
5324 - """Checks for use of the deprecated hasq function"""
5325 -
5326 - repoman_check_name = "ebuild.minorsyn"
5327 - re = re.compile(r"(^|.*\b)hasq\b")
5328 - error = "HASQ_ERROR"
5329 -
5330 -
5331 -class PreserveOldLib(LineCheck):
5332 - """Check for calls to the preserve_old_lib function reserved for system packages."""
5333 -
5334 - repoman_check_name = "ebuild.minorsyn"
5335 - re = re.compile(r".*preserve_old_lib")
5336 - error = "PRESERVE_OLD_LIB"
5337 -
5338 -
5339 -class DeprecatedBindnowFlags(LineCheck):
5340 - """Check for calls to the deprecated bindnow-flags function."""
5341 -
5342 - repoman_check_name = "ebuild.minorsyn"
5343 - re = re.compile(r".*\$\(bindnow-flags\)")
5344 - error = "DEPRECATED_BINDNOW_FLAGS"
5345
5346 diff --git a/repoman/lib/repoman/modules/linechecks/deprecated/inherit.py b/repoman/lib/repoman/modules/linechecks/deprecated/inherit.py
5347 deleted file mode 100644
5348 index 7d7f66d5d..000000000
5349 --- a/repoman/lib/repoman/modules/linechecks/deprecated/inherit.py
5350 +++ /dev/null
5351 @@ -1,67 +0,0 @@
5352 -import re
5353 -
5354 -from repoman.modules.linechecks.base import LineCheck
5355 -
5356 -
5357 -class InheritDeprecated(LineCheck):
5358 - """Check if ebuild directly or indirectly inherits a deprecated eclass."""
5359 -
5360 - repoman_check_name = "inherit.deprecated"
5361 -
5362 - # deprecated eclass : new eclass (False if no new eclass)
5363 - deprecated_eclasses = {
5364 - "autotools-multilib": "multilib-minimal",
5365 - "autotools-utils": False,
5366 - "base": False,
5367 - "bash-completion": "bash-completion-r1",
5368 - "boost-utils": False,
5369 - "clutter": "gnome2",
5370 - "cmake-utils": "cmake",
5371 - "confutils": False,
5372 - "distutils": "distutils-r1",
5373 - "epatch": "(eapply since EAPI 6)",
5374 - "fdo-mime": "xdg-utils",
5375 - "games": False,
5376 - "gems": "ruby-fakegem",
5377 - "git-2": "git-r3",
5378 - "gpe": False,
5379 - "gst-plugins-bad": "gstreamer",
5380 - "gst-plugins-base": "gstreamer",
5381 - "gst-plugins-good": "gstreamer",
5382 - "gst-plugins-ugly": "gstreamer",
5383 - "gst-plugins10": "gstreamer",
5384 - "ltprune": False,
5385 - "mono": "mono-env",
5386 - "python": "python-r1 / python-single-r1 / python-any-r1",
5387 - "ruby": "ruby-ng",
5388 - "user": "GLEP 81",
5389 - "versionator": "eapi7-ver (built-in since EAPI 7)",
5390 - "x-modular": "xorg-2",
5391 - "xfconf": False,
5392 - }
5393 -
5394 - _inherit_re = re.compile(r"^\s*inherit\s(.*)$")
5395 -
5396 - def check(self, num, line):
5397 - direct_inherits = None
5398 - m = self._inherit_re.match(line)
5399 - if m is not None:
5400 - direct_inherits = m.group(1)
5401 - if direct_inherits:
5402 - direct_inherits = direct_inherits.split()
5403 -
5404 - if not direct_inherits:
5405 - return
5406 -
5407 - errors = []
5408 - for eclass in direct_inherits:
5409 - replacement = self.deprecated_eclasses.get(eclass)
5410 - if replacement is None:
5411 - pass
5412 - elif replacement is False:
5413 - errors.append("please migrate from " "'%s' (no replacement)" % eclass)
5414 - else:
5415 - errors.append(
5416 - "please migrate from " "'%s' to '%s'" % (eclass, replacement)
5417 - )
5418 - return errors
5419
5420 diff --git a/repoman/lib/repoman/modules/linechecks/do/__init__.py b/repoman/lib/repoman/modules/linechecks/do/__init__.py
5421 deleted file mode 100644
5422 index 597b961e7..000000000
5423 --- a/repoman/lib/repoman/modules/linechecks/do/__init__.py
5424 +++ /dev/null
5425 @@ -1,21 +0,0 @@
5426 -# Copyright 2015-2021 Gentoo Authors
5427 -# Distributed under the terms of the GNU General Public License v2
5428 -
5429 -doc = """Do plug-in module for repoman LineChecks.
5430 -Performs do* checks on ebuilds."""
5431 -__doc__ = doc[:]
5432 -
5433 -
5434 -module_spec = {
5435 - "name": "do",
5436 - "description": doc,
5437 - "provides": {
5438 - "nonrelative-check": {
5439 - "name": "dosym",
5440 - "sourcefile": "dosym",
5441 - "class": "EbuildNonRelativeDosym",
5442 - "description": doc,
5443 - },
5444 - },
5445 - "version": 1,
5446 -}
5447
5448 diff --git a/repoman/lib/repoman/modules/linechecks/do/dosym.py b/repoman/lib/repoman/modules/linechecks/do/dosym.py
5449 deleted file mode 100644
5450 index 2276b3315..000000000
5451 --- a/repoman/lib/repoman/modules/linechecks/do/dosym.py
5452 +++ /dev/null
5453 @@ -1,20 +0,0 @@
5454 -import re
5455 -
5456 -from repoman.modules.linechecks.base import LineCheck
5457 -
5458 -
5459 -class EbuildNonRelativeDosym(LineCheck):
5460 - """Check ebuild for dosym using absolute paths instead of relative."""
5461 -
5462 - repoman_check_name = "ebuild.absdosym"
5463 - variables = ("D", "ED", "ROOT", "EROOT", "BROOT")
5464 - regex = re.compile(
5465 - r'^\s*dosym\s+(["\']?((\$(%s)\W|\${(%s)(%%/)?})|/(bin|etc|lib|opt|sbin|srv|usr|var))\S*)'
5466 - % ("|".join(variables), "|".join(variables)),
5467 - getattr(re, "ASCII", 0),
5468 - )
5469 -
5470 - def check(self, num, line):
5471 - match = self.regex.match(line)
5472 - if match:
5473 - return "dosym '%s'... could use relative path" % match.group(1)
5474
5475 diff --git a/repoman/lib/repoman/modules/linechecks/eapi/__init__.py b/repoman/lib/repoman/modules/linechecks/eapi/__init__.py
5476 deleted file mode 100644
5477 index 68e6b722a..000000000
5478 --- a/repoman/lib/repoman/modules/linechecks/eapi/__init__.py
5479 +++ /dev/null
5480 @@ -1,51 +0,0 @@
5481 -# Copyright 2015-2021 Gentoo Authors
5482 -# Distributed under the terms of the GNU General Public License v2
5483 -
5484 -doc = """Eapi plug-in module for repoman LineChecks.
5485 -Performs eapi dependant checks on ebuilds."""
5486 -__doc__ = doc[:]
5487 -
5488 -
5489 -module_spec = {
5490 - "name": "eapi",
5491 - "description": doc,
5492 - "provides": {
5493 - "definition-check": {
5494 - "name": "definition",
5495 - "sourcefile": "definition",
5496 - "class": "EapiDefinition",
5497 - "description": doc,
5498 - },
5499 - "srcprepare-check": {
5500 - "name": "srcprepare",
5501 - "sourcefile": "checks",
5502 - "class": "UndefinedSrcPrepareSrcConfigurePhases",
5503 - "description": doc,
5504 - },
5505 - "eapi3deprecated-check": {
5506 - "name": "eapi3deprecated",
5507 - "sourcefile": "checks",
5508 - "class": "Eapi3DeprecatedFuncs",
5509 - "description": doc,
5510 - },
5511 - "pkgpretend-check": {
5512 - "name": "pkgpretend",
5513 - "sourcefile": "checks",
5514 - "class": "UndefinedPkgPretendPhase",
5515 - "description": doc,
5516 - },
5517 - "eapi4incompatible-check": {
5518 - "name": "eapi4incompatible",
5519 - "sourcefile": "checks",
5520 - "class": "Eapi4IncompatibleFuncs",
5521 - "description": doc,
5522 - },
5523 - "eapi4gonevars-check": {
5524 - "name": "eapi4gonevars",
5525 - "sourcefile": "checks",
5526 - "class": "Eapi4GoneVars",
5527 - "description": doc,
5528 - },
5529 - },
5530 - "version": 1,
5531 -}
5532
5533 diff --git a/repoman/lib/repoman/modules/linechecks/eapi/checks.py b/repoman/lib/repoman/modules/linechecks/eapi/checks.py
5534 deleted file mode 100644
5535 index 64bb509a7..000000000
5536 --- a/repoman/lib/repoman/modules/linechecks/eapi/checks.py
5537 +++ /dev/null
5538 @@ -1,79 +0,0 @@
5539 -import re
5540 -
5541 -from portage.eapi import (
5542 - eapi_has_src_prepare_and_src_configure,
5543 - eapi_has_dosed_dohard,
5544 - eapi_exports_AA,
5545 - eapi_has_pkg_pretend,
5546 -)
5547 -from repoman.modules.linechecks.base import LineCheck
5548 -
5549 -
5550 -# EAPI <2 checks
5551 -class UndefinedSrcPrepareSrcConfigurePhases(LineCheck):
5552 - repoman_check_name = "EAPI.incompatible"
5553 - src_configprepare_re = re.compile(r"\s*(src_configure|src_prepare)\s*\(\)")
5554 -
5555 - def check_eapi(self, eapi):
5556 - return not eapi_has_src_prepare_and_src_configure(eapi)
5557 -
5558 - def check(self, num, line):
5559 - m = self.src_configprepare_re.match(line)
5560 - if m is not None:
5561 - return ("'%s'" % m.group(1)) + " phase is not defined in EAPI < 2"
5562 -
5563 -
5564 -# EAPI-3 checks
5565 -class Eapi3DeprecatedFuncs(LineCheck):
5566 - repoman_check_name = "EAPI.deprecated"
5567 - deprecated_commands_re = re.compile(r"^\s*(check_license)\b")
5568 -
5569 - def check_eapi(self, eapi):
5570 - return eapi not in ("0", "1", "2")
5571 -
5572 - def check(self, num, line):
5573 - m = self.deprecated_commands_re.match(line)
5574 - if m is not None:
5575 - return ("'%s'" % m.group(1)) + " has been deprecated in EAPI=3"
5576 -
5577 -
5578 -# EAPI <4 checks
5579 -class UndefinedPkgPretendPhase(LineCheck):
5580 - repoman_check_name = "EAPI.incompatible"
5581 - pkg_pretend_re = re.compile(r"\s*(pkg_pretend)\s*\(\)")
5582 -
5583 - def check_eapi(self, eapi):
5584 - return not eapi_has_pkg_pretend(eapi)
5585 -
5586 - def check(self, num, line):
5587 - m = self.pkg_pretend_re.match(line)
5588 - if m is not None:
5589 - return ("'%s'" % m.group(1)) + " phase is not defined in EAPI < 4"
5590 -
5591 -
5592 -# EAPI-4 checks
5593 -class Eapi4IncompatibleFuncs(LineCheck):
5594 - repoman_check_name = "EAPI.incompatible"
5595 - banned_commands_re = re.compile(r"^\s*(dosed|dohard)")
5596 -
5597 - def check_eapi(self, eapi):
5598 - return not eapi_has_dosed_dohard(eapi)
5599 -
5600 - def check(self, num, line):
5601 - m = self.banned_commands_re.match(line)
5602 - if m is not None:
5603 - return ("'%s'" % m.group(1)) + " has been banned in EAPI=4"
5604 -
5605 -
5606 -class Eapi4GoneVars(LineCheck):
5607 - repoman_check_name = "EAPI.incompatible"
5608 - undefined_vars_re = re.compile(r".*\$(\{(AA|KV|EMERGE_FROM)\}|(AA|KV|EMERGE_FROM))")
5609 -
5610 - def check_eapi(self, eapi):
5611 - # AA, KV, and EMERGE_FROM should not be referenced in EAPI 4 or later.
5612 - return not eapi_exports_AA(eapi)
5613 -
5614 - def check(self, num, line):
5615 - m = self.undefined_vars_re.match(line)
5616 - if m is not None:
5617 - return ("variable '$%s'" % m.group(1)) + " is gone in EAPI=4"
5618
5619 diff --git a/repoman/lib/repoman/modules/linechecks/eapi/definition.py b/repoman/lib/repoman/modules/linechecks/eapi/definition.py
5620 deleted file mode 100644
5621 index 964fa4ea3..000000000
5622 --- a/repoman/lib/repoman/modules/linechecks/eapi/definition.py
5623 +++ /dev/null
5624 @@ -1,35 +0,0 @@
5625 -from repoman.modules.linechecks.base import LineCheck
5626 -from repoman._portage import portage
5627 -
5628 -
5629 -class EapiDefinition(LineCheck):
5630 - """
5631 - Check that EAPI assignment conforms to PMS section 7.3.1
5632 - (first non-comment, non-blank line).
5633 - """
5634 -
5635 - repoman_check_name = "EAPI.definition"
5636 - ignore_comment = True
5637 - _eapi_re = portage._pms_eapi_re
5638 -
5639 - def new(self, pkg):
5640 - self._cached_eapi = pkg.eapi
5641 - self._parsed_eapi = None
5642 - self._eapi_line_num = None
5643 -
5644 - def check(self, num, line):
5645 - if self._eapi_line_num is None and line.strip():
5646 - self._eapi_line_num = num + 1
5647 - m = self._eapi_re.match(line)
5648 - if m is not None:
5649 - self._parsed_eapi = m.group(2)
5650 -
5651 - def end(self):
5652 - if self._parsed_eapi is None:
5653 - if self._cached_eapi != "0":
5654 - yield "valid EAPI assignment must occur on or before line: %s" % self._eapi_line_num
5655 - elif self._parsed_eapi != self._cached_eapi:
5656 - yield (
5657 - "bash returned EAPI '%s' which does not match "
5658 - "assignment on line: %s" % (self._cached_eapi, self._eapi_line_num)
5659 - )
5660
5661 diff --git a/repoman/lib/repoman/modules/linechecks/emake/__init__.py b/repoman/lib/repoman/modules/linechecks/emake/__init__.py
5662 deleted file mode 100644
5663 index 9a2c54915..000000000
5664 --- a/repoman/lib/repoman/modules/linechecks/emake/__init__.py
5665 +++ /dev/null
5666 @@ -1,27 +0,0 @@
5667 -# Copyright 2015-2021 Gentoo Authors
5668 -# Distributed under the terms of the GNU General Public License v2
5669 -
5670 -doc = """Emake plug-in module for repoman LineChecks.
5671 -Performs emake checks on ebuilds."""
5672 -__doc__ = doc[:]
5673 -
5674 -
5675 -module_spec = {
5676 - "name": "do",
5677 - "description": doc,
5678 - "provides": {
5679 - "paralleldisabled-check": {
5680 - "name": "paralleldisabled",
5681 - "sourcefile": "emake",
5682 - "class": "EMakeParallelDisabledViaMAKEOPTS",
5683 - "description": doc,
5684 - },
5685 - "autodefault-check": {
5686 - "name": "autodefault",
5687 - "sourcefile": "emake",
5688 - "class": "WantAutoDefaultValue",
5689 - "description": doc,
5690 - },
5691 - },
5692 - "version": 1,
5693 -}
5694
5695 diff --git a/repoman/lib/repoman/modules/linechecks/emake/emake.py b/repoman/lib/repoman/modules/linechecks/emake/emake.py
5696 deleted file mode 100644
5697 index 3bb7fc35b..000000000
5698 --- a/repoman/lib/repoman/modules/linechecks/emake/emake.py
5699 +++ /dev/null
5700 @@ -1,25 +0,0 @@
5701 -import re
5702 -
5703 -from repoman.modules.linechecks.base import LineCheck
5704 -
5705 -
5706 -class EMakeParallelDisabledViaMAKEOPTS(LineCheck):
5707 - """Check for MAKEOPTS=-j1 that disables parallelization."""
5708 -
5709 - repoman_check_name = "upstream.workaround"
5710 - re = re.compile(r'^\s*MAKEOPTS=(\'|")?.*-j\s*1\b')
5711 - error = "EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS"
5712 -
5713 -
5714 -class WantAutoDefaultValue(LineCheck):
5715 - """Check setting WANT_AUTO* to latest (default value)."""
5716 -
5717 - repoman_check_name = "ebuild.minorsyn"
5718 - _re = re.compile(r'^WANT_AUTO(CONF|MAKE)=(\'|")?latest')
5719 -
5720 - def check(self, num, line):
5721 - m = self._re.match(line)
5722 - if m is not None:
5723 - return (
5724 - "WANT_AUTO" + m.group(1) + ' redundantly set to default value "latest"'
5725 - )
5726
5727 diff --git a/repoman/lib/repoman/modules/linechecks/gentoo_header/__init__.py b/repoman/lib/repoman/modules/linechecks/gentoo_header/__init__.py
5728 deleted file mode 100644
5729 index 565b43ec2..000000000
5730 --- a/repoman/lib/repoman/modules/linechecks/gentoo_header/__init__.py
5731 +++ /dev/null
5732 @@ -1,21 +0,0 @@
5733 -# Copyright 2015-2021 Gentoo Authors
5734 -# Distributed under the terms of the GNU General Public License v2
5735 -
5736 -doc = """Gentoo-header plug-in module for repoman LineChecks.
5737 -Performs header checks on ebuilds."""
5738 -__doc__ = doc[:]
5739 -
5740 -
5741 -module_spec = {
5742 - "name": "do",
5743 - "description": doc,
5744 - "provides": {
5745 - "header-check": {
5746 - "name": "gentooheader",
5747 - "sourcefile": "header",
5748 - "class": "EbuildHeader",
5749 - "description": doc,
5750 - },
5751 - },
5752 - "version": 1,
5753 -}
5754
5755 diff --git a/repoman/lib/repoman/modules/linechecks/gentoo_header/header.py b/repoman/lib/repoman/modules/linechecks/gentoo_header/header.py
5756 deleted file mode 100644
5757 index 7ef77ae44..000000000
5758 --- a/repoman/lib/repoman/modules/linechecks/gentoo_header/header.py
5759 +++ /dev/null
5760 @@ -1,56 +0,0 @@
5761 -import re
5762 -import time
5763 -
5764 -from repoman.modules.linechecks.base import LineCheck
5765 -
5766 -
5767 -class EbuildHeader(LineCheck):
5768 - """Ensure ebuilds have proper headers
5769 - Copyright header errors
5770 - CVS header errors
5771 - License header errors
5772 -
5773 - Args:
5774 - modification_year - Year the ebuild was last modified
5775 - """
5776 -
5777 - repoman_check_name = "ebuild.badheader"
5778 -
5779 - gentoo_copyright = r"^# Copyright ((1999|2\d\d\d)-)?(?P<year2>%s) (?P<author>.*)$"
5780 - gentoo_license = (
5781 - "# Distributed under the terms" " of the GNU General Public License v2"
5782 - )
5783 - id_header_re = re.compile(r".*\$(Id|Header)(:.*)?\$.*")
5784 - blank_line_re = re.compile(r"^$")
5785 - ignore_comment = False
5786 -
5787 - def new(self, pkg):
5788 - if pkg.mtime is None:
5789 - self.modification_year = r"2\d\d\d"
5790 - else:
5791 - self.modification_year = str(time.gmtime(pkg.mtime)[0])
5792 - self.gentoo_copyright_re = re.compile(
5793 - self.gentoo_copyright % self.modification_year
5794 - )
5795 -
5796 - def check(self, num, line):
5797 - if num > 2:
5798 - return
5799 - elif num == 0:
5800 - match = self.gentoo_copyright_re.match(line)
5801 - if match is None:
5802 - return self.errors["COPYRIGHT_ERROR"]
5803 - if not (
5804 - match.group("author") == "Gentoo Authors"
5805 - or (
5806 - int(match.group("year2")) < 2019
5807 - and match.group("author") == "Gentoo Foundation"
5808 - )
5809 - ):
5810 - return self.errors["COPYRIGHT_ERROR"]
5811 - elif num == 1 and line.rstrip("\n") != self.gentoo_license:
5812 - return self.errors["LICENSE_ERROR"]
5813 - elif num == 2 and self.id_header_re.match(line):
5814 - return self.errors["ID_HEADER_ERROR"]
5815 - elif num == 2 and not self.blank_line_re.match(line):
5816 - return self.errors["NO_BLANK_LINE_ERROR"]
5817
5818 diff --git a/repoman/lib/repoman/modules/linechecks/helpers/__init__.py b/repoman/lib/repoman/modules/linechecks/helpers/__init__.py
5819 deleted file mode 100644
5820 index b65b454f1..000000000
5821 --- a/repoman/lib/repoman/modules/linechecks/helpers/__init__.py
5822 +++ /dev/null
5823 @@ -1,21 +0,0 @@
5824 -# Copyright 2015-2021 Gentoo Authors
5825 -# Distributed under the terms of the GNU General Public License v2
5826 -
5827 -doc = """Helpers plug-in module for repoman LineChecks.
5828 -Performs variable helpers checks on ebuilds."""
5829 -__doc__ = doc[:]
5830 -
5831 -
5832 -module_spec = {
5833 - "name": "do",
5834 - "description": doc,
5835 - "provides": {
5836 - "nooffset-check": {
5837 - "name": "nooffset",
5838 - "sourcefile": "offset",
5839 - "class": "NoOffsetWithHelpers",
5840 - "description": doc,
5841 - },
5842 - },
5843 - "version": 1,
5844 -}
5845
5846 diff --git a/repoman/lib/repoman/modules/linechecks/helpers/offset.py b/repoman/lib/repoman/modules/linechecks/helpers/offset.py
5847 deleted file mode 100644
5848 index 72ece48d5..000000000
5849 --- a/repoman/lib/repoman/modules/linechecks/helpers/offset.py
5850 +++ /dev/null
5851 @@ -1,21 +0,0 @@
5852 -import re # pylint: disable=unused-import
5853 -
5854 -from repoman.modules.linechecks.base import LineCheck
5855 -
5856 -
5857 -class NoOffsetWithHelpers(LineCheck):
5858 - """Check that the image location, the alternate root offset, and the
5859 - offset prefix (D, ROOT, ED, EROOT and EPREFIX) are not used with
5860 - helpers"""
5861 -
5862 - repoman_check_name = "variable.usedwithhelpers"
5863 - # Ignore matches in quoted strings like this:
5864 - # elog "installed into ${ROOT}usr/share/php5/apc/."
5865 - _install_funcs = (
5866 - "docinto|do(compress|dir|hard)" "|exeinto|fowners|fperms|insinto|into"
5867 - )
5868 - _quoted_vars = "D|ROOT|ED|EROOT|EPREFIX"
5869 - re = re.compile(
5870 - r'^[^#"\']*\b(%s)\s+"?\$\{?(%s)\b.*' % (_install_funcs, _quoted_vars)
5871 - )
5872 - error = "NO_OFFSET_WITH_HELPERS"
5873
5874 diff --git a/repoman/lib/repoman/modules/linechecks/nested/__init__.py b/repoman/lib/repoman/modules/linechecks/nested/__init__.py
5875 deleted file mode 100644
5876 index 83d69127d..000000000
5877 --- a/repoman/lib/repoman/modules/linechecks/nested/__init__.py
5878 +++ /dev/null
5879 @@ -1,21 +0,0 @@
5880 -# Copyright 2015-2021 Gentoo Authors
5881 -# Distributed under the terms of the GNU General Public License v2
5882 -
5883 -doc = """Nested plug-in module for repoman LineChecks.
5884 -Performs nested subshell checks on ebuilds."""
5885 -__doc__ = doc[:]
5886 -
5887 -
5888 -module_spec = {
5889 - "name": "do",
5890 - "description": doc,
5891 - "provides": {
5892 - "nesteddie-check": {
5893 - "name": "nesteddie",
5894 - "sourcefile": "nested",
5895 - "class": "EbuildNestedDie",
5896 - "description": doc,
5897 - },
5898 - },
5899 - "version": 1,
5900 -}
5901
5902 diff --git a/repoman/lib/repoman/modules/linechecks/nested/nested.py b/repoman/lib/repoman/modules/linechecks/nested/nested.py
5903 deleted file mode 100644
5904 index fc04bde01..000000000
5905 --- a/repoman/lib/repoman/modules/linechecks/nested/nested.py
5906 +++ /dev/null
5907 @@ -1,14 +0,0 @@
5908 -import re
5909 -
5910 -from repoman.modules.linechecks.base import LineCheck
5911 -
5912 -
5913 -class EbuildNestedDie(LineCheck):
5914 - """Check ebuild for nested die statements (die statements in subshells)"""
5915 -
5916 - repoman_check_name = "ebuild.nesteddie"
5917 - nesteddie_re = re.compile(r"^[^#]*\s\(\s[^)]*\bdie\b")
5918 -
5919 - def check(self, num, line):
5920 - if self.nesteddie_re.match(line):
5921 - return self.errors["NESTED_DIE_ERROR"]
5922
5923 diff --git a/repoman/lib/repoman/modules/linechecks/nested/nesteddie.py b/repoman/lib/repoman/modules/linechecks/nested/nesteddie.py
5924 deleted file mode 100644
5925 index 4b256bb1f..000000000
5926 --- a/repoman/lib/repoman/modules/linechecks/nested/nesteddie.py
5927 +++ /dev/null
5928 @@ -1,9 +0,0 @@
5929 -class EbuildNestedDie(LineCheck):
5930 - """Check ebuild for nested die statements (die statements in subshells)"""
5931 -
5932 - repoman_check_name = "ebuild.nesteddie"
5933 - nesteddie_re = re.compile(r"^[^#]*\s\(\s[^)]*\bdie\b")
5934 -
5935 - def check(self, num, line):
5936 - if self.nesteddie_re.match(line):
5937 - return errors.NESTED_DIE_ERROR
5938
5939 diff --git a/repoman/lib/repoman/modules/linechecks/patches/__init__.py b/repoman/lib/repoman/modules/linechecks/patches/__init__.py
5940 deleted file mode 100644
5941 index e4aec16a1..000000000
5942 --- a/repoman/lib/repoman/modules/linechecks/patches/__init__.py
5943 +++ /dev/null
5944 @@ -1,21 +0,0 @@
5945 -# Copyright 2015-2021 Gentoo Authors
5946 -# Distributed under the terms of the GNU General Public License v2
5947 -
5948 -doc = """Patches plug-in module for repoman LineChecks.
5949 -Performs PATCHES variable checks on ebuilds."""
5950 -__doc__ = doc[:]
5951 -
5952 -
5953 -module_spec = {
5954 - "name": "do",
5955 - "description": doc,
5956 - "provides": {
5957 - "patches-check": {
5958 - "name": "patches",
5959 - "sourcefile": "patches",
5960 - "class": "EbuildPatches",
5961 - "description": doc,
5962 - },
5963 - },
5964 - "version": 1,
5965 -}
5966
5967 diff --git a/repoman/lib/repoman/modules/linechecks/patches/patches.py b/repoman/lib/repoman/modules/linechecks/patches/patches.py
5968 deleted file mode 100644
5969 index ca9a4cada..000000000
5970 --- a/repoman/lib/repoman/modules/linechecks/patches/patches.py
5971 +++ /dev/null
5972 @@ -1,22 +0,0 @@
5973 -import re # pylint: disable=unused-import
5974 -
5975 -from repoman.modules.linechecks.base import LineCheck
5976 -
5977 -
5978 -class EbuildPatches(LineCheck):
5979 - """Ensure ebuilds use bash arrays for PATCHES to ensure white space safety"""
5980 -
5981 - repoman_check_name = "ebuild.patches"
5982 - re = re.compile(r"^\s*PATCHES=[^\(]")
5983 - error = "PATCHES_ERROR"
5984 -
5985 - def check_eapi(self, eapi):
5986 - return eapi in (
5987 - "0",
5988 - "1",
5989 - "2",
5990 - "3",
5991 - "4",
5992 - "4-slot-abi",
5993 - "5",
5994 - )
5995
5996 diff --git a/repoman/lib/repoman/modules/linechecks/phases/__init__.py b/repoman/lib/repoman/modules/linechecks/phases/__init__.py
5997 deleted file mode 100644
5998 index 880eac02b..000000000
5999 --- a/repoman/lib/repoman/modules/linechecks/phases/__init__.py
6000 +++ /dev/null
6001 @@ -1,40 +0,0 @@
6002 -# Copyright 2015-2021 Gentoo Authors
6003 -# Distributed under the terms of the GNU General Public License v2
6004 -
6005 -doc = """Phases plug-in module for repoman LineChecks.
6006 -Performs phase dependant checks on ebuilds using a PhaseCheck base class.
6007 -"""
6008 -__doc__ = doc[:]
6009 -
6010 -
6011 -module_spec = {
6012 - "name": "do",
6013 - "description": doc,
6014 - "provides": {
6015 - "emakeparallel-check": {
6016 - "name": "emakeparallel",
6017 - "sourcefile": "phase",
6018 - "class": "EMakeParallelDisabled",
6019 - "description": doc,
6020 - },
6021 - "srccompileeconf-check": {
6022 - "name": "srccompileeconf",
6023 - "sourcefile": "phase",
6024 - "class": "SrcCompileEconf",
6025 - "description": doc,
6026 - },
6027 - "srcunpackpatches-check": {
6028 - "name": "srcunpackpatches",
6029 - "sourcefile": "phase",
6030 - "class": "SrcUnpackPatches",
6031 - "description": doc,
6032 - },
6033 - "pmsvariablerefphasescope-check": {
6034 - "name": "pmsvariablerefphasescope",
6035 - "sourcefile": "phase",
6036 - "class": "PMSVariableReference",
6037 - "description": doc,
6038 - },
6039 - },
6040 - "version": 1,
6041 -}
6042
6043 diff --git a/repoman/lib/repoman/modules/linechecks/phases/phase.py b/repoman/lib/repoman/modules/linechecks/phases/phase.py
6044 deleted file mode 100644
6045 index 5d89b263d..000000000
6046 --- a/repoman/lib/repoman/modules/linechecks/phases/phase.py
6047 +++ /dev/null
6048 @@ -1,188 +0,0 @@
6049 -import fnmatch
6050 -import re
6051 -import types
6052 -
6053 -from portage.eapi import (
6054 - eapi_has_broot,
6055 - eapi_has_sysroot,
6056 - eapi_has_src_prepare_and_src_configure,
6057 - eapi_exports_AA,
6058 - eapi_exports_replace_vars,
6059 - eapi_exports_ECLASSDIR,
6060 - eapi_exports_PORTDIR,
6061 - eapi_supports_prefix,
6062 - eapi_exports_merge_type,
6063 -)
6064 -from repoman.modules.linechecks.base import LineCheck
6065 -
6066 -
6067 -class PhaseCheck(LineCheck):
6068 - """basic class for function detection"""
6069 -
6070 - func_end_re = re.compile(r"^\}$")
6071 - phase_funcs = (
6072 - "pkg_pretend",
6073 - "pkg_setup",
6074 - "src_unpack",
6075 - "src_prepare",
6076 - "src_configure",
6077 - "src_compile",
6078 - "src_test",
6079 - "src_install",
6080 - "pkg_preinst",
6081 - "pkg_postinst",
6082 - "pkg_prerm",
6083 - "pkg_postrm",
6084 - "pkg_config",
6085 - )
6086 - phases_re = re.compile("(%s)" % "|".join(phase_funcs))
6087 - in_phase = ""
6088 -
6089 - def check(self, num, line):
6090 - m = self.phases_re.match(line)
6091 - if m is not None:
6092 - self.in_phase = m.group(1)
6093 - if self.in_phase != "" and self.func_end_re.match(line) is not None:
6094 - self.in_phase = ""
6095 -
6096 - return self.phase_check(num, line)
6097 -
6098 - def phase_check(self, num, line):
6099 - """override this function for your checks"""
6100 - pass
6101 -
6102 -
6103 -class EMakeParallelDisabled(PhaseCheck):
6104 - """Check for emake -j1 calls which disable parallelization."""
6105 -
6106 - repoman_check_name = "upstream.workaround"
6107 - re = re.compile(r"^\s*emake\s+.*-j\s*1\b")
6108 -
6109 - def phase_check(self, num, line):
6110 - if self.in_phase == "src_compile" or self.in_phase == "src_install":
6111 - if self.re.match(line):
6112 - return self.errors["EMAKE_PARALLEL_DISABLED"]
6113 -
6114 -
6115 -class SrcCompileEconf(PhaseCheck):
6116 - repoman_check_name = "ebuild.minorsyn"
6117 - configure_re = re.compile(r"\s(econf|./configure)")
6118 -
6119 - def check_eapi(self, eapi):
6120 - return eapi_has_src_prepare_and_src_configure(eapi)
6121 -
6122 - def phase_check(self, num, line):
6123 - if self.in_phase == "src_compile":
6124 - m = self.configure_re.match(line)
6125 - if m is not None:
6126 - return ("'%s'" % m.group(1)) + " call should be moved to src_configure"
6127 -
6128 -
6129 -class SrcUnpackPatches(PhaseCheck):
6130 - repoman_check_name = "ebuild.minorsyn"
6131 - src_prepare_tools_re = re.compile(r"\s(e?patch|sed)\s")
6132 -
6133 - def check_eapi(self, eapi):
6134 - return eapi_has_src_prepare_and_src_configure(eapi)
6135 -
6136 - def phase_check(self, num, line):
6137 - if self.in_phase == "src_unpack":
6138 - m = self.src_prepare_tools_re.search(line)
6139 - if m is not None:
6140 - return ("'%s'" % m.group(1)) + " call should be moved to src_prepare"
6141 -
6142 -
6143 -# Refererences
6144 -# - https://projects.gentoo.org/pms/7/pms.html#x1-10900011.1
6145 -# - https://pkgcore.github.io/pkgcheck/_modules/pkgcheck/checks/codingstyle.html#VariableScopeCheck
6146 -_pms_vars = (
6147 - ("A", None, ("src_*", "pkg_nofetch")),
6148 - ("AA", eapi_exports_AA, ("src_*", "pkg_nofetch")),
6149 - ("FILESDIR", None, ("src_*",)),
6150 - ("DISTDIR", None, ("src_*",)),
6151 - ("WORKDIR", None, ("src_*",)),
6152 - ("S", None, ("src_*",)),
6153 - ("PORTDIR", eapi_exports_PORTDIR, ("src_*",)),
6154 - ("ECLASSDIR", eapi_exports_ECLASSDIR, ("src_*",)),
6155 - ("ROOT", None, ("pkg_*",)),
6156 - ("EROOT", eapi_supports_prefix, ("pkg_*",)),
6157 - ("SYSROOT", eapi_has_sysroot, ("src_*", "pkg_setup")),
6158 - ("ESYSROOT", eapi_has_sysroot, ("src_*", "pkg_setup")),
6159 - ("BROOT", eapi_has_broot, ("src_*", "pkg_setup")),
6160 - ("D", None, ("src_install", "pkg_preinst", "pkg_postint")),
6161 - ("ED", eapi_supports_prefix, ("src_install", "pkg_preinst", "pkg_postint")),
6162 - ("DESTTREE", None, ("src_install",)),
6163 - ("INSDESTTREE", None, ("src_install",)),
6164 - ("MERGE_TYPE", eapi_exports_merge_type, ("pkg_*",)),
6165 - ("REPLACING_VERSIONS", eapi_exports_replace_vars, ("pkg_*",)),
6166 - ("REPLACED_BY_VERSION", eapi_exports_replace_vars, ("pkg_prerm", "pkg_postrm")),
6167 -)
6168 -
6169 -
6170 -def _compile_phases():
6171 - phase_vars = {}
6172 - for phase_func in PhaseCheck.phase_funcs:
6173 - for variable, eapi_filter, allowed_scopes in _pms_vars:
6174 - allowed = False
6175 - for scope in allowed_scopes:
6176 - if fnmatch.fnmatch(phase_func, scope):
6177 - allowed = True
6178 - break
6179 -
6180 - if not allowed:
6181 - phase_vars.setdefault(phase_func, []).append((variable, eapi_filter))
6182 -
6183 - phase_info = {}
6184 - for phase_func, prohibited_vars in phase_vars.items():
6185 - phase_func_vars = []
6186 - for variable, eapi_filter in prohibited_vars:
6187 - phase_func_vars.append(variable)
6188 - phase_obj = phase_info[phase_func] = types.SimpleNamespace()
6189 - phase_obj.prohibited_vars = dict(prohibited_vars)
6190 - phase_obj.var_names = "(%s)" % "|".join(
6191 - variable for variable, eapi_filter in prohibited_vars
6192 - )
6193 - phase_obj.var_reference = re.compile(
6194 - r"\$(\{|)%s(\}|\W)" % (phase_obj.var_names,)
6195 - )
6196 -
6197 - return phase_info
6198 -
6199 -
6200 -class PMSVariableReference(PhaseCheck):
6201 - """Check phase scope for references to variables specified by PMS"""
6202 -
6203 - repoman_check_name = "variable.phase"
6204 - phase_info = _compile_phases()
6205 -
6206 - def new(self, pkg):
6207 - self._eapi = pkg.eapi
6208 -
6209 - def end(self):
6210 - self._eapi = None
6211 -
6212 - def phase_check(self, num, line):
6213 - try:
6214 - phase_info = self.phase_info[self.in_phase]
6215 - except KeyError:
6216 - return
6217 -
6218 - eapi = self._eapi
6219 - issues = []
6220 - for m in phase_info.var_reference.finditer(line):
6221 - open_brace = m.group(1)
6222 - var_name = m.group(2)
6223 - close_brace = m.group(3)
6224 - # discard \W if matched by (\}|\W)
6225 - close_brace = close_brace if close_brace == "}" else ""
6226 - if bool(open_brace) != bool(close_brace):
6227 - continue
6228 - var_name = m.group(2)
6229 - eapi_filter = phase_info.prohibited_vars[var_name]
6230 - if eapi_filter is not None and not eapi_filter(eapi):
6231 - continue
6232 - issues.append(
6233 - "phase %s: EAPI %s: variable %s: Forbidden reference to variable specified by PMS"
6234 - % (self.in_phase, eapi, var_name)
6235 - )
6236 - return issues
6237
6238 diff --git a/repoman/lib/repoman/modules/linechecks/portage/__init__.py b/repoman/lib/repoman/modules/linechecks/portage/__init__.py
6239 deleted file mode 100644
6240 index d30877d6d..000000000
6241 --- a/repoman/lib/repoman/modules/linechecks/portage/__init__.py
6242 +++ /dev/null
6243 @@ -1,27 +0,0 @@
6244 -# Copyright 2015-2021 Gentoo Authors
6245 -# Distributed under the terms of the GNU General Public License v2
6246 -
6247 -doc = """Portage plug-in module for repoman LineChecks.
6248 -Performs checks for internal portage variable usage in ebuilds."""
6249 -__doc__ = doc[:]
6250 -
6251 -
6252 -module_spec = {
6253 - "name": "do",
6254 - "description": doc,
6255 - "provides": {
6256 - "internal-check": {
6257 - "name": "portageinternal",
6258 - "sourcefile": "internal",
6259 - "class": "PortageInternal",
6260 - "description": doc,
6261 - },
6262 - "portageinternalvariableassignment-check": {
6263 - "name": "portageinternalvariableassignment",
6264 - "sourcefile": "internal",
6265 - "class": "PortageInternalVariableAssignment",
6266 - "description": doc,
6267 - },
6268 - },
6269 - "version": 1,
6270 -}
6271
6272 diff --git a/repoman/lib/repoman/modules/linechecks/portage/internal.py b/repoman/lib/repoman/modules/linechecks/portage/internal.py
6273 deleted file mode 100644
6274 index 5d6af1088..000000000
6275 --- a/repoman/lib/repoman/modules/linechecks/portage/internal.py
6276 +++ /dev/null
6277 @@ -1,32 +0,0 @@
6278 -import re
6279 -
6280 -from repoman.modules.linechecks.base import LineCheck
6281 -
6282 -
6283 -class PortageInternal(LineCheck):
6284 - repoman_check_name = "portage.internal"
6285 - ignore_comment = True
6286 - # Match when the command is preceded only by leading whitespace or a shell
6287 - # operator such as (, {, |, ||, or &&. This prevents false positives in
6288 - # things like elog messages, as reported in bug #413285.
6289 -
6290 - internal_portage_func_or_var = (
6291 - "ecompress|ecompressdir|env-update|prepall|prepalldocs|preplib"
6292 - )
6293 - re = re.compile(r"^(\s*|.*[|&{(]+\s*)\b(%s)\b" % internal_portage_func_or_var)
6294 -
6295 - def check(self, num, line):
6296 - """Run the check on line and return error if there is one"""
6297 - m = self.re.match(line)
6298 - if m is not None:
6299 - return "'%s' called" % m.group(2)
6300 -
6301 -
6302 -class PortageInternalVariableAssignment(LineCheck):
6303 - repoman_check_name = "portage.internal"
6304 - internal_assignment = re.compile(r"\s*(export\s+)?(EXTRA_ECONF|EXTRA_EMAKE)\+?=")
6305 -
6306 - def check(self, num, line):
6307 - match = self.internal_assignment.match(line)
6308 - if match is not None:
6309 - return "Assignment to variable %s" % match.group(2)
6310
6311 diff --git a/repoman/lib/repoman/modules/linechecks/quotes/__init__.py b/repoman/lib/repoman/modules/linechecks/quotes/__init__.py
6312 deleted file mode 100644
6313 index deb4ced97..000000000
6314 --- a/repoman/lib/repoman/modules/linechecks/quotes/__init__.py
6315 +++ /dev/null
6316 @@ -1,27 +0,0 @@
6317 -# Copyright 2015-2021 Gentoo Authors
6318 -# Distributed under the terms of the GNU General Public License v2
6319 -
6320 -doc = """Nested plug-in module for repoman LineChecks.
6321 -Performs nested subshell checks on ebuilds."""
6322 -__doc__ = doc[:]
6323 -
6324 -
6325 -module_spec = {
6326 - "name": "do",
6327 - "description": doc,
6328 - "provides": {
6329 - "quote-check": {
6330 - "name": "quote",
6331 - "sourcefile": "quotes",
6332 - "class": "EbuildQuote",
6333 - "description": doc,
6334 - },
6335 - "quoteda-check": {
6336 - "name": "quoteda",
6337 - "sourcefile": "quoteda",
6338 - "class": "EbuildQuotedA",
6339 - "description": doc,
6340 - },
6341 - },
6342 - "version": 1,
6343 -}
6344
6345 diff --git a/repoman/lib/repoman/modules/linechecks/quotes/quoteda.py b/repoman/lib/repoman/modules/linechecks/quotes/quoteda.py
6346 deleted file mode 100644
6347 index f44d4e38e..000000000
6348 --- a/repoman/lib/repoman/modules/linechecks/quotes/quoteda.py
6349 +++ /dev/null
6350 @@ -1,15 +0,0 @@
6351 -import re
6352 -
6353 -from repoman.modules.linechecks.base import LineCheck
6354 -
6355 -
6356 -class EbuildQuotedA(LineCheck):
6357 - """Ensure ebuilds have no quoting around ${A}"""
6358 -
6359 - repoman_check_name = "ebuild.minorsyn"
6360 - a_quoted = re.compile(r".*\"\$(\{A\}|A)\"")
6361 -
6362 - def check(self, num, line):
6363 - match = self.a_quoted.match(line)
6364 - if match:
6365 - return 'Quoted "${A}"'
6366
6367 diff --git a/repoman/lib/repoman/modules/linechecks/quotes/quotes.py b/repoman/lib/repoman/modules/linechecks/quotes/quotes.py
6368 deleted file mode 100644
6369 index c170c10ef..000000000
6370 --- a/repoman/lib/repoman/modules/linechecks/quotes/quotes.py
6371 +++ /dev/null
6372 @@ -1,92 +0,0 @@
6373 -import re
6374 -
6375 -from repoman.modules.linechecks.base import LineCheck
6376 -
6377 -
6378 -class EbuildQuote(LineCheck):
6379 - """Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
6380 -
6381 - repoman_check_name = "ebuild.minorsyn"
6382 - _message_commands = ["die", "echo", "eerror", "einfo", "elog", "eqawarn", "ewarn"]
6383 - _message_re = re.compile(r"\s(" + "|".join(_message_commands) + r')\s+"[^"]*"\s*$')
6384 - _ignored_commands = ["local", "export"] + _message_commands
6385 - ignore_line = re.compile(
6386 - r"(^$)|(^\s*#.*)|(^\s*\w+=.*)"
6387 - + r"|(^\s*("
6388 - + "|".join(_ignored_commands)
6389 - + r")\s+)"
6390 - )
6391 - ignore_comment = False
6392 - var_names = ["D", "DISTDIR", "FILESDIR", "S", "T", "ROOT", "BROOT", "WORKDIR"]
6393 -
6394 - # EAPI=3/Prefix vars
6395 - var_names += ["ED", "EPREFIX", "EROOT"]
6396 -
6397 - # variables for games.eclass
6398 - var_names += [
6399 - "Ddir",
6400 - "GAMES_PREFIX_OPT",
6401 - "GAMES_DATADIR",
6402 - "GAMES_DATADIR_BASE",
6403 - "GAMES_SYSCONFDIR",
6404 - "GAMES_STATEDIR",
6405 - "GAMES_LOGDIR",
6406 - "GAMES_BINDIR",
6407 - ]
6408 -
6409 - # variables for multibuild.eclass
6410 - var_names += ["BUILD_DIR"]
6411 -
6412 - var_names = "(%s)" % "|".join(var_names)
6413 - var_reference = re.compile(r"\$(\{%s\}|%s\W)" % (var_names, var_names))
6414 - missing_quotes = re.compile(r'(\s|^)[^"\'\s]*\$\{?%s\}?[^"\'\s]*(\s|$)' % var_names)
6415 - cond_begin = re.compile(r"(^|\s+)\[\[($|\\$|\s+)")
6416 - cond_end = re.compile(r"(^|\s+)\]\]($|\\$|\s+)")
6417 -
6418 - def check(self, num, line):
6419 - if self.var_reference.search(line) is None:
6420 - return
6421 - # There can be multiple matches / violations on a single line. We
6422 - # have to make sure none of the matches are violators. Once we've
6423 - # found one violator, any remaining matches on the same line can
6424 - # be ignored.
6425 - pos = 0
6426 - while pos <= len(line) - 1:
6427 - missing_quotes = self.missing_quotes.search(line, pos)
6428 - if not missing_quotes:
6429 - break
6430 - # If the last character of the previous match is a whitespace
6431 - # character, that character may be needed for the next
6432 - # missing_quotes match, so search overlaps by 1 character.
6433 - group = missing_quotes.group()
6434 - pos = missing_quotes.end() - 1
6435 -
6436 - # Filter out some false positives that can
6437 - # get through the missing_quotes regex.
6438 - if self.var_reference.search(group) is None:
6439 - continue
6440 -
6441 - # Filter matches that appear to be an
6442 - # argument to a message command.
6443 - # For example: false || ewarn "foo $WORKDIR/bar baz"
6444 - message_match = self._message_re.search(line)
6445 - if (
6446 - message_match is not None
6447 - and message_match.start() < pos
6448 - and message_match.end() > pos
6449 - ):
6450 - break
6451 -
6452 - # This is an attempt to avoid false positives without getting
6453 - # too complex, while possibly allowing some (hopefully
6454 - # unlikely) violations to slip through. We just assume
6455 - # everything is correct if the there is a ' [[ ' or a ' ]] '
6456 - # anywhere in the whole line (possibly continued over one
6457 - # line).
6458 - if self.cond_begin.search(line) is not None:
6459 - continue
6460 - if self.cond_end.search(line) is not None:
6461 - continue
6462 -
6463 - # Any remaining matches on the same line can be ignored.
6464 - return self.errors["MISSING_QUOTES_ERROR"]
6465
6466 diff --git a/repoman/lib/repoman/modules/linechecks/uri/__init__.py b/repoman/lib/repoman/modules/linechecks/uri/__init__.py
6467 deleted file mode 100644
6468 index 4018020c3..000000000
6469 --- a/repoman/lib/repoman/modules/linechecks/uri/__init__.py
6470 +++ /dev/null
6471 @@ -1,21 +0,0 @@
6472 -# Copyright 2015-2021 Gentoo Authors
6473 -# Distributed under the terms of the GNU General Public License v2
6474 -
6475 -doc = """Uri plug-in module for repoman LineChecks.
6476 -Performs HOMEPAGE variable checks on ebuilds."""
6477 -__doc__ = doc[:]
6478 -
6479 -
6480 -module_spec = {
6481 - "name": "do",
6482 - "description": doc,
6483 - "provides": {
6484 - "httpsuri-check": {
6485 - "name": "httpsuri",
6486 - "sourcefile": "uri",
6487 - "class": "UriUseHttps",
6488 - "description": doc,
6489 - },
6490 - },
6491 - "version": 1,
6492 -}
6493
6494 diff --git a/repoman/lib/repoman/modules/linechecks/uri/uri.py b/repoman/lib/repoman/modules/linechecks/uri/uri.py
6495 deleted file mode 100644
6496 index 9f3e49fe0..000000000
6497 --- a/repoman/lib/repoman/modules/linechecks/uri/uri.py
6498 +++ /dev/null
6499 @@ -1,30 +0,0 @@
6500 -import re # pylint: disable=unused-import
6501 -
6502 -from repoman.modules.linechecks.base import LineCheck
6503 -
6504 -
6505 -class UriUseHttps(LineCheck):
6506 - """Check that we use https:// for known good sites."""
6507 -
6508 - repoman_check_name = "uri.https"
6509 - _SITES = (
6510 - r"([-._a-zA-Z0-9]*\.)?apache\.org",
6511 - r"((alioth|packages(\.qa)?|people|www)\.)?debian\.org",
6512 - # Most FDO sites support https, but not all (like tango).
6513 - # List the most common ones here for now.
6514 - r"((anongit|bugs|cgit|dri|patchwork|people|specifications|www|xcb|xorg)\.)?freedesktop\.org",
6515 - r"((bugs|dev|wiki|www)\.)?gentoo\.org",
6516 - r"((wiki)\.)?github\.(io|com)",
6517 - r"savannah\.(non)?gnu\.org",
6518 - r"((gcc|www)\.)?gnu\.org",
6519 - r"curl\.haxx\.se",
6520 - r"((bugzilla|git|mirrors|patchwork|planet|www(\.wiki)?)\.)?kernel\.org",
6521 - r"((bugs|wiki|www)\.)?linuxfoundation\.org",
6522 - r"((docs|pypi|www)\.)?python\.org",
6523 - r"(sf|sourceforge)\.net",
6524 - r"(www\.)?(enlightenment|sourceware|x)\.org",
6525 - )
6526 - # Try to anchor the end of the URL so we don't get false positives
6527 - # with http://github.com.foo.bar.com/. Unlikely, but possible.
6528 - re = re.compile(r'.*\bhttp://(%s)(\s|["\'/]|$)' % r"|".join(_SITES))
6529 - error = "URI_HTTPS"
6530
6531 diff --git a/repoman/lib/repoman/modules/linechecks/use/__init__.py b/repoman/lib/repoman/modules/linechecks/use/__init__.py
6532 deleted file mode 100644
6533 index 0d738c37c..000000000
6534 --- a/repoman/lib/repoman/modules/linechecks/use/__init__.py
6535 +++ /dev/null
6536 @@ -1,21 +0,0 @@
6537 -# Copyright 2015-2021 Gentoo Authors
6538 -# Distributed under the terms of the GNU General Public License v2
6539 -
6540 -doc = """Use plug-in module for repoman LineChecks.
6541 -Performs Built-With-Use checks on ebuilds."""
6542 -__doc__ = doc[:]
6543 -
6544 -
6545 -module_spec = {
6546 - "name": "do",
6547 - "description": doc,
6548 - "provides": {
6549 - "builtwith-check": {
6550 - "name": "builtwith",
6551 - "sourcefile": "builtwith",
6552 - "class": "BuiltWithUse",
6553 - "description": doc,
6554 - },
6555 - },
6556 - "version": 1,
6557 -}
6558
6559 diff --git a/repoman/lib/repoman/modules/linechecks/use/builtwith.py b/repoman/lib/repoman/modules/linechecks/use/builtwith.py
6560 deleted file mode 100644
6561 index 0b16de028..000000000
6562 --- a/repoman/lib/repoman/modules/linechecks/use/builtwith.py
6563 +++ /dev/null
6564 @@ -1,9 +0,0 @@
6565 -import re # pylint: disable=unused-import
6566 -
6567 -from repoman.modules.linechecks.base import LineCheck
6568 -
6569 -
6570 -class BuiltWithUse(LineCheck):
6571 - repoman_check_name = "ebuild.minorsyn"
6572 - re = re.compile(r"(^|.*\b)built_with_use\b")
6573 - error = "BUILT_WITH_USE"
6574
6575 diff --git a/repoman/lib/repoman/modules/linechecks/useless/__init__.py b/repoman/lib/repoman/modules/linechecks/useless/__init__.py
6576 deleted file mode 100644
6577 index 9be951584..000000000
6578 --- a/repoman/lib/repoman/modules/linechecks/useless/__init__.py
6579 +++ /dev/null
6580 @@ -1,27 +0,0 @@
6581 -# Copyright 2015-2021 Gentoo Authors
6582 -# Distributed under the terms of the GNU General Public License v2
6583 -
6584 -doc = """Useless plug-in module for repoman LineChecks.
6585 -Performs checks for useless operations on ebuilds."""
6586 -__doc__ = doc[:]
6587 -
6588 -
6589 -module_spec = {
6590 - "name": "do",
6591 - "description": doc,
6592 - "provides": {
6593 - "uselesscds-check": {
6594 - "name": "uselesscds",
6595 - "sourcefile": "cd",
6596 - "class": "EbuildUselessCdS",
6597 - "description": doc,
6598 - },
6599 - "uselessdodoc-check": {
6600 - "name": "uselessdodoc",
6601 - "sourcefile": "dodoc",
6602 - "class": "EbuildUselessDodoc",
6603 - "description": doc,
6604 - },
6605 - },
6606 - "version": 1,
6607 -}
6608
6609 diff --git a/repoman/lib/repoman/modules/linechecks/useless/cd.py b/repoman/lib/repoman/modules/linechecks/useless/cd.py
6610 deleted file mode 100644
6611 index 73063209f..000000000
6612 --- a/repoman/lib/repoman/modules/linechecks/useless/cd.py
6613 +++ /dev/null
6614 @@ -1,24 +0,0 @@
6615 -import re
6616 -
6617 -from repoman.modules.linechecks.base import LineCheck
6618 -
6619 -
6620 -class EbuildUselessCdS(LineCheck):
6621 - """Check for redundant cd ${S} statements"""
6622 -
6623 - repoman_check_name = "ebuild.minorsyn"
6624 - _src_phases = r"^\s*src_(prepare|configure|compile|install|test)\s*\(\)"
6625 - method_re = re.compile(_src_phases)
6626 - cds_re = re.compile(r'^\s*cd\s+("\$(\{S\}|S)"|\$(\{S\}|S))\s')
6627 -
6628 - def __init__(self, errors):
6629 - self.errors = errors
6630 - self.check_next_line = False
6631 -
6632 - def check(self, num, line):
6633 - if self.check_next_line:
6634 - self.check_next_line = False
6635 - if self.cds_re.match(line):
6636 - return self.errors["REDUNDANT_CD_S_ERROR"]
6637 - elif self.method_re.match(line):
6638 - self.check_next_line = True
6639
6640 diff --git a/repoman/lib/repoman/modules/linechecks/useless/dodoc.py b/repoman/lib/repoman/modules/linechecks/useless/dodoc.py
6641 deleted file mode 100644
6642 index 49f6fde91..000000000
6643 --- a/repoman/lib/repoman/modules/linechecks/useless/dodoc.py
6644 +++ /dev/null
6645 @@ -1,17 +0,0 @@
6646 -import re
6647 -
6648 -from repoman.modules.linechecks.base import LineCheck
6649 -
6650 -
6651 -class EbuildUselessDodoc(LineCheck):
6652 - """Check ebuild for useless files in dodoc arguments."""
6653 -
6654 - repoman_check_name = "ebuild.minorsyn"
6655 - uselessdodoc_re = re.compile(
6656 - r"^\s*dodoc(\s+|\s+.*\s+)(ABOUT-NLS|COPYING|LICENCE|LICENSE)($|\s)"
6657 - )
6658 -
6659 - def check(self, num, line):
6660 - match = self.uselessdodoc_re.match(line)
6661 - if match:
6662 - return "Useless dodoc '%s'" % match.group(2)
6663
6664 diff --git a/repoman/lib/repoman/modules/linechecks/whitespace/__init__.py b/repoman/lib/repoman/modules/linechecks/whitespace/__init__.py
6665 deleted file mode 100644
6666 index 17b3abab5..000000000
6667 --- a/repoman/lib/repoman/modules/linechecks/whitespace/__init__.py
6668 +++ /dev/null
6669 @@ -1,27 +0,0 @@
6670 -# Copyright 2015-2021 Gentoo Authors
6671 -# Distributed under the terms of the GNU General Public License v2
6672 -
6673 -doc = """Whitespace plug-in module for repoman LineChecks.
6674 -Performs checks for useless whitespace in ebuilds."""
6675 -__doc__ = doc[:]
6676 -
6677 -
6678 -module_spec = {
6679 - "name": "do",
6680 - "description": doc,
6681 - "provides": {
6682 - "whitespace-check": {
6683 - "name": "whitespace",
6684 - "sourcefile": "whitespace",
6685 - "class": "EbuildWhitespace",
6686 - "description": doc,
6687 - },
6688 - "blankline-check": {
6689 - "name": "blankline",
6690 - "sourcefile": "blank",
6691 - "class": "EbuildBlankLine",
6692 - "description": doc,
6693 - },
6694 - },
6695 - "version": 1,
6696 -}
6697
6698 diff --git a/repoman/lib/repoman/modules/linechecks/whitespace/blank.py b/repoman/lib/repoman/modules/linechecks/whitespace/blank.py
6699 deleted file mode 100644
6700 index 89e38c68c..000000000
6701 --- a/repoman/lib/repoman/modules/linechecks/whitespace/blank.py
6702 +++ /dev/null
6703 @@ -1,24 +0,0 @@
6704 -import re
6705 -
6706 -from repoman.modules.linechecks.base import LineCheck
6707 -
6708 -
6709 -class EbuildBlankLine(LineCheck):
6710 - repoman_check_name = "ebuild.minorsyn"
6711 - ignore_comment = False
6712 - blank_line = re.compile(r"^$")
6713 -
6714 - def new(self, pkg):
6715 - self.line_is_blank = False
6716 -
6717 - def check(self, num, line):
6718 - if self.line_is_blank and self.blank_line.match(line):
6719 - return "Useless blank line"
6720 - if self.blank_line.match(line):
6721 - self.line_is_blank = True
6722 - else:
6723 - self.line_is_blank = False
6724 -
6725 - def end(self):
6726 - if self.line_is_blank:
6727 - yield "Useless blank line on last line"
6728
6729 diff --git a/repoman/lib/repoman/modules/linechecks/whitespace/whitespace.py b/repoman/lib/repoman/modules/linechecks/whitespace/whitespace.py
6730 deleted file mode 100644
6731 index a1274048d..000000000
6732 --- a/repoman/lib/repoman/modules/linechecks/whitespace/whitespace.py
6733 +++ /dev/null
6734 @@ -1,20 +0,0 @@
6735 -import re
6736 -
6737 -from repoman.modules.linechecks.base import LineCheck
6738 -
6739 -
6740 -class EbuildWhitespace(LineCheck):
6741 - """Ensure ebuilds have proper whitespacing"""
6742 -
6743 - repoman_check_name = "ebuild.minorsyn"
6744 -
6745 - ignore_line = re.compile(r"(^$)|(^(\t)*#)")
6746 - ignore_comment = False
6747 - leading_spaces = re.compile(r"^[\S\t]")
6748 - trailing_whitespace = re.compile(r".*([\S]$)")
6749 -
6750 - def check(self, num, line):
6751 - if self.leading_spaces.match(line) is None:
6752 - return self.errors["LEADING_SPACES_ERROR"]
6753 - if self.trailing_whitespace.match(line) is None:
6754 - return self.errors["TRAILING_WHITESPACE_ERROR"]
6755
6756 diff --git a/repoman/lib/repoman/modules/linechecks/workaround/__init__.py b/repoman/lib/repoman/modules/linechecks/workaround/__init__.py
6757 deleted file mode 100644
6758 index eff33cf23..000000000
6759 --- a/repoman/lib/repoman/modules/linechecks/workaround/__init__.py
6760 +++ /dev/null
6761 @@ -1,21 +0,0 @@
6762 -# Copyright 2015-2021 Gentoo Authors
6763 -# Distributed under the terms of the GNU General Public License v2
6764 -
6765 -doc = """Workaround plug-in module for repoman LineChecks.
6766 -Performs checks for upstream workarounds in ebuilds."""
6767 -__doc__ = doc[:]
6768 -
6769 -
6770 -module_spec = {
6771 - "name": "do",
6772 - "description": doc,
6773 - "provides": {
6774 - "noasneeded-check": {
6775 - "name": "noasneeded",
6776 - "sourcefile": "workarounds",
6777 - "class": "NoAsNeeded",
6778 - "description": doc,
6779 - },
6780 - },
6781 - "version": 1,
6782 -}
6783
6784 diff --git a/repoman/lib/repoman/modules/linechecks/workaround/workarounds.py b/repoman/lib/repoman/modules/linechecks/workaround/workarounds.py
6785 deleted file mode 100644
6786 index 47b6881ff..000000000
6787 --- a/repoman/lib/repoman/modules/linechecks/workaround/workarounds.py
6788 +++ /dev/null
6789 @@ -1,11 +0,0 @@
6790 -import re # pylint: disable=unused-import
6791 -
6792 -from repoman.modules.linechecks.base import LineCheck
6793 -
6794 -
6795 -class NoAsNeeded(LineCheck):
6796 - """Check for calls to the no-as-needed function."""
6797 -
6798 - repoman_check_name = "upstream.workaround"
6799 - re = re.compile(r".*\$\(no-as-needed\)")
6800 - error = "NO_AS_NEEDED"
6801
6802 diff --git a/repoman/lib/repoman/modules/scan/__init__.py b/repoman/lib/repoman/modules/scan/__init__.py
6803 deleted file mode 100644
6804 index e69de29bb..000000000
6805
6806 diff --git a/repoman/lib/repoman/modules/scan/depend/__init__.py b/repoman/lib/repoman/modules/scan/depend/__init__.py
6807 deleted file mode 100644
6808 index cac382b6f..000000000
6809 --- a/repoman/lib/repoman/modules/scan/depend/__init__.py
6810 +++ /dev/null
6811 @@ -1,43 +0,0 @@
6812 -# Copyright 2015-2021 Gentoo Authors
6813 -# Distributed under the terms of the GNU General Public License v2
6814 -
6815 -doc = """Depend plug-in module for repoman.
6816 -Performs Dependency checks on ebuilds."""
6817 -__doc__ = doc[:]
6818 -
6819 -
6820 -module_spec = {
6821 - "name": "depend",
6822 - "description": doc,
6823 - "provides": {
6824 - "profile-module": {
6825 - "name": "profile",
6826 - "sourcefile": "profile",
6827 - "class": "ProfileDependsChecks",
6828 - "description": doc,
6829 - "functions": ["check"],
6830 - "func_desc": {},
6831 - "mod_kwargs": [
6832 - "qatracker",
6833 - "portdb",
6834 - "profiles",
6835 - "options",
6836 - "repo_metadata",
6837 - "repo_settings",
6838 - "include_arches",
6839 - "include_profiles",
6840 - "caches",
6841 - "repoman_incrementals",
6842 - "env",
6843 - "have",
6844 - "dev_keywords",
6845 - ],
6846 - "func_kwargs": {
6847 - "ebuild": (None, None),
6848 - "pkg": (None, None),
6849 - },
6850 - "module_runsIn": ["ebuilds"],
6851 - },
6852 - },
6853 - "version": 1,
6854 -}
6855
6856 diff --git a/repoman/lib/repoman/modules/scan/depend/_depend_checks.py b/repoman/lib/repoman/modules/scan/depend/_depend_checks.py
6857 deleted file mode 100644
6858 index 11a2fbf56..000000000
6859 --- a/repoman/lib/repoman/modules/scan/depend/_depend_checks.py
6860 +++ /dev/null
6861 @@ -1,260 +0,0 @@
6862 -# -*- coding:utf-8 -*-
6863 -
6864 -import collections
6865 -
6866 -from _emerge.Package import Package
6867 -
6868 -from portage.dep import Atom
6869 -
6870 -from repoman.check_missingslot import check_missingslot
6871 -
6872 -# import our initialized portage instance
6873 -from repoman._portage import portage
6874 -
6875 -
6876 -def check_slotop(depstr, is_valid_flag, badsyntax, mytype, qatracker, relative_path):
6877 - """Checks if RDEPEND uses ':=' slot operator
6878 - in '||' style dependencies."""
6879 -
6880 - try:
6881 - # to find use of ':=' in '||' we preserve
6882 - # tree structure of dependencies
6883 - my_dep_tree = portage.dep.use_reduce(
6884 - depstr,
6885 - flat=False,
6886 - matchall=1,
6887 - is_valid_flag=is_valid_flag,
6888 - opconvert=True,
6889 - token_class=portage.dep.Atom,
6890 - )
6891 - except portage.exception.InvalidDependString as e:
6892 - my_dep_tree = None
6893 - badsyntax.append((mytype, str(e)))
6894 -
6895 - def _traverse_tree(dep_tree, in_any_of):
6896 - # leaf
6897 - if isinstance(dep_tree, Atom):
6898 - atom = dep_tree
6899 - if in_any_of and atom.slot_operator == "=":
6900 - qatracker.add_error(
6901 - "dependency.badslotop",
6902 - "%s: %s: '%s' uses ':=' slot operator under '||' dep clause."
6903 - % (relative_path, mytype, atom),
6904 - )
6905 -
6906 - # branches
6907 - if isinstance(dep_tree, list):
6908 - if len(dep_tree) == 0:
6909 - return
6910 - # entering any-of
6911 - if dep_tree[0] == "||":
6912 - _traverse_tree(dep_tree[1:], in_any_of=True)
6913 - else:
6914 - for branch in dep_tree:
6915 - _traverse_tree(branch, in_any_of=in_any_of)
6916 -
6917 - _traverse_tree(my_dep_tree, False)
6918 -
6919 -
6920 -def _depend_checks(ebuild, pkg, portdb, qatracker, repo_metadata, qadata):
6921 - """Checks the ebuild dependencies for errors
6922 -
6923 - @param pkg: Package in which we check (object).
6924 - @param ebuild: Ebuild which we check (object).
6925 - @param portdb: portdb instance
6926 - @param qatracker: QATracker instance
6927 - @param repo_metadata: dictionary of various repository items.
6928 - @returns: (unknown_pkgs, badlicsyntax)
6929 - """
6930 -
6931 - unknown_pkgs = set()
6932 -
6933 - inherited_java_eclass = (
6934 - "java-pkg-2" in ebuild.inherited or "java-pkg-opt-2" in ebuild.inherited
6935 - )
6936 - inherited_wxwidgets_eclass = "wxwidgets" in ebuild.inherited
6937 - # operator_tokens = set(["||", "(", ")"])
6938 - badsyntax = []
6939 - for mytype in Package._dep_keys + ("LICENSE", "PROPERTIES"):
6940 - mydepstr = ebuild.metadata[mytype]
6941 -
6942 - buildtime = mytype in Package._buildtime_keys
6943 - runtime = mytype in Package._runtime_keys
6944 - token_class = None
6945 - if mytype.endswith("DEPEND"):
6946 - token_class = portage.dep.Atom
6947 -
6948 - try:
6949 - atoms = portage.dep.use_reduce(
6950 - mydepstr,
6951 - matchall=1,
6952 - flat=True,
6953 - is_valid_flag=pkg.iuse.is_valid_flag,
6954 - token_class=token_class,
6955 - )
6956 - except portage.exception.InvalidDependString as e:
6957 - atoms = None
6958 - badsyntax.append((mytype, str(e)))
6959 -
6960 - if atoms and mytype.endswith("DEPEND"):
6961 - if runtime and "test?" in mydepstr.split():
6962 - qatracker.add_error(
6963 - mytype + ".suspect",
6964 - "%s: 'test?' USE conditional in %s"
6965 - % (ebuild.relative_path, mytype),
6966 - )
6967 -
6968 - for atom in atoms:
6969 - if atom == "||":
6970 - continue
6971 -
6972 - is_blocker = atom.blocker
6973 -
6974 - # Skip dependency.unknown for blockers, so that we
6975 - # don't encourage people to remove necessary blockers,
6976 - # as discussed in bug 382407. We use atom.without_use
6977 - # due to bug 525376.
6978 - if (
6979 - not is_blocker
6980 - and not portdb.xmatch("match-all", atom.without_use)
6981 - and not atom.cp.startswith("virtual/")
6982 - ):
6983 - unknown_pkgs.add((mytype, atom.unevaluated_atom))
6984 -
6985 - if not atom.blocker:
6986 - all_deprecated = False
6987 - for pkg_match in portdb.xmatch("match-all", atom):
6988 - if any(
6989 - repo_metadata["package.deprecated"].iterAtomsForPackage(
6990 - pkg_match
6991 - )
6992 - ):
6993 - all_deprecated = True
6994 - else:
6995 - all_deprecated = False
6996 - break
6997 -
6998 - if all_deprecated:
6999 - qatracker.add_error(
7000 - "dependency.deprecated",
7001 - ebuild.relative_path + ": '%s'" % atom,
7002 - )
7003 -
7004 - if pkg.category != "virtual":
7005 - if not is_blocker and atom.cp in qadata.suspect_virtual:
7006 - qatracker.add_error(
7007 - "virtual.suspect",
7008 - ebuild.relative_path
7009 - + ": %s: consider using '%s' instead of '%s'"
7010 - % (mytype, qadata.suspect_virtual[atom.cp], atom),
7011 - )
7012 - if not is_blocker and atom.cp.startswith("perl-core/"):
7013 - qatracker.add_error(
7014 - "dependency.perlcore",
7015 - ebuild.relative_path
7016 - + ": %s: please use '%s' instead of '%s'"
7017 - % (
7018 - mytype,
7019 - atom.replace("perl-core/", "virtual/perl-"),
7020 - atom,
7021 - ),
7022 - )
7023 -
7024 - if (
7025 - buildtime
7026 - and not is_blocker
7027 - and not inherited_java_eclass
7028 - and atom.cp == "virtual/jdk"
7029 - ):
7030 - qatracker.add_error("java.eclassesnotused", ebuild.relative_path)
7031 - elif (
7032 - buildtime
7033 - and not is_blocker
7034 - and not inherited_wxwidgets_eclass
7035 - and atom.cp == "x11-libs/wxGTK"
7036 - ):
7037 - qatracker.add_error(
7038 - "wxwidgets.eclassnotused",
7039 - "%s: %ss on x11-libs/wxGTK without inheriting"
7040 - " wxwidgets.eclass" % (ebuild.relative_path, mytype),
7041 - )
7042 - elif runtime:
7043 - if not is_blocker and atom.cp in qadata.suspect_rdepend:
7044 - qatracker.add_error(
7045 - mytype + ".suspect", ebuild.relative_path + ": '%s'" % atom
7046 - )
7047 -
7048 - if (
7049 - atom.operator == "~"
7050 - and portage.versions.catpkgsplit(atom.cpv)[3] != "r0"
7051 - ):
7052 - qacat = "dependency.badtilde"
7053 - qatracker.add_error(
7054 - qacat,
7055 - "%s: %s uses the ~ operator"
7056 - " with a non-zero revision: '%s'"
7057 - % (ebuild.relative_path, mytype, atom),
7058 - )
7059 - # plain =foo-1.2.3 without revision or *
7060 - if atom.operator == "=" and "-r" not in atom.version:
7061 - qacat = "dependency.equalsversion"
7062 - qatracker.add_error(
7063 - qacat,
7064 - "%s: %s uses the = operator with"
7065 - " no revision: '%s'; if any revision is"
7066 - " acceptable, use '~' instead; if only -r0"
7067 - " then please append '-r0' to the dep"
7068 - % (ebuild.relative_path, mytype, atom),
7069 - )
7070 -
7071 - check_missingslot(
7072 - atom,
7073 - mytype,
7074 - ebuild.eapi,
7075 - portdb,
7076 - qatracker,
7077 - ebuild.relative_path,
7078 - ebuild.metadata,
7079 - )
7080 -
7081 - if runtime:
7082 - check_slotop(
7083 - mydepstr,
7084 - pkg.iuse.is_valid_flag,
7085 - badsyntax,
7086 - mytype,
7087 - qatracker,
7088 - ebuild.relative_path,
7089 - )
7090 -
7091 - baddepsyntax = False
7092 - dedup = collections.defaultdict(set)
7093 - for m, b in badsyntax:
7094 - if b in dedup[m]:
7095 - continue
7096 - dedup[m].add(b)
7097 -
7098 - if m.endswith("DEPEND"):
7099 - baddepsyntax = True
7100 - qacat = "dependency.syntax"
7101 - else:
7102 - qacat = m + ".syntax"
7103 - qatracker.add_error(qacat, "%s: %s: %s" % (ebuild.relative_path, m, b))
7104 -
7105 - # Parse the LICENSE variable, remove USE conditions and flatten it.
7106 - licenses = portage.dep.use_reduce(ebuild.metadata["LICENSE"], matchall=1, flat=True)
7107 -
7108 - # Check each entry to ensure that it exists in ${PORTDIR}/licenses/.
7109 - for lic in licenses:
7110 - # Need to check for "||" manually as no portage
7111 - # function will remove it without removing values.
7112 - if lic not in repo_metadata["liclist"] and lic != "||":
7113 - qatracker.add_error(
7114 - "LICENSE.invalid", "%s: %s" % (ebuild.relative_path, lic)
7115 - )
7116 - elif lic in repo_metadata["lic_deprecated"]:
7117 - qatracker.add_error(
7118 - "LICENSE.deprecated", "%s: %s" % (ebuild.relative_path, lic)
7119 - )
7120 -
7121 - return unknown_pkgs, baddepsyntax
7122
7123 diff --git a/repoman/lib/repoman/modules/scan/depend/_gen_arches.py b/repoman/lib/repoman/modules/scan/depend/_gen_arches.py
7124 deleted file mode 100644
7125 index 6e3000014..000000000
7126 --- a/repoman/lib/repoman/modules/scan/depend/_gen_arches.py
7127 +++ /dev/null
7128 @@ -1,67 +0,0 @@
7129 -# -*- coding:utf-8 -*-
7130 -
7131 -
7132 -def _gen_arches(ebuild, options, repo_settings, profiles):
7133 - """Determines the arches for the ebuild following the profile rules
7134 -
7135 - @param ebuild: Ebuild which we check (object).
7136 - @param profiles: dictionary
7137 - @param options: cli options
7138 - @param repo_settings: repository settings instance
7139 - @returns: dictionary, including arches set
7140 - """
7141 - if options.ignore_arches:
7142 - arches = [
7143 - [
7144 - repo_settings.repoman_settings["ARCH"],
7145 - repo_settings.repoman_settings["ARCH"],
7146 - repo_settings.repoman_settings["ACCEPT_KEYWORDS"].split(),
7147 - ]
7148 - ]
7149 - else:
7150 - arches = set()
7151 - for keyword in ebuild.keywords:
7152 - if keyword[0] == "-":
7153 - continue
7154 - elif keyword[0] == "~":
7155 - arch = keyword[1:]
7156 - if arch == "*":
7157 - for expanded_arch in profiles:
7158 - if expanded_arch == "**":
7159 - continue
7160 - arches.add(
7161 - (
7162 - keyword,
7163 - expanded_arch,
7164 - (expanded_arch, "~" + expanded_arch),
7165 - )
7166 - )
7167 - else:
7168 - arches.add((keyword, arch, (arch, keyword)))
7169 - else:
7170 - # For ebuilds with stable keywords, check if the
7171 - # dependencies are satisfiable for unstable
7172 - # configurations, since use.stable.mask is not
7173 - # applied for unstable configurations (see bug
7174 - # 563546).
7175 - if keyword == "*":
7176 - for expanded_arch in profiles:
7177 - if expanded_arch == "**":
7178 - continue
7179 - arches.add((keyword, expanded_arch, (expanded_arch,)))
7180 - arches.add(
7181 - (
7182 - keyword,
7183 - expanded_arch,
7184 - (expanded_arch, "~" + expanded_arch),
7185 - )
7186 - )
7187 - else:
7188 - arches.add((keyword, keyword, (keyword,)))
7189 - arches.add((keyword, keyword, (keyword, "~" + keyword)))
7190 - if not arches:
7191 - # Use an empty profile for checking dependencies of
7192 - # packages that have empty KEYWORDS.
7193 - arches.add(("**", "**", ("**",)))
7194 -
7195 - return arches
7196
7197 diff --git a/repoman/lib/repoman/modules/scan/depend/profile.py b/repoman/lib/repoman/modules/scan/depend/profile.py
7198 deleted file mode 100644
7199 index a0cb3a314..000000000
7200 --- a/repoman/lib/repoman/modules/scan/depend/profile.py
7201 +++ /dev/null
7202 @@ -1,427 +0,0 @@
7203 -# -*- coding:utf-8 -*-
7204 -
7205 -
7206 -import copy
7207 -import functools
7208 -import os
7209 -import types
7210 -from pprint import pformat
7211 -
7212 -from _emerge.Package import Package
7213 -
7214 -# import our initialized portage instance
7215 -from repoman._portage import portage
7216 -from repoman.modules.scan.scanbase import ScanBase
7217 -from repoman.modules.scan.depend._depend_checks import _depend_checks
7218 -from repoman.modules.scan.depend._gen_arches import _gen_arches
7219 -from portage.dep import Atom
7220 -from portage.package.ebuild.profile_iuse import iter_iuse_vars
7221 -from portage.util import getconfig
7222 -from portage.util.futures import asyncio
7223 -from portage.util.futures.executor.fork import ForkExecutor
7224 -from portage.util.futures.iter_completed import async_iter_completed
7225 -
7226 -
7227 -def sort_key(item):
7228 - return item[2].sub_path
7229 -
7230 -
7231 -class ProfileDependsChecks(ScanBase):
7232 - """Perform dependency checks for the different profiles"""
7233 -
7234 - def __init__(self, **kwargs):
7235 - """Class init
7236 -
7237 - @param qatracker: QATracker instance
7238 - @param portdb: portdb instance
7239 - @param profiles: dictionary
7240 - @param options: cli options
7241 - @param repo_settings: repository settings instance
7242 - @param include_arches: set
7243 - @param include_profiles: set
7244 - @param caches: dictionary of our caches
7245 - @param repoman_incrementals: tuple
7246 - @param env: the environment
7247 - @param have: dictionary instance
7248 - @param dev_keywords: developer profile keywords
7249 - @param repo_metadata: dictionary of various repository items.
7250 - """
7251 - self.qatracker = kwargs.get("qatracker")
7252 - self.portdb = kwargs.get("portdb")
7253 - self.profiles = kwargs.get("profiles")
7254 - self.options = kwargs.get("options")
7255 - self.repo_settings = kwargs.get("repo_settings")
7256 - self.include_arches = kwargs.get("include_arches")
7257 - self.include_profiles = kwargs.get("include_profiles")
7258 - self.caches = kwargs.get("caches")
7259 - self.repoman_incrementals = kwargs.get("repoman_incrementals")
7260 - self.env = kwargs.get("env")
7261 - self.have = kwargs.get("have")
7262 - self.dev_keywords = kwargs.get("dev_keywords")
7263 - self.repo_metadata = kwargs.get("repo_metadata")
7264 -
7265 - def check(self, **kwargs):
7266 - """Perform profile dependant dependency checks
7267 -
7268 - @param pkg: Package in which we check (object).
7269 - @param ebuild: Ebuild which we check (object).
7270 - @returns: dictionary
7271 - """
7272 - ebuild = kwargs.get("ebuild").get()
7273 - pkg = kwargs.get("pkg").get()
7274 -
7275 - ebuild.unknown_pkgs, ebuild.baddepsyntax = _depend_checks(
7276 - ebuild,
7277 - pkg,
7278 - self.portdb,
7279 - self.qatracker,
7280 - self.repo_metadata,
7281 - self.repo_settings.qadata,
7282 - )
7283 -
7284 - relevant_profiles = []
7285 - for keyword, arch, groups in _gen_arches(
7286 - ebuild, self.options, self.repo_settings, self.profiles
7287 - ):
7288 - if arch not in self.profiles:
7289 - # A missing profile will create an error further down
7290 - # during the KEYWORDS verification.
7291 - continue
7292 -
7293 - if self.include_arches is not None:
7294 - if arch not in self.include_arches:
7295 - continue
7296 -
7297 - for prof in self.profiles[arch]:
7298 - if self.include_profiles is not None:
7299 - if prof.sub_path not in self.include_profiles:
7300 - continue
7301 - relevant_profiles.append((keyword, groups, prof))
7302 -
7303 - relevant_profiles.sort(key=sort_key)
7304 - ebuild.relevant_profiles = relevant_profiles
7305 -
7306 - if self.options.jobs <= 1:
7307 - for task in self._iter_tasks(None, None, ebuild, pkg):
7308 - task, results = task
7309 - for result in results:
7310 - self._check_result(task, result)
7311 -
7312 - loop = asyncio.get_event_loop()
7313 - loop.run_until_complete(self._async_check(loop, **kwargs))
7314 -
7315 - return False
7316 -
7317 - async def _async_check(self, loop, **kwargs):
7318 - """Perform async profile dependant dependency checks
7319 -
7320 - @param arches:
7321 - @param pkg: Package in which we check (object).
7322 - @param ebuild: Ebuild which we check (object).
7323 - @param baddepsyntax: boolean
7324 - @param unknown_pkgs: set of tuples (type, atom.unevaluated_atom)
7325 - @returns: dictionary
7326 - """
7327 - ebuild = kwargs.get("ebuild").get()
7328 - pkg = kwargs.get("pkg").get()
7329 - unknown_pkgs = ebuild.unknown_pkgs
7330 - baddepsyntax = ebuild.baddepsyntax
7331 -
7332 - # Use max_workers=True to ensure immediate fork, since _iter_tasks
7333 - # needs the fork to create a snapshot of current state.
7334 - executor = ForkExecutor(max_workers=self.options.jobs)
7335 -
7336 - if self.options.jobs > 1:
7337 - for future_done_set in async_iter_completed(
7338 - self._iter_tasks(loop, executor, ebuild, pkg),
7339 - max_jobs=self.options.jobs,
7340 - max_load=self.options.load_average,
7341 - ):
7342 - for task in await future_done_set:
7343 - task, results = task.result()
7344 - for result in results:
7345 - self._check_result(task, result)
7346 -
7347 - if not baddepsyntax and unknown_pkgs:
7348 - type_map = {}
7349 - for mytype, atom in unknown_pkgs:
7350 - type_map.setdefault(mytype, set()).add(atom)
7351 - for mytype, atoms in type_map.items():
7352 - self.qatracker.add_error(
7353 - "dependency.unknown",
7354 - "%s: %s: %s"
7355 - % (ebuild.relative_path, mytype, ", ".join(sorted(atoms))),
7356 - )
7357 -
7358 - async def _task(self, task):
7359 - await task.future
7360 - return (task, task.future.result())
7361 -
7362 - def _iter_tasks(self, loop, executor, ebuild, pkg):
7363 - for keyword, groups, prof in ebuild.relevant_profiles:
7364 -
7365 - is_stable_profile = prof.status == "stable"
7366 - is_dev_profile = prof.status == "dev" and self.options.include_dev
7367 - is_exp_profile = (
7368 - prof.status == "exp" and self.options.include_exp_profiles == "y"
7369 - )
7370 - if not (is_stable_profile or is_dev_profile or is_exp_profile):
7371 - continue
7372 -
7373 - dep_settings = self.caches["arch"].get(prof.sub_path)
7374 - if dep_settings is None:
7375 - dep_settings = portage.config(
7376 - config_profile_path=prof.abs_path,
7377 - config_incrementals=self.repoman_incrementals,
7378 - config_root=self.repo_settings.config_root,
7379 - local_config=False,
7380 - _unmatched_removal=self.options.unmatched_removal,
7381 - env=self.env,
7382 - repositories=self.repo_settings.repoman_settings.repositories,
7383 - )
7384 -
7385 - if not prof.abs_path:
7386 - self._populate_implicit_iuse(
7387 - dep_settings, self.repo_settings.repo_config.eclass_db.porttrees
7388 - )
7389 -
7390 - dep_settings.categories = self.repo_settings.repoman_settings.categories
7391 - if self.options.without_mask:
7392 - dep_settings._mask_manager_obj = copy.deepcopy(
7393 - dep_settings._mask_manager
7394 - )
7395 - dep_settings._mask_manager._pmaskdict.clear()
7396 - self.caches["arch"][prof.sub_path] = dep_settings
7397 -
7398 - xmatch_cache_key = (prof.sub_path, tuple(groups))
7399 - xcache = self.caches["arch_xmatch"].get(xmatch_cache_key)
7400 - if xcache is None:
7401 - self.portdb.melt()
7402 - self.portdb.freeze()
7403 - xcache = self.portdb.xcache
7404 - xcache.update(self.caches["shared_xmatch"])
7405 - self.caches["arch_xmatch"][xmatch_cache_key] = xcache
7406 -
7407 - self.repo_settings.trees[self.repo_settings.root][
7408 - "porttree"
7409 - ].settings = dep_settings
7410 - self.portdb.settings = dep_settings
7411 - self.portdb.xcache = xcache
7412 -
7413 - dep_settings["ACCEPT_KEYWORDS"] = " ".join(groups)
7414 - # just in case, prevent config.reset() from nuking these.
7415 - dep_settings.backup_changes("ACCEPT_KEYWORDS")
7416 -
7417 - # This attribute is used in dbapi._match_use() to apply
7418 - # use.stable.{mask,force} settings based on the stable
7419 - # status of the parent package. This is required in order
7420 - # for USE deps of unstable packages to be resolved correctly,
7421 - # since otherwise use.stable.{mask,force} settings of
7422 - # dependencies may conflict (see bug #456342).
7423 - dep_settings._parent_stable = dep_settings._isStable(pkg)
7424 -
7425 - # Handle package.use*.{force,mask) calculation, for use
7426 - # in dep_check.
7427 - dep_settings.useforce = dep_settings._use_manager.getUseForce(
7428 - pkg, stable=dep_settings._parent_stable
7429 - )
7430 - dep_settings.usemask = dep_settings._use_manager.getUseMask(
7431 - pkg, stable=dep_settings._parent_stable
7432 - )
7433 -
7434 - task = types.SimpleNamespace(ebuild=ebuild, prof=prof, keyword=keyword)
7435 -
7436 - target = functools.partial(self._task_subprocess, task, pkg, dep_settings)
7437 -
7438 - if self.options.jobs <= 1:
7439 - yield (task, target())
7440 - else:
7441 - task.future = asyncio.ensure_future(
7442 - loop.run_in_executor(executor, target), loop=loop
7443 - )
7444 - yield asyncio.ensure_future(self._task(task), loop=loop)
7445 -
7446 - def _task_subprocess(self, task, pkg, dep_settings):
7447 - ebuild = task.ebuild
7448 - baddepsyntax = ebuild.baddepsyntax
7449 - results = []
7450 - prof = task.prof
7451 - if not baddepsyntax:
7452 - ismasked = not ebuild.archs or pkg.cpv not in self.portdb.xmatch(
7453 - "match-visible",
7454 - Atom("%s::%s" % (pkg.cp, self.repo_settings.repo_config.name)),
7455 - )
7456 - if ismasked:
7457 - if not self.have["pmasked"]:
7458 - self.have["pmasked"] = bool(
7459 - dep_settings._getMaskAtom(pkg.cpv, ebuild.metadata)
7460 - )
7461 - if self.options.ignore_masked:
7462 - return results
7463 - # we are testing deps for a masked package; give it some lee-way
7464 - suffix = "masked"
7465 - matchmode = "minimum-all-ignore-profile"
7466 - else:
7467 - suffix = ""
7468 - matchmode = "minimum-visible"
7469 -
7470 - if not self.have["dev_keywords"]:
7471 - self.have["dev_keywords"] = bool(
7472 - self.dev_keywords.intersection(ebuild.keywords)
7473 - )
7474 -
7475 - if prof.status == "dev":
7476 - suffix = suffix + "indev"
7477 - elif prof.status == "exp":
7478 - suffix = suffix + "inexp"
7479 -
7480 - for mytype in Package._dep_keys:
7481 -
7482 - mykey = "dependency.bad" + suffix
7483 - myvalue = ebuild.metadata[mytype]
7484 - if not myvalue:
7485 - continue
7486 -
7487 - success, atoms = portage.dep_check(
7488 - myvalue,
7489 - self.portdb,
7490 - dep_settings,
7491 - use="all",
7492 - mode=matchmode,
7493 - trees=self.repo_settings.trees,
7494 - )
7495 -
7496 - results.append(
7497 - types.SimpleNamespace(
7498 - atoms=atoms, success=success, mykey=mykey, mytype=mytype
7499 - )
7500 - )
7501 -
7502 - return results
7503 -
7504 - def _check_result(self, task, result):
7505 - prof = task.prof
7506 - keyword = task.keyword
7507 - ebuild = task.ebuild
7508 - unknown_pkgs = ebuild.unknown_pkgs
7509 -
7510 - success = result.success
7511 - atoms = result.atoms
7512 - mykey = result.mykey
7513 - mytype = result.mytype
7514 -
7515 - if success:
7516 - if atoms:
7517 -
7518 - # Don't bother with dependency.unknown for
7519 - # cases in which *DEPEND.bad is triggered.
7520 - for atom in atoms:
7521 - # dep_check returns all blockers and they
7522 - # aren't counted for *DEPEND.bad, so we
7523 - # ignore them here.
7524 - if not atom.blocker:
7525 - unknown_pkgs.discard((mytype, atom.unevaluated_atom))
7526 -
7527 - if not prof.sub_path:
7528 - # old-style virtuals currently aren't
7529 - # resolvable with empty profile, since
7530 - # 'virtuals' mappings are unavailable
7531 - # (it would be expensive to search
7532 - # for PROVIDE in all ebuilds)
7533 - atoms = [
7534 - atom
7535 - for atom in atoms
7536 - if not (
7537 - atom.cp.startswith("virtual/")
7538 - and not self.portdb.cp_list(atom.cp)
7539 - )
7540 - ]
7541 -
7542 - # we have some unsolvable deps
7543 - # remove ! deps, which always show up as unsatisfiable
7544 - all_atoms = [
7545 - str(atom.unevaluated_atom) for atom in atoms if not atom.blocker
7546 - ]
7547 -
7548 - # if we emptied out our list, continue:
7549 - if not all_atoms:
7550 - return
7551 -
7552 - # Filter out duplicates. We do this by hand (rather
7553 - # than use a set) so the order is stable and better
7554 - # matches the order that's in the ebuild itself.
7555 - atoms = []
7556 - for atom in all_atoms:
7557 - if atom not in atoms:
7558 - atoms.append(atom)
7559 -
7560 - if self.options.output_style in ["column"]:
7561 - self.qatracker.add_error(
7562 - mykey,
7563 - "%s: %s: %s(%s) %s"
7564 - % (ebuild.relative_path, mytype, keyword, prof, repr(atoms)),
7565 - )
7566 - else:
7567 - self.qatracker.add_error(
7568 - mykey,
7569 - "%s: %s: %s(%s)\n%s"
7570 - % (
7571 - ebuild.relative_path,
7572 - mytype,
7573 - keyword,
7574 - prof,
7575 - pformat(atoms, indent=6),
7576 - ),
7577 - )
7578 - else:
7579 - if self.options.output_style in ["column"]:
7580 - self.qatracker.add_error(
7581 - mykey,
7582 - "%s: %s: %s(%s) %s"
7583 - % (ebuild.relative_path, mytype, keyword, prof, repr(atoms)),
7584 - )
7585 - else:
7586 - self.qatracker.add_error(
7587 - mykey,
7588 - "%s: %s: %s(%s)\n%s"
7589 - % (
7590 - ebuild.relative_path,
7591 - mytype,
7592 - keyword,
7593 - prof,
7594 - pformat(atoms, indent=6),
7595 - ),
7596 - )
7597 -
7598 - @property
7599 - def runInEbuilds(self):
7600 - """Ebuild level scans"""
7601 - return (True, [self.check])
7602 -
7603 - @staticmethod
7604 - def _populate_implicit_iuse(config, repo_locations):
7605 - """
7606 - Populate implicit IUSE for the empty profile, see bug 660982.
7607 -
7608 - @param config: config instance for the empty profile
7609 - @type config: portage.config
7610 - @param repo_locations: locations of repositories containing relevant
7611 - implicit IUSE settings
7612 - @type repo_locations: list
7613 - """
7614 - dest = config.configdict["defaults"]
7615 - for location in repo_locations:
7616 - for parent_dir, dirs, files in os.walk(os.path.join(location, "profiles")):
7617 - src = getconfig(os.path.join(parent_dir, "make.defaults"))
7618 - if not src:
7619 - continue
7620 - for k, v in iter_iuse_vars(src):
7621 - v_before = dest.get(k)
7622 - if v_before is not None:
7623 - merged_values = set(v_before.split())
7624 - merged_values.update(v.split())
7625 - v = " ".join(sorted(merged_values))
7626 - dest[k] = v
7627 -
7628 - config.regenerate()
7629 - config._init_iuse()
7630
7631 diff --git a/repoman/lib/repoman/modules/scan/directories/__init__.py b/repoman/lib/repoman/modules/scan/directories/__init__.py
7632 deleted file mode 100644
7633 index 68596267d..000000000
7634 --- a/repoman/lib/repoman/modules/scan/directories/__init__.py
7635 +++ /dev/null
7636 @@ -1,53 +0,0 @@
7637 -# Copyright 2015-2021 Gentoo Authors
7638 -# Distributed under the terms of the GNU General Public License v2
7639 -
7640 -doc = """Directories plug-in module for repoman.
7641 -Performs an FilesChecks check on ebuilds."""
7642 -__doc__ = doc[:]
7643 -
7644 -
7645 -module_spec = {
7646 - "name": "directories",
7647 - "description": doc,
7648 - "provides": {
7649 - "directories-module": {
7650 - "name": "files",
7651 - "sourcefile": "files",
7652 - "class": "FileChecks",
7653 - "description": doc,
7654 - "functions": ["check"],
7655 - "func_kwargs": {},
7656 - "mod_kwargs": [
7657 - "portdb",
7658 - "qatracker",
7659 - "repo_settings",
7660 - "vcs_settings",
7661 - ],
7662 - "func_kwargs": {
7663 - "changed": (None, None),
7664 - "checkdir": (None, None),
7665 - "checkdirlist": (None, None),
7666 - "checkdir_relative": (None, None),
7667 - },
7668 - "module_runsIn": ["pkgs"],
7669 - },
7670 - "mtime-module": {
7671 - "name": "mtime",
7672 - "sourcefile": "mtime",
7673 - "class": "MtimeChecks",
7674 - "description": doc,
7675 - "functions": ["check"],
7676 - "func_kwargs": {},
7677 - "mod_kwargs": [
7678 - "vcs_settings",
7679 - ],
7680 - "func_kwargs": {
7681 - "changed": (None, None),
7682 - "ebuild": (None, None),
7683 - "pkg": (None, None),
7684 - },
7685 - "module_runsIn": ["ebuilds"],
7686 - },
7687 - },
7688 - "version": 1,
7689 -}
7690
7691 diff --git a/repoman/lib/repoman/modules/scan/directories/files.py b/repoman/lib/repoman/modules/scan/directories/files.py
7692 deleted file mode 100644
7693 index 246d88483..000000000
7694 --- a/repoman/lib/repoman/modules/scan/directories/files.py
7695 +++ /dev/null
7696 @@ -1,99 +0,0 @@
7697 -# -*- coding:utf-8 -*-
7698 -
7699 -"""repoman/checks/diretories/files.py
7700 -
7701 -"""
7702 -
7703 -import io
7704 -
7705 -from portage import _encodings, _unicode_encode
7706 -from portage import os
7707 -
7708 -from repoman.modules.vcs.vcs import vcs_new_changed
7709 -from repoman.modules.scan.scanbase import ScanBase
7710 -
7711 -
7712 -class FileChecks(ScanBase):
7713 - """Performs various file checks in the package's directory"""
7714 -
7715 - def __init__(self, **kwargs):
7716 - """
7717 - @param portdb: portdb instance
7718 - @param qatracker: QATracker instance
7719 - @param repo_settings: settings instance
7720 - @param vcs_settings: VCSSettings instance
7721 - """
7722 - super(FileChecks, self).__init__(**kwargs)
7723 - self.portdb = kwargs.get("portdb")
7724 - self.qatracker = kwargs.get("qatracker")
7725 - self.repo_settings = kwargs.get("repo_settings")
7726 - self.repoman_settings = self.repo_settings.repoman_settings
7727 - self.vcs_settings = kwargs.get("vcs_settings")
7728 -
7729 - def check(self, **kwargs):
7730 - """Checks the ebuild sources and files for errors
7731 -
7732 - @param checkdir: string, directory path
7733 - @param checkdir_relative: repolevel determined path
7734 - @param changed: dictionary instance
7735 - @returns: dictionary
7736 - """
7737 - checkdir = kwargs.get("checkdir")
7738 - checkdirlist = kwargs.get("checkdirlist").get()
7739 - checkdir_relative = kwargs.get("checkdir_relative")
7740 - changed = kwargs.get("changed").changed
7741 - new = kwargs.get("changed").new
7742 - for y_file in checkdirlist:
7743 - index = self.repo_settings.repo_config.find_invalid_path_char(y_file)
7744 - if index != -1:
7745 - y_relative = os.path.join(checkdir_relative, y_file)
7746 - invcs = self.vcs_settings.vcs is not None
7747 - inchangeset = vcs_new_changed(y_relative, changed, new)
7748 - if invcs and not inchangeset:
7749 - # If the file isn't in the VCS new or changed set, then
7750 - # assume that it's an irrelevant temporary file (Manifest
7751 - # entries are not generated for file names containing
7752 - # prohibited characters). See bug #406877.
7753 - index = -1
7754 - if index != -1:
7755 - self.qatracker.add_error(
7756 - "file.name", "%s/%s: char '%s'" % (checkdir, y_file, y_file[index])
7757 - )
7758 -
7759 - if not (
7760 - y_file in ("ChangeLog", "metadata.xml") or y_file.endswith(".ebuild")
7761 - ):
7762 - continue
7763 - f = None
7764 - try:
7765 - line = 1
7766 - f = io.open(
7767 - _unicode_encode(
7768 - os.path.join(checkdir, y_file),
7769 - encoding=_encodings["fs"],
7770 - errors="strict",
7771 - ),
7772 - mode="r",
7773 - encoding=_encodings["repo.content"],
7774 - )
7775 - for l in f:
7776 - line += 1
7777 - except UnicodeDecodeError as ue:
7778 - s = ue.object[: ue.start]
7779 - l2 = s.count("\n")
7780 - line += l2
7781 - if l2 != 0:
7782 - s = s[s.rfind("\n") + 1 :]
7783 - self.qatracker.add_error(
7784 - "file.UTF8",
7785 - "%s/%s: line %i, just after: '%s'" % (checkdir, y_file, line, s),
7786 - )
7787 - finally:
7788 - if f is not None:
7789 - f.close()
7790 - return False
7791 -
7792 - @property
7793 - def runInPkgs(self):
7794 - """Package level scans"""
7795 - return (True, [self.check])
7796
7797 diff --git a/repoman/lib/repoman/modules/scan/directories/mtime.py b/repoman/lib/repoman/modules/scan/directories/mtime.py
7798 deleted file mode 100644
7799 index 34e210257..000000000
7800 --- a/repoman/lib/repoman/modules/scan/directories/mtime.py
7801 +++ /dev/null
7802 @@ -1,30 +0,0 @@
7803 -from repoman.modules.scan.scanbase import ScanBase
7804 -
7805 -
7806 -class MtimeChecks(ScanBase):
7807 - def __init__(self, **kwargs):
7808 - self.vcs_settings = kwargs.get("vcs_settings")
7809 -
7810 - def check(self, **kwargs):
7811 - """Perform a changelog and untracked checks on the ebuild
7812 -
7813 - @param pkg: Package in which we check (object).
7814 - @param ebuild: Ebuild which we check (object).
7815 - @param changed: dictionary instance
7816 - @returns: dictionary
7817 - """
7818 - ebuild = kwargs.get("ebuild").get()
7819 - changed = kwargs.get("changed")
7820 - pkg = kwargs.get("pkg").get()
7821 - if not self.vcs_settings.vcs_preserves_mtime:
7822 - if (
7823 - ebuild.ebuild_path not in changed.new_ebuilds
7824 - and ebuild.ebuild_path not in changed.ebuilds
7825 - ):
7826 - pkg.mtime = None
7827 - return False
7828 -
7829 - @property
7830 - def runInEbuilds(self):
7831 - """Ebuild level scans"""
7832 - return (True, [self.check])
7833
7834 diff --git a/repoman/lib/repoman/modules/scan/eapi/__init__.py b/repoman/lib/repoman/modules/scan/eapi/__init__.py
7835 deleted file mode 100644
7836 index a86d74b3c..000000000
7837 --- a/repoman/lib/repoman/modules/scan/eapi/__init__.py
7838 +++ /dev/null
7839 @@ -1,28 +0,0 @@
7840 -# Copyright 2015-2021 Gentoo Authors
7841 -# Distributed under the terms of the GNU General Public License v2
7842 -
7843 -doc = """Eapi plug-in module for repoman.
7844 -Performs an IsEbuild check on ebuilds."""
7845 -__doc__ = doc[:]
7846 -
7847 -
7848 -module_spec = {
7849 - "name": "eapi",
7850 - "description": doc,
7851 - "provides": {
7852 - "live-module": {
7853 - "name": "eapi",
7854 - "sourcefile": "eapi",
7855 - "class": "EAPIChecks",
7856 - "description": doc,
7857 - "functions": ["check"],
7858 - "func_kwargs": {},
7859 - "mod_kwargs": ["qatracker", "repo_settings"],
7860 - "func_kwargs": {
7861 - "ebuild": (None, None),
7862 - },
7863 - "module_runsIn": ["ebuilds"],
7864 - },
7865 - },
7866 - "version": 1,
7867 -}
7868
7869 diff --git a/repoman/lib/repoman/modules/scan/eapi/eapi.py b/repoman/lib/repoman/modules/scan/eapi/eapi.py
7870 deleted file mode 100644
7871 index df7c220e6..000000000
7872 --- a/repoman/lib/repoman/modules/scan/eapi/eapi.py
7873 +++ /dev/null
7874 @@ -1,50 +0,0 @@
7875 -"""eapi.py
7876 -Perform checks on the EAPI variable.
7877 -"""
7878 -
7879 -from repoman.modules.scan.scanbase import ScanBase
7880 -
7881 -
7882 -class EAPIChecks(ScanBase):
7883 - """Perform checks on the EAPI variable."""
7884 -
7885 - def __init__(self, **kwargs):
7886 - """
7887 - @param qatracker: QATracker instance
7888 - @param repo_settings: Repository settings
7889 - """
7890 - self.qatracker = kwargs.get("qatracker")
7891 - self.repo_settings = kwargs.get("repo_settings")
7892 -
7893 - def check(self, **kwargs):
7894 - """
7895 - @param pkg: Package in which we check (object).
7896 - @param ebuild: Ebuild which we check (object).
7897 - @returns: dictionary
7898 - """
7899 - ebuild = kwargs.get("ebuild").get()
7900 -
7901 - if not self._checkBanned(ebuild):
7902 - self._checkDeprecated(ebuild)
7903 - return False
7904 -
7905 - def _checkBanned(self, ebuild):
7906 - if self.repo_settings.repo_config.eapi_is_banned(ebuild.eapi):
7907 - self.qatracker.add_error(
7908 - "repo.eapi-banned", "%s: %s" % (ebuild.relative_path, ebuild.eapi)
7909 - )
7910 - return True
7911 - return False
7912 -
7913 - def _checkDeprecated(self, ebuild):
7914 - if self.repo_settings.repo_config.eapi_is_deprecated(ebuild.eapi):
7915 - self.qatracker.add_error(
7916 - "repo.eapi-deprecated", "%s: %s" % (ebuild.relative_path, ebuild.eapi)
7917 - )
7918 - return True
7919 - return False
7920 -
7921 - @property
7922 - def runInEbuilds(self):
7923 - """Ebuild level scans"""
7924 - return (True, [self.check])
7925
7926 diff --git a/repoman/lib/repoman/modules/scan/ebuild/__init__.py b/repoman/lib/repoman/modules/scan/ebuild/__init__.py
7927 deleted file mode 100644
7928 index 029b5628d..000000000
7929 --- a/repoman/lib/repoman/modules/scan/ebuild/__init__.py
7930 +++ /dev/null
7931 @@ -1,66 +0,0 @@
7932 -# Copyright 2015-2021 Gentoo Authors
7933 -# Distributed under the terms of the GNU General Public License v2
7934 -
7935 -doc = """Ebuild plug-in module for repoman.
7936 -Performs an IsEbuild check on ebuilds."""
7937 -__doc__ = doc[:]
7938 -
7939 -
7940 -module_spec = {
7941 - "name": "ebuild",
7942 - "description": doc,
7943 - "provides": {
7944 - "ebuild-module": {
7945 - "name": "ebuild",
7946 - "sourcefile": "ebuild",
7947 - "class": "Ebuild",
7948 - "description": doc,
7949 - "functions": ["check"],
7950 - "func_desc": {},
7951 - "mod_kwargs": [
7952 - "qatracker",
7953 - "repo_settings",
7954 - "vcs_settings",
7955 - "checks",
7956 - "portdb",
7957 - ],
7958 - "func_kwargs": {
7959 - "can_force": (None, None),
7960 - "catdir": (None, None),
7961 - "changed": (None, None),
7962 - "changelog_modified": (None, None),
7963 - "checkdir": (None, None),
7964 - "checkdirlist": (None, None),
7965 - "ebuild": ("Future", "UNSET"),
7966 - "pkg": ("Future", "UNSET"),
7967 - "pkgdir": (None, None),
7968 - "pkgs": ("Future", "dict"),
7969 - "repolevel": (None, None),
7970 - "validity_future": (None, None),
7971 - "xpkg": (None, None),
7972 - "y_ebuild": (None, None),
7973 - },
7974 - "module_runsIn": ["pkgs", "ebuilds"],
7975 - },
7976 - "multicheck-module": {
7977 - "name": "multicheck",
7978 - "sourcefile": "multicheck",
7979 - "class": "MultiCheck",
7980 - "description": doc,
7981 - "functions": ["check"],
7982 - "func_kwargs": {},
7983 - "mod_kwargs": [
7984 - "qatracker",
7985 - "options",
7986 - "repo_settings",
7987 - "linechecks",
7988 - ],
7989 - "func_kwargs": {
7990 - "ebuild": (None, None),
7991 - "pkg": (None, None),
7992 - },
7993 - "module_runsIn": ["ebuilds"],
7994 - },
7995 - },
7996 - "version": 1,
7997 -}
7998
7999 diff --git a/repoman/lib/repoman/modules/scan/ebuild/ebuild.py b/repoman/lib/repoman/modules/scan/ebuild/ebuild.py
8000 deleted file mode 100644
8001 index ae3275780..000000000
8002 --- a/repoman/lib/repoman/modules/scan/ebuild/ebuild.py
8003 +++ /dev/null
8004 @@ -1,263 +0,0 @@
8005 -# -*- coding:utf-8 -*-
8006 -
8007 -import re
8008 -import stat
8009 -
8010 -from _emerge.Package import Package
8011 -from _emerge.RootConfig import RootConfig
8012 -
8013 -from repoman.modules.scan.scanbase import ScanBase
8014 -
8015 -# import our initialized portage instance
8016 -from repoman._portage import portage
8017 -
8018 -from portage import os
8019 -from portage.exception import InvalidPackageName
8020 -
8021 -pv_toolong_re = re.compile(r"[0-9]{19,}")
8022 -
8023 -
8024 -class Ebuild(ScanBase):
8025 - """Class to run primary checks on ebuilds"""
8026 -
8027 - def __init__(self, **kwargs):
8028 - """Class init
8029 -
8030 - @param qatracker: QATracker instance
8031 - @param portdb: portdb instance
8032 - @param repo_settings: repository settings instance
8033 - @param vcs_settings: VCSSettings instance
8034 - @param checks: checks dictionary
8035 - """
8036 - super(Ebuild, self).__init__(**kwargs)
8037 - self.qatracker = kwargs.get("qatracker")
8038 - self.portdb = kwargs.get("portdb")
8039 - self.repo_settings = kwargs.get("repo_settings")
8040 - self.vcs_settings = kwargs.get("vcs_settings")
8041 - self.checks = kwargs.get("checks")
8042 - self.root_config = RootConfig(
8043 - self.repo_settings.repoman_settings,
8044 - self.repo_settings.trees[self.repo_settings.root],
8045 - None,
8046 - )
8047 - self.changed = None
8048 - self.xpkg = None
8049 - self.y_ebuild = None
8050 - self.pkg = None
8051 - self.metadata = None
8052 - self.eapi = None
8053 - self.inherited = None
8054 - self.live_ebuild = None
8055 - self.keywords = None
8056 - self.pkgs = {}
8057 -
8058 - def _set_paths(self, **kwargs):
8059 - repolevel = kwargs.get("repolevel")
8060 - self.relative_path = os.path.join(self.xpkg, self.y_ebuild + ".ebuild")
8061 - self.full_path = os.path.join(self.repo_settings.repodir, self.relative_path)
8062 - self.ebuild_path = self.y_ebuild + ".ebuild"
8063 - if repolevel < 3:
8064 - self.ebuild_path = os.path.join(kwargs.get("pkgdir"), self.ebuild_path)
8065 - if repolevel < 2:
8066 - self.ebuild_path = os.path.join(kwargs.get("catdir"), self.ebuild_path)
8067 - self.ebuild_path = os.path.join(".", self.ebuild_path)
8068 -
8069 - @property
8070 - def untracked(self):
8071 - """Determines and returns if the ebuild is not tracked by the vcs"""
8072 - do_check = self.vcs_settings.vcs in ("cvs", "svn", "bzr")
8073 - really_notadded = (
8074 - self.checks["ebuild_notadded"]
8075 - and self.y_ebuild not in self.vcs_settings.eadded
8076 - )
8077 - if do_check and really_notadded:
8078 - # ebuild not added to vcs
8079 - return True
8080 - return False
8081 -
8082 - def check(self, **kwargs):
8083 - """Perform a changelog and untracked checks on the ebuild
8084 -
8085 - @param xpkg: Package in which we check (object).
8086 - @param y_ebuild: Ebuild which we check (string).
8087 - @param changed: dictionary instance
8088 - @param repolevel: The depth within the repository
8089 - @param catdir: The category directiory
8090 - @param pkgdir: the package directory
8091 - @returns: dictionary, including {ebuild object}
8092 - """
8093 - self.xpkg = kwargs.get("xpkg")
8094 - self.y_ebuild = kwargs.get("y_ebuild")
8095 - self.changed = kwargs.get("changed")
8096 - changelog_modified = kwargs.get("changelog_modified")
8097 - self._set_paths(**kwargs)
8098 -
8099 - if (
8100 - self.checks["changelog"]
8101 - and not changelog_modified
8102 - and self.ebuild_path in self.changed.new_ebuilds
8103 - ):
8104 - self.qatracker.add_error("changelog.ebuildadded", self.relative_path)
8105 -
8106 - if self.untracked:
8107 - # ebuild not added to vcs
8108 - self.qatracker.add_error(
8109 - "ebuild.notadded", self.xpkg + "/" + self.y_ebuild + ".ebuild"
8110 - )
8111 - # update the dynamic data
8112 - dyn_ebuild = kwargs.get("ebuild")
8113 - dyn_ebuild.set(self)
8114 - return False
8115 -
8116 - def set_pkg_data(self, **kwargs):
8117 - """Sets some classwide data needed for some of the checks
8118 -
8119 - @returns: dictionary
8120 - """
8121 - self.pkg = self.pkgs[self.y_ebuild]
8122 - self.metadata = self.pkg._metadata
8123 - self.eapi = self.metadata["EAPI"]
8124 - self.inherited = self.pkg.inherited
8125 - self.live_ebuild = "live" in self.metadata["PROPERTIES"].split()
8126 - self.keywords = self.metadata["KEYWORDS"].split()
8127 - self.archs = set(
8128 - kw.lstrip("~") for kw in self.keywords if not kw.startswith("-")
8129 - )
8130 - return False
8131 -
8132 - def bad_split_check(self, **kwargs):
8133 - """Checks for bad category/package splits.
8134 -
8135 - @param pkgdir: string: path
8136 - @returns: dictionary
8137 - """
8138 - pkgdir = kwargs.get("pkgdir")
8139 - myesplit = portage.pkgsplit(self.y_ebuild)
8140 - is_bad_split = myesplit is None or myesplit[0] != self.xpkg.split("/")[-1]
8141 - if is_bad_split:
8142 - is_pv_toolong = pv_toolong_re.search(myesplit[1])
8143 - is_pv_toolong2 = pv_toolong_re.search(myesplit[2])
8144 - if is_pv_toolong or is_pv_toolong2:
8145 - self.qatracker.add_error(
8146 - "ebuild.invalidname", self.xpkg + "/" + self.y_ebuild + ".ebuild"
8147 - )
8148 - return True
8149 - elif myesplit[0] != pkgdir:
8150 - print(pkgdir, myesplit[0])
8151 - self.qatracker.add_error(
8152 - "ebuild.namenomatch", self.xpkg + "/" + self.y_ebuild + ".ebuild"
8153 - )
8154 - return True
8155 - return False
8156 -
8157 - def pkg_invalid(self, **kwargs):
8158 - """Sets some pkg info and checks for invalid packages
8159 -
8160 - @param validity_future: Future instance
8161 - @returns: dictionary, including {pkg object}
8162 - """
8163 - fuse = kwargs.get("validity_future")
8164 - dyn_pkg = kwargs.get("pkg")
8165 - if self.pkg.invalid:
8166 - for k, msgs in self.pkg.invalid.items():
8167 - for msg in msgs:
8168 - self.qatracker.add_error(k, "%s: %s" % (self.relative_path, msg))
8169 - # update the dynamic data
8170 - fuse.set(False, ignore_InvalidState=True)
8171 - dyn_pkg.set(self.pkg)
8172 - return True
8173 - # update the dynamic data
8174 - dyn_pkg.set(self.pkg)
8175 - return False
8176 -
8177 - def check_isebuild(self, **kwargs):
8178 - """Test the file for qualifications that is is an ebuild
8179 -
8180 - @param checkdirlist: list of files in the current package directory
8181 - @param checkdir: current package directory path
8182 - @param xpkg: current package directory being checked
8183 - @param validity_future: Future instance
8184 - @returns: dictionary, including {pkgs, can_force}
8185 - """
8186 - checkdirlist = kwargs.get("checkdirlist").get()
8187 - checkdir = kwargs.get("checkdir")
8188 - xpkg = kwargs.get("xpkg")
8189 - fuse = kwargs.get("validity_future")
8190 - can_force = kwargs.get("can_force")
8191 - self.continue_ = False
8192 - ebuildlist = []
8193 - pkgs = {}
8194 - for y in checkdirlist:
8195 - file_is_ebuild = y.endswith(".ebuild")
8196 - file_should_be_non_executable = (
8197 - y in self.repo_settings.qadata.no_exec or file_is_ebuild
8198 - )
8199 -
8200 - if file_should_be_non_executable:
8201 - file_is_executable = (
8202 - stat.S_IMODE(os.stat(os.path.join(checkdir, y)).st_mode) & 0o111
8203 - )
8204 -
8205 - if file_is_executable:
8206 - self.qatracker.add_error(
8207 - "file.executable", os.path.join(checkdir, y)
8208 - )
8209 - if file_is_ebuild:
8210 - pf = y[:-7]
8211 - ebuildlist.append(pf)
8212 - catdir = xpkg.split("/")[0]
8213 - cpv = "%s/%s" % (catdir, pf)
8214 - allvars = self.repo_settings.qadata.allvars
8215 - try:
8216 - myaux = dict(zip(allvars, self.portdb.aux_get(cpv, allvars)))
8217 - except KeyError:
8218 - fuse.set(False, ignore_InvalidState=True)
8219 - self.qatracker.add_error("ebuild.syntax", os.path.join(xpkg, y))
8220 - continue
8221 - except IOError:
8222 - fuse.set(False, ignore_InvalidState=True)
8223 - self.qatracker.add_error("ebuild.output", os.path.join(xpkg, y))
8224 - continue
8225 - except InvalidPackageName:
8226 - fuse.set(False, ignore_InvalidState=True)
8227 - self.qatracker.add_error(
8228 - "ebuild.invalidname", os.path.join(xpkg, y)
8229 - )
8230 - continue
8231 - if not portage.eapi_is_supported(myaux["EAPI"]):
8232 - fuse.set(False, ignore_InvalidState=True)
8233 - self.qatracker.add_error("EAPI.unsupported", os.path.join(xpkg, y))
8234 - continue
8235 - pkgs[pf] = Package(
8236 - cpv=cpv,
8237 - metadata=myaux,
8238 - root_config=self.root_config,
8239 - type_name="ebuild",
8240 - )
8241 -
8242 - if len(pkgs) != len(ebuildlist):
8243 - # If we can't access all the metadata then it's totally unsafe to
8244 - # commit since there's no way to generate a correct Manifest.
8245 - # Do not try to do any more QA checks on this package since missing
8246 - # metadata leads to false positives for several checks, and false
8247 - # positives confuse users.
8248 - self.continue_ = True
8249 - can_force.set(False, ignore_InvalidState=True)
8250 - self.pkgs = pkgs
8251 - # set our updated data
8252 - dyn_pkgs = kwargs.get("pkgs")
8253 - dyn_pkgs.set(pkgs)
8254 - return self.continue_
8255 -
8256 - @property
8257 - def runInPkgs(self):
8258 - """Package level scans"""
8259 - return (True, [self.check_isebuild])
8260 -
8261 - @property
8262 - def runInEbuilds(self):
8263 - """Ebuild level scans"""
8264 - return (
8265 - True,
8266 - [self.check, self.set_pkg_data, self.bad_split_check, self.pkg_invalid],
8267 - )
8268
8269 diff --git a/repoman/lib/repoman/modules/scan/ebuild/multicheck.py b/repoman/lib/repoman/modules/scan/ebuild/multicheck.py
8270 deleted file mode 100644
8271 index 1db0dfc92..000000000
8272 --- a/repoman/lib/repoman/modules/scan/ebuild/multicheck.py
8273 +++ /dev/null
8274 @@ -1,62 +0,0 @@
8275 -"""multicheck.py
8276 -Perform multiple different checks on an ebuild
8277 -"""
8278 -
8279 -import io
8280 -
8281 -from portage import _encodings, _unicode_encode
8282 -
8283 -from repoman.modules.scan.scanbase import ScanBase
8284 -from repoman.modules.linechecks.controller import LineCheckController
8285 -
8286 -
8287 -class MultiCheck(ScanBase):
8288 - """Class to run multiple different checks on an ebuild"""
8289 -
8290 - def __init__(self, **kwargs):
8291 - """Class init
8292 -
8293 - @param qatracker: QATracker instance
8294 - @param options: the run time cli options
8295 - """
8296 - self.qatracker = kwargs.get("qatracker")
8297 - self.options = kwargs.get("options")
8298 - self.controller = LineCheckController(
8299 - kwargs.get("repo_settings"), kwargs.get("linechecks")
8300 - )
8301 - self.controller.checks_init(self.options.experimental_inherit == "y")
8302 -
8303 - def check(self, **kwargs):
8304 - """Check the ebuild for utf-8 encoding
8305 -
8306 - @param pkg: Package in which we check (object).
8307 - @param ebuild: Ebuild which we check (object).
8308 - @returns: dictionary
8309 - """
8310 - ebuild = kwargs.get("ebuild").get()
8311 - pkg = kwargs.get("pkg").get()
8312 - try:
8313 - # All ebuilds should have utf_8 encoding.
8314 - f = io.open(
8315 - _unicode_encode(
8316 - ebuild.full_path, encoding=_encodings["fs"], errors="strict"
8317 - ),
8318 - mode="r",
8319 - encoding=_encodings["repo.content"],
8320 - )
8321 - try:
8322 - for check_name, e in self.controller.run_checks(f, pkg):
8323 - self.qatracker.add_error(
8324 - check_name, ebuild.relative_path + ": %s" % e
8325 - )
8326 - finally:
8327 - f.close()
8328 - except UnicodeDecodeError:
8329 - # A file.UTF8 failure will have already been recorded.
8330 - pass
8331 - return False
8332 -
8333 - @property
8334 - def runInEbuilds(self):
8335 - """Ebuild level scans"""
8336 - return (True, [self.check])
8337
8338 diff --git a/repoman/lib/repoman/modules/scan/eclasses/__init__.py b/repoman/lib/repoman/modules/scan/eclasses/__init__.py
8339 deleted file mode 100644
8340 index 8a14000e8..000000000
8341 --- a/repoman/lib/repoman/modules/scan/eclasses/__init__.py
8342 +++ /dev/null
8343 @@ -1,49 +0,0 @@
8344 -# Copyright 2015-2021 Gentoo Authors
8345 -# Distributed under the terms of the GNU General Public License v2
8346 -
8347 -doc = """Eclasses plug-in module for repoman.
8348 -Performs an live and ruby eclass checks on ebuilds."""
8349 -__doc__ = doc[:]
8350 -
8351 -
8352 -module_spec = {
8353 - "name": "eclasses",
8354 - "description": doc,
8355 - "provides": {
8356 - "live-module": {
8357 - "name": "live",
8358 - "sourcefile": "live",
8359 - "class": "LiveEclassChecks",
8360 - "description": doc,
8361 - "functions": ["check"],
8362 - "func_kwargs": {},
8363 - "mod_kwargs": [
8364 - "qatracker",
8365 - "repo_metadata",
8366 - "repo_settings",
8367 - ],
8368 - "func_kwargs": {
8369 - "ebuild": (None, None),
8370 - "pkg": (None, None),
8371 - "xpkg": (None, None),
8372 - "y_ebuild": (None, None),
8373 - },
8374 - "module_runsIn": ["ebuilds"],
8375 - },
8376 - "ruby-module": {
8377 - "name": "ruby",
8378 - "sourcefile": "ruby",
8379 - "class": "RubyEclassChecks",
8380 - "description": doc,
8381 - "functions": ["check"],
8382 - "func_kwargs": {},
8383 - "mod_kwargs": ["qatracker", "repo_settings"],
8384 - "func_kwargs": {
8385 - "ebuild": (None, None),
8386 - "pkg": (None, None),
8387 - },
8388 - "module_runsIn": ["ebuilds"],
8389 - },
8390 - },
8391 - "version": 1,
8392 -}
8393
8394 diff --git a/repoman/lib/repoman/modules/scan/eclasses/live.py b/repoman/lib/repoman/modules/scan/eclasses/live.py
8395 deleted file mode 100644
8396 index 82ee168ed..000000000
8397 --- a/repoman/lib/repoman/modules/scan/eclasses/live.py
8398 +++ /dev/null
8399 @@ -1,77 +0,0 @@
8400 -"""live.py
8401 -Performs Live eclass checks
8402 -"""
8403 -
8404 -from repoman._portage import portage
8405 -from repoman.modules.scan.scanbase import ScanBase
8406 -
8407 -
8408 -class LiveEclassChecks(ScanBase):
8409 - """Performs checks for the usage of Live eclasses in ebuilds"""
8410 -
8411 - def __init__(self, **kwargs):
8412 - """
8413 - @param qatracker: QATracker instance
8414 - """
8415 - self.qatracker = kwargs.get("qatracker")
8416 - self.pmaskdict = kwargs.get("repo_metadata")["pmaskdict"]
8417 - self.repo_settings = kwargs.get("repo_settings")
8418 -
8419 - def check(self, **kwargs):
8420 - """Ebuilds that inherit a "Live" eclass (darcs, subversion, git, cvs,
8421 - etc..) should not be allowed to be marked stable
8422 -
8423 - @param pkg: Package in which we check (object).
8424 - @param xpkg: Package in which we check (string).
8425 - @param ebuild: Ebuild which we check (object).
8426 - @param y_ebuild: Ebuild which we check (string).
8427 - @returns: boolean
8428 - """
8429 - pkg = kwargs.get("pkg").result()
8430 - package = kwargs.get("xpkg")
8431 - ebuild = kwargs.get("ebuild").get()
8432 - y_ebuild = kwargs.get("y_ebuild")
8433 -
8434 - if ebuild.live_ebuild and self.repo_settings.repo_config.name == "gentoo":
8435 - return self.check_live(pkg, package, ebuild, y_ebuild)
8436 - return False
8437 -
8438 - def check_live(self, pkg, package, ebuild, y_ebuild):
8439 - """Perform the live vcs check
8440 -
8441 - @param pkg: Package in which we check (object).
8442 - @param xpkg: Package in which we check (string).
8443 - @param ebuild: Ebuild which we check (object).
8444 - @param y_ebuild: Ebuild which we check (string).
8445 - @returns: boolean
8446 - """
8447 - keywords = ebuild.keywords
8448 - is_stable = lambda kw: not kw.startswith("~") and not kw.startswith("-")
8449 - bad_stable_keywords = list(filter(is_stable, keywords))
8450 -
8451 - if bad_stable_keywords:
8452 - self.qatracker.add_error(
8453 - "LIVEVCS.stable",
8454 - "%s/%s.ebuild with stable keywords: %s"
8455 - % (package, y_ebuild, bad_stable_keywords),
8456 - )
8457 -
8458 - good_keywords_exist = len(bad_stable_keywords) < len(keywords)
8459 - if good_keywords_exist and not self._has_global_mask(pkg, self.pmaskdict):
8460 - self.qatracker.add_error("LIVEVCS.unmasked", ebuild.relative_path)
8461 - return False
8462 -
8463 - @staticmethod
8464 - def _has_global_mask(pkg, global_pmaskdict):
8465 - mask_atoms = global_pmaskdict.get(pkg.cp)
8466 - if mask_atoms:
8467 - pkg_list = [pkg]
8468 - for x in mask_atoms:
8469 - if portage.dep.match_from_list(x, pkg_list):
8470 - return x
8471 - return None
8472 -
8473 - @property
8474 - def runInEbuilds(self):
8475 - """Ebuild level scans"""
8476 - return (True, [self.check])
8477
8478 diff --git a/repoman/lib/repoman/modules/scan/eclasses/ruby.py b/repoman/lib/repoman/modules/scan/eclasses/ruby.py
8479 deleted file mode 100644
8480 index 16043ee0c..000000000
8481 --- a/repoman/lib/repoman/modules/scan/eclasses/ruby.py
8482 +++ /dev/null
8483 @@ -1,49 +0,0 @@
8484 -"""ruby.py
8485 -Performs Ruby eclass checks
8486 -"""
8487 -
8488 -from repoman.modules.scan.scanbase import ScanBase
8489 -
8490 -
8491 -class RubyEclassChecks(ScanBase):
8492 - """Performs checks for the usage of Ruby eclasses in ebuilds"""
8493 -
8494 - def __init__(self, **kwargs):
8495 - """
8496 - @param qatracker: QATracker instance
8497 - """
8498 - super(RubyEclassChecks, self).__init__(**kwargs)
8499 - self.qatracker = kwargs.get("qatracker")
8500 - self.repo_settings = kwargs.get("repo_settings")
8501 - self.old_ruby_eclasses = ["ruby-ng", "ruby-fakegem", "ruby"]
8502 -
8503 - def check(self, **kwargs):
8504 - """Check ebuilds that inherit the ruby eclasses
8505 -
8506 - @param pkg: Package in which we check (object).
8507 - @param ebuild: Ebuild which we check (object).
8508 - @returns: dictionary
8509 - """
8510 - pkg = kwargs.get("pkg").get()
8511 - ebuild = kwargs.get("ebuild").get()
8512 - is_inherited = lambda eclass: eclass in pkg.inherited
8513 - is_old_ruby_eclass_inherited = filter(is_inherited, self.old_ruby_eclasses)
8514 -
8515 - if is_old_ruby_eclass_inherited:
8516 - ruby_intersection = pkg.iuse.all.intersection(
8517 - self.repo_settings.qadata.ruby_deprecated
8518 - )
8519 -
8520 - if ruby_intersection:
8521 - for myruby in ruby_intersection:
8522 - self.qatracker.add_error(
8523 - "IUSE.rubydeprecated",
8524 - (ebuild.relative_path + ": Deprecated ruby target: %s")
8525 - % myruby,
8526 - )
8527 - return False
8528 -
8529 - @property
8530 - def runInEbuilds(self):
8531 - """Ebuild level scans"""
8532 - return (True, [self.check])
8533
8534 diff --git a/repoman/lib/repoman/modules/scan/fetch/__init__.py b/repoman/lib/repoman/modules/scan/fetch/__init__.py
8535 deleted file mode 100644
8536 index 9bd9d468d..000000000
8537 --- a/repoman/lib/repoman/modules/scan/fetch/__init__.py
8538 +++ /dev/null
8539 @@ -1,37 +0,0 @@
8540 -# Copyright 2015-2021 Gentoo Authors
8541 -# Distributed under the terms of the GNU General Public License v2
8542 -
8543 -doc = """fetches plug-in module for repoman.
8544 -Performs fetch related checks on ebuilds."""
8545 -__doc__ = doc[:]
8546 -
8547 -
8548 -module_spec = {
8549 - "name": "fetches",
8550 - "description": doc,
8551 - "provides": {
8552 - "fetches-module": {
8553 - "name": "fetches",
8554 - "sourcefile": "fetches",
8555 - "class": "FetchChecks",
8556 - "description": doc,
8557 - "functions": ["check"],
8558 - "func_desc": {},
8559 - "mod_kwargs": [
8560 - "portdb",
8561 - "qatracker",
8562 - "repo_settings",
8563 - "vcs_settings",
8564 - ],
8565 - "func_kwargs": {
8566 - "changed": (None, None),
8567 - "checkdir": (None, None),
8568 - "checkdir_relative": (None, None),
8569 - "ebuild": (None, None),
8570 - "xpkg": (None, None),
8571 - },
8572 - "module_runsIn": ["pkgs", "ebuilds"],
8573 - },
8574 - },
8575 - "version": 1,
8576 -}
8577
8578 diff --git a/repoman/lib/repoman/modules/scan/fetch/fetches.py b/repoman/lib/repoman/modules/scan/fetch/fetches.py
8579 deleted file mode 100644
8580 index 56a36a13f..000000000
8581 --- a/repoman/lib/repoman/modules/scan/fetch/fetches.py
8582 +++ /dev/null
8583 @@ -1,205 +0,0 @@
8584 -# -*- coding:utf-8 -*-
8585 -
8586 -"""fetches.py
8587 -Performs the src_uri fetchlist and files checks
8588 -"""
8589 -
8590 -from stat import S_ISDIR
8591 -
8592 -# import our initialized portage instance
8593 -from repoman._portage import portage
8594 -from repoman.modules.vcs.vcs import vcs_new_changed
8595 -from repoman.modules.scan.scanbase import ScanBase
8596 -
8597 -from portage import os
8598 -
8599 -
8600 -class FetchChecks(ScanBase):
8601 - """Performs checks on the files needed for the ebuild"""
8602 -
8603 - def __init__(self, **kwargs):
8604 - """
8605 - @param portdb: portdb instance
8606 - @param qatracker: QATracker instance
8607 - @param repo_settings: repository settings instance
8608 - @param vcs_settings: VCSSettings instance
8609 - """
8610 - super(FetchChecks, self).__init__(**kwargs)
8611 - self.portdb = kwargs.get("portdb")
8612 - self.qatracker = kwargs.get("qatracker")
8613 - self.repo_settings = kwargs.get("repo_settings")
8614 - self.repoman_settings = self.repo_settings.repoman_settings
8615 - self.vcs_settings = kwargs.get("vcs_settings")
8616 - self._src_uri_error = False
8617 -
8618 - # TODO: Build a regex instead here, for the SRC_URI.mirror check.
8619 - self.thirdpartymirrors = {}
8620 - profile_thirdpartymirrors = (
8621 - self.repo_settings.repoman_settings.thirdpartymirrors().items()
8622 - )
8623 - for mirror_alias, mirrors in profile_thirdpartymirrors:
8624 - # Skip thirdpartymirrors that do not list more than one mirror
8625 - # anymore. There is no point in using mirror:// there and this
8626 - # means that the thirdpartymirrors entry will most likely
8627 - # be removed anyway.
8628 - if len(mirrors) <= 1:
8629 - continue
8630 - for mirror in mirrors:
8631 - if not mirror.endswith("/"):
8632 - mirror += "/"
8633 - self.thirdpartymirrors[mirror] = mirror_alias
8634 -
8635 - def check(self, **kwargs):
8636 - """Checks the ebuild sources and files for errors
8637 -
8638 - @param xpkg: the pacakge being checked
8639 - @param checkdir: string, directory path
8640 - @param checkdir_relative: repolevel determined path
8641 - @returns: boolean
8642 - """
8643 - xpkg = kwargs.get("xpkg")
8644 - checkdir = kwargs.get("checkdir")
8645 - checkdir_relative = kwargs.get("checkdir_relative")
8646 - changed = kwargs.get("changed").changed
8647 - new = kwargs.get("changed").new
8648 - _digests = self.digests(checkdir)
8649 - fetchlist_dict = portage.FetchlistDict(
8650 - checkdir, self.repoman_settings, self.portdb
8651 - )
8652 - myfiles_all = []
8653 - self._src_uri_error = False
8654 - for mykey in fetchlist_dict:
8655 - try:
8656 - myfiles_all.extend(fetchlist_dict[mykey])
8657 - except portage.exception.InvalidDependString as e:
8658 - self._src_uri_error = True
8659 - try:
8660 - self.portdb.aux_get(mykey, ["SRC_URI"])
8661 - except KeyError:
8662 - # This will be reported as an "ebuild.syntax" error.
8663 - pass
8664 - else:
8665 - self.qatracker.add_error(
8666 - "SRC_URI.syntax", "%s.ebuild SRC_URI: %s" % (mykey, e)
8667 - )
8668 - del fetchlist_dict
8669 - if not self._src_uri_error:
8670 - # This test can produce false positives if SRC_URI could not
8671 - # be parsed for one or more ebuilds. There's no point in
8672 - # producing a false error here since the root cause will
8673 - # produce a valid error elsewhere, such as "SRC_URI.syntax"
8674 - # or "ebuild.sytax".
8675 - myfiles_all = set(myfiles_all)
8676 - for entry in _digests:
8677 - if entry not in myfiles_all:
8678 - self.qatracker.add_error("digest.unused", checkdir + "::" + entry)
8679 - for entry in myfiles_all:
8680 - if entry not in _digests:
8681 - self.qatracker.add_error("digest.missing", checkdir + "::" + entry)
8682 - del myfiles_all
8683 -
8684 - if os.path.exists(checkdir + "/files"):
8685 - filesdirlist = os.listdir(checkdir + "/files")
8686 -
8687 - # Recurse through files directory, use filesdirlist as a stack;
8688 - # appending directories as needed,
8689 - # so people can't hide > 20k files in a subdirectory.
8690 - while filesdirlist:
8691 - y = filesdirlist.pop(0)
8692 - relative_path = os.path.join(xpkg, "files", y)
8693 - full_path = os.path.join(self.repo_settings.repodir, relative_path)
8694 - try:
8695 - mystat = os.stat(full_path)
8696 - except OSError as oe:
8697 - if oe.errno == 2:
8698 - # don't worry about it. it likely was removed via fix above.
8699 - continue
8700 - else:
8701 - raise oe
8702 - if S_ISDIR(mystat.st_mode):
8703 - if self.vcs_settings.status.isVcsDir(y):
8704 - continue
8705 - for z in os.listdir(checkdir + "/files/" + y):
8706 - if self.vcs_settings.status.isVcsDir(z):
8707 - continue
8708 - filesdirlist.append(y + "/" + z)
8709 - # Current policy is no files over 20 KiB, these are the checks.
8710 - # File size over 20 KiB causes an error.
8711 - elif mystat.st_size > 20480:
8712 - self.qatracker.add_error(
8713 - "file.size",
8714 - "(%d KiB) %s/files/%s" % (mystat.st_size // 1024, xpkg, y),
8715 - )
8716 - elif mystat.st_size == 0:
8717 - self.qatracker.add_error("file.empty", "%s/files/%s" % (xpkg, y))
8718 -
8719 - index = self.repo_settings.repo_config.find_invalid_path_char(y)
8720 - if index != -1:
8721 - y_relative = os.path.join(checkdir_relative, "files", y)
8722 - if self.vcs_settings.vcs is not None and not vcs_new_changed(
8723 - y_relative, changed, new
8724 - ):
8725 - # If the file isn't in the VCS new or changed set, then
8726 - # assume that it's an irrelevant temporary file (Manifest
8727 - # entries are not generated for file names containing
8728 - # prohibited characters). See bug #406877.
8729 - index = -1
8730 - if index != -1:
8731 - self.qatracker.add_error(
8732 - "file.name", "%s/files/%s: char '%s'" % (checkdir, y, y[index])
8733 - )
8734 - return False
8735 -
8736 - def digests(self, checkdir):
8737 - """Returns the freshly loaded digests
8738 -
8739 - @param checkdir: string, directory path
8740 - """
8741 - mf = self.repoman_settings.repositories.get_repo_for_location(
8742 - os.path.dirname(os.path.dirname(checkdir))
8743 - )
8744 - mf = mf.load_manifest(checkdir, self.repoman_settings["DISTDIR"])
8745 - _digests = mf.getTypeDigests("DIST")
8746 - del mf
8747 - return _digests
8748 -
8749 - def check_mirrors(self, **kwargs):
8750 - """Check that URIs don't reference a server from thirdpartymirrors
8751 -
8752 - @param ebuild: Ebuild which we check (object).
8753 - @returns: boolean
8754 - """
8755 - ebuild = kwargs.get("ebuild").get()
8756 -
8757 - for uri in portage.dep.use_reduce(
8758 - ebuild.metadata["SRC_URI"],
8759 - matchall=True,
8760 - is_src_uri=True,
8761 - eapi=ebuild.eapi,
8762 - flat=True,
8763 - ):
8764 - contains_mirror = False
8765 - for mirror, mirror_alias in self.thirdpartymirrors.items():
8766 - if uri.startswith(mirror):
8767 - contains_mirror = True
8768 - break
8769 - if not contains_mirror:
8770 - continue
8771 -
8772 - new_uri = "mirror://%s/%s" % (mirror_alias, uri[len(mirror) :])
8773 - self.qatracker.add_error(
8774 - "SRC_URI.mirror",
8775 - "%s: '%s' found in thirdpartymirrors, use '%s'"
8776 - % (ebuild.relative_path, mirror, new_uri),
8777 - )
8778 - return False
8779 -
8780 - @property
8781 - def runInPkgs(self):
8782 - """Package level scans"""
8783 - return (True, [self.check])
8784 -
8785 - @property
8786 - def runInEbuilds(self):
8787 - """Ebuild level scans"""
8788 - return (True, [self.check_mirrors])
8789
8790 diff --git a/repoman/lib/repoman/modules/scan/keywords/__init__.py b/repoman/lib/repoman/modules/scan/keywords/__init__.py
8791 deleted file mode 100644
8792 index a830e35ba..000000000
8793 --- a/repoman/lib/repoman/modules/scan/keywords/__init__.py
8794 +++ /dev/null
8795 @@ -1,37 +0,0 @@
8796 -# Copyright 2015-2021 Gentoo Authors
8797 -# Distributed under the terms of the GNU General Public License v2
8798 -
8799 -doc = """Keywords plug-in module for repoman.
8800 -Performs keywords checks on ebuilds."""
8801 -__doc__ = doc[:]
8802 -
8803 -
8804 -module_spec = {
8805 - "name": "keywords",
8806 - "description": doc,
8807 - "provides": {
8808 - "keywords-module": {
8809 - "name": "keywords",
8810 - "sourcefile": "keywords",
8811 - "class": "KeywordChecks",
8812 - "description": doc,
8813 - "functions": ["prepare", "check"],
8814 - "func_desc": {},
8815 - "mod_kwargs": [
8816 - "qatracker",
8817 - "options",
8818 - "repo_metadata",
8819 - "profiles",
8820 - ],
8821 - "func_kwargs": {
8822 - "changed": (None, None),
8823 - "ebuild": ("Future", "UNSET"),
8824 - "pkg": ("Future", "UNSET"),
8825 - "xpkg": None,
8826 - "y_ebuild": (None, None),
8827 - },
8828 - "module_runsIn": ["pkgs", "ebuilds", "final"],
8829 - },
8830 - },
8831 - "version": 1,
8832 -}
8833
8834 diff --git a/repoman/lib/repoman/modules/scan/keywords/keywords.py b/repoman/lib/repoman/modules/scan/keywords/keywords.py
8835 deleted file mode 100644
8836 index 1e00421c6..000000000
8837 --- a/repoman/lib/repoman/modules/scan/keywords/keywords.py
8838 +++ /dev/null
8839 @@ -1,179 +0,0 @@
8840 -# -*- coding:utf-8 -*-
8841 -
8842 -"""keywords.py
8843 -Perform KEYWORDS related checks
8844 -
8845 -"""
8846 -
8847 -from repoman.modules.scan.scanbase import ScanBase
8848 -
8849 -
8850 -class KeywordChecks(ScanBase):
8851 - """Perform checks on the KEYWORDS of an ebuild"""
8852 -
8853 - def __init__(self, **kwargs):
8854 - """
8855 - @param qatracker: QATracker instance
8856 - @param options: argparse options instance
8857 - """
8858 - super(KeywordChecks, self).__init__(**kwargs)
8859 - self.qatracker = kwargs.get("qatracker")
8860 - self.options = kwargs.get("options")
8861 - self.repo_metadata = kwargs.get("repo_metadata")
8862 - self.profiles = kwargs.get("profiles")
8863 - self.slot_keywords = {}
8864 -
8865 - def prepare(self, **kwargs):
8866 - """Prepare the checks for the next package."""
8867 - self.slot_keywords = {}
8868 - self.dropped_keywords = {}
8869 - return False
8870 -
8871 - def check(self, **kwargs):
8872 - """Perform the check.
8873 -
8874 - @param pkg: Package in which we check (object).
8875 - @param xpkg: Package in which we check (string).
8876 - @param ebuild: Ebuild which we check (object).
8877 - @param y_ebuild: Ebuild which we check (string).
8878 - @param ebuild_archs: Just the architectures (no prefixes) of the ebuild.
8879 - @param changed: Changes instance
8880 - @returns: dictionary
8881 - """
8882 - pkg = kwargs.get("pkg").get()
8883 - xpkg = kwargs.get("xpkg")
8884 - ebuild = kwargs.get("ebuild").get()
8885 - y_ebuild = kwargs.get("y_ebuild")
8886 - changed = kwargs.get("changed")
8887 - if not self.options.straight_to_stable:
8888 - self._checkAddedWithStableKeywords(
8889 - xpkg, ebuild, y_ebuild, ebuild.keywords, changed
8890 - )
8891 -
8892 - self._checkForDroppedKeywords(pkg, ebuild, ebuild.archs)
8893 -
8894 - self._checkForInvalidKeywords(ebuild, xpkg, y_ebuild)
8895 -
8896 - self._checkForMaskLikeKeywords(xpkg, y_ebuild, ebuild.keywords)
8897 -
8898 - self._checkForUnsortedKeywords(ebuild, xpkg, y_ebuild)
8899 -
8900 - self.slot_keywords[pkg.slot].update(ebuild.archs)
8901 - return False
8902 -
8903 - def check_dropped_keywords(self, **kwargs):
8904 - """Report on any dropped keywords for the latest ebuild in a slot
8905 -
8906 - @returns: boolean
8907 - """
8908 - for ebuild, arches in self.dropped_keywords.values():
8909 - if arches:
8910 - self.qatracker.add_error(
8911 - "KEYWORDS.dropped", "%s: %s" % (ebuild, " ".join(sorted(arches)))
8912 - )
8913 - return False
8914 -
8915 - @staticmethod
8916 - def _isKeywordStable(keyword):
8917 - return not keyword.startswith("~") and not keyword.startswith("-")
8918 -
8919 - def _checkAddedWithStableKeywords(
8920 - self, package, ebuild, y_ebuild, keywords, changed
8921 - ):
8922 - catdir, pkgdir = package.split("/")
8923 -
8924 - stable_keywords = list(filter(self._isKeywordStable, keywords))
8925 - if stable_keywords:
8926 - if ebuild.ebuild_path in changed.new_ebuilds and catdir != "virtual":
8927 - stable_keywords.sort()
8928 - self.qatracker.add_error(
8929 - "KEYWORDS.stable",
8930 - "%s/%s.ebuild added with stable keywords: %s"
8931 - % (package, y_ebuild, " ".join(stable_keywords)),
8932 - )
8933 -
8934 - def _checkForDroppedKeywords(self, pkg, ebuild, ebuild_archs):
8935 - previous_keywords = self.slot_keywords.get(pkg.slot)
8936 - if previous_keywords is None:
8937 - self.slot_keywords[pkg.slot] = set()
8938 - elif ebuild_archs and "*" not in ebuild_archs and not ebuild.live_ebuild:
8939 - self.slot_keywords[pkg.slot].update(ebuild_archs)
8940 - dropped_keywords = previous_keywords.difference(ebuild_archs)
8941 - self.dropped_keywords[pkg.slot] = (
8942 - ebuild.relative_path,
8943 - {arch for arch in dropped_keywords},
8944 - )
8945 -
8946 - def _checkForInvalidKeywords(self, ebuild, xpkg, y_ebuild):
8947 - myuse = ebuild.keywords
8948 -
8949 - for mykey in myuse:
8950 - if mykey not in ("-*", "*", "~*"):
8951 - myskey = mykey
8952 -
8953 - if not self._isKeywordStable(myskey[:1]):
8954 - myskey = myskey[1:]
8955 -
8956 - if myskey not in self.repo_metadata["kwlist"]:
8957 - self.qatracker.add_error(
8958 - "KEYWORDS.invalid", "%s/%s.ebuild: %s" % (xpkg, y_ebuild, mykey)
8959 - )
8960 - elif myskey not in self.profiles:
8961 - self.qatracker.add_error(
8962 - "KEYWORDS.invalid",
8963 - "%s/%s.ebuild: %s (profile invalid)" % (xpkg, y_ebuild, mykey),
8964 - )
8965 -
8966 - def _checkForMaskLikeKeywords(self, xpkg, y_ebuild, keywords):
8967 - # KEYWORDS="-*" is a stupid replacement for package.mask
8968 - # and screws general KEYWORDS semantics
8969 - if "-*" in keywords:
8970 - haskeyword = False
8971 -
8972 - for kw in keywords:
8973 - if kw[0] == "~":
8974 - kw = kw[1:]
8975 - if kw in self.repo_metadata["kwlist"]:
8976 - haskeyword = True
8977 -
8978 - if not haskeyword:
8979 - self.qatracker.add_error(
8980 - "KEYWORDS.stupid", "%s/%s.ebuild" % (xpkg, y_ebuild)
8981 - )
8982 -
8983 - def _checkForUnsortedKeywords(self, ebuild, xpkg, y_ebuild):
8984 - """Ebuilds that contain KEYWORDS
8985 - which are not sorted alphabetically."""
8986 -
8987 - def sort_keywords(kw):
8988 - # Split keywords containing hyphens. The part after
8989 - # the hyphen should be treated as the primary key.
8990 - # This is consistent with ekeyword.
8991 - parts = list(reversed(kw.lstrip("~-").split("-", 1)))
8992 - # Hack to make sure that keywords
8993 - # without hyphens are sorted first
8994 - if len(parts) == 1:
8995 - parts.insert(0, "")
8996 - return parts
8997 -
8998 - sorted_keywords = sorted(ebuild.keywords, key=sort_keywords)
8999 - if sorted_keywords != ebuild.keywords:
9000 - self.qatracker.add_error(
9001 - "KEYWORDS.unsorted",
9002 - "%s/%s.ebuild contains unsorted keywords" % (xpkg, y_ebuild),
9003 - )
9004 -
9005 - @property
9006 - def runInPkgs(self):
9007 - """Package level scans"""
9008 - return (True, [self.prepare])
9009 -
9010 - @property
9011 - def runInEbuilds(self):
9012 - """Ebuild level scans"""
9013 - return (True, [self.check])
9014 -
9015 - @property
9016 - def runInFinal(self):
9017 - """Final package level scans"""
9018 - return (True, [self.check_dropped_keywords])
9019
9020 diff --git a/repoman/lib/repoman/modules/scan/manifest/__init__.py b/repoman/lib/repoman/modules/scan/manifest/__init__.py
9021 deleted file mode 100644
9022 index 2315a2a7e..000000000
9023 --- a/repoman/lib/repoman/modules/scan/manifest/__init__.py
9024 +++ /dev/null
9025 @@ -1,34 +0,0 @@
9026 -# Copyright 2015-2021 Gentoo Authors
9027 -# Distributed under the terms of the GNU General Public License v2
9028 -
9029 -doc = """Ebuild plug-in module for repoman.
9030 -Performs an IsEbuild check on ebuilds."""
9031 -__doc__ = doc[:]
9032 -
9033 -
9034 -module_spec = {
9035 - "name": "manifest",
9036 - "description": doc,
9037 - "provides": {
9038 - "manifest-module": {
9039 - "name": "manifests",
9040 - "sourcefile": "manifests",
9041 - "class": "Manifests",
9042 - "description": doc,
9043 - "functions": ["check", "create_manifest", "digest_check"],
9044 - "func_desc": {},
9045 - "mod_kwargs": [
9046 - "options",
9047 - "portdb",
9048 - "qatracker",
9049 - "repo_settings",
9050 - ],
9051 - "func_kwargs": {
9052 - "checkdir": (None, None),
9053 - "xpkg": (None, None),
9054 - },
9055 - "module_runsIn": ["pkgs"],
9056 - },
9057 - },
9058 - "version": 1,
9059 -}
9060
9061 diff --git a/repoman/lib/repoman/modules/scan/manifest/manifests.py b/repoman/lib/repoman/modules/scan/manifest/manifests.py
9062 deleted file mode 100644
9063 index 24b4e7f9b..000000000
9064 --- a/repoman/lib/repoman/modules/scan/manifest/manifests.py
9065 +++ /dev/null
9066 @@ -1,56 +0,0 @@
9067 -# -*- coding:utf-8 -*-
9068 -
9069 -# import our initialized portage instance
9070 -from repoman._portage import portage
9071 -from repoman.modules.scan.scanbase import ScanBase
9072 -
9073 -from portage import os
9074 -
9075 -
9076 -class Manifests(ScanBase):
9077 - """Creates as well as checks pkg Manifest entries/files"""
9078 -
9079 - def __init__(self, **kwargs):
9080 - """Class init
9081 -
9082 - @param options: the run time cli options
9083 - @param portdb: portdb instance
9084 - @param qatracker: QATracker instance
9085 - @param repo_settings: repository settings instance
9086 - """
9087 - self.options = kwargs.get("options")
9088 - self.portdb = kwargs.get("portdb")
9089 - self.qatracker = kwargs.get("qatracker")
9090 - self.repoman_settings = kwargs.get("repo_settings").repoman_settings
9091 -
9092 - def check(self, **kwargs):
9093 - """Perform a changelog and untracked checks on the ebuild
9094 -
9095 - @param xpkg: Package in which we check (object).
9096 - @param checkdir: the current package directory
9097 - @returns: dictionary
9098 - """
9099 - checkdir = kwargs.get("checkdir")
9100 - xpkg = kwargs.get("xpkg")
9101 - if self.options.pretend:
9102 - return False
9103 - self.digest_check(xpkg, checkdir)
9104 - if self.options.mode == "manifest-check":
9105 - return True
9106 - return False
9107 -
9108 - def digest_check(self, xpkg, checkdir):
9109 - """Check the manifest entries, report any Q/A errors
9110 -
9111 - @param xpkg: the cat/pkg name to check
9112 - @param checkdir: the directory path to check"""
9113 - self.repoman_settings["O"] = checkdir
9114 - self.repoman_settings["PORTAGE_QUIET"] = "1"
9115 - if not portage.digestcheck([], self.repoman_settings, strict=1):
9116 - self.qatracker.add_error("manifest.bad", os.path.join(xpkg, "Manifest"))
9117 - self.repoman_settings.pop("PORTAGE_QUIET", None)
9118 -
9119 - @property
9120 - def runInPkgs(self):
9121 - """Package level scans"""
9122 - return (True, [self.check])
9123
9124 diff --git a/repoman/lib/repoman/modules/scan/metadata/__init__.py b/repoman/lib/repoman/modules/scan/metadata/__init__.py
9125 deleted file mode 100644
9126 index c133b1b37..000000000
9127 --- a/repoman/lib/repoman/modules/scan/metadata/__init__.py
9128 +++ /dev/null
9129 @@ -1,89 +0,0 @@
9130 -# Copyright 2015-2021 Gentoo Authors
9131 -# Distributed under the terms of the GNU General Public License v2
9132 -
9133 -doc = """Metadata plug-in module for repoman.
9134 -Performs metadata checks on packages."""
9135 -__doc__ = doc[:]
9136 -
9137 -
9138 -module_spec = {
9139 - "name": "metadata",
9140 - "description": doc,
9141 - "provides": {
9142 - "pkg-metadata": {
9143 - "name": "pkgmetadata",
9144 - "sourcefile": "pkgmetadata",
9145 - "class": "PkgMetadata",
9146 - "description": doc,
9147 - "functions": ["check"],
9148 - "func_desc": {},
9149 - "mod_kwargs": [
9150 - "repo_settings",
9151 - "qatracker",
9152 - "options",
9153 - "metadata_xsd",
9154 - "uselist",
9155 - ],
9156 - "func_kwargs": {
9157 - "checkdir": (None, None),
9158 - "checkdirlist": (None, None),
9159 - "ebuild": (None, None),
9160 - "pkg": (None, None),
9161 - "repolevel": (None, None),
9162 - "validity_future": (None, None),
9163 - "xpkg": (None, None),
9164 - "y_ebuild": (None, None),
9165 - },
9166 - "module_runsIn": ["pkgs", "ebuilds", "final"],
9167 - },
9168 - "ebuild-metadata": {
9169 - "name": "ebuild_metadata",
9170 - "sourcefile": "ebuild_metadata",
9171 - "class": "EbuildMetadata",
9172 - "description": doc,
9173 - "functions": ["check"],
9174 - "func_desc": {},
9175 - "mod_kwargs": [
9176 - "qatracker",
9177 - "repo_settings",
9178 - ],
9179 - "func_kwargs": {
9180 - "catdir": (None, None),
9181 - "ebuild": (None, None),
9182 - "xpkg": (None, None),
9183 - "y_ebuild": (None, None),
9184 - },
9185 - "module_runsIn": ["ebuilds"],
9186 - },
9187 - "description-metadata": {
9188 - "name": "description",
9189 - "sourcefile": "description",
9190 - "class": "DescriptionChecks",
9191 - "description": doc,
9192 - "functions": ["check"],
9193 - "func_desc": {},
9194 - "mod_kwargs": ["qatracker", "repo_settings"],
9195 - "func_kwargs": {
9196 - "ebuild": (None, None),
9197 - "pkg": ("Future", "UNSET"),
9198 - },
9199 - "module_runsIn": ["ebuilds"],
9200 - },
9201 - "restrict-metadata": {
9202 - "name": "restrict",
9203 - "sourcefile": "restrict",
9204 - "class": "RestrictChecks",
9205 - "description": doc,
9206 - "functions": ["check"],
9207 - "func_desc": {},
9208 - "mod_kwargs": ["qatracker", "repo_settings"],
9209 - "func_kwargs": {
9210 - "ebuild": (None, None),
9211 - "xpkg": (None, None),
9212 - "y_ebuild": (None, None),
9213 - },
9214 - "module_runsIn": ["ebuilds"],
9215 - },
9216 - },
9217 - "version": 1,
9218 -}
9219
9220 diff --git a/repoman/lib/repoman/modules/scan/metadata/description.py b/repoman/lib/repoman/modules/scan/metadata/description.py
9221 deleted file mode 100644
9222 index c9fb5e7f9..000000000
9223 --- a/repoman/lib/repoman/modules/scan/metadata/description.py
9224 +++ /dev/null
9225 @@ -1,44 +0,0 @@
9226 -"""description.py
9227 -Perform checks on the DESCRIPTION variable.
9228 -"""
9229 -
9230 -from repoman.modules.scan.scanbase import ScanBase
9231 -
9232 -
9233 -class DescriptionChecks(ScanBase):
9234 - """Perform checks on the DESCRIPTION variable."""
9235 -
9236 - def __init__(self, **kwargs):
9237 - """
9238 - @param qatracker: QATracker instance
9239 - """
9240 - self.qatracker = kwargs.get("qatracker")
9241 - self.repo_settings = kwargs.get("repo_settings")
9242 -
9243 - def checkTooLong(self, **kwargs):
9244 - """
9245 - @param pkg: Package in which we check (object).
9246 - @param ebuild: Ebuild which we check (object).
9247 - """
9248 - ebuild = kwargs.get("ebuild").get()
9249 - pkg = kwargs.get("pkg").get()
9250 - # 14 is the length of DESCRIPTION=""
9251 - if len(pkg._metadata["DESCRIPTION"]) > self.repo_settings.qadata.max_desc_len:
9252 - self.qatracker.add_error(
9253 - "DESCRIPTION.toolong",
9254 - "%s: DESCRIPTION is %d characters (max %d)"
9255 - % (
9256 - ebuild.relative_path,
9257 - len(pkg._metadata["DESCRIPTION"]),
9258 - self.repo_settings.qadata.max_desc_len,
9259 - ),
9260 - )
9261 - return False
9262 -
9263 - @property
9264 - def runInPkgs(self):
9265 - return (False, [])
9266 -
9267 - @property
9268 - def runInEbuilds(self):
9269 - return (True, [self.checkTooLong])
9270
9271 diff --git a/repoman/lib/repoman/modules/scan/metadata/ebuild_metadata.py b/repoman/lib/repoman/modules/scan/metadata/ebuild_metadata.py
9272 deleted file mode 100644
9273 index fd0552ce7..000000000
9274 --- a/repoman/lib/repoman/modules/scan/metadata/ebuild_metadata.py
9275 +++ /dev/null
9276 @@ -1,84 +0,0 @@
9277 -# -*- coding:utf-8 -*-
9278 -
9279 -"""Ebuild Metadata Checks"""
9280 -
9281 -import re
9282 -
9283 -from repoman.modules.scan.scanbase import ScanBase
9284 -
9285 -from portage.dep import use_reduce
9286 -
9287 -NON_ASCII_RE = re.compile(r"[^\x00-\x7f]")
9288 -URISCHEME_RE = re.compile(r"^[a-z][0-9a-z\-\.\+]+://")
9289 -
9290 -
9291 -class EbuildMetadata(ScanBase):
9292 - def __init__(self, **kwargs):
9293 - self.qatracker = kwargs.get("qatracker")
9294 - self.repo_settings = kwargs.get("repo_settings")
9295 -
9296 - def invalidchar(self, **kwargs):
9297 - ebuild = kwargs.get("ebuild").get()
9298 - for k, v in ebuild.metadata.items():
9299 - if not isinstance(v, str):
9300 - continue
9301 - m = NON_ASCII_RE.search(v)
9302 - if m is not None:
9303 - self.qatracker.add_error(
9304 - "variable.invalidchar",
9305 - "%s: %s variable contains non-ASCII "
9306 - "character at position %s"
9307 - % (ebuild.relative_path, k, m.start() + 1),
9308 - )
9309 - return False
9310 -
9311 - def missing(self, **kwargs):
9312 - ebuild = kwargs.get("ebuild").get()
9313 - for pos, missing_var in enumerate(self.repo_settings.qadata.missingvars):
9314 - if not ebuild.metadata.get(missing_var):
9315 - if kwargs.get("catdir") in (
9316 - "acct-group",
9317 - "acct-user",
9318 - "virtual",
9319 - ) and missing_var in ("HOMEPAGE", "LICENSE"):
9320 - continue
9321 - if ebuild.live_ebuild and missing_var == "KEYWORDS":
9322 - continue
9323 - myqakey = self.repo_settings.qadata.missingvars[pos] + ".missing"
9324 - self.qatracker.add_error(
9325 - myqakey,
9326 - "%s/%s.ebuild" % (kwargs.get("xpkg"), kwargs.get("y_ebuild")),
9327 - )
9328 - return False
9329 -
9330 - def virtual(self, **kwargs):
9331 - ebuild = kwargs.get("ebuild").get()
9332 - if kwargs.get("catdir") == "virtual":
9333 - for var in ("HOMEPAGE", "LICENSE"):
9334 - if ebuild.metadata.get(var):
9335 - myqakey = var + ".virtual"
9336 - self.qatracker.add_error(myqakey, ebuild.relative_path)
9337 - return False
9338 -
9339 - def homepage_urischeme(self, **kwargs):
9340 - ebuild = kwargs.get("ebuild").get()
9341 - if kwargs.get("catdir") != "virtual":
9342 - for homepage in use_reduce(
9343 - ebuild.metadata["HOMEPAGE"], matchall=True, flat=True
9344 - ):
9345 - if URISCHEME_RE.match(homepage) is None:
9346 - self.qatracker.add_error(
9347 - "HOMEPAGE.missingurischeme", ebuild.relative_path
9348 - )
9349 - return False
9350 -
9351 - @property
9352 - def runInPkgs(self):
9353 - return (False, [])
9354 -
9355 - @property
9356 - def runInEbuilds(self):
9357 - return (
9358 - True,
9359 - [self.invalidchar, self.missing, self.virtual, self.homepage_urischeme],
9360 - )
9361
9362 diff --git a/repoman/lib/repoman/modules/scan/metadata/pkgmetadata.py b/repoman/lib/repoman/modules/scan/metadata/pkgmetadata.py
9363 deleted file mode 100644
9364 index 0fb97a0df..000000000
9365 --- a/repoman/lib/repoman/modules/scan/metadata/pkgmetadata.py
9366 +++ /dev/null
9367 @@ -1,221 +0,0 @@
9368 -# -*- coding:utf-8 -*-
9369 -
9370 -"""Package Metadata Checks operations"""
9371 -
9372 -import sys
9373 -import re
9374 -
9375 -from itertools import chain
9376 -from collections import Counter
9377 -
9378 -try:
9379 - from lxml import etree
9380 - from lxml.etree import ParserError
9381 -except (SystemExit, KeyboardInterrupt):
9382 - raise
9383 -except (ImportError, SystemError, RuntimeError, Exception):
9384 - # broken or missing xml support
9385 - # https://bugs.python.org/issue14988
9386 - msg = ["Please emerge dev-python/lxml in order to use repoman."]
9387 - from portage.output import EOutput
9388 -
9389 - out = EOutput()
9390 - for line in msg:
9391 - out.eerror(line)
9392 - sys.exit(1)
9393 -
9394 -# import our initialized portage instance
9395 -from repoman._portage import portage # pylint: disable=unused-import
9396 -from repoman.metadata import metadata_dtd_uri
9397 -from repoman.modules.scan.scanbase import ScanBase
9398 -
9399 -# pylint: disable=ungrouped-imports
9400 -from portage.exception import InvalidAtom
9401 -from portage import os
9402 -from portage.dep import Atom
9403 -from portage.xml.metadata import parse_metadata_use
9404 -
9405 -from .use_flags import USEFlagChecks
9406 -
9407 -metadata_xml_encoding = "UTF-8"
9408 -metadata_xml_declaration = '<?xml version="1.0" encoding="%s"?>' % (
9409 - metadata_xml_encoding,
9410 -)
9411 -metadata_doctype_name = "pkgmetadata"
9412 -
9413 -
9414 -class PkgMetadata(ScanBase, USEFlagChecks):
9415 - """Package metadata.xml checks"""
9416 -
9417 - def __init__(self, **kwargs):
9418 - """PkgMetadata init function
9419 -
9420 - @param repo_settings: settings instance
9421 - @param qatracker: QATracker instance
9422 - @param options: argparse options instance
9423 - @param metadata_xsd: path of metadata.xsd
9424 - """
9425 - super(PkgMetadata, self).__init__(**kwargs)
9426 - repo_settings = kwargs.get("repo_settings")
9427 - self.qatracker = kwargs.get("qatracker")
9428 - self.options = kwargs.get("options")
9429 - self.metadata_xsd = kwargs.get("metadata_xsd")
9430 - self.globalUseFlags = kwargs.get("uselist")
9431 - self.repoman_settings = repo_settings.repoman_settings
9432 - self.musedict = {}
9433 - self.muselist = set()
9434 -
9435 - def check(self, **kwargs):
9436 - """Performs the checks on the metadata.xml for the package
9437 - @param xpkg: the pacakge being checked
9438 - @param checkdir: string, directory path
9439 - @param checkdirlist: list of checkdir's
9440 - @param repolevel: integer
9441 - @returns: boolean
9442 - """
9443 - xpkg = kwargs.get("xpkg")
9444 - checkdir = kwargs.get("checkdir")
9445 - checkdirlist = kwargs.get("checkdirlist").get()
9446 -
9447 - self.musedict = {}
9448 - if self.options.mode in ["manifest"]:
9449 - self.muselist = frozenset(self.musedict)
9450 - return False
9451 -
9452 - # metadata.xml file check
9453 - if "metadata.xml" not in checkdirlist:
9454 - self.qatracker.add_error("metadata.missing", xpkg + "/metadata.xml")
9455 - self.muselist = frozenset(self.musedict)
9456 - return False
9457 -
9458 - # metadata.xml parse check
9459 - metadata_bad = False
9460 -
9461 - # read metadata.xml into memory
9462 - try:
9463 - _metadata_xml = etree.parse(os.path.join(checkdir, "metadata.xml"))
9464 - except (ParserError, SyntaxError, EnvironmentError) as e:
9465 - metadata_bad = True
9466 - self.qatracker.add_error("metadata.bad", "%s/metadata.xml: %s" % (xpkg, e))
9467 - del e
9468 - self.muselist = frozenset(self.musedict)
9469 - return False
9470 -
9471 - indentation_chars = Counter()
9472 - for l in etree.tostring(_metadata_xml).splitlines():
9473 - indentation_chars.update(re.match(rb"\s*", l).group(0))
9474 - if len(indentation_chars) > 1:
9475 - self.qatracker.add_error(
9476 - "metadata.warning",
9477 - "%s/metadata.xml: %s"
9478 - % (xpkg, "inconsistent use of tabs and spaces in indentation"),
9479 - )
9480 -
9481 - xml_encoding = _metadata_xml.docinfo.encoding
9482 - if xml_encoding.upper() != metadata_xml_encoding:
9483 - self.qatracker.add_error(
9484 - "metadata.bad",
9485 - "%s/metadata.xml: "
9486 - "xml declaration encoding should be '%s', not '%s'"
9487 - % (xpkg, metadata_xml_encoding, xml_encoding),
9488 - )
9489 -
9490 - if not _metadata_xml.docinfo.doctype:
9491 - metadata_bad = True
9492 - self.qatracker.add_error(
9493 - "metadata.bad", "%s/metadata.xml: %s" % (xpkg, "DOCTYPE is missing")
9494 - )
9495 - else:
9496 - doctype_system = _metadata_xml.docinfo.system_url
9497 - if doctype_system != metadata_dtd_uri:
9498 - if doctype_system is None:
9499 - system_problem = "but it is undefined"
9500 - else:
9501 - system_problem = "not '%s'" % doctype_system
9502 - self.qatracker.add_error(
9503 - "metadata.bad",
9504 - "%s/metadata.xml: "
9505 - "DOCTYPE: SYSTEM should refer to '%s', %s"
9506 - % (xpkg, metadata_dtd_uri, system_problem),
9507 - )
9508 - doctype_name = _metadata_xml.docinfo.doctype.split(" ")[1]
9509 - if doctype_name != metadata_doctype_name:
9510 - self.qatracker.add_error(
9511 - "metadata.bad",
9512 - "%s/metadata.xml: "
9513 - "DOCTYPE: name should be '%s', not '%s'"
9514 - % (xpkg, metadata_doctype_name, doctype_name),
9515 - )
9516 -
9517 - # load USE flags from metadata.xml
9518 - self.musedict = parse_metadata_use(_metadata_xml)
9519 - for atom in chain(*self.musedict.values()):
9520 - if atom is None:
9521 - continue
9522 - try:
9523 - atom = Atom(atom)
9524 - except InvalidAtom as e:
9525 - self.qatracker.add_error(
9526 - "metadata.bad", "%s/metadata.xml: Invalid atom: %s" % (xpkg, e)
9527 - )
9528 - else:
9529 - if atom.cp != xpkg:
9530 - self.qatracker.add_error(
9531 - "metadata.bad",
9532 - "%s/metadata.xml: Atom contains "
9533 - "unexpected cat/pn: %s" % (xpkg, atom),
9534 - )
9535 -
9536 - # Only carry out if in package directory or check forced
9537 - if not metadata_bad:
9538 - validator = etree.XMLSchema(file=self.metadata_xsd)
9539 - if not validator.validate(_metadata_xml):
9540 - self._add_validate_errors(xpkg, validator.error_log)
9541 - self.muselist = frozenset(self.musedict)
9542 - return False
9543 -
9544 - def check_unused(self, **kwargs):
9545 - """Reports on any unused metadata.xml use descriptions
9546 -
9547 - @param xpkg: the pacakge being checked
9548 - @param used_useflags: use flag list
9549 - @param validity_future: Future instance
9550 - """
9551 - xpkg = kwargs.get("xpkg")
9552 - valid_state = kwargs.get("validity_future").get()
9553 - # check if there are unused local USE-descriptions in metadata.xml
9554 - # (unless there are any invalids, to avoid noise)
9555 - if valid_state:
9556 - for myflag in self.muselist.difference(self.usedUseFlags):
9557 - self.qatracker.add_error(
9558 - "metadata.bad",
9559 - "%s/metadata.xml: unused local USE-description: '%s'"
9560 - % (xpkg, myflag),
9561 - )
9562 - return False
9563 -
9564 - def _add_validate_errors(self, xpkg, log):
9565 - listed = set()
9566 - for error in log:
9567 - msg_prefix = error.message.split(":", 1)[0]
9568 - info = "%s %s" % (error.line, msg_prefix)
9569 - if info not in listed:
9570 - listed.add(info)
9571 - self.qatracker.add_error(
9572 - "metadata.bad",
9573 - "%s/metadata.xml: line: %s, %s" % (xpkg, error.line, error.message),
9574 - )
9575 -
9576 - @property
9577 - def runInPkgs(self):
9578 - """Package level scans"""
9579 - return (True, [self.check])
9580 -
9581 - @property
9582 - def runInEbuilds(self):
9583 - return (True, [self.check_useflags])
9584 -
9585 - @property
9586 - def runInFinal(self):
9587 - """Final scans at the package level"""
9588 - return (True, [self.check_unused])
9589
9590 diff --git a/repoman/lib/repoman/modules/scan/metadata/restrict.py b/repoman/lib/repoman/modules/scan/metadata/restrict.py
9591 deleted file mode 100644
9592 index 036af88f6..000000000
9593 --- a/repoman/lib/repoman/modules/scan/metadata/restrict.py
9594 +++ /dev/null
9595 @@ -1,58 +0,0 @@
9596 -"""restrict.py
9597 -Perform checks on the RESTRICT variable.
9598 -"""
9599 -
9600 -# import our initialized portage instance
9601 -from repoman._portage import portage
9602 -
9603 -from repoman.modules.scan.scanbase import ScanBase
9604 -
9605 -
9606 -class RestrictChecks(ScanBase):
9607 - """Perform checks on the RESTRICT variable."""
9608 -
9609 - def __init__(self, **kwargs):
9610 - """
9611 - @param qatracker: QATracker instance
9612 - """
9613 - self.qatracker = kwargs.get("qatracker")
9614 - self.repo_settings = kwargs.get("repo_settings")
9615 - if self.repo_settings.repo_config.restrict_allowed is None:
9616 - self._restrict_allowed = self.repo_settings.qadata.valid_restrict
9617 - else:
9618 - self._restrict_allowed = self.repo_settings.repo_config.restrict_allowed
9619 -
9620 - def check(self, **kwargs):
9621 - xpkg = kwargs.get("xpkg")
9622 - ebuild = kwargs.get("ebuild").get()
9623 - y_ebuild = kwargs.get("y_ebuild")
9624 - myrestrict = None
9625 -
9626 - try:
9627 - myrestrict = portage.dep.use_reduce(
9628 - ebuild.metadata["RESTRICT"], matchall=1, flat=True
9629 - )
9630 - except portage.exception.InvalidDependString as e:
9631 - self.qatracker.add_error(
9632 - "RESTRICT.syntax", "%s: RESTRICT: %s" % (ebuild.relative_path, e)
9633 - )
9634 - del e
9635 -
9636 - if myrestrict:
9637 - myrestrict = set(myrestrict)
9638 - mybadrestrict = myrestrict.difference(self._restrict_allowed)
9639 -
9640 - if mybadrestrict:
9641 - for mybad in mybadrestrict:
9642 - self.qatracker.add_error(
9643 - "RESTRICT.invalid", "%s/%s.ebuild: %s" % (xpkg, y_ebuild, mybad)
9644 - )
9645 - return False
9646 -
9647 - @property
9648 - def runInPkgs(self):
9649 - return (False, [])
9650 -
9651 - @property
9652 - def runInEbuilds(self):
9653 - return (True, [self.check])
9654
9655 diff --git a/repoman/lib/repoman/modules/scan/metadata/use_flags.py b/repoman/lib/repoman/modules/scan/metadata/use_flags.py
9656 deleted file mode 100644
9657 index f2116800e..000000000
9658 --- a/repoman/lib/repoman/modules/scan/metadata/use_flags.py
9659 +++ /dev/null
9660 @@ -1,103 +0,0 @@
9661 -# -*- coding:utf-8 -*-
9662 -
9663 -"""use_flags.py
9664 -Performs USE flag related checks
9665 -"""
9666 -
9667 -# import our centrally initialized portage instance
9668 -from repoman._portage import portage
9669 -
9670 -from portage import eapi
9671 -from portage.eapi import eapi_has_iuse_defaults, eapi_has_required_use
9672 -
9673 -
9674 -class USEFlagChecks:
9675 - """Performs checks on USE flags listed in the ebuilds and metadata.xml"""
9676 -
9677 - def __init__(self, **kwargs):
9678 - """Class init
9679 -
9680 - @param qatracker: QATracker instance
9681 - @param globalUseFlags: Global USE flags
9682 - """
9683 - super(USEFlagChecks, self).__init__()
9684 - self.qatracker = None
9685 - self.globalUseFlags = None
9686 - self.useFlags = []
9687 - self.defaultUseFlags = []
9688 - self.usedUseFlags = set()
9689 -
9690 - def check_useflags(self, **kwargs):
9691 - """Perform the check.
9692 -
9693 - @param pkg: Package in which we check (object).
9694 - @param xpkg: Package in which we check (string).
9695 - @param ebuild: Ebuild which we check (object).
9696 - @param y_ebuild: Ebuild which we check (string).
9697 - @returns: dictionary, including {ebuild_UsedUseFlags, used_useflags}
9698 - """
9699 - pkg = kwargs.get("pkg").get()
9700 - package = kwargs.get("xpkg")
9701 - ebuild = kwargs.get("ebuild").get()
9702 - y_ebuild = kwargs.get("y_ebuild")
9703 - # reset state variables for the run
9704 - self.useFlags = []
9705 - self.defaultUseFlags = []
9706 - # perform the checks
9707 - self._checkGlobal(pkg)
9708 - self._checkMetadata(package, ebuild, y_ebuild, self.muselist)
9709 - self._checkRequiredUSE(pkg, ebuild)
9710 - return False
9711 -
9712 - def _checkGlobal(self, pkg):
9713 - for myflag in pkg._metadata["IUSE"].split():
9714 - flag_name = myflag.lstrip("+-")
9715 - self.usedUseFlags.add(flag_name)
9716 - if myflag != flag_name:
9717 - self.defaultUseFlags.append(myflag)
9718 - if flag_name not in self.globalUseFlags:
9719 - self.useFlags.append(flag_name)
9720 -
9721 - def _checkMetadata(self, package, ebuild, y_ebuild, localUseFlags):
9722 - for mypos in range(len(self.useFlags) - 1, -1, -1):
9723 - if self.useFlags[mypos] and (self.useFlags[mypos] in localUseFlags):
9724 - del self.useFlags[mypos]
9725 -
9726 - if self.defaultUseFlags and not eapi_has_iuse_defaults(eapi):
9727 - for myflag in self.defaultUseFlags:
9728 - self.qatracker.add_error(
9729 - "EAPI.incompatible",
9730 - "%s: IUSE defaults"
9731 - " not supported with EAPI='%s': '%s'"
9732 - % (ebuild.relative_path, eapi, myflag),
9733 - )
9734 -
9735 - for mypos in range(len(self.useFlags)):
9736 - self.qatracker.add_error(
9737 - "IUSE.invalid",
9738 - "%s/%s.ebuild: %s" % (package, y_ebuild, self.useFlags[mypos]),
9739 - )
9740 -
9741 - def _checkRequiredUSE(self, pkg, ebuild):
9742 - required_use = pkg._metadata["REQUIRED_USE"]
9743 - if required_use:
9744 - if not eapi_has_required_use(eapi):
9745 - self.qatracker.add_error(
9746 - "EAPI.incompatible",
9747 - "%s: REQUIRED_USE"
9748 - " not supported with EAPI='%s'"
9749 - % (
9750 - ebuild.relative_path,
9751 - eapi,
9752 - ),
9753 - )
9754 - try:
9755 - portage.dep.check_required_use(
9756 - required_use, (), pkg.iuse.is_valid_flag, eapi=eapi
9757 - )
9758 - except portage.exception.InvalidDependString as e:
9759 - self.qatracker.add_error(
9760 - "REQUIRED_USE.syntax",
9761 - "%s: REQUIRED_USE: %s" % (ebuild.relative_path, e),
9762 - )
9763 - del e
9764
9765 diff --git a/repoman/lib/repoman/modules/scan/module.py b/repoman/lib/repoman/modules/scan/module.py
9766 deleted file mode 100644
9767 index 9e67f9bd6..000000000
9768 --- a/repoman/lib/repoman/modules/scan/module.py
9769 +++ /dev/null
9770 @@ -1,127 +0,0 @@
9771 -"""
9772 -moudules/scan/module.py
9773 -Module loading and run list generator
9774 -"""
9775 -
9776 -import logging
9777 -import os
9778 -import yaml
9779 -
9780 -import portage
9781 -from portage.module import InvalidModuleName, Modules
9782 -from portage.util import stack_lists
9783 -from repoman import _not_installed
9784 -from repoman.config import ConfigError
9785 -
9786 -MODULES_PATH = os.path.dirname(__file__)
9787 -# initial development debug info
9788 -logging.debug("module path: %s", MODULES_PATH)
9789 -
9790 -
9791 -class ModuleConfig:
9792 - """Holds the scan modules configuration information and
9793 - creates the ordered list of modulles to run"""
9794 -
9795 - def __init__(self, configpaths, valid_versions=None, repository_modules=False):
9796 - """Module init
9797 -
9798 - @param configpaths: ordered list of filepaths to load
9799 - """
9800 - if repository_modules:
9801 - self.configpaths = [
9802 - os.path.join(path, "repository.yaml") for path in configpaths
9803 - ]
9804 - elif _not_installed:
9805 - self.configpaths = [
9806 - os.path.realpath(
9807 - os.path.join(
9808 - os.path.dirname(
9809 - os.path.dirname(
9810 - os.path.dirname(
9811 - os.path.dirname(os.path.dirname(__file__))
9812 - )
9813 - )
9814 - ),
9815 - "cnf/repository/repository.yaml",
9816 - )
9817 - )
9818 - ]
9819 - else:
9820 - self.configpaths = [
9821 - os.path.join(
9822 - portage.const.EPREFIX or "/",
9823 - "usr/share/repoman/repository/repository.yaml",
9824 - )
9825 - ]
9826 - logging.debug("ModuleConfig; configpaths: %s", self.configpaths)
9827 -
9828 - self.controller = Modules(path=MODULES_PATH, namepath="repoman.modules.scan")
9829 - logging.debug("ModuleConfig; module_names: %s", self.controller.module_names)
9830 -
9831 - self._configs = None
9832 - self.enabled = []
9833 - self.pkgs_loop = []
9834 - self.ebuilds_loop = []
9835 - self.final_loop = []
9836 - self.modules_forced = ["ebuild", "mtime"]
9837 - self.load_configs(valid_versions=valid_versions)
9838 - for loop in ["pkgs", "ebuilds", "final"]:
9839 - logging.debug("ModuleConfig; Processing loop %s", loop)
9840 - setattr(self, "%s_loop" % loop, self._determine_list(loop))
9841 - self.linechecks = stack_lists(
9842 - c["linechecks_modules"].split() for c in self._configs
9843 - )
9844 -
9845 - def load_configs(self, configpaths=None, valid_versions=None):
9846 - """load the config files in order
9847 -
9848 - @param configpaths: ordered list of filepaths to load
9849 - """
9850 - if configpaths:
9851 - self.configpaths = configpaths
9852 - elif not self.configpaths:
9853 - logging.error("ModuleConfig; Error: No repository.yaml files defined")
9854 - configs = []
9855 - for path in self.configpaths:
9856 - logging.debug("ModuleConfig; Processing: %s", path)
9857 - if os.path.exists(path):
9858 - try:
9859 - with open(path, "r") as inputfile:
9860 - configs.append(yaml.safe_load(inputfile))
9861 - except IOError as error:
9862 - logging, error("Failed to load file: %s", inputfile)
9863 - logging.exception(error)
9864 - else:
9865 - if configs[-1]["version"] not in valid_versions:
9866 - raise ConfigError(
9867 - "Invalid file version: %s in: %s\nPlease upgrade repoman"
9868 - % (configs["version"], path)
9869 - )
9870 - logging.debug("ModuleConfig; completed : %s", path)
9871 - logging.debug("ModuleConfig; new _configs: %s", configs)
9872 - self._configs = configs
9873 -
9874 - def _determine_list(self, loop):
9875 - """Determine the ordered list from the config data and
9876 - the moule_runsIn value in the module_spec
9877 -
9878 - @returns: list of modules
9879 - """
9880 - lists = [c["scan_modules"].split() for c in self._configs]
9881 - stacked = self.modules_forced + stack_lists(lists)
9882 - mlist = []
9883 - try:
9884 - for mod in stacked:
9885 - logging.debug(
9886 - "ModuleConfig; checking loop %s, module: %s, in: %s",
9887 - loop,
9888 - mod,
9889 - self.controller.get_spec(mod, "module_runsIn"),
9890 - )
9891 - if loop in self.controller.get_spec(mod, "module_runsIn"):
9892 - mlist.append(mod)
9893 - except InvalidModuleName:
9894 - logging.error("ModuleConfig; unknown module: %s, skipping", mod)
9895 -
9896 - logging.debug("ModuleConfig; mlist: %s", mlist)
9897 - return mlist
9898
9899 diff --git a/repoman/lib/repoman/modules/scan/options/__init__.py b/repoman/lib/repoman/modules/scan/options/__init__.py
9900 deleted file mode 100644
9901 index ce57cbbfc..000000000
9902 --- a/repoman/lib/repoman/modules/scan/options/__init__.py
9903 +++ /dev/null
9904 @@ -1,28 +0,0 @@
9905 -# Copyright 2015-2021 Gentoo Authors
9906 -# Distributed under the terms of the GNU General Public License v2
9907 -
9908 -doc = """Options plug-in module for repoman.
9909 -Performs option related actions on ebuilds."""
9910 -__doc__ = doc[:]
9911 -
9912 -
9913 -module_spec = {
9914 - "name": "options",
9915 - "description": doc,
9916 - "provides": {
9917 - "options-module": {
9918 - "name": "options",
9919 - "sourcefile": "options",
9920 - "class": "Options",
9921 - "description": doc,
9922 - "functions": ["is_forced"],
9923 - "func_desc": {},
9924 - "mod_kwargs": [
9925 - "options",
9926 - ],
9927 - "func_kwargs": {},
9928 - "module_runsIn": ["ebuilds"],
9929 - },
9930 - },
9931 - "version": 1,
9932 -}
9933
9934 diff --git a/repoman/lib/repoman/modules/scan/options/options.py b/repoman/lib/repoman/modules/scan/options/options.py
9935 deleted file mode 100644
9936 index 2a16be7ef..000000000
9937 --- a/repoman/lib/repoman/modules/scan/options/options.py
9938 +++ /dev/null
9939 @@ -1,27 +0,0 @@
9940 -from repoman.modules.scan.scanbase import ScanBase
9941 -
9942 -
9943 -class Options(ScanBase):
9944 - def __init__(self, **kwargs):
9945 - """Class init function
9946 -
9947 - @param options: argparse options instance
9948 - """
9949 - self.options = kwargs.get("options")
9950 -
9951 - def is_forced(self, **kwargs):
9952 - """Simple boolean function to trigger a skip past some additional checks
9953 -
9954 - @returns: dictionary
9955 - """
9956 - if self.options.force:
9957 - # The dep_check() calls are the most expensive QA test. If --force
9958 - # is enabled, there's no point in wasting time on these since the
9959 - # user is intent on forcing the commit anyway.
9960 - return True
9961 - return False
9962 -
9963 - @property
9964 - def runInEbuilds(self):
9965 - """Ebuild level scans"""
9966 - return (True, [self.is_forced])
9967
9968 diff --git a/repoman/lib/repoman/modules/scan/scan.py b/repoman/lib/repoman/modules/scan/scan.py
9969 deleted file mode 100644
9970 index 30de50c35..000000000
9971 --- a/repoman/lib/repoman/modules/scan/scan.py
9972 +++ /dev/null
9973 @@ -1,67 +0,0 @@
9974 -# -*- coding:utf-8 -*-
9975 -
9976 -"""
9977 -moudules/scan.py
9978 -Module specific package scan list generator
9979 -"""
9980 -
9981 -import logging
9982 -import os
9983 -import sys
9984 -
9985 -from repoman.errors import caterror
9986 -
9987 -
9988 -def scan(repolevel, reposplit, startdir, categories, repo_settings):
9989 - """Generate a list of pkgs to scan
9990 -
9991 - @param repolevel: integer, number of subdirectories deep from the tree root
9992 - @param reposplit: list of the path subdirs
9993 - @param startdir: the top level directory to begin scanning from
9994 - @param categories: list of known categories
9995 - @param repo_settings: repository settings instance
9996 - @returns: scanlist, sorted list of pkgs to scan
9997 - """
9998 - scanlist = []
9999 - if repolevel == 2:
10000 - # we are inside a category directory
10001 - catdir = reposplit[-1]
10002 - if catdir not in categories:
10003 - caterror(catdir, repo_settings.repodir)
10004 - mydirlist = os.listdir(startdir)
10005 - for x in mydirlist:
10006 - if x == "CVS" or x.startswith("."):
10007 - continue
10008 - if os.path.isdir(startdir + "/" + x):
10009 - scanlist.append(catdir + "/" + x)
10010 - # repo_subdir = catdir + os.sep
10011 - elif repolevel == 1:
10012 - for x in categories:
10013 - if not os.path.isdir(startdir + "/" + x):
10014 - continue
10015 - for y in os.listdir(startdir + "/" + x):
10016 - if y == "CVS" or y.startswith("."):
10017 - continue
10018 - if os.path.isdir(startdir + "/" + x + "/" + y):
10019 - scanlist.append(x + "/" + y)
10020 - # repo_subdir = ""
10021 - elif repolevel == 3:
10022 - catdir = reposplit[-2]
10023 - if catdir not in categories:
10024 - caterror(catdir, repo_settings.repodir)
10025 - scanlist.append(catdir + "/" + reposplit[-1])
10026 - # repo_subdir = scanlist[-1] + os.sep
10027 - else:
10028 - msg = (
10029 - "Repoman is unable to determine PORTDIR or PORTDIR_OVERLAY"
10030 - + " from the current working directory"
10031 - )
10032 - logging.critical(msg)
10033 - sys.exit(1)
10034 -
10035 - # repo_subdir_len = len(repo_subdir)
10036 - scanlist.sort()
10037 -
10038 - logging.debug("Found the following packages to scan:\n%s" % "\n".join(scanlist))
10039 -
10040 - return scanlist
10041
10042 diff --git a/repoman/lib/repoman/modules/scan/scanbase.py b/repoman/lib/repoman/modules/scan/scanbase.py
10043 deleted file mode 100644
10044 index 5a7cd6219..000000000
10045 --- a/repoman/lib/repoman/modules/scan/scanbase.py
10046 +++ /dev/null
10047 @@ -1,79 +0,0 @@
10048 -# -*- coding:utf-8 -*-
10049 -
10050 -
10051 -class ScanBase:
10052 - """Skeleton class for performing a scan for one or more items
10053 - to check in a pkg directory or ebuild."""
10054 -
10055 - def __init__(self, **kwargs):
10056 - """Class init
10057 -
10058 - @param kwargs: an optional dictionary of common repository
10059 - wide parameters that may be required.
10060 - """
10061 - # Since no two checks are identicle as to what kwargs are needed,
10062 - # this does not define any from it here.
10063 - super(ScanBase, self).__init__()
10064 -
10065 - """ # sample check
10066 - def check_foo(self, **kwargs):
10067 - '''Class check skeleton function. Define this for a
10068 - specific check to perform.
10069 -
10070 - @param kwargs: an optional dictionary of dynamic package and or ebuild
10071 - specific data that may be required. Dynamic data can
10072 - vary depending what checks have run before it.
10073 - So execution order can be important.
10074 - '''
10075 - # Insert the code for the check here
10076 - # It should return a dictionary of at least {'continue': False}
10077 - # The continue attribute will default to False if not returned.
10078 - # This will allow the loop to continue with the next check in the list.
10079 - # Include any additional dynamic data that needs to be added or updated.
10080 - return False # used as a continue True/False value
10081 - """
10082 -
10083 - @property
10084 - def runInPkgs(self):
10085 - """Package level scans"""
10086 - # default no run (False) and empty list of functions to run
10087 - # override this method to define a function or
10088 - # functions to run in this process loop
10089 - # return a tuple of a boolean or boolean result and an ordered list
10090 - # of functions to run. ie: return (True, [self.check_foo])
10091 - # in this way, it can be dynamically determined at run time, if
10092 - # later stage scans are to be run.
10093 - # This class instance is maintaned for all stages, so data can be
10094 - # carried over from stage to stage
10095 - # next stage is runInEbuilds
10096 - return (False, [])
10097 -
10098 - @property
10099 - def runInEbuilds(self):
10100 - """Ebuild level scans"""
10101 - # default empty list of functions to run
10102 - # override this method to define a function or
10103 - # functions to run in this process loop
10104 - # return a tuple of a boolean or boolean result and an ordered list
10105 - # of functions to run. ie: return (True, [self.check_bar])
10106 - # in this way, it can be dynamically determined at run time, if
10107 - # later stage scans are to be run.
10108 - # This class instance is maintaned for all stages, so data can be
10109 - # carried over from stage to stage
10110 - # next stage is runInFinal
10111 - return (False, [])
10112 -
10113 - @property
10114 - def runInFinal(self):
10115 - """Final scans at the package level"""
10116 - # default empty list of functions to run
10117 - # override this method to define a function or
10118 - # functions to run in this process loop
10119 - # return a tuple of a boolean or boolean result and an ordered list
10120 - # of functions to run. ie: return (True, [self.check_baz])
10121 - # in this way, it can be dynamically determined at run time, if
10122 - # later stage scans are to be run.
10123 - # This class instance is maintaned for all stages, so data can be
10124 - # carried over from stage to stage
10125 - # runInFinal is currently the last stage of scans performed.
10126 - return (False, [])
10127
10128 diff --git a/repoman/lib/repoman/modules/vcs/None/__init__.py b/repoman/lib/repoman/modules/vcs/None/__init__.py
10129 deleted file mode 100644
10130 index dc9eb51ad..000000000
10131 --- a/repoman/lib/repoman/modules/vcs/None/__init__.py
10132 +++ /dev/null
10133 @@ -1,32 +0,0 @@
10134 -# Copyright 2014-2015 Gentoo Foundation
10135 -# Distributed under the terms of the GNU General Public License v2
10136 -
10137 -doc = """None (non vcs type) plug-in module for portage.
10138 -Performs various git actions and checks on repositories."""
10139 -__doc__ = doc[:]
10140 -
10141 -
10142 -module_spec = {
10143 - "name": "None",
10144 - "description": doc,
10145 - "provides": {
10146 - "None-module": {
10147 - "name": "None_status",
10148 - "sourcefile": "status",
10149 - "class": "Status",
10150 - "description": doc,
10151 - "functions": ["check", "supports_gpg_sign", "detect_conflicts"],
10152 - "func_desc": {},
10153 - "vcs_preserves_mtime": False,
10154 - "needs_keyword_expansion": False,
10155 - },
10156 - "None-changes": {
10157 - "name": "None_changes",
10158 - "sourcefile": "changes",
10159 - "class": "Changes",
10160 - "description": doc,
10161 - "functions": ["scan"],
10162 - "func_desc": {},
10163 - },
10164 - },
10165 -}
10166
10167 diff --git a/repoman/lib/repoman/modules/vcs/None/changes.py b/repoman/lib/repoman/modules/vcs/None/changes.py
10168 deleted file mode 100644
10169 index 4164c84bf..000000000
10170 --- a/repoman/lib/repoman/modules/vcs/None/changes.py
10171 +++ /dev/null
10172 @@ -1,50 +0,0 @@
10173 -"""
10174 -None module Changes class submodule
10175 -"""
10176 -
10177 -from repoman.modules.vcs.changes import ChangesBase
10178 -
10179 -
10180 -class Changes(ChangesBase):
10181 - """Class object to scan and hold the resultant data
10182 - for all changes to process.
10183 - """
10184 -
10185 - vcs = "None"
10186 -
10187 - def __init__(self, options, repo_settings):
10188 - """Class init
10189 -
10190 - @param options: the run time cli options
10191 - @param repo_settings: RepoSettings instance
10192 - """
10193 - super(Changes, self).__init__(options, repo_settings)
10194 -
10195 - def scan(self):
10196 - """VCS type scan function, looks for all detectable changes"""
10197 - pass
10198 -
10199 - def add_items(self, autoadd):
10200 - """Add files to the vcs's modified or new index
10201 -
10202 - @param autoadd: the files to add to the vcs modified index"""
10203 - pass
10204 -
10205 - def commit(self, myfiles, commitmessagefile):
10206 - """None commit function
10207 -
10208 - @param commitfiles: list of files to commit
10209 - @param commitmessagefile: file containing the commit message
10210 - @returns: The sub-command exit value or 0
10211 - """
10212 - commit_cmd = []
10213 - # substitute a bogus vcs value for pretend output
10214 - commit_cmd.append("pretend")
10215 - commit_cmd.extend(self.vcs_settings.vcs_global_opts)
10216 - commit_cmd.append("commit")
10217 - commit_cmd.extend(self.vcs_settings.vcs_local_opts)
10218 - commit_cmd.extend(["-F", commitmessagefile])
10219 - commit_cmd.extend(f.lstrip("./") for f in myfiles)
10220 -
10221 - print("(%s)" % (" ".join(commit_cmd),))
10222 - return 0
10223
10224 diff --git a/repoman/lib/repoman/modules/vcs/None/status.py b/repoman/lib/repoman/modules/vcs/None/status.py
10225 deleted file mode 100644
10226 index c5809bc9e..000000000
10227 --- a/repoman/lib/repoman/modules/vcs/None/status.py
10228 +++ /dev/null
10229 @@ -1,52 +0,0 @@
10230 -"""
10231 -None (non-VCS) module Status class submodule
10232 -"""
10233 -
10234 -
10235 -class Status:
10236 - """Performs status checks on the svn repository"""
10237 -
10238 - def __init__(self, qatracker, eadded):
10239 - """Class init
10240 -
10241 - @param qatracker: QATracker class instance
10242 - @param eadded: list
10243 - """
10244 - self.qatracker = qatracker
10245 - self.eadded = eadded
10246 -
10247 - def check(self, checkdir, checkdir_relative, xpkg):
10248 - """Perform the svn status check
10249 -
10250 - @param checkdir: string of the directory being checked
10251 - @param checkdir_relative: string of the relative directory being checked
10252 - @param xpkg: string of the package being checked
10253 - @returns: boolean
10254 - """
10255 - return True
10256 -
10257 - @staticmethod
10258 - def detect_conflicts(options):
10259 - """Are there any merge conflicts present in the VCS tracking system
10260 -
10261 - @param options: command line options
10262 - @returns: Boolean
10263 - """
10264 - return False
10265 -
10266 - @staticmethod
10267 - def supports_gpg_sign():
10268 - """Does this vcs system support gpg commit signatures
10269 -
10270 - @returns: Boolean
10271 - """
10272 - return False
10273 -
10274 - @staticmethod
10275 - def isVcsDir(dirname):
10276 - """Is the directory belong to the vcs system
10277 -
10278 - @param dirname: string, directory name
10279 - @returns: Boolean
10280 - """
10281 - return False
10282
10283 diff --git a/repoman/lib/repoman/modules/vcs/__init__.py b/repoman/lib/repoman/modules/vcs/__init__.py
10284 deleted file mode 100644
10285 index 85cc979c0..000000000
10286 --- a/repoman/lib/repoman/modules/vcs/__init__.py
10287 +++ /dev/null
10288 @@ -1,12 +0,0 @@
10289 -import os
10290 -from portage.module import Modules
10291 -
10292 -path = os.path.dirname(__file__)
10293 -# initial development debug info
10294 -# print("module path:", path)
10295 -
10296 -module_controller = Modules(path=path, namepath="repoman.modules.vcs")
10297 -
10298 -# initial development debug info
10299 -# print(module_controller.module_names)
10300 -module_names = module_controller.module_names[:]
10301
10302 diff --git a/repoman/lib/repoman/modules/vcs/bzr/__init__.py b/repoman/lib/repoman/modules/vcs/bzr/__init__.py
10303 deleted file mode 100644
10304 index 982017da6..000000000
10305 --- a/repoman/lib/repoman/modules/vcs/bzr/__init__.py
10306 +++ /dev/null
10307 @@ -1,32 +0,0 @@
10308 -# Copyright 2014-2015 Gentoo Foundation
10309 -# Distributed under the terms of the GNU General Public License v2
10310 -
10311 -doc = """Bazaar (bzr) plug-in module for portage.
10312 -Performs variaous Bazaar actions and checks on repositories."""
10313 -__doc__ = doc[:]
10314 -
10315 -
10316 -module_spec = {
10317 - "name": "bzr",
10318 - "description": doc,
10319 - "provides": {
10320 - "bzr-module": {
10321 - "name": "bzr_status",
10322 - "sourcefile": "status",
10323 - "class": "Status",
10324 - "description": doc,
10325 - "functions": ["check", "supports_gpg_sign", "detect_conflicts"],
10326 - "func_desc": {},
10327 - "vcs_preserves_mtime": True,
10328 - "needs_keyword_expansion": False,
10329 - },
10330 - "bzr-changes": {
10331 - "name": "bzr_changes",
10332 - "sourcefile": "changes",
10333 - "class": "Changes",
10334 - "description": doc,
10335 - "functions": ["scan"],
10336 - "func_desc": {},
10337 - },
10338 - },
10339 -}
10340
10341 diff --git a/repoman/lib/repoman/modules/vcs/bzr/changes.py b/repoman/lib/repoman/modules/vcs/bzr/changes.py
10342 deleted file mode 100644
10343 index 0366b3862..000000000
10344 --- a/repoman/lib/repoman/modules/vcs/bzr/changes.py
10345 +++ /dev/null
10346 @@ -1,77 +0,0 @@
10347 -"""
10348 -Bazaar module Changes class submodule
10349 -"""
10350 -
10351 -from repoman.modules.vcs.changes import ChangesBase
10352 -from repoman._subprocess import repoman_popen
10353 -from repoman._portage import portage # pylint: disable=unused-import
10354 -from portage import os
10355 -from portage.package.ebuild.digestgen import digestgen
10356 -
10357 -
10358 -class Changes(ChangesBase):
10359 - """Class object to scan and hold the resultant data
10360 - for all changes to process.
10361 - """
10362 -
10363 - vcs = "bzr"
10364 -
10365 - def __init__(self, options, repo_settings):
10366 - """Class init
10367 -
10368 - @param options: the run time cli options
10369 - @param repo_settings: RepoSettings instance
10370 - """
10371 - super(Changes, self).__init__(options, repo_settings)
10372 -
10373 - def _scan(self):
10374 - """VCS type scan function, looks for all detectable changes"""
10375 - with repoman_popen("bzr status -S .") as f:
10376 - bzrstatus = f.readlines()
10377 - self.changed = [
10378 - "./" + elem.split()[-1:][0].split("/")[-1:][0]
10379 - for elem in bzrstatus
10380 - if elem and elem[1:2] == "M"
10381 - ]
10382 - self.new = [
10383 - "./" + elem.split()[-1:][0].split("/")[-1:][0]
10384 - for elem in bzrstatus
10385 - if elem and (elem[1:2] == "NK" or elem[0:1] == "R")
10386 - ]
10387 - self.removed = [
10388 - "./" + elem.split()[-3:-2][0].split("/")[-1:][0]
10389 - for elem in bzrstatus
10390 - if elem and (elem[1:2] == "K" or elem[0:1] == "R")
10391 - ]
10392 - self.bzrstatus = bzrstatus
10393 - # Bazaar expands nothing.
10394 -
10395 - @property
10396 - def unadded(self):
10397 - """Bazzar method of getting the unadded files in the repository"""
10398 - if self._unadded is not None:
10399 - return self._unadded
10400 - self._unadded = [
10401 - "./" + elem.rstrip().split()[1].split("/")[-1:][0]
10402 - for elem in self.bzrstatus
10403 - if elem.startswith("?") or elem[0:2] == " D"
10404 - ]
10405 - return self._unadded
10406 -
10407 - def digest_regen(
10408 - self, updates, removed, manifests, scanner, broken_changelog_manifests
10409 - ):
10410 - """Regenerate manifests
10411 -
10412 - @param updates: updated files
10413 - @param removed: removed files
10414 - @param manifests: Manifest files
10415 - @param scanner: The repoman.scanner.Scanner instance
10416 - @param broken_changelog_manifests: broken changelog manifests
10417 - """
10418 - if broken_changelog_manifests:
10419 - for x in broken_changelog_manifests:
10420 - self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
10421 - digestgen(
10422 - mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb
10423 - )
10424
10425 diff --git a/repoman/lib/repoman/modules/vcs/bzr/status.py b/repoman/lib/repoman/modules/vcs/bzr/status.py
10426 deleted file mode 100644
10427 index 5ca18c4f6..000000000
10428 --- a/repoman/lib/repoman/modules/vcs/bzr/status.py
10429 +++ /dev/null
10430 @@ -1,72 +0,0 @@
10431 -"""
10432 -Bazaar module Status class submodule
10433 -"""
10434 -
10435 -from repoman._portage import portage
10436 -from portage import os
10437 -
10438 -# pylint: disable=ungrouped-imports
10439 -from repoman._subprocess import repoman_popen
10440 -
10441 -
10442 -class Status:
10443 - """Performs status checks on the svn repository"""
10444 -
10445 - def __init__(self, qatracker, eadded):
10446 - """Class init
10447 -
10448 - @param qatracker: QATracker class instance
10449 - @param eadded: list
10450 - """
10451 - self.qatracker = qatracker
10452 - self.eadded = eadded
10453 -
10454 - def check(self, checkdir, checkdir_relative, xpkg):
10455 - """Perform the svn status check
10456 -
10457 - @param checkdir: string of the directory being checked
10458 - @param checkdir_relative: string of the relative directory being checked
10459 - @param xpkg: string of the package being checked
10460 - @returns: boolean
10461 - """
10462 - try:
10463 - myf = repoman_popen(
10464 - "bzr ls -v --kind=file " + portage._shell_quote(checkdir)
10465 - )
10466 - myl = myf.readlines()
10467 - myf.close()
10468 - except IOError:
10469 - raise
10470 - for l in myl:
10471 - if l[1:2] == "?":
10472 - continue
10473 - l = l.split()[-1]
10474 - if l[-7:] == ".ebuild":
10475 - self.eadded.append(os.path.basename(l[:-7]))
10476 - return True
10477 -
10478 - @staticmethod
10479 - def detect_conflicts(options):
10480 - """Are there any merge conflicts present in the VCS tracking system
10481 -
10482 - @param options: command line options
10483 - @returns: Boolean
10484 - """
10485 - return False
10486 -
10487 - @staticmethod
10488 - def supports_gpg_sign():
10489 - """Does this vcs system support gpg commit signatures
10490 -
10491 - @returns: Boolean
10492 - """
10493 - return False
10494 -
10495 - @staticmethod
10496 - def isVcsDir(dirname):
10497 - """Does the directory belong to the vcs system
10498 -
10499 - @param dirname: string, directory name
10500 - @returns: Boolean
10501 - """
10502 - return dirname in [".bzr"]
10503
10504 diff --git a/repoman/lib/repoman/modules/vcs/changes.py b/repoman/lib/repoman/modules/vcs/changes.py
10505 deleted file mode 100644
10506 index c1c7b0909..000000000
10507 --- a/repoman/lib/repoman/modules/vcs/changes.py
10508 +++ /dev/null
10509 @@ -1,170 +0,0 @@
10510 -"""
10511 -Base Changes class
10512 -"""
10513 -
10514 -import logging
10515 -import os
10516 -import subprocess
10517 -import sys
10518 -from itertools import chain
10519 -
10520 -from repoman._portage import portage
10521 -from portage import _unicode_encode
10522 -from portage.process import spawn
10523 -
10524 -
10525 -class ChangesBase:
10526 - """Base Class object to scan and hold the resultant data
10527 - for all changes to process.
10528 - """
10529 -
10530 - vcs = "None"
10531 -
10532 - def __init__(self, options, repo_settings):
10533 - """Class init function
10534 -
10535 - @param options: the run time cli options
10536 - @param repo_settings: RepoSettings instance
10537 - """
10538 - self.options = options
10539 - self.repo_settings = repo_settings
10540 - self.repoman_settings = repo_settings.repoman_settings
10541 - self.vcs_settings = repo_settings.vcs_settings
10542 - self._reset()
10543 -
10544 - def _reset(self):
10545 - """Reset the class variables for a new run"""
10546 - self.new_ebuilds = set()
10547 - self.ebuilds = set()
10548 - self.changelogs = set()
10549 - self.changed = []
10550 - self.new = []
10551 - self.removed = []
10552 - self.no_expansion = set()
10553 - self._expansion = None
10554 - self._deleted = None
10555 - self._unadded = None
10556 -
10557 - def scan(self):
10558 - """Scan the vcs for detectable changes.
10559 -
10560 - base method which calls the subclassing VCS module's _scan()
10561 - then updates some classwide variables.
10562 - """
10563 - self._reset()
10564 -
10565 - if self.vcs:
10566 - self._scan()
10567 - self.new_ebuilds.update(x for x in self.new if x.endswith(".ebuild"))
10568 - self.ebuilds.update(x for x in self.changed if x.endswith(".ebuild"))
10569 - self.changelogs.update(
10570 - x
10571 - for x in chain(self.changed, self.new)
10572 - if os.path.basename(x) == "ChangeLog"
10573 - )
10574 -
10575 - def _scan(self):
10576 - """Placeholder for subclassing"""
10577 - pass
10578 -
10579 - @property
10580 - def has_deleted(self):
10581 - """Placeholder for VCS that requires manual deletion of files"""
10582 - return self.deleted != []
10583 -
10584 - @property
10585 - def has_changes(self):
10586 - """Placeholder for VCS repo common has changes result"""
10587 - changed = self.changed or self.new or self.removed or self.deleted
10588 - return changed != []
10589 -
10590 - @property
10591 - def unadded(self):
10592 - """Override this function as needed"""
10593 - return []
10594 -
10595 - @property
10596 - def deleted(self):
10597 - """Override this function as needed"""
10598 - return []
10599 -
10600 - @property
10601 - def expansion(self):
10602 - """Override this function as needed"""
10603 - return {}
10604 -
10605 - def thick_manifest(self, updates, headers, no_expansion, expansion):
10606 - """Create a thick manifest
10607 -
10608 - @param updates:
10609 - @param headers:
10610 - @param no_expansion:
10611 - @param expansion:
10612 - """
10613 - pass
10614 -
10615 - def digest_regen(
10616 - self, updates, removed, manifests, scanner, broken_changelog_manifests
10617 - ):
10618 - """Regenerate manifests
10619 -
10620 - @param updates: updated files
10621 - @param removed: removed files
10622 - @param manifests: Manifest files
10623 - @param scanner: The repoman.scanner.Scanner instance
10624 - @param broken_changelog_manifests: broken changelog manifests
10625 - """
10626 - pass
10627 -
10628 - @staticmethod
10629 - def clear_attic(headers):
10630 - """Old CVS leftover
10631 -
10632 - @param headers: file headers"""
10633 - pass
10634 -
10635 - def update_index(self, mymanifests, myupdates):
10636 - """Update the vcs's modified index if it is needed
10637 -
10638 - @param mymanifests: manifest files updated
10639 - @param myupdates: other files updated"""
10640 - pass
10641 -
10642 - def add_items(self, autoadd):
10643 - """Add files to the vcs's modified or new index
10644 -
10645 - @param autoadd: the files to add to the vcs modified index"""
10646 - add_cmd = [self.vcs, "add"]
10647 - add_cmd += autoadd
10648 - if self.options.pretend:
10649 - portage.writemsg_stdout("(%s)\n" % " ".join(add_cmd), noiselevel=-1)
10650 - else:
10651 - add_cmd = [_unicode_encode(arg) for arg in add_cmd]
10652 - retcode = subprocess.call(add_cmd)
10653 - if retcode != os.EX_OK:
10654 - logging.error(
10655 - "Exiting on %s error code: %s\n", self.vcs_settings.vcs, retcode
10656 - )
10657 - sys.exit(retcode)
10658 -
10659 - def commit(self, commitfiles, commitmessagefile):
10660 - """Common generic commit function
10661 -
10662 - @param commitfiles: list of files to commit
10663 - @param commitmessagefile: file containing the commit message
10664 - @returns: The sub-command exit value or 0
10665 - """
10666 - commit_cmd = []
10667 - commit_cmd.append(self.vcs)
10668 - commit_cmd.extend(self.vcs_settings.vcs_global_opts)
10669 - commit_cmd.append("commit")
10670 - commit_cmd.extend(self.vcs_settings.vcs_local_opts)
10671 - commit_cmd.extend(["-F", commitmessagefile])
10672 - commit_cmd.extend(f.lstrip("./") for f in commitfiles)
10673 -
10674 - if self.options.pretend:
10675 - print("(%s)" % (" ".join(commit_cmd),))
10676 - return 0
10677 - else:
10678 - retval = spawn(commit_cmd, env=self.repo_settings.commit_env)
10679 - return retval
10680
10681 diff --git a/repoman/lib/repoman/modules/vcs/cvs/__init__.py b/repoman/lib/repoman/modules/vcs/cvs/__init__.py
10682 deleted file mode 100644
10683 index f71f806fb..000000000
10684 --- a/repoman/lib/repoman/modules/vcs/cvs/__init__.py
10685 +++ /dev/null
10686 @@ -1,32 +0,0 @@
10687 -# Copyright 2014-2015 Gentoo Foundation
10688 -# Distributed under the terms of the GNU General Public License v2
10689 -
10690 -doc = """CVS (cvs) plug-in module for portage.
10691 -Performs variaous CVS actions and checks on repositories."""
10692 -__doc__ = doc[:]
10693 -
10694 -
10695 -module_spec = {
10696 - "name": "cvs",
10697 - "description": doc,
10698 - "provides": {
10699 - "cvs-status": {
10700 - "name": "cvs_status",
10701 - "sourcefile": "status",
10702 - "class": "Status",
10703 - "description": doc,
10704 - "functions": ["check", "supports_gpg_sign", "detect_conflicts"],
10705 - "func_desc": {},
10706 - "vcs_preserves_mtime": True,
10707 - "needs_keyword_expansion": True,
10708 - },
10709 - "cvs-changes": {
10710 - "name": "cvs_changes",
10711 - "sourcefile": "changes",
10712 - "class": "Changes",
10713 - "description": doc,
10714 - "functions": ["scan"],
10715 - "func_desc": {},
10716 - },
10717 - },
10718 -}
10719
10720 diff --git a/repoman/lib/repoman/modules/vcs/cvs/changes.py b/repoman/lib/repoman/modules/vcs/cvs/changes.py
10721 deleted file mode 100644
10722 index be382f291..000000000
10723 --- a/repoman/lib/repoman/modules/vcs/cvs/changes.py
10724 +++ /dev/null
10725 @@ -1,134 +0,0 @@
10726 -"""
10727 -CVS module Changes class submodule
10728 -"""
10729 -
10730 -import re
10731 -from itertools import chain
10732 -
10733 -from repoman._portage import portage
10734 -from repoman.modules.vcs.changes import ChangesBase
10735 -from repoman.modules.vcs.vcs import vcs_files_to_cps
10736 -from repoman._subprocess import repoman_getstatusoutput
10737 -
10738 -from portage import _encodings, _unicode_encode
10739 -from portage import cvstree, os
10740 -from portage.output import green
10741 -from portage.package.ebuild.digestgen import digestgen
10742 -
10743 -
10744 -class Changes(ChangesBase):
10745 - """Class object to scan and hold the resultant data
10746 - for all changes to process.
10747 - """
10748 -
10749 - vcs = "cvs"
10750 -
10751 - def __init__(self, options, repo_settings):
10752 - """Class init
10753 -
10754 - @param options: the run time cli options
10755 - @param repo_settings: RepoSettings instance
10756 - """
10757 - super(Changes, self).__init__(options, repo_settings)
10758 - self._tree = None
10759 -
10760 - def _scan(self):
10761 - """VCS type scan function, looks for all detectable changes"""
10762 - self._tree = portage.cvstree.getentries("./", recursive=1)
10763 - self.changed = cvstree.findchanged(self._tree, recursive=1, basedir="./")
10764 - self.new = cvstree.findnew(self._tree, recursive=1, basedir="./")
10765 - self.removed = cvstree.findremoved(self._tree, recursive=1, basedir="./")
10766 - bin_blob_pattern = re.compile("^-kb$")
10767 - self.no_expansion = set(
10768 - portage.cvstree.findoption(
10769 - self._tree, bin_blob_pattern, recursive=1, basedir="./"
10770 - )
10771 - )
10772 -
10773 - @property
10774 - def unadded(self):
10775 - """VCS method of getting the unadded files in the repository"""
10776 - if self._unadded is not None:
10777 - return self._unadded
10778 - self._unadded = portage.cvstree.findunadded(
10779 - self._tree, recursive=1, basedir="./"
10780 - )
10781 - return self._unadded
10782 -
10783 - @staticmethod
10784 - def clear_attic(headers):
10785 - """Clear the attic (inactive files)
10786 -
10787 - @param headers: file headers
10788 - """
10789 - cvs_header_re = re.compile(rb"^#\s*\$Header.*\$$")
10790 - attic_str = b"/Attic/"
10791 - attic_replace = b"/"
10792 - for x in headers:
10793 - f = open(
10794 - _unicode_encode(x, encoding=_encodings["fs"], errors="strict"),
10795 - mode="rb",
10796 - )
10797 - mylines = f.readlines()
10798 - f.close()
10799 - modified = False
10800 - for i, line in enumerate(mylines):
10801 - if cvs_header_re.match(line) is not None and attic_str in line:
10802 - mylines[i] = line.replace(attic_str, attic_replace)
10803 - modified = True
10804 - if modified:
10805 - portage.util.write_atomic(x, b"".join(mylines), mode="wb")
10806 -
10807 - def thick_manifest(self, updates, headers, no_expansion, expansion):
10808 - """Create a thick manifest
10809 -
10810 - @param updates:
10811 - @param headers:
10812 - @param no_expansion:
10813 - @param expansion:
10814 - """
10815 - headerstring = r"'\$(Header|Id).*\$'"
10816 -
10817 - for _file in updates:
10818 -
10819 - # for CVS, no_expansion contains files that are excluded from expansion
10820 - if _file in no_expansion:
10821 - continue
10822 -
10823 - _out = repoman_getstatusoutput(
10824 - "egrep -q %s %s" % (headerstring, portage._shell_quote(_file))
10825 - )
10826 - if _out[0] == 0:
10827 - headers.append(_file)
10828 -
10829 - print("%s have headers that will change." % green(str(len(headers))))
10830 - print(
10831 - "* Files with headers will"
10832 - " cause the manifests to be changed and committed separately."
10833 - )
10834 -
10835 - def digest_regen(
10836 - self, updates, removed, manifests, scanner, broken_changelog_manifests
10837 - ):
10838 - """Regenerate manifests
10839 -
10840 - @param updates: updated files
10841 - @param removed: removed files
10842 - @param manifests: Manifest files
10843 - @param scanner: The repoman.scanner.Scanner instance
10844 - @param broken_changelog_manifests: broken changelog manifests
10845 - """
10846 - if updates or removed:
10847 - for x in sorted(
10848 - vcs_files_to_cps(
10849 - chain(updates, removed, manifests),
10850 - self.repo_settings.repodir,
10851 - scanner.repolevel,
10852 - scanner.reposplit,
10853 - scanner.categories,
10854 - )
10855 - ):
10856 - self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
10857 - digestgen(
10858 - mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb
10859 - )
10860
10861 diff --git a/repoman/lib/repoman/modules/vcs/cvs/status.py b/repoman/lib/repoman/modules/vcs/cvs/status.py
10862 deleted file mode 100644
10863 index 0d131c75a..000000000
10864 --- a/repoman/lib/repoman/modules/vcs/cvs/status.py
10865 +++ /dev/null
10866 @@ -1,134 +0,0 @@
10867 -"""
10868 -CVS module Status class submodule
10869 -"""
10870 -
10871 -import logging
10872 -import subprocess
10873 -import sys
10874 -
10875 -from repoman._portage import portage # pylint: disable=unused-import
10876 -from portage import os
10877 -from portage.const import BASH_BINARY
10878 -from portage.output import red, green
10879 -from portage import _unicode_encode, _unicode_decode
10880 -
10881 -
10882 -class Status:
10883 - """Performs status checks on the svn repository"""
10884 -
10885 - def __init__(self, qatracker, eadded):
10886 - """Class init
10887 -
10888 - @param qatracker: QATracker class instance
10889 - @param eadded: list
10890 - """
10891 - self.qatracker = qatracker
10892 - self.eadded = eadded
10893 -
10894 - def check(self, checkdir, checkdir_relative, xpkg):
10895 - """Perform the svn status check
10896 -
10897 - @param checkdir: string of the directory being checked
10898 - @param checkdir_relative: string of the relative directory being checked
10899 - @param xpkg: string of the package being checked
10900 - @returns: boolean
10901 - """
10902 - try:
10903 - myf = open(checkdir + "/CVS/Entries", "r")
10904 - myl = myf.readlines()
10905 - myf.close()
10906 - except IOError:
10907 - self.qatracker.add_error("CVS/Entries.IO_error", checkdir + "/CVS/Entries")
10908 - return True
10909 - for l in myl:
10910 - if l[0] != "/":
10911 - continue
10912 - splitl = l[1:].split("/")
10913 - if not len(splitl):
10914 - continue
10915 - if splitl[0][-7:] == ".ebuild":
10916 - self.eadded.append(splitl[0][:-7])
10917 - return True
10918 -
10919 - @staticmethod
10920 - def detect_conflicts(options):
10921 - """Determine if the checkout has cvs conflicts.
10922 -
10923 - TODO(antarus): Also this should probably not call sys.exit() as
10924 - repoman is run on >1 packages and one failure should not cause
10925 - subsequent packages to fail.
10926 -
10927 - Returns:
10928 - None (calls sys.exit on fatal problems)
10929 - """
10930 -
10931 - cmd = (
10932 - r"cvs -n up 2>/dev/null | "
10933 - r"egrep '^[^\?] .*' | "
10934 - r"egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'"
10935 - )
10936 - msg = "Performing a %s with a little magic grep to check for updates." % green(
10937 - "cvs -n up"
10938 - )
10939 -
10940 - logging.info(msg)
10941 - # Use Popen instead of getstatusoutput(), in order to avoid
10942 - # unicode handling problems (see bug #310789).
10943 - args = [BASH_BINARY, "-c", cmd]
10944 - args = [_unicode_encode(x) for x in args]
10945 - proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
10946 - out = _unicode_decode(proc.communicate()[0])
10947 - proc.wait()
10948 - mylines = out.splitlines()
10949 - myupdates = []
10950 - for line in mylines:
10951 - if not line:
10952 - continue
10953 -
10954 - # [ ] Unmodified (SVN) [U] Updates [P] Patches
10955 - # [M] Modified [A] Added [R] Removed / Replaced
10956 - # [D] Deleted
10957 - if line[0] not in " UPMARD":
10958 - # Stray Manifest is fine, we will readd it anyway.
10959 - if line[0] == "?" and line[1:].lstrip() == "Manifest":
10960 - continue
10961 - logging.error(
10962 - red(
10963 - "!!! Please fix the following issues reported "
10964 - "from cvs: %s" % green("(U,P,M,A,R,D are ok)")
10965 - )
10966 - )
10967 - logging.error(red("!!! Note: This is a pretend/no-modify pass..."))
10968 - logging.error(out)
10969 - sys.exit(1)
10970 - elif line[0] in "UP":
10971 - myupdates.append(line[2:])
10972 -
10973 - if myupdates:
10974 - logging.info(green("Fetching trivial updates..."))
10975 - if options.pretend:
10976 - logging.info("(cvs update " + " ".join(myupdates) + ")")
10977 - retval = os.EX_OK
10978 - else:
10979 - retval = os.system("cvs update " + " ".join(myupdates))
10980 - if retval != os.EX_OK:
10981 - logging.fatal("!!! cvs exited with an error. Terminating.")
10982 - sys.exit(retval)
10983 - return False
10984 -
10985 - @staticmethod
10986 - def supports_gpg_sign():
10987 - """Does this vcs system support gpg commit signatures
10988 -
10989 - @returns: Boolean
10990 - """
10991 - return False
10992 -
10993 - @staticmethod
10994 - def isVcsDir(dirname):
10995 - """Does the directory belong to the vcs system
10996 -
10997 - @param dirname: string, directory name
10998 - @returns: Boolean
10999 - """
11000 - return dirname in ["CVS"]
11001
11002 diff --git a/repoman/lib/repoman/modules/vcs/git/__init__.py b/repoman/lib/repoman/modules/vcs/git/__init__.py
11003 deleted file mode 100644
11004 index c3005fc41..000000000
11005 --- a/repoman/lib/repoman/modules/vcs/git/__init__.py
11006 +++ /dev/null
11007 @@ -1,32 +0,0 @@
11008 -# Copyright 2014-2015 Gentoo Foundation
11009 -# Distributed under the terms of the GNU General Public License v2
11010 -
11011 -doc = """Git (git) plug-in module for portage.
11012 -Performs variaous git actions and checks on repositories."""
11013 -__doc__ = doc[:]
11014 -
11015 -
11016 -module_spec = {
11017 - "name": "git",
11018 - "description": doc,
11019 - "provides": {
11020 - "git-module": {
11021 - "name": "git_status",
11022 - "sourcefile": "status",
11023 - "class": "Status",
11024 - "description": doc,
11025 - "functions": ["check", "supports_gpg_sign", "detect_conflicts"],
11026 - "func_desc": {},
11027 - "vcs_preserves_mtime": False,
11028 - "needs_keyword_expansion": False,
11029 - },
11030 - "git-changes": {
11031 - "name": "git_changes",
11032 - "sourcefile": "changes",
11033 - "class": "Changes",
11034 - "description": doc,
11035 - "functions": ["scan"],
11036 - "func_desc": {},
11037 - },
11038 - },
11039 -}
11040
11041 diff --git a/repoman/lib/repoman/modules/vcs/git/changes.py b/repoman/lib/repoman/modules/vcs/git/changes.py
11042 deleted file mode 100644
11043 index 3430cf3ec..000000000
11044 --- a/repoman/lib/repoman/modules/vcs/git/changes.py
11045 +++ /dev/null
11046 @@ -1,145 +0,0 @@
11047 -"""
11048 -Git module Changes class submodule
11049 -"""
11050 -
11051 -import logging
11052 -import sys
11053 -
11054 -from repoman._portage import portage # pylint: disable=unused-import
11055 -from repoman.modules.vcs.changes import ChangesBase
11056 -from repoman._subprocess import repoman_popen
11057 -
11058 -from portage import os
11059 -from portage.package.ebuild.digestgen import digestgen
11060 -from portage.process import spawn
11061 -from portage.util import writemsg_level
11062 -
11063 -
11064 -class Changes(ChangesBase):
11065 - """Class object to scan and hold the resultant data
11066 - for all changes to process.
11067 - """
11068 -
11069 - vcs = "git"
11070 -
11071 - def __init__(self, options, repo_settings):
11072 - """Class init
11073 -
11074 - @param options: the run time cli options
11075 - @param repo_settings: RepoSettings instance
11076 - """
11077 - super(Changes, self).__init__(options, repo_settings)
11078 -
11079 - def _scan(self, _reindex=None):
11080 - """
11081 - VCS type scan function, looks for all detectable changes
11082 -
11083 - @param _reindex: ensure that the git index reflects the state on
11084 - disk for files returned by git diff-index (this parameter is
11085 - used in recursive calls and it's not intended to be used for
11086 - any other reason)
11087 - @type _reindex: bool
11088 - """
11089 - # Automatically reindex for commit mode, but not for other modes
11090 - # were the user might not want changes to be staged in the index.
11091 - if _reindex is None and self.options.mode == "commit":
11092 - _reindex = True
11093 -
11094 - with repoman_popen(
11095 - "git diff-index --name-only " "--relative --diff-filter=M HEAD"
11096 - ) as f:
11097 - changed = f.readlines()
11098 - self.changed = ["./" + elem[:-1] for elem in changed]
11099 - del changed
11100 -
11101 - with repoman_popen(
11102 - "git diff-index --name-only " "--relative --diff-filter=A HEAD"
11103 - ) as f:
11104 - new = f.readlines()
11105 - self.new = ["./" + elem[:-1] for elem in new]
11106 - del new
11107 -
11108 - with repoman_popen(
11109 - "git diff-index --name-only " "--relative --diff-filter=D HEAD"
11110 - ) as f:
11111 - removed = f.readlines()
11112 - self.removed = ["./" + elem[:-1] for elem in removed]
11113 - del removed
11114 - if _reindex and (self.changed or self.new or self.removed):
11115 - self.update_index([], self.changed + self.new + self.removed)
11116 - self._scan(_reindex=False)
11117 -
11118 - @property
11119 - def unadded(self):
11120 - """VCS method of getting the unadded files in the repository"""
11121 - if self._unadded is not None:
11122 - return self._unadded
11123 - # get list of files not under version control or missing
11124 - with repoman_popen("git ls-files --others") as f:
11125 - unadded = f.readlines()
11126 - self._unadded = ["./" + elem[:-1] for elem in unadded]
11127 - del unadded
11128 - return self._unadded
11129 -
11130 - def digest_regen(
11131 - self, updates, removed, manifests, scanner, broken_changelog_manifests
11132 - ):
11133 - """Regenerate manifests
11134 -
11135 - @param updates: updated files
11136 - @param removed: removed files
11137 - @param manifests: Manifest files
11138 - @param scanner: The repoman.scanner.Scanner instance
11139 - @param broken_changelog_manifests: broken changelog manifests
11140 - """
11141 - if broken_changelog_manifests:
11142 - for x in broken_changelog_manifests:
11143 - self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
11144 - digestgen(
11145 - mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb
11146 - )
11147 -
11148 - def update_index(self, mymanifests, myupdates):
11149 - """Update the vcs's modified index if it is needed
11150 -
11151 - @param mymanifests: manifest files updated
11152 - @param myupdates: other files updated"""
11153 - # It's not safe to use the git commit -a option since there might
11154 - # be some modified files elsewhere in the working tree that the
11155 - # user doesn't want to commit. Therefore, call git update-index
11156 - # in order to ensure that the index is updated with the latest
11157 - # versions of all new and modified files in the relevant portion
11158 - # of the working tree.
11159 - myfiles = mymanifests + myupdates
11160 - myfiles.sort()
11161 - update_index_cmd = ["git", "update-index", "--add", "--remove"]
11162 - update_index_cmd.extend(f.lstrip("./") for f in myfiles)
11163 - if self.options.pretend:
11164 - print("(%s)" % (" ".join(update_index_cmd),))
11165 - else:
11166 - retval = spawn(update_index_cmd, env=os.environ)
11167 - if retval != os.EX_OK:
11168 - writemsg_level(
11169 - "!!! Exiting on %s (shell) "
11170 - "error code: %s\n" % (self.vcs_settings.vcs, retval),
11171 - level=logging.ERROR,
11172 - noiselevel=-1,
11173 - )
11174 - sys.exit(retval)
11175 -
11176 - def commit(self, myfiles, commitmessagefile):
11177 - """Git commit function
11178 -
11179 - @param commitfiles: list of files to commit
11180 - @param commitmessagefile: file containing the commit message
11181 - @returns: The sub-command exit value or 0
11182 - """
11183 - retval = super(Changes, self).commit(myfiles, commitmessagefile)
11184 - if retval != os.EX_OK:
11185 - if (
11186 - self.repo_settings.repo_config.sign_commit
11187 - and not self.vcs_settings.status.supports_gpg_sign()
11188 - ):
11189 - # Inform user that newer git is needed (bug #403323).
11190 - logging.error("Git >=1.7.9 is required for signed commits!")
11191 - return retval
11192
11193 diff --git a/repoman/lib/repoman/modules/vcs/git/status.py b/repoman/lib/repoman/modules/vcs/git/status.py
11194 deleted file mode 100644
11195 index ec2e3a655..000000000
11196 --- a/repoman/lib/repoman/modules/vcs/git/status.py
11197 +++ /dev/null
11198 @@ -1,80 +0,0 @@
11199 -"""
11200 -Git module Status class submodule
11201 -"""
11202 -
11203 -import re
11204 -
11205 -from repoman._portage import portage
11206 -from portage import os
11207 -
11208 -# pylint: disable=ungrouped-imports
11209 -from repoman._subprocess import repoman_popen, repoman_getstatusoutput
11210 -
11211 -
11212 -class Status:
11213 - """Performs status checks on the git repository"""
11214 -
11215 - def __init__(self, qatracker, eadded):
11216 - """Class init
11217 -
11218 - @param qatracker: QATracker class instance
11219 - @param eadded: list
11220 - """
11221 - self.qatracker = qatracker
11222 - self.eadded = eadded
11223 -
11224 - def check(self, checkdir, checkdir_relative, xpkg):
11225 - """Perform the git status check
11226 -
11227 - @param checkdir: string of the directory being checked
11228 - @param checkdir_relative: string of the relative directory being checked
11229 - @param xpkg: string of the package being checked
11230 - @returns: boolean
11231 - """
11232 - with repoman_popen(
11233 - "git ls-files --others %s" % (portage._shell_quote(checkdir_relative),)
11234 - ) as myf:
11235 - for l in myf:
11236 - if l[:-1][-7:] == ".ebuild":
11237 - self.qatracker.add_error(
11238 - "ebuild.notadded", os.path.join(xpkg, os.path.basename(l[:-1]))
11239 - )
11240 - return True
11241 -
11242 - @staticmethod
11243 - def detect_conflicts(options):
11244 - """Are there any merge conflicts present in the VCS tracking system
11245 -
11246 - @param options: command line options
11247 - @returns: Boolean
11248 - """
11249 - return False
11250 -
11251 - @staticmethod
11252 - def supports_gpg_sign():
11253 - """Does this vcs system support gpg commit signatures
11254 -
11255 - @returns: Boolean
11256 - """
11257 - status, cmd_output = repoman_getstatusoutput("git --version")
11258 - cmd_output = cmd_output.split()
11259 - if cmd_output:
11260 - version = re.match(r"^(\d+)\.(\d+)\.(\d+)", cmd_output[-1])
11261 - if version is not None:
11262 - version = [int(x) for x in version.groups()]
11263 - if (
11264 - version[0] > 1
11265 - or (version[0] == 1 and version[1] > 7)
11266 - or (version[0] == 1 and version[1] == 7 and version[2] >= 9)
11267 - ):
11268 - return True
11269 - return False
11270 -
11271 - @staticmethod
11272 - def isVcsDir(dirname):
11273 - """Does the directory belong to the vcs system
11274 -
11275 - @param dirname: string, directory name
11276 - @returns: Boolean
11277 - """
11278 - return dirname in [".git"]
11279
11280 diff --git a/repoman/lib/repoman/modules/vcs/hg/__init__.py b/repoman/lib/repoman/modules/vcs/hg/__init__.py
11281 deleted file mode 100644
11282 index 4b96b04c8..000000000
11283 --- a/repoman/lib/repoman/modules/vcs/hg/__init__.py
11284 +++ /dev/null
11285 @@ -1,32 +0,0 @@
11286 -# Copyright 2014-2015 Gentoo Foundation
11287 -# Distributed under the terms of the GNU General Public License v2
11288 -
11289 -doc = """Mercurial (hg) plug-in module for portage.
11290 -Performs variaous mercurial actions and checks on repositories."""
11291 -__doc__ = doc[:]
11292 -
11293 -
11294 -module_spec = {
11295 - "name": "hg",
11296 - "description": doc,
11297 - "provides": {
11298 - "hg-module": {
11299 - "name": "hg_status",
11300 - "sourcefile": "status",
11301 - "class": "Status",
11302 - "description": doc,
11303 - "functions": ["check", "supports_gpg_sign", "detect_conflicts"],
11304 - "func_desc": {},
11305 - "vcs_preserves_mtime": False,
11306 - "needs_keyword_expansion": False,
11307 - },
11308 - "hg-changes": {
11309 - "name": "hg_changes",
11310 - "sourcefile": "changes",
11311 - "class": "Changes",
11312 - "description": doc,
11313 - "functions": ["scan"],
11314 - "func_desc": {},
11315 - },
11316 - },
11317 -}
11318
11319 diff --git a/repoman/lib/repoman/modules/vcs/hg/changes.py b/repoman/lib/repoman/modules/vcs/hg/changes.py
11320 deleted file mode 100644
11321 index 3ce1763b7..000000000
11322 --- a/repoman/lib/repoman/modules/vcs/hg/changes.py
11323 +++ /dev/null
11324 @@ -1,109 +0,0 @@
11325 -"""
11326 -Mercurial module Changes class submodule
11327 -"""
11328 -
11329 -from repoman._portage import portage # pylint: disable=unused-import
11330 -from repoman.modules.vcs.changes import ChangesBase
11331 -from repoman._subprocess import repoman_popen
11332 -
11333 -from portage import os
11334 -from portage.package.ebuild.digestgen import digestgen
11335 -from portage.process import spawn
11336 -
11337 -
11338 -class Changes(ChangesBase):
11339 - """Class object to scan and hold the resultant data
11340 - for all changes to process.
11341 - """
11342 -
11343 - vcs = "hg"
11344 -
11345 - def __init__(self, options, repo_settings):
11346 - """Class init
11347 -
11348 - @param options: the run time cli options
11349 - @param repo_settings: RepoSettings instance
11350 - """
11351 - super(Changes, self).__init__(options, repo_settings)
11352 -
11353 - def _scan(self):
11354 - """VCS type scan function, looks for all detectable changes"""
11355 - with repoman_popen("hg status --no-status --modified .") as f:
11356 - changed = f.readlines()
11357 - self.changed = ["./" + elem.rstrip() for elem in changed]
11358 - del changed
11359 -
11360 - with repoman_popen("hg status --no-status --added .") as f:
11361 - new = f.readlines()
11362 - self.new = ["./" + elem.rstrip() for elem in new]
11363 - del new
11364 -
11365 - with repoman_popen("hg status --no-status --removed .") as f:
11366 - removed = f.readlines()
11367 - self.removed = ["./" + elem.rstrip() for elem in removed]
11368 - del removed
11369 -
11370 - @property
11371 - def unadded(self):
11372 - """VCS method of getting the unadded files in the repository"""
11373 - if self._unadded is not None:
11374 - return self._unadded
11375 - with repoman_popen("hg status --no-status --unknown .") as f:
11376 - unadded = f.readlines()
11377 - self._unadded = ["./" + elem.rstrip() for elem in unadded]
11378 - del unadded
11379 - return self._unadded
11380 -
11381 - @property
11382 - def deleted(self):
11383 - """VCS method of getting the deleted files in the repository"""
11384 - if self._deleted is not None:
11385 - return self._deleted
11386 - # Mercurial doesn't handle manually deleted files as removed from
11387 - # the repository, so the user need to remove them before commit,
11388 - # using "hg remove [FILES]"
11389 - with repoman_popen("hg status --no-status --deleted .") as f:
11390 - deleted = f.readlines()
11391 - self._deleted = ["./" + elem.rstrip() for elem in deleted]
11392 - del deleted
11393 - return self._deleted
11394 -
11395 - def digest_regen(
11396 - self, updates, removed, manifests, scanner, broken_changelog_manifests
11397 - ):
11398 - """Regenerate manifests
11399 -
11400 - @param updates: updated files
11401 - @param removed: removed files
11402 - @param manifests: Manifest files
11403 - @param scanner: The repoman.scanner.Scanner instance
11404 - @param broken_changelog_manifests: broken changelog manifests
11405 - """
11406 - if broken_changelog_manifests:
11407 - for x in broken_changelog_manifests:
11408 - self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
11409 - digestgen(
11410 - mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb
11411 - )
11412 -
11413 - def commit(self, myfiles, commitmessagefile):
11414 - """Hg commit function
11415 -
11416 - @param commitfiles: list of files to commit
11417 - @param commitmessagefile: file containing the commit message
11418 - @returns: The sub-command exit value or 0
11419 - """
11420 - commit_cmd = []
11421 - commit_cmd.append(self.vcs)
11422 - commit_cmd.extend(self.vcs_settings.vcs_global_opts)
11423 - commit_cmd.append("commit")
11424 - commit_cmd.extend(self.vcs_settings.vcs_local_opts)
11425 - commit_cmd.extend(["--logfile", commitmessagefile])
11426 - commit_cmd.extend(myfiles)
11427 -
11428 - if self.options.pretend:
11429 - print("(%s)" % (" ".join(commit_cmd),))
11430 - return 0
11431 - else:
11432 - retval = spawn(commit_cmd, env=self.repo_settings.commit_env)
11433 - return retval
11434
11435 diff --git a/repoman/lib/repoman/modules/vcs/hg/status.py b/repoman/lib/repoman/modules/vcs/hg/status.py
11436 deleted file mode 100644
11437 index 2b56f2e1f..000000000
11438 --- a/repoman/lib/repoman/modules/vcs/hg/status.py
11439 +++ /dev/null
11440 @@ -1,68 +0,0 @@
11441 -"""
11442 -Mercurial module Status class submodule
11443 -"""
11444 -
11445 -from repoman._portage import portage
11446 -from portage import os
11447 -
11448 -# pylint: disable=ungrouped-imports
11449 -from repoman._subprocess import repoman_popen
11450 -
11451 -
11452 -class Status:
11453 - """Performs status checks on the svn repository"""
11454 -
11455 - def __init__(self, qatracker, eadded):
11456 - """Class init
11457 -
11458 - @param qatracker: QATracker class instance
11459 - @param eadded: list
11460 - """
11461 - self.qatracker = qatracker
11462 - self.eadded = eadded
11463 -
11464 - def check(self, checkdir, checkdir_relative, xpkg):
11465 - """Perform the svn status check
11466 -
11467 - @param checkdir: string of the directory being checked
11468 - @param checkdir_relative: string of the relative directory being checked
11469 - @param xpkg: string of the package being checked
11470 - @returns: boolean
11471 - """
11472 - myf = repoman_popen(
11473 - "hg status --no-status --unknown %s"
11474 - % (portage._shell_quote(checkdir_relative),)
11475 - )
11476 - for l in myf:
11477 - if l[:-1][-7:] == ".ebuild":
11478 - self.qatracker.add_error(
11479 - "ebuild.notadded", os.path.join(xpkg, os.path.basename(l[:-1]))
11480 - )
11481 - myf.close()
11482 - return True
11483 -
11484 - @staticmethod
11485 - def detect_conflicts(options):
11486 - """Are there any merge conflicts present in the VCS tracking system
11487 -
11488 - @param options: command line options
11489 - @returns: Boolean
11490 - """
11491 - return False
11492 -
11493 - @staticmethod
11494 - def supports_gpg_sign():
11495 - """Does this vcs system support gpg commit signatures
11496 -
11497 - @returns: Boolean
11498 - """
11499 - return False
11500 -
11501 - @staticmethod
11502 - def isVcsDir(dirname):
11503 - """Does the directory belong to the vcs system
11504 -
11505 - @param dirname: string, directory name
11506 - @returns: Boolean
11507 - """
11508 - return dirname in [".hg"]
11509
11510 diff --git a/repoman/lib/repoman/modules/vcs/settings.py b/repoman/lib/repoman/modules/vcs/settings.py
11511 deleted file mode 100644
11512 index b186b7044..000000000
11513 --- a/repoman/lib/repoman/modules/vcs/settings.py
11514 +++ /dev/null
11515 @@ -1,113 +0,0 @@
11516 -"""
11517 -Repoman VCSSettings modules
11518 -"""
11519 -
11520 -import logging
11521 -import sys
11522 -
11523 -from portage.output import red
11524 -
11525 -from repoman.modules.vcs import module_controller, module_names
11526 -from repoman.modules.vcs.vcs import FindVCS
11527 -from repoman.qa_tracker import QATracker
11528 -
11529 -
11530 -class VCSSettings:
11531 - """Holds various VCS settings"""
11532 -
11533 - def __init__(self, options=None, repoman_settings=None, repo_settings=None):
11534 - """Class init function
11535 -
11536 - @param options: the run time cli options
11537 - @param repoman_settings: portage.config settings instance
11538 - @param repo_settings: RepoSettings instance
11539 - """
11540 - self.options = options
11541 - self.repoman_settings = repoman_settings
11542 - self.repo_settings = repo_settings
11543 - if options.vcs:
11544 - if options.vcs in module_names:
11545 - self.vcs = options.vcs
11546 - else:
11547 - self.vcs = None
11548 - else:
11549 - vcses = FindVCS()
11550 - if len(vcses) > 1:
11551 - print(
11552 - red(
11553 - "*** Ambiguous workdir -- more than one VCS found"
11554 - " at the same depth: %s." % ", ".join(vcses)
11555 - )
11556 - )
11557 - print(
11558 - red(
11559 - "*** Please either clean up your workdir"
11560 - " or specify --vcs option."
11561 - )
11562 - )
11563 - sys.exit(1)
11564 - elif vcses:
11565 - self.vcs = vcses[0]
11566 - else:
11567 - self.vcs = None
11568 -
11569 - if options.if_modified == "y" and self.vcs is None:
11570 - logging.info(
11571 - "Not in a version controlled repository; " "disabling --if-modified."
11572 - )
11573 - options.if_modified = "n"
11574 -
11575 - # initialize our instance placeholders
11576 - self._status = None
11577 - self._changes = None
11578 - # get our vcs plugin controller and available module names
11579 - self.module_controller = module_controller
11580 - self.module_names = module_names
11581 -
11582 - # Disable copyright/mtime check if vcs does not preserve mtime (bug #324075).
11583 - if str(self.vcs) in self.module_controller.parents:
11584 - self.vcs_preserves_mtime = module_controller.modules[
11585 - "%s_status" % self.vcs
11586 - ]["vcs_preserves_mtime"]
11587 - else:
11588 - self.vcs_preserves_mtime = False
11589 - logging.error("VCSSettings: Unknown VCS type: %s", self.vcs)
11590 - logging.error("Available modules: %s", module_controller.parents)
11591 -
11592 - self.needs_keyword_expansion = module_controller.modules[
11593 - "%s_status" % self.vcs
11594 - ]["needs_keyword_expansion"]
11595 - self.vcs_local_opts = repoman_settings.get("REPOMAN_VCS_LOCAL_OPTS", "").split()
11596 - self.vcs_global_opts = repoman_settings.get("REPOMAN_VCS_GLOBAL_OPTS")
11597 - if self.vcs_global_opts is None:
11598 - if self.vcs in ("cvs", "svn"):
11599 - self.vcs_global_opts = "-q"
11600 - else:
11601 - self.vcs_global_opts = ""
11602 - self.vcs_global_opts = self.vcs_global_opts.split()
11603 -
11604 - if options.mode == "commit" and not options.pretend and not self.vcs:
11605 - logging.info(
11606 - "Not in a version controlled repository; " "enabling pretend mode."
11607 - )
11608 - options.pretend = True
11609 - self.qatracker = QATracker()
11610 - self.eadded = []
11611 -
11612 - @property
11613 - def status(self):
11614 - """Initializes and returns the class instance
11615 - of the vcs's Status class"""
11616 - if not self._status:
11617 - status = self.module_controller.get_class("%s_status" % self.vcs)
11618 - self._status = status(self.qatracker, self.eadded)
11619 - return self._status
11620 -
11621 - @property
11622 - def changes(self):
11623 - """Initializes and returns the class instance
11624 - of the vcs's Changes class"""
11625 - if not self._changes:
11626 - changes = self.module_controller.get_class("%s_changes" % self.vcs)
11627 - self._changes = changes(self.options, self.repo_settings)
11628 - return self._changes
11629
11630 diff --git a/repoman/lib/repoman/modules/vcs/svn/__init__.py b/repoman/lib/repoman/modules/vcs/svn/__init__.py
11631 deleted file mode 100644
11632 index f8da39363..000000000
11633 --- a/repoman/lib/repoman/modules/vcs/svn/__init__.py
11634 +++ /dev/null
11635 @@ -1,32 +0,0 @@
11636 -# Copyright 2014-2015 Gentoo Foundation
11637 -# Distributed under the terms of the GNU General Public License v2
11638 -
11639 -doc = """Subversion (svn) plug-in module for portage.
11640 -Performs variaous subversion actions and checks on repositories."""
11641 -__doc__ = doc[:]
11642 -
11643 -
11644 -module_spec = {
11645 - "name": "svn",
11646 - "description": doc,
11647 - "provides": {
11648 - "svn-module": {
11649 - "name": "svn_status",
11650 - "sourcefile": "status",
11651 - "class": "Status",
11652 - "description": doc,
11653 - "functions": ["check", "supports_gpg_sign", "detect_conflicts"],
11654 - "func_desc": {},
11655 - "vcs_preserves_mtime": False,
11656 - "needs_keyword_expansion": True,
11657 - },
11658 - "svn-changes": {
11659 - "name": "svn_changes",
11660 - "sourcefile": "changes",
11661 - "class": "Changes",
11662 - "description": doc,
11663 - "functions": ["scan"],
11664 - "func_desc": {},
11665 - },
11666 - },
11667 -}
11668
11669 diff --git a/repoman/lib/repoman/modules/vcs/svn/changes.py b/repoman/lib/repoman/modules/vcs/svn/changes.py
11670 deleted file mode 100644
11671 index e437325db..000000000
11672 --- a/repoman/lib/repoman/modules/vcs/svn/changes.py
11673 +++ /dev/null
11674 @@ -1,156 +0,0 @@
11675 -"""
11676 -Subversion module Changes class submodule
11677 -"""
11678 -
11679 -from itertools import chain
11680 -
11681 -from repoman.modules.vcs.changes import ChangesBase
11682 -from repoman._subprocess import repoman_popen
11683 -from repoman._subprocess import repoman_getstatusoutput
11684 -from repoman.modules.vcs.vcs import vcs_files_to_cps
11685 -from repoman._portage import portage
11686 -from portage import os
11687 -from portage.output import green
11688 -from portage.package.ebuild.digestgen import digestgen
11689 -
11690 -
11691 -class Changes(ChangesBase):
11692 - """Class object to scan and hold the resultant data
11693 - for all changes to process.
11694 - """
11695 -
11696 - vcs = "svn"
11697 -
11698 - def __init__(self, options, repo_settings):
11699 - """Class init
11700 -
11701 - @param options: the run time cli options
11702 - @param repo_settings: RepoSettings instance
11703 - """
11704 - super(Changes, self).__init__(options, repo_settings)
11705 -
11706 - def _scan(self):
11707 - """VCS type scan function, looks for all detectable changes"""
11708 - with repoman_popen("svn status") as f:
11709 - svnstatus = f.readlines()
11710 - self.changed = [
11711 - "./" + elem.split()[-1:][0]
11712 - for elem in svnstatus
11713 - if elem and elem[:1] in "MR"
11714 - ]
11715 - self.new = [
11716 - "./" + elem.split()[-1:][0] for elem in svnstatus if elem.startswith("A")
11717 - ]
11718 - self.removed = [
11719 - "./" + elem.split()[-1:][0] for elem in svnstatus if elem.startswith("D")
11720 - ]
11721 -
11722 - @property
11723 - def expansion(self):
11724 - """VCS method of getting the expanded keywords in the repository"""
11725 - if self._expansion is not None:
11726 - return self._expansion
11727 - # Subversion expands keywords specified in svn:keywords properties.
11728 - with repoman_popen("svn propget -R svn:keywords") as f:
11729 - props = f.readlines()
11730 - self._expansion = dict(
11731 - ("./" + prop.split(" - ")[0], prop.split(" - ")[1].split())
11732 - for prop in props
11733 - if " - " in prop
11734 - )
11735 - del props
11736 - return self._expansion
11737 -
11738 - @property
11739 - def unadded(self):
11740 - """VCS method of getting the unadded files in the repository"""
11741 - if self._unadded is not None:
11742 - return self._unadded
11743 - with repoman_popen("svn status --no-ignore") as f:
11744 - svnstatus = f.readlines()
11745 - self._unadded = [
11746 - "./" + elem.rstrip().split()[1]
11747 - for elem in svnstatus
11748 - if elem.startswith("?") or elem.startswith("I")
11749 - ]
11750 - del svnstatus
11751 - return self._unadded
11752 -
11753 - def thick_manifest(self, updates, headers, no_expansion, expansion):
11754 - """Create a thick manifest
11755 -
11756 - @param updates:
11757 - @param headers:
11758 - @param no_expansion:
11759 - @param expansion:
11760 - """
11761 - svn_keywords = dict(
11762 - (k.lower(), k)
11763 - for k in [
11764 - "Rev",
11765 - "Revision",
11766 - "LastChangedRevision",
11767 - "Date",
11768 - "LastChangedDate",
11769 - "Author",
11770 - "LastChangedBy",
11771 - "URL",
11772 - "HeadURL",
11773 - "Id",
11774 - "Header",
11775 - ]
11776 - )
11777 -
11778 - for _file in updates:
11779 - # for SVN, expansion contains files that are included in expansion
11780 - if _file not in expansion:
11781 - continue
11782 -
11783 - # Subversion keywords are case-insensitive
11784 - # in svn:keywords properties,
11785 - # but case-sensitive in contents of files.
11786 - enabled_keywords = []
11787 - for k in expansion[_file]:
11788 - keyword = svn_keywords.get(k.lower())
11789 - if keyword is not None:
11790 - enabled_keywords.append(keyword)
11791 -
11792 - headerstring = r"'\$(%s).*\$'" % "|".join(enabled_keywords)
11793 -
11794 - _out = repoman_getstatusoutput(
11795 - "egrep -q %s %s" % (headerstring, portage._shell_quote(_file))
11796 - )
11797 - if _out[0] == 0:
11798 - headers.append(_file)
11799 -
11800 - print("%s have headers that will change." % green(str(len(headers))))
11801 - print(
11802 - "* Files with headers will"
11803 - " cause the manifests to be changed and committed separately."
11804 - )
11805 -
11806 - def digest_regen(
11807 - self, updates, removed, manifests, scanner, broken_changelog_manifests
11808 - ):
11809 - """Regenerate manifests
11810 -
11811 - @param updates: updated files
11812 - @param removed: removed files
11813 - @param manifests: Manifest files
11814 - @param scanner: The repoman.scanner.Scanner instance
11815 - @param broken_changelog_manifests: broken changelog manifests
11816 - """
11817 - if updates or removed:
11818 - for x in sorted(
11819 - vcs_files_to_cps(
11820 - chain(updates, removed, manifests),
11821 - scanner.repo_settings.repodir,
11822 - scanner.repolevel,
11823 - scanner.reposplit,
11824 - scanner.categories,
11825 - )
11826 - ):
11827 - self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
11828 - digestgen(
11829 - mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb
11830 - )
11831
11832 diff --git a/repoman/lib/repoman/modules/vcs/svn/status.py b/repoman/lib/repoman/modules/vcs/svn/status.py
11833 deleted file mode 100644
11834 index 2e6ee927d..000000000
11835 --- a/repoman/lib/repoman/modules/vcs/svn/status.py
11836 +++ /dev/null
11837 @@ -1,151 +0,0 @@
11838 -"""
11839 -Subversion module Status class submodule
11840 -"""
11841 -
11842 -import logging
11843 -import subprocess
11844 -import sys
11845 -
11846 -from repoman._portage import portage
11847 -from portage import os
11848 -from portage.const import BASH_BINARY
11849 -from portage.output import red, green
11850 -from portage import _unicode_encode, _unicode_decode
11851 -
11852 -# pylint: disable=ungrouped-imports
11853 -from repoman._subprocess import repoman_popen
11854 -
11855 -
11856 -class Status:
11857 - """Performs status checks on the svn repository"""
11858 -
11859 - def __init__(self, qatracker, eadded):
11860 - """Class init
11861 -
11862 - @param qatracker: QATracker class instance
11863 - @param eadded: list
11864 - """
11865 - self.qatracker = qatracker
11866 - self.eadded = eadded
11867 -
11868 - def check(self, checkdir, checkdir_relative, xpkg):
11869 - """Perform the svn status check
11870 -
11871 - @param checkdir: string of the directory being checked
11872 - @param checkdir_relative: string of the relative directory being checked
11873 - @param xpkg: string of the package being checked
11874 - @returns: boolean
11875 - """
11876 - try:
11877 - myf = repoman_popen(
11878 - "svn status --depth=files --verbose " + portage._shell_quote(checkdir)
11879 - )
11880 - myl = myf.readlines()
11881 - myf.close()
11882 - except IOError:
11883 - raise
11884 - for l in myl:
11885 - if l[:1] == "?":
11886 - continue
11887 - if l[:7] == " >":
11888 - # tree conflict, new in subversion 1.6
11889 - continue
11890 - l = l.split()[-1]
11891 - if l[-7:] == ".ebuild":
11892 - self.eadded.append(os.path.basename(l[:-7]))
11893 - try:
11894 - myf = repoman_popen("svn status " + portage._shell_quote(checkdir))
11895 - myl = myf.readlines()
11896 - myf.close()
11897 - except IOError:
11898 - raise
11899 - for l in myl:
11900 - if l[0] == "A":
11901 - l = l.rstrip().split(" ")[-1]
11902 - if l[-7:] == ".ebuild":
11903 - self.eadded.append(os.path.basename(l[:-7]))
11904 - return True
11905 -
11906 - @staticmethod
11907 - def detect_conflicts(options):
11908 - """Determine if the checkout has problems like cvs conflicts.
11909 -
11910 - If you want more vcs support here just keep adding if blocks...
11911 - This could be better.
11912 -
11913 - TODO(antarus): Also this should probably not call sys.exit() as
11914 - repoman is run on >1 packages and one failure should not cause
11915 - subsequent packages to fail.
11916 -
11917 - Args:
11918 - vcs - A string identifying the version control system in use
11919 - Returns: boolean
11920 - (calls sys.exit on fatal problems)
11921 - """
11922 -
11923 - cmd = "svn status -u 2>&1 | egrep -v '^. +.*/digest-[^/]+' | head -n-1"
11924 - msg = "Performing a %s with a little magic grep to check for updates." % green(
11925 - "svn status -u"
11926 - )
11927 -
11928 - logging.info(msg)
11929 - # Use Popen instead of getstatusoutput(), in order to avoid
11930 - # unicode handling problems (see bug #310789).
11931 - args = [BASH_BINARY, "-c", cmd]
11932 - args = [_unicode_encode(x) for x in args]
11933 - proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
11934 - out = _unicode_decode(proc.communicate()[0])
11935 - proc.wait()
11936 - mylines = out.splitlines()
11937 - myupdates = []
11938 - for line in mylines:
11939 - if not line:
11940 - continue
11941 -
11942 - # [ ] Unmodified (SVN) [U] Updates [P] Patches
11943 - # [M] Modified [A] Added [R] Removed / Replaced
11944 - # [D] Deleted
11945 - if line[0] not in " UPMARD":
11946 - # Stray Manifest is fine, we will readd it anyway.
11947 - if line[0] == "?" and line[1:].lstrip() == "Manifest":
11948 - continue
11949 - logging.error(
11950 - red(
11951 - "!!! Please fix the following issues reported "
11952 - "from cvs: %s" % green("(U,P,M,A,R,D are ok)")
11953 - )
11954 - )
11955 - logging.error(red("!!! Note: This is a pretend/no-modify pass..."))
11956 - logging.error(out)
11957 - sys.exit(1)
11958 - elif line[8] == "*":
11959 - myupdates.append(line[9:].lstrip(" 1234567890"))
11960 -
11961 - if myupdates:
11962 - logging.info(green("Fetching trivial updates..."))
11963 - if options.pretend:
11964 - logging.info("(svn update " + " ".join(myupdates) + ")")
11965 - retval = os.EX_OK
11966 - else:
11967 - retval = os.system("svn update " + " ".join(myupdates))
11968 - if retval != os.EX_OK:
11969 - logging.fatal("!!! svn exited with an error. Terminating.")
11970 - sys.exit(retval)
11971 - return False
11972 -
11973 - @staticmethod
11974 - def supports_gpg_sign():
11975 - """Does this vcs system support gpg commit signatures
11976 -
11977 - @returns: Boolean
11978 - """
11979 - return False
11980 -
11981 - @staticmethod
11982 - def isVcsDir(dirname):
11983 - """Does the directory belong to the vcs system
11984 -
11985 - @param dirname: string, directory name
11986 - @returns: Boolean
11987 - """
11988 - return dirname in [".svn"]
11989
11990 diff --git a/repoman/lib/repoman/modules/vcs/vcs.py b/repoman/lib/repoman/modules/vcs/vcs.py
11991 deleted file mode 100644
11992 index 1ee8b52ff..000000000
11993 --- a/repoman/lib/repoman/modules/vcs/vcs.py
11994 +++ /dev/null
11995 @@ -1,145 +0,0 @@
11996 -# -*- coding:utf-8 -*-
11997 -
11998 -import collections
11999 -import logging
12000 -
12001 -from itertools import chain
12002 -
12003 -from portage import os
12004 -
12005 -
12006 -_vcs_type = collections.namedtuple("_vcs_type", "name dir_name file_name")
12007 -
12008 -_FindVCS_data = (
12009 - _vcs_type(name="git", dir_name=".git", file_name=".git"),
12010 - _vcs_type(name="bzr", dir_name=".bzr", file_name=""),
12011 - _vcs_type(name="hg", dir_name=".hg", file_name=""),
12012 - _vcs_type(name="svn", dir_name=".svn", file_name=""),
12013 -)
12014 -
12015 -
12016 -def FindVCS(cwd=None):
12017 - """
12018 - Try to figure out in what VCS' working tree we are.
12019 -
12020 - @param cwd: working directory (default is os.getcwd())
12021 - @type cwd: str
12022 - @return: list of strings describing the discovered vcs types
12023 - @rtype: list
12024 - """
12025 -
12026 - if cwd is None:
12027 - cwd = os.getcwd()
12028 -
12029 - outvcs = []
12030 -
12031 - def seek(depth=None):
12032 - """Seek for VCSes that have a top-level data directory only.
12033 -
12034 - @param depth: integer
12035 - @returns: list of strings
12036 - """
12037 - retvcs = []
12038 - pathprep = cwd
12039 -
12040 - while depth is None or depth > 0:
12041 - for vcs_type in _FindVCS_data:
12042 - vcs_dir = os.path.join(pathprep, vcs_type.dir_name)
12043 - if os.path.isdir(vcs_dir):
12044 - logging.debug(
12045 - "FindVCS: found %(name)s dir: %(vcs_dir)s"
12046 - % {"name": vcs_type.name, "vcs_dir": os.path.abspath(vcs_dir)}
12047 - )
12048 - retvcs.append(vcs_type.name)
12049 - elif vcs_type.file_name:
12050 - vcs_file = os.path.join(pathprep, vcs_type.file_name)
12051 - if os.path.exists(vcs_file):
12052 - logging.debug(
12053 - "FindVCS: found %(name)s file: %(vcs_file)s"
12054 - % {
12055 - "name": vcs_type.name,
12056 - "vcs_file": os.path.abspath(vcs_file),
12057 - }
12058 - )
12059 - retvcs.append(vcs_type.name)
12060 -
12061 - if retvcs:
12062 - break
12063 - pathprep = os.path.join(pathprep, "..")
12064 - if os.path.realpath(pathprep).strip("/") == "":
12065 - break
12066 - if depth is not None:
12067 - depth = depth - 1
12068 -
12069 - return retvcs
12070 -
12071 - # Level zero VCS-es.
12072 - if os.path.isdir(os.path.join(cwd, "CVS")):
12073 - outvcs.append("cvs")
12074 - if os.path.isdir(".svn"): # <1.7
12075 - outvcs.append(os.path.join(cwd, "svn"))
12076 -
12077 - # If we already found one of 'level zeros', just take a quick look
12078 - # at the current directory. Otherwise, seek parents till we get
12079 - # something or reach root.
12080 - if outvcs:
12081 - outvcs.extend(seek(1))
12082 - else:
12083 - outvcs = seek()
12084 -
12085 - if len(outvcs) > 1:
12086 - # eliminate duplicates, like for svn in bug #391199
12087 - outvcs = list(set(outvcs))
12088 -
12089 - return outvcs
12090 -
12091 -
12092 -def vcs_files_to_cps(vcs_file_iter, repodir, repolevel, reposplit, categories):
12093 - """
12094 - Iterate over the given modified file paths returned from the vcs,
12095 - and return a frozenset containing category/pn strings for each
12096 - modified package.
12097 - """
12098 -
12099 - modified_cps = []
12100 -
12101 - if repolevel == 3:
12102 - if reposplit[-2] in categories and next(vcs_file_iter, None) is not None:
12103 - modified_cps.append("/".join(reposplit[-2:]))
12104 -
12105 - elif repolevel == 2:
12106 - category = reposplit[-1]
12107 - if category in categories:
12108 - for filename in vcs_file_iter:
12109 - f_split = filename.split(os.sep)
12110 - # ['.', pn, ...]
12111 - if len(f_split) > 2:
12112 - modified_cps.append(category + "/" + f_split[1])
12113 -
12114 - else:
12115 - # repolevel == 1
12116 - for filename in vcs_file_iter:
12117 - f_split = filename.split(os.sep)
12118 - # ['.', category, pn, ...]
12119 - if len(f_split) > 3 and f_split[1] in categories:
12120 - modified_cps.append("/".join(f_split[1:3]))
12121 -
12122 - # Exclude packages that have been removed, since calling
12123 - # code assumes that the packages exist.
12124 - return frozenset(
12125 - x for x in frozenset(modified_cps) if os.path.exists(os.path.join(repodir, x))
12126 - )
12127 -
12128 -
12129 -def vcs_new_changed(relative_path, mychanged, mynew):
12130 - """Check if any vcs tracked file have been modified
12131 -
12132 - @param relative_path:
12133 - @param mychanged: iterable of changed files
12134 - @param mynew: iterable of new files
12135 - @returns boolean
12136 - """
12137 - for x in chain(mychanged, mynew):
12138 - if x == relative_path:
12139 - return True
12140 - return False
12141
12142 diff --git a/repoman/lib/repoman/profile.py b/repoman/lib/repoman/profile.py
12143 deleted file mode 100644
12144 index b317189ef..000000000
12145 --- a/repoman/lib/repoman/profile.py
12146 +++ /dev/null
12147 @@ -1,94 +0,0 @@
12148 -# -*- coding:utf-8 -*-
12149 -
12150 -from portage import normalize_path
12151 -from portage import os
12152 -from portage.output import red
12153 -
12154 -
12155 -class ProfileDesc:
12156 - __slots__ = (
12157 - "abs_path",
12158 - "arch",
12159 - "status",
12160 - "sub_path",
12161 - "tree_path",
12162 - )
12163 -
12164 - def __init__(self, arch, status, sub_path, tree_path):
12165 - self.arch = arch
12166 - self.status = status
12167 - if sub_path:
12168 - sub_path = normalize_path(sub_path.lstrip(os.sep))
12169 - self.sub_path = sub_path
12170 - self.tree_path = tree_path
12171 - if tree_path:
12172 - self.abs_path = os.path.join(tree_path, "profiles", self.sub_path)
12173 - else:
12174 - self.abs_path = tree_path
12175 -
12176 - def __str__(self):
12177 - if self.sub_path:
12178 - return self.sub_path
12179 - return "empty profile"
12180 -
12181 -
12182 -valid_profile_types = frozenset(["dev", "exp", "stable"])
12183 -
12184 -
12185 -def dev_profile_keywords(profiles):
12186 - """
12187 - Create a set of KEYWORDS values that exist in 'dev'
12188 - profiles. These are used
12189 - to trigger a message notifying the user when they might
12190 - want to add the --include-dev option.
12191 - """
12192 - type_arch_map = {}
12193 - for arch, arch_profiles in profiles.items():
12194 - for prof in arch_profiles:
12195 - arch_set = type_arch_map.get(prof.status)
12196 - if arch_set is None:
12197 - arch_set = set()
12198 - type_arch_map[prof.status] = arch_set
12199 - arch_set.add(arch)
12200 -
12201 - dev_keywords = type_arch_map.get("dev", set())
12202 - dev_keywords.update(["~" + arch for arch in dev_keywords])
12203 - return frozenset(dev_keywords)
12204 -
12205 -
12206 -def setup_profile(profile_list):
12207 - # Ensure that profile sub_path attributes are unique. Process in reverse order
12208 - # so that profiles with duplicate sub_path from overlays will override
12209 - # profiles with the same sub_path from parent repos.
12210 - profiles = {}
12211 - profile_list.reverse()
12212 - profile_sub_paths = set()
12213 - for prof in profile_list:
12214 - if prof.sub_path in profile_sub_paths:
12215 - continue
12216 - profile_sub_paths.add(prof.sub_path)
12217 - profiles.setdefault(prof.arch, []).append(prof)
12218 -
12219 - # Use an empty profile for checking dependencies of
12220 - # packages that have empty KEYWORDS.
12221 - prof = ProfileDesc("**", "stable", "", "")
12222 - profiles.setdefault(prof.arch, []).append(prof)
12223 - return profiles
12224 -
12225 -
12226 -def check_profiles(profiles, archlist):
12227 - for x in archlist:
12228 - if x[0] == "~":
12229 - continue
12230 - if x not in profiles:
12231 - print(
12232 - red('"%s" doesn\'t have a valid profile listed in profiles.desc.' % x)
12233 - )
12234 - print(
12235 - red(
12236 - 'You need to either "cvs update" your profiles dir'
12237 - " or follow this"
12238 - )
12239 - )
12240 - print(red("up with the " + x + " team."))
12241 - print()
12242
12243 diff --git a/repoman/lib/repoman/qa_data.py b/repoman/lib/repoman/qa_data.py
12244 deleted file mode 100644
12245 index 0892c1f5c..000000000
12246 --- a/repoman/lib/repoman/qa_data.py
12247 +++ /dev/null
12248 @@ -1,210 +0,0 @@
12249 -# -*- coding:utf-8 -*-
12250 -
12251 -import logging
12252 -import os
12253 -
12254 -from _emerge.Package import Package
12255 -
12256 -# import our initialized portage instance
12257 -from repoman import _not_installed
12258 -from repoman._portage import portage
12259 -from repoman.config import load_config
12260 -
12261 -
12262 -class QAData:
12263 - def __init__(self):
12264 - # Create the main exported data variables
12265 - self.max_desc_len = None
12266 - self.allowed_filename_chars = None
12267 - self.qahelp = None
12268 - self.qacats = None
12269 - self.qawarnings = None
12270 - self.missingvars = None
12271 - self.allvars = None
12272 - self.valid_restrict = None
12273 - self.suspect_rdepend = None
12274 - self.suspect_virtual = None
12275 - self.ruby_deprecated = None
12276 - self.no_exec = None
12277 -
12278 - def load_repo_config(self, repopaths, options, valid_versions):
12279 - """Load the repository repoman qa_data.yml config
12280 -
12281 - @param repopaths: list of strings, The path of the repository being scanned
12282 - This could be a parent repository using the
12283 - repoman_masters layout.conf variable
12284 - """
12285 - # add our base qahelp
12286 - repository_modules = options.experimental_repository_modules == "y"
12287 - if _not_installed:
12288 - cnfdir = os.path.realpath(
12289 - os.path.join(
12290 - os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
12291 - "cnf/qa_data",
12292 - )
12293 - )
12294 - else:
12295 - cnfdir = os.path.join(
12296 - portage.const.EPREFIX or "/", "usr/share/repoman/qa_data"
12297 - )
12298 - repomanpaths = [os.path.join(cnfdir, _file_) for _file_ in os.listdir(cnfdir)]
12299 - logging.debug("QAData: cnfdir: %s, repomanpaths: %s", cnfdir, repomanpaths)
12300 - if repository_modules:
12301 - repopaths = [os.path.join(path, "qa_data.yaml") for path in repopaths]
12302 - elif _not_installed:
12303 - repopaths = [
12304 - os.path.realpath(
12305 - os.path.join(
12306 - os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
12307 - "cnf/repository/qa_data.yaml",
12308 - )
12309 - )
12310 - ]
12311 - else:
12312 - repopaths = [
12313 - os.path.join(
12314 - portage.const.EPREFIX or "/",
12315 - "usr/share/repoman/repository/qa_data.yaml",
12316 - )
12317 - ]
12318 - infopaths = repomanpaths + repopaths
12319 -
12320 - qadata = load_config(infopaths, None, valid_versions)
12321 - if qadata == {}:
12322 - logging.error(
12323 - "QAData: Failed to load a valid 'qa_data.yaml' file at paths: %s",
12324 - infopaths,
12325 - )
12326 - return False
12327 - self.max_desc_len = qadata.get("max_description_length", 80)
12328 - self.allowed_filename_chars = qadata.get(
12329 - "allowed_filename_chars", "a-zA-Z0-9._-+:"
12330 - )
12331 -
12332 - self.qahelp = qadata["qahelp"]
12333 - logging.debug("qa_help primary keys: %s", sorted(self.qahelp))
12334 -
12335 - self.qacats = []
12336 - for x in sorted(self.qahelp):
12337 - for y in sorted(self.qahelp[x]):
12338 - self.qacats.append(".".join([x, y]))
12339 - self.qacats.sort()
12340 -
12341 - self.qawarnings = set(qadata.get("qawarnings", []))
12342 - if options.experimental_inherit == "y":
12343 - # This is experimental, so it's non-fatal.
12344 - self.qawarnings.add("inherit.missing")
12345 -
12346 - self.missingvars = qadata.get("missingvars", [])
12347 - logging.debug("QAData: missingvars: %s", self.missingvars)
12348 - self.allvars = set(portage.auxdbkeys)
12349 - self.allvars.update(Package.metadata_keys)
12350 - self.allvars = sorted(self.allvars)
12351 -
12352 - for x in self.missingvars:
12353 - x += ".missing"
12354 - if x not in self.qacats:
12355 - logging.warning(
12356 - 'QAData: * missingvars values need to be added to qahelp ("%s")' % x
12357 - )
12358 - self.qacats.append(x)
12359 - self.qawarnings.add(x)
12360 -
12361 - self.valid_restrict = frozenset(qadata.get("valid_restrict", []))
12362 -
12363 - self.suspect_rdepend = frozenset(qadata.get("suspect_rdepend", []))
12364 -
12365 - self.suspect_virtual = qadata.get("suspect_virtual", {})
12366 -
12367 - self.ruby_deprecated = frozenset(qadata.get("ruby_deprecated", []))
12368 -
12369 - # file.executable
12370 - self.no_exec = frozenset(qadata.get("no_exec_files", []))
12371 - logging.debug("QAData: completed loading file: %s", repopaths)
12372 - return True
12373 -
12374 -
12375 -def format_qa_output(formatter, fails, dofull, dofail, options, qawarnings):
12376 - """Helper function that formats output properly
12377 -
12378 - @param formatter: an instance of Formatter
12379 - @type formatter: Formatter
12380 - @param fails: dict of qa status failures
12381 - @type fails: dict
12382 - @param dofull: Whether to print full results or a summary
12383 - @type dofull: boolean
12384 - @param dofail: Whether failure was hard or soft
12385 - @type dofail: boolean
12386 - @param options: The command-line options provided to repoman
12387 - @type options: Namespace
12388 - @param qawarnings: the set of warning types
12389 - @type qawarnings: set
12390 - @return: None (modifies formatter)
12391 - """
12392 - full = options.mode == "full"
12393 - # we only want key value pairs where value > 0
12394 - for category in sorted(fails):
12395 - number = len(fails[category])
12396 - formatter.add_literal_data(" " + category)
12397 - spacing_width = 30 - len(category)
12398 - if category in qawarnings:
12399 - formatter.push_style("WARN")
12400 - else:
12401 - formatter.push_style("BAD")
12402 - formatter.add_literal_data(" [fatal]")
12403 - spacing_width -= 8
12404 -
12405 - formatter.add_literal_data(" " * spacing_width)
12406 - formatter.add_literal_data("%s" % number)
12407 - formatter.pop_style()
12408 - formatter.add_line_break()
12409 - if not dofull:
12410 - if not full and dofail and category in qawarnings:
12411 - # warnings are considered noise when there are failures
12412 - continue
12413 - fails_list = fails[category]
12414 - if not full and len(fails_list) > 12:
12415 - fails_list = fails_list[:12]
12416 - for failure in fails_list:
12417 - formatter.add_literal_data(" " + failure)
12418 - formatter.add_line_break()
12419 -
12420 -
12421 -def format_qa_output_column(formatter, fails, dofull, dofail, options, qawarnings):
12422 - """Helper function that formats output in a machine-parseable column format
12423 -
12424 - @param formatter: an instance of Formatter
12425 - @type formatter: Formatter
12426 - @param fails: dict of qa status failures
12427 - @type fails: dict
12428 - @param dofull: Whether to print full results or a summary
12429 - @type dofull: boolean
12430 - @param dofail: Whether failure was hard or soft
12431 - @type dofail: boolean
12432 - @param options: The command-line options provided to repoman
12433 - @type options: Namespace
12434 - @param qawarnings: the set of warning types
12435 - @type qawarnings: set
12436 - @return: None (modifies formatter)
12437 - """
12438 - full = options.mode == "full"
12439 - for category in sorted(fails):
12440 - number = len(fails[category])
12441 - formatter.add_literal_data("NumberOf " + category + " ")
12442 - if category in qawarnings:
12443 - formatter.push_style("WARN")
12444 - else:
12445 - formatter.push_style("BAD")
12446 - formatter.add_literal_data("%s" % number)
12447 - formatter.pop_style()
12448 - formatter.add_line_break()
12449 - if not dofull:
12450 - if not full and dofail and category in qawarnings:
12451 - # warnings are considered noise when there are failures
12452 - continue
12453 - fails_list = fails[category]
12454 - if not full and len(fails_list) > 12:
12455 - fails_list = fails_list[:12]
12456 - for failure in fails_list:
12457 - formatter.add_literal_data(category + " " + failure)
12458 - formatter.add_line_break()
12459
12460 diff --git a/repoman/lib/repoman/qa_tracker.py b/repoman/lib/repoman/qa_tracker.py
12461 deleted file mode 100644
12462 index 6cb5f3207..000000000
12463 --- a/repoman/lib/repoman/qa_tracker.py
12464 +++ /dev/null
12465 @@ -1,46 +0,0 @@
12466 -import logging
12467 -import sys
12468 -
12469 -
12470 -class QATracker:
12471 - """Track all occurrances of Q/A problems detected"""
12472 -
12473 - def __init__(self, qacats=None, qawarnings=None):
12474 - self.fails = {}
12475 - self.warns = {}
12476 - self.qacats = qacats
12477 - self.qawarnings = qawarnings
12478 -
12479 - def add_error(self, detected_qa, info):
12480 - """Add the Q/A error to the database of detected problems
12481 -
12482 - @param detected_qa: string, member of qa_data.qacats list
12483 - @param info: string, details of the detected problem
12484 - """
12485 - if detected_qa not in self.qacats:
12486 - logging.error(
12487 - "QATracker: Exiting on error. Unknown detected_qa type passed "
12488 - "in to add_error(): %s, %s" % (detected_qa, info)
12489 - )
12490 - sys.exit(1)
12491 - try:
12492 - self.fails[detected_qa].append(info)
12493 - except KeyError:
12494 - self.fails[detected_qa] = [info]
12495 -
12496 - def add_warning(self, detected_qa, info):
12497 - """Add the Q/A warning to the database of detected problems
12498 -
12499 - @param detected_qa: string, member of qa_data.qawarnings list
12500 - @param info: string, details of the detected problem
12501 - """
12502 - if detected_qa not in self.qawarnings:
12503 - logging.error(
12504 - "QATracker: Exiting on error. Unknown detected_qa type passed "
12505 - "in to add_warning(): %s, %s" % (detected_qa, info)
12506 - )
12507 - sys.exit(1)
12508 - try:
12509 - self.warns[detected_qa].append(info)
12510 - except KeyError:
12511 - self.warns[detected_qa] = [info]
12512
12513 diff --git a/repoman/lib/repoman/repos.py b/repoman/lib/repoman/repos.py
12514 deleted file mode 100644
12515 index d89e0508a..000000000
12516 --- a/repoman/lib/repoman/repos.py
12517 +++ /dev/null
12518 @@ -1,377 +0,0 @@
12519 -# -*- coding:utf-8 -*-
12520 -
12521 -
12522 -import io
12523 -import logging
12524 -import re
12525 -import sys
12526 -import textwrap
12527 -
12528 -# import our initialized portage instance
12529 -from repoman._portage import portage
12530 -
12531 -from portage import os
12532 -from portage import _encodings
12533 -from portage import _unicode_encode
12534 -from portage.checksum import get_valid_checksum_keys
12535 -from portage.repository.config import allow_profile_repo_deps
12536 -
12537 -# pylint: disable=ungrouped-imports
12538 -from repoman.errors import err
12539 -from repoman.profile import ProfileDesc, valid_profile_types
12540 -
12541 -GPG_KEY_ID_REGEX = r"(0x)?([0-9a-fA-F]{8}){1,5}!?"
12542 -bad = portage.output.create_color_func("BAD")
12543 -
12544 -
12545 -class RepoSettings:
12546 - """Holds our repo specific settings"""
12547 -
12548 - def __init__(
12549 - self,
12550 - config_root,
12551 - portdir,
12552 - portdir_overlay,
12553 - repoman_settings=None,
12554 - vcs_settings=None,
12555 - options=None,
12556 - qadata=None,
12557 - ):
12558 - self.config_root = config_root
12559 - self.repoman_settings = repoman_settings
12560 - self.vcs_settings = vcs_settings
12561 -
12562 - self.repositories = self.repoman_settings.repositories
12563 -
12564 - # Ensure that current repository is in the list of enabled repositories.
12565 - self.repodir = os.path.realpath(portdir_overlay)
12566 - try:
12567 - self.repositories.get_repo_for_location(self.repodir)
12568 - except KeyError:
12569 - self._add_repo(config_root, portdir_overlay)
12570 -
12571 - # Determine the master config loading list
12572 - self.masters_list = []
12573 - # get out repo masters value
12574 - masters = self.repositories.get_repo_for_location(self.repodir).masters
12575 - for repo in masters:
12576 - self.masters_list.append(os.path.join(repo.location, "metadata", "repoman"))
12577 - self.masters_list.append(os.path.join(self.repodir, "metadata", "repoman"))
12578 -
12579 - logging.debug("RepoSettings: init(); load qadata")
12580 - # load the repo specific configuration
12581 - self.qadata = qadata
12582 - if not self.qadata.load_repo_config(
12583 - self.masters_list, options, repoman_settings.valid_versions
12584 - ):
12585 - logging.error("Aborting...")
12586 - sys.exit(1)
12587 - logging.debug("RepoSettings: qadata loaded: %s", qadata.no_exec)
12588 -
12589 - self.root = self.repoman_settings["EROOT"]
12590 - self.trees = {
12591 - self.root: {"porttree": portage.portagetree(settings=self.repoman_settings)}
12592 - }
12593 - self.portdb = self.trees[self.root]["porttree"].dbapi
12594 -
12595 - # Constrain dependency resolution to the master(s)
12596 - # that are specified in layout.conf.
12597 - self.repo_config = self.repositories.get_repo_for_location(self.repodir)
12598 - self.portdb.porttrees = list(self.repo_config.eclass_db.porttrees)
12599 - self.portdir = self.portdb.porttrees[0]
12600 - self.commit_env = os.environ.copy()
12601 - # list() is for iteration on a copy.
12602 - for repo in list(self.repositories):
12603 - # all paths are canonical
12604 - if repo.location not in self.repo_config.eclass_db.porttrees:
12605 - del self.repositories[repo.name]
12606 -
12607 - if self.repo_config.sign_commit and options.mode in (
12608 - "commit",
12609 - "fix",
12610 - "manifest",
12611 - ):
12612 - if vcs_settings.vcs:
12613 - func = getattr(self, "_vcs_gpg_%s" % vcs_settings.vcs)
12614 - func()
12615 - else:
12616 - logging.warning("No VCS type detected, unable to sign the commit")
12617 -
12618 - # In order to disable manifest signatures, repos may set
12619 - # "sign-manifests = false" in metadata/layout.conf. This
12620 - # can be used to prevent merge conflicts like those that
12621 - # thin-manifests is designed to prevent.
12622 - self.sign_manifests = (
12623 - "sign" in self.repoman_settings.features and self.repo_config.sign_manifest
12624 - )
12625 -
12626 - if (
12627 - self.repo_config.sign_manifest
12628 - and self.repo_config.name == "gentoo"
12629 - and options.mode in ("commit",)
12630 - and not self.sign_manifests
12631 - ):
12632 - msg = (
12633 - "The '%s' repository has manifest signatures enabled, "
12634 - "but FEATURES=sign is currently disabled. In order to avoid this "
12635 - "warning, enable FEATURES=sign in make.conf. Alternatively, "
12636 - "repositories can disable manifest signatures by setting "
12637 - "'sign-manifests = false' in metadata/layout.conf."
12638 - ) % (self.repo_config.name,)
12639 - for line in textwrap.wrap(msg, 60):
12640 - logging.warn(line)
12641 -
12642 - is_commit = options.mode in ("commit",)
12643 - valid_gpg_key = self.repoman_settings.get("PORTAGE_GPG_KEY") and re.match(
12644 - r"^%s$" % GPG_KEY_ID_REGEX, self.repoman_settings["PORTAGE_GPG_KEY"]
12645 - )
12646 -
12647 - if self.sign_manifests and is_commit and not valid_gpg_key:
12648 - logging.error(
12649 - "PORTAGE_GPG_KEY value is invalid: %s"
12650 - % self.repoman_settings["PORTAGE_GPG_KEY"]
12651 - )
12652 - sys.exit(1)
12653 -
12654 - manifest_hashes = self.repo_config.manifest_hashes
12655 - manifest_required_hashes = self.repo_config.manifest_required_hashes
12656 - if manifest_hashes is None:
12657 - manifest_hashes = portage.const.MANIFEST2_HASH_DEFAULTS
12658 - manifest_required_hashes = manifest_hashes
12659 -
12660 - if options.mode in ("commit", "fix", "manifest"):
12661 - missing_required_hashes = manifest_required_hashes.difference(
12662 - manifest_hashes
12663 - )
12664 - if missing_required_hashes:
12665 - msg = (
12666 - "The 'manifest-hashes' setting in the '%s' repository's "
12667 - "metadata/layout.conf does not contain the '%s' hashes which "
12668 - "are listed in 'manifest-required-hashes'. Please fix that "
12669 - "file if you want to generate valid manifests for "
12670 - "this repository."
12671 - ) % (self.repo_config.name, " ".join(missing_required_hashes))
12672 - for line in textwrap.wrap(msg, 70):
12673 - logging.error(line)
12674 - sys.exit(1)
12675 -
12676 - unsupported_hashes = manifest_hashes.difference(get_valid_checksum_keys())
12677 - if unsupported_hashes:
12678 - msg = (
12679 - "The 'manifest-hashes' setting in the '%s' repository's "
12680 - "metadata/layout.conf contains one or more hash types '%s' "
12681 - "which are not supported by this portage version. You will "
12682 - "have to upgrade portage if you want to generate valid "
12683 - "manifests for this repository."
12684 - ) % (self.repo_config.name, " ".join(sorted(unsupported_hashes)))
12685 - for line in textwrap.wrap(msg, 70):
12686 - logging.error(line)
12687 - sys.exit(1)
12688 -
12689 - def _add_repo(self, config_root, portdir_overlay):
12690 - self.repo_conf = portage.repository.config
12691 - self.repo_name = self.repo_conf.RepoConfig._read_valid_repo_name(
12692 - portdir_overlay
12693 - )[0]
12694 - self.layout_conf_data = self.repo_conf.parse_layout_conf(portdir_overlay)[0]
12695 - if self.layout_conf_data["repo-name"]:
12696 - self.repo_name = self.layout_conf_data["repo-name"]
12697 - tmp_conf_file = io.StringIO(
12698 - textwrap.dedent(
12699 - """
12700 - [%s]
12701 - location = %s
12702 - """
12703 - )
12704 - % (self.repo_name, portdir_overlay)
12705 - )
12706 - # Ensure that the repository corresponding to $PWD overrides a
12707 - # repository of the same name referenced by the existing PORTDIR
12708 - # or PORTDIR_OVERLAY settings.
12709 - self.repoman_settings["PORTDIR_OVERLAY"] = "%s %s" % (
12710 - self.repoman_settings.get("PORTDIR_OVERLAY", ""),
12711 - portage._shell_quote(portdir_overlay),
12712 - )
12713 - self.repositories = self.repo_conf.load_repository_config(
12714 - self.repoman_settings, extra_files=[tmp_conf_file]
12715 - )
12716 - # We have to call the config constructor again so that attributes
12717 - # dependent on config.repositories are initialized correctly.
12718 - self.repoman_settings = portage.config(
12719 - config_root=config_root, local_config=False, repositories=self.repositories
12720 - )
12721 -
12722 - ##########
12723 - # future vcs plugin functions
12724 - ##########
12725 -
12726 - def _vcs_gpg_bzr(self):
12727 - pass
12728 -
12729 - def _vcs_gpg_cvs(self):
12730 - pass
12731 -
12732 - def _vcs_gpg_git(self):
12733 - # NOTE: It's possible to use --gpg-sign=key_id to specify the key in
12734 - # the commit arguments. If key_id is unspecified, then it must be
12735 - # configured by `git config user.signingkey key_id`.
12736 - self.vcs_settings.vcs_local_opts.append("--gpg-sign")
12737 - if self.repoman_settings.get("PORTAGE_GPG_DIR"):
12738 - # Pass GNUPGHOME to git for bug #462362.
12739 - self.commit_env["GNUPGHOME"] = self.repoman_settings["PORTAGE_GPG_DIR"]
12740 -
12741 - # Pass GPG_TTY to git for bug #477728.
12742 - try:
12743 - self.commit_env["GPG_TTY"] = os.ttyname(sys.stdin.fileno())
12744 - except OSError:
12745 - pass
12746 -
12747 - def _vcs_gpg_hg(self):
12748 - pass
12749 -
12750 - def _vcs_gpg_svn(self):
12751 - pass
12752 -
12753 -
12754 -def list_checks(kwlist, liclist, uselist, repoman_settings):
12755 - liclist_deprecated = set()
12756 - if "DEPRECATED" in repoman_settings._license_manager._license_groups:
12757 - liclist_deprecated.update(
12758 - repoman_settings._license_manager.expandLicenseTokens(["@DEPRECATED"])
12759 - )
12760 -
12761 - if not liclist:
12762 - logging.fatal("Couldn't find licenses?")
12763 - sys.exit(1)
12764 -
12765 - if not kwlist:
12766 - logging.fatal("Couldn't read KEYWORDS from arch.list")
12767 - sys.exit(1)
12768 -
12769 - if not uselist:
12770 - logging.fatal("Couldn't find use.desc?")
12771 - sys.exit(1)
12772 - return liclist_deprecated
12773 -
12774 -
12775 -def repo_metadata(portdb, repoman_settings):
12776 - # get lists of valid keywords, licenses, and use
12777 - kwlist = set()
12778 - liclist = set()
12779 - uselist = set()
12780 - profile_list = []
12781 - global_pmasklines = []
12782 -
12783 - for repo in portdb.repositories:
12784 - path = repo.location
12785 -
12786 - try:
12787 - liclist.update(os.listdir(os.path.join(path, "licenses")))
12788 - except OSError:
12789 - pass
12790 - kwlist.update(portage.grabfile(os.path.join(path, "profiles", "arch.list")))
12791 -
12792 - use_desc = portage.grabfile(os.path.join(path, "profiles", "use.desc"))
12793 - for x in use_desc:
12794 - x = x.split()
12795 - if x:
12796 - uselist.add(x[0])
12797 -
12798 - expand_desc_dir = os.path.join(path, "profiles", "desc")
12799 - try:
12800 - expand_list = os.listdir(expand_desc_dir)
12801 - except OSError:
12802 - pass
12803 - else:
12804 - for fn in expand_list:
12805 - if not fn[-5:] == ".desc":
12806 - continue
12807 - use_prefix = fn[:-5].lower() + "_"
12808 - for x in portage.grabfile(os.path.join(expand_desc_dir, fn)):
12809 - x = x.split()
12810 - if x:
12811 - uselist.add(use_prefix + x[0])
12812 -
12813 - global_pmasklines.append(
12814 - portage.util.grabfile_package(
12815 - os.path.join(path, "profiles", "package.mask"),
12816 - recursive=1,
12817 - verify_eapi=True,
12818 - allow_repo=allow_profile_repo_deps(repo),
12819 - )
12820 - )
12821 -
12822 - desc_path = os.path.join(path, "profiles", "profiles.desc")
12823 - try:
12824 - desc_file = io.open(
12825 - _unicode_encode(desc_path, encoding=_encodings["fs"], errors="strict"),
12826 - mode="r",
12827 - encoding=_encodings["repo.content"],
12828 - errors="replace",
12829 - )
12830 - except EnvironmentError:
12831 - pass
12832 - else:
12833 - for i, x in enumerate(desc_file):
12834 - if x[0] == "#":
12835 - continue
12836 - arch = x.split()
12837 - if len(arch) == 0:
12838 - continue
12839 - if len(arch) != 3:
12840 - err(
12841 - 'wrong format: "%s" in %s line %d'
12842 - % (
12843 - bad(x.strip()),
12844 - desc_path,
12845 - i + 1,
12846 - )
12847 - )
12848 - elif arch[0] not in kwlist:
12849 - err(
12850 - 'invalid arch: "%s" in %s line %d'
12851 - % (
12852 - bad(arch[0]),
12853 - desc_path,
12854 - i + 1,
12855 - )
12856 - )
12857 - elif arch[2] not in valid_profile_types:
12858 - err(
12859 - 'invalid profile type: "%s" in %s line %d'
12860 - % (
12861 - bad(arch[2]),
12862 - desc_path,
12863 - i + 1,
12864 - )
12865 - )
12866 - profile_desc = ProfileDesc(arch[0], arch[2], arch[1], path)
12867 - if not os.path.isdir(profile_desc.abs_path):
12868 - logging.error(
12869 - "Invalid %s profile (%s) for arch %s in %s line %d",
12870 - arch[2],
12871 - arch[1],
12872 - arch[0],
12873 - desc_path,
12874 - i + 1,
12875 - )
12876 - continue
12877 - if os.path.exists(os.path.join(profile_desc.abs_path, "deprecated")):
12878 - continue
12879 - profile_list.append(profile_desc)
12880 - desc_file.close()
12881 -
12882 - global_pmasklines = portage.util.stack_lists(global_pmasklines, incremental=1)
12883 - global_pmaskdict = {}
12884 - for x in global_pmasklines:
12885 - global_pmaskdict.setdefault(x.cp, []).append(x)
12886 - del global_pmasklines
12887 -
12888 - return (
12889 - kwlist,
12890 - liclist,
12891 - uselist,
12892 - profile_list,
12893 - global_pmaskdict,
12894 - list_checks(kwlist, liclist, uselist, repoman_settings),
12895 - )
12896
12897 diff --git a/repoman/lib/repoman/scanner.py b/repoman/lib/repoman/scanner.py
12898 deleted file mode 100644
12899 index 890950c65..000000000
12900 --- a/repoman/lib/repoman/scanner.py
12901 +++ /dev/null
12902 @@ -1,484 +0,0 @@
12903 -# -*- coding:utf-8 -*-
12904 -
12905 -import logging
12906 -import portage
12907 -
12908 -from itertools import chain
12909 -
12910 -from portage import normalize_path
12911 -from portage import os
12912 -from portage._sets.base import InternalPackageSet
12913 -from portage.output import green
12914 -from portage.util.futures.extendedfutures import ExtendedFuture
12915 -
12916 -from repoman.metadata import get_metadata_xsd
12917 -from repoman.modules.commit import repochecks
12918 -from repoman.modules.commit import manifest
12919 -from repoman.profile import check_profiles, dev_profile_keywords, setup_profile
12920 -from repoman.repos import repo_metadata
12921 -from repoman.modules.scan.module import ModuleConfig
12922 -from repoman.modules.scan.scan import scan
12923 -from repoman.modules.vcs.vcs import vcs_files_to_cps
12924 -
12925 -
12926 -DATA_TYPES = {"dict": dict, "Future": ExtendedFuture, "list": list, "set": set}
12927 -
12928 -
12929 -class Scanner:
12930 - """Primary scan class. Operates all the small Q/A tests and checks"""
12931 -
12932 - def __init__(
12933 - self, repo_settings, myreporoot, config_root, options, vcs_settings, mydir, env
12934 - ):
12935 - """Class __init__"""
12936 - self.repo_settings = repo_settings
12937 - self.config_root = config_root
12938 - self.options = options
12939 - self.vcs_settings = vcs_settings
12940 - self.env = env
12941 -
12942 - # Repoman sets it's own ACCEPT_KEYWORDS and we don't want it to
12943 - # behave incrementally.
12944 - self.repoman_incrementals = tuple(
12945 - x for x in portage.const.INCREMENTALS if x != "ACCEPT_KEYWORDS"
12946 - )
12947 -
12948 - self.categories = []
12949 - for path in self.repo_settings.repo_config.eclass_db.porttrees:
12950 - self.categories.extend(
12951 - portage.util.grabfile(os.path.join(path, "profiles", "categories"))
12952 - )
12953 - self.repo_settings.repoman_settings.categories = frozenset(
12954 - portage.util.stack_lists([self.categories], incremental=1)
12955 - )
12956 - self.categories = self.repo_settings.repoman_settings.categories
12957 -
12958 - self.portdb = repo_settings.portdb
12959 - self.portdb.settings = self.repo_settings.repoman_settings
12960 -
12961 - digest_only = (
12962 - self.options.mode != "manifest-check" and self.options.digest == "y"
12963 - )
12964 - self.generate_manifest = digest_only or self.options.mode in (
12965 - "manifest",
12966 - "commit",
12967 - "fix",
12968 - )
12969 -
12970 - # We really only need to cache the metadata that's necessary for visibility
12971 - # filtering. Anything else can be discarded to reduce memory consumption.
12972 - if not self.generate_manifest:
12973 - # Don't do this when generating manifests, since that uses
12974 - # additional keys if spawn_nofetch is called (RESTRICT and
12975 - # DEFINED_PHASES).
12976 - self.portdb._aux_cache_keys.clear()
12977 - self.portdb._aux_cache_keys.update(
12978 - ["EAPI", "IUSE", "KEYWORDS", "repository", "SLOT"]
12979 - )
12980 -
12981 - self.reposplit = myreporoot.split(os.path.sep)
12982 - self.repolevel = len(self.reposplit)
12983 -
12984 - if self.options.mode == "commit":
12985 - repochecks.commit_check(self.repolevel, self.reposplit)
12986 - repochecks.conflict_check(self.vcs_settings, self.options)
12987 -
12988 - # Make startdir relative to the canonical repodir, so that we can pass
12989 - # it to digestgen and it won't have to be canonicalized again.
12990 - if self.repolevel == 1:
12991 - startdir = self.repo_settings.repodir
12992 - else:
12993 - startdir = normalize_path(mydir)
12994 - startdir = os.path.join(
12995 - self.repo_settings.repodir,
12996 - *startdir.split(os.sep)[-2 - self.repolevel + 3 :]
12997 - )
12998 -
12999 - # get lists of valid keywords, licenses, and use
13000 - new_data = repo_metadata(self.portdb, self.repo_settings.repoman_settings)
13001 - (
13002 - kwlist,
13003 - liclist,
13004 - uselist,
13005 - profile_list,
13006 - global_pmaskdict,
13007 - liclist_deprecated,
13008 - ) = new_data
13009 - self.repo_metadata = {
13010 - "kwlist": kwlist,
13011 - "liclist": liclist,
13012 - "uselist": uselist,
13013 - "profile_list": profile_list,
13014 - "pmaskdict": global_pmaskdict,
13015 - "lic_deprecated": liclist_deprecated,
13016 - "package.deprecated": InternalPackageSet(
13017 - initial_atoms=portage.util.stack_lists(
13018 - [
13019 - portage.util.grabfile_package(
13020 - os.path.join(path, "profiles", "package.deprecated"),
13021 - recursive=True,
13022 - )
13023 - for path in self.portdb.porttrees
13024 - ],
13025 - incremental=True,
13026 - )
13027 - ),
13028 - }
13029 -
13030 - self.repo_settings.repoman_settings["PORTAGE_ARCHLIST"] = " ".join(
13031 - sorted(kwlist)
13032 - )
13033 - self.repo_settings.repoman_settings.backup_changes("PORTAGE_ARCHLIST")
13034 -
13035 - profiles = setup_profile(profile_list)
13036 -
13037 - check_profiles(profiles, self.repo_settings.repoman_settings.archlist())
13038 -
13039 - scanlist = scan(
13040 - self.repolevel,
13041 - self.reposplit,
13042 - startdir,
13043 - self.categories,
13044 - self.repo_settings,
13045 - )
13046 -
13047 - self.dev_keywords = dev_profile_keywords(profiles)
13048 -
13049 - self.qatracker = self.vcs_settings.qatracker
13050 -
13051 - if (
13052 - self.options.echangelog is None
13053 - and self.repo_settings.repo_config.update_changelog
13054 - ):
13055 - self.options.echangelog = "y"
13056 -
13057 - if self.vcs_settings.vcs is None:
13058 - self.options.echangelog = "n"
13059 -
13060 - # Initialize the ModuleConfig class here
13061 - # TODO Add layout.conf masters repository.yml config to the list to load/stack
13062 - self.moduleconfig = ModuleConfig(
13063 - self.repo_settings.masters_list,
13064 - self.repo_settings.repoman_settings.valid_versions,
13065 - repository_modules=self.options.experimental_repository_modules == "y",
13066 - )
13067 -
13068 - checks = {}
13069 - # The --echangelog option causes automatic ChangeLog generation,
13070 - # which invalidates changelog.ebuildadded and changelog.missing
13071 - # checks.
13072 - # Note: Some don't use ChangeLogs in distributed SCMs.
13073 - # It will be generated on server side from scm log,
13074 - # before package moves to the rsync server.
13075 - # This is needed because they try to avoid merge collisions.
13076 - # Gentoo's Council decided to always use the ChangeLog file.
13077 - # TODO: shouldn't this just be switched on the repo, iso the VCS?
13078 - is_echangelog_enabled = self.options.echangelog in ("y", "force")
13079 - self.vcs_settings.vcs_is_cvs_or_svn = self.vcs_settings.vcs in ("cvs", "svn")
13080 - checks["changelog"] = (
13081 - not is_echangelog_enabled and self.vcs_settings.vcs_is_cvs_or_svn
13082 - )
13083 -
13084 - if self.options.mode == "manifest" or self.options.quiet:
13085 - pass
13086 - elif self.options.pretend:
13087 - print(green("\nRepoMan does a once-over of the neighborhood..."))
13088 - else:
13089 - print(green("\nRepoMan scours the neighborhood..."))
13090 -
13091 - self.changed = self.vcs_settings.changes
13092 - # bypass unneeded VCS operations if not needed
13093 - if self.options.if_modified == "y" or self.options.mode not in (
13094 - "manifest",
13095 - "manifest-check",
13096 - ):
13097 - self.changed.scan()
13098 -
13099 - self.have = {
13100 - "pmasked": False,
13101 - "dev_keywords": False,
13102 - }
13103 -
13104 - # NOTE: match-all caches are not shared due to potential
13105 - # differences between profiles in _get_implicit_iuse.
13106 - self.caches = {
13107 - "arch": {},
13108 - "arch_xmatch": {},
13109 - "shared_xmatch": {"cp-list": {}},
13110 - }
13111 -
13112 - self.include_arches = None
13113 - if self.options.include_arches:
13114 - self.include_arches = set()
13115 - self.include_arches.update(
13116 - *[x.split() for x in self.options.include_arches]
13117 - )
13118 - self.include_profiles = None
13119 - if self.options.include_profiles:
13120 - self.include_profiles = set()
13121 - self.include_profiles.update(
13122 - *[x.split() for x in self.options.include_profiles]
13123 - )
13124 -
13125 - # Disable the "self.modules['Ebuild'].notadded" check when not in commit mode and
13126 - # running `svn status` in every package dir will be too expensive.
13127 - checks["ebuild_notadded"] = not (
13128 - self.vcs_settings.vcs == "svn"
13129 - and self.repolevel < 3
13130 - and self.options.mode != "commit"
13131 - )
13132 -
13133 - self.effective_scanlist = scanlist
13134 - if self.options.if_modified == "y":
13135 - self.effective_scanlist = sorted(
13136 - vcs_files_to_cps(
13137 - chain(self.changed.changed, self.changed.new, self.changed.removed),
13138 - self.repo_settings.repodir,
13139 - self.repolevel,
13140 - self.reposplit,
13141 - self.categories,
13142 - )
13143 - )
13144 -
13145 - # Create our kwargs dict here to initialize the plugins with
13146 - self.kwargs = {
13147 - "repo_settings": self.repo_settings,
13148 - "portdb": self.portdb,
13149 - "qatracker": self.qatracker,
13150 - "vcs_settings": self.vcs_settings,
13151 - "options": self.options,
13152 - "metadata_xsd": get_metadata_xsd(self.repo_settings),
13153 - "uselist": uselist,
13154 - "checks": checks,
13155 - "repo_metadata": self.repo_metadata,
13156 - "profiles": profiles,
13157 - "include_arches": self.include_arches,
13158 - "include_profiles": self.include_profiles,
13159 - "caches": self.caches,
13160 - "repoman_incrementals": self.repoman_incrementals,
13161 - "env": self.env,
13162 - "have": self.have,
13163 - "dev_keywords": self.dev_keywords,
13164 - "linechecks": self.moduleconfig.linechecks,
13165 - }
13166 - # initialize the plugin checks here
13167 - self.modules = {}
13168 - self._ext_futures = {}
13169 - self.pkg_level_futures = None
13170 -
13171 - def set_kwargs(self, mod):
13172 - """Creates a limited set of kwargs to pass to the module's __init__()
13173 -
13174 - @param mod: module name string
13175 - @returns: dictionary
13176 - """
13177 - kwargs = {}
13178 - for key in self.moduleconfig.controller.modules[mod]["mod_kwargs"]:
13179 - kwargs[key] = self.kwargs[key]
13180 - return kwargs
13181 -
13182 - def set_func_kwargs(self, mod, dynamic_data=None):
13183 - """Updates the dynamic_data dictionary with any new key, value pairs.
13184 - Creates a limited set of kwargs to pass to the modulefunctions to run
13185 -
13186 - @param mod: module name string
13187 - @param dynamic_data: dictionary structure
13188 - @returns: dictionary
13189 - """
13190 - func_kwargs = self.moduleconfig.controller.modules[mod]["func_kwargs"]
13191 - # determine new keys
13192 - required = set(list(func_kwargs))
13193 - exist = set(list(dynamic_data))
13194 - new = required.difference(exist)
13195 - # update dynamic_data with initialized entries
13196 - for key in new:
13197 - logging.debug("set_func_kwargs(); adding: %s, %s", key, func_kwargs[key])
13198 - if func_kwargs[key][0] in ["Future", "ExtendedFuture"]:
13199 - if key not in self._ext_futures:
13200 - logging.debug(
13201 - "Adding a new key: %s to the ExtendedFuture dict", key
13202 - )
13203 - self._ext_futures[key] = func_kwargs[key]
13204 - self._set_future(dynamic_data, key, func_kwargs[key])
13205 - else: # builtin python data type
13206 - dynamic_data[key] = DATA_TYPES[func_kwargs[key][0]]()
13207 - kwargs = {}
13208 - for key in required:
13209 - kwargs[key] = dynamic_data[key]
13210 - return kwargs
13211 -
13212 - def reset_futures(self, dynamic_data):
13213 - """Reset any Future data types
13214 -
13215 - @param dynamic_data: dictionary
13216 - """
13217 - for key in list(self._ext_futures):
13218 - if key not in self.pkg_level_futures:
13219 - self._set_future(dynamic_data, key, self._ext_futures[key])
13220 -
13221 - @staticmethod
13222 - def _set_future(dynamic_data, key, data):
13223 - """Set a dynamic_data key to a new ExtendedFuture instance
13224 -
13225 - @param dynamic_data: dictionary
13226 - @param key: tuple of (dictionary-key, default-value)
13227 - """
13228 - if data[0] in ["Future", "ExtendedFuture"]:
13229 - if data[1] in ["UNSET"]:
13230 - dynamic_data[key] = ExtendedFuture()
13231 - else:
13232 - if data[1] in DATA_TYPES:
13233 - default = DATA_TYPES[data[1]]()
13234 - else:
13235 - default = data[1]
13236 - dynamic_data[key] = ExtendedFuture(default)
13237 -
13238 - def scan_pkgs(self, can_force):
13239 - for xpkg in self.effective_scanlist:
13240 - xpkg_continue = False
13241 - # ebuilds and digests added to cvs respectively.
13242 - logging.info("checking package %s", xpkg)
13243 - # save memory by discarding xmatch caches from previous package(s)
13244 - self.caches["arch_xmatch"].clear()
13245 - catdir, pkgdir = xpkg.split("/")
13246 - checkdir = self.repo_settings.repodir + "/" + xpkg
13247 - checkdir_relative = ""
13248 - if self.repolevel < 3:
13249 - checkdir_relative = os.path.join(pkgdir, checkdir_relative)
13250 - if self.repolevel < 2:
13251 - checkdir_relative = os.path.join(catdir, checkdir_relative)
13252 - checkdir_relative = os.path.join(".", checkdir_relative)
13253 -
13254 - # Run the status check
13255 - if self.kwargs["checks"]["ebuild_notadded"]:
13256 - self.vcs_settings.status.check(checkdir, checkdir_relative, xpkg)
13257 -
13258 - if self.generate_manifest:
13259 - if not manifest.Manifest(**self.kwargs).update_manifest(checkdir):
13260 - self.qatracker.add_error(
13261 - "manifest.bad", os.path.join(xpkg, "Manifest")
13262 - )
13263 - if self.options.mode == "manifest":
13264 - continue
13265 - checkdirlist = os.listdir(checkdir)
13266 -
13267 - dynamic_data = {
13268 - "changelog_modified": False,
13269 - "checkdirlist": ExtendedFuture(checkdirlist),
13270 - "checkdir": checkdir,
13271 - "xpkg": xpkg,
13272 - "changed": self.changed,
13273 - "checkdir_relative": checkdir_relative,
13274 - "can_force": can_force,
13275 - "repolevel": self.repolevel,
13276 - "catdir": catdir,
13277 - "pkgdir": pkgdir,
13278 - "validity_future": ExtendedFuture(True),
13279 - "y_ebuild": None,
13280 - # this needs to be reset at the pkg level only,
13281 - # easiest is to just initialize it here
13282 - "muselist": ExtendedFuture(set()),
13283 - "src_uri_error": ExtendedFuture(),
13284 - }
13285 - self.pkg_level_futures = [
13286 - "checkdirlist",
13287 - "muselist",
13288 - "pkgs",
13289 - "src_uri_error",
13290 - "validity_future",
13291 - ]
13292 - # need to set it up for ==> self.modules or some other ordered list
13293 - logging.debug("***** starting pkgs_loop: %s", self.moduleconfig.pkgs_loop)
13294 - for mod in self.moduleconfig.pkgs_loop:
13295 - mod_class = self.moduleconfig.controller.get_class(mod)
13296 - logging.debug("Initializing class name: %s", mod_class.__name__)
13297 - self.modules[mod_class.__name__] = mod_class(**self.set_kwargs(mod))
13298 - logging.debug("scan_pkgs; module: %s", mod_class.__name__)
13299 - do_it, functions = self.modules[mod_class.__name__].runInPkgs
13300 - if do_it:
13301 - for func in functions:
13302 - _continue = func(**self.set_func_kwargs(mod, dynamic_data))
13303 - if _continue:
13304 - # If we can't access all the metadata then it's totally unsafe to
13305 - # commit since there's no way to generate a correct Manifest.
13306 - # Do not try to do any more QA checks on this package since missing
13307 - # metadata leads to false positives for several checks, and false
13308 - # positives confuse users.
13309 - xpkg_continue = True
13310 - break
13311 -
13312 - if xpkg_continue:
13313 - continue
13314 -
13315 - # Sort ebuilds in ascending order for the KEYWORDS.dropped check.
13316 - pkgs = dynamic_data["pkgs"].get()
13317 - ebuildlist = sorted(pkgs.values())
13318 - ebuildlist = [pkg.pf for pkg in ebuildlist]
13319 -
13320 - if self.kwargs["checks"]["changelog"] and "ChangeLog" not in checkdirlist:
13321 - self.qatracker.add_error("changelog.missing", xpkg + "/ChangeLog")
13322 -
13323 - changelog_path = os.path.join(checkdir_relative, "ChangeLog")
13324 - dynamic_data["changelog_modified"] = (
13325 - changelog_path in self.changed.changelogs
13326 - )
13327 -
13328 - self._scan_ebuilds(ebuildlist, dynamic_data)
13329 -
13330 - def _scan_ebuilds(self, ebuildlist, dynamic_data):
13331 -
13332 - for y_ebuild in ebuildlist:
13333 - self.reset_futures(dynamic_data)
13334 - dynamic_data["y_ebuild"] = y_ebuild
13335 -
13336 - # initialize per ebuild plugin checks here
13337 - # need to set it up for ==> self.modules_list or some other ordered list
13338 - for mod in self.moduleconfig.ebuilds_loop:
13339 - if mod:
13340 - mod_class = self.moduleconfig.controller.get_class(mod)
13341 - if mod_class.__name__ not in self.modules:
13342 - logging.debug("Initializing class name: %s", mod_class.__name__)
13343 - self.modules[mod_class.__name__] = mod_class(
13344 - **self.set_kwargs(mod)
13345 - )
13346 - logging.debug("scan_ebuilds: module: %s", mod_class.__name__)
13347 - do_it, functions = self.modules[mod_class.__name__].runInEbuilds
13348 - logging.debug(
13349 - "do_it: %s, functions: %s", do_it, [x.__name__ for x in functions]
13350 - )
13351 - if do_it:
13352 - for func in functions:
13353 - logging.debug("\tRunning function: %s", func)
13354 - _continue = func(**self.set_func_kwargs(mod, dynamic_data))
13355 - if _continue:
13356 - # If we can't access all the metadata then it's totally unsafe to
13357 - # commit since there's no way to generate a correct Manifest.
13358 - # Do not try to do any more QA checks on this package since missing
13359 - # metadata leads to false positives for several checks, and false
13360 - # positives confuse users.
13361 - # logging.debug("\t>>> Continuing")
13362 - break
13363 -
13364 - logging.debug("Finished ebuild plugin loop, continuing...")
13365 -
13366 - # Final checks
13367 - # initialize per pkg plugin final checks here
13368 - # need to set it up for ==> self.modules_list or some other ordered list
13369 - for mod in self.moduleconfig.final_loop:
13370 - if mod:
13371 - mod_class = self.moduleconfig.controller.get_class(mod)
13372 - if mod_class.__name__ not in self.modules:
13373 - logging.debug("Initializing class name: %s", mod_class.__name__)
13374 - self.modules[mod_class.__name__] = mod_class(**self.set_kwargs(mod))
13375 - logging.debug("scan_ebuilds final checks: module: %s", mod_class.__name__)
13376 - do_it, functions = self.modules[mod_class.__name__].runInFinal
13377 - logging.debug(
13378 - "do_it: %s, functions: %s", do_it, [x.__name__ for x in functions]
13379 - )
13380 - if do_it:
13381 - for func in functions:
13382 - logging.debug("\tRunning function: %s", func)
13383 - _continue = func(**self.set_func_kwargs(mod, dynamic_data))
13384 - if _continue:
13385 - # logging.debug("\t>>> Continuing")
13386 - break
13387
13388 diff --git a/repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/06B3A311BD775C280D22A9305D90EA06352177F6.rev b/repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/06B3A311BD775C280D22A9305D90EA06352177F6.rev
13389 deleted file mode 100644
13390 index a6752fd30..000000000
13391 --- a/repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/06B3A311BD775C280D22A9305D90EA06352177F6.rev
13392 +++ /dev/null
13393 @@ -1,37 +0,0 @@
13394 -This is a revocation certificate for the OpenPGP key:
13395 -
13396 -pub rsa4096 2020-07-14 [S]
13397 - 06B3A311BD775C280D22A9305D90EA06352177F6
13398 -uid Gentoo Portage Test Trusted Key (Test Only, Do NOT Trust!!!) (Gentoo Test Key) <test@×××××××.org>
13399 -
13400 -A revocation certificate is a kind of "kill switch" to publicly
13401 -declare that a key shall not anymore be used. It is not possible
13402 -to retract such a revocation certificate once it has been published.
13403 -
13404 -Use it to revoke this key in case of a compromise or loss of
13405 -the secret key. However, if the secret key is still accessible,
13406 -it is better to generate a new revocation certificate and give
13407 -a reason for the revocation. For details see the description of
13408 -of the gpg command "--generate-revocation" in the GnuPG manual.
13409 -
13410 -To avoid an accidental use of this file, a colon has been inserted
13411 -before the 5 dashes below. Remove this colon with a text editor
13412 -before importing and publishing this revocation certificate.
13413 -
13414 -:-----BEGIN PGP PUBLIC KEY BLOCK-----
13415 -Comment: This is a revocation certificate
13416 -
13417 -iQI2BCABCAAgFiEEBrOjEb13XCgNIqkwXZDqBjUhd/YFAl8OFTwCHQAACgkQXZDq
13418 -BjUhd/aXCA/+OgzosMDaDe5DNwkSi2yKdC2X18v8JcaYnXBUR93nXA0LVN7iVWkR
13419 -WEH3NuVspQZ5vK+3AHTKabqZFC/buA5oQOH01Ncd4lQISfOOhFiBn5DIPX31BVT0
13420 -iPmVkcxHAD4031ptP4oat6EFclT13SRchtlnAO04JofeHnzQIw3SozQGzXpAA1g4
13421 -BogQ0HWA88HzuEYYE+e/yzZL4D496X1DTaXksg0Py5c4SS6u5pND6lcUtAGxAwa9
13422 -sJFPs+coeURaRV99CrJfdh4u2OkvINTfrKOS6NFBQq6HVH5mLsRXZlcE4Oo4d+fN
13423 -XoPrTZnRUqpJADUdjHFvO/lr0fArJTS5IQCVBNFeCMlvgmUPeKWJ1r6Uiwe/UHor
13424 -9OP/tK97EqpsaXmHbo0jOUkn5iiUwy784+JBSSu/Q2NxqcBr74aaRdfxvs62dmv7
13425 -droCDQi3ebqTdnlDSaeCIWHyVlSroOhZ+ZETVy193K1X7VXFX3hYKiJ3G8QZwy3e
13426 -AlsVGjIHWfC+K+enIn+uwSUvOWPN3upK8kqMRuXvAOppFCE4sTqNbxUnHHXaqo/r
13427 -s1q6zVsWVILBk97BHlJph2IaqhV7iIgPU97/r4U/BT11VqDFdVSHcXcs4PDNs5vh
13428 -6qttaDiyDqZjwMr+0iDoouHxFpqY8e+3M2gycUgGr2XV6ML0pXE6BqA=
13429 -=nIjC
13430 ------END PGP PUBLIC KEY BLOCK-----
13431
13432 diff --git a/repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/8DEDA2CDED49C8809287B89D8812797DDF1DD192.rev b/repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/8DEDA2CDED49C8809287B89D8812797DDF1DD192.rev
13433 deleted file mode 100644
13434 index 456e0aa50..000000000
13435 --- a/repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/8DEDA2CDED49C8809287B89D8812797DDF1DD192.rev
13436 +++ /dev/null
13437 @@ -1,37 +0,0 @@
13438 -This is a revocation certificate for the OpenPGP key:
13439 -
13440 -pub rsa4096 2020-07-14 [S]
13441 - 8DEDA2CDED49C8809287B89D8812797DDF1DD192
13442 -uid Gentoo Portage Test Untrusted Key (Test Only, Do NOT Trust!!!) (Gentoo Test Key) <test@×××××××.org>
13443 -
13444 -A revocation certificate is a kind of "kill switch" to publicly
13445 -declare that a key shall not anymore be used. It is not possible
13446 -to retract such a revocation certificate once it has been published.
13447 -
13448 -Use it to revoke this key in case of a compromise or loss of
13449 -the secret key. However, if the secret key is still accessible,
13450 -it is better to generate a new revocation certificate and give
13451 -a reason for the revocation. For details see the description of
13452 -of the gpg command "--generate-revocation" in the GnuPG manual.
13453 -
13454 -To avoid an accidental use of this file, a colon has been inserted
13455 -before the 5 dashes below. Remove this colon with a text editor
13456 -before importing and publishing this revocation certificate.
13457 -
13458 -:-----BEGIN PGP PUBLIC KEY BLOCK-----
13459 -Comment: This is a revocation certificate
13460 -
13461 -iQI2BCABCAAgFiEEje2ize1JyICSh7idiBJ5fd8d0ZIFAl8OFXUCHQAACgkQiBJ5
13462 -fd8d0ZKdwxAAhmkC0V+OLyOU9PCV6ogD9/3b3nVqNIreoc+gxHTLmEvxiMSItqmq
13463 -DkcW9RJKAduA/HiLZQ8Yzxw+ldC6kuWqYEjNpSM54VDkrgOePi8W1bVDTCoSp7bo
13464 -0JOG4frieqIxA6lhAA2UppH7EPRXoODPLYqooNxWAs3xxVrR6eGAb5l8NXzrymvN
13465 -acFfOZ0s5FgADQskQHWVq6TaJn9DrcZxd+b+plSwPYDXqzTChKQ5jw7uMAPUvDkG
13466 -JUWgoKiKSrK64bslUq8aEDEZQ4uxjyEi6G0vO/wPL/ysGhS7KkPgCZsEfNjWjajb
13467 -jAsdvl1raoHxK/O7llMNr9uRAZtC56pJ//SRDc3kylZrkAo0RNoXQFowT739HWei
13468 -2UkCFDfz488VKKrOI8TzTyUvLFEo14ZAXGg1wdHaGnbYMzxpKjP15alOFo6fKIcS
13469 -Kz1f/Mab4wf4Sg0XAjQ9pnai1/U9ZF3/NSnRtYgJkLCrIEtRLrgSHJsLDPxjCfGV
13470 -jWszAbIk167aA0yKsSmuwkpc5bZqqBaTo904r857fxyt5Les6SOHsV7iNXt7F+am
13471 -03Y6u6m2eROba7M67l115vTyYcw5EZVp5j0nI81PXsC9X2DD1ci5xrNmPyEeupC4
13472 -7y7mcGbUYPJAJHJ0kHG4ZYLnNMl42ZYr1ssEeasDwUsLWgVqvx9RkKI=
13473 -=kVUQ
13474 ------END PGP PUBLIC KEY BLOCK-----
13475
13476 diff --git a/repoman/lib/repoman/tests/.gnupg/private-keys-v1.d/273B030399E7BEA66A9AD42216DE7CA17BA5D42E.key b/repoman/lib/repoman/tests/.gnupg/private-keys-v1.d/273B030399E7BEA66A9AD42216DE7CA17BA5D42E.key
13477 deleted file mode 100644
13478 index 0bd1026ad..000000000
13479 Binary files a/repoman/lib/repoman/tests/.gnupg/private-keys-v1.d/273B030399E7BEA66A9AD42216DE7CA17BA5D42E.key and /dev/null differ
13480
13481 diff --git a/repoman/lib/repoman/tests/.gnupg/private-keys-v1.d/C99796FB85B0C3DF03314A11B5850C51167D6282.key b/repoman/lib/repoman/tests/.gnupg/private-keys-v1.d/C99796FB85B0C3DF03314A11B5850C51167D6282.key
13482 deleted file mode 100644
13483 index 8e29ef43c..000000000
13484 Binary files a/repoman/lib/repoman/tests/.gnupg/private-keys-v1.d/C99796FB85B0C3DF03314A11B5850C51167D6282.key and /dev/null differ
13485
13486 diff --git a/repoman/lib/repoman/tests/.gnupg/pubring.kbx b/repoman/lib/repoman/tests/.gnupg/pubring.kbx
13487 deleted file mode 100644
13488 index f6367f83b..000000000
13489 Binary files a/repoman/lib/repoman/tests/.gnupg/pubring.kbx and /dev/null differ
13490
13491 diff --git a/repoman/lib/repoman/tests/.gnupg/trustdb.gpg b/repoman/lib/repoman/tests/.gnupg/trustdb.gpg
13492 deleted file mode 100644
13493 index db5b1023b..000000000
13494 Binary files a/repoman/lib/repoman/tests/.gnupg/trustdb.gpg and /dev/null differ
13495
13496 diff --git a/repoman/lib/repoman/tests/__init__.py b/repoman/lib/repoman/tests/__init__.py
13497 deleted file mode 100644
13498 index ba0872c5b..000000000
13499 --- a/repoman/lib/repoman/tests/__init__.py
13500 +++ /dev/null
13501 @@ -1,328 +0,0 @@
13502 -# tests/__init__.py -- Portage Unit Test functionality
13503 -# Copyright 2006-2021 Gentoo Authors
13504 -# Distributed under the terms of the GNU General Public License v2
13505 -
13506 -import argparse
13507 -import sys
13508 -import time
13509 -import unittest
13510 -
13511 -from unittest.runner import TextTestResult as _TextTestResult
13512 -
13513 -import repoman
13514 -from repoman import REPOMAN_BASE_PATH
13515 -from repoman._portage import portage
13516 -
13517 -from portage import os
13518 -from portage import _encodings
13519 -from portage import _unicode_decode
13520 -from portage.const import EPREFIX, GLOBAL_CONFIG_PATH, PORTAGE_BIN_PATH
13521 -
13522 -if repoman._not_installed:
13523 - cnf_path = os.path.join(REPOMAN_BASE_PATH, "cnf")
13524 - cnf_path_repoman = cnf_path
13525 - cnf_etc_path = cnf_path
13526 - cnf_bindir = os.path.join(REPOMAN_BASE_PATH, "bin")
13527 - cnf_sbindir = cnf_bindir
13528 -else:
13529 - cnf_path = os.path.join(EPREFIX or "/", GLOBAL_CONFIG_PATH)
13530 - cnf_path_repoman = os.path.join(
13531 - EPREFIX or "/", sys.prefix.lstrip(os.sep), "share", "repoman"
13532 - )
13533 - cnf_etc_path = os.path.join(EPREFIX or "/", "etc")
13534 - cnf_eprefix = EPREFIX
13535 - cnf_bindir = os.path.join(EPREFIX or "/", "usr", "bin")
13536 - cnf_sbindir = os.path.join(EPREFIX or "/", "usr", "sbin")
13537 -
13538 -
13539 -def main():
13540 - suite = unittest.TestSuite()
13541 - basedir = os.path.dirname(os.path.realpath(__file__))
13542 -
13543 - usage = "usage: %s [options] [tests to run]" % os.path.basename(sys.argv[0])
13544 - parser = argparse.ArgumentParser(usage=usage)
13545 - parser.add_argument(
13546 - "-l", "--list", help="list all tests", action="store_true", dest="list_tests"
13547 - )
13548 - options, args = parser.parse_known_args(args=sys.argv)
13549 -
13550 - if (
13551 - os.environ.get("NOCOLOR") in ("yes", "true")
13552 - or os.environ.get("TERM") == "dumb"
13553 - or not sys.stdout.isatty()
13554 - ):
13555 - portage.output.nocolor()
13556 -
13557 - if options.list_tests:
13558 - testdir = os.path.dirname(sys.argv[0])
13559 - for mydir in getTestDirs(basedir):
13560 - testsubdir = os.path.basename(mydir)
13561 - for name in getTestNames(mydir):
13562 - print("%s/%s/%s.py" % (testdir, testsubdir, name))
13563 - return os.EX_OK
13564 -
13565 - if len(args) > 1:
13566 - suite.addTests(getTestFromCommandLine(args[1:], basedir))
13567 - else:
13568 - for mydir in getTestDirs(basedir):
13569 - suite.addTests(getTests(os.path.join(basedir, mydir), basedir))
13570 -
13571 - result = TextTestRunner(verbosity=2).run(suite)
13572 - if not result.wasSuccessful():
13573 - return 1
13574 - return os.EX_OK
13575 -
13576 -
13577 -def my_import(name):
13578 - mod = __import__(name)
13579 - components = name.split(".")
13580 - for comp in components[1:]:
13581 - mod = getattr(mod, comp)
13582 - return mod
13583 -
13584 -
13585 -def getTestFromCommandLine(args, base_path):
13586 - result = []
13587 - for arg in args:
13588 - realpath = os.path.realpath(arg)
13589 - path = os.path.dirname(realpath)
13590 - f = realpath[len(path) + 1 :]
13591 -
13592 - if not f.startswith("test") or not f.endswith(".py"):
13593 - raise Exception("Invalid argument: '%s'" % arg)
13594 -
13595 - mymodule = f[:-3]
13596 - result.extend(getTestsFromFiles(path, base_path, [mymodule]))
13597 - return result
13598 -
13599 -
13600 -def getTestDirs(base_path):
13601 - TEST_FILE = b"__test__.py"
13602 - testDirs = []
13603 -
13604 - # the os.walk help mentions relative paths as being quirky
13605 - # I was tired of adding dirs to the list, so now we add __test__.py
13606 - # to each dir we want tested.
13607 - for root, dirs, files in os.walk(base_path):
13608 - try:
13609 - root = _unicode_decode(root, encoding=_encodings["fs"], errors="strict")
13610 - except UnicodeDecodeError:
13611 - continue
13612 -
13613 - if TEST_FILE in files:
13614 - testDirs.append(root)
13615 -
13616 - testDirs.sort()
13617 - return testDirs
13618 -
13619 -
13620 -def getTestNames(path):
13621 - files = os.listdir(path)
13622 - files = [f[:-3] for f in files if f.startswith("test") and f.endswith(".py")]
13623 - files.sort()
13624 - return files
13625 -
13626 -
13627 -def getTestsFromFiles(path, base_path, files):
13628 - parent_path = path[len(base_path) + 1 :]
13629 - parent_module = ".".join(("repoman", "tests", parent_path))
13630 - parent_module = parent_module.replace("/", ".")
13631 - result = []
13632 - for mymodule in files:
13633 - # Make the trailing / a . for module importing
13634 - modname = ".".join((parent_module, mymodule))
13635 - mod = my_import(modname)
13636 - result.append(unittest.TestLoader().loadTestsFromModule(mod))
13637 - return result
13638 -
13639 -
13640 -def getTests(path, base_path):
13641 - """
13642 -
13643 - path is the path to a given subdir ( 'portage/' for example)
13644 - This does a simple filter on files in that dir to give us modules
13645 - to import
13646 -
13647 - """
13648 - return getTestsFromFiles(path, base_path, getTestNames(path))
13649 -
13650 -
13651 -class TextTestResult(_TextTestResult):
13652 - """
13653 - We need a subclass of unittest.runner.TextTestResult to handle tests with TODO
13654 -
13655 - This just adds an addTodo method that can be used to add tests
13656 - that are marked TODO; these can be displayed later
13657 - by the test runner.
13658 - """
13659 -
13660 - def __init__(self, stream, descriptions, verbosity):
13661 - super(TextTestResult, self).__init__(stream, descriptions, verbosity)
13662 - self.todoed = []
13663 - self.portage_skipped = []
13664 -
13665 - def addTodo(self, test, info):
13666 - self.todoed.append((test, info))
13667 - if self.showAll:
13668 - self.stream.writeln("TODO")
13669 - elif self.dots:
13670 - self.stream.write(".")
13671 -
13672 - def addPortageSkip(self, test, info):
13673 - self.portage_skipped.append((test, info))
13674 - if self.showAll:
13675 - self.stream.writeln("SKIP")
13676 - elif self.dots:
13677 - self.stream.write(".")
13678 -
13679 - def printErrors(self):
13680 - if self.dots or self.showAll:
13681 - self.stream.writeln()
13682 - self.printErrorList("ERROR", self.errors)
13683 - self.printErrorList("FAIL", self.failures)
13684 - self.printErrorList("TODO", self.todoed)
13685 - self.printErrorList("SKIP", self.portage_skipped)
13686 -
13687 -
13688 -class TestCase(unittest.TestCase):
13689 - """
13690 - We need a way to mark a unit test as "ok to fail"
13691 - This way someone can add a broken test and mark it as failed
13692 - and then fix the code later. This may not be a great approach
13693 - (broken code!!??!11oneone) but it does happen at times.
13694 - """
13695 -
13696 - def __init__(self, *pargs, **kwargs):
13697 - unittest.TestCase.__init__(self, *pargs, **kwargs)
13698 - self.todo = False
13699 - self.portage_skip = None
13700 - self.cnf_path = cnf_path
13701 - self.cnf_etc_path = cnf_etc_path
13702 - self.bindir = cnf_bindir
13703 - self.sbindir = cnf_sbindir
13704 -
13705 - def defaultTestResult(self):
13706 - return TextTestResult()
13707 -
13708 - def run(self, result=None):
13709 - if result is None:
13710 - result = self.defaultTestResult()
13711 - result.startTest(self)
13712 - testMethod = getattr(self, self._testMethodName)
13713 - try:
13714 - try:
13715 - self.setUp()
13716 - except SystemExit:
13717 - raise
13718 - except KeyboardInterrupt:
13719 - raise
13720 - except:
13721 - result.addError(self, sys.exc_info())
13722 - return
13723 -
13724 - ok = False
13725 - try:
13726 - testMethod()
13727 - ok = True
13728 - except unittest.SkipTest as e:
13729 - result.addPortageSkip(self, "%s: SKIP: %s" % (testMethod, str(e)))
13730 - except self.failureException:
13731 - if self.portage_skip is not None:
13732 - if self.portage_skip is True:
13733 - result.addPortageSkip(self, "%s: SKIP" % testMethod)
13734 - else:
13735 - result.addPortageSkip(
13736 - self, "%s: SKIP: %s" % (testMethod, self.portage_skip)
13737 - )
13738 - elif self.todo:
13739 - result.addTodo(self, "%s: TODO" % testMethod)
13740 - else:
13741 - result.addFailure(self, sys.exc_info())
13742 - except (KeyboardInterrupt, SystemExit):
13743 - raise
13744 - except:
13745 - result.addError(self, sys.exc_info())
13746 -
13747 - try:
13748 - self.tearDown()
13749 - except SystemExit:
13750 - raise
13751 - except KeyboardInterrupt:
13752 - raise
13753 - except:
13754 - result.addError(self, sys.exc_info())
13755 - ok = False
13756 - if ok:
13757 - result.addSuccess(self)
13758 - finally:
13759 - result.stopTest(self)
13760 -
13761 - def assertRaisesMsg(self, msg, excClass, callableObj, *args, **kwargs):
13762 - """Fail unless an exception of class excClass is thrown
13763 - by callableObj when invoked with arguments args and keyword
13764 - arguments kwargs. If a different type of exception is
13765 - thrown, it will not be caught, and the test case will be
13766 - deemed to have suffered an error, exactly as for an
13767 - unexpected exception.
13768 - """
13769 - try:
13770 - callableObj(*args, **kwargs)
13771 - except excClass:
13772 - return
13773 - else:
13774 - if hasattr(excClass, "__name__"):
13775 - excName = excClass.__name__
13776 - else:
13777 - excName = str(excClass)
13778 - raise self.failureException("%s not raised: %s" % (excName, msg))
13779 -
13780 - def assertNotExists(self, path):
13781 - """Make sure |path| does not exist"""
13782 - if os.path.exists(path):
13783 - raise self.failureException("path exists when it should not: %s" % path)
13784 -
13785 -
13786 -class TextTestRunner(unittest.TextTestRunner):
13787 - """
13788 - We subclass unittest.TextTestRunner to output SKIP for tests that fail but are skippable
13789 - """
13790 -
13791 - def _makeResult(self):
13792 - return TextTestResult(self.stream, self.descriptions, self.verbosity)
13793 -
13794 - def run(self, test):
13795 - """
13796 - Run the given test case or test suite.
13797 - """
13798 - result = self._makeResult()
13799 - startTime = time.time()
13800 - test(result)
13801 - stopTime = time.time()
13802 - timeTaken = stopTime - startTime
13803 - result.printErrors()
13804 - self.stream.writeln(result.separator2)
13805 - run = result.testsRun
13806 - self.stream.writeln(
13807 - "Ran %d test%s in %.3fs" % (run, run != 1 and "s" or "", timeTaken)
13808 - )
13809 - self.stream.writeln()
13810 - if not result.wasSuccessful():
13811 - self.stream.write("FAILED (")
13812 - failed = len(result.failures)
13813 - errored = len(result.errors)
13814 - if failed:
13815 - self.stream.write("failures=%d" % failed)
13816 - if errored:
13817 - if failed:
13818 - self.stream.write(", ")
13819 - self.stream.write("errors=%d" % errored)
13820 - self.stream.writeln(")")
13821 - else:
13822 - self.stream.writeln("OK")
13823 - return result
13824 -
13825 -
13826 -test_cps = ["sys-apps/portage", "virtual/portage"]
13827 -test_versions = ["1.0", "1.0-r1", "2.3_p4", "1.0_alpha57"]
13828 -test_slots = [None, "1", "gentoo-sources-2.6.17", "spankywashere"]
13829 -test_usedeps = ["foo", "-bar", ("foo", "bar"), ("foo", "-bar"), ("foo?", "!bar?")]
13830
13831 diff --git a/repoman/lib/repoman/tests/__test__.py b/repoman/lib/repoman/tests/__test__.py
13832 deleted file mode 100644
13833 index e69de29bb..000000000
13834
13835 diff --git a/repoman/lib/repoman/tests/changelog/__init__.py b/repoman/lib/repoman/tests/changelog/__init__.py
13836 deleted file mode 100644
13837 index 532918b6a..000000000
13838 --- a/repoman/lib/repoman/tests/changelog/__init__.py
13839 +++ /dev/null
13840 @@ -1,2 +0,0 @@
13841 -# Copyright 2011 Gentoo Foundation
13842 -# Distributed under the terms of the GNU General Public License v2
13843
13844 diff --git a/repoman/lib/repoman/tests/changelog/__test__.py b/repoman/lib/repoman/tests/changelog/__test__.py
13845 deleted file mode 100644
13846 index e69de29bb..000000000
13847
13848 diff --git a/repoman/lib/repoman/tests/changelog/test_echangelog.py b/repoman/lib/repoman/tests/changelog/test_echangelog.py
13849 deleted file mode 100644
13850 index f0c43e20b..000000000
13851 --- a/repoman/lib/repoman/tests/changelog/test_echangelog.py
13852 +++ /dev/null
13853 @@ -1,169 +0,0 @@
13854 -# Copyright 2012 Gentoo Foundation
13855 -# Distributed under the terms of the GNU General Public License v2
13856 -
13857 -import tempfile
13858 -import time
13859 -
13860 -from portage import os
13861 -from portage import shutil
13862 -from portage.tests import TestCase
13863 -from repoman.utilities import UpdateChangeLog
13864 -
13865 -
13866 -class RepomanEchangelogTestCase(TestCase):
13867 - def setUp(self):
13868 - super(RepomanEchangelogTestCase, self).setUp()
13869 -
13870 - self.tmpdir = tempfile.mkdtemp(prefix="repoman.echangelog.")
13871 -
13872 - self.skel_changelog = os.path.join(self.tmpdir, "skel.ChangeLog")
13873 - skel = [
13874 - "# ChangeLog for <CATEGORY>/<PACKAGE_NAME>\n",
13875 - "# Copyright 1999-2000 Gentoo Foundation; Distributed under the GPL v2\n",
13876 - "# $Header: $\n",
13877 - ]
13878 - self._writelines(self.skel_changelog, skel)
13879 -
13880 - self.cat = "mycat"
13881 - self.pkg = "mypkg"
13882 - self.pkgdir = os.path.join(self.tmpdir, self.cat, self.pkg)
13883 - os.makedirs(self.pkgdir)
13884 -
13885 - self.header_pkg = "# ChangeLog for %s/%s\n" % (self.cat, self.pkg)
13886 - self.header_copyright = (
13887 - "# Copyright 1999-%s Gentoo Authors; Distributed under the GPL v2\n"
13888 - % time.strftime("%Y", time.gmtime())
13889 - )
13890 - self.header_cvs = "# $Header: $\n"
13891 -
13892 - self.changelog = os.path.join(self.pkgdir, "ChangeLog")
13893 -
13894 - self.user = "Testing User <portage@g.o>"
13895 -
13896 - def tearDown(self):
13897 - super(RepomanEchangelogTestCase, self).tearDown()
13898 - shutil.rmtree(self.tmpdir)
13899 -
13900 - def _readlines(self, file):
13901 - with open(file, "r") as f:
13902 - return f.readlines()
13903 -
13904 - def _writelines(self, file, data):
13905 - with open(file, "w") as f:
13906 - f.writelines(data)
13907 -
13908 - def testRejectRootUser(self):
13909 - self.assertEqual(
13910 - UpdateChangeLog(
13911 - self.pkgdir, "me <root@g.o>", "", "", "", "", quiet=True
13912 - ),
13913 - None,
13914 - )
13915 -
13916 - def testMissingSkelFile(self):
13917 - # Test missing ChangeLog, but with empty skel (i.e. do nothing).
13918 - UpdateChangeLog(
13919 - self.pkgdir,
13920 - self.user,
13921 - "test!",
13922 - "/does/not/exist",
13923 - self.cat,
13924 - self.pkg,
13925 - quiet=True,
13926 - )
13927 - actual_cl = self._readlines(self.changelog)
13928 - self.assertTrue(len(actual_cl[0]) > 0)
13929 -
13930 - def testEmptyChangeLog(self):
13931 - # Make sure we do the right thing with a 0-byte ChangeLog
13932 - open(self.changelog, "w").close()
13933 - UpdateChangeLog(
13934 - self.pkgdir,
13935 - self.user,
13936 - "test!",
13937 - self.skel_changelog,
13938 - self.cat,
13939 - self.pkg,
13940 - quiet=True,
13941 - )
13942 - actual_cl = self._readlines(self.changelog)
13943 - self.assertEqual(actual_cl[0], self.header_pkg)
13944 - self.assertEqual(actual_cl[1], self.header_copyright)
13945 - self.assertEqual(actual_cl[2], self.header_cvs)
13946 -
13947 - def testCopyrightUpdate(self):
13948 - # Make sure updating the copyright line works
13949 - UpdateChangeLog(
13950 - self.pkgdir,
13951 - self.user,
13952 - "test!",
13953 - self.skel_changelog,
13954 - self.cat,
13955 - self.pkg,
13956 - quiet=True,
13957 - )
13958 - actual_cl = self._readlines(self.changelog)
13959 - self.assertEqual(actual_cl[1], self.header_copyright)
13960 -
13961 - def testSkelHeader(self):
13962 - # Test skel.ChangeLog -> ChangeLog
13963 - UpdateChangeLog(
13964 - self.pkgdir,
13965 - self.user,
13966 - "test!",
13967 - self.skel_changelog,
13968 - self.cat,
13969 - self.pkg,
13970 - quiet=True,
13971 - )
13972 - actual_cl = self._readlines(self.changelog)
13973 - self.assertEqual(actual_cl[0], self.header_pkg)
13974 - self.assertNotEqual(actual_cl[-1], "\n")
13975 -
13976 - def testExistingGoodHeader(self):
13977 - # Test existing ChangeLog (correct values)
13978 - self._writelines(self.changelog, [self.header_pkg])
13979 -
13980 - UpdateChangeLog(
13981 - self.pkgdir,
13982 - self.user,
13983 - "test!",
13984 - self.skel_changelog,
13985 - self.cat,
13986 - self.pkg,
13987 - quiet=True,
13988 - )
13989 - actual_cl = self._readlines(self.changelog)
13990 - self.assertEqual(actual_cl[0], self.header_pkg)
13991 -
13992 - def testExistingBadHeader(self):
13993 - # Test existing ChangeLog (wrong values)
13994 - self._writelines(self.changelog, ["# ChangeLog for \n"])
13995 -
13996 - UpdateChangeLog(
13997 - self.pkgdir,
13998 - self.user,
13999 - "test!",
14000 - self.skel_changelog,
14001 - self.cat,
14002 - self.pkg,
14003 - quiet=True,
14004 - )
14005 - actual_cl = self._readlines(self.changelog)
14006 - self.assertEqual(actual_cl[0], self.header_pkg)
14007 -
14008 - def testTrailingNewlines(self):
14009 - # Make sure trailing newlines get chomped.
14010 - self._writelines(self.changelog, ["#\n", "foo\n", "\n", "bar\n", "\n", "\n"])
14011 -
14012 - UpdateChangeLog(
14013 - self.pkgdir,
14014 - self.user,
14015 - "test!",
14016 - self.skel_changelog,
14017 - self.cat,
14018 - self.pkg,
14019 - quiet=True,
14020 - )
14021 - actual_cl = self._readlines(self.changelog)
14022 - self.assertNotEqual(actual_cl[-1], "\n")
14023
14024 diff --git a/repoman/lib/repoman/tests/commit/__init__.py b/repoman/lib/repoman/tests/commit/__init__.py
14025 deleted file mode 100644
14026 index d74fd94a7..000000000
14027 --- a/repoman/lib/repoman/tests/commit/__init__.py
14028 +++ /dev/null
14029 @@ -1,2 +0,0 @@
14030 -# Copyright 2011-2018 Gentoo Foundation
14031 -# Distributed under the terms of the GNU General Public License v2
14032
14033 diff --git a/repoman/lib/repoman/tests/commit/__test__.py b/repoman/lib/repoman/tests/commit/__test__.py
14034 deleted file mode 100644
14035 index e69de29bb..000000000
14036
14037 diff --git a/repoman/lib/repoman/tests/commit/test_commitmsg.py b/repoman/lib/repoman/tests/commit/test_commitmsg.py
14038 deleted file mode 100644
14039 index 392d17cb3..000000000
14040 --- a/repoman/lib/repoman/tests/commit/test_commitmsg.py
14041 +++ /dev/null
14042 @@ -1,155 +0,0 @@
14043 -# Copyright 2011-2018 Gentoo Foundation
14044 -# Distributed under the terms of the GNU General Public License v2
14045 -
14046 -from repoman.actions import Actions
14047 -from repoman.tests import TestCase
14048 -
14049 -
14050 -class CommitMessageVerificationTest(TestCase):
14051 - def assertGood(self, commitmsg):
14052 - res, expl = Actions.verify_commit_message(commitmsg)
14053 - self.assertTrue(
14054 - res,
14055 - """Commit message verification failed for:
14056 -%s
14057 -
14058 -Error:
14059 -%s"""
14060 - % (commitmsg, expl),
14061 - )
14062 -
14063 - def assertBad(self, commitmsg, reason_re):
14064 - res, expl = Actions.verify_commit_message(commitmsg)
14065 - self.assertFalse(
14066 - res,
14067 - """Commit message verification succeeded unexpectedly, for:
14068 -%s
14069 -
14070 -Expected: /%s/"""
14071 - % (commitmsg, reason_re),
14072 - )
14073 - self.assertNotIn(
14074 - "\n",
14075 - expl.strip(),
14076 - """Commit message verification returned multiple errors (one expected):
14077 -%s
14078 -
14079 -Expected: /%s/
14080 -Errors:
14081 -%s"""
14082 - % (commitmsg, reason_re, expl),
14083 - )
14084 - (
14085 - self.assertRegex
14086 - if hasattr(self, "assertRegex")
14087 - else self.assertRegexpMatches
14088 - )(
14089 - expl,
14090 - reason_re,
14091 - """Commit message verification did not return expected error, for:
14092 -%s
14093 -
14094 -Expected: /%s/
14095 -Errors:
14096 -%s"""
14097 - % (commitmsg, reason_re, expl),
14098 - )
14099 -
14100 - def test_summary_only(self):
14101 - self.assertGood("dev-foo/bar: Actually good commit message")
14102 -
14103 - def test_summary_and_body(self):
14104 - self.assertGood(
14105 - """dev-foo/bar: Good commit message
14106 -
14107 -Extended description goes here and is properly wrapped at 72 characters
14108 -which is very nice and blah blah.
14109 -
14110 -Another paragraph for the sake of having one."""
14111 - )
14112 -
14113 - def test_summary_and_footer(self):
14114 - self.assertGood(
14115 - """dev-foo/bar: Good commit message
14116 -
14117 -Closes: https://bugs.gentoo.org/NNNNNN"""
14118 - )
14119 -
14120 - def test_summary_body_and_footer(self):
14121 - self.assertGood(
14122 - """dev-foo/bar: Good commit message
14123 -
14124 -Extended description goes here and is properly wrapped at 72 characters
14125 -which is very nice and blah blah.
14126 -
14127 -Another paragraph for the sake of having one.
14128 -
14129 -Closes: https://bugs.gentoo.org/NNNNNN"""
14130 - )
14131 -
14132 - def test_summary_without_unit_name(self):
14133 - self.assertBad("Version bump", r"summary.*logical unit name")
14134 -
14135 - def test_multiline_summary(self):
14136 - self.assertBad(
14137 - """dev-foo/bar: Commit message with very long summary
14138 -that got wrapped because of length""",
14139 - r"single.*line.*summary",
14140 - )
14141 -
14142 - def test_overlong_summary(self):
14143 - self.assertBad(
14144 - "dev-foo/bar: Commit message with very long summary \
14145 -in a single line that should trigger an explicit error",
14146 - r"summary.*too long",
14147 - )
14148 -
14149 - def test_summary_with_very_long_package_name(self):
14150 - self.assertGood(
14151 - "dev-foo/foo-bar-bar-baz-bar-bar-foo-bar-bar-\
14152 -baz-foo-baz-baz-foo: We do not fail because pkgname was long"
14153 - )
14154 -
14155 - def test_multiple_footers(self):
14156 - self.assertBad(
14157 - """dev-foo/bar: Good summary
14158 -
14159 -Bug: https://bugs.gentoo.org/NNNNNN
14160 -
14161 -Closes: https://github.com/gentoo/gentoo/pull/NNNN""",
14162 - r"multiple footer",
14163 - )
14164 -
14165 - def test_gentoo_bug(self):
14166 - self.assertBad(
14167 - """dev-foo/bar: Good summary
14168 -
14169 -Gentoo-Bug: NNNNNN""",
14170 - r"Gentoo-Bug",
14171 - )
14172 -
14173 - def test_bug_with_number(self):
14174 - self.assertBad(
14175 - """dev-foo/bar: Good summary
14176 -
14177 -Bug: NNNNNN""",
14178 - r"Bug.*full URL",
14179 - )
14180 -
14181 - def test_closes_with_number(self):
14182 - self.assertBad(
14183 - """dev-foo/bar: Good summary
14184 -
14185 -Closes: NNNNNN""",
14186 - r"Closes.*full URL",
14187 - )
14188 -
14189 - def test_body_too_long(self):
14190 - self.assertBad(
14191 - """dev-foo/bar: Good summary
14192 -
14193 -But the body is not wrapped properly and has very long lines that are \
14194 -very hard to read and blah blah blah
14195 -blah blah.""",
14196 - r"body.*wrapped",
14197 - )
14198
14199 diff --git a/repoman/lib/repoman/tests/runTests.py b/repoman/lib/repoman/tests/runTests.py
14200 deleted file mode 100644
14201 index 4a081551e..000000000
14202 --- a/repoman/lib/repoman/tests/runTests.py
14203 +++ /dev/null
14204 @@ -1,85 +0,0 @@
14205 -#!/usr/bin/env python
14206 -# runTests.py -- Portage Unit Test Functionality
14207 -# Copyright 2006-2021 Gentoo Authors
14208 -# Distributed under the terms of the GNU General Public License v2
14209 -
14210 -import os
14211 -import os.path as osp
14212 -import sys
14213 -import grp
14214 -import platform
14215 -import pwd
14216 -import signal
14217 -import tempfile
14218 -from distutils.dir_util import copy_tree
14219 -
14220 -
14221 -def debug_signal(signum, frame):
14222 - import pdb
14223 -
14224 - pdb.set_trace()
14225 -
14226 -
14227 -if platform.python_implementation() == "Jython":
14228 - debug_signum = signal.SIGUSR2 # bug #424259
14229 -else:
14230 - debug_signum = signal.SIGUSR1
14231 -
14232 -signal.signal(debug_signum, debug_signal)
14233 -
14234 -# Pretend that the current user's uid/gid are the 'portage' uid/gid,
14235 -# so things go smoothly regardless of the current user and global
14236 -# user/group configuration.
14237 -os.environ["PORTAGE_USERNAME"] = pwd.getpwuid(os.getuid()).pw_name
14238 -os.environ["PORTAGE_GRPNAME"] = grp.getgrgid(os.getgid()).gr_name
14239 -
14240 -# Insert our parent dir so we can do shiny import "tests"
14241 -# This line courtesy of Marienz and Pkgcore ;)
14242 -repoman_pym = osp.dirname(osp.dirname(osp.dirname(osp.realpath(__file__))))
14243 -sys.path.insert(0, repoman_pym)
14244 -
14245 -# Add in the parent portage python modules
14246 -portage_pym = osp.dirname(osp.dirname(repoman_pym)) + "/lib"
14247 -sys.path.insert(0, portage_pym)
14248 -
14249 -# import our centrally initialized portage instance
14250 -from repoman._portage import portage
14251 -
14252 -portage._internal_caller = True
14253 -import repoman.tests as tests
14254 -
14255 -# Ensure that we don't instantiate portage.settings, so that tests should
14256 -# work the same regardless of global configuration file state/existence.
14257 -portage._disable_legacy_globals()
14258 -from portage.util._eventloop.global_event_loop import global_event_loop
14259 -from portage.const import PORTAGE_BIN_PATH
14260 -
14261 -if os.environ.get("NOCOLOR") in ("yes", "true"):
14262 - portage.output.nocolor()
14263 -
14264 -path = os.environ.get("PATH", "").split(":")
14265 -path = [x for x in path if x]
14266 -
14267 -insert_bin_path = True
14268 -try:
14269 - insert_bin_path = not path or not os.path.samefile(path[0], PORTAGE_BIN_PATH)
14270 -except OSError:
14271 - pass
14272 -
14273 -if insert_bin_path:
14274 - path.insert(0, PORTAGE_BIN_PATH)
14275 - os.environ["PATH"] = ":".join(path)
14276 -
14277 -# Copy GPG test keys to temporary directory
14278 -gpg_path = tempfile.mkdtemp(prefix="gpg_")
14279 -
14280 -copy_tree(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".gnupg"), gpg_path)
14281 -
14282 -os.chmod(gpg_path, 0o700)
14283 -os.environ["PORTAGE_GNUPGHOME"] = gpg_path
14284 -
14285 -if __name__ == "__main__":
14286 - try:
14287 - sys.exit(tests.main())
14288 - finally:
14289 - global_event_loop().close()
14290
14291 diff --git a/repoman/lib/repoman/tests/simple/__init__.py b/repoman/lib/repoman/tests/simple/__init__.py
14292 deleted file mode 100644
14293 index 532918b6a..000000000
14294 --- a/repoman/lib/repoman/tests/simple/__init__.py
14295 +++ /dev/null
14296 @@ -1,2 +0,0 @@
14297 -# Copyright 2011 Gentoo Foundation
14298 -# Distributed under the terms of the GNU General Public License v2
14299
14300 diff --git a/repoman/lib/repoman/tests/simple/__test__.py b/repoman/lib/repoman/tests/simple/__test__.py
14301 deleted file mode 100644
14302 index e69de29bb..000000000
14303
14304 diff --git a/repoman/lib/repoman/tests/simple/test_simple.py b/repoman/lib/repoman/tests/simple/test_simple.py
14305 deleted file mode 100644
14306 index 41735b8b4..000000000
14307 --- a/repoman/lib/repoman/tests/simple/test_simple.py
14308 +++ /dev/null
14309 @@ -1,512 +0,0 @@
14310 -# Copyright 2011-2021 Gentoo Authors
14311 -# Distributed under the terms of the GNU General Public License v2
14312 -
14313 -import collections
14314 -import subprocess
14315 -import sys
14316 -import time
14317 -import types
14318 -
14319 -from repoman._portage import portage
14320 -from portage import os
14321 -from portage.process import find_binary
14322 -from portage.tests.resolver.ResolverPlayground import ResolverPlayground
14323 -from portage.util import ensure_dirs
14324 -from portage.util.futures import asyncio
14325 -from portage.util.futures._asyncio.streams import _reader
14326 -from portage.util._async.AsyncFunction import AsyncFunction
14327 -
14328 -# pylint: disable=ungrouped-imports
14329 -from repoman import REPOMAN_BASE_PATH
14330 -from repoman.copyrights import update_copyright_year
14331 -from repoman.main import _repoman_init, _repoman_scan, _handle_result
14332 -from repoman.tests import TestCase
14333 -
14334 -
14335 -class RepomanRun(types.SimpleNamespace):
14336 - async def run(self):
14337 - self.expected = getattr(self, "expected", None) or {"returncode": 0}
14338 - if self.debug:
14339 - fd_pipes = {}
14340 - pr = None
14341 - pw = None
14342 - else:
14343 - pr, pw = os.pipe()
14344 - fd_pipes = {1: pw, 2: pw}
14345 - pr = open(pr, "rb", 0)
14346 -
14347 - proc = AsyncFunction(
14348 - scheduler=asyncio.get_event_loop(),
14349 - target=self._subprocess,
14350 - args=(self.args, self.cwd, self.env, self.expected, self.debug),
14351 - fd_pipes=fd_pipes,
14352 - )
14353 -
14354 - proc.start()
14355 - if pw is not None:
14356 - os.close(pw)
14357 -
14358 - await proc.async_wait()
14359 -
14360 - if pr is None:
14361 - stdio = None
14362 - else:
14363 - stdio = await _reader(pr)
14364 -
14365 - self.result = {
14366 - "stdio": stdio,
14367 - "result": proc.result,
14368 - }
14369 -
14370 - @staticmethod
14371 - def _subprocess(args, cwd, env, expected, debug):
14372 - os.chdir(cwd)
14373 - os.environ.update(env)
14374 - portage.const.EPREFIX = env["PORTAGE_OVERRIDE_EPREFIX"]
14375 - if debug:
14376 - args = ["-vvvv"] + args
14377 - repoman_vars = _repoman_init(["repoman"] + args)
14378 - if repoman_vars.exitcode is not None:
14379 - return {"returncode": repoman_vars.exitcode}
14380 - result = _repoman_scan(*repoman_vars)
14381 - returncode = _handle_result(*repoman_vars, result)
14382 - qawarnings = repoman_vars.vcs_settings.qatracker.qawarnings
14383 - warns = collections.defaultdict(list)
14384 - fails = collections.defaultdict(list)
14385 - for qacat, issues in repoman_vars.vcs_settings.qatracker.fails.items():
14386 - if qacat in qawarnings:
14387 - warns[qacat].extend(issues)
14388 - else:
14389 - fails[qacat].extend(issues)
14390 - result = {"returncode": returncode}
14391 - if fails:
14392 - result["fails"] = fails
14393 - if warns:
14394 - result["warns"] = warns
14395 - return result
14396 -
14397 -
14398 -class SimpleRepomanTestCase(TestCase):
14399 - def testCopyrightUpdate(self):
14400 - test_cases = (
14401 - (
14402 - "2011",
14403 - "# Copyright 1999-2008 Gentoo Foundation; Distributed under the GPL v2",
14404 - "# Copyright 1999-2011 Gentoo Authors; Distributed under the GPL v2",
14405 - ),
14406 - (
14407 - "2011",
14408 - "# Copyright 1999 Gentoo Foundation; Distributed under the GPL v2",
14409 - "# Copyright 1999-2011 Gentoo Authors; Distributed under the GPL v2",
14410 - ),
14411 - (
14412 - "1999",
14413 - "# Copyright 1999 Gentoo Foundation; Distributed under the GPL v2",
14414 - "# Copyright 1999 Gentoo Foundation; Distributed under the GPL v2",
14415 - ),
14416 - (
14417 - "2018",
14418 - "# Copyright 1999-2008 Gentoo Authors; Distributed under the GPL v2",
14419 - "# Copyright 1999-2018 Gentoo Authors; Distributed under the GPL v2",
14420 - ),
14421 - (
14422 - "2018",
14423 - "# Copyright 2017 Gentoo Authors; Distributed under the GPL v2",
14424 - "# Copyright 2017-2018 Gentoo Authors; Distributed under the GPL v2",
14425 - ),
14426 - )
14427 -
14428 - for year, before, after in test_cases:
14429 - self.assertEqual(update_copyright_year(year, before), after)
14430 -
14431 - def _must_skip(self):
14432 - xmllint = find_binary("xmllint")
14433 - if not xmllint:
14434 - return "xmllint not found"
14435 -
14436 - try:
14437 - __import__("xml.etree.ElementTree")
14438 - __import__("xml.parsers.expat").parsers.expat.ExpatError
14439 - except (AttributeError, ImportError):
14440 - return "python is missing xml support"
14441 -
14442 - def testSimple(self):
14443 - debug = False
14444 -
14445 - skip_reason = self._must_skip()
14446 - if skip_reason:
14447 - self.portage_skip = skip_reason
14448 - self.assertFalse(True, skip_reason)
14449 - return
14450 -
14451 - copyright_header = (
14452 - """# Copyright 1999-%s Gentoo Authors
14453 -# Distributed under the terms of the GNU General Public License v2
14454 -
14455 -"""
14456 - % time.gmtime().tm_year
14457 - )
14458 -
14459 - pkg_preinst_references_forbidden_var = """
14460 -pkg_preinst() {
14461 - echo "This ${A} reference is not allowed. Neither is this $BROOT reference."
14462 -}
14463 -"""
14464 -
14465 - repo_configs = {
14466 - "test_repo": {
14467 - "layout.conf": ("update-changelog = true",),
14468 - }
14469 - }
14470 -
14471 - profiles = (
14472 - ("x86", "default/linux/x86/test_profile", "stable"),
14473 - ("x86", "default/linux/x86/test_dev", "dev"),
14474 - ("x86", "default/linux/x86/test_exp", "exp"),
14475 - )
14476 -
14477 - profile = {"eapi": ("5",), "package.use.stable.mask": ("dev-libs/A flag",)}
14478 -
14479 - ebuilds = {
14480 - "dev-libs/A-0": {
14481 - "COPYRIGHT_HEADER": copyright_header,
14482 - "DESCRIPTION": "Desc goes here",
14483 - "EAPI": "5",
14484 - "HOMEPAGE": "https://example.com",
14485 - "IUSE": "flag",
14486 - "KEYWORDS": "x86",
14487 - "LICENSE": "GPL-2",
14488 - "RDEPEND": "flag? ( dev-libs/B[flag] )",
14489 - },
14490 - "dev-libs/A-1": {
14491 - "COPYRIGHT_HEADER": copyright_header,
14492 - "DESCRIPTION": "Desc goes here",
14493 - "EAPI": "4",
14494 - "HOMEPAGE": "https://example.com",
14495 - "IUSE": "flag",
14496 - "KEYWORDS": "~x86",
14497 - "LICENSE": "GPL-2",
14498 - "RDEPEND": "flag? ( dev-libs/B[flag] )",
14499 - },
14500 - "dev-libs/B-1": {
14501 - "COPYRIGHT_HEADER": copyright_header,
14502 - "DESCRIPTION": "Desc goes here",
14503 - "EAPI": "4",
14504 - "HOMEPAGE": "https://example.com",
14505 - "IUSE": "flag",
14506 - "KEYWORDS": "~x86",
14507 - "LICENSE": "GPL-2",
14508 - },
14509 - "dev-libs/C-0": {
14510 - "COPYRIGHT_HEADER": copyright_header,
14511 - "DESCRIPTION": "Desc goes here",
14512 - "EAPI": "7",
14513 - "HOMEPAGE": "https://example.com",
14514 - "IUSE": "flag",
14515 - # must be unstable, since dev-libs/A[flag] is stable masked
14516 - "KEYWORDS": "~x86",
14517 - "LICENSE": "GPL-2",
14518 - "RDEPEND": "flag? ( dev-libs/A[flag] )",
14519 - "MISC_CONTENT": pkg_preinst_references_forbidden_var,
14520 - },
14521 - }
14522 - licenses = ["GPL-2"]
14523 - arch_list = ["x86"]
14524 - metadata_xsd = os.path.join(REPOMAN_BASE_PATH, "cnf/metadata.xsd")
14525 - metadata_xml_files = (
14526 - (
14527 - "dev-libs/A",
14528 - {
14529 - "flags": "<flag name='flag' restrict='&gt;=dev-libs/A-0'>Description of how USE='flag' affects this package</flag>",
14530 - },
14531 - ),
14532 - (
14533 - "dev-libs/B",
14534 - {
14535 - "flags": "<flag name='flag'>Description of how USE='flag' affects this package</flag>",
14536 - },
14537 - ),
14538 - (
14539 - "dev-libs/C",
14540 - {
14541 - "flags": "<flag name='flag'>Description of how USE='flag' affects this package</flag>",
14542 - },
14543 - ),
14544 - )
14545 -
14546 - use_desc = (("flag", "Description of how USE='flag' affects packages"),)
14547 -
14548 - playground = ResolverPlayground(
14549 - ebuilds=ebuilds, profile=profile, repo_configs=repo_configs, debug=debug
14550 - )
14551 -
14552 - loop = asyncio._wrap_loop()
14553 - loop.run_until_complete(
14554 - asyncio.ensure_future(
14555 - self._async_test_simple(
14556 - playground,
14557 - metadata_xml_files,
14558 - profiles,
14559 - profile,
14560 - licenses,
14561 - arch_list,
14562 - use_desc,
14563 - metadata_xsd,
14564 - copyright_header,
14565 - debug,
14566 - ),
14567 - loop=loop,
14568 - )
14569 - )
14570 -
14571 - async def _async_test_simple(
14572 - self,
14573 - playground,
14574 - metadata_xml_files,
14575 - profiles,
14576 - profile,
14577 - licenses,
14578 - arch_list,
14579 - use_desc,
14580 - metadata_xsd,
14581 - copyright_header,
14582 - debug,
14583 - ):
14584 - settings = playground.settings
14585 - eprefix = settings["EPREFIX"]
14586 - eroot = settings["EROOT"]
14587 - portdb = playground.trees[playground.eroot]["porttree"].dbapi
14588 - homedir = os.path.join(eroot, "home")
14589 - distdir = os.path.join(eprefix, "distdir")
14590 - test_repo_location = settings.repositories["test_repo"].location
14591 - profiles_dir = os.path.join(test_repo_location, "profiles")
14592 - license_dir = os.path.join(test_repo_location, "licenses")
14593 -
14594 - repoman_cmd = (
14595 - portage._python_interpreter,
14596 - "-b",
14597 - "-Wd",
14598 - os.path.join(self.bindir, "repoman"),
14599 - )
14600 -
14601 - git_binary = find_binary("git")
14602 - git_cmd = (git_binary,)
14603 -
14604 - cp_binary = find_binary("cp")
14605 - self.assertEqual(cp_binary is None, False, "cp command not found")
14606 - cp_cmd = (cp_binary,)
14607 -
14608 - test_ebuild = portdb.findname("dev-libs/A-1")
14609 - self.assertFalse(test_ebuild is None)
14610 -
14611 - committer_name = "Gentoo Dev"
14612 - committer_email = "gentoo-dev@g.o"
14613 - expected_warnings = {
14614 - "returncode": 0,
14615 - "warns": {
14616 - "variable.phase": [
14617 - "dev-libs/C/C-0.ebuild: line 15: phase pkg_preinst: EAPI 7: variable A: Forbidden reference to variable specified by PMS",
14618 - "dev-libs/C/C-0.ebuild: line 15: phase pkg_preinst: EAPI 7: variable BROOT: Forbidden reference to variable specified by PMS",
14619 - ]
14620 - },
14621 - }
14622 -
14623 - git_test = (
14624 - ("", RepomanRun(args=["--version"])),
14625 - ("", RepomanRun(args=["manifest"])),
14626 - (
14627 - "",
14628 - git_cmd
14629 - + (
14630 - "config",
14631 - "--global",
14632 - "user.name",
14633 - committer_name,
14634 - ),
14635 - ),
14636 - (
14637 - "",
14638 - git_cmd
14639 - + (
14640 - "config",
14641 - "--global",
14642 - "user.email",
14643 - committer_email,
14644 - ),
14645 - ),
14646 - ("", git_cmd + ("init-db",)),
14647 - ("", git_cmd + ("add", ".")),
14648 - ("", git_cmd + ("commit", "-a", "-m", "add whole repo")),
14649 - ("", RepomanRun(args=["full", "-d"], expected=expected_warnings)),
14650 - (
14651 - "",
14652 - RepomanRun(
14653 - args=[
14654 - "full",
14655 - "--include-profiles",
14656 - "default/linux/x86/test_profile",
14657 - ],
14658 - expected=expected_warnings,
14659 - ),
14660 - ),
14661 - ("", cp_cmd + (test_ebuild, test_ebuild[:-8] + "2.ebuild")),
14662 - ("", git_cmd + ("add", test_ebuild[:-8] + "2.ebuild")),
14663 - (
14664 - "",
14665 - RepomanRun(
14666 - args=["commit", "-m", "cat/pkg: bump to version 2"],
14667 - expected=expected_warnings,
14668 - ),
14669 - ),
14670 - ("", cp_cmd + (test_ebuild, test_ebuild[:-8] + "3.ebuild")),
14671 - ("", git_cmd + ("add", test_ebuild[:-8] + "3.ebuild")),
14672 - (
14673 - "dev-libs",
14674 - RepomanRun(
14675 - args=["commit", "-m", "cat/pkg: bump to version 3"],
14676 - expected=expected_warnings,
14677 - ),
14678 - ),
14679 - ("", cp_cmd + (test_ebuild, test_ebuild[:-8] + "4.ebuild")),
14680 - ("", git_cmd + ("add", test_ebuild[:-8] + "4.ebuild")),
14681 - (
14682 - "dev-libs/A",
14683 - RepomanRun(args=["commit", "-m", "cat/pkg: bump to version 4"]),
14684 - ),
14685 - )
14686 -
14687 - env = {
14688 - "PORTAGE_OVERRIDE_EPREFIX": eprefix,
14689 - "DISTDIR": distdir,
14690 - "GENTOO_COMMITTER_NAME": committer_name,
14691 - "GENTOO_COMMITTER_EMAIL": committer_email,
14692 - "HOME": homedir,
14693 - "PATH": os.environ["PATH"],
14694 - "PORTAGE_GRPNAME": os.environ["PORTAGE_GRPNAME"],
14695 - "PORTAGE_USERNAME": os.environ["PORTAGE_USERNAME"],
14696 - "PORTAGE_REPOSITORIES": settings.repositories.config_string(),
14697 - "PYTHONDONTWRITEBYTECODE": os.environ.get("PYTHONDONTWRITEBYTECODE", ""),
14698 - }
14699 -
14700 - if os.environ.get("SANDBOX_ON") == "1":
14701 - # avoid problems from nested sandbox instances
14702 - env["FEATURES"] = "-sandbox -usersandbox"
14703 -
14704 - dirs = [homedir, license_dir, profiles_dir, distdir]
14705 - try:
14706 - for d in dirs:
14707 - ensure_dirs(d)
14708 - with open(os.path.join(test_repo_location, "skel.ChangeLog"), "w") as f:
14709 - f.write(copyright_header)
14710 - with open(os.path.join(profiles_dir, "profiles.desc"), "w") as f:
14711 - for x in profiles:
14712 - f.write("%s %s %s\n" % x)
14713 -
14714 - # ResolverPlayground only created the first profile,
14715 - # so create the remaining ones.
14716 - for x in profiles[1:]:
14717 - sub_profile_dir = os.path.join(profiles_dir, x[1])
14718 - ensure_dirs(sub_profile_dir)
14719 - for config_file, lines in profile.items():
14720 - file_name = os.path.join(sub_profile_dir, config_file)
14721 - with open(file_name, "w") as f:
14722 - for line in lines:
14723 - f.write("%s\n" % line)
14724 -
14725 - for x in licenses:
14726 - open(os.path.join(license_dir, x), "wb").close()
14727 - with open(os.path.join(profiles_dir, "arch.list"), "w") as f:
14728 - for x in arch_list:
14729 - f.write("%s\n" % x)
14730 - with open(os.path.join(profiles_dir, "use.desc"), "w") as f:
14731 - for k, v in use_desc:
14732 - f.write("%s - %s\n" % (k, v))
14733 - for cp, xml_data in metadata_xml_files:
14734 - with open(
14735 - os.path.join(test_repo_location, cp, "metadata.xml"), "w"
14736 - ) as f:
14737 - f.write(playground.metadata_xml_template % xml_data)
14738 - # Use a symlink to test_repo, in order to trigger bugs
14739 - # involving canonical vs. non-canonical paths.
14740 - test_repo_symlink = os.path.join(eroot, "test_repo_symlink")
14741 - os.symlink(test_repo_location, test_repo_symlink)
14742 - metadata_xsd_dest = os.path.join(
14743 - test_repo_location, "metadata/xml-schema/metadata.xsd"
14744 - )
14745 - os.makedirs(os.path.dirname(metadata_xsd_dest))
14746 - os.symlink(metadata_xsd, metadata_xsd_dest)
14747 -
14748 - if debug:
14749 - # The subprocess inherits both stdout and stderr, for
14750 - # debugging purposes.
14751 - stdout = None
14752 - else:
14753 - # The subprocess inherits stderr so that any warnings
14754 - # triggered by python -Wd will be visible.
14755 - stdout = subprocess.PIPE
14756 -
14757 - for cwd in ("", "dev-libs", "dev-libs/A", "dev-libs/B", "dev-libs/C"):
14758 - abs_cwd = os.path.join(test_repo_symlink, cwd)
14759 -
14760 - proc = await asyncio.create_subprocess_exec(
14761 - *(repoman_cmd + ("full",)),
14762 - env=env,
14763 - stderr=None,
14764 - stdout=stdout,
14765 - cwd=abs_cwd
14766 - )
14767 -
14768 - if debug:
14769 - await proc.wait()
14770 - else:
14771 - output, _err = await proc.communicate()
14772 - await proc.wait()
14773 - if proc.returncode != os.EX_OK:
14774 - portage.writemsg(output)
14775 -
14776 - self.assertEqual(
14777 - os.EX_OK, proc.returncode, "repoman failed in %s" % (cwd,)
14778 - )
14779 -
14780 - if git_binary is not None:
14781 - for cwd, cmd in git_test:
14782 - abs_cwd = os.path.join(test_repo_symlink, cwd)
14783 - if isinstance(cmd, RepomanRun):
14784 - cmd.cwd = abs_cwd
14785 - cmd.env = env
14786 - cmd.debug = debug
14787 - await cmd.run()
14788 - if cmd.result["result"] != cmd.expected and cmd.result.get(
14789 - "stdio"
14790 - ):
14791 - portage.writemsg(cmd.result["stdio"])
14792 - try:
14793 - self.assertEqual(cmd.result["result"], cmd.expected)
14794 - except Exception:
14795 - print(cmd.result["result"], file=sys.stderr, flush=True)
14796 - raise
14797 - continue
14798 -
14799 - proc = await asyncio.create_subprocess_exec(
14800 - *cmd, env=env, stderr=None, stdout=stdout, cwd=abs_cwd
14801 - )
14802 -
14803 - if debug:
14804 - await proc.wait()
14805 - else:
14806 - output, _err = await proc.communicate()
14807 - await proc.wait()
14808 - if proc.returncode != os.EX_OK:
14809 - portage.writemsg(output)
14810 -
14811 - self.assertEqual(
14812 - os.EX_OK,
14813 - proc.returncode,
14814 - "%s failed in %s"
14815 - % (
14816 - cmd,
14817 - cwd,
14818 - ),
14819 - )
14820 - finally:
14821 - playground.cleanup()
14822
14823 diff --git a/repoman/lib/repoman/utilities.py b/repoman/lib/repoman/utilities.py
14824 deleted file mode 100644
14825 index 6c5414470..000000000
14826 --- a/repoman/lib/repoman/utilities.py
14827 +++ /dev/null
14828 @@ -1,590 +0,0 @@
14829 -# -*- coding:utf-8 -*-
14830 -# repoman: Utilities
14831 -# Copyright 2007-2021 Gentoo Authors
14832 -# Distributed under the terms of the GNU General Public License v2
14833 -
14834 -"""This module contains utility functions to help repoman find ebuilds to
14835 -scan"""
14836 -
14837 -__all__ = [
14838 - "editor_is_executable",
14839 - "FindPackagesToScan",
14840 - "FindPortdir",
14841 - "get_commit_message_with_editor",
14842 - "get_committer_name",
14843 - "have_ebuild_dir",
14844 - "have_profile_dir",
14845 - "UpdateChangeLog",
14846 -]
14847 -
14848 -import errno
14849 -import io
14850 -from itertools import chain
14851 -import logging
14852 -import pwd
14853 -import stat
14854 -import time
14855 -import textwrap
14856 -import difflib
14857 -import tempfile
14858 -
14859 -# import our initialized portage instance
14860 -from repoman._portage import portage
14861 -
14862 -from portage import os
14863 -from portage import shutil
14864 -from portage import _encodings
14865 -from portage import _unicode_decode
14866 -from portage import _unicode_encode
14867 -from portage import util
14868 -from portage.localization import _
14869 -from portage.process import find_binary
14870 -from portage.output import green
14871 -
14872 -# pylint: disable=ungrouped-imports
14873 -from repoman.copyrights import update_copyright_year
14874 -
14875 -
14876 -normalize_path = util.normalize_path
14877 -util.initialize_logger()
14878 -
14879 -
14880 -def have_profile_dir(path, maxdepth=3, filename="profiles.desc"):
14881 - """
14882 - Try to figure out if 'path' has a profiles/
14883 - dir in it by checking for the given filename.
14884 - """
14885 - while path != "/" and maxdepth:
14886 - if os.path.exists(os.path.join(path, "profiles", filename)):
14887 - return normalize_path(path)
14888 - path = normalize_path(path + "/..")
14889 - maxdepth -= 1
14890 -
14891 -
14892 -def have_ebuild_dir(path, maxdepth=3):
14893 - """
14894 - Try to figure out if 'path' or a subdirectory contains one or more
14895 - ebuild files named appropriately for their parent directory.
14896 - """
14897 - stack = [(normalize_path(path), 1)]
14898 - while stack:
14899 - path, depth = stack.pop()
14900 - basename = os.path.basename(path)
14901 - try:
14902 - listdir = os.listdir(path)
14903 - except OSError:
14904 - continue
14905 - for filename in listdir:
14906 - abs_filename = os.path.join(path, filename)
14907 - try:
14908 - st = os.stat(abs_filename)
14909 - except OSError:
14910 - continue
14911 - if stat.S_ISDIR(st.st_mode):
14912 - if depth < maxdepth:
14913 - stack.append((abs_filename, depth + 1))
14914 - elif stat.S_ISREG(st.st_mode):
14915 - if filename.endswith(".ebuild") and filename.startswith(basename + "-"):
14916 - return os.path.dirname(os.path.dirname(path))
14917 -
14918 -
14919 -def FindPackagesToScan(settings, startdir, reposplit):
14920 - """Try to find packages that need to be scanned
14921 -
14922 - Args:
14923 - settings - portage.config instance, preferably repoman_settings
14924 - startdir - directory that repoman was run in
14925 - reposplit - root of the repository
14926 - Returns:
14927 - A list of directories to scan
14928 - """
14929 -
14930 - def AddPackagesInDir(path):
14931 - """Given a list of dirs, add any packages in it"""
14932 - ret = []
14933 - pkgdirs = os.listdir(path)
14934 - for d in pkgdirs:
14935 - if d == "CVS" or d.startswith("."):
14936 - continue
14937 - p = os.path.join(path, d)
14938 -
14939 - if os.path.isdir(p):
14940 - cat_pkg_dir = os.path.join(*p.split(os.path.sep)[-2:])
14941 - logging.debug("adding %s to scanlist" % cat_pkg_dir)
14942 - ret.append(cat_pkg_dir)
14943 - return ret
14944 -
14945 - scanlist = []
14946 - repolevel = len(reposplit)
14947 - if repolevel == 1: # root of the tree, startdir = repodir
14948 - for cat in settings.categories:
14949 - path = os.path.join(startdir, cat)
14950 - if not os.path.isdir(path):
14951 - continue
14952 - scanlist.extend(AddPackagesInDir(path))
14953 - elif repolevel == 2: # category level, startdir = catdir
14954 - # We only want 1 segment of the directory,
14955 - # this is why we use catdir instead of startdir.
14956 - catdir = reposplit[-2]
14957 - if catdir not in settings.categories:
14958 - logging.warn(
14959 - "%s is not a valid category according to profiles/categories, "
14960 - "skipping checks in %s" % (catdir, catdir)
14961 - )
14962 - else:
14963 - scanlist = AddPackagesInDir(catdir)
14964 - elif repolevel == 3: # pkgdir level, startdir = pkgdir
14965 - catdir = reposplit[-2]
14966 - pkgdir = reposplit[-1]
14967 - if catdir not in settings.categories:
14968 - logging.warn(
14969 - "%s is not a valid category according to profiles/categories, "
14970 - "skipping checks in %s" % (catdir, catdir)
14971 - )
14972 - else:
14973 - path = os.path.join(catdir, pkgdir)
14974 - logging.debug("adding %s to scanlist" % path)
14975 - scanlist.append(path)
14976 - return scanlist
14977 -
14978 -
14979 -def editor_is_executable(editor):
14980 - """
14981 - Given an EDITOR string, validate that it refers to
14982 - an executable. This uses shlex_split() to split the
14983 - first component and do a PATH lookup if necessary.
14984 -
14985 - @param editor: An EDITOR value from the environment.
14986 - @type: string
14987 - @rtype: bool
14988 - @return: True if an executable is found, False otherwise.
14989 - """
14990 - editor_split = util.shlex_split(editor)
14991 - if not editor_split:
14992 - return False
14993 - filename = editor_split[0]
14994 - if not os.path.isabs(filename):
14995 - return find_binary(filename) is not None
14996 - return os.access(filename, os.X_OK) and os.path.isfile(filename)
14997 -
14998 -
14999 -def get_commit_message_with_editor(editor, message=None, prefix=""):
15000 - """
15001 - Execute editor with a temporary file as it's argument
15002 - and return the file content afterwards.
15003 -
15004 - @param editor: An EDITOR value from the environment
15005 - @type: string
15006 - @param message: An iterable of lines to show in the editor.
15007 - @type: iterable
15008 - @param prefix: Suggested prefix for the commit message summary line.
15009 - @type: string
15010 - @rtype: string or None
15011 - @return: A string on success or None if an error occurs.
15012 - """
15013 - commitmessagedir = tempfile.mkdtemp(".repoman.msg")
15014 - filename = os.path.join(commitmessagedir, "COMMIT_EDITMSG")
15015 - try:
15016 - with open(filename, "wb") as mymsg:
15017 - mymsg.write(
15018 - _unicode_encode(
15019 - _(
15020 - prefix + "\n\n# Please enter the commit message "
15021 - "for your changes.\n# (Comment lines starting "
15022 - "with '#' will not be included)\n"
15023 - ),
15024 - encoding=_encodings["content"],
15025 - errors="backslashreplace",
15026 - )
15027 - )
15028 - if message:
15029 - mymsg.write(b"#\n")
15030 - for line in message:
15031 - mymsg.write(
15032 - _unicode_encode(
15033 - "#" + line,
15034 - encoding=_encodings["content"],
15035 - errors="backslashreplace",
15036 - )
15037 - )
15038 - retval = os.system(editor + " '%s'" % filename)
15039 - if not (os.WIFEXITED(retval) and os.WEXITSTATUS(retval) == os.EX_OK):
15040 - return None
15041 - try:
15042 - with io.open(
15043 - _unicode_encode(filename, encoding=_encodings["fs"], errors="strict"),
15044 - mode="r",
15045 - encoding=_encodings["content"],
15046 - errors="replace",
15047 - ) as f:
15048 - mylines = f.readlines()
15049 - except OSError as e:
15050 - if e.errno != errno.ENOENT:
15051 - raise
15052 - del e
15053 - return None
15054 - return "".join(line for line in mylines if not line.startswith("#"))
15055 - finally:
15056 - try:
15057 - shutil.rmtree(commitmessagedir)
15058 - except OSError:
15059 - pass
15060 -
15061 -
15062 -def FindPortdir(settings):
15063 - """Try to figure out what repo we are in and whether we are in a regular
15064 - tree or an overlay.
15065 -
15066 - Basic logic is:
15067 -
15068 - 1. Determine what directory we are in (supports symlinks).
15069 - 2. Build a list of directories from / to our current location
15070 - 3. Iterate over PORTDIR_OVERLAY, if we find a match,
15071 - search for a profiles directory in the overlay. If it has one,
15072 - make it portdir, otherwise make it portdir_overlay.
15073 - 4. If we didn't find an overlay in PORTDIR_OVERLAY,
15074 - see if we are in PORTDIR; if so, set portdir_overlay to PORTDIR.
15075 - If we aren't in PORTDIR, see if PWD has a profiles dir, if so,
15076 - set portdir_overlay and portdir to PWD, else make them False.
15077 - 5. If we haven't found portdir_overlay yet,
15078 - it means the user is doing something odd, report an error.
15079 - 6. If we haven't found a portdir yet, set portdir to PORTDIR.
15080 -
15081 - Args:
15082 - settings - portage.config instance, preferably repoman_settings
15083 - Returns:
15084 - list(portdir, portdir_overlay, location)
15085 - """
15086 -
15087 - portdir = None
15088 - portdir_overlay = None
15089 - location = os.getcwd()
15090 - pwd = _unicode_decode(os.environ.get("PWD", ""), encoding=_encodings["fs"])
15091 - if pwd and pwd != location and os.path.realpath(pwd) == location:
15092 - # getcwd() returns the canonical path but that makes it hard for repoman to
15093 - # orient itself if the user has symlinks in their repository structure.
15094 - # We use os.environ["PWD"], if available, to get the non-canonical path of
15095 - # the current working directory (from the shell).
15096 - location = pwd
15097 -
15098 - location = normalize_path(location)
15099 -
15100 - path_ids = {}
15101 - p = location
15102 - s = None
15103 - while True:
15104 - s = os.stat(p)
15105 - path_ids[(s.st_dev, s.st_ino)] = p
15106 - if p == "/":
15107 - break
15108 - p = os.path.dirname(p)
15109 - if location[-1] != "/":
15110 - location += "/"
15111 -
15112 - for overlay in portage.util.shlex_split(settings["PORTDIR_OVERLAY"]):
15113 - overlay = os.path.realpath(overlay)
15114 - try:
15115 - s = os.stat(overlay)
15116 - except OSError:
15117 - continue
15118 - overlay = path_ids.get((s.st_dev, s.st_ino))
15119 - if overlay is None:
15120 - continue
15121 - if overlay[-1] != "/":
15122 - overlay += "/"
15123 - if True:
15124 - portdir_overlay = overlay
15125 - subdir = location[len(overlay) :]
15126 - if subdir and subdir[-1] != "/":
15127 - subdir += "/"
15128 - if have_profile_dir(location, subdir.count("/")):
15129 - portdir = portdir_overlay
15130 - break
15131 -
15132 - # Couldn't match location with anything from PORTDIR_OVERLAY,
15133 - # so fall back to have_profile_dir() checks alone. Assume that
15134 - # an overlay will contain at least a "repo_name" file while a
15135 - # master repo (portdir) will contain at least a "profiles.desc"
15136 - # file.
15137 - if not portdir_overlay:
15138 - portdir_overlay = have_profile_dir(location, filename="repo_name")
15139 - if not portdir_overlay:
15140 - portdir_overlay = have_ebuild_dir(location)
15141 - if portdir_overlay:
15142 - subdir = location[len(portdir_overlay) :]
15143 - if subdir and subdir[-1] != os.sep:
15144 - subdir += os.sep
15145 - if have_profile_dir(location, subdir.count(os.sep)):
15146 - portdir = portdir_overlay
15147 -
15148 - if not portdir_overlay:
15149 - if (settings["PORTDIR"] + os.path.sep).startswith(location):
15150 - portdir_overlay = settings["PORTDIR"]
15151 - else:
15152 - portdir_overlay = have_profile_dir(location)
15153 - portdir = portdir_overlay
15154 -
15155 - if not portdir_overlay:
15156 - msg = (
15157 - "Repoman is unable to determine PORTDIR or PORTDIR_OVERLAY"
15158 - + " from the current working directory"
15159 - )
15160 - logging.critical(msg)
15161 - return (None, None, None)
15162 -
15163 - if not portdir:
15164 - portdir = settings["PORTDIR"]
15165 -
15166 - if not portdir_overlay.endswith("/"):
15167 - portdir_overlay += "/"
15168 -
15169 - if not portdir.endswith("/"):
15170 - portdir += "/"
15171 -
15172 - return [normalize_path(x) for x in (portdir, portdir_overlay, location)]
15173 -
15174 -
15175 -def get_committer_name(env=None):
15176 - """Generate a committer string like echangelog does."""
15177 - if env is None:
15178 - env = os.environ
15179 - if "GENTOO_COMMITTER_NAME" in env and "GENTOO_COMMITTER_EMAIL" in env:
15180 - user = "%s <%s>" % (env["GENTOO_COMMITTER_NAME"], env["GENTOO_COMMITTER_EMAIL"])
15181 - elif "GENTOO_AUTHOR_NAME" in env and "GENTOO_AUTHOR_EMAIL" in env:
15182 - user = "%s <%s>" % (env["GENTOO_AUTHOR_NAME"], env["GENTOO_AUTHOR_EMAIL"])
15183 - elif "ECHANGELOG_USER" in env:
15184 - user = env["ECHANGELOG_USER"]
15185 - else:
15186 - pwd_struct = pwd.getpwuid(os.getuid())
15187 - gecos = pwd_struct.pw_gecos.split(",")[0] # bug #80011
15188 - user = "%s <%s@g.o>" % (gecos, pwd_struct.pw_name)
15189 - return user
15190 -
15191 -
15192 -def UpdateChangeLog(
15193 - pkgdir,
15194 - user,
15195 - msg,
15196 - skel_path,
15197 - category,
15198 - package,
15199 - new=(),
15200 - removed=(),
15201 - changed=(),
15202 - pretend=False,
15203 - quiet=False,
15204 -):
15205 - """
15206 - Write an entry to an existing ChangeLog, or create a new one.
15207 - Updates copyright year on changed files, and updates the header of
15208 - ChangeLog with the contents of skel.ChangeLog.
15209 - """
15210 -
15211 - if "<root@" in user:
15212 - if not quiet:
15213 - logging.critical("Please set ECHANGELOG_USER or run as non-root")
15214 - return None
15215 -
15216 - # ChangeLog times are in UTC
15217 - gmtime = time.gmtime()
15218 - year = time.strftime("%Y", gmtime)
15219 - date = time.strftime("%d %b %Y", gmtime)
15220 -
15221 - cl_path = os.path.join(pkgdir, "ChangeLog")
15222 - clold_lines = []
15223 - clnew_lines = []
15224 - old_header_lines = []
15225 - header_lines = []
15226 -
15227 - clold_file = None
15228 - try:
15229 - clold_file = io.open(
15230 - _unicode_encode(cl_path, encoding=_encodings["fs"], errors="strict"),
15231 - mode="r",
15232 - encoding=_encodings["repo.content"],
15233 - errors="replace",
15234 - )
15235 - except EnvironmentError:
15236 - pass
15237 -
15238 - f, clnew_path = tempfile.mkstemp()
15239 -
15240 - # construct correct header first
15241 - try:
15242 - if clold_file is not None:
15243 - # retain header from old ChangeLog
15244 - first_line = True
15245 - for line in clold_file:
15246 - line_strip = line.strip()
15247 - if line_strip and line[:1] != "#":
15248 - clold_lines.append(line)
15249 - break
15250 - # always make sure cat/pkg is up-to-date in case we are
15251 - # moving packages around, or copied from another pkg, or ...
15252 - if first_line:
15253 - if line.startswith("# ChangeLog for"):
15254 - line = "# ChangeLog for %s/%s\n" % (category, package)
15255 - first_line = False
15256 - old_header_lines.append(line)
15257 - header_lines.append(update_copyright_year(year, line))
15258 - if not line_strip:
15259 - break
15260 -
15261 - clskel_file = None
15262 - if not header_lines:
15263 - # delay opening this until we find we need a header
15264 - try:
15265 - clskel_file = io.open(
15266 - _unicode_encode(
15267 - skel_path, encoding=_encodings["fs"], errors="strict"
15268 - ),
15269 - mode="r",
15270 - encoding=_encodings["repo.content"],
15271 - errors="replace",
15272 - )
15273 - except EnvironmentError:
15274 - pass
15275 -
15276 - if clskel_file is not None:
15277 - # read skel.ChangeLog up to first empty line
15278 - for line in clskel_file:
15279 - line_strip = line.strip()
15280 - if not line_strip:
15281 - break
15282 - line = line.replace("<CATEGORY>", category)
15283 - line = line.replace("<PACKAGE_NAME>", package)
15284 - line = update_copyright_year(year, line)
15285 - header_lines.append(line)
15286 - header_lines.append("\n")
15287 - clskel_file.close()
15288 -
15289 - # write new ChangeLog entry
15290 - clnew_lines.extend(header_lines)
15291 - newebuild = False
15292 - for fn in new:
15293 - if not fn.endswith(".ebuild"):
15294 - continue
15295 - ebuild = fn.split(os.sep)[-1][0:-7]
15296 - clnew_lines.append("*%s (%s)\n" % (ebuild, date))
15297 - newebuild = True
15298 - if newebuild:
15299 - clnew_lines.append("\n")
15300 - trivial_files = ("ChangeLog", "Manifest")
15301 - display_new = ["+" + elem for elem in new if elem not in trivial_files]
15302 - display_removed = ["-" + elem for elem in removed]
15303 - display_changed = [elem for elem in changed if elem not in trivial_files]
15304 - if not (display_new or display_removed or display_changed):
15305 - # If there's nothing else to display, show one of the
15306 - # trivial files.
15307 - for fn in trivial_files:
15308 - if fn in new:
15309 - display_new = ["+" + fn]
15310 - break
15311 - elif fn in changed:
15312 - display_changed = [fn]
15313 - break
15314 -
15315 - display_new.sort()
15316 - display_removed.sort()
15317 - display_changed.sort()
15318 -
15319 - mesg = "%s; %s %s:" % (
15320 - date,
15321 - user,
15322 - ", ".join(chain(display_new, display_removed, display_changed)),
15323 - )
15324 - for line in textwrap.wrap(
15325 - mesg,
15326 - 80,
15327 - initial_indent=" ",
15328 - subsequent_indent=" ",
15329 - break_on_hyphens=False,
15330 - ):
15331 - clnew_lines.append("%s\n" % line)
15332 - for line in textwrap.wrap(msg, 80, initial_indent=" ", subsequent_indent=" "):
15333 - clnew_lines.append("%s\n" % line)
15334 - # Don't append a trailing newline if the file is new.
15335 - if clold_file is not None:
15336 - clnew_lines.append("\n")
15337 -
15338 - f = io.open(
15339 - f, mode="w", encoding=_encodings["repo.content"], errors="backslashreplace"
15340 - )
15341 -
15342 - for line in clnew_lines:
15343 - f.write(line)
15344 -
15345 - # append stuff from old ChangeLog
15346 - if clold_file is not None:
15347 -
15348 - if clold_lines:
15349 - # clold_lines may contain a saved non-header line
15350 - # that we want to write first.
15351 - # Also, append this line to clnew_lines so that the
15352 - # unified_diff call doesn't show it as removed.
15353 - for line in clold_lines:
15354 - f.write(line)
15355 - clnew_lines.append(line)
15356 -
15357 - else:
15358 - # ensure that there is no more than one blank
15359 - # line after our new entry
15360 - for line in clold_file:
15361 - if line.strip():
15362 - f.write(line)
15363 - break
15364 -
15365 - # Now prepend old_header_lines to clold_lines, for use
15366 - # in the unified_diff call below.
15367 - clold_lines = old_header_lines + clold_lines
15368 -
15369 - # Trim any trailing newlines.
15370 - lines = clold_file.readlines()
15371 - clold_file.close()
15372 - while lines and lines[-1] == "\n":
15373 - del lines[-1]
15374 - f.writelines(lines)
15375 - f.close()
15376 -
15377 - # show diff
15378 - if not quiet:
15379 - for line in difflib.unified_diff(
15380 - clold_lines, clnew_lines, fromfile=cl_path, tofile=cl_path, n=0
15381 - ):
15382 - util.writemsg_stdout(line, noiselevel=-1)
15383 - util.writemsg_stdout("\n", noiselevel=-1)
15384 -
15385 - if pretend:
15386 - # remove what we've done
15387 - os.remove(clnew_path)
15388 - else:
15389 - # rename to ChangeLog, and set permissions
15390 - try:
15391 - clold_stat = os.stat(cl_path)
15392 - except OSError:
15393 - clold_stat = None
15394 -
15395 - shutil.move(clnew_path, cl_path)
15396 -
15397 - if clold_stat is None:
15398 - util.apply_permissions(cl_path, mode=0o644)
15399 - else:
15400 - util.apply_stat_permissions(cl_path, clold_stat)
15401 -
15402 - if clold_file is None:
15403 - return True
15404 - else:
15405 - return False
15406 - except IOError as e:
15407 - err = "Repoman is unable to create/write to Changelog.new file: %s" % (e,)
15408 - logging.critical(err)
15409 - # try to remove if possible
15410 - try:
15411 - os.remove(clnew_path)
15412 - except OSError:
15413 - pass
15414 - return None
15415 -
15416 -
15417 -def repoman_sez(msg):
15418 - print(green("RepoMan sez:"), msg)
15419
15420 diff --git a/repoman/man/repoman.1 b/repoman/man/repoman.1
15421 deleted file mode 100644
15422 index 5dbc41560..000000000
15423 --- a/repoman/man/repoman.1
15424 +++ /dev/null
15425 @@ -1,478 +0,0 @@
15426 -.TH "REPOMAN" "1" "March 2021" "Repoman VERSION" "Repoman"
15427 -.SH NAME
15428 -repoman \- Gentoo's program to enforce a minimal level of quality assurance in
15429 -packages added to the ebuild repository
15430 -.SH SYNOPSIS
15431 -\fBrepoman\fR [\fIoption\fR] [\fImode\fR]
15432 -.SH DESCRIPTION
15433 -.BR "Quality is job zero."
15434 -
15435 -.BR repoman
15436 -checks the quality of ebuild repositories.
15437 -
15438 -Note: \fBrepoman commit\fR only works \fIinside local\fR cvs, git, or
15439 -subversion repositories.
15440 -
15441 -Note: Messages pertaining to specific lines may be inaccurate in the
15442 -prescence of continuation lines from use of the \fI\\\fR character in
15443 -BASH.
15444 -.SH OPTIONS
15445 -.TP
15446 -\fB-a\fR, \fB--ask\fR
15447 -Request a confirmation before commiting
15448 -.TP
15449 -\fB-b\fR, \fB--bug\fR
15450 -Include a bug reference in the commit message footer. The argument can
15451 -be either a Gentoo bug number or a full bug URL (either Gentoo
15452 -or upstream). Gentoo bug URLs are automatically shortened to
15453 -the canonical \fBhttps://bugs.gentoo.org/NNNNNN\fR form, and HTTPS
15454 -is forced for known bug trackers.
15455 -
15456 -When pushing to the Gentoo repository, the reference to the commit
15457 -will be automatically added as a comment on the bug.
15458 -.TP
15459 -\fB-c\fR, \fB--closes\fR
15460 -Include a \fBCloses\fR tag in the commit message footer that can be used
15461 -to close bugs and pull requests. The argument can be either a Gentoo bug
15462 -number or a full PR/bug URL. Gentoo bug URLs are automatically shortened
15463 -to the canonical \fBhttps://bugs.gentoo.org/NNNNNN\fR form, and HTTPS
15464 -is forced for known bug trackers.
15465 -
15466 -When pushing to the Gentoo repository, the referenced bugs will be
15467 -closed as RESOLVED/FIXED automatically with a comment referencing
15468 -the commit. Furthermore, GitHub pull requests will be closed as well
15469 -due to the automatic GitHub mirroring.
15470 -
15471 -Other platforms using the \fBCloses\fR tag include GitLab and Bitbucket.
15472 -.TP
15473 -\fB\-\-digest=<y|n>\fR
15474 -Automatically update Manifest digests for modified files. This
15475 -option triggers a behavior that is very similar to that enabled
15476 -by FEATURES="digest" in \fBmake.conf\fR(5). In order to enable
15477 -this behavior by default for repoman alone, add
15478 -\fB\-\-digest=y\fR to the \fIREPOMAN_DEFAULT_OPTS\fR variable in
15479 -\fBmake.conf\fR(5). The \fBmanifest\-check\fR mode will
15480 -automatically ignore the \-\-digest option.
15481 -
15482 -\fBNOTE:\fR
15483 -This option does not trigger update of digests for Manifest DIST
15484 -entries that already exist. Replacement of existing Manifest
15485 -DIST entries can be forced by using the \fBmanifest\fR mode
15486 -together with the \fB\-\-force\fR option.
15487 -.TP
15488 -\fB-f\fR, \fB--force\fR
15489 -Force commit to proceed, regardless of QA issues. For convenience, this option
15490 -causes the most time consuming QA checks to be skipped. The commit message will
15491 -include an indication that this option has been enabled, together with the
15492 -usual portage version stamp.
15493 -
15494 -When used together with \fBmanifest\fR mode, \fB--force\fR causes existing
15495 -digests to be replaced for any files that exist in ${DISTDIR}.
15496 -Existing digests are assumed to be correct for files that would otherwise
15497 -have to be downloaded in order to recompute digests. \fBWARNING:\fR When
15498 -replacing existing digests, it is the user's responsibility to ensure that
15499 -files contained in ${DISTDIR} have the correct identities. Especially beware
15500 -of partially downloaded files.
15501 -.TP
15502 -\fB-S\fR, \fB--straight-to-stable\fR
15503 -Allow committing straight to stable
15504 -.TP
15505 -\fB-q\fR, \fB--quiet\fR
15506 -Be less verbose about extraneous info
15507 -.TP
15508 -\fB-p\fR, \fB--pretend\fR
15509 -Don't commit or fix anything; just show what would be done
15510 -.TP
15511 -\fB\-j\fR, \fB\-\-jobs\fR
15512 -Specifies the number of jobs (processes) to run simultaneously.
15513 -.TP
15514 -\fB\-l\fR, \fB\-\-load-average\fR
15515 -Specifies that no new jobs (processes) should be started if there are others
15516 -jobs running and the load average is at least load (a floating\-point number).
15517 -.TP
15518 -\fB-x\fR, \fB--xmlparse\fR
15519 -Forces the metadata.xml parse check to be carried out
15520 -.TP
15521 -\fB-v\fR, \fB--verbose\fR
15522 -Displays every package name while checking
15523 -.TP
15524 -\fB\-\-echangelog=<y|n|force>\fR
15525 -For commit mode, call echangelog if ChangeLog is unmodified (or
15526 -regardless of modification if 'force' is specified). This option
15527 -can be enabled by default for a particular repository by setting
15528 -"update\-changelog = true" in metadata/layout.conf (see
15529 -\fBportage\fR(5)).
15530 -.TP
15531 -\fB\-\-experimental\-inherit=<y|n>\fR
15532 -Enable experimental inherit.missing checks which may misbehave when the
15533 -internal eclass database becomes outdated.
15534 -.TP
15535 -\fB\-\-experimental\-repository\-modules=<y|n>\fR
15536 -Enable experimental repository modules:
15537 -\fIhttps://wiki.gentoo.org/wiki/Project:Portage/Repoman-Module-specs\fR
15538 -.TP
15539 -\fB\-\-if\-modified=<y|n>\fR
15540 -Only check packages that have uncommitted modifications
15541 -.TP
15542 -\fB\-i\fR, \fB\-\-ignore\-arches\fR
15543 -Ignore arch-specific failures (where arch != host)
15544 -.TP
15545 -\fB\-\-ignore\-default\-opts\fR
15546 -Do not use the \fIREPOMAN_DEFAULT_OPTS\fR environment variable.
15547 -.TP
15548 -\fB\-I\fR, \fB\-\-ignore\-masked\fR
15549 -Ignore masked packages (not allowed with commit mode)
15550 -.TP
15551 -.BR "\-\-include\-arches " ARCHES
15552 -A space separated list of arches used to filter the selection of
15553 -profiles for dependency checks.
15554 -.TP
15555 -.BR "\-\-include\-profiles " PROFILES
15556 -A space separated list of profiles used to
15557 -define the selection of profiles for dependency checks.
15558 -.TP
15559 -\fB\-d\fR, \fB\-\-include\-dev\fR
15560 -Include dev profiles in dependency checks.
15561 -.TP
15562 -\fB\-e <y|n>\fR, \fB\-\-include\-exp\-profiles=<y|n>\fR
15563 -Include exp profiles in dependency checks.
15564 -.TP
15565 -\fB\-\-unmatched\-removal\fR
15566 -Enable strict checking of package.mask and package.unmask files for
15567 -unmatched removal atoms.
15568 -.TP
15569 -\fB\-\-without\-mask\fR
15570 -Behave as if no package.mask entries exist (not allowed with commit mode)
15571 -.TP
15572 -\fB-m\fR, \fB--commitmsg\fR
15573 -Adds a commit message via the command line
15574 -.TP
15575 -\fB-M\fR, \fB--commitmsgfile\fR
15576 -Adds a commit message from the specified file. This option also will perform
15577 -an automatic text substitution of a leading "cat/pkg: " string (upper or lower
15578 -case) with the actual category/package prefix as defined by the required message
15579 -format. Use this option for templating a common commit message for multiple
15580 -package updates.
15581 -.TP
15582 -\fB-V\fR, \fB--version\fR
15583 -Show version info
15584 -.TP
15585 -\fB-h\fR, \fB--help\fR
15586 -Show this screen
15587 -.SH MODES
15588 -.TP
15589 -.B full
15590 -Scan directory tree for QA issues (full listing)
15591 -.TP
15592 -.B help
15593 -Show this screen
15594 -.TP
15595 -.B scan
15596 -Scan directory tree for QA issues (short listing)
15597 -.TP
15598 -.B fix
15599 -Fix simple QA issues (stray digests, missing digests)
15600 -.TP
15601 -.B manifest
15602 -Generate a Manifest (fetches distfiles if necessary). See the \fB\-\-force\fR
15603 -option if you would like to replace existing distfiles digests.
15604 -.TP
15605 -.B manifest-check
15606 -Check Manifests for missing or incorrect digests
15607 -.TP
15608 -.B commit
15609 -Scan directory tree for QA issues; if OK, commit via VCS
15610 -.TP
15611 -.B ci
15612 -Synonym for commit
15613 -.SH QA KEYWORDS
15614 -.TP
15615 -.B CVS/Entries.IO_error
15616 -Attempting to commit, and an IO error was encountered access the Entries file
15617 -.TP
15618 -.B DESCRIPTION.missing
15619 -Ebuilds that have a missing or empty DESCRIPTION variable
15620 -.TP
15621 -.B EAPI.definition
15622 -EAPI definition does not conform to PMS section 7.3.1 (first
15623 -non\-comment, non\-blank line). See bug #402167.
15624 -.TP
15625 -.B EAPI.deprecated
15626 -Ebuilds that use features that are deprecated in the current EAPI
15627 -.TP
15628 -.B EAPI.incompatible
15629 -Ebuilds that use features that are only available with a different EAPI
15630 -.TP
15631 -.B EAPI.unsupported
15632 -Ebuilds that have an unsupported EAPI version (you must upgrade portage)
15633 -.TP
15634 -.B HOMEPAGE.missing
15635 -Ebuilds that have a missing or empty HOMEPAGE variable
15636 -.TP
15637 -.B HOMEPAGE.missingurischeme
15638 -HOMEPAGE is missing an URI scheme
15639 -.TP
15640 -.B HOMEPAGE.virtual
15641 -Virtuals that have a non-empty HOMEPAGE variable
15642 -.TP
15643 -.B IUSE.invalid
15644 -This ebuild has a variable in IUSE that is not in the use.desc or its
15645 -metadata.xml file
15646 -.TP
15647 -.B IUSE.missing
15648 -This ebuild has a USE conditional which references a flag that is not listed in
15649 -IUSE
15650 -.TP
15651 -.B KEYWORDS.dropped
15652 -Ebuilds that appear to have dropped KEYWORDS for some arch
15653 -.TP
15654 -.B KEYWORDS.invalid
15655 -This ebuild contains KEYWORDS that are not listed in profiles/arch.list or for
15656 -which no valid profile was found
15657 -.TP
15658 -.B KEYWORDS.missing
15659 -Ebuilds that have a missing or empty KEYWORDS variable
15660 -.TP
15661 -.B KEYWORDS.stable
15662 -Ebuilds that have been added directly with stable KEYWORDS
15663 -.TP
15664 -.B KEYWORDS.stupid
15665 -Ebuilds that use KEYWORDS=-* instead of package.mask
15666 -.TP
15667 -.B KEYWORDS.unsorted
15668 -Ebuilds that contain KEYWORDS which are not sorted alphabetically.
15669 -.TP
15670 -.B LICENSE.deprecated
15671 -This ebuild is listing a deprecated license.
15672 -.TP
15673 -.B LICENSE.invalid
15674 -This ebuild is listing a license that doesnt exist in portages license/ dir.
15675 -.TP
15676 -.B LICENSE.missing
15677 -Ebuilds that have a missing or empty LICENSE variable
15678 -.TP
15679 -.B LICENSE.syntax
15680 -Syntax error in LICENSE (usually an extra/missing space/parenthesis)
15681 -.TP
15682 -.B LICENSE.virtual
15683 -Virtuals that have a non-empty LICENSE variable
15684 -.TP
15685 -.B LIVEVCS.stable
15686 -Ebuild is a live ebuild (cvs, git, darcs, svn, etc) checkout with stable
15687 -keywords.
15688 -.TP
15689 -.B LIVEVCS.unmasked
15690 -Ebuild is a live ebuild (cvs, git, darcs, svn, etc) checkout but has keywords
15691 -and is not masked in the global package.mask.
15692 -.TP
15693 -.B PDEPEND.suspect
15694 -PDEPEND contains a package that usually only belongs in DEPEND
15695 -.TP
15696 -.B RDEPEND.implicit
15697 -RDEPEND is unset in the ebuild which triggers implicit RDEPEND=$DEPEND
15698 -assignment (prior to EAPI 4)
15699 -.TP
15700 -.B RDEPEND.suspect
15701 -RDEPEND contains a package that usually only belongs in DEPEND
15702 -.TP
15703 -.B PROPERTIES.syntax
15704 -Syntax error in PROPERTIES (usually an extra/missing space/parenthesis)
15705 -.TP
15706 -.B RESTRICT.syntax
15707 -Syntax error in RESTRICT (usually an extra/missing space/parenthesis)
15708 -.B SLOT.invalid
15709 -Ebuilds that have a missing or invalid SLOT variable value
15710 -.TP
15711 -.B SRC_URI.mirror
15712 -A uri listed in profiles/thirdpartymirrors is found in SRC_URI
15713 -.TP
15714 -.B changelog.ebuildadded
15715 -An ebuild was added but the ChangeLog was not modified
15716 -.TP
15717 -.B changelog.missing
15718 -Missing ChangeLog files
15719 -.TP
15720 -.B changelog.notadded
15721 -ChangeLogs that exist but have not been added to the vcs
15722 -.TP
15723 -.B dependency.bad
15724 -User-visible ebuilds with unsatisfied dependencies (matched against *visible*
15725 -ebuilds)
15726 -.TP
15727 -.B dependency.badindev
15728 -User-visible ebuilds with unsatisfied dependencies (matched against *visible*
15729 -ebuilds) in developing arch
15730 -.TP
15731 -.B dependency.badinexp
15732 -User-visible ebuilds with unsatisfied dependencies (matched against *visible*
15733 -ebuilds) in experimental arch
15734 -.TP
15735 -.B dependency.badmasked
15736 -Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds)
15737 -.TP
15738 -.B dependency.badmaskedindev
15739 -Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds) in
15740 -developing arch
15741 -.TP
15742 -.B dependency.badmaskedinexp
15743 -Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds) in
15744 -experimental arch
15745 -.TP
15746 -.B dependency.badtilde
15747 -Uses the ~ dep operator with a non-zero revision part, which is useless (the
15748 -revision is ignored)
15749 -.TP
15750 -.B dependency.deprecated
15751 -Ebuild has a dependency that refers to a deprecated package
15752 -.TP
15753 -.B dependency.syntax
15754 -Syntax error in dependency string (usually an extra/missing space/parenthesis)
15755 -.TP
15756 -.B dependency.unknown
15757 -Ebuild has a dependency that refers to an unknown package (which may be
15758 -valid if it is a blocker for a renamed/removed package, or is an
15759 -alternative choice provided by an overlay)
15760 -.TP
15761 -.B digest.assumed
15762 -Existing digest must be assumed correct (Package level only)
15763 -.TP
15764 -.B digest.missing
15765 -Some files listed in SRC_URI aren't referenced in the Manifest
15766 -.TP
15767 -.B digest.unused
15768 -Some files listed in the Manifest aren't referenced in SRC_URI
15769 -.TP
15770 -.B ebuild.absdosym
15771 -Ebuild uses 'dosym' with explicit absolute path where relative path
15772 -could be used
15773 -.TP
15774 -.B ebuild.badheader
15775 -This ebuild has a malformed header
15776 -.TP
15777 -.B ebuild.invalidname
15778 -Ebuild files with a non-parseable or syntactically incorrect name (or using 2.1
15779 -versioning extensions)
15780 -.TP
15781 -.B ebuild.majorsyn
15782 -This ebuild has a major syntax error that may cause the ebuild to fail
15783 -partially or fully
15784 -.TP
15785 -.B ebuild.minorsyn
15786 -This ebuild has a minor syntax error that contravenes gentoo coding style
15787 -.TP
15788 -.B ebuild.namenomatch
15789 -Ebuild files that do not have the same name as their parent directory
15790 -.TP
15791 -.B ebuild.nesteddie
15792 -Placing 'die' inside ( ) prints an error, but doesn't stop the ebuild.
15793 -.TP
15794 -.B ebuild.notadded
15795 -Ebuilds that exist but have not been added to the vcs
15796 -.TP
15797 -.B ebuild.output
15798 -A simple sourcing of the ebuild produces output; this breaks ebuild policy.
15799 -.TP
15800 -.B ebuild.patches
15801 -PATCHES variable should be a bash array to ensure white space safety
15802 -.TP
15803 -.B ebuild.syntax
15804 -Error generating cache entry for ebuild; typically caused by ebuild syntax
15805 -error or digest verification failure.
15806 -.TP
15807 -.B file.UTF8
15808 -File is not UTF8 compliant
15809 -.TP
15810 -.B file.empty
15811 -Empty file in the files directory
15812 -.TP
15813 -.B file.executable
15814 -Ebuilds, digests, metadata.xml, Manifest, and ChangeLog do not need the
15815 -executable bit
15816 -.TP
15817 -.B file.name
15818 -File/dir name must be composed of only the following chars: a-zA-Z0-9._-+:
15819 -.TP
15820 -.B file.size
15821 -Files in the files directory must be under 20 KiB
15822 -.TP
15823 -.B inherit.missing
15824 -Ebuild uses functions from an eclass but does not inherit it
15825 -.TP
15826 -.B inherit.unused
15827 -Ebuild inherits an eclass but does not use it
15828 -.TP
15829 -.B inherit.deprecated
15830 -Ebuild inherits a deprecated eclass
15831 -.TP
15832 -.B java.eclassesnotused
15833 -With virtual/jdk in DEPEND you must inherit a java eclass. Refer to
15834 -\fIhttps://wiki.gentoo.org/wiki/Project:Java\fR for more information.
15835 -.TP
15836 -.B manifest.bad
15837 -Manifest has missing or incorrect digests
15838 -.TP
15839 -.B metadata.bad
15840 -Bad metadata.xml files
15841 -.TP
15842 -.B metadata.missing
15843 -Missing metadata.xml files
15844 -.TP
15845 -.B metadata.warning
15846 -Warnings in metadata.xml files
15847 -.TP
15848 -.B repo.eapi.banned
15849 -The ebuild uses an EAPI which is banned by the repository's
15850 -metadata/layout.conf settings.
15851 -.TP
15852 -.B repo.eapi.deprecated
15853 -The ebuild uses an EAPI which is deprecated by the repository's
15854 -metadata/layout.conf settings.
15855 -.TP
15856 -.B IUSE.rubydeprecated
15857 -The ebuild has set a ruby interpreter in USE_RUBY, that is not available as a ruby target anymore
15858 -.TP
15859 -.B portage.internal
15860 -The ebuild uses an internal Portage function or variable
15861 -.TP
15862 -.B upstream.workaround
15863 -The ebuild works around an upstream bug, an upstream bug should be filed and
15864 -tracked in bugs.gentoo.org
15865 -.TP
15866 -.B usage.obsolete
15867 -The ebuild makes use of an obsolete construct
15868 -.TP
15869 -.B variable.invalidchar
15870 -A variable contains an invalid character that is not part of the ASCII
15871 -character set.
15872 -.TP
15873 -.B variable.phase
15874 -Variable referenced found within scope of incorrect ebuild phase as specified by PMS.
15875 -.TP
15876 -.B variable.readonly
15877 -Assigning a readonly variable
15878 -.TP
15879 -.B variable.usedwithhelpers
15880 -Ebuild uses D, ROOT, BROOT, ED, EROOT or EPREFIX with helpers
15881 -.TP
15882 -.B virtual.suspect
15883 -Ebuild contains a package that usually should be pulled via virtual/,
15884 -not directly.
15885 -.TP
15886 -.B wxwidgets.eclassnotused
15887 -Ebuild DEPENDs on x11-libs/wxGTK without inheriting wxwidgets.eclass. Refer to
15888 -bug #305469 for more information.
15889 -.SH "BEHAVIOR"
15890 -When invoked from a level higher than a package directory, \fBrepoman\fR
15891 -will recurse through a directory tree and execute the given command
15892 -on a per\-package basis, e.g. \fBrepoman manifest\fR at the root of
15893 -the repository will generate manifests for every package within the
15894 -repository.
15895 -.SH "REPORTING BUGS"
15896 -Please report bugs via https://bugs.gentoo.org/
15897 -.SH AUTHORS
15898 -.nf
15899 -Daniel Robbins <drobbins@g.o>
15900 -Saleem Abdulrasool <compnerd@g.o>
15901 -.fi
15902 -.SH "SEE ALSO"
15903 -.BR emerge (1)
15904
15905 diff --git a/repoman/runtests b/repoman/runtests
15906 deleted file mode 100755
15907 index f02bfe875..000000000
15908 --- a/repoman/runtests
15909 +++ /dev/null
15910 @@ -1,189 +0,0 @@
15911 -#!/usr/bin/env python
15912 -# Copyright 2010-2020 Gentoo Authors
15913 -# Distributed under the terms of the GNU General Public License v2
15914 -#
15915 -# Note: We don't want to import portage modules directly because we do things
15916 -# like run the testsuite through multiple versions of python.
15917 -
15918 -"""Helper script to run portage unittests against different python versions.
15919 -
15920 -Note: Any additional arguments will be passed down directly to the underlying
15921 -unittest runner. This lets you select specific tests to execute.
15922 -"""
15923 -
15924 -import argparse
15925 -import os
15926 -import shutil
15927 -import subprocess
15928 -import sys
15929 -import tempfile
15930 -
15931 -
15932 -# These are the versions we fully support and require to pass tests.
15933 -PYTHON_SUPPORTED_VERSIONS = ["2.7", "3.6", "3.7", "3.8", "3.9"]
15934 -# The rest are just "nice to have".
15935 -PYTHON_NICE_VERSIONS = ["pypy3", "3.10"]
15936 -
15937 -EPREFIX = os.environ.get("PORTAGE_OVERRIDE_EPREFIX", "/")
15938 -
15939 -
15940 -class Colors(object):
15941 - """Simple object holding color constants."""
15942 -
15943 - _COLORS_YES = ("y", "yes", "true")
15944 - _COLORS_NO = ("n", "no", "false")
15945 -
15946 - WARN = GOOD = BAD = NORMAL = ""
15947 -
15948 - def __init__(self, colorize=None):
15949 - if colorize is None:
15950 - nocolors = os.environ.get("NOCOLOR", "false")
15951 - # Ugh, look away, for here we invert the world!
15952 - if nocolors in self._COLORS_YES:
15953 - colorize = False
15954 - elif nocolors in self._COLORS_NO:
15955 - colorize = True
15956 - else:
15957 - raise ValueError("$NOCOLORS is invalid: %s" % nocolors)
15958 - else:
15959 - if colorize in self._COLORS_YES:
15960 - colorize = True
15961 - elif colorize in self._COLORS_NO:
15962 - colorize = False
15963 - else:
15964 - raise ValueError("--colors is invalid: %s" % colorize)
15965 -
15966 - if colorize:
15967 - self.WARN = "\033[1;33m"
15968 - self.GOOD = "\033[1;32m"
15969 - self.BAD = "\033[1;31m"
15970 - self.NORMAL = "\033[0m"
15971 -
15972 -
15973 -def get_python_executable(ver):
15974 - """Find the right python executable for |ver|"""
15975 - if ver in ("pypy", "pypy3"):
15976 - prog = ver
15977 - else:
15978 - prog = "python" + ver
15979 - return os.path.join(EPREFIX, "usr", "bin", prog)
15980 -
15981 -
15982 -def get_parser():
15983 - """Return a argument parser for this module"""
15984 - epilog = """Examples:
15985 -List all the available unittests.
15986 -$ %(prog)s --list
15987 -
15988 -Run against specific versions of python.
15989 -$ %(prog)s --python-versions '2.7 3.3'
15990 -
15991 -Run just one unittest.
15992 -$ %(prog)s lib/portage/tests/xpak/test_decodeint.py
15993 -"""
15994 - parser = argparse.ArgumentParser(
15995 - description=__doc__,
15996 - formatter_class=argparse.RawDescriptionHelpFormatter,
15997 - epilog=epilog,
15998 - )
15999 - parser.add_argument(
16000 - "--keep-temp",
16001 - default=False,
16002 - action="store_true",
16003 - help="Do not delete the temporary directory when exiting",
16004 - )
16005 - parser.add_argument(
16006 - "--color",
16007 - type=str,
16008 - default=None,
16009 - help="Whether to use colorized output (default is auto)",
16010 - )
16011 - parser.add_argument(
16012 - "--python-versions",
16013 - action="append",
16014 - help="Versions of python to test (default is test available)",
16015 - )
16016 - return parser
16017 -
16018 -
16019 -def main(argv):
16020 - parser = get_parser()
16021 - opts, args = parser.parse_known_args(argv)
16022 - colors = Colors(colorize=opts.color)
16023 -
16024 - # Figure out all the versions we want to test.
16025 - if opts.python_versions is None:
16026 - ignore_missing = True
16027 - pyversions = PYTHON_SUPPORTED_VERSIONS + PYTHON_NICE_VERSIONS
16028 - else:
16029 - ignore_missing = False
16030 - pyversions = []
16031 - for ver in opts.python_versions:
16032 - if ver == "supported":
16033 - pyversions.extend(PYTHON_SUPPORTED_VERSIONS)
16034 - else:
16035 - pyversions.extend(ver.split())
16036 -
16037 - here = os.path.dirname(__file__)
16038 - run_path = os.path.join(here, "lib/repoman/tests/runTests.py")
16039 - tempdir = None
16040 - try:
16041 - # Set up a single tempdir for all the tests to use.
16042 - # This way we know the tests won't leak things on us.
16043 - tempdir = tempfile.mkdtemp(prefix="repoman.runtests.")
16044 - os.environ["TMPDIR"] = tempdir
16045 -
16046 - # Actually test those versions now.
16047 - statuses = []
16048 - for ver in pyversions:
16049 - prog = get_python_executable(ver)
16050 - cmd = [prog, "-b", "-Wd", run_path] + args
16051 - if os.access(prog, os.X_OK):
16052 - print(
16053 - "%sTesting with Python %s...%s" % (colors.GOOD, ver, colors.NORMAL)
16054 - )
16055 - statuses.append((ver, subprocess.call(cmd)))
16056 - elif not ignore_missing:
16057 - print(
16058 - "%sCould not find requested Python %s%s"
16059 - % (colors.BAD, ver, colors.NORMAL)
16060 - )
16061 - statuses.append((ver, 1))
16062 - else:
16063 - print("%sSkip Python %s...%s" % (colors.WARN, ver, colors.NORMAL))
16064 - print()
16065 - finally:
16066 - if tempdir is not None:
16067 - if opts.keep_temp:
16068 - print("Temporary directory left behind:\n%s" % tempdir)
16069 - else:
16070 - # Nuke our tempdir and anything that might be under it.
16071 - shutil.rmtree(tempdir, True)
16072 -
16073 - # Then summarize it all.
16074 - print("\nSummary:\n")
16075 - width = 10
16076 - header = "| %-*s | %s" % (width, "Version", "Status")
16077 - print("%s\n|%s" % (header, "-" * (len(header) - 1)))
16078 - exit_status = 0
16079 - for ver, status in statuses:
16080 - exit_status += status
16081 - if status:
16082 - color = colors.BAD
16083 - msg = "FAIL"
16084 - else:
16085 - color = colors.GOOD
16086 - msg = "PASS"
16087 - print(
16088 - "| %s%-*s%s | %s%s%s"
16089 - % (color, width, ver, colors.NORMAL, color, msg, colors.NORMAL)
16090 - )
16091 - exit(exit_status)
16092 -
16093 -
16094 -if __name__ == "__main__":
16095 - try:
16096 - main(sys.argv[1:])
16097 - except KeyboardInterrupt:
16098 - print("interrupted ...", file=sys.stderr)
16099 - exit(1)
16100
16101 diff --git a/repoman/setup.py b/repoman/setup.py
16102 deleted file mode 100755
16103 index 8231c8f75..000000000
16104 --- a/repoman/setup.py
16105 +++ /dev/null
16106 @@ -1,523 +0,0 @@
16107 -#!/usr/bin/env python
16108 -# Copyright 1998-2021 Gentoo Authors
16109 -# Distributed under the terms of the GNU General Public License v2
16110 -
16111 -try:
16112 - from setuptools.core import setup, Command
16113 - from setuptools.command.build import build
16114 - from setuptools.command.build_scripts import build_scripts
16115 - from setuptools.command.clean import clean
16116 - from setuptools.command.install import install
16117 - from setuptools.command.install_data import install_data
16118 - from setuptools.command.install_lib import install_lib
16119 - from setuptools.command.install_scripts import install_scripts
16120 - from setuptools.command.sdist import sdist
16121 - from setuptools.dep_util import newer
16122 - from setuptools.dir_util import mkpath, remove_tree, copy_tree
16123 - from setuptools.util import change_root, subst_vars
16124 -except ImportError:
16125 - from distutils.core import setup, Command
16126 - from distutils.command.build import build
16127 - from distutils.command.build_scripts import build_scripts
16128 - from distutils.command.clean import clean
16129 - from distutils.command.install import install
16130 - from distutils.command.install_data import install_data
16131 - from distutils.command.install_lib import install_lib
16132 - from distutils.command.install_scripts import install_scripts
16133 - from distutils.command.sdist import sdist
16134 - from distutils.dep_util import newer
16135 - from distutils.dir_util import mkpath, remove_tree, copy_tree
16136 - from distutils.util import change_root, subst_vars
16137 -
16138 -import codecs
16139 -import collections
16140 -import os
16141 -import os.path
16142 -import re
16143 -import subprocess
16144 -import sys
16145 -
16146 -# change the cwd to this one
16147 -os.chdir(os.path.dirname(os.path.realpath(__file__)))
16148 -
16149 -# TODO:
16150 -# - smarter rebuilds of docs w/ 'install_docbook' and 'install_epydoc'.
16151 -
16152 -x_scripts = {
16153 - "bin": [
16154 - "bin/repoman",
16155 - ],
16156 -}
16157 -
16158 -
16159 -class x_build(build):
16160 - """Build command with extra build_man call."""
16161 -
16162 - def run(self):
16163 - build.run(self)
16164 - self.run_command("build_man")
16165 -
16166 -
16167 -class build_man(Command):
16168 - """Perform substitutions in manpages."""
16169 -
16170 - user_options = []
16171 -
16172 - def initialize_options(self):
16173 - self.build_base = None
16174 -
16175 - def finalize_options(self):
16176 - self.set_undefined_options("build", ("build_base", "build_base"))
16177 -
16178 - def run(self):
16179 - for d, files in self.distribution.data_files:
16180 - if not d.startswith("$mandir/"):
16181 - continue
16182 -
16183 - for source in files:
16184 - target = os.path.join(self.build_base, source)
16185 - mkpath(os.path.dirname(target))
16186 -
16187 - if not newer(source, target) and not newer(__file__, target):
16188 - continue
16189 -
16190 - print("copying and updating %s -> %s" % (source, target))
16191 -
16192 - with codecs.open(source, "r", "utf8") as f:
16193 - data = f.readlines()
16194 - data[0] = data[0].replace("VERSION", self.distribution.get_version())
16195 - with codecs.open(target, "w", "utf8") as f:
16196 - f.writelines(data)
16197 -
16198 -
16199 -class x_build_scripts_custom(build_scripts):
16200 - def finalize_options(self):
16201 - build_scripts.finalize_options(self)
16202 - if "dir_name" in dir(self):
16203 - self.build_dir = os.path.join(self.build_dir, self.dir_name)
16204 - if self.dir_name in x_scripts:
16205 - self.scripts = x_scripts[self.dir_name]
16206 - else:
16207 - self.scripts = set(self.scripts)
16208 - for other_files in x_scripts.values():
16209 - self.scripts.difference_update(other_files)
16210 -
16211 - def run(self):
16212 - # group scripts by subdirectory
16213 - split_scripts = collections.defaultdict(list)
16214 - for f in self.scripts:
16215 - dir_name = os.path.dirname(f[len("bin/") :])
16216 - split_scripts[dir_name].append(f)
16217 -
16218 - base_dir = self.build_dir
16219 - base_scripts = self.scripts
16220 - for d, files in split_scripts.items():
16221 - self.build_dir = os.path.join(base_dir, d)
16222 - self.scripts = files
16223 - self.copy_scripts()
16224 -
16225 - # restore previous values
16226 - self.build_dir = base_dir
16227 - self.scripts = base_scripts
16228 -
16229 -
16230 -class x_build_scripts_bin(x_build_scripts_custom):
16231 - dir_name = "bin"
16232 -
16233 -
16234 -class x_build_scripts(build_scripts):
16235 - def initialize_option(self):
16236 - build_scripts.initialize_options(self)
16237 -
16238 - def finalize_options(self):
16239 - build_scripts.finalize_options(self)
16240 -
16241 - def run(self):
16242 - self.run_command("build_scripts_bin")
16243 -
16244 -
16245 -class x_clean(clean):
16246 - """clean extended for doc & post-test cleaning"""
16247 -
16248 - def clean_tests(self):
16249 - # do not remove incorrect dirs accidentally
16250 - top_dir = os.path.normpath(os.path.join(self.build_lib, ".."))
16251 - cprefix = os.path.commonprefix((self.build_base, top_dir))
16252 - if cprefix != self.build_base:
16253 - return
16254 -
16255 - bin_dir = os.path.join(top_dir, "bin")
16256 - if os.path.exists(bin_dir):
16257 - remove_tree(bin_dir)
16258 -
16259 - conf_dir = os.path.join(top_dir, "cnf")
16260 - if os.path.islink(conf_dir):
16261 - print("removing %s symlink" % repr(conf_dir))
16262 - os.unlink(conf_dir)
16263 -
16264 - pni_file = os.path.join(top_dir, ".repoman_not_installed")
16265 - if os.path.exists(pni_file):
16266 - print("removing %s" % repr(pni_file))
16267 - os.unlink(pni_file)
16268 -
16269 - def clean_man(self):
16270 - man_dir = os.path.join(self.build_base, "man")
16271 - if os.path.exists(man_dir):
16272 - remove_tree(man_dir)
16273 -
16274 - def run(self):
16275 - if self.all:
16276 - self.clean_tests()
16277 - self.clean_docs()
16278 - self.clean_man()
16279 -
16280 - clean.run(self)
16281 -
16282 -
16283 -class x_install(install):
16284 - """install command with extra Portage paths"""
16285 -
16286 - user_options = install.user_options + [
16287 - # note: $prefix and $exec_prefix are reserved for Python install
16288 - ("system-prefix=", None, "Prefix for architecture-independent data"),
16289 - ("system-exec-prefix=", None, "Prefix for architecture-specific data"),
16290 - ("bindir=", None, "Install directory for main executables"),
16291 - ("datarootdir=", None, "Data install root directory"),
16292 - ("docdir=", None, "Documentation install directory"),
16293 - ("htmldir=", None, "HTML documentation install directory"),
16294 - ("mandir=", None, "Manpage root install directory"),
16295 - ("portage-base=", "b", "Portage install base"),
16296 - (
16297 - "portage-bindir=",
16298 - None,
16299 - "Install directory for Portage internal-use executables",
16300 - ),
16301 - ("portage-datadir=", None, "Install directory for data files"),
16302 - ("sbindir=", None, "Install directory for superuser-intended executables"),
16303 - ("sysconfdir=", None, "System configuration path"),
16304 - ]
16305 -
16306 - # note: the order is important for proper substitution
16307 - paths = [
16308 - ("system_prefix", "/usr"),
16309 - ("system_exec_prefix", "$system_prefix"),
16310 - ("bindir", "$system_exec_prefix/bin"),
16311 - ("sbindir", "$system_exec_prefix/sbin"),
16312 - ("sysconfdir", "/etc"),
16313 - ("datarootdir", "$system_prefix/share"),
16314 - ("docdir", "$datarootdir/doc/$package-$version"),
16315 - ("htmldir", "$docdir/html"),
16316 - ("mandir", "$datarootdir/man"),
16317 - ("portage_base", "$system_exec_prefix/lib/portage"),
16318 - ("portage_bindir", "$portage_base/bin"),
16319 - ("portage_datadir", "$datarootdir/portage"),
16320 - # not customized at the moment
16321 - ("logrotatedir", "$sysconfdir/logrotate.d"),
16322 - ("portage_confdir", "$portage_datadir/config"),
16323 - ("portage_setsdir", "$portage_confdir/sets"),
16324 - ]
16325 -
16326 - def initialize_options(self):
16327 - install.initialize_options(self)
16328 -
16329 - for key, default in self.paths:
16330 - setattr(self, key, default)
16331 - self.subst_paths = {}
16332 -
16333 - def finalize_options(self):
16334 - install.finalize_options(self)
16335 -
16336 - # substitute variables
16337 - new_paths = {
16338 - "package": self.distribution.get_name(),
16339 - "version": self.distribution.get_version(),
16340 - }
16341 - for key, _default in self.paths:
16342 - new_paths[key] = subst_vars(getattr(self, key), new_paths)
16343 - setattr(self, key, new_paths[key])
16344 - self.subst_paths = new_paths
16345 -
16346 -
16347 -class x_install_data(install_data):
16348 - """install_data with customized path support"""
16349 -
16350 - user_options = install_data.user_options
16351 -
16352 - def initialize_options(self):
16353 - install_data.initialize_options(self)
16354 - self.build_base = None
16355 - self.paths = None
16356 -
16357 - def finalize_options(self):
16358 - install_data.finalize_options(self)
16359 - self.set_undefined_options("build", ("build_base", "build_base"))
16360 - self.set_undefined_options("install", ("subst_paths", "paths"))
16361 -
16362 - def run(self):
16363 - self.run_command("build_man")
16364 -
16365 - def process_data_files(df):
16366 - for d, files in df:
16367 - # substitute man sources
16368 - if d.startswith("$mandir/"):
16369 - files = [os.path.join(self.build_base, v) for v in files]
16370 -
16371 - # substitute variables in path
16372 - d = subst_vars(d, self.paths)
16373 - yield (d, files)
16374 -
16375 - old_data_files = self.data_files
16376 - self.data_files = process_data_files(self.data_files)
16377 -
16378 - install_data.run(self)
16379 - self.data_files = old_data_files
16380 -
16381 -
16382 -class x_install_lib(install_lib):
16383 - """install_lib command with Portage path substitution"""
16384 -
16385 - user_options = install_lib.user_options
16386 -
16387 - def initialize_options(self):
16388 - install_lib.initialize_options(self)
16389 -
16390 - def finalize_options(self):
16391 - install_lib.finalize_options(self)
16392 - self.set_undefined_options(
16393 - "install",
16394 - )
16395 -
16396 - def install(self):
16397 - ret = install_lib.install(self)
16398 -
16399 - def rewrite_file(path, val_dict):
16400 - path = os.path.join(self.install_dir, path)
16401 - print("Rewriting %s" % path)
16402 - with codecs.open(path, "r", "utf-8") as f:
16403 - data = f.read()
16404 -
16405 - for varname, val in val_dict.items():
16406 - regexp = r"(?m)^(%s\s*=).*$" % varname
16407 - repl = r"\1 %s" % repr(val)
16408 -
16409 - data = re.sub(regexp, repl, data)
16410 -
16411 - with codecs.open(path, "w", "utf-8") as f:
16412 - f.write(data)
16413 -
16414 - rewrite_file(
16415 - "repoman/__init__.py",
16416 - {
16417 - "VERSION": self.distribution.get_version(),
16418 - },
16419 - )
16420 -
16421 - return ret
16422 -
16423 -
16424 -class x_install_scripts_custom(install_scripts):
16425 - def initialize_options(self):
16426 - install_scripts.initialize_options(self)
16427 - self.root = None
16428 -
16429 - def finalize_options(self):
16430 - self.set_undefined_options(
16431 - "install", ("root", "root"), (self.var_name, "install_dir")
16432 - )
16433 - install_scripts.finalize_options(self)
16434 - self.build_dir = os.path.join(self.build_dir, self.dir_name)
16435 -
16436 - # prepend root
16437 - if self.root is not None:
16438 - self.install_dir = change_root(self.root, self.install_dir)
16439 -
16440 -
16441 -class x_install_scripts_bin(x_install_scripts_custom):
16442 - dir_name = "bin"
16443 - var_name = "bindir"
16444 -
16445 -
16446 -class x_install_scripts(install_scripts):
16447 - def initialize_option(self):
16448 - pass
16449 -
16450 - def finalize_options(self):
16451 - pass
16452 -
16453 - def run(self):
16454 - self.run_command("install_scripts_bin")
16455 -
16456 -
16457 -class x_sdist(sdist):
16458 - """sdist defaulting to .tar.xz format, and archive files owned by root"""
16459 -
16460 - def initialize_options(self):
16461 - super().initialize_options()
16462 - self.formats = ["xztar"]
16463 -
16464 - def finalize_options(self):
16465 - if self.owner is None:
16466 - self.owner = "root"
16467 - if self.group is None:
16468 - self.group = "root"
16469 -
16470 - sdist.finalize_options(self)
16471 -
16472 -
16473 -class build_tests(x_build_scripts_custom):
16474 - """Prepare build dir for running tests."""
16475 -
16476 - def initialize_options(self):
16477 - x_build_scripts_custom.initialize_options(self)
16478 - self.build_base = None
16479 - self.build_lib = None
16480 -
16481 - def finalize_options(self):
16482 - x_build_scripts_custom.finalize_options(self)
16483 - self.set_undefined_options(
16484 - "build", ("build_base", "build_base"), ("build_lib", "build_lib")
16485 - )
16486 -
16487 - # since we will be writing to $build_lib/.., it is important
16488 - # that we do not leave $build_base
16489 - self.top_dir = os.path.normpath(os.path.join(self.build_lib, ".."))
16490 - cprefix = os.path.commonprefix((self.build_base, self.top_dir))
16491 - if cprefix != self.build_base:
16492 - raise SystemError("build_lib must be a subdirectory of build_base")
16493 -
16494 - self.build_dir = os.path.join(self.top_dir, "bin")
16495 -
16496 - def run(self):
16497 - self.run_command("build_py")
16498 -
16499 - # install all scripts $build_lib/../bin
16500 - # (we can't do a symlink since we want shebangs corrected)
16501 - x_build_scripts_custom.run(self)
16502 -
16503 - # symlink 'cnf' directory
16504 - conf_dir = os.path.join(self.top_dir, "cnf")
16505 - if os.path.exists(conf_dir):
16506 - if not os.path.islink(conf_dir):
16507 - raise SystemError(
16508 - "%s exists and is not a symlink (collision)" % repr(conf_dir)
16509 - )
16510 - os.unlink(conf_dir)
16511 - conf_src = os.path.relpath("cnf", self.top_dir)
16512 - print("Symlinking %s -> %s" % (conf_dir, conf_src))
16513 - os.symlink(conf_src, conf_dir)
16514 -
16515 - # create $build_lib/../.repoman_not_installed
16516 - # to enable proper paths in tests
16517 - with open(os.path.join(self.top_dir, ".repoman_not_installed"), "w"):
16518 - pass
16519 -
16520 -
16521 -class test(Command):
16522 - """run tests"""
16523 -
16524 - user_options = []
16525 -
16526 - def initialize_options(self):
16527 - self.build_lib = None
16528 -
16529 - def finalize_options(self):
16530 - self.set_undefined_options("build", ("build_lib", "build_lib"))
16531 -
16532 - def run(self):
16533 - self.run_command("build_tests")
16534 - # copy GPG test keys
16535 - copy_tree(
16536 - os.path.join(
16537 - self.build_lib, "..", "..", "lib", "repoman", "tests", ".gnupg"
16538 - ),
16539 - os.path.join(self.build_lib, "repoman", "tests", ".gnupg"),
16540 - )
16541 - os.chmod(os.path.join(self.build_lib, "repoman", "tests", ".gnupg"), 0o700)
16542 - subprocess.check_call(
16543 - [
16544 - sys.executable,
16545 - "-bWd",
16546 - os.path.join(self.build_lib, "repoman/tests/runTests.py"),
16547 - ]
16548 - )
16549 -
16550 -
16551 -def find_packages():
16552 - for dirpath, _dirnames, filenames in os.walk("lib"):
16553 - if "__init__.py" in filenames:
16554 - yield os.path.relpath(dirpath, "lib")
16555 -
16556 -
16557 -def find_scripts():
16558 - for dirpath, _dirnames, filenames in os.walk("bin"):
16559 - for f in filenames:
16560 - if f not in ["deprecated-path"]:
16561 - yield os.path.join(dirpath, f)
16562 -
16563 -
16564 -def get_manpages():
16565 - linguas = os.environ.get("LINGUAS")
16566 - if linguas is not None:
16567 - linguas = linguas.split()
16568 -
16569 - for dirpath, _dirnames, filenames in os.walk("man"):
16570 - groups = collections.defaultdict(list)
16571 - for f in filenames:
16572 - _fn, suffix = f.rsplit(".", 1)
16573 - groups[suffix].append(os.path.join(dirpath, f))
16574 -
16575 - topdir = dirpath[len("man/") :]
16576 - if not topdir or linguas is None or topdir in linguas:
16577 - for g, mans in groups.items():
16578 - yield [os.path.join("$mandir", topdir, "man%s" % g), mans]
16579 -
16580 -
16581 -setup(
16582 - name="repoman",
16583 - version="3.0.3",
16584 - url="https://wiki.gentoo.org/wiki/Project:Portage",
16585 - author="Gentoo Portage Development Team",
16586 - author_email="dev-portage@g.o",
16587 - package_dir={"": "lib"},
16588 - packages=list(find_packages()),
16589 - # something to cheat build & install commands
16590 - scripts=list(find_scripts()),
16591 - data_files=list(get_manpages())
16592 - + [
16593 - ["$docdir", ["NEWS", "RELEASE-NOTES"]],
16594 - ["share/repoman/qa_data", ["cnf/qa_data/qa_data.yaml"]],
16595 - ["share/repoman/linechecks", ["cnf/linechecks/linechecks.yaml"]],
16596 - [
16597 - "share/repoman/repository",
16598 - [
16599 - "cnf/repository/linechecks.yaml",
16600 - "cnf/repository/qa_data.yaml",
16601 - "cnf/repository/repository.yaml",
16602 - ],
16603 - ],
16604 - ],
16605 - cmdclass={
16606 - "build": x_build,
16607 - "build_man": build_man,
16608 - "build_scripts": x_build_scripts,
16609 - "build_scripts_bin": x_build_scripts_bin,
16610 - "build_tests": build_tests,
16611 - "clean": x_clean,
16612 - "install": x_install,
16613 - "install_data": x_install_data,
16614 - "install_lib": x_install_lib,
16615 - "install_scripts": x_install_scripts,
16616 - "install_scripts_bin": x_install_scripts_bin,
16617 - "sdist": x_sdist,
16618 - "test": test,
16619 - },
16620 - classifiers=[
16621 - "Development Status :: 5 - Production/Stable",
16622 - "Environment :: Console",
16623 - "Intended Audience :: System Administrators",
16624 - "License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
16625 - "Operating System :: POSIX",
16626 - "Programming Language :: Python :: 3",
16627 - "Topic :: System :: Installation/Setup",
16628 - ],
16629 -)
16630
16631 diff --git a/tox.ini b/tox.ini
16632 index 2281dfa24..84c24396e 100644
16633 --- a/tox.ini
16634 +++ b/tox.ini
16635 @@ -20,6 +20,5 @@ deps =
16636 setenv =
16637 PYTHONPATH={toxinidir}/lib
16638 commands =
16639 - pylint: bash -c 'rm -rf build && PYTHONPATH=$PWD/lib:$PWD/repoman/lib pylint bin/* lib/* repoman/bin/* repoman/lib/*'
16640 + pylint: bash -c 'rm -rf build && PYTHONPATH=$PWD/lib pylint bin/* lib/*'
16641 python -b -Wd setup.py test
16642 - bash -c 'if python -c "import lxml.etree"; then python -b -Wd repoman/setup.py test; else echo "repoman tests skipped due to lxml breakage"; fi'