aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Turner <mattst88@gentoo.org>2022-02-21 12:59:34 -0800
committerMatt Turner <mattst88@gentoo.org>2022-05-02 11:44:51 -0700
commit3ec97d8f0cd427b7b9874b05f55d1aec5a1df8b0 (patch)
treed6dc767b96cb791dbff24df54cc4ab126f19e225
parentebegin/eend: accept properly nested calls in different functions (diff)
downloadgentoo-portage-3ec97d8f0cd427b7b9874b05f55d1aec5a1df8b0.tar.xz
gentoo-portage-3ec97d8f0cd427b7b9874b05f55d1aec5a1df8b0.zip
repoman: Remove
RepoMan sez: So long and thanks for all the fish! I'll be enjoying my retirement now. Haven't I done enough to deserve that? Bug: https://bugs.gentoo.org/835013 Signed-off-by: Matt Turner <mattst88@gentoo.org>
-rw-r--r--.github/workflows/black.yml2
-rw-r--r--.gitignore2
-rw-r--r--cnf/make.globals2
-rw-r--r--lib/_emerge/Package.py5
-rw-r--r--lib/_emerge/depgraph.py2
-rw-r--r--lib/portage/dbapi/__init__.py12
-rw-r--r--lib/portage/dbapi/porttree.py6
-rw-r--r--lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py2
-rw-r--r--lib/portage/tests/resolver/ResolverPlayground.py10
-rw-r--r--man/ebuild.56
-rw-r--r--man/make.conf.58
-rw-r--r--man/portage.542
-rw-r--r--repoman/.repoman_not_installed0
-rw-r--r--repoman/MANIFEST.in4
-rw-r--r--repoman/NEWS14
-rw-r--r--repoman/README49
-rw-r--r--repoman/RELEASE-NOTES213
-rw-r--r--repoman/TEST-NOTES45
-rwxr-xr-xrepoman/bin/repoman56
-rw-r--r--repoman/cnf/linechecks/linechecks.yaml34
-rw-r--r--repoman/cnf/metadata.xsd548
-rw-r--r--repoman/cnf/qa_data/qa_data.yaml139
-rw-r--r--repoman/cnf/repository/linechecks.yaml248
-rw-r--r--repoman/cnf/repository/qa_data.yaml163
-rw-r--r--repoman/cnf/repository/repository.yaml76
-rw-r--r--repoman/lib/repoman/__init__.py103
-rw-r--r--repoman/lib/repoman/_portage.py26
-rw-r--r--repoman/lib/repoman/_subprocess.py58
-rw-r--r--repoman/lib/repoman/actions.py828
-rw-r--r--repoman/lib/repoman/argparser.py388
-rw-r--r--repoman/lib/repoman/check_missingslot.py39
-rw-r--r--repoman/lib/repoman/checks/__init__.py0
-rw-r--r--repoman/lib/repoman/config.py172
-rw-r--r--repoman/lib/repoman/copyrights.py143
-rw-r--r--repoman/lib/repoman/errors.py21
-rw-r--r--repoman/lib/repoman/gpg.py73
-rwxr-xr-xrepoman/lib/repoman/main.py255
-rw-r--r--repoman/lib/repoman/metadata.py89
-rw-r--r--repoman/lib/repoman/modules/__init__.py0
-rw-r--r--repoman/lib/repoman/modules/commit/__init__.py0
-rw-r--r--repoman/lib/repoman/modules/commit/manifest.py122
-rw-r--r--repoman/lib/repoman/modules/commit/repochecks.py44
-rw-r--r--repoman/lib/repoman/modules/linechecks/__init__.py0
-rw-r--r--repoman/lib/repoman/modules/linechecks/assignment/__init__.py27
-rw-r--r--repoman/lib/repoman/modules/linechecks/assignment/assignment.py38
-rw-r--r--repoman/lib/repoman/modules/linechecks/base.py115
-rw-r--r--repoman/lib/repoman/modules/linechecks/config.py149
-rw-r--r--repoman/lib/repoman/modules/linechecks/controller.py164
-rw-r--r--repoman/lib/repoman/modules/linechecks/depend/__init__.py21
-rw-r--r--repoman/lib/repoman/modules/linechecks/depend/implicit.py38
-rw-r--r--repoman/lib/repoman/modules/linechecks/deprecated/__init__.py46
-rw-r--r--repoman/lib/repoman/modules/linechecks/deprecated/deprecated.py35
-rw-r--r--repoman/lib/repoman/modules/linechecks/deprecated/inherit.py67
-rw-r--r--repoman/lib/repoman/modules/linechecks/do/__init__.py21
-rw-r--r--repoman/lib/repoman/modules/linechecks/do/dosym.py20
-rw-r--r--repoman/lib/repoman/modules/linechecks/eapi/__init__.py51
-rw-r--r--repoman/lib/repoman/modules/linechecks/eapi/checks.py79
-rw-r--r--repoman/lib/repoman/modules/linechecks/eapi/definition.py35
-rw-r--r--repoman/lib/repoman/modules/linechecks/emake/__init__.py27
-rw-r--r--repoman/lib/repoman/modules/linechecks/emake/emake.py25
-rw-r--r--repoman/lib/repoman/modules/linechecks/gentoo_header/__init__.py21
-rw-r--r--repoman/lib/repoman/modules/linechecks/gentoo_header/header.py56
-rw-r--r--repoman/lib/repoman/modules/linechecks/helpers/__init__.py21
-rw-r--r--repoman/lib/repoman/modules/linechecks/helpers/offset.py21
-rw-r--r--repoman/lib/repoman/modules/linechecks/nested/__init__.py21
-rw-r--r--repoman/lib/repoman/modules/linechecks/nested/nested.py14
-rw-r--r--repoman/lib/repoman/modules/linechecks/nested/nesteddie.py9
-rw-r--r--repoman/lib/repoman/modules/linechecks/patches/__init__.py21
-rw-r--r--repoman/lib/repoman/modules/linechecks/patches/patches.py22
-rw-r--r--repoman/lib/repoman/modules/linechecks/phases/__init__.py40
-rw-r--r--repoman/lib/repoman/modules/linechecks/phases/phase.py188
-rw-r--r--repoman/lib/repoman/modules/linechecks/portage/__init__.py27
-rw-r--r--repoman/lib/repoman/modules/linechecks/portage/internal.py32
-rw-r--r--repoman/lib/repoman/modules/linechecks/quotes/__init__.py27
-rw-r--r--repoman/lib/repoman/modules/linechecks/quotes/quoteda.py15
-rw-r--r--repoman/lib/repoman/modules/linechecks/quotes/quotes.py92
-rw-r--r--repoman/lib/repoman/modules/linechecks/uri/__init__.py21
-rw-r--r--repoman/lib/repoman/modules/linechecks/uri/uri.py30
-rw-r--r--repoman/lib/repoman/modules/linechecks/use/__init__.py21
-rw-r--r--repoman/lib/repoman/modules/linechecks/use/builtwith.py9
-rw-r--r--repoman/lib/repoman/modules/linechecks/useless/__init__.py27
-rw-r--r--repoman/lib/repoman/modules/linechecks/useless/cd.py24
-rw-r--r--repoman/lib/repoman/modules/linechecks/useless/dodoc.py17
-rw-r--r--repoman/lib/repoman/modules/linechecks/whitespace/__init__.py27
-rw-r--r--repoman/lib/repoman/modules/linechecks/whitespace/blank.py24
-rw-r--r--repoman/lib/repoman/modules/linechecks/whitespace/whitespace.py20
-rw-r--r--repoman/lib/repoman/modules/linechecks/workaround/__init__.py21
-rw-r--r--repoman/lib/repoman/modules/linechecks/workaround/workarounds.py11
-rw-r--r--repoman/lib/repoman/modules/scan/__init__.py0
-rw-r--r--repoman/lib/repoman/modules/scan/depend/__init__.py43
-rw-r--r--repoman/lib/repoman/modules/scan/depend/_depend_checks.py260
-rw-r--r--repoman/lib/repoman/modules/scan/depend/_gen_arches.py67
-rw-r--r--repoman/lib/repoman/modules/scan/depend/profile.py427
-rw-r--r--repoman/lib/repoman/modules/scan/directories/__init__.py53
-rw-r--r--repoman/lib/repoman/modules/scan/directories/files.py99
-rw-r--r--repoman/lib/repoman/modules/scan/directories/mtime.py30
-rw-r--r--repoman/lib/repoman/modules/scan/eapi/__init__.py28
-rw-r--r--repoman/lib/repoman/modules/scan/eapi/eapi.py50
-rw-r--r--repoman/lib/repoman/modules/scan/ebuild/__init__.py66
-rw-r--r--repoman/lib/repoman/modules/scan/ebuild/ebuild.py263
-rw-r--r--repoman/lib/repoman/modules/scan/ebuild/multicheck.py62
-rw-r--r--repoman/lib/repoman/modules/scan/eclasses/__init__.py49
-rw-r--r--repoman/lib/repoman/modules/scan/eclasses/live.py77
-rw-r--r--repoman/lib/repoman/modules/scan/eclasses/ruby.py49
-rw-r--r--repoman/lib/repoman/modules/scan/fetch/__init__.py37
-rw-r--r--repoman/lib/repoman/modules/scan/fetch/fetches.py205
-rw-r--r--repoman/lib/repoman/modules/scan/keywords/__init__.py37
-rw-r--r--repoman/lib/repoman/modules/scan/keywords/keywords.py179
-rw-r--r--repoman/lib/repoman/modules/scan/manifest/__init__.py34
-rw-r--r--repoman/lib/repoman/modules/scan/manifest/manifests.py56
-rw-r--r--repoman/lib/repoman/modules/scan/metadata/__init__.py89
-rw-r--r--repoman/lib/repoman/modules/scan/metadata/description.py44
-rw-r--r--repoman/lib/repoman/modules/scan/metadata/ebuild_metadata.py84
-rw-r--r--repoman/lib/repoman/modules/scan/metadata/pkgmetadata.py221
-rw-r--r--repoman/lib/repoman/modules/scan/metadata/restrict.py58
-rw-r--r--repoman/lib/repoman/modules/scan/metadata/use_flags.py103
-rw-r--r--repoman/lib/repoman/modules/scan/module.py127
-rw-r--r--repoman/lib/repoman/modules/scan/options/__init__.py28
-rw-r--r--repoman/lib/repoman/modules/scan/options/options.py27
-rw-r--r--repoman/lib/repoman/modules/scan/scan.py67
-rw-r--r--repoman/lib/repoman/modules/scan/scanbase.py79
-rw-r--r--repoman/lib/repoman/modules/vcs/None/__init__.py32
-rw-r--r--repoman/lib/repoman/modules/vcs/None/changes.py50
-rw-r--r--repoman/lib/repoman/modules/vcs/None/status.py52
-rw-r--r--repoman/lib/repoman/modules/vcs/__init__.py12
-rw-r--r--repoman/lib/repoman/modules/vcs/bzr/__init__.py32
-rw-r--r--repoman/lib/repoman/modules/vcs/bzr/changes.py77
-rw-r--r--repoman/lib/repoman/modules/vcs/bzr/status.py72
-rw-r--r--repoman/lib/repoman/modules/vcs/changes.py170
-rw-r--r--repoman/lib/repoman/modules/vcs/cvs/__init__.py32
-rw-r--r--repoman/lib/repoman/modules/vcs/cvs/changes.py134
-rw-r--r--repoman/lib/repoman/modules/vcs/cvs/status.py134
-rw-r--r--repoman/lib/repoman/modules/vcs/git/__init__.py32
-rw-r--r--repoman/lib/repoman/modules/vcs/git/changes.py145
-rw-r--r--repoman/lib/repoman/modules/vcs/git/status.py80
-rw-r--r--repoman/lib/repoman/modules/vcs/hg/__init__.py32
-rw-r--r--repoman/lib/repoman/modules/vcs/hg/changes.py109
-rw-r--r--repoman/lib/repoman/modules/vcs/hg/status.py68
-rw-r--r--repoman/lib/repoman/modules/vcs/settings.py113
-rw-r--r--repoman/lib/repoman/modules/vcs/svn/__init__.py32
-rw-r--r--repoman/lib/repoman/modules/vcs/svn/changes.py156
-rw-r--r--repoman/lib/repoman/modules/vcs/svn/status.py151
-rw-r--r--repoman/lib/repoman/modules/vcs/vcs.py145
-rw-r--r--repoman/lib/repoman/profile.py94
-rw-r--r--repoman/lib/repoman/qa_data.py210
-rw-r--r--repoman/lib/repoman/qa_tracker.py46
-rw-r--r--repoman/lib/repoman/repos.py377
-rw-r--r--repoman/lib/repoman/scanner.py484
-rw-r--r--repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/06B3A311BD775C280D22A9305D90EA06352177F6.rev37
-rw-r--r--repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/8DEDA2CDED49C8809287B89D8812797DDF1DD192.rev37
-rw-r--r--repoman/lib/repoman/tests/.gnupg/private-keys-v1.d/273B030399E7BEA66A9AD42216DE7CA17BA5D42E.keybin2055 -> 0 bytes
-rw-r--r--repoman/lib/repoman/tests/.gnupg/private-keys-v1.d/C99796FB85B0C3DF03314A11B5850C51167D6282.keybin2055 -> 0 bytes
-rw-r--r--repoman/lib/repoman/tests/.gnupg/pubring.kbxbin2774 -> 0 bytes
-rw-r--r--repoman/lib/repoman/tests/.gnupg/trustdb.gpgbin1360 -> 0 bytes
-rw-r--r--repoman/lib/repoman/tests/__init__.py328
-rw-r--r--repoman/lib/repoman/tests/__test__.py0
-rw-r--r--repoman/lib/repoman/tests/changelog/__init__.py2
-rw-r--r--repoman/lib/repoman/tests/changelog/__test__.py0
-rw-r--r--repoman/lib/repoman/tests/changelog/test_echangelog.py169
-rw-r--r--repoman/lib/repoman/tests/commit/__init__.py2
-rw-r--r--repoman/lib/repoman/tests/commit/__test__.py0
-rw-r--r--repoman/lib/repoman/tests/commit/test_commitmsg.py155
-rw-r--r--repoman/lib/repoman/tests/runTests.py85
-rw-r--r--repoman/lib/repoman/tests/simple/__init__.py2
-rw-r--r--repoman/lib/repoman/tests/simple/__test__.py0
-rw-r--r--repoman/lib/repoman/tests/simple/test_simple.py512
-rw-r--r--repoman/lib/repoman/utilities.py590
-rw-r--r--repoman/man/repoman.1478
-rwxr-xr-xrepoman/runtests189
-rwxr-xr-xrepoman/setup.py523
-rw-r--r--tox.ini3
171 files changed, 32 insertions, 15135 deletions
diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml
index d3c3fa3e1e1..1d6f1378c14 100644
--- a/.github/workflows/black.yml
+++ b/.github/workflows/black.yml
@@ -11,7 +11,7 @@ jobs:
id: stragglers
run: |
echo "::set-output name=missed::$(
- find bin repoman runtests -type f -not -name '*.py' -not -name '*.sh' | \
+ find bin runtests -type f -not -name '*.py' -not -name '*.sh' | \
xargs grep -l '#!/usr/bin/env python' | tr $'\n' ' ')"
- uses: psf/black@stable
with:
diff --git a/.gitignore b/.gitignore
index a9f772c4c89..c04a22a0b2b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,5 +6,3 @@ __pycache__/
/tags
/.tox/
setup.cfg
-
-repoman/build
diff --git a/cnf/make.globals b/cnf/make.globals
index f42cffe8ba4..f951bb31724 100644
--- a/cnf/make.globals
+++ b/cnf/make.globals
@@ -147,7 +147,7 @@ PORTAGE_ELOG_MAILURI="root"
PORTAGE_ELOG_MAILSUBJECT="[portage] ebuild log for \${PACKAGE} on \${HOST}"
PORTAGE_ELOG_MAILFROM="portage@localhost"
-# Signing command used by repoman
+# Signing command used by egencache
PORTAGE_GPG_SIGNING_COMMAND="gpg --sign --digest-algo SHA256 --clearsign --yes --default-key \"\${PORTAGE_GPG_KEY}\" --homedir \"\${PORTAGE_GPG_DIR}\" \"\${FILE}\""
# btrfs.* attributes are irrelevant, see bug #527636.
diff --git a/lib/_emerge/Package.py b/lib/_emerge/Package.py
index db42d836e1f..a1990411318 100644
--- a/lib/_emerge/Package.py
+++ b/lib/_emerge/Package.py
@@ -136,10 +136,7 @@ class Package(Task):
# sync metadata with validated repo (may be UNKNOWN_REPO)
self._metadata["repository"] = self.cpv.repo
- if self.root_config.settings.local_config:
- implicit_match = db._iuse_implicit_cnstr(self.cpv, self._metadata)
- else:
- implicit_match = db._repoman_iuse_implicit_cnstr(self.cpv, self._metadata)
+ implicit_match = db._iuse_implicit_cnstr(self.cpv, self._metadata)
self.iuse = self._iuse(
self, self._metadata["IUSE"].split(), implicit_match, self.eapi
)
diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index c3f872c4394..79fa1f3df61 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -9048,7 +9048,7 @@ class depgraph:
):
# Make sure that portage always has all of its
# RDEPENDs installed first, but ignore uninstalls
- # (these occur when new portage blocks older repoman).
+ # (these occur when new portage blocks an older package version).
return False
selected_nodes.add(node)
for child in mygraph.child_nodes(node, ignore_priority=ignore_priority):
diff --git a/lib/portage/dbapi/__init__.py b/lib/portage/dbapi/__init__.py
index 43c3283e80d..f52329c90e1 100644
--- a/lib/portage/dbapi/__init__.py
+++ b/lib/portage/dbapi/__init__.py
@@ -219,18 +219,6 @@ class dbapi:
yield cpv
- def _repoman_iuse_implicit_cnstr(self, pkg, metadata):
- """
- In repoman's version of _iuse_implicit_cnstr, account for modifications
- of the self.settings reference between calls.
- """
- eapi_attrs = _get_eapi_attrs(metadata["EAPI"])
- if eapi_attrs.iuse_effective:
- iuse_implicit_match = lambda flag: self.settings._iuse_effective_match(flag)
- else:
- iuse_implicit_match = lambda flag: self.settings._iuse_implicit_match(flag)
- return iuse_implicit_match
-
def _iuse_implicit_cnstr(self, pkg, metadata):
"""
Construct a callable that checks if a given USE flag should
diff --git a/lib/portage/dbapi/porttree.py b/lib/portage/dbapi/porttree.py
index 93f3fee2fb2..cd919ba3134 100644
--- a/lib/portage/dbapi/porttree.py
+++ b/lib/portage/dbapi/porttree.py
@@ -359,9 +359,9 @@ class portdbapi(dbapi):
def _set_porttrees(self, porttrees):
"""
- Consumers, such as repoman and emirrordist, may modify the porttrees
- attribute in order to modify the effective set of repositories for
- all portdbapi operations.
+ Consumers, such as emirrordist, may modify the porttrees attribute in
+ order to modify the effective set of repositories for all portdbapi
+ operations.
@param porttrees: list of repo locations, in ascending order by
repo priority
diff --git a/lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py b/lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py
index cf239240cea..8cc248db915 100644
--- a/lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py
+++ b/lib/portage/tests/lazyimport/test_lazy_import_portage_baseline.py
@@ -14,7 +14,7 @@ from _emerge.SpawnProcess import SpawnProcess
class LazyImportPortageBaselineTestCase(TestCase):
- _module_re = re.compile(r"^(portage|repoman|_emerge)\.")
+ _module_re = re.compile(r"^(portage|_emerge)\.")
_baseline_imports = frozenset(
[
diff --git a/lib/portage/tests/resolver/ResolverPlayground.py b/lib/portage/tests/resolver/ResolverPlayground.py
index 8811354b5bb..ec69ee06895 100644
--- a/lib/portage/tests/resolver/ResolverPlayground.py
+++ b/lib/portage/tests/resolver/ResolverPlayground.py
@@ -35,11 +35,6 @@ from _emerge.DependencyArg import DependencyArg
from _emerge.depgraph import backtrack_depgraph
from _emerge.RootConfig import RootConfig
-try:
- from repoman.tests import cnf_path_repoman
-except ImportError:
- cnf_path_repoman = None
-
class ResolverPlayground:
"""
@@ -664,11 +659,6 @@ class ResolverPlayground:
for line in lines:
f.write("%s\n" % line)
- if cnf_path_repoman is not None:
- # Create /usr/share/repoman
- repoman_share_dir = os.path.join(self.eroot, "usr", "share", "repoman")
- os.symlink(cnf_path_repoman, repoman_share_dir)
-
def _create_world(self, world, world_sets):
# Create /var/lib/portage/world
var_lib_portage = os.path.join(self.eroot, "var", "lib", "portage")
diff --git a/man/ebuild.5 b/man/ebuild.5
index 3a3982738cb..8402d667bd0 100644
--- a/man/ebuild.5
+++ b/man/ebuild.5
@@ -554,9 +554,9 @@ EAPI value then it will mask the package and refuse to perform any
operations with it since this means that a newer version of portage
needs to be installed first. For maximum backward compatiblity, a
package should conform to the lowest possible EAPI. Note that anyone
-who uses the \fBebuild\fR(1) and \fBrepoman\fR(1) commands with this
-package will be required to have a version of portage that recognizes
-the EAPI to which this package conforms.
+who uses the \fBebuild\fR(1) command with this package will be
+required to have a version of portage that recognizes the EAPI to
+which this package conforms.
.TP
.B SRC_URI\fR = \fI"https://example.com/path/${P}.tar.gz"
Contains a list of URIs for the required source files. It can contain
diff --git a/man/make.conf.5 b/man/make.conf.5
index fc4a018c536..8c77eda2e39 100644
--- a/man/make.conf.5
+++ b/man/make.conf.5
@@ -457,9 +457,9 @@ enabled by default.
.TP
.B digest
Autogenerate digests for packages when running the
-\fBemerge\fR(1), \fBebuild\fR(1), or \fBrepoman\fR(1) commands. If
-the \fIassume\-digests\fR feature is also enabled then existing SRC_URI digests
-will be reused whenever they are available.
+\fBemerge\fR(1) or \fBebuild\fR(1) commands. If the
+\fIassume\-digests\fR feature is also enabled then existing SRC_URI
+digests will be reused whenever they are available.
.TP
.B distcc
Enable portage support for the distcc package.
@@ -1051,7 +1051,7 @@ when \fBsign\fR is in \fBFEATURES\fR. In order to sign commits with
to be configured by \fI`git config user.signingkey key_id`\fR.
.TP
.B PORTAGE_GPG_SIGNING_COMMAND
-The command used by \fBrepoman\fR(1) to sign manifests when \fBsign\fR is
+The command used by \fBegencache\fR(1) to sign manifests when \fBsign\fR is
in \fBFEATURES\fR.
.TP
\fBPORTAGE_GRPNAME\fR = \fI[group]\fR
diff --git a/man/portage.5 b/man/portage.5
index 50f20454c23..f42564664ca 100644
--- a/man/portage.5
+++ b/man/portage.5
@@ -944,14 +944,13 @@ Setting this attribute is generally not recommended since resulting changes
in eclass inheritance may trigger performance issues due to invalidation
of metadata cache.
.br
-When 'force = eclass\-overrides' attribute is not set, \fBegencache\fR(1),
-\fBemirrordist\fR(1) and \fBrepoman\fR(1) ignore this attribute,
-since operations performed by these tools are inherently
-\fBnot\fR \fIsite\-specific\fR.
+When 'force = eclass\-overrides' attribute is not set, \fBegencache\fR(1)
+and \fBemirrordist\fR(1) ignore this attribute, since operations
+performed by these tools are inherently \fBnot\fR \fIsite\-specific\fR.
.TP
.B force
Specifies names of attributes, which should be forcefully respected by
-\fBegencache\fR(1), \fBemirrordist\fR(1) and \fBrepoman\fR(1).
+\fBegencache\fR(1) and \fBemirrordist\fR(1).
.br
Valid values: aliases, eclass\-overrides, masters
.RE
@@ -966,10 +965,9 @@ Setting this attribute is generally not recommended since resulting changes
in eclass inheritance may trigger performance issues due to invalidation
of metadata cache.
.br
-When 'force = aliases' attribute is not set, \fBegencache\fR(1),
-\fBemirrordist\fR(1) and \fBrepoman\fR(1) ignore this attribute,
-since operations performed by these tools are inherently
-\fBnot\fR \fIsite\-specific\fR.
+When 'force = aliases' attribute is not set, \fBegencache\fR(1) and
+\fBemirrordist\fR(1) ignore this attribute, since operations performed by
+these tools are inherently \fBnot\fR \fIsite\-specific\fR.
.TP
.B auto\-sync = yes|no|true|false
This setting determines if the repo will be synced during "\fBemerge \-\-sync\fR" or
@@ -990,14 +988,13 @@ Setting this attribute is generally not recommended since resulting changes
in eclass inheritance may trigger performance issues due to invalidation
of metadata cache.
.br
-When 'force = eclass\-overrides' attribute is not set, \fBegencache\fR(1),
-\fBemirrordist\fR(1) and \fBrepoman\fR(1) ignore this attribute,
-since operations performed by these tools are inherently
-\fBnot\fR \fIsite\-specific\fR.
+When 'force = eclass\-overrides' attribute is not set, \fBegencache\fR(1)
+and \fBemirrordist\fR(1) ignore this attribute, since operations
+performed by these tools are inherently \fBnot\fR \fIsite\-specific\fR.
.TP
.B force
Specifies names of attributes, which should be forcefully respected by
-\fBegencache\fR(1), \fBemirrordist\fR(1) and \fBrepoman\fR(1).
+\fBegencache\fR(1) and \fBemirrordist\fR(1).
.br
Valid values: aliases, eclass\-overrides, masters
.TP
@@ -1011,10 +1008,9 @@ Setting this attribute is generally not recommended since resulting changes
in eclass inheritance may trigger performance issues due to invalidation
of metadata cache.
.br
-When 'force = masters' attribute is not set, \fBegencache\fR(1),
-\fBemirrordist\fR(1) and \fBrepoman\fR(1) ignore this attribute,
-since operations performed by these tools are inherently
-\fBnot\fR \fIsite\-specific\fR.
+When 'force = masters' attribute is not set, \fBegencache\fR(1) and
+\fBemirrordist\fR(1) ignore this attribute, since operations performed by
+these tools are inherently \fBnot\fR \fIsite\-specific\fR.
.TP
.B priority
Specifies priority of given repository.
@@ -1423,7 +1419,7 @@ Specifies information about the repository layout.
\fISite-specific\fR overrides to \fBlayout.conf\fR settings may be specified in
\fB/etc/portage/repos.conf\fR.
Settings in \fBrepos.conf\fR take precedence over settings in
-\fBlayout.conf\fR, except tools such as \fBrepoman\fR(1) and \fBegencache\fR(1)
+\fBlayout.conf\fR, except tools such as \fBegencache\fR(1)
ignore "aliases", "eclass-overrides" and "masters" attributes set in
\fBrepos.conf\fR since their operations are inherently \fBnot\fR
\fIsite\-specific\fR.
@@ -1485,9 +1481,6 @@ here are not present in the Manifest, Portage will refetch all distfiles
and update the respective entries to include them. Must be a subset
of manifest\-hashes. If not specified, defaults to all manifest\-hashes.
.TP
-.BR update\-changelog " = [true|" false "]"
-The default setting for repoman's --echangelog option.
-.TP
.BR cache\-formats " = [pms] [md5-dict]"
The cache formats supported in the metadata tree. There is the old "pms" format
and the newer/faster "md5-dict" format. Default is to detect dirs.
@@ -1553,9 +1546,6 @@ use\-manifests = strict
# customize the set of hashes generated for Manifest entries
manifest\-hashes = SHA256 SHA512 WHIRLPOOL
-# indicate that this repo enables repoman's --echangelog=y option automatically
-update\-changelog = false
-
# indicate that this repo contains the md5-dict cache format,
# which may be generated by egencache(1)
cache\-formats = md5-dict
@@ -1700,7 +1690,7 @@ package has been masked and WHO is doing the masking.
.TP
.BR profiles.desc
List all the current stable and development profiles. If a profile is listed
-here, then it will be checked by repoman.
+here, then it will be checked by pkgcheck.
.I Format:
.nf
\- comments begin with # (no inline comments)
diff --git a/repoman/.repoman_not_installed b/repoman/.repoman_not_installed
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/repoman/.repoman_not_installed
+++ /dev/null
diff --git a/repoman/MANIFEST.in b/repoman/MANIFEST.in
deleted file mode 100644
index d9ef2aee0b4..00000000000
--- a/repoman/MANIFEST.in
+++ /dev/null
@@ -1,4 +0,0 @@
-
-# for the tests
-include cnf/metadata.xsd
-include .repoman_not_installed
diff --git a/repoman/NEWS b/repoman/NEWS
deleted file mode 100644
index c8d22d02498..00000000000
--- a/repoman/NEWS
+++ /dev/null
@@ -1,14 +0,0 @@
-News (mainly features/major bug fixes)
-
-repoman 2.3.8
-=====================
-- Support for plugin module systems, see
- https://wiki.gentoo.org/wiki/Project:Portage/Repoman-Module-specs
-
-repoman 2.3.0
-=====================
-- Final release
-
-repoman 2.3.0_rc1
-=====================
-- First test release
diff --git a/repoman/README b/repoman/README
deleted file mode 100644
index f0976e8414b..00000000000
--- a/repoman/README
+++ /dev/null
@@ -1,49 +0,0 @@
-About Portage
-=============
-
-Portage is a package management system based on ports collections. The
-Package Manager Specification Project (PMS) standardises and documents
-the behaviour of Portage so that ebuild repositories can be used by other
-package managers.
-
-
-Dependencies
-============
-
-Python and Bash should be the only hard dependencies. Python 2.7 is the
-minimum supported version.
-
-
-Licensing and Legalese
-=======================
-
-Portage is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-version 2 as published by the Free Software Foundation.
-
-Portage is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Portage; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.
-
-
-More information
-================
-
--DEVELOPING contains some code guidelines.
--LICENSE contains the GNU General Public License version 2.
--NEWS contains new features/major bug fixes for each version.
--RELEASE NOTES contains mainly upgrade information for each version.
--TEST-NOTES contains Portage unit test information.
-
-
-Links
-=====
-Gentoo project page: <https://wiki.gentoo.org/wiki/Project:Portage>
-PMS: <https://dev.gentoo.org/~ulm/pms/head/pms.html>
-PMS git repo: <https://gitweb.gentoo.org/proj/pms.git/>
diff --git a/repoman/RELEASE-NOTES b/repoman/RELEASE-NOTES
deleted file mode 100644
index df34803ccb8..00000000000
--- a/repoman/RELEASE-NOTES
+++ /dev/null
@@ -1,213 +0,0 @@
-Release Notes; upgrade information mainly.
-Features/major bugfixes are listed in NEWS
-
-repoman-3.0.3
-==================================
-* Bug Fixes:
- - Bug 608664 variable.phase check like pkgcheck VariableScopeCheck
- - Bug 692486 Change message for preserve_old_lib
-
-repoman-3.0.2
-==================================
-* Bug Fixes:
- - Bug 748144 Make file.size fatal for files larger than 20 KiB
-
-repoman-3.0.1
-==================================
-* Bug Fixes:
- - Bug 737698 Update repoman for compatibility with portage-3.0.4.
-
-repoman-3.0.0
-==================================
-* Bug Fixes:
- - Bug 448462 Add --jobs and --load-average options which allow
- dependency checks for multiple profiles to run in parallel.
-
-repoman-2.3.23
-==================================
-* Bug Fixes:
- - Bug 637824 Deprecate netsurf.eclass
-
-repoman-2.3.22
-==================================
-* Bug Fixes:
- - Bug 712106 only stage changes in index for commit mode
-
-repoman-2.3.21
-==================================
-* Bug Fixes:
- - Bug 712106 prevent spurious copyright header updates
-
-
-repoman-2.3.20
-==================================
-* Bug Fixes:
- - Bug 541076 repoman commit: ignore unadded hidden files
- - Bug 702100 repoman: support profiles/package.deprecated
-
-
-repoman-2.3.19
-==================================
-* Bug Fixes:
- - Bug 667432 Rename DCO_SIGNED_OFF_BY config variable to SIGNED_OFF_BY.
- - Bug 700456 Add --include-profiles=PROFILES
-
-
-repoman-2.3.18
-==================================
-* Bug Fixes:
- - Bug 690786 Support metadata/layout.conf restrict-allowed
- - Bug 699514 Detect dosym absolute paths starting with ${D}, ${ED} etc.
- - Bug 699508 Fix unsafe string interpolation.
-
-
-repoman-2.3.17
-==================================
-* Bug Fixes:
- - Bug 233589 Support PROPERTIES="live"
-
-
-repoman-2.3.16
-==================================
-* Bug Fixes:
- - Bug 687420 Allow empty LICENSE in acct-* packages for GLEP 81
-
-
-repoman-2.3.15
-==================================
-* Bug Fixes:
- - Bug 688278 Accept 'Gentoo Foundation' copyright for old ebuilds
-
-
-repoman-2.3.14
-==================================
-* Bug Fixes:
- - Bug 666330 Update for new copyright policy
-
-
-repoman-2.3.13
-==================================
-* Bug Fixes:
- - Bug 686074 report error for unknown arguments
-
-
-repoman-2.3.12
-==================================
-* Bug Fixes:
- - Bug 588752 fix exit code for manifest mode
-
-
-repoman-2.3.11
-==================================
-* Bug Fixes:
- - Bug 666330 support new 'Gentoo Authors' copyright policy and
- automatically apply the new policy when updating copyright headers.
- Earlier versions of repoman will report an ebuild.badheader warning
- for the new copyright headers. Users of earlier versions of repoman
- should be advised to simply ignore the ebuild.badheader warning, or
- else upgrade to the latest version of repoman.
-
-
-repoman-2.3.10
-==================================
-* Bug Fixes:
- - Bug 649482 warn about = deps without revision
- - Bug 660982 populate implicit IUSE for empty profile
-
-
-repoman-2.3.8
-==================================
-* The --experimental-repository-modules=<y|n> option enables a new
- plugin modules system:
- https://wiki.gentoo.org/wiki/Project:Portage/Repoman-Module-specs
-
-
-repoman-2.3.7
-==================================
-* Bug Fixes:
- - Bug 552720 allow https for metadata.dtd URI
-
-
-repoman-2.3.6
-==================================
-* Bug Fixes:
- - Bug 637460 Fix import paths for unit tests
-
-
-repoman-2.3.5
-==================================
-* Repository metadata/layout.conf supports manifest-required-hashes
- attribute (default value is SHA512).
-
-
-repoman-2.3.4
-==================================
-* Support two new options: --bug (-b) and --closes (-c)
-
-
-repoman-2.3.3
-==================================
-* Bug Fixes:
- - Bug 571546 Change how the tmp file for the commit msg is made
-* flag URIs using http:// when https:// is available
-* Add a check for relative dosym candidates
-* Make all shebangs prefix friendly
-* Mark ruby-2.0 as deprecated
-* Detect inconsistent metadata.xml indentation
-* Warn about dropped keywords only for latest in SLOT.
-
-
-repoman-2.3.2
-==================================
-* Bug Fixes:
- - Bug 544938 add dev-qt/linguist-tools to RDEPEND.suspect set
- - Bug 602002 make unused local USE flags an error
- - Bug 533554 add HOMEPAGE.missingurischeme check
- - Bug 610414 use regular expression to detect line continuations
- - Bug 610954 Warn about stale CVS keywords in ebuild header
- - Bug 611296 Don't update years in non-Gentoo copyright lines
-* Add virtual/linuxtv-dvb-headers to RDEPEND.suspect set
-* Add virtual/os-headers to RDEPEND.suspect set
-* Add gentoo to remote-id type
-* Define long for python3 Fixes: 006b168c1bb6
-* Commit footer improvements
-* Check for empty files in filesdir
-* Deprecate gpe.eclass, confutils.eclass
-
-
-repoman-2.3.1
-==================================
-* Bug Fixes:
- - Bug 586864 skip QA checks in manifest mode
- - Bug 591184 fix erroneous LICENSE.syntax
- - use https to fetch metadata.xsd
- - update links to https
- - Make LIVEVCS.* checks fatal
- - fix _depend_checks baddepsyntax accounting
- - Fix commitmessage assignment not being done
- - Add cat/pkg: substtution in the commitsgfile text
- - Disable SRC_URI.mirror warnings when there is only 1 mirror
- - Fix version output string to say Repoman, fix live versioning,
- add portage version to --version output.
- - Add repoman version to "Package manager:" commit footer
-
-repoman-2.3.0
-==================================
-* Bug Fixes:
- - Bug 584786 Add support for .git as a file when --separate-git-dir is used
- - Bug 585864 fix missing vcs_files_to_cps repodir argument
- - Bug 585388 fix KeyError during manifest generation
-* New QA error: slot operator under '||' alternative
-
-repoman-2.3.0_rc1
-==================================
-* Initial test release
-* Bug Fixes:
- - Bug 579460 Disable the $ID header check
- - Bug 546010 Handle removed packages in vcs_files_to_cps
- - Bug 581594 Fix commit 8e7971169c2 missing self in func() parameters
- - Bug 581598 Add InvalidPackageName exception trap
- - Bug 405017 Fix copyright update
-* Includes the stage2 re-writes, the checks are now in a modular system
- which is not yet fully plug-in capable. Becoming fully plug-in capable and
- configurable is to be done in the stage3 rewites.
diff --git a/repoman/TEST-NOTES b/repoman/TEST-NOTES
deleted file mode 100644
index 8be5f9cf340..00000000000
--- a/repoman/TEST-NOTES
+++ /dev/null
@@ -1,45 +0,0 @@
-UnitTests
----------
-
-Portage has some tests that use the unittest framework that ships with python (2.3-2.4ish)
-Tests have a specific naming convention.
-
-in lib/portage/tests/ there is a runTest script that invokes lib/portage/tests/__init__.py
-
-This init looks at a hardcoded list of test dirs to search for tests.
-If you add a new dir and don't see your new tests, make sure that the dir is in this list.
-
-On the subject of adding more directories; the layout is basically 1 directory per portage
-file at this point (we have few files, and even fewer large files). Inside of the dir
-you should have files of the form test_${function}.py.
-
-So if I was to write a vercmp test, and vercmp is in portage_versions.
-
-lib/portage/tests/portage_versions/test_vercmp.py
-
-would be the filename.
-
-The __init__.py file now does recursive tests, but you need to tell it so. For example, if
-you had cache tests the dir format would be something like...
-
-lib/portage/tests/cache/flat_hash/test_foo.py
-
-and you would put "cache/flat_hash" into the testDirs variable in __init__.py.
-
-
-Skipping
---------
-
-Please use the portage.tests.* classes as they support throwing a SkipException for
-tests that are known to fail. Normally one uses testing to do Test Driven Development
-(TDD); however we do not do that here. Therefore there are times when legitimate tests
-exist but fail due to code in trunk. We would still like the suite to pass in some instances
-because the suite is built around two things, testing functionality in the current code as
-well as poking holes in the current code (isvalidatom is an example). So sometimes we desire
-a test to point out that "this needs fixing" but it doesn't affect portage's overall
-functionality. You should raise portage.tests.SkipException in that case.
-
-emerge
-------
-
-The emerge namespace currently has 0 tests (and no runner)
diff --git a/repoman/bin/repoman b/repoman/bin/repoman
deleted file mode 100755
index beaf8147a6a..00000000000
--- a/repoman/bin/repoman
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-"""Ebuild and tree health checks and maintenance utilities.
-"""
-
-import sys
-import errno
-
-# This block ensures that ^C interrupts are handled quietly.
-try:
- import signal
-
- def exithandler(signum, _frame):
- signal.signal(signal.SIGINT, signal.SIG_IGN)
- signal.signal(signal.SIGTERM, signal.SIG_IGN)
- sys.exit(128 + signum)
-
- signal.signal(signal.SIGINT, exithandler)
- signal.signal(signal.SIGTERM, exithandler)
- signal.signal(signal.SIGPIPE, signal.SIG_DFL)
-
-except KeyboardInterrupt:
- sys.exit(1)
-
-from os import path as osp
-
-here = osp.realpath(__file__)
-if osp.isfile(osp.join(osp.dirname(osp.dirname(here)), ".repoman_not_installed")):
- # Add the repoman subpkg
- pym_path = osp.join(osp.dirname(osp.dirname(here)), "lib")
- sys.path.insert(0, pym_path)
- if osp.isfile(
- osp.join(osp.dirname(osp.dirname(osp.dirname(here))), ".portage_not_installed")
- ):
- # Add the base portage pkg
- pym_path = osp.join(osp.dirname(osp.dirname(osp.dirname(here))), "lib")
- sys.path.insert(0, pym_path)
-
-import portage
-
-portage._internal_caller = True
-from portage.util._eventloop.global_event_loop import global_event_loop
-from repoman.main import repoman_main
-
-try:
- sys.exit(repoman_main(sys.argv))
-except IOError as e:
- if e.errno == errno.EACCES:
- print("\nRepoman: Need user access")
- sys.exit(1)
- else:
- raise
-finally:
- global_event_loop().close()
diff --git a/repoman/cnf/linechecks/linechecks.yaml b/repoman/cnf/linechecks/linechecks.yaml
deleted file mode 100644
index c6c72ab26ee..00000000000
--- a/repoman/cnf/linechecks/linechecks.yaml
+++ /dev/null
@@ -1,34 +0,0 @@
----
-# linecheck_help.yaml
-
-# Repoman API version (do not edit)
-version: 1
-# minimum
-repoman_version: 2.3.3
-
-# configuration file for the LineCheck plugins run via the multicheck
-# scan module
-errors:
- COPYRIGHT_ERROR: 'Invalid Copyright'
- LICENSE_ERROR: 'Invalid Gentoo/GPL License'
- ID_HEADER_ERROR: 'Stale CVS header'
- NO_BLANK_LINE_ERROR: 'Non-blank line after header'
- LEADING_SPACES_ERROR: 'Ebuild contains leading spaces'
- TRAILING_WHITESPACE_ERROR: 'Trailing whitespace error'
- READONLY_ASSIGNMENT_ERROR: 'Ebuild contains assignment to read-only variable'
- MISSING_QUOTES_ERROR: 'Unquoted Variable'
- NESTED_DIE_ERROR: 'Ebuild calls die in a subshell'
- PATCHES_ERROR: 'PATCHES is not a bash array'
- REDUNDANT_CD_S_ERROR: 'Ebuild has redundant cd ${S} statement'
- EMAKE_PARALLEL_DISABLED: 'Upstream parallel compilation bug (ebuild calls emake -j1)'
- EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS: 'Upstream parallel compilation bug (MAKEOPTS=-j1)'
- DEPRECATED_BINDNOW_FLAGS: 'Deprecated bindnow-flags call'
- EAPI_DEFINED_AFTER_INHERIT: 'EAPI defined after inherit'
- NO_AS_NEEDED: 'Upstream asneeded linking bug (no-as-needed)'
- PRESERVE_OLD_LIB: 'Ebuild calls preserve_old_lib function reserved for system packages'
- BUILT_WITH_USE: 'built_with_use'
- NO_OFFSET_WITH_HELPERS: 'Helper function is used with D, ROOT, ED, EROOT or EPREFIX'
- USEQ_ERROR: 'Ebuild calls deprecated useq function'
- HASQ_ERROR: 'Ebuild calls deprecated hasq function'
- URI_HTTPS: 'Ebuild uses http:// but should use https://'
-
diff --git a/repoman/cnf/metadata.xsd b/repoman/cnf/metadata.xsd
deleted file mode 100644
index 33ff58eac1b..00000000000
--- a/repoman/cnf/metadata.xsd
+++ /dev/null
@@ -1,548 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-
-<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
- <!-- top-level variants -->
- <xs:element name='pkgmetadata' type='pkgMetadataType'>
- <!-- note: restrict uniquity rules are simplified
- the spec says: one for each matched package
- we can only do: one for each restrict rule -->
- <xs:unique name='longDescUniquityConstraint'>
- <xs:selector xpath='longdescription'/>
- <xs:field xpath='@lang'/>
- <xs:field xpath='@restrict'/>
- </xs:unique>
- <xs:unique name='maintainerUniquityConstraint'>
- <xs:selector xpath='maintainer'/>
- <xs:field xpath='email'/>
- <xs:field xpath='@restrict'/>
- </xs:unique>
- <xs:unique name='slotsUniquityConstraint'>
- <xs:selector xpath='slots'/>
- <xs:field xpath='@lang'/>
- </xs:unique>
- <xs:unique name='upstreamSingleConstraint'>
- <xs:selector xpath='upstream'/>
- <xs:field xpath='@fake-only-once'/>
- </xs:unique>
- <xs:unique name='useUniquityConstraint'>
- <xs:selector xpath='use'/>
- <xs:field xpath='@lang'/>
- </xs:unique>
- </xs:element>
- <xs:element name='catmetadata' type='catMetadataType'>
- <xs:unique name='catLongDescUniquityConstraint'>
- <xs:selector xpath='longdescription'/>
- <xs:field xpath='@lang'/>
- </xs:unique>
- </xs:element>
-
- <!-- global elements -->
- <xs:complexType name='pkgMetadataType'>
- <xs:choice minOccurs='0' maxOccurs='unbounded'>
- <xs:element name='longdescription' type='longDescType'/>
- <xs:element name='maintainer' type='maintainerType'>
- <xs:unique name='maintainerDescUniquityConstraint'>
- <xs:selector xpath='description'/>
- <xs:field xpath='@lang'/>
- </xs:unique>
- </xs:element>
- <xs:element name='slots' type='slotsType'>
- <xs:unique name='slotUniquityConstraint'>
- <xs:selector xpath='slot'/>
- <xs:field xpath='@name'/>
- </xs:unique>
- <xs:unique name='subslotsSingleConstraint'>
- <xs:selector xpath='subslots'/>
- <xs:field xpath='@fake-only-once'/>
- </xs:unique>
- </xs:element>
- <xs:element name='upstream' type='upstreamType'>
- <xs:unique name='bugsToSingleConstraint'>
- <xs:selector xpath='bugs-to'/>
- <xs:field xpath='@fake-only-once'/>
- </xs:unique>
- <xs:unique name='changelogSingleConstraint'>
- <xs:selector xpath='changelog'/>
- <xs:field xpath='@fake-only-once'/>
- </xs:unique>
- <!-- prevent accidentally repeating the same remote -->
- <xs:unique name='upstreamRemoteIdRepetitionConstraint'>
- <xs:selector xpath='remote-id'/>
- <xs:field xpath='@type'/>
- <xs:field xpath='.'/>
- </xs:unique>
- <xs:unique name='upstreamDocUniquityConstraint'>
- <xs:selector xpath='doc'/>
- <xs:field xpath='@lang'/>
- </xs:unique>
- </xs:element>
- <xs:element name='use' type='useType'>
- <xs:unique name='flagUniquityConstraint'>
- <xs:selector xpath='flag'/>
- <xs:field xpath='@name'/>
- <xs:field xpath='@restrict'/>
- </xs:unique>
- </xs:element>
- </xs:choice>
- </xs:complexType>
-
- <xs:complexType name='catMetadataType'>
- <xs:choice minOccurs='0' maxOccurs='unbounded'>
- <xs:element name='longdescription' type='catLongDescType'/>
- </xs:choice>
- </xs:complexType>
-
- <!-- the huge <upstream/> structure -->
- <xs:complexType name='upstreamType'>
- <xs:choice minOccurs='0' maxOccurs='unbounded'>
- <xs:element name='maintainer' type='upstreamMaintainerType'>
- <xs:unique name='upstreamMaintainerUniquityConstraint'>
- <xs:selector xpath='maintainer'/>
- <xs:field xpath='name'/>
- </xs:unique>
- </xs:element>
- <xs:element name='changelog' type='urlOnceType'/>
- <xs:element name='doc' type='upstreamDocType'/>
- <xs:element name='bugs-to' type='urlOnceType'/>
- <xs:element name='remote-id' type='upstreamRemoteIdType'/>
- </xs:choice>
- <xs:attribute name='fake-only-once'
- fixed='there can be at most one &lt;upstream/&gt; element'/>
- </xs:complexType>
-
- <!-- maintainer in two variants -->
- <xs:complexType name='maintainerType'>
- <xs:all>
- <xs:element name='email' type='emailType'
- minOccurs='1'/>
- <xs:element name='name' type='xs:token'
- minOccurs='0'/>
- <xs:element name='description' type='maintainerDescType'
- minOccurs='0'/>
- </xs:all>
- <xs:attribute name='type' type='maintainerTypeAttrType'
- use='required'/>
- <xs:attribute name='restrict' type='restrictAttrType'/>
- </xs:complexType>
-
- <xs:simpleType name='maintainerTypeAttrType'>
- <xs:restriction base='xs:token'>
- <xs:enumeration value='person'/>
- <xs:enumeration value='project'/>
- </xs:restriction>
- </xs:simpleType>
-
- <xs:complexType name='upstreamMaintainerType'>
- <xs:all>
- <xs:element name='email' type='emailType'
- minOccurs='0'/>
- <xs:element name='name' type='xs:token'
- minOccurs='0'/>
- </xs:all>
- <xs:attribute name='status' type='upstreamMaintainerStatusAttrType'
- default='unknown'/>
- </xs:complexType>
-
- <xs:simpleType name='upstreamMaintainerStatusAttrType'>
- <xs:restriction base='xs:token'>
- <xs:enumeration value='active'/>
- <xs:enumeration value='inactive'/>
- <xs:enumeration value='unknown'/>
- </xs:restriction>
- </xs:simpleType>
-
- <xs:complexType name='maintainerDescType'>
- <xs:simpleContent>
- <xs:extension base="xs:token">
- <xs:attribute name='lang' type='langAttrType' default='en'/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <!-- long description -->
- <xs:complexType name='longDescType' mixed='true'>
- <xs:choice minOccurs='0' maxOccurs='unbounded'>
- <xs:element name='pkg' type='pkgType'/>
- <xs:element name='cat' type='catType'/>
- </xs:choice>
- <xs:attribute name='lang' type='langAttrType' default='en'/>
- <xs:attribute name='restrict' type='restrictAttrType'/>
- </xs:complexType>
-
- <xs:complexType name='catLongDescType' mixed='true'>
- <xs:choice minOccurs='0' maxOccurs='unbounded'>
- <xs:element name='pkg' type='pkgType'/>
- <xs:element name='cat' type='catType'/>
- </xs:choice>
- <xs:attribute name='lang' type='langAttrType' default='en'/>
- </xs:complexType>
-
- <!-- slots -->
- <xs:complexType name='slotsType'>
- <xs:choice minOccurs='0' maxOccurs='unbounded'>
- <xs:element name='slot' type='slotType'/>
- <xs:element name='subslots' type='tokenOnceType'/>
- </xs:choice>
- <xs:attribute name='lang' type='langAttrType' default='en'/>
- </xs:complexType>
-
- <xs:complexType name='slotType'>
- <xs:simpleContent>
- <xs:extension base="xs:token">
- <xs:attribute name='name' type='slotNameAttrType'
- use='required'/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:simpleType name='slotNameAttrType'>
- <xs:restriction base='xs:token'>
- <!-- PMS 3.1.3 Slot Names + special value '*' -->
- <xs:pattern value="[A-Za-z0-9_][A-Za-z0-9+_.-]*|[*]"/>
- </xs:restriction>
- </xs:simpleType>
-
- <!-- use flags -->
- <xs:complexType name='useType'>
- <xs:choice minOccurs='0' maxOccurs='unbounded'>
- <xs:element name='flag' type='flagType'/>
- </xs:choice>
- <xs:attribute name='lang' type='langAttrType' default='en'/>
- </xs:complexType>
-
- <xs:complexType name='flagType' mixed='true'>
- <xs:choice minOccurs='0' maxOccurs='unbounded'>
- <xs:element name='cat' type='catType'/>
- <xs:element name='pkg' type='pkgType'/>
- </xs:choice>
- <xs:attribute name='name' type='flagNameAttrType'
- use='required'/>
- <xs:attribute name='restrict' type='restrictAttrType'
- default=''/>
- </xs:complexType>
-
- <xs:simpleType name='flagNameAttrType'>
- <xs:restriction base='xs:token'>
- <!-- PMS 3.1.4 USE Flag Names -->
- <xs:pattern value="[A-Za-z0-9][A-Za-z0-9+_@-]*"/>
- </xs:restriction>
- </xs:simpleType>
-
- <!-- upstream-specific types -->
- <xs:complexType name='upstreamDocType'>
- <xs:simpleContent>
- <xs:extension base="urlType">
- <xs:attribute name='lang' type='langAttrType' default='en'/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name='upstreamRemoteIdType'>
- <xs:simpleContent>
- <xs:extension base="xs:token">
- <xs:attribute name='type' type='upstreamRemoteIdTypeAttrType'
- use='required'/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:simpleType name='upstreamRemoteIdTypeAttrType'>
- <xs:restriction base='xs:token'>
- <xs:enumeration value='bitbucket'/>
- <xs:enumeration value='cpan'/>
- <xs:enumeration value='cpan-module'/>
- <xs:enumeration value='cpe'/>
- <xs:enumeration value='cran'/>
- <xs:enumeration value='ctan'/>
- <xs:enumeration value='freecode'/>
- <xs:enumeration value='freshmeat'/>
- <xs:enumeration value='gentoo'/>
- <xs:enumeration value='github'/>
- <xs:enumeration value='gitlab'/>
- <xs:enumeration value='gitorious'/>
- <xs:enumeration value='google-code'/>
- <xs:enumeration value='launchpad'/>
- <xs:enumeration value='pear'/>
- <xs:enumeration value='pecl'/>
- <xs:enumeration value='pypi'/>
- <xs:enumeration value='rubyforge'/>
- <xs:enumeration value='rubygems'/>
- <xs:enumeration value='sourceforge'/>
- <xs:enumeration value='sourceforge-jp'/>
- <xs:enumeration value='vim'/>
- </xs:restriction>
- </xs:simpleType>
-
- <!-- creepy mixed-text types -->
- <xs:simpleType name='catType'>
- <xs:restriction base='xs:token'>
- <!-- PMS 3.1.1 Category Names -->
- <xs:pattern value="[A-Za-z0-9_][A-Za-z0-9+_.-]*"/>
- </xs:restriction>
- </xs:simpleType>
- <xs:simpleType name='pkgType'>
- <xs:restriction base='xs:token'>
- <!-- PMS 3.1.1 Category Names + 3.1.2 Package Names -->
- <!-- note: this does not enforce the 'anything matching
- the version syntax' requirement -->
- <xs:pattern
- value="[A-Za-z0-9_][A-Za-z0-9+_.-]*/[A-Za-z0-9_][A-Za-z0-9+_-]*"/>
- </xs:restriction>
- </xs:simpleType>
-
- <!-- common attributes -->
- <xs:simpleType name='langAttrType'>
- <xs:restriction base='xs:token'>
- <!-- ISO 639-1 language codes -->
- <xs:enumeration value='aa'/>
- <xs:enumeration value='ab'/>
- <xs:enumeration value='ae'/>
- <xs:enumeration value='af'/>
- <xs:enumeration value='ak'/>
- <xs:enumeration value='am'/>
- <xs:enumeration value='an'/>
- <xs:enumeration value='ar'/>
- <xs:enumeration value='as'/>
- <xs:enumeration value='av'/>
- <xs:enumeration value='ay'/>
- <xs:enumeration value='az'/>
- <xs:enumeration value='ba'/>
- <xs:enumeration value='be'/>
- <xs:enumeration value='bg'/>
- <xs:enumeration value='bh'/>
- <xs:enumeration value='bi'/>
- <xs:enumeration value='bm'/>
- <xs:enumeration value='bn'/>
- <xs:enumeration value='bo'/>
- <xs:enumeration value='bo'/>
- <xs:enumeration value='br'/>
- <xs:enumeration value='bs'/>
- <xs:enumeration value='ca'/>
- <xs:enumeration value='ce'/>
- <xs:enumeration value='ch'/>
- <xs:enumeration value='co'/>
- <xs:enumeration value='cr'/>
- <xs:enumeration value='cs'/>
- <xs:enumeration value='cs'/>
- <xs:enumeration value='cu'/>
- <xs:enumeration value='cv'/>
- <xs:enumeration value='cy'/>
- <xs:enumeration value='cy'/>
- <xs:enumeration value='da'/>
- <xs:enumeration value='de'/>
- <xs:enumeration value='de'/>
- <xs:enumeration value='dv'/>
- <xs:enumeration value='dz'/>
- <xs:enumeration value='ee'/>
- <xs:enumeration value='el'/>
- <xs:enumeration value='el'/>
- <xs:enumeration value='en'/>
- <xs:enumeration value='eo'/>
- <xs:enumeration value='es'/>
- <xs:enumeration value='et'/>
- <xs:enumeration value='eu'/>
- <xs:enumeration value='eu'/>
- <xs:enumeration value='fa'/>
- <xs:enumeration value='fa'/>
- <xs:enumeration value='ff'/>
- <xs:enumeration value='fi'/>
- <xs:enumeration value='fj'/>
- <xs:enumeration value='fo'/>
- <xs:enumeration value='fr'/>
- <xs:enumeration value='fr'/>
- <xs:enumeration value='fy'/>
- <xs:enumeration value='ga'/>
- <xs:enumeration value='ga'/>
- <xs:enumeration value='Ga'/>
- <xs:enumeration value='gd'/>
- <xs:enumeration value='gl'/>
- <xs:enumeration value='gn'/>
- <xs:enumeration value='gu'/>
- <xs:enumeration value='gv'/>
- <xs:enumeration value='ha'/>
- <xs:enumeration value='he'/>
- <xs:enumeration value='hi'/>
- <xs:enumeration value='ho'/>
- <xs:enumeration value='hr'/>
- <xs:enumeration value='ht'/>
- <xs:enumeration value='hu'/>
- <xs:enumeration value='hy'/>
- <xs:enumeration value='hy'/>
- <xs:enumeration value='hz'/>
- <xs:enumeration value='ia'/>
- <xs:enumeration value='id'/>
- <xs:enumeration value='ie'/>
- <xs:enumeration value='ig'/>
- <xs:enumeration value='ii'/>
- <xs:enumeration value='ik'/>
- <xs:enumeration value='io'/>
- <xs:enumeration value='is'/>
- <xs:enumeration value='is'/>
- <xs:enumeration value='it'/>
- <xs:enumeration value='iu'/>
- <xs:enumeration value='ja'/>
- <xs:enumeration value='jv'/>
- <xs:enumeration value='ka'/>
- <xs:enumeration value='ka'/>
- <xs:enumeration value='kg'/>
- <xs:enumeration value='ki'/>
- <xs:enumeration value='kj'/>
- <xs:enumeration value='kk'/>
- <xs:enumeration value='kl'/>
- <xs:enumeration value='km'/>
- <xs:enumeration value='kn'/>
- <xs:enumeration value='ko'/>
- <xs:enumeration value='kr'/>
- <xs:enumeration value='ks'/>
- <xs:enumeration value='ku'/>
- <xs:enumeration value='kv'/>
- <xs:enumeration value='kw'/>
- <xs:enumeration value='ky'/>
- <xs:enumeration value='la'/>
- <xs:enumeration value='lb'/>
- <xs:enumeration value='lg'/>
- <xs:enumeration value='li'/>
- <xs:enumeration value='ln'/>
- <xs:enumeration value='lo'/>
- <xs:enumeration value='lt'/>
- <xs:enumeration value='lu'/>
- <xs:enumeration value='lv'/>
- <xs:enumeration value='mg'/>
- <xs:enumeration value='mh'/>
- <xs:enumeration value='mi'/>
- <xs:enumeration value='mi'/>
- <xs:enumeration value='mk'/>
- <xs:enumeration value='mk'/>
- <xs:enumeration value='ml'/>
- <xs:enumeration value='mn'/>
- <xs:enumeration value='mr'/>
- <xs:enumeration value='ms'/>
- <xs:enumeration value='ms'/>
- <xs:enumeration value='mt'/>
- <xs:enumeration value='my'/>
- <xs:enumeration value='my'/>
- <xs:enumeration value='na'/>
- <xs:enumeration value='nb'/>
- <xs:enumeration value='nd'/>
- <xs:enumeration value='ne'/>
- <xs:enumeration value='ng'/>
- <xs:enumeration value='nl'/>
- <xs:enumeration value='nl'/>
- <xs:enumeration value='nn'/>
- <xs:enumeration value='no'/>
- <xs:enumeration value='nr'/>
- <xs:enumeration value='nv'/>
- <xs:enumeration value='ny'/>
- <xs:enumeration value='oc'/>
- <xs:enumeration value='oj'/>
- <xs:enumeration value='om'/>
- <xs:enumeration value='or'/>
- <xs:enumeration value='os'/>
- <xs:enumeration value='pa'/>
- <xs:enumeration value='pi'/>
- <xs:enumeration value='pl'/>
- <xs:enumeration value='ps'/>
- <xs:enumeration value='pt'/>
- <xs:enumeration value='qu'/>
- <xs:enumeration value='rm'/>
- <xs:enumeration value='rn'/>
- <xs:enumeration value='ro'/>
- <xs:enumeration value='ro'/>
- <xs:enumeration value='ru'/>
- <xs:enumeration value='rw'/>
- <xs:enumeration value='sa'/>
- <xs:enumeration value='sc'/>
- <xs:enumeration value='sd'/>
- <xs:enumeration value='se'/>
- <xs:enumeration value='sg'/>
- <xs:enumeration value='si'/>
- <xs:enumeration value='sk'/>
- <xs:enumeration value='sk'/>
- <xs:enumeration value='sl'/>
- <xs:enumeration value='sm'/>
- <xs:enumeration value='sn'/>
- <xs:enumeration value='so'/>
- <xs:enumeration value='sq'/>
- <xs:enumeration value='sq'/>
- <xs:enumeration value='sr'/>
- <xs:enumeration value='ss'/>
- <xs:enumeration value='st'/>
- <xs:enumeration value='su'/>
- <xs:enumeration value='sv'/>
- <xs:enumeration value='sw'/>
- <xs:enumeration value='ta'/>
- <xs:enumeration value='te'/>
- <xs:enumeration value='tg'/>
- <xs:enumeration value='th'/>
- <xs:enumeration value='ti'/>
- <xs:enumeration value='tk'/>
- <xs:enumeration value='tl'/>
- <xs:enumeration value='tn'/>
- <xs:enumeration value='to'/>
- <xs:enumeration value='tr'/>
- <xs:enumeration value='ts'/>
- <xs:enumeration value='tt'/>
- <xs:enumeration value='tw'/>
- <xs:enumeration value='ty'/>
- <xs:enumeration value='ug'/>
- <xs:enumeration value='uk'/>
- <xs:enumeration value='ur'/>
- <xs:enumeration value='uz'/>
- <xs:enumeration value='ve'/>
- <xs:enumeration value='vi'/>
- <xs:enumeration value='vo'/>
- <xs:enumeration value='wa'/>
- <xs:enumeration value='wo'/>
- <xs:enumeration value='xh'/>
- <xs:enumeration value='yi'/>
- <xs:enumeration value='yo'/>
- <xs:enumeration value='za'/>
- <xs:enumeration value='zh'/>
- <xs:enumeration value='zh'/>
- <xs:enumeration value='zu'/>
- </xs:restriction>
- </xs:simpleType>
-
- <xs:simpleType name='restrictAttrType'>
- <xs:restriction base='xs:token'>
- <!-- simplified package dependency syntax -->
- <!-- note: 'pure' package atom is technically valid too
- but not really meaningful -->
- <xs:pattern
- 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]+)?\*?)?"/>
- </xs:restriction>
- </xs:simpleType>
-
- <!-- generic types -->
- <xs:simpleType name='emailType'>
- <xs:restriction base='xs:token'>
- <!-- minimal safe regex -->
- <xs:pattern value="[^@]+@[^.]+\..+"/>
- </xs:restriction>
- </xs:simpleType>
-
- <xs:complexType name='tokenOnceType'>
- <xs:simpleContent>
- <xs:extension base="xs:token">
- <xs:attribute name='fake-only-once'
- fixed='there can be at most one element of this type'/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:simpleType name='urlType'>
- <xs:restriction base='xs:token'>
- <!-- TODO: something better? -->
- <xs:pattern value="(mailto:[^@]+@[^.]+\..+|https?://.+)"/>
- </xs:restriction>
- </xs:simpleType>
-
- <xs:complexType name='urlOnceType'>
- <xs:simpleContent>
- <xs:extension base="urlType">
- <xs:attribute name='fake-only-once'
- fixed='there can be at most one element of this type'/>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-</xs:schema>
diff --git a/repoman/cnf/qa_data/qa_data.yaml b/repoman/cnf/qa_data/qa_data.yaml
deleted file mode 100644
index 530c8c8061a..00000000000
--- a/repoman/cnf/qa_data/qa_data.yaml
+++ /dev/null
@@ -1,139 +0,0 @@
----
-# qa_help.yaml
-
-# configuration file for the LineCheck plugins run via the multicheck
-# scan module
-
-# Repoman API version (do not edit)
-version: 1
-# minimum
-repoman_version: 2.3.3
-
-# qahelp: Primary QA help messages to describe the errors or warnings
-# Dictionary
-qahelp:
- Entries:
- IO_error: "Attempting to commit, and an IO error was encountered access the Entries file"
- changelog:
- ebuildadded: "An ebuild was added but the ChangeLog was not modified"
- missing: "Missing ChangeLog files"
- notadded: "ChangeLogs that exist but have not been added to cvs"
- dependency:
- bad: "User-visible ebuilds with unsatisfied dependencies (matched against *visible* ebuilds)"
- badmasked: "Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds)"
- badindev: "User-visible ebuilds with unsatisfied dependencies (matched against *visible* ebuilds) in developing arch"
- badmaskedindev: "Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds) in developing arch"
- badinexp: "User-visible ebuilds with unsatisfied dependencies (matched against *visible* ebuilds) in experimental arch"
- badmaskedinexp: "Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds) in experimental arch"
- badtilde: "Uses the ~ dep operator with a non-zero revision part, which is useless (the revision is ignored)"
- deprecated: "Ebuild has a dependency that refers to a deprecated package"
- 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."
- missingslot: "RDEPEND matches more than one SLOT but does not specify a slot and/or use the := or :* slot operator"
- perlcore: "This ebuild directly depends on a package in perl-core; it should use the corresponding virtual instead."
- syntax: "Syntax error in dependency string (usually an extra/missing space/parenthesis)"
- 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)"
- badslotop: "RDEPEND contains ':=' slot operator under '||' dependency."
- DESCRIPTION:
- missing: "Ebuilds that have a missing or empty DESCRIPTION variable"
- toolong: "DESCRIPTION is over %d characters"
- digest:
- assumed: "Existing digest must be assumed correct (Package level only)"
- missing: "Some files listed in SRC_URI aren't referenced in the Manifest"
- unused: "Some files listed in the Manifest aren't referenced in SRC_URI"
- EAPI:
- definition: "EAPI definition does not conform to PMS section 7.3.1 (first non-comment, non-blank line)"
- deprecated: "Ebuilds that use features that are deprecated in the current EAPI"
- incompatible: "Ebuilds that use features that are only available with a different EAPI"
- unsupported: "Ebuilds that have an unsupported EAPI version (you must upgrade portage)"
- ebuild:
- absdosym: "This ebuild uses absolute target to dosym where relative symlink could be used instead"
- badheader: "This ebuild has a malformed header"
- invalidname: "Ebuild files with a non-parseable or syntactically incorrect name (or using 2.1 versioning extensions)"
- majorsyn: "This ebuild has a major syntax error that may cause the ebuild to fail partially or fully"
- minorsyn: "This ebuild has a minor syntax error that contravenes gentoo coding style"
- namenomatch: "Ebuild files that do not have the same name as their parent directory"
- notadded: "Ebuilds that exist but have not been added to the vcs"
- nesteddie: "Placing 'die' inside ( ) prints an error, but doesn't stop the ebuild."
- output: "A simple sourcing of the ebuild produces output; this breaks ebuild policy."
- patches: "PATCHES variable should be a bash array to ensure white space safety"
- syntax: "Error generating cache entry for ebuild; typically caused by ebuild syntax error or digest verification failure"
- file:
- executable: "Ebuilds, digests, metadata.xml, Manifest, and ChangeLog do not need the executable bit"
- size: "Files in the files directory must be under 20 KiB"
- empty: "Empty file in the files directory"
- name: "File/dir name must be composed of only the following chars: %s "
- UTF8: "File is not UTF8 compliant"
- HOMEPAGE:
- missing: "Ebuilds that have a missing or empty HOMEPAGE variable"
- virtual: "Virtuals that have a non-empty HOMEPAGE variable"
- missingurischeme: "HOMEPAGE is missing an URI scheme"
- inherit:
- deprecated: "Ebuild inherits a deprecated eclass"
- missing: "Ebuild uses functions from an eclass but does not inherit it"
- unused: "Ebuild inherits an eclass but does not use it"
- IUSE:
- invalid: "This ebuild has a variable in IUSE that is not in the use.desc or its metadata.xml file"
- missing: "This ebuild has a USE conditional which references a flag that is not listed in IUSE"
- rubydeprecated: "The ebuild has set a ruby interpreter in USE_RUBY, that is not available as a ruby target anymore"
- java:
- eclassesnotused: "With virtual/jdk in DEPEND you must inherit a java eclass"
- KEYWORDS:
- dropped: "Ebuilds that appear to have dropped KEYWORDS for some arch"
- invalid: "This ebuild contains KEYWORDS that are not listed in profiles/arch.list or for which no valid profile was found"
- missing: "Ebuilds that have a missing or empty KEYWORDS variable"
- stable: "Ebuilds that have been added directly with stable KEYWORDS"
- stupid: "Ebuilds that use KEYWORDS=-* instead of package.mask"
- unsorted: "Ebuilds that contain KEYWORDS which are not sorted alphabetically."
- LICENSE:
- deprecated: "This ebuild is listing a deprecated license."
- invalid: "This ebuild is listing a license that doesnt exist in portages license/ dir."
- missing: "Ebuilds that have a missing or empty LICENSE variable"
- syntax: "Syntax error in LICENSE (usually an extra/missing space/parenthesis)"
- virtual: "Virtuals that have a non-empty LICENSE variable"
- LIVEVCS:
- stable: "This ebuild is a live checkout from a VCS but has stable keywords."
- unmasked: "This ebuild is a live checkout from a VCS but has keywords and is not masked in the global package.mask."
- manifest:
- bad: "Manifest has missing or incorrect digests"
- metadata:
- bad: "Bad metadata.xml files"
- missing: "Missing metadata.xml files"
- warning: "Warnings in metadata.xml files"
- PDEPEND:
- suspect: "PDEPEND contains a package that usually only belongs in DEPEND."
- portage:
- internal: "The ebuild uses an internal Portage function or variable"
- PROPERTIES:
- syntax: "Syntax error in PROPERTIES (usually an extra/missing space/parenthesis)"
- RDEPEND:
- implicit: "RDEPEND is unset in the ebuild which triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4)"
- suspect: "RDEPEND contains a package that usually only belongs in DEPEND."
- repo:
- eapi-banned: "The ebuild uses an EAPI which is banned by the repository's metadata/layout.conf settings"
- eapi-deprecated: "The ebuild uses an EAPI which is deprecated by the repository's metadata/layout.conf settings"
- RESTRICT:
- invalid: "This ebuild contains invalid RESTRICT values."
- syntax: "Syntax error in RESTRICT (usually an extra/missing space/parenthesis)"
- REQUIRED_USE:
- syntax: "Syntax error in REQUIRED_USE (usually an extra/missing space/parenthesis)"
- SLOT:
- invalid: "Ebuilds that have a missing or invalid SLOT variable value"
- SRC_URI:
- syntax: "Syntax error in SRC_URI (usually an extra/missing space/parenthesis)"
- mirror: "A uri listed in profiles/thirdpartymirrors is found in SRC_URI"
- upstream:
- workaround: "The ebuild works around an upstream bug, an upstream bug should be filed and tracked in bugs.gentoo.org"
- uri:
- https: "URI uses http:// but should use https://"
- usage:
- obsolete: "The ebuild makes use of an obsolete construct"
- variable:
- invalidchar: "A variable contains an invalid character that is not part of the ASCII character set"
- phase: "Variable referenced found within scope of incorrect ebuild phase as specified by PMS"
- readonly: "Assigning a readonly variable"
- usedwithhelpers: "Ebuild uses D, ROOT, BROOT, ED, EROOT or EPREFIX with helpers"
- virtual:
- suspect: "Ebuild contains a package that usually should be pulled via virtual/, not directly."
- wxwidgets:
- eclassnotused: "Ebuild DEPENDs on x11-libs/wxGTK without inheriting wxwidgets.eclass"
-
diff --git a/repoman/cnf/repository/linechecks.yaml b/repoman/cnf/repository/linechecks.yaml
deleted file mode 100644
index 528fdd99c42..00000000000
--- a/repoman/cnf/repository/linechecks.yaml
+++ /dev/null
@@ -1,248 +0,0 @@
----
-# linecheck.yaml
-
-# configuration file for the LineCheck plugins run via the multicheck
-# scan module
-# no random drive-by commits please
-# Please obtain authorization from the portage team
-#
-# Overlay maintainers override/add/negate checks at your discression
-# but support for third party module will be limited to the plugin API
-#
-
-# Repoman API version (do not edit)
-version: 1
-# minimum
-repoman_version: 2.3.3
-
-eclass_export_functions:
- - ant-tasks
- - apache-2
- - apache-module
- - aspell-dict
- - autotools-utils
- - base
- - bsdmk
- - cannadic
- - clutter
- - cmake-utils
- - db
- - distutils
- - elisp
- - embassy
- - emboss
- - emul-linux-x86
- - enlightenment
- - font-ebdftopcf
- - font
- - fox
- - freebsd
- - freedict
- - games
- - games-ggz
- - games-mods
- - gdesklets
- - gems
- - gkrellm-plugin
- - gnatbuild
- - gnat
- - gnome2
- - gnome-python-common
- - gnustep-base
- - go-mono
- - gpe
- - gst-plugins-bad
- - gst-plugins-base
- - gst-plugins-good
- - gst-plugins-ugly
- - gtk-sharp-module
- - haskell-cabal
- - horde
- - java-ant-2
- - java-pkg-2
- - java-pkg-simple
- - java-virtuals-2
- - kde4-base
- - kde4-meta
- - kernel-2
- - latex-package
- - linux-mod
- - mozlinguas
- - myspell
- - myspell-r2
- - mysql
- - mysql-v2
- - mythtv-plugins
- - oasis
- - obs-service
- - office-ext
- - perl-app
- - perl-module
- - php-ext-base-r1
- - php-ext-pecl-r2
- - php-ext-source-r2
- - php-lib-r1
- - php-pear-lib-r1
- - php-pear-r1
- - python-distutils-ng
- - python
- - qt4-build
- - qt4-r2
- - rox-0install
- - rox
- - ruby
- - ruby-ng
- - scsh
- - selinux-policy-2
- - sgml-catalog
- - stardict
- - sword-module
- - tetex-3
- - tetex
- - texlive-module
- - toolchain-binutils
- - toolchain
- - twisted
- - vdr-plugin-2
- - vdr-plugin
- - vim
- - vim-plugin
- - vim-spell
- - virtuoso
- - vmware
- - vmware-mod
- - waf-utils
- - webapp
- - xemacs-elisp
- - xemacs-packages
- - xfconf
- - x-modular
- - xorg-2
- - zproduct
-
-eclass_info_experimental_inherit:
- autotools:
- funcs:
- - eaclocal
- - eautoconf
- - eautoheader
- - eautomake
- - eautoreconf
- - _elibtoolize
- - eautopoint
- comprehensive: true
- # Exempt eclasses:
- # git - An EGIT_BOOTSTRAP variable may be used to call one of
- # the autotools functions.
- # subversion - An ESVN_BOOTSTRAP variable may be used to call one of
- # the autotools functions.
- exempt_eclasses:
- - git
- - git-2
- - subversion
- - autotools-utils
- eutils:
- funcs:
- - estack_push
- - estack_pop
- - eshopts_push
- - eshopts_pop
- - eumask_push
- - eumask_pop
- - epatch
- - epatch_user
- - emktemp
- - edos2unix
- - in_iuse
- - use_if_iuse
- - usex
- comprehensive: false
- flag-o-matic:
- funcs:
- - 'filter-(ld)?flags'
- - 'strip-flags'
- - 'strip-unsupported-flags'
- - 'append-((ld|c(pp|xx)?))?flags'
- - 'append-libs'
- comprehensive: false
- libtool:
- funcs:
- - elibtoolize
- comprehensive: true
- exempt_eclasses:
- - autotools
- multilib:
- funcs:
- - get_libdir
- # These are "eclasses are the whole ebuild" type thing.
- exempt_eclasses:
- - autotools
- - libtool
- - multilib-minimal
- comprehensive: false
- multiprocessing:
- funcs:
- - makeopts_jobs
- comprehensive: false
- prefix:
- funcs:
- - eprefixify
- comprehensive: true
- toolchain-funcs:
- funcs:
- - gen_usr_ldscript
- comprehensive: false
- user:
- funcs:
- - enewuser
- - enewgroup
- - egetent
- - egethome
- - egetshell
- - esethome
- comprehensive: true
-
-# non experimental_inherit
-eclass_info:
- autotools:
- funcs:
- - eaclocal
- - eautoconf
- - eautoheader
- - eautomake
- - eautoreconf
- - _elibtoolize
- - eautopoint
- comprehensive: true
- ignore_missing: true
- # Exempt eclasses:
- # git - An EGIT_BOOTSTRAP variable may be used to call one of
- # the autotools functions.
- # subversion - An ESVN_BOOTSTRAP variable may be used to call one of
- # the autotools functions.
- exempt_eclasses:
- - git
- - git-2
- - subversion
- - autotools-utils
- prefix:
- funcs:
- - eprefixify
- comprehensive: true
-
-usex_supported_eapis:
- - "0"
- - "1"
- - "2"
- - "3"
- - "4"
- - "4-slot-abi"
-
-in_iuse_supported_eapis:
- - "0"
- - "1"
- - "2"
- - "3"
- - "4"
- - "4-slot-abi"
- - "5"
diff --git a/repoman/cnf/repository/qa_data.yaml b/repoman/cnf/repository/qa_data.yaml
deleted file mode 100644
index 2249000c3fe..00000000000
--- a/repoman/cnf/repository/qa_data.yaml
+++ /dev/null
@@ -1,163 +0,0 @@
----
-# This yaml syntax file holds various configuration data for
-# the Quality-Assurance checks performed.
-
-# no random drive-by commits please
-# Please obtain authorization from the portage team
-#
-# Overlay maintainers override/add/negate checks at your discression
-# but support for third party module will be limited to the plugin API
-#
-
-# Repoman API version (do not edit)
-version: 1
-# minimum
-repoman_version: 2.3.3
-
-
-allowed_filename_chars: "a-zA-Z0-9._-+:"
-max_description_length: 80
-
-# missingvars check: Mandatory (non-defaulted) ebuild variables
-# list
-missingvars:
- - KEYWORDS
- - LICENSE
- - DESCRIPTION
- - HOMEPAGE
-
-# file.executable check, non executable files
-# list
-no_exec_files:
- - Manifest
- - ChangeLog
- - metadata.xml
-
-# qawarnings: Non-fatal warnings,
-# all values in here MUST have a corresponding qahelp entry
-# list
-qawarnings:
- - changelog.missing
- - changelog.notadded
- - dependency.unknown
- - dependency.badmasked
- - dependency.badindev
- - dependency.badmaskedindev
- - dependency.badtilde
- - dependency.deprecated
- - dependency.equalsversion
- - dependency.missingslot
- - dependency.perlcore
- - DESCRIPTION.toolong
- - digest.assumed
- - digest.unused
- - EAPI.deprecated
- - ebuild.notadded
- - ebuild.nesteddie
- - ebuild.absdosym
- - ebuild.minorsyn
- - ebuild.badheader
- - ebuild.patches
- - file.empty
- - HOMEPAGE.virtual
- - inherit.unused
- - inherit.deprecated
- - IUSE.rubydeprecated
- - java.eclassesnotused
- - KEYWORDS.dropped
- - KEYWORDS.stupid
- - KEYWORDS.missing
- - KEYWORDS.unsorted
- - LICENSE.deprecated
- - LICENSE.virtual
- - metadata.warning
- - PDEPEND.suspect
- - portage.internal
- - RDEPEND.implicit
- - RDEPEND.suspect
- - repo.eapi-deprecated
- - RESTRICT.invalid
- - usage.obsolete
- - upstream.workaround
- - uri.https
- - variable.phase
- - virtual.suspect
- - wxwidgets.eclassnotused
-
-# ruby_deprecated: Deprecated ruby targets
-# list
-ruby_deprecated:
- - ruby_targets_ruby18
- - ruby_targets_ruby19
- - ruby_targets_ruby20
-
-# suspect_rdepend: Common build only Dependencies
-# not usually run time dependencies
-# list
-suspect_rdepend:
- - app-arch/cabextract
- - app-arch/rpm2targz
- - app-doc/doxygen
- - dev-lang/nasm
- - dev-lang/swig
- - dev-lang/yasm
- - dev-perl/extutils-pkgconfig
- - dev-qt/linguist-tools
- - dev-util/byacc
- - dev-util/cmake
- - dev-util/ftjam
- - dev-util/gperf
- - dev-util/gtk-doc
- - dev-util/gtk-doc-am
- - dev-util/intltool
- - dev-util/jam
- - dev-util/pkg-config-lite
- - dev-util/pkgconf
- - dev-util/pkgconfig
- - dev-util/pkgconfig-openbsd
- - dev-util/scons
- - dev-util/unifdef
- - dev-util/yacc
- - media-gfx/ebdftopcf
- - sys-apps/help2man
- - sys-devel/autoconf
- - sys-devel/automake
- - sys-devel/bin86
- - sys-devel/bison
- - sys-devel/dev86
- - sys-devel/flex
- - sys-devel/m4
- - sys-devel/pmake
- - virtual/linux-sources
- - virtual/linuxtv-dvb-headers
- - virtual/os-headers
- - virtual/pkgconfig
- - x11-misc/bdftopcf
- - x11-misc/imake
-
-# suspect_virtual: Dependencies that should usually be made to the virtual
-# Not to the final target library
-# dictionary
-suspect_virtual:
- dev-libs/libusb: virtual/libusb
- dev-libs/libusb-compat: virtual/libusb
- dev-libs/libusbx: virtual/libusb
- dev-util/pkg-config-lite: virtual/pkgconfig
- dev-util/pkgconf: virtual/pkgconfig
- dev-util/pkgconfig: virtual/pkgconfig
- dev-util/pkgconfig-openbsd: virtual/pkgconfig
-
-# valid_restrict: ???
-# list
-valid_restrict:
- - binchecks
- - bindist
- - fetch
- - installsources
- - mirror
- - preserve-libs
- - primaryuri
- - splitdebug
- - strip
- - test
- - userpriv
diff --git a/repoman/cnf/repository/repository.yaml b/repoman/cnf/repository/repository.yaml
deleted file mode 100644
index dbc1decaa76..00000000000
--- a/repoman/cnf/repository/repository.yaml
+++ /dev/null
@@ -1,76 +0,0 @@
----
-# repository-modules.yaml
-#
-# This is the repository configuration file for repoman modules
-#
-# no random drive-by commits please
-# Please obtain authorization from the portage team
-#
-# Overlay maintainers override/add/negate checks at your discression
-# but support for third party module will be limited to the plugin API
-#
-
-# Repoman API version (do not edit)
-version: 1
-# minimum
-repoman_version: 2.3.3
-
-# NOTE: for non-gentoo repos, any custom modules added will need their
-# module names to the modules list in order for them to run.
-
-# These are the non-mandatory modules that can be disabled/enabled.
-# use -foo notation to disable, just like use flags
-# Add custom modules to enable them too
-scan_modules:
- description
- eapi
- ebuild_metadata
- fetches
- files
- keywords
- live
- manifests
- multicheck
- pkgmetadata
- profile
- restrict
- ruby
-
-linechecks_modules:
- assignment
- eapi3assignment
- implicitdepend
- hasq
- useq
- preservelib
- bindnow
- inherit
- dosym
- definition
- srcprepare
- eapi3deprecated
- pkgpretend
- eapi4incompatible
- eapi4gonevars
- paralleldisabled
- autodefault
- gentooheader
- nooffset
- nesteddie
- patches
- emakeparallel
- srccompileeconf
- srcunpackpatches
- pmsvariablerefphasescope
- portageinternal
- portageinternalvariableassignment
- quote
- quoteda
- httpsuri
- builtwith
- uselesscds
- uselessdodoc
- whitespace
- blankline
- noasneeded
-
diff --git a/repoman/lib/repoman/__init__.py b/repoman/lib/repoman/__init__.py
deleted file mode 100644
index b3690c07db9..00000000000
--- a/repoman/lib/repoman/__init__.py
+++ /dev/null
@@ -1,103 +0,0 @@
-import os.path
-import subprocess
-import sys
-import time
-
-try:
- import portage.const
- import portage.proxy as proxy
- from portage import _encodings, _shell_quote, _unicode_encode, _unicode_decode
- from portage.const import PORTAGE_BASE_PATH, BASH_BINARY
-except ImportError as e:
- sys.stderr.write("\n\n")
- sys.stderr.write(
- "!!! Failed to complete portage imports. There are internal modules for\n"
- )
- sys.stderr.write(
- "!!! portage and failure here indicates that you have a problem with your\n"
- )
- sys.stderr.write(
- "!!! installation of portage. Please try a rescue portage located in the ebuild\n"
- )
- sys.stderr.write(
- "!!! repository under '/var/db/repos/gentoo/sys-apps/portage/files/' (default).\n"
- )
- sys.stderr.write(
- "!!! There is a README.RESCUE file that details the steps required to perform\n"
- )
- sys.stderr.write("!!! a recovery of portage.\n")
- sys.stderr.write(" " + str(e) + "\n\n")
- raise
-
-
-VERSION = "HEAD"
-
-REPOMAN_BASE_PATH = os.path.join(
- os.sep, os.sep.join(os.path.realpath(__file__.rstrip("co")).split(os.sep)[:-3])
-)
-
-_not_installed = os.path.isfile(
- os.path.join(REPOMAN_BASE_PATH, ".repoman_not_installed")
-)
-
-if VERSION == "HEAD":
-
- class _LazyVersion(proxy.objectproxy.ObjectProxy):
- def _get_target(self):
- global VERSION
- if VERSION is not self:
- return VERSION
- if os.path.isdir(os.path.join(PORTAGE_BASE_PATH, ".git")):
- encoding = _encodings["fs"]
- cmd = [
- BASH_BINARY,
- "-c",
- (
- "cd %s ; git describe --match 'repoman-*' || exit $? ; "
- + 'if [ -n "`git diff-index --name-only --diff-filter=M HEAD`" ] ; '
- + "then echo modified ; git rev-list --format=%%ct -n 1 HEAD ; fi ; "
- + "exit 0"
- )
- % _shell_quote(PORTAGE_BASE_PATH),
- ]
- cmd = [
- _unicode_encode(x, encoding=encoding, errors="strict") for x in cmd
- ]
- proc = subprocess.Popen(
- cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
- )
- output = _unicode_decode(proc.communicate()[0], encoding=encoding)
- status = proc.wait()
- if os.WIFEXITED(status) and os.WEXITSTATUS(status) == os.EX_OK:
- output_lines = output.splitlines()
- if output_lines:
- version_split = output_lines[0].split("-")
- if len(version_split) > 1:
- VERSION = version_split[1]
- patchlevel = False
- if len(version_split) > 2:
- patchlevel = True
- VERSION = "%s_p%s" % (VERSION, version_split[2])
- if len(output_lines) > 1 and output_lines[1] == "modified":
- head_timestamp = None
- if len(output_lines) > 3:
- try:
- head_timestamp = int(output_lines[3])
- except ValueError:
- pass
- timestamp = int(time.time())
- if (
- head_timestamp is not None
- and timestamp > head_timestamp
- ):
- timestamp = timestamp - head_timestamp
- if not patchlevel:
- VERSION = "%s_p0" % (VERSION,)
- VERSION = "%s_p%d" % (VERSION, timestamp)
- return VERSION
- else:
- print("NO output lines :(")
- VERSION = "HEAD"
- return VERSION
-
- VERSION = _LazyVersion()
diff --git a/repoman/lib/repoman/_portage.py b/repoman/lib/repoman/_portage.py
deleted file mode 100644
index 01a2a4cf525..00000000000
--- a/repoman/lib/repoman/_portage.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""repoman/_portage.py
-Central location for the portage import.
-There were problems when portage was imported by submodules
-due to the portage instance was somehow different that the
-initial portage import in main.py. The later portage imports
-did not contain the repo it was working on. That repo was my cvs tree
-and not listed in those subsequent portage imports.
-
-All modules should import portage from this one
-
-from repoman._portage import portage
-
-Then continue to import the remaining portage modules needed
-"""
-
-import sys
-
-from os import path as osp
-
-pym_path = osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))))
-sys.path.insert(0, pym_path)
-
-import portage
-
-portage._internal_caller = True
-portage._disable_legacy_globals()
diff --git a/repoman/lib/repoman/_subprocess.py b/repoman/lib/repoman/_subprocess.py
deleted file mode 100644
index 08ee9e74848..00000000000
--- a/repoman/lib/repoman/_subprocess.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# -*- coding:utf-8 -*-
-
-
-import codecs
-import subprocess
-
-# import our initialized portage instance
-from repoman._portage import portage
-from portage import _encodings, _unicode_encode
-
-
-def repoman_getstatusoutput(cmd):
- """
- Implements an interface similar to getstatusoutput(), but with
- customized unicode handling (see bug #310789) and without the shell.
- """
- args = portage.util.shlex_split(cmd)
-
- encoding = _encodings["fs"]
- args = [_unicode_encode(x, encoding=encoding, errors="strict") for x in args]
- proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- output = portage._unicode_decode(
- proc.communicate()[0], encoding=encoding, errors="strict"
- )
- if output and output[-1] == "\n":
- # getstatusoutput strips one newline
- output = output[:-1]
- return (proc.wait(), output)
-
-
-class repoman_popen(portage.proxy.objectproxy.ObjectProxy):
- """
- Implements an interface similar to os.popen(), but with customized
- unicode handling (see bug #310789) and without the shell.
- """
-
- __slots__ = ("_proc", "_stdout")
-
- def __init__(self, cmd):
- args = portage.util.shlex_split(cmd)
-
- encoding = _encodings["fs"]
- args = [_unicode_encode(x, encoding=encoding, errors="strict") for x in args]
- proc = subprocess.Popen(args, stdout=subprocess.PIPE)
- object.__setattr__(self, "_proc", proc)
- object.__setattr__(
- self, "_stdout", codecs.getreader(encoding)(proc.stdout, "strict")
- )
-
- def _get_target(self):
- return object.__getattribute__(self, "_stdout")
-
- __enter__ = _get_target
-
- def __exit__(self, exc_type, exc_value, traceback):
- proc = object.__getattribute__(self, "_proc")
- proc.wait()
- proc.stdout.close()
diff --git a/repoman/lib/repoman/actions.py b/repoman/lib/repoman/actions.py
deleted file mode 100644
index 920f0e97a65..00000000000
--- a/repoman/lib/repoman/actions.py
+++ /dev/null
@@ -1,828 +0,0 @@
-# -*- coding:utf-8 -*-
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-import errno
-import io
-import logging
-import platform
-import re
-import shutil
-import signal
-import sys
-import tempfile
-import time
-from itertools import chain
-
-try:
- from urllib.parse import parse_qs, urlsplit, urlunsplit
-except ImportError:
- from urlparse import parse_qs, urlsplit, urlunsplit
-
-from _emerge.UserQuery import UserQuery
-
-from repoman._portage import portage
-from portage import os
-from portage import _encodings
-from portage import _unicode_encode
-from portage.output import bold, create_color_func, green, red
-from portage.package.ebuild.digestgen import digestgen
-from portage.util import writemsg_level
-
-# pylint: disable=ungrouped-imports
-from repoman.copyrights import update_copyright
-from repoman.gpg import gpgsign, need_signature
-from repoman import utilities
-from repoman.modules.vcs.vcs import vcs_files_to_cps
-from repoman import VERSION
-
-bad = create_color_func("BAD")
-
-
-class Actions:
- """Handles post check result output and performs
- the various vcs activities for committing the results"""
-
- def __init__(self, repo_settings, options, scanner, vcs_settings):
- self.repo_settings = repo_settings
- self.options = options
- self.scanner = scanner
- self.vcs_settings = vcs_settings
- self.repoman_settings = repo_settings.repoman_settings
- self.suggest = {
- "ignore_masked": False,
- "include_dev": False,
- }
- if scanner.have["pmasked"] and not (
- options.without_mask or options.ignore_masked
- ):
- self.suggest["ignore_masked"] = True
- if scanner.have["dev_keywords"] and not options.include_dev:
- self.suggest["include_dev"] = True
-
- def inform(self, can_force, result):
- """Inform the user of all the problems found"""
- if (
- self.suggest["ignore_masked"] or self.suggest["include_dev"]
- ) and not self.options.quiet:
- self._suggest()
- if self.options.mode != "commit":
- self._non_commit(result)
- return False
- else:
- self._fail(result, can_force)
- if self.options.pretend:
- utilities.repoman_sez('"So, you want to play it safe. Good call."\n')
- return True
-
- def perform(self, qa_output):
- myautoadd = self._vcs_autoadd()
-
- self._vcs_deleted()
-
- changes = self.get_vcs_changed()
-
- mynew, mychanged, myremoved, no_expansion, expansion = changes
-
- # Manifests need to be regenerated after all other commits, so don't commit
- # them now even if they have changed.
- mymanifests = set()
- myupdates = set()
- for f in mychanged + mynew:
- if "Manifest" == os.path.basename(f):
- mymanifests.add(f)
- else:
- myupdates.add(f)
- myupdates.difference_update(myremoved)
- myupdates = list(myupdates)
- mymanifests = list(mymanifests)
- myheaders = []
-
- commitmessage = self.options.commitmsg
- if self.options.commitmsgfile:
- try:
- f = io.open(
- _unicode_encode(
- self.options.commitmsgfile,
- encoding=_encodings["fs"],
- errors="strict",
- ),
- mode="r",
- encoding=_encodings["content"],
- errors="replace",
- )
- commitmessage = f.read()
- f.close()
- del f
- except (IOError, OSError) as e:
- if e.errno == errno.ENOENT:
- portage.writemsg(
- "!!! File Not Found:"
- " --commitmsgfile='%s'\n" % self.options.commitmsgfile
- )
- else:
- raise
- if commitmessage[:9].lower() in ("cat/pkg: ",):
- commitmessage = self.msg_prefix() + commitmessage[9:]
-
- if commitmessage is not None and commitmessage.strip():
- res, expl = self.verify_commit_message(commitmessage)
- if not res:
- print(bad("RepoMan does not like your commit message:"))
- print(expl)
- if self.options.force:
- print("(but proceeding due to --force)")
- else:
- sys.exit(1)
- else:
- commitmessage = None
- msg_qa_output = qa_output
- initial_message = None
- while True:
- commitmessage = self.get_new_commit_message(
- msg_qa_output, commitmessage
- )
- res, expl = self.verify_commit_message(commitmessage)
- if res:
- break
- else:
- full_expl = (
- """Issues with the commit message were found. Please fix it or remove
-the whole commit message to abort.
-
-"""
- + expl
- )
- msg_qa_output = [
- " %s\n" % x for x in full_expl.splitlines()
- ] + qa_output
-
- commitmessage = commitmessage.rstrip()
-
- # Update copyright for new and changed files
- year = time.strftime("%Y", time.gmtime())
- updated_copyright = []
- for fn in chain(mynew, mychanged):
- if fn.endswith(".diff") or fn.endswith(".patch"):
- continue
- if update_copyright(fn, year, pretend=self.options.pretend):
- updated_copyright.append(fn)
-
- if updated_copyright and not (
- self.options.pretend or self.repo_settings.repo_config.thin_manifest
- ):
- for cp in sorted(self._vcs_files_to_cps(iter(updated_copyright))):
- self._manifest_gen(cp)
-
- myupdates, broken_changelog_manifests = self.changelogs(
- myupdates,
- mymanifests,
- myremoved,
- mychanged,
- myautoadd,
- mynew,
- commitmessage,
- )
-
- lines = commitmessage.splitlines()
- lastline = lines[-1]
- if len(lines) == 1 or re.match(r"^\S+:\s", lastline) is None:
- commitmessage += "\n"
-
- commit_footer = self.get_commit_footer()
- commitmessage += commit_footer
-
- print("* %s files being committed..." % green(str(len(myupdates))), end=" ")
-
- if not self.vcs_settings.needs_keyword_expansion:
- # With some VCS types there's never any keyword expansion, so
- # there's no need to regenerate manifests and all files will be
- # committed in one big commit at the end.
- logging.debug("VCS type doesn't need keyword expansion")
- print()
- elif not self.repo_settings.repo_config.thin_manifest:
- logging.debug("perform: Calling thick_manifest()")
- self.vcs_settings.changes.thick_manifest(
- myupdates, myheaders, no_expansion, expansion
- )
-
- logging.info("myupdates: %s", myupdates)
- logging.info("myheaders: %s", myheaders)
-
- uq = UserQuery(self.options)
- if self.options.ask and uq.query("Commit changes?", True) != "Yes":
- print("* aborting commit.")
- sys.exit(128 + signal.SIGINT)
-
- # Handle the case where committed files have keywords which
- # will change and need a priming commit before the Manifest
- # can be committed.
- if (myupdates or myremoved) and myheaders:
- self.priming_commit(myupdates, myremoved, commitmessage)
-
- # When files are removed and re-added, the cvs server will put /Attic/
- # inside the $Header path. This code detects the problem and corrects it
- # so that the Manifest will generate correctly. See bug #169500.
- # Use binary mode in order to avoid potential character encoding issues.
- self.vcs_settings.changes.clear_attic(myheaders)
-
- if self.scanner.repolevel == 1:
- utilities.repoman_sez(
- "\"You're rather crazy... " 'doing the entire repository."\n'
- )
-
- self.vcs_settings.changes.digest_regen(
- myupdates, myremoved, mymanifests, self.scanner, broken_changelog_manifests
- )
-
- if self.repo_settings.sign_manifests:
- self.sign_manifest(myupdates, myremoved, mymanifests)
-
- self.vcs_settings.changes.update_index(mymanifests, myupdates)
-
- self.add_manifest(mymanifests, myheaders, myupdates, myremoved, commitmessage)
-
- if self.options.quiet:
- return
- print()
- if self.vcs_settings.vcs:
- print("Commit complete.")
- else:
- print(
- "repoman was too scared"
- " by not seeing any familiar version control file"
- " that he forgot to commit anything"
- )
- utilities.repoman_sez('"If everyone were like you, I\'d be out of business!"\n')
- return
-
- def _vcs_files_to_cps(self, vcs_file_iter):
- """
- Iterate over the given modified file paths returned from the vcs,
- and return a frozenset containing category/pn strings for each
- modified package.
-
- @param vcs_file_iter: file paths from vcs module
- @type iter
- @rtype: frozenset
- @return: category/pn strings for each package.
- """
- return vcs_files_to_cps(
- vcs_file_iter,
- self.repo_settings.repodir,
- self.scanner.repolevel,
- self.scanner.reposplit,
- self.scanner.categories,
- )
-
- def _manifest_gen(self, cp):
- """
- Generate manifest for a cp.
-
- @param cp: category/pn string
- @type str
- @rtype: bool
- @return: True if successful, False otherwise
- """
- self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, cp)
- return bool(
- digestgen(
- mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb
- )
- )
-
- def _suggest(self):
- print()
- if self.suggest["ignore_masked"]:
- print(
- bold(
- "Note: use --without-mask to check "
- "KEYWORDS on dependencies of masked packages"
- )
- )
-
- if self.suggest["include_dev"]:
- print(
- bold(
- "Note: use --include-dev (-d) to check "
- "dependencies for 'dev' profiles"
- )
- )
- print()
-
- def _non_commit(self, result):
- if result["full"]:
- print(bold('Note: type "repoman full" for a complete listing.'))
- if result["warn"] and not result["fail"]:
- if self.options.quiet:
- print(bold("Non-Fatal QA errors found"))
- else:
- utilities.repoman_sez(
- "\"You're only giving me a partial QA payment?\n"
- " I'll take it this time, but I'm not happy.\""
- )
- elif not result["fail"]:
- if self.options.quiet:
- print("No QA issues found")
- else:
- utilities.repoman_sez(
- '"If everyone were like you, I\'d be out of business!"'
- )
- elif result["fail"]:
- print(bad("Please fix these important QA issues first."))
- if not self.options.quiet:
- utilities.repoman_sez(
- '"Make your QA payment on time'
- " and you'll never see the likes of me.\"\n"
- )
-
- def _fail(self, result, can_force):
- if (
- result["fail"]
- and can_force
- and self.options.force
- and not self.options.pretend
- ):
- utilities.repoman_sez(
- ' "You want to commit even with these QA issues?\n'
- " I'll take it this time, but I'm not happy.\"\n"
- )
- elif result["fail"]:
- if self.options.force and not can_force:
- print(
- bad(
- "The --force option has been disabled"
- " due to extraordinary issues."
- )
- )
- print(bad("Please fix these important QA issues first."))
- utilities.repoman_sez(
- '"Make your QA payment on time'
- " and you'll never see the likes of me.\"\n"
- )
- sys.exit(1)
-
- def _vcs_autoadd(self):
- myunadded = self.vcs_settings.changes.unadded
- myautoadd = []
- if myunadded:
- for x in range(len(myunadded) - 1, -1, -1):
- xs = myunadded[x].split("/")
- if (
- any(token.startswith(".") and token != "." for token in xs)
- or self.repo_settings.repo_config.find_invalid_path_char(
- myunadded[x]
- )
- != -1
- ):
- # The Manifest excludes this file,
- # so it's safe to ignore.
- del myunadded[x]
- elif xs[-1] == "files":
- print("!!! files dir is not added! Please correct this.")
- sys.exit(-1)
- elif xs[-1] == "Manifest":
- # It's a manifest... auto add
- myautoadd += [myunadded[x]]
- del myunadded[x]
-
- if myunadded:
- print(
- red(
- "!!! The following files are in your local tree"
- " but are not added to the master"
- )
- )
- print(
- red(
- "!!! tree. Please remove them from the local tree"
- " or add them to the master tree."
- )
- )
- for x in myunadded:
- print(" ", x)
- print()
- print()
- sys.exit(1)
- return myautoadd
-
- def _vcs_deleted(self):
- if self.vcs_settings.changes.has_deleted:
- print(
- red(
- "!!! The following files are removed manually"
- " from your local tree but are not"
- )
- )
- print(
- red(
- "!!! removed from the repository."
- ' Please remove them, using "%s remove [FILES]".'
- % self.vcs_settings.vcs
- )
- )
- for x in self.vcs_settings.changes.deleted:
- print(" ", x)
- print()
- print()
- sys.exit(1)
-
- def get_vcs_changed(self):
- """Holding function which calls the approriate VCS module for the data"""
- changes = self.vcs_settings.changes
- # re-run the scan to pick up a newly modified Manifest file
- logging.debug("RE-scanning for changes...")
- changes.scan()
-
- if not changes.has_changes:
- utilities.repoman_sez('"Doing nothing is not always good for QA."')
- print()
- print("(Didn't find any changed files...)")
- print()
- sys.exit(1)
- return (
- changes.new,
- changes.changed,
- changes.removed,
- changes.no_expansion,
- changes.expansion,
- )
-
- https_bugtrackers = frozenset(
- [
- "bitbucket.org",
- "bugs.gentoo.org",
- "github.com",
- "gitlab.com",
- ]
- )
-
- def get_commit_footer(self):
- portage_version = getattr(portage, "VERSION", None)
- gpg_key = self.repoman_settings.get("PORTAGE_GPG_KEY", "")
- signoff = self.repoman_settings.get("SIGNED_OFF_BY", "")
- report_options = []
- if self.options.force:
- report_options.append("--force")
- if self.options.ignore_arches:
- report_options.append("--ignore-arches")
- if self.scanner.include_arches is not None:
- report_options.append(
- '--include-arches="%s"' % " ".join(sorted(self.scanner.include_arches))
- )
- if self.scanner.include_profiles is not None:
- report_options.append(
- '--include-profiles="%s"'
- % " ".join(sorted(self.scanner.include_profiles))
- )
-
- if portage_version is None:
- sys.stderr.write("Failed to insert portage version in message!\n")
- sys.stderr.flush()
- portage_version = "Unknown"
-
- # Common part of commit footer
- commit_footer = ""
- for tag, bug in chain(
- (("Bug", x) for x in self.options.bug),
- (("Closes", x) for x in self.options.closes),
- ):
- # case 1: pure number NNNNNN
- if bug.isdigit():
- bug = "https://bugs.gentoo.org/%s" % (bug,)
- else:
- purl = urlsplit(bug)
- qs = parse_qs(purl.query)
- # case 2: long Gentoo bugzilla URL to shorten
- if (
- purl.netloc == "bugs.gentoo.org"
- and purl.path == "/show_bug.cgi"
- and tuple(qs.keys()) == ("id",)
- ):
- bug = urlunsplit(
- ("https", purl.netloc, qs["id"][-1], "", purl.fragment)
- )
- # case 3: bug tracker w/ http -> https
- elif purl.scheme == "http" and purl.netloc in self.https_bugtrackers:
- bug = urlunsplit(("https",) + purl[1:])
- commit_footer += "\n%s: %s" % (tag, bug)
-
- # Use new footer only for git (see bug #438364).
- if self.vcs_settings.vcs in ["git"]:
- commit_footer += "\nPackage-Manager: Portage-%s, Repoman-%s" % (
- portage.VERSION,
- VERSION,
- )
- if report_options:
- commit_footer += "\nRepoMan-Options: " + " ".join(report_options)
- if self.repo_settings.sign_manifests:
- commit_footer += "\nManifest-Sign-Key: %s" % (gpg_key,)
- else:
- unameout = platform.system() + " "
- if platform.system() in ["Darwin", "SunOS"]:
- unameout += platform.processor()
- else:
- unameout += platform.machine()
- commit_footer += "\n(Portage version: %s/%s/%s" % (
- portage_version,
- self.vcs_settings.vcs,
- unameout,
- )
- if report_options:
- commit_footer += ", RepoMan options: " + " ".join(report_options)
- if self.repo_settings.sign_manifests:
- commit_footer += ", signed Manifest commit with key %s" % (gpg_key,)
- else:
- commit_footer += ", unsigned Manifest commit"
- commit_footer += ")"
-
- if signoff:
- commit_footer += "\nSigned-off-by: %s" % (signoff,)
-
- return commit_footer
-
- def changelogs(
- self,
- myupdates,
- mymanifests,
- myremoved,
- mychanged,
- myautoadd,
- mynew,
- changelog_msg,
- ):
- broken_changelog_manifests = []
- if self.options.echangelog in ("y", "force"):
- logging.info("checking for unmodified ChangeLog files")
- committer_name = utilities.get_committer_name(env=self.repoman_settings)
- for x in sorted(
- vcs_files_to_cps(
- chain(myupdates, mymanifests, myremoved),
- self.repo_settings.repodir,
- self.scanner.repolevel,
- self.scanner.reposplit,
- self.scanner.categories,
- )
- ):
- catdir, pkgdir = x.split("/")
- checkdir = self.repo_settings.repodir + "/" + x
- checkdir_relative = ""
- if self.scanner.repolevel < 3:
- checkdir_relative = os.path.join(pkgdir, checkdir_relative)
- if self.scanner.repolevel < 2:
- checkdir_relative = os.path.join(catdir, checkdir_relative)
- checkdir_relative = os.path.join(".", checkdir_relative)
-
- changelog_path = os.path.join(checkdir_relative, "ChangeLog")
- changelog_modified = changelog_path in self.scanner.changed.changelogs
- if changelog_modified and self.options.echangelog != "force":
- continue
-
- # get changes for this package
- cdrlen = len(checkdir_relative)
- check_relative = lambda e: e.startswith(checkdir_relative)
- split_relative = lambda e: e[cdrlen:]
- clnew = list(map(split_relative, filter(check_relative, mynew)))
- clremoved = list(map(split_relative, filter(check_relative, myremoved)))
- clchanged = list(map(split_relative, filter(check_relative, mychanged)))
-
- # Skip ChangeLog generation if only the Manifest was modified,
- # as discussed in bug #398009.
- nontrivial_cl_files = set()
- nontrivial_cl_files.update(clnew, clremoved, clchanged)
- nontrivial_cl_files.difference_update(["Manifest"])
- if not nontrivial_cl_files and self.options.echangelog != "force":
- continue
-
- new_changelog = utilities.UpdateChangeLog(
- checkdir_relative,
- committer_name,
- changelog_msg,
- os.path.join(self.repo_settings.repodir, "skel.ChangeLog"),
- catdir,
- pkgdir,
- new=clnew,
- removed=clremoved,
- changed=clchanged,
- pretend=self.options.pretend,
- )
- if new_changelog is None:
- writemsg_level(
- "!!! Updating the ChangeLog failed\n",
- level=logging.ERROR,
- noiselevel=-1,
- )
- sys.exit(1)
-
- # if the ChangeLog was just created, add it to vcs
- if new_changelog:
- myautoadd.append(changelog_path)
- # myautoadd is appended to myupdates below
- else:
- myupdates.append(changelog_path)
-
- if self.options.ask and not self.options.pretend:
- # regenerate Manifest for modified ChangeLog (bug #420735)
- self.repoman_settings["O"] = checkdir
- digestgen(
- mysettings=self.repoman_settings,
- myportdb=self.repo_settings.portdb,
- )
- else:
- broken_changelog_manifests.append(x)
-
- if myautoadd:
- print(">>> Auto-Adding missing Manifest/ChangeLog file(s)...")
- self.vcs_settings.changes.add_items(myautoadd)
- myupdates += myautoadd
- return myupdates, broken_changelog_manifests
-
- def add_manifest(self, mymanifests, myheaders, myupdates, myremoved, commitmessage):
- myfiles = mymanifests[:]
- # If there are no header (SVN/CVS keywords) changes in
- # the files, this Manifest commit must include the
- # other (yet uncommitted) files.
- if not myheaders:
- myfiles += myupdates
- myfiles += myremoved
- myfiles.sort()
-
- commitmessagedir = tempfile.mkdtemp(".repoman.msg")
- commitmessagefile = os.path.join(commitmessagedir, "COMMIT_EDITMSG")
- with open(commitmessagefile, "wb") as mymsg:
- mymsg.write(_unicode_encode(commitmessage))
-
- retval = self.vcs_settings.changes.commit(myfiles, commitmessagefile)
- # cleanup the commit message before possibly exiting
- try:
- shutil.rmtree(commitmessagedir)
- except OSError:
- pass
- if retval != os.EX_OK:
- writemsg_level(
- "!!! Exiting on %s (shell) "
- "error code: %s\n" % (self.vcs_settings.vcs, retval),
- level=logging.ERROR,
- noiselevel=-1,
- )
- sys.exit(retval)
-
- def priming_commit(self, myupdates, myremoved, commitmessage):
- myfiles = myupdates + myremoved
- commitmessagedir = tempfile.mkdtemp(".repoman.msg")
- commitmessagefile = os.path.join(commitmessagedir, "COMMIT_EDITMSG")
- with open(commitmessagefile, "wb") as mymsg:
- mymsg.write(_unicode_encode(commitmessage))
-
- separator = "-" * 78
-
- print()
- print(green("Using commit message:"))
- print(green(separator))
- print(commitmessage)
- print(green(separator))
- print()
-
- # Having a leading ./ prefix on file paths can trigger a bug in
- # the cvs server when committing files to multiple directories,
- # so strip the prefix.
- myfiles = [f.lstrip("./") for f in myfiles]
-
- retval = self.vcs_settings.changes.commit(myfiles, commitmessagefile)
- # cleanup the commit message before possibly exiting
- try:
- shutil.rmtree(commitmessagedir)
- except OSError:
- pass
- if retval != os.EX_OK:
- writemsg_level(
- "!!! Exiting on %s (shell) "
- "error code: %s\n" % (self.vcs_settings.vcs, retval),
- level=logging.ERROR,
- noiselevel=-1,
- )
- sys.exit(retval)
-
- def sign_manifest(self, myupdates, myremoved, mymanifests):
- try:
- for x in sorted(
- vcs_files_to_cps(
- chain(myupdates, myremoved, mymanifests),
- self.scanner.repo_settings.repodir,
- self.scanner.repolevel,
- self.scanner.reposplit,
- self.scanner.categories,
- )
- ):
- self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
- manifest_path = os.path.join(self.repoman_settings["O"], "Manifest")
- if not need_signature(manifest_path):
- continue
- gpgsign(manifest_path, self.repoman_settings, self.options)
- except portage.exception.PortageException as e:
- portage.writemsg("!!! %s\n" % str(e))
- portage.writemsg("!!! Disabled FEATURES='sign'\n")
- self.repo_settings.sign_manifests = False
-
- def msg_prefix(self):
- prefix = ""
- if self.scanner.repolevel > 1:
- prefix = "/".join(self.scanner.reposplit[1:]) + ": "
- return prefix
-
- def get_new_commit_message(self, qa_output, old_message=None):
- msg_prefix = old_message or self.msg_prefix()
- try:
- editor = os.environ.get("EDITOR")
- if editor and utilities.editor_is_executable(editor):
- commitmessage = utilities.get_commit_message_with_editor(
- editor, message=qa_output, prefix=msg_prefix
- )
- else:
- print(
- "EDITOR is unset or invalid. Please set EDITOR to your preferred editor."
- )
- print(bad("* no EDITOR found for commit message, aborting commit."))
- sys.exit(1)
- except KeyboardInterrupt:
- logging.fatal("Interrupted; exiting...")
- sys.exit(1)
- if (
- not commitmessage
- or not commitmessage.strip()
- or commitmessage.strip() == msg_prefix
- ):
- print("* no commit message? aborting commit.")
- sys.exit(1)
- return commitmessage
-
- @staticmethod
- def verify_commit_message(msg):
- """
- Check whether the message roughly complies with GLEP66. Returns
- (True, None) if it does, (False, <explanation>) if it does not.
- """
-
- problems = []
- paras = msg.strip().split("\n\n")
- summary = paras.pop(0)
-
- if ":" not in summary:
- problems.append(
- 'summary line must start with a logical unit name, e.g. "cat/pkg:"'
- )
- if "\n" in summary.strip():
- problems.append(
- "commit message must start with a *single* line of summary, followed by empty line"
- )
- # accept 69 overall or unit+50, in case of very long package names
- elif len(summary.strip()) > 69 and len(summary.split(":", 1)[-1]) > 50:
- problems.append("summary line is too long (max 69 characters)")
-
- multiple_footers = False
- gentoo_bug_used = False
- bug_closes_without_url = False
- body_too_long = False
-
- footer_re = re.compile(r"^[\w-]+:")
-
- found_footer = False
- for p in paras:
- lines = p.splitlines()
- # if all lines look like footer material, we assume it's footer
- # else, we assume it's body text
- if all(footer_re.match(l) for l in lines if l.strip()):
- # multiple footer-like blocks?
- if found_footer:
- multiple_footers = True
- found_footer = True
- for l in lines:
- if l.startswith("Gentoo-Bug"):
- gentoo_bug_used = True
- elif l.startswith("Bug:") or l.startswith("Closes:"):
- if "http://" not in l and "https://" not in l:
- bug_closes_without_url = True
- else:
- for l in lines:
- # we recommend wrapping at 72 but accept up to 80;
- # do not complain if we have single word (usually
- # it means very long URL)
- if len(l.strip()) > 80 and len(l.split()) > 1:
- body_too_long = True
-
- if multiple_footers:
- problems.append(
- "multiple footer-style blocks found, please combine them into one"
- )
- if gentoo_bug_used:
- problems.append(
- "please replace Gentoo-Bug with GLEP 66-compliant Bug/Closes"
- )
- if bug_closes_without_url:
- problems.append("Bug/Closes footers require full URL")
- if body_too_long:
- problems.append("body lines should be wrapped at 72 (max 80) characters")
-
- if problems:
- return (False, "\n".join("- %s" % x for x in problems))
- return (True, None)
diff --git a/repoman/lib/repoman/argparser.py b/repoman/lib/repoman/argparser.py
deleted file mode 100644
index 019c7381b25..00000000000
--- a/repoman/lib/repoman/argparser.py
+++ /dev/null
@@ -1,388 +0,0 @@
-# repoman: Argument parser
-# Copyright 2007-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains functions used in Repoman to parse CLI arguments."""
-
-import argparse
-import logging
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage import _unicode_decode
-from portage import util
-
-
-def parse_args(argv, repoman_default_opts):
- """Use a customized optionParser to parse command line arguments for repoman
- Args:
- argv - a sequence of command line arguments
- Returns:
- (opts, args), just like a call to parser.parse_args()
- """
-
- argv = portage._decode_argv(argv)
-
- modes = {
- "commit": "Run a scan then commit changes",
- "ci": "Run a scan then commit changes",
- "fix": "Fix simple QA issues (stray digests, missing digests)",
- "full": "Scan directory tree and print all issues (not a summary)",
- "help": "Show this screen",
- "manifest": "Generate a Manifest (fetches files if necessary)",
- "manifest-check": "Check Manifests for missing or incorrect digests",
- "scan": "Scan directory tree for QA issues",
- }
-
- output_choices = {
- "default": "The normal output format",
- "column": "Columnar output suitable for use with grep",
- }
-
- mode_keys = list(modes)
- mode_keys.sort()
-
- output_keys = sorted(output_choices)
-
- parser = argparse.ArgumentParser(
- usage="repoman [options] [mode]",
- description="Modes: %s" % " | ".join(mode_keys),
- epilog="For more help consult the man page.",
- )
-
- parser.add_argument(
- "-a",
- "--ask",
- dest="ask",
- action="store_true",
- default=False,
- help="Request a confirmation before commiting",
- )
-
- parser.add_argument(
- "-b",
- "--bug",
- dest="bug",
- action="append",
- metavar="<BUG-NO|BUG-URL>",
- default=[],
- help=(
- "Mention a Gentoo or upstream bug in the commit footer; "
- "takes either Gentoo bug number or full bug URL"
- ),
- )
-
- parser.add_argument(
- "-c",
- "--closes",
- dest="closes",
- action="append",
- metavar="<PR-NO|PR-URL>",
- default=[],
- help=(
- "Adds a Closes footer to close GitHub pull request (or compatible); "
- "takes either GitHub PR number or full PR URL"
- ),
- )
-
- parser.add_argument(
- "-m",
- "--commitmsg",
- dest="commitmsg",
- help="specify a commit message on the command line",
- )
-
- parser.add_argument(
- "-M",
- "--commitmsgfile",
- dest="commitmsgfile",
- help="specify a path to a file that contains a commit message",
- )
-
- parser.add_argument(
- "--digest",
- choices=("y", "n"),
- metavar="<y|n>",
- help="Automatically update Manifest digests for modified files",
- )
-
- parser.add_argument(
- "-p",
- "--pretend",
- dest="pretend",
- default=False,
- action="store_true",
- help="don't commit or fix anything; just show what would be done",
- )
-
- parser.add_argument(
- "-q",
- "--quiet",
- dest="quiet",
- action="count",
- default=0,
- help="do not print unnecessary messages",
- )
-
- parser.add_argument(
- "--echangelog",
- choices=("y", "n", "force"),
- metavar="<y|n|force>",
- help=(
- "for commit mode, call echangelog if ChangeLog is unmodified (or "
- "regardless of modification if 'force' is specified)"
- ),
- )
-
- parser.add_argument(
- "--experimental-inherit",
- choices=("y", "n"),
- metavar="<y|n>",
- default="n",
- help=(
- "Enable experimental inherit.missing checks which may misbehave"
- " when the internal eclass database becomes outdated"
- ),
- )
-
- parser.add_argument(
- "--experimental-repository-modules",
- choices=("y", "n"),
- metavar="<y|n>",
- default="n",
- help="Enable experimental repository modules",
- )
-
- parser.add_argument(
- "-f",
- "--force",
- dest="force",
- action="store_true",
- default=False,
- help="Commit with QA violations",
- )
-
- parser.add_argument(
- "-S",
- "--straight-to-stable",
- dest="straight_to_stable",
- default=False,
- action="store_true",
- help="Allow committing straight to stable",
- )
-
- parser.add_argument(
- "--vcs", dest="vcs", help="Force using specific VCS instead of autodetection"
- )
-
- parser.add_argument(
- "-v",
- "--verbose",
- dest="verbosity",
- action="count",
- help="be very verbose in output",
- default=0,
- )
-
- parser.add_argument(
- "-V", "--version", dest="version", action="store_true", help="show version info"
- )
-
- parser.add_argument(
- "-x",
- "--xmlparse",
- dest="xml_parse",
- action="store_true",
- default=False,
- help="forces the metadata.xml parse check to be carried out",
- )
-
- parser.add_argument(
- "--if-modified",
- choices=("y", "n"),
- default="n",
- metavar="<y|n>",
- help="only check packages that have uncommitted modifications",
- )
-
- parser.add_argument(
- "-i",
- "--ignore-arches",
- dest="ignore_arches",
- action="store_true",
- default=False,
- help="ignore arch-specific failures (where arch != host)",
- )
-
- parser.add_argument(
- "--ignore-default-opts",
- action="store_true",
- help="do not use the REPOMAN_DEFAULT_OPTS environment variable",
- )
-
- parser.add_argument(
- "-I",
- "--ignore-masked",
- dest="ignore_masked",
- action="store_true",
- default=False,
- help="ignore masked packages (not allowed with commit mode)",
- )
-
- parser.add_argument(
- "--include-arches",
- dest="include_arches",
- metavar="ARCHES",
- action="append",
- help=(
- "A space separated list of arches used to "
- "filter the selection of profiles for dependency checks"
- ),
- )
-
- parser.add_argument(
- "--include-profiles",
- dest="include_profiles",
- metavar="PROFILES",
- action="append",
- help=(
- "A space separated list of profiles used to "
- "define the selection of profiles for dependency checks"
- ),
- )
-
- parser.add_argument(
- "-d",
- "--include-dev",
- dest="include_dev",
- action="store_true",
- default=False,
- help="include dev profiles in dependency checks",
- )
-
- parser.add_argument(
- "-e",
- "--include-exp-profiles",
- choices=("y", "n"),
- metavar="<y|n>",
- default=False,
- help="include exp profiles in dependency checks",
- )
-
- parser.add_argument(
- "--unmatched-removal",
- dest="unmatched_removal",
- action="store_true",
- default=False,
- help=(
- "enable strict checking of package.mask and package.unmask files"
- " for unmatched removal atoms"
- ),
- )
-
- parser.add_argument(
- "--without-mask",
- dest="without_mask",
- action="store_true",
- default=False,
- help=(
- "behave as if no package.mask entries exist"
- " (not allowed with commit mode)"
- ),
- )
-
- parser.add_argument(
- "--output-style",
- dest="output_style",
- choices=output_keys,
- help="select output type",
- default="default",
- )
-
- parser.add_argument(
- "-j",
- "--jobs",
- dest="jobs",
- action="store",
- type=int,
- default=1,
- help="Specifies the number of jobs (processes) to run simultaneously.",
- )
-
- parser.add_argument(
- "-l",
- "--load-average",
- dest="load_average",
- action="store",
- type=float,
- default=None,
- help="Specifies that no new jobs (processes) should be started if there are others "
- "jobs running and the load average is at least load (a floating-point number).",
- )
-
- parser.add_argument(
- "--mode",
- dest="mode",
- choices=mode_keys,
- help="specify which mode repoman will run in (default=full)",
- )
-
- # Modes help is included earlier, in the parser description.
- parser.add_argument(
- "mode_positional",
- nargs="?",
- metavar="mode",
- choices=mode_keys,
- help=argparse.SUPPRESS,
- )
-
- opts = parser.parse_args(argv[1:])
-
- if not opts.ignore_default_opts:
- default_opts = util.shlex_split(repoman_default_opts)
- if default_opts:
- opts = parser.parse_args(default_opts + argv[1:])
-
- args = []
- if opts.mode is not None:
- args.append(opts.mode)
- if opts.mode_positional is not None:
- args.append(opts.mode_positional)
-
- if len(set(args)) > 1:
- parser.error("multiple modes specified: %s" % " ".join(args))
-
- opts.mode = args[0] if args else None
-
- if opts.mode == "help":
- parser.print_help()
- parser.exit()
-
- if not opts.mode:
- opts.mode = "full"
-
- if opts.mode == "ci":
- opts.mode = "commit" # backwards compat shortcut
-
- # Use verbosity and quiet options to appropriately fiddle with the loglevel
- for val in range(opts.verbosity):
- logger = logging.getLogger()
- logger.setLevel(logger.getEffectiveLevel() - 10)
-
- for val in range(opts.quiet):
- logger = logging.getLogger()
- logger.setLevel(logger.getEffectiveLevel() + 10)
-
- if opts.mode == "commit" and opts.commitmsg:
- opts.commitmsg = _unicode_decode(opts.commitmsg)
-
- if opts.mode == "commit" and not (opts.force or opts.pretend):
- if opts.ignore_masked:
- opts.ignore_masked = False
- logging.warn("Commit mode automatically disables --ignore-masked")
- if opts.without_mask:
- opts.without_mask = False
- logging.warn("Commit mode automatically disables --without-mask")
-
- return (opts, args)
diff --git a/repoman/lib/repoman/check_missingslot.py b/repoman/lib/repoman/check_missingslot.py
deleted file mode 100644
index 4d2d7676b3a..00000000000
--- a/repoman/lib/repoman/check_missingslot.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: missing slot check
-# Copyright 2014 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains the check used to find missing slot values
-in dependencies."""
-
-from portage.eapi import eapi_has_slot_operator
-
-
-def check_missingslot(atom, mytype, eapi, portdb, qatracker, relative_path, my_aux):
- # If no slot or slot operator is specified in RDEP...
- if (
- not atom.blocker
- and not atom.slot
- and not atom.slot_operator
- and mytype == "RDEPEND"
- and eapi_has_slot_operator(eapi)
- ):
- # Check whether it doesn't match more than one.
- atom_matches = portdb.xmatch("match-all", atom)
- dep_slots = frozenset(
- portdb.aux_get(cpv, ["SLOT"])[0].split("/")[0] for cpv in atom_matches
- )
-
- if len(dep_slots) > 1:
- # See if it is a DEPEND as well. It's a very simple & dumb
- # check but should suffice for catching it.
- depend = my_aux["DEPEND"].split()
- if atom not in depend:
- return
-
- qatracker.add_error(
- "dependency.missingslot",
- relative_path
- + ": %s: '%s' matches more than one slot, please specify an explicit slot and/or use the := or :* slot operator"
- % (mytype, atom),
- )
diff --git a/repoman/lib/repoman/checks/__init__.py b/repoman/lib/repoman/checks/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/repoman/lib/repoman/checks/__init__.py
+++ /dev/null
diff --git a/repoman/lib/repoman/config.py b/repoman/lib/repoman/config.py
deleted file mode 100644
index 621143de4f6..00000000000
--- a/repoman/lib/repoman/config.py
+++ /dev/null
@@ -1,172 +0,0 @@
-# -*- coding:utf-8 -*-
-
-import copy
-import itertools
-import json
-import os
-import stat
-
-try:
- import yaml
-except ImportError:
- yaml = None
-
-
-class ConfigError(Exception):
- """Raised when a config file fails to load"""
-
- pass
-
-
-def merge_config(base, head):
- """
- Merge two JSON or YAML documents into a single object. Arrays are
- merged by extension. If dissimilar types are encountered, then the
- head value overwrites the base value.
- """
-
- if isinstance(head, dict):
- if not isinstance(base, dict):
- return copy.deepcopy(head)
-
- result = {}
- for k in itertools.chain(head, base):
- try:
- result[k] = merge_config(base[k], head[k])
- except KeyError:
- try:
- result[k] = copy.deepcopy(head[k])
- except KeyError:
- result[k] = copy.deepcopy(base[k])
-
- elif isinstance(head, list):
- result = []
- if not isinstance(base, list):
- result.extend(copy.deepcopy(x) for x in head)
- else:
- if any(isinstance(x, (dict, list)) for x in itertools.chain(head, base)):
- # merge items with identical indexes
- for x, y in zip(base, head):
- if isinstance(x, (dict, list)):
- result.append(merge_config(x, y))
- else:
- # head overwrites base (preserving index)
- result.append(copy.deepcopy(y))
- # copy remaining items from the longer list
- if len(base) != len(head):
- if len(base) > len(head):
- result.extend(copy.deepcopy(x) for x in base[len(head) :])
- else:
- result.extend(copy.deepcopy(x) for x in head[len(base) :])
- else:
- result.extend(copy.deepcopy(x) for x in base)
- result.extend(copy.deepcopy(x) for x in head)
-
- else:
- result = copy.deepcopy(head)
-
- return result
-
-
-def _yaml_load(filename):
- """
- Load filename as YAML and return a dict. Raise ConfigError if
- it fails to load.
- """
- if yaml is None:
- raise ImportError("Please install pyyaml in order to read yaml files")
-
- with open(filename, "rt") as f:
- try:
- return yaml.safe_load(f)
- except yaml.parser.ParserError as e:
- raise ConfigError("{}: {}".format(filename, e))
-
-
-def _json_load(filename):
- """
- Load filename as JSON and return a dict. Raise ConfigError if
- it fails to load.
- """
- with open(filename, "rt") as f:
- try:
- return json.load(f) # nosec
- except ValueError as e:
- raise ConfigError("{}: {}".format(filename, e))
-
-
-def iter_files(files_dirs):
- """
- Iterate over nested file paths in lexical order.
- """
- stack = list(reversed(files_dirs))
- while stack:
- location = stack.pop()
- try:
- st = os.stat(location)
- except FileNotFoundError:
- continue
-
- if stat.S_ISDIR(st.st_mode):
- stack.extend(
- os.path.join(location, x)
- for x in sorted(os.listdir(location), reverse=True)
- )
-
- elif stat.S_ISREG(st.st_mode):
- yield location
-
-
-def load_config(conf_dirs, file_extensions=None, valid_versions=None):
- """
- Load JSON and/or YAML files from a directories, and merge them together
- into a single object.
-
- @param conf_dirs: ordered iterable of directories to load the config from
- @param file_extensions: Optional list of file extension types to load
- @param valid_versions: list of compatible file versions allowed
- @returns: the stacked config
- """
-
- result = {}
- for filename in iter_files(conf_dirs):
- if file_extensions is not None and not filename.endswith(file_extensions):
- continue
-
- loaders = []
- extension = filename.rsplit(".", 1)[1]
- if extension in ["json"]:
- loaders.append(_json_load)
- elif extension in ["yml", "yaml"]:
- loaders.append(_yaml_load)
-
- config = None
- exception = None
- for loader in loaders:
- try:
- config = loader(filename) or {}
- except ConfigError as e:
- exception = e
- else:
- break
-
- if config is None:
- print("Repoman.config.load_config(), Error loading file: %s" % filename)
- print(" Aborting...")
- raise exception
-
- if config:
- if config["version"] not in valid_versions:
- raise ConfigError(
- "Invalid file version: %s in: %s\nPlease upgrade to "
- ">=app-portage/repoman-%s, current valid API versions: %s"
- % (
- config["version"],
- filename,
- config["repoman_version"],
- valid_versions,
- )
- )
- result = merge_config(result, config)
-
- return result
diff --git a/repoman/lib/repoman/copyrights.py b/repoman/lib/repoman/copyrights.py
deleted file mode 100644
index 199f5efbfe9..00000000000
--- a/repoman/lib/repoman/copyrights.py
+++ /dev/null
@@ -1,143 +0,0 @@
-# -*- coding:utf-8 -*-
-
-
-import difflib
-import io
-import re
-from tempfile import mkstemp
-
-from portage import _encodings
-from portage import _unicode_decode
-from portage import _unicode_encode
-from portage import os
-from portage import shutil
-from portage import util
-
-
-_copyright_re1 = re.compile(
- rb"^(# Copyright \d\d\d\d)-\d\d\d\d( Gentoo (Foundation|Authors))\b"
-)
-_copyright_re2 = re.compile(
- rb"^(# Copyright )(\d\d\d\d)( Gentoo (Foundation|Authors))\b"
-)
-
-
-class _copyright_repl:
- __slots__ = ("year",)
-
- def __init__(self, year):
- self.year = year
-
- def __call__(self, matchobj):
- if matchobj.group(2) == self.year:
- return matchobj.group(0)
- else:
- return (
- matchobj.group(1)
- + matchobj.group(2)
- + b"-"
- + self.year
- + b" Gentoo Authors"
- )
-
-
-def update_copyright_year(year, line):
- """
- These two regexes are taken from echangelog
- update_copyright(), except that we don't hardcode
- 1999 here (in order to be more generic).
- """
- is_bytes = isinstance(line, bytes)
- if is_bytes:
- if not line.startswith(b"# Copyright "):
- return line
- else:
- if not line.startswith("# Copyright "):
- return line
-
- year = _unicode_encode(year)
- line = _unicode_encode(line)
-
- line = _copyright_re1.sub(rb"\1-" + year + b" Gentoo Authors", line)
- line = _copyright_re2.sub(_copyright_repl(year), line)
- if not is_bytes:
- line = _unicode_decode(line)
- return line
-
-
-def update_copyright(fn_path, year, pretend=False):
- """
- Check file for a Copyright statement, and update its year. The
- patterns used for replacing copyrights are taken from echangelog.
- Only the first lines of each file that start with a hash ('#') are
- considered, until a line is found that doesn't start with a hash.
- Files are read and written in binary mode, so that this function
- will work correctly with files encoded in any character set, as
- long as the copyright statements consist of plain ASCII.
-
- @param fn_path: file path
- @type str
- @param year: current year
- @type str
- @param pretend: pretend mode
- @type bool
- @rtype: bool
- @return: True if copyright update was needed, False otherwise
- """
-
- try:
- fn_hdl = io.open(
- _unicode_encode(fn_path, encoding=_encodings["fs"], errors="strict"),
- mode="rb",
- )
- except EnvironmentError:
- return
-
- orig_header = []
- new_header = []
-
- for line in fn_hdl:
- line_strip = line.strip()
- orig_header.append(line)
- if not line_strip or line_strip[:1] != b"#":
- new_header.append(line)
- break
-
- line = update_copyright_year(year, line)
- new_header.append(line)
-
- difflines = 0
- for diffline in difflib.unified_diff(
- [_unicode_decode(diffline) for diffline in orig_header],
- [_unicode_decode(diffline) for diffline in new_header],
- fromfile=fn_path,
- tofile=fn_path,
- n=0,
- ):
- util.writemsg_stdout(diffline, noiselevel=-1)
- difflines += 1
- util.writemsg_stdout("\n", noiselevel=-1)
-
- # unified diff has three lines to start with
- if difflines > 3 and not pretend:
- # write new file with changed header
- f, fnnew_path = mkstemp()
- f = io.open(f, mode="wb")
- for line in new_header:
- f.write(line)
- for line in fn_hdl:
- f.write(line)
- f.close()
- try:
- fn_stat = os.stat(fn_path)
- except OSError:
- fn_stat = None
-
- shutil.move(fnnew_path, fn_path)
-
- if fn_stat is None:
- util.apply_permissions(fn_path, mode=0o644)
- else:
- util.apply_stat_permissions(fn_path, fn_stat)
- fn_hdl.close()
- return difflines > 3
diff --git a/repoman/lib/repoman/errors.py b/repoman/lib/repoman/errors.py
deleted file mode 100644
index c3ee92d37f6..00000000000
--- a/repoman/lib/repoman/errors.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- coding:utf-8 -*-
-
-import sys
-
-
-def warn(txt):
- print("repoman: " + txt)
-
-
-def err(txt):
- warn(txt)
- sys.exit(1)
-
-
-def caterror(catdir, repodir):
- err(
- "%s is not an official category."
- " Skipping QA checks in this directory.\n"
- "Please ensure that you add %s to %s/profiles/categories\n"
- "if it is a new category." % (catdir, catdir, repodir)
- )
diff --git a/repoman/lib/repoman/gpg.py b/repoman/lib/repoman/gpg.py
deleted file mode 100644
index 10e884e52bb..00000000000
--- a/repoman/lib/repoman/gpg.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- coding:utf-8 -*-
-
-import errno
-import logging
-import subprocess
-
-import portage
-from portage import os
-from portage import _encodings
-from portage import _unicode_encode
-from portage.exception import MissingParameter
-
-
-# Setup the GPG commands
-def gpgsign(filename, repoman_settings, options):
- gpgcmd = repoman_settings.get("PORTAGE_GPG_SIGNING_COMMAND")
- if gpgcmd in [None, ""]:
- raise MissingParameter(
- "PORTAGE_GPG_SIGNING_COMMAND is unset!" " Is make.globals missing?"
- )
- if "${PORTAGE_GPG_KEY}" in gpgcmd and "PORTAGE_GPG_KEY" not in repoman_settings:
- raise MissingParameter("PORTAGE_GPG_KEY is unset!")
- if "${PORTAGE_GPG_DIR}" in gpgcmd:
- if "PORTAGE_GPG_DIR" not in repoman_settings:
- repoman_settings["PORTAGE_GPG_DIR"] = os.path.expanduser("~/.gnupg")
- logging.info(
- "Automatically setting PORTAGE_GPG_DIR to '%s'"
- % repoman_settings["PORTAGE_GPG_DIR"]
- )
- else:
- repoman_settings["PORTAGE_GPG_DIR"] = os.path.expanduser(
- repoman_settings["PORTAGE_GPG_DIR"]
- )
- if not os.access(repoman_settings["PORTAGE_GPG_DIR"], os.X_OK):
- raise portage.exception.InvalidLocation(
- "Unable to access directory: PORTAGE_GPG_DIR='%s'"
- % repoman_settings["PORTAGE_GPG_DIR"]
- )
- gpgvars = {"FILE": filename}
- for k in ("PORTAGE_GPG_DIR", "PORTAGE_GPG_KEY"):
- v = repoman_settings.get(k)
- if v is not None:
- gpgvars[k] = v
- gpgcmd = portage.util.varexpand(gpgcmd, mydict=gpgvars)
- if options.pretend:
- print("(" + gpgcmd + ")")
- else:
- # Encode unicode manually for bug #310789.
- gpgcmd = portage.util.shlex_split(gpgcmd)
-
- gpgcmd = [
- _unicode_encode(arg, encoding=_encodings["fs"], errors="strict")
- for arg in gpgcmd
- ]
- rValue = subprocess.call(gpgcmd)
- if rValue == os.EX_OK:
- os.rename(filename + ".asc", filename)
- else:
- raise portage.exception.PortageException(
- "!!! gpg exited with '" + str(rValue) + "' status"
- )
-
-
-def need_signature(filename):
- try:
- with open(
- _unicode_encode(filename, encoding=_encodings["fs"], errors="strict"), "rb"
- ) as f:
- return b"BEGIN PGP SIGNED MESSAGE" not in f.readline()
- except IOError as e:
- if e.errno in (errno.ENOENT, errno.ESTALE):
- return False
- raise
diff --git a/repoman/lib/repoman/main.py b/repoman/lib/repoman/main.py
deleted file mode 100755
index 1cfe86e8d55..00000000000
--- a/repoman/lib/repoman/main.py
+++ /dev/null
@@ -1,255 +0,0 @@
-#!/usr/bin/env python
-# -*- coding:utf-8 -*-
-# Copyright 1999-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-import collections
-import io
-import logging
-import sys
-
-# import our centrally initialized portage instance
-from repoman._portage import portage
-
-portage._internal_caller = True
-portage._disable_legacy_globals()
-
-
-from portage import os
-import portage.checksum
-import portage.const
-import portage.repository.config
-from portage.output import create_color_func, nocolor
-from portage.output import ConsoleStyleFile, StyleWriter
-from portage.util import formatter
-from portage.util.futures.extendedfutures import (
- ExtendedFuture,
-)
-
-# pylint: disable=ungrouped-imports
-from repoman.actions import Actions
-from repoman.argparser import parse_args
-from repoman.qa_data import QAData
-from repoman.qa_data import format_qa_output, format_qa_output_column
-from repoman.repos import RepoSettings
-from repoman.scanner import Scanner
-from repoman import utilities
-from repoman.modules.vcs.settings import VCSSettings
-from repoman import VERSION
-
-
-bad = create_color_func("BAD")
-
-# A sane umask is needed for files that portage creates.
-os.umask(0o22)
-
-LOGLEVEL = logging.WARNING
-portage.util.initialize_logger(LOGLEVEL)
-
-VALID_VERSIONS = [
- 1,
-]
-
-_repoman_main_vars = collections.namedtuple(
- "_repoman_main_vars",
- (
- "can_force",
- "exitcode",
- "options",
- "qadata",
- "repo_settings",
- "scanner",
- "vcs_settings",
- ),
-)
-
-
-def repoman_main(argv):
- repoman_vars = _repoman_init(argv)
- if repoman_vars.exitcode is not None:
- return repoman_vars.exitcode
- result = _repoman_scan(*repoman_vars)
- return _handle_result(*repoman_vars, result)
-
-
-def _repoman_init(argv):
- config_root = os.environ.get("PORTAGE_CONFIGROOT")
- repoman_settings = portage.config(config_root=config_root, local_config=False)
- repoman_settings.valid_versions = VALID_VERSIONS
-
- if (
- repoman_settings.get("NOCOLOR", "").lower() in ("yes", "true")
- or repoman_settings.get("TERM") == "dumb"
- or not sys.stdout.isatty()
- ):
- nocolor()
-
- options, arguments = parse_args(
- argv, repoman_settings.get("REPOMAN_DEFAULT_OPTS", "")
- )
-
- if options.version:
- print("Repoman", VERSION, "(portage-%s)" % portage.VERSION)
- return _repoman_main_vars(None, 0, None, None, None, None, None)
-
- logger = logging.getLogger()
-
- if options.verbosity > 0:
- logger.setLevel(LOGLEVEL - 10 * options.verbosity)
- else:
- logger.setLevel(LOGLEVEL)
-
- # Set this to False when an extraordinary issue (generally
- # something other than a QA issue) makes it impossible to
- # commit (like if Manifest generation fails).
- can_force = ExtendedFuture(True)
- repo_settings, vcs_settings, scanner, qadata = _create_scanner(
- options, can_force, config_root, repoman_settings
- )
- return _repoman_main_vars(
- can_force, None, options, qadata, repo_settings, scanner, vcs_settings
- )
-
-
-def _create_scanner(options, can_force, config_root, repoman_settings):
-
- portdir, portdir_overlay, mydir = utilities.FindPortdir(repoman_settings)
- if portdir is None:
- return (None, None, None, None)
-
- myreporoot = os.path.basename(portdir_overlay)
- myreporoot += mydir[len(portdir_overlay) :]
-
- # avoid a circular parameter repo_settings
- vcs_settings = VCSSettings(options, repoman_settings)
- qadata = QAData()
-
- logging.debug("repoman_main: RepoSettings init")
- repo_settings = RepoSettings(
- config_root,
- portdir,
- portdir_overlay,
- repoman_settings,
- vcs_settings,
- options,
- qadata,
- )
- repoman_settings = repo_settings.repoman_settings
- repoman_settings.valid_versions = VALID_VERSIONS
-
- # Now set repo_settings
- vcs_settings.repo_settings = repo_settings
- # set QATracker qacats, qawarnings
- vcs_settings.qatracker.qacats = repo_settings.qadata.qacats
- vcs_settings.qatracker.qawarnings = repo_settings.qadata.qawarnings
- logging.debug("repoman_main: vcs_settings done")
- logging.debug("repoman_main: qadata: %s", repo_settings.qadata)
-
- if "digest" in repoman_settings.features and options.digest != "n":
- options.digest = "y"
-
- logging.debug("vcs: %s" % (vcs_settings.vcs,))
- logging.debug("repo config: %s" % (repo_settings.repo_config,))
- logging.debug("options: %s" % (options,))
-
- # It's confusing if these warnings are displayed without the user
- # being told which profile they come from, so disable them.
- env = os.environ.copy()
- env["FEATURES"] = env.get("FEATURES", "") + " -unknown-features-warn"
-
- # Perform the main checks
- scanner = Scanner(
- repo_settings, myreporoot, config_root, options, vcs_settings, mydir, env
- )
- return repo_settings, vcs_settings, scanner, qadata
-
-
-def _repoman_scan(
- can_force, exitcode, options, qadata, repo_settings, scanner, vcs_settings
-):
- scanner.scan_pkgs(can_force)
-
- if options.if_modified == "y" and len(scanner.effective_scanlist) < 1:
- logging.warning(
- "--if-modified is enabled, but no modified packages were found!"
- )
-
- result = {
- # fail will be true if we have failed in at least one non-warning category
- "fail": 0,
- # warn will be true if we tripped any warnings
- "warn": 0,
- # full will be true if we should print a "repoman full" informational message
- "full": options.mode != "full",
- }
-
- for x in qadata.qacats:
- if x not in vcs_settings.qatracker.fails:
- continue
- result["warn"] = 1
- if x not in qadata.qawarnings:
- result["fail"] = 1
-
- if result["fail"] or (
- result["warn"] and not (options.quiet or options.mode == "scan")
- ):
- result["full"] = 0
-
- return result
-
-
-def _handle_result(
- can_force, exitcode, options, qadata, repo_settings, scanner, vcs_settings, result
-):
- commitmessage = None
- if options.commitmsg:
- commitmessage = options.commitmsg
- elif options.commitmsgfile:
- # we don't need the actual text of the commit message here
- # the filename will do for the next code block
- commitmessage = options.commitmsgfile
-
- # Save QA output so that it can be conveniently displayed
- # in $EDITOR while the user creates a commit message.
- # Otherwise, the user would not be able to see this output
- # once the editor has taken over the screen.
- qa_output = io.StringIO()
- style_file = ConsoleStyleFile(sys.stdout)
- if options.mode == "commit" and (not commitmessage or not commitmessage.strip()):
- style_file.write_listener = qa_output
- console_writer = StyleWriter(file=style_file, maxcol=9999)
- console_writer.style_listener = style_file.new_styles
-
- f = formatter.AbstractFormatter(console_writer)
-
- format_outputs = {"column": format_qa_output_column, "default": format_qa_output}
-
- format_output = format_outputs.get(options.output_style, format_outputs["default"])
- format_output(
- f,
- vcs_settings.qatracker.fails,
- result["full"],
- result["fail"],
- options,
- qadata.qawarnings,
- )
-
- style_file.flush()
- del console_writer, f, style_file
-
- # early out for manifest generation
- if options.mode == "manifest":
- return 1 if result["fail"] else 0
-
- qa_output = qa_output.getvalue()
- qa_output = qa_output.splitlines(True)
-
- # output the results
- actions = Actions(repo_settings, options, scanner, vcs_settings)
- if actions.inform(can_force.get(), result):
- # perform any other actions
- actions.perform(qa_output)
- elif result["fail"]:
- return 1
-
- return 0
diff --git a/repoman/lib/repoman/metadata.py b/repoman/lib/repoman/metadata.py
deleted file mode 100644
index 5dc44b11947..00000000000
--- a/repoman/lib/repoman/metadata.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# -*- coding:utf-8 -*-
-
-import errno
-import logging
-import time
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage import os
-from portage.output import green
-from portage.package.ebuild.fetch import fetch
-
-
-# Note: This URI is hardcoded in all metadata.xml files. We can't
-# change it without updating all the xml files in the tree.
-metadata_dtd_uri = "https://www.gentoo.org/dtd/metadata.dtd"
-metadata_xsd_uri = "https://www.gentoo.org/xml-schema/metadata.xsd"
-# force refetch if the local copy creation time is older than this
-metadata_xsd_ctime_interval = 60 * 60 * 24 * 7 # 7 days
-
-
-def fetch_metadata_xsd(metadata_xsd, repoman_settings):
- """
- Fetch metadata.xsd if it doesn't exist or the ctime is older than
- metadata_xsd_ctime_interval.
- @rtype: bool
- @return: True if successful, otherwise False
- """
-
- must_fetch = True
- metadata_xsd_st = None
- current_time = int(time.time())
- try:
- metadata_xsd_st = os.stat(metadata_xsd)
- except EnvironmentError as e:
- if e.errno not in (errno.ENOENT, errno.ESTALE):
- raise
- del e
- else:
- # Trigger fetch if metadata.xsd mtime is old or clock is wrong.
- if abs(current_time - metadata_xsd_st.st_ctime) < metadata_xsd_ctime_interval:
- must_fetch = False
-
- if must_fetch:
- print()
- print(
- "%s the local copy of metadata.xsd "
- "needs to be refetched, doing that now" % green("***")
- )
- print()
-
- if not fetch([metadata_xsd_uri], repoman_settings, force=1, try_mirrors=0):
- logging.error("failed to fetch metadata.xsd from '%s'" % metadata_xsd_uri)
- return False
-
- try:
- portage.util.apply_secpass_permissions(
- metadata_xsd, gid=portage.data.portage_gid, mode=0o664, mask=0o2
- )
- except portage.exception.PortageException:
- pass
-
- return True
-
-
-def get_metadata_xsd(repo_settings):
- """Locate and or fetch the metadata.xsd file
-
- @param repo_settings: RepoSettings instance
- @returns: path to the metadata.xsd file
- """
- metadata_xsd = None
- paths = list(repo_settings.repo_config.eclass_db.porttrees)
- paths.reverse()
- # add the test copy
- paths.append("/usr/lib/portage/cnf/")
- for path in paths:
- path = os.path.join(path, "metadata/xml-schema/metadata.xsd")
- if os.path.exists(path):
- metadata_xsd = path
- break
- if metadata_xsd is None:
- metadata_xsd = os.path.join(
- repo_settings.repoman_settings["DISTDIR"], "metadata.xsd"
- )
-
- fetch_metadata_xsd(metadata_xsd, repo_settings.repoman_settings)
- return metadata_xsd
diff --git a/repoman/lib/repoman/modules/__init__.py b/repoman/lib/repoman/modules/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/repoman/lib/repoman/modules/__init__.py
+++ /dev/null
diff --git a/repoman/lib/repoman/modules/commit/__init__.py b/repoman/lib/repoman/modules/commit/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/repoman/lib/repoman/modules/commit/__init__.py
+++ /dev/null
diff --git a/repoman/lib/repoman/modules/commit/manifest.py b/repoman/lib/repoman/modules/commit/manifest.py
deleted file mode 100644
index e282ad40694..00000000000
--- a/repoman/lib/repoman/modules/commit/manifest.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# -*- coding:utf-8 -*-
-
-import logging
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage import os
-from portage.package.ebuild.digestgen import digestgen
-from portage.util import writemsg_level
-
-
-class Manifest:
- """Creates as well as checks pkg Manifest entries/files"""
-
- def __init__(self, **kwargs):
- """Class init
-
- @param options: the run time cli options
- @param portdb: portdb instance
- @param repo_settings: repository settings instance
- """
- self.options = kwargs.get("options")
- self.portdb = kwargs.get("portdb")
- self.repoman_settings = kwargs.get("repo_settings").repoman_settings
- self.generated_manifest = False
-
- def update_manifest(self, checkdir):
- """Perform a manifest generation for the pkg
-
- @param checkdir: the current package directory
- @rtype: bool
- @return: True if successful, False otherwise
- """
- self.generated_manifest = False
- failed = False
- self.auto_assumed = set()
- fetchlist_dict = portage.FetchlistDict(
- checkdir, self.repoman_settings, self.portdb
- )
- if self.options.mode == "manifest" and self.options.force:
- self._discard_dist_digests(checkdir, fetchlist_dict)
- self.repoman_settings["O"] = checkdir
- try:
- self.generated_manifest = digestgen(
- mysettings=self.repoman_settings, myportdb=self.portdb
- )
- except portage.exception.PermissionDenied as e:
- self.generated_manifest = False
- writemsg_level(
- "!!! Permission denied: '%s'\n" % (e,),
- level=logging.ERROR,
- noiselevel=-1,
- )
-
- if not self.generated_manifest:
- writemsg_level(
- "!!! Unable to generate manifest for '%s'.\n" % (checkdir,),
- level=logging.ERROR,
- noiselevel=-1,
- )
- failed = True
-
- if self.options.mode == "manifest":
- if (
- not failed
- and self.options.force
- and self.auto_assumed
- and "assume-digests" in self.repoman_settings.features
- ):
- # Show which digests were assumed despite the --force option
- # being given. This output will already have been shown by
- # digestgen() if assume-digests is not enabled, so only show
- # it here if assume-digests is enabled.
- pkgs = list(fetchlist_dict)
- pkgs.sort()
- portage.writemsg_stdout(
- " digest.assumed %s"
- % portage.output.colorize(
- "WARN", str(len(self.auto_assumed)).rjust(18)
- )
- + "\n"
- )
- for cpv in pkgs:
- fetchmap = fetchlist_dict[cpv]
- pf = portage.catsplit(cpv)[1]
- for distfile in sorted(fetchmap):
- if distfile in self.auto_assumed:
- portage.writemsg_stdout(" %s::%s\n" % (pf, distfile))
- return not failed
-
- def _discard_dist_digests(self, checkdir, fetchlist_dict):
- """Discard DIST digests for files that exist in DISTDIR
-
- This method is intended to be called prior to digestgen, only for
- manifest mode with the --force option, in order to discard DIST
- digests that we intend to update. This is necessary because
- digestgen never replaces existing digests, since otherwise it
- would be too easy for ebuild developers to accidentally corrupt
- existing DIST digests.
-
- @param checkdir: the directory to generate the Manifest in
- @param fetchlist_dict: dictionary of files to fetch and/or include
- in the manifest
- """
- portage._doebuild_manifest_exempt_depend += 1
- try:
- distdir = self.repoman_settings["DISTDIR"]
- mf = self.repoman_settings.repositories.get_repo_for_location(
- os.path.dirname(os.path.dirname(checkdir))
- )
- mf = mf.load_manifest(checkdir, distdir, fetchlist_dict=fetchlist_dict)
- mf.create(requiredDistfiles=None, assumeDistHashesAlways=True)
- for distfiles in fetchlist_dict.values():
- for distfile in distfiles:
- if os.path.isfile(os.path.join(distdir, distfile)):
- mf.fhashdict["DIST"].pop(distfile, None)
- else:
- self.auto_assumed.add(distfile)
- mf.write()
- finally:
- portage._doebuild_manifest_exempt_depend -= 1
diff --git a/repoman/lib/repoman/modules/commit/repochecks.py b/repoman/lib/repoman/modules/commit/repochecks.py
deleted file mode 100644
index 32466021e05..00000000000
--- a/repoman/lib/repoman/modules/commit/repochecks.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# -*- coding:utf-8 -*-
-
-from portage.output import red
-
-from repoman.errors import err
-
-
-def commit_check(repolevel, reposplit):
- # Check if it's in $PORTDIR/$CATEGORY/$PN , otherwise bail if commiting.
- # Reason for this is if they're trying to commit in just $FILESDIR/*,
- # the Manifest needs updating.
- # This check ensures that repoman knows where it is,
- # and the manifest recommit is at least possible.
- if repolevel not in [1, 2, 3]:
- print(
- red("***")
- + (
- " Commit attempts *must* be from within a vcs checkout,"
- " category, or package directory."
- )
- )
- print(
- red("***")
- + (
- " Attempting to commit from a packages files directory"
- " will be blocked for instance."
- )
- )
- print(
- red("***")
- + (
- " This is intended behaviour,"
- " to ensure the manifest is recommitted for a package."
- )
- )
- print(red("***"))
- err(
- "Unable to identify level we're commiting from for %s" % "/".join(reposplit)
- )
-
-
-def conflict_check(vcs_settings, options):
- if vcs_settings.vcs:
- conflicts = vcs_settings.status.detect_conflicts(options)
diff --git a/repoman/lib/repoman/modules/linechecks/__init__.py b/repoman/lib/repoman/modules/linechecks/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/repoman/lib/repoman/modules/linechecks/__init__.py
+++ /dev/null
diff --git a/repoman/lib/repoman/modules/linechecks/assignment/__init__.py b/repoman/lib/repoman/modules/linechecks/assignment/__init__.py
deleted file mode 100644
index df2844cf5b9..00000000000
--- a/repoman/lib/repoman/modules/linechecks/assignment/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Assignment plug-in module for repoman LineChecks.
-Performs assignments checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "assignment",
- "description": doc,
- "provides": {
- "assignment-check": {
- "name": "assignment",
- "sourcefile": "assignment",
- "class": "EbuildAssignment",
- "description": doc,
- },
- "eapi3-check": {
- "name": "eapi3assignment",
- "sourcefile": "assignment",
- "class": "Eapi3EbuildAssignment",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/assignment/assignment.py b/repoman/lib/repoman/modules/linechecks/assignment/assignment.py
deleted file mode 100644
index 2fbdef7ae6b..00000000000
--- a/repoman/lib/repoman/modules/linechecks/assignment/assignment.py
+++ /dev/null
@@ -1,38 +0,0 @@
-import re
-
-from portage.eapi import eapi_supports_prefix, eapi_has_broot
-from repoman.modules.linechecks.base import LineCheck
-
-
-class EbuildAssignment(LineCheck):
- """Ensure ebuilds don't assign to readonly variables."""
-
- repoman_check_name = "variable.readonly"
- read_only_vars = "A|CATEGORY|P|P[VNRF]|PVR|D|WORKDIR|FILESDIR|FEATURES|USE"
- readonly_assignment = re.compile(r"^\s*(export\s+)?(%s)=" % read_only_vars)
-
- def check(self, num, line):
- match = self.readonly_assignment.match(line)
- e = None
- if match is not None:
- e = self.errors["READONLY_ASSIGNMENT_ERROR"]
- return e
-
-
-class Eapi3EbuildAssignment(EbuildAssignment):
- """Ensure ebuilds don't assign to readonly EAPI 3-introduced variables."""
-
- read_only_vars = "ED|EPREFIX|EROOT"
- readonly_assignment = re.compile(r"\s*(export\s+)?(%s)=" % read_only_vars)
-
- def check_eapi(self, eapi):
- return eapi_supports_prefix(eapi)
-
-
-class Eapi7EbuildAssignment(EbuildAssignment):
- """Ensure ebuilds don't assign to readonly EAPI 7-introduced variables."""
-
- readonly_assignment = re.compile(r"\s*(export\s+)?BROOT=")
-
- def check_eapi(self, eapi):
- return eapi_has_broot(eapi)
diff --git a/repoman/lib/repoman/modules/linechecks/base.py b/repoman/lib/repoman/modules/linechecks/base.py
deleted file mode 100644
index 851057940dd..00000000000
--- a/repoman/lib/repoman/modules/linechecks/base.py
+++ /dev/null
@@ -1,115 +0,0 @@
-import logging
-import re
-
-
-class LineCheck:
- """Run a check on a line of an ebuild."""
-
- """A regular expression to determine whether to ignore the line"""
- ignore_line = False
- """True if lines containing nothing more than comments with optional
- leading whitespace should be ignored"""
- ignore_comment = True
-
- def __init__(self, errors):
- self.errors = errors
-
- def new(self, pkg):
- pass
-
- def check_eapi(self, eapi):
- """Returns if check should be run in the given EAPI (default: True)"""
- return True
-
- def check(self, num, line):
- """Run the check on line and return error if there is one"""
- if self.re.match(line):
- return self.errors[self.error]
-
- def end(self):
- pass
-
-
-class InheritEclass(LineCheck):
- """
- Base class for checking for missing inherits, as well as excess inherits.
-
- Args:
- eclass: Set to the name of your eclass.
- funcs: A tuple of functions that this eclass provides.
- comprehensive: Is the list of functions complete?
- exempt_eclasses: If these eclasses are inherited, disable the missing
- inherit check.
- """
-
- def __init__(
- self,
- eclass,
- eclass_eapi_functions,
- errors,
- funcs=None,
- comprehensive=False,
- exempt_eclasses=None,
- ignore_missing=False,
- **kwargs
- ):
- self._eclass = eclass
- self._comprehensive = comprehensive
- self._exempt_eclasses = exempt_eclasses
- self._ignore_missing = ignore_missing
- self.errors = errors
- inherit_re = eclass
- self._eclass_eapi_functions = eclass_eapi_functions
- self._inherit_re = re.compile(
- r"^(\s*|.*[|&]\s*)\binherit\s(.*\s)?%s(\s|$)" % inherit_re
- )
- # Match when the function is preceded only by leading whitespace, a
- # shell operator such as (, {, |, ||, or &&, or optional variable
- # setting(s). This prevents false positives in things like elog
- # messages, as reported in bug #413285.
- logging.debug("InheritEclass, eclass: %s, funcs: %s", eclass, funcs)
- self._func_re = re.compile(
- r"(^|[|&{(])\s*(\w+=.*)?\b(" + r"|".join(funcs) + r")\b"
- )
-
- def new(self, pkg):
- self.repoman_check_name = "inherit.missing"
- # We can't use pkg.inherited because that tells us all the eclasses that
- # have been inherited and not just the ones we inherit directly.
- self._inherit = False
- self._func_call = False
- if self._exempt_eclasses is not None:
- inherited = pkg.inherited
- self._disabled = any(x in inherited for x in self._exempt_eclasses)
- else:
- self._disabled = False
- self._eapi = pkg.eapi
-
- def check(self, num, line):
- if not self._inherit:
- self._inherit = self._inherit_re.match(line)
- if not self._inherit:
- if self._disabled or self._ignore_missing:
- return
- s = self._func_re.search(line)
- if s is not None:
- func_name = s.group(3)
- eapi_func = self._eclass_eapi_functions.get(func_name)
- if eapi_func is None or not eapi_func(self._eapi):
- self._func_call = True
- return '%s.eclass not inherited, but "%s" called' % (
- self._eclass,
- func_name,
- )
- elif not self._func_call:
- self._func_call = self._func_re.search(line)
-
- def end(self):
- if (
- not self._disabled
- and self._comprehensive
- and self._inherit
- and not self._func_call
- ):
- self.repoman_check_name = "inherit.unused"
- yield "no function called from %s.eclass; please drop" % self._eclass
diff --git a/repoman/lib/repoman/modules/linechecks/config.py b/repoman/lib/repoman/modules/linechecks/config.py
deleted file mode 100644
index e4275f5ccd8..00000000000
--- a/repoman/lib/repoman/modules/linechecks/config.py
+++ /dev/null
@@ -1,149 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Checks
-# Copyright 2007-2017 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains functions used in Repoman to ascertain the quality
-and correctness of an ebuild."""
-
-import collections
-import logging
-import os
-from copy import deepcopy
-
-from repoman._portage import portage
-from repoman.config import load_config
-from repoman import _not_installed
-
-# Avoid a circular import issue in py2.7
-portage.proxy.lazyimport.lazyimport(
- globals(),
- "portage.util:stack_lists",
-)
-
-
-def merge(dict1, dict2):
- """Return a new dictionary by merging two dictionaries recursively."""
-
- result = deepcopy(dict1)
-
- for key, value in dict2.items():
- if isinstance(value, collections.Mapping):
- result[key] = merge(result.get(key, {}), value)
- else:
- result[key] = deepcopy(dict2[key])
-
- return result
-
-
-class LineChecksConfig:
- """Holds our LineChecks configuration data and operation functions"""
-
- def __init__(self, repo_settings):
- """Class init
-
- @param repo_settings: RepoSettings instance
- @param configpaths: ordered list of filepaths to load
- """
- self.repo_settings = repo_settings
- self.infopaths = None
- self.info_config = None
- self._config = None
- self.usex_supported_eapis = None
- self.in_iuse_supported_eapis = None
- self.get_libdir_supported_eapis = None
- self.eclass_eapi_functions = {}
- self.eclass_export_functions = None
- self.eclass_info = {}
- self.eclass_info_experimental_inherit = {}
- self.errors = {}
- self.set_infopaths()
- self.load_checks_info()
-
- def set_infopaths(self):
- if _not_installed:
- cnfdir = os.path.realpath(
- os.path.join(
- os.path.dirname(
- os.path.dirname(
- os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
- )
- ),
- "cnf/linechecks",
- )
- )
- else:
- cnfdir = os.path.join(
- portage.const.EPREFIX or "/", "usr/share/repoman/linechecks"
- )
- repomanpaths = [os.path.join(cnfdir, _file_) for _file_ in os.listdir(cnfdir)]
- logging.debug("LineChecksConfig; repomanpaths: %s", repomanpaths)
- repopaths = [
- os.path.join(path, "linechecks.yaml")
- for path in self.repo_settings.masters_list
- ]
- self.infopaths = repomanpaths + repopaths
- logging.debug("LineChecksConfig; configpaths: %s", self.infopaths)
-
- def load_checks_info(self, infopaths=None):
- """load the config files in order
-
- @param infopaths: ordered list of filepaths to load
- """
- if infopaths:
- self.infopaths = infopaths
- elif not self.infopaths:
- logging.error("LineChecksConfig; Error: No linechecks.yaml files defined")
-
- configs = load_config(
- self.infopaths, "yaml", self.repo_settings.repoman_settings.valid_versions
- )
- if configs == {}:
- logging.error(
- "LineChecksConfig: Failed to load a valid 'linechecks.yaml' file at paths: %s",
- self.infopaths,
- )
- return False
- logging.debug("LineChecksConfig: linechecks.yaml configs: %s", configs)
- self.info_config = configs
-
- self.errors = self.info_config["errors"]
- self.usex_supported_eapis = self.info_config.get("usex_supported_eapis", [])
- self.in_iuse_supported_eapis = self.info_config.get(
- "in_iuse_supported_eapis", []
- )
- self.eclass_info_experimental_inherit = self.info_config.get(
- "eclass_info_experimental_inherit", []
- )
- self.get_libdir_supported_eapis = self.in_iuse_supported_eapis
- self.eclass_eapi_functions = {
- "usex": lambda eapi: eapi not in self.usex_supported_eapis,
- "in_iuse": lambda eapi: eapi not in self.in_iuse_supported_eapis,
- "get_libdir": lambda eapi: eapi not in self.get_libdir_supported_eapis,
- }
-
- # eclasses that export ${ECLASS}_src_(compile|configure|install)
- self.eclass_export_functions = self.info_config.get(
- "eclass_export_functions", []
- )
-
- self.eclass_info_experimental_inherit = self.info_config.get(
- "eclass_info_experimental_inherit", {}
- )
- # These are "eclasses are the whole ebuild" type thing.
- try:
- self.eclass_info_experimental_inherit["eutils"][
- "exempt_eclasses"
- ] = self.eclass_export_functions
- except KeyError:
- pass
- try:
- self.eclass_info_experimental_inherit["multilib"][
- "exempt_eclasses"
- ] = self.eclass_export_functions + [
- "autotools",
- "libtool",
- "multilib-minimal",
- ]
- except KeyError:
- pass
diff --git a/repoman/lib/repoman/modules/linechecks/controller.py b/repoman/lib/repoman/modules/linechecks/controller.py
deleted file mode 100644
index f4cfe2aca2b..00000000000
--- a/repoman/lib/repoman/modules/linechecks/controller.py
+++ /dev/null
@@ -1,164 +0,0 @@
-import logging
-import operator
-import os
-import re
-
-from repoman.modules.linechecks.base import InheritEclass
-from repoman.modules.linechecks.config import LineChecksConfig
-from repoman._portage import portage
-
-# Avoid a circular import issue in py2.7
-portage.proxy.lazyimport.lazyimport(
- globals(),
- "portage.module:Modules",
-)
-
-MODULES_PATH = os.path.dirname(__file__)
-# initial development debug info
-logging.debug("LineChecks module path: %s", MODULES_PATH)
-
-
-class LineCheckController:
- """Initializes and runs the LineCheck checks"""
-
- def __init__(self, repo_settings, linechecks):
- """Class init
-
- @param repo_settings: RepoSettings instance
- """
- self.repo_settings = repo_settings
- self.linechecks = linechecks
- self.config = LineChecksConfig(repo_settings)
-
- self.controller = Modules(
- path=MODULES_PATH, namepath="repoman.modules.linechecks"
- )
- logging.debug(
- "LineCheckController; module_names: %s", self.controller.module_names
- )
-
- self._constant_checks = None
-
- self._here_doc_re = re.compile(r".*<<[-]?(\w+)\s*(>\s*\S+\s*)?$")
- self._ignore_comment_re = re.compile(r"^\s*#")
- self._continuation_re = re.compile(r"(\\)*$")
-
- def checks_init(self, experimental_inherit=False):
- """Initialize the main variables
-
- @param experimental_inherit boolean
- """
- if not experimental_inherit:
- # Emulate the old eprefixify.defined and inherit.autotools checks.
- self._eclass_info = self.config.eclass_info
- else:
- self._eclass_info = self.config.eclass_info_experimental_inherit
-
- self._constant_checks = []
- logging.debug("LineCheckController; modules: %s", self.linechecks)
- # Add in the pluggable modules
- for mod in self.linechecks:
- mod_class = self.controller.get_class(mod)
- logging.debug(
- "LineCheckController; module_name: %s, class: %s",
- mod,
- mod_class.__name__,
- )
- self._constant_checks.append(mod_class(self.config.errors))
- # Add in the InheritEclass checks
- logging.debug(
- "LineCheckController; eclass_info.items(): %s",
- list(self.config.eclass_info),
- )
- for k, kwargs in self.config.eclass_info.items():
- logging.debug("LineCheckController; k: %s, kwargs: %s", k, kwargs)
- self._constant_checks.append(
- InheritEclass(
- k, self.config.eclass_eapi_functions, self.config.errors, **kwargs
- )
- )
-
- def run_checks(self, contents, pkg):
- """Run the configured linechecks
-
- @param contents: the ebuild contents to check
- @param pkg: the package being checked
- """
- if self._constant_checks is None:
- self.checks_init()
- checks = self._constant_checks
- here_doc_delim = None
- multiline = None
-
- for lc in checks:
- lc.new(pkg)
-
- multinum = 0
- for num, line in enumerate(contents):
-
- # Check if we're inside a here-document.
- if here_doc_delim is not None:
- if here_doc_delim.match(line):
- here_doc_delim = None
- if here_doc_delim is None:
- here_doc = self._here_doc_re.match(line)
- if here_doc is not None:
- here_doc_delim = re.compile(r"^\s*%s$" % here_doc.group(1))
- if here_doc_delim is not None:
- continue
-
- # Unroll multiline escaped strings so that we can check things:
- # inherit foo bar \
- # moo \
- # cow
- # This will merge these lines like so:
- # inherit foo bar moo cow
- # A line ending with an even number of backslashes does not count,
- # because the last backslash is escaped. Therefore, search for an
- # odd number of backslashes.
- line_escaped = (
- operator.sub(*self._continuation_re.search(line).span()) % 2 == 1
- )
- if multiline:
- # Chop off the \ and \n bytes from the previous line.
- multiline = multiline[:-2] + line
- if not line_escaped:
- line = multiline
- num = multinum
- multiline = None
- else:
- continue
- else:
- if line_escaped:
- multinum = num
- multiline = line
- continue
-
- if not line.endswith("#nowarn\n"):
- # Finally we have a full line to parse.
- is_comment = self._ignore_comment_re.match(line) is not None
- for lc in checks:
- if is_comment and lc.ignore_comment:
- continue
- if lc.check_eapi(pkg.eapi):
- ignore = lc.ignore_line
- if not ignore or not ignore.match(line):
- errors = lc.check(num, line)
- if errors:
- if isinstance(errors, (tuple, list)):
- for error in errors:
- yield lc.repoman_check_name, "line %d: %s" % (
- num + 1,
- error,
- )
- else:
- yield lc.repoman_check_name, "line %d: %s" % (
- num + 1,
- errors,
- )
-
- for lc in checks:
- i = lc.end()
- if i is not None:
- for e in i:
- yield lc.repoman_check_name, e
diff --git a/repoman/lib/repoman/modules/linechecks/depend/__init__.py b/repoman/lib/repoman/modules/linechecks/depend/__init__.py
deleted file mode 100644
index 7fe35f9686e..00000000000
--- a/repoman/lib/repoman/modules/linechecks/depend/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Depend plug-in module for repoman LineChecks.
-Performs dependency checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "depend",
- "description": doc,
- "provides": {
- "implicit-check": {
- "name": "implicitdepend",
- "sourcefile": "implicit",
- "class": "ImplicitRuntimeDeps",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/depend/implicit.py b/repoman/lib/repoman/modules/linechecks/depend/implicit.py
deleted file mode 100644
index 5f4c0661869..00000000000
--- a/repoman/lib/repoman/modules/linechecks/depend/implicit.py
+++ /dev/null
@@ -1,38 +0,0 @@
-import re
-
-from portage.eapi import eapi_has_implicit_rdepend
-from repoman.modules.linechecks.base import LineCheck
-
-
-class ImplicitRuntimeDeps(LineCheck):
- """
- Detect the case where DEPEND is set and RDEPEND is unset in the ebuild,
- since this triggers implicit RDEPEND=$DEPEND assignment (prior to EAPI 4).
- """
-
- repoman_check_name = "RDEPEND.implicit"
- _assignment_re = re.compile(r"^\s*(R?DEPEND)\+?=")
-
- def new(self, pkg):
- self._rdepend = False
- self._depend = False
-
- def check_eapi(self, eapi):
- # Beginning with EAPI 4, there is no
- # implicit RDEPEND=$DEPEND assignment
- # to be concerned with.
- return eapi_has_implicit_rdepend(eapi)
-
- def check(self, num, line):
- if not self._rdepend:
- m = self._assignment_re.match(line)
- if m is None:
- pass
- elif m.group(1) == "RDEPEND":
- self._rdepend = True
- elif m.group(1) == "DEPEND":
- self._depend = True
-
- def end(self):
- if self._depend and not self._rdepend:
- yield "RDEPEND is not explicitly assigned"
diff --git a/repoman/lib/repoman/modules/linechecks/deprecated/__init__.py b/repoman/lib/repoman/modules/linechecks/deprecated/__init__.py
deleted file mode 100644
index 593bc1d3f2a..00000000000
--- a/repoman/lib/repoman/modules/linechecks/deprecated/__init__.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Deprecated plug-in module for repoman LineChecks.
-Performs miscelaneous deprecation checks on ebuilds not covered by
-specialty modules."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "deprecated",
- "description": doc,
- "provides": {
- "useq-check": {
- "name": "useq",
- "sourcefile": "deprecated",
- "class": "DeprecatedUseq",
- "description": doc,
- },
- "hasq-check": {
- "name": "hasq",
- "sourcefile": "deprecated",
- "class": "DeprecatedHasq",
- "description": doc,
- },
- "preserve-check": {
- "name": "preservelib",
- "sourcefile": "deprecated",
- "class": "PreserveOldLib",
- "description": doc,
- },
- "bindnow-check": {
- "name": "bindnow",
- "sourcefile": "deprecated",
- "class": "DeprecatedBindnowFlags",
- "description": doc,
- },
- "inherit-check": {
- "name": "inherit",
- "sourcefile": "inherit",
- "class": "InheritDeprecated",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/deprecated/deprecated.py b/repoman/lib/repoman/modules/linechecks/deprecated/deprecated.py
deleted file mode 100644
index abf7dbf423d..00000000000
--- a/repoman/lib/repoman/modules/linechecks/deprecated/deprecated.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import re # pylint: disable=unused-import
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class DeprecatedUseq(LineCheck):
- """Checks for use of the deprecated useq function"""
-
- repoman_check_name = "ebuild.minorsyn"
- re = re.compile(r"(^|.*\b)useq\b")
- error = "USEQ_ERROR"
-
-
-class DeprecatedHasq(LineCheck):
- """Checks for use of the deprecated hasq function"""
-
- repoman_check_name = "ebuild.minorsyn"
- re = re.compile(r"(^|.*\b)hasq\b")
- error = "HASQ_ERROR"
-
-
-class PreserveOldLib(LineCheck):
- """Check for calls to the preserve_old_lib function reserved for system packages."""
-
- repoman_check_name = "ebuild.minorsyn"
- re = re.compile(r".*preserve_old_lib")
- error = "PRESERVE_OLD_LIB"
-
-
-class DeprecatedBindnowFlags(LineCheck):
- """Check for calls to the deprecated bindnow-flags function."""
-
- repoman_check_name = "ebuild.minorsyn"
- re = re.compile(r".*\$\(bindnow-flags\)")
- error = "DEPRECATED_BINDNOW_FLAGS"
diff --git a/repoman/lib/repoman/modules/linechecks/deprecated/inherit.py b/repoman/lib/repoman/modules/linechecks/deprecated/inherit.py
deleted file mode 100644
index 7d7f66d5d6c..00000000000
--- a/repoman/lib/repoman/modules/linechecks/deprecated/inherit.py
+++ /dev/null
@@ -1,67 +0,0 @@
-import re
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class InheritDeprecated(LineCheck):
- """Check if ebuild directly or indirectly inherits a deprecated eclass."""
-
- repoman_check_name = "inherit.deprecated"
-
- # deprecated eclass : new eclass (False if no new eclass)
- deprecated_eclasses = {
- "autotools-multilib": "multilib-minimal",
- "autotools-utils": False,
- "base": False,
- "bash-completion": "bash-completion-r1",
- "boost-utils": False,
- "clutter": "gnome2",
- "cmake-utils": "cmake",
- "confutils": False,
- "distutils": "distutils-r1",
- "epatch": "(eapply since EAPI 6)",
- "fdo-mime": "xdg-utils",
- "games": False,
- "gems": "ruby-fakegem",
- "git-2": "git-r3",
- "gpe": False,
- "gst-plugins-bad": "gstreamer",
- "gst-plugins-base": "gstreamer",
- "gst-plugins-good": "gstreamer",
- "gst-plugins-ugly": "gstreamer",
- "gst-plugins10": "gstreamer",
- "ltprune": False,
- "mono": "mono-env",
- "python": "python-r1 / python-single-r1 / python-any-r1",
- "ruby": "ruby-ng",
- "user": "GLEP 81",
- "versionator": "eapi7-ver (built-in since EAPI 7)",
- "x-modular": "xorg-2",
- "xfconf": False,
- }
-
- _inherit_re = re.compile(r"^\s*inherit\s(.*)$")
-
- def check(self, num, line):
- direct_inherits = None
- m = self._inherit_re.match(line)
- if m is not None:
- direct_inherits = m.group(1)
- if direct_inherits:
- direct_inherits = direct_inherits.split()
-
- if not direct_inherits:
- return
-
- errors = []
- for eclass in direct_inherits:
- replacement = self.deprecated_eclasses.get(eclass)
- if replacement is None:
- pass
- elif replacement is False:
- errors.append("please migrate from " "'%s' (no replacement)" % eclass)
- else:
- errors.append(
- "please migrate from " "'%s' to '%s'" % (eclass, replacement)
- )
- return errors
diff --git a/repoman/lib/repoman/modules/linechecks/do/__init__.py b/repoman/lib/repoman/modules/linechecks/do/__init__.py
deleted file mode 100644
index 597b961e798..00000000000
--- a/repoman/lib/repoman/modules/linechecks/do/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Do plug-in module for repoman LineChecks.
-Performs do* checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "nonrelative-check": {
- "name": "dosym",
- "sourcefile": "dosym",
- "class": "EbuildNonRelativeDosym",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/do/dosym.py b/repoman/lib/repoman/modules/linechecks/do/dosym.py
deleted file mode 100644
index 2276b3315e3..00000000000
--- a/repoman/lib/repoman/modules/linechecks/do/dosym.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import re
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class EbuildNonRelativeDosym(LineCheck):
- """Check ebuild for dosym using absolute paths instead of relative."""
-
- repoman_check_name = "ebuild.absdosym"
- variables = ("D", "ED", "ROOT", "EROOT", "BROOT")
- regex = re.compile(
- r'^\s*dosym\s+(["\']?((\$(%s)\W|\${(%s)(%%/)?})|/(bin|etc|lib|opt|sbin|srv|usr|var))\S*)'
- % ("|".join(variables), "|".join(variables)),
- getattr(re, "ASCII", 0),
- )
-
- def check(self, num, line):
- match = self.regex.match(line)
- if match:
- return "dosym '%s'... could use relative path" % match.group(1)
diff --git a/repoman/lib/repoman/modules/linechecks/eapi/__init__.py b/repoman/lib/repoman/modules/linechecks/eapi/__init__.py
deleted file mode 100644
index 68e6b722a0f..00000000000
--- a/repoman/lib/repoman/modules/linechecks/eapi/__init__.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Eapi plug-in module for repoman LineChecks.
-Performs eapi dependant checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "eapi",
- "description": doc,
- "provides": {
- "definition-check": {
- "name": "definition",
- "sourcefile": "definition",
- "class": "EapiDefinition",
- "description": doc,
- },
- "srcprepare-check": {
- "name": "srcprepare",
- "sourcefile": "checks",
- "class": "UndefinedSrcPrepareSrcConfigurePhases",
- "description": doc,
- },
- "eapi3deprecated-check": {
- "name": "eapi3deprecated",
- "sourcefile": "checks",
- "class": "Eapi3DeprecatedFuncs",
- "description": doc,
- },
- "pkgpretend-check": {
- "name": "pkgpretend",
- "sourcefile": "checks",
- "class": "UndefinedPkgPretendPhase",
- "description": doc,
- },
- "eapi4incompatible-check": {
- "name": "eapi4incompatible",
- "sourcefile": "checks",
- "class": "Eapi4IncompatibleFuncs",
- "description": doc,
- },
- "eapi4gonevars-check": {
- "name": "eapi4gonevars",
- "sourcefile": "checks",
- "class": "Eapi4GoneVars",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/eapi/checks.py b/repoman/lib/repoman/modules/linechecks/eapi/checks.py
deleted file mode 100644
index 64bb509a7d4..00000000000
--- a/repoman/lib/repoman/modules/linechecks/eapi/checks.py
+++ /dev/null
@@ -1,79 +0,0 @@
-import re
-
-from portage.eapi import (
- eapi_has_src_prepare_and_src_configure,
- eapi_has_dosed_dohard,
- eapi_exports_AA,
- eapi_has_pkg_pretend,
-)
-from repoman.modules.linechecks.base import LineCheck
-
-
-# EAPI <2 checks
-class UndefinedSrcPrepareSrcConfigurePhases(LineCheck):
- repoman_check_name = "EAPI.incompatible"
- src_configprepare_re = re.compile(r"\s*(src_configure|src_prepare)\s*\(\)")
-
- def check_eapi(self, eapi):
- return not eapi_has_src_prepare_and_src_configure(eapi)
-
- def check(self, num, line):
- m = self.src_configprepare_re.match(line)
- if m is not None:
- return ("'%s'" % m.group(1)) + " phase is not defined in EAPI < 2"
-
-
-# EAPI-3 checks
-class Eapi3DeprecatedFuncs(LineCheck):
- repoman_check_name = "EAPI.deprecated"
- deprecated_commands_re = re.compile(r"^\s*(check_license)\b")
-
- def check_eapi(self, eapi):
- return eapi not in ("0", "1", "2")
-
- def check(self, num, line):
- m = self.deprecated_commands_re.match(line)
- if m is not None:
- return ("'%s'" % m.group(1)) + " has been deprecated in EAPI=3"
-
-
-# EAPI <4 checks
-class UndefinedPkgPretendPhase(LineCheck):
- repoman_check_name = "EAPI.incompatible"
- pkg_pretend_re = re.compile(r"\s*(pkg_pretend)\s*\(\)")
-
- def check_eapi(self, eapi):
- return not eapi_has_pkg_pretend(eapi)
-
- def check(self, num, line):
- m = self.pkg_pretend_re.match(line)
- if m is not None:
- return ("'%s'" % m.group(1)) + " phase is not defined in EAPI < 4"
-
-
-# EAPI-4 checks
-class Eapi4IncompatibleFuncs(LineCheck):
- repoman_check_name = "EAPI.incompatible"
- banned_commands_re = re.compile(r"^\s*(dosed|dohard)")
-
- def check_eapi(self, eapi):
- return not eapi_has_dosed_dohard(eapi)
-
- def check(self, num, line):
- m = self.banned_commands_re.match(line)
- if m is not None:
- return ("'%s'" % m.group(1)) + " has been banned in EAPI=4"
-
-
-class Eapi4GoneVars(LineCheck):
- repoman_check_name = "EAPI.incompatible"
- undefined_vars_re = re.compile(r".*\$(\{(AA|KV|EMERGE_FROM)\}|(AA|KV|EMERGE_FROM))")
-
- def check_eapi(self, eapi):
- # AA, KV, and EMERGE_FROM should not be referenced in EAPI 4 or later.
- return not eapi_exports_AA(eapi)
-
- def check(self, num, line):
- m = self.undefined_vars_re.match(line)
- if m is not None:
- return ("variable '$%s'" % m.group(1)) + " is gone in EAPI=4"
diff --git a/repoman/lib/repoman/modules/linechecks/eapi/definition.py b/repoman/lib/repoman/modules/linechecks/eapi/definition.py
deleted file mode 100644
index 964fa4ea340..00000000000
--- a/repoman/lib/repoman/modules/linechecks/eapi/definition.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from repoman.modules.linechecks.base import LineCheck
-from repoman._portage import portage
-
-
-class EapiDefinition(LineCheck):
- """
- Check that EAPI assignment conforms to PMS section 7.3.1
- (first non-comment, non-blank line).
- """
-
- repoman_check_name = "EAPI.definition"
- ignore_comment = True
- _eapi_re = portage._pms_eapi_re
-
- def new(self, pkg):
- self._cached_eapi = pkg.eapi
- self._parsed_eapi = None
- self._eapi_line_num = None
-
- def check(self, num, line):
- if self._eapi_line_num is None and line.strip():
- self._eapi_line_num = num + 1
- m = self._eapi_re.match(line)
- if m is not None:
- self._parsed_eapi = m.group(2)
-
- def end(self):
- if self._parsed_eapi is None:
- if self._cached_eapi != "0":
- yield "valid EAPI assignment must occur on or before line: %s" % self._eapi_line_num
- elif self._parsed_eapi != self._cached_eapi:
- yield (
- "bash returned EAPI '%s' which does not match "
- "assignment on line: %s" % (self._cached_eapi, self._eapi_line_num)
- )
diff --git a/repoman/lib/repoman/modules/linechecks/emake/__init__.py b/repoman/lib/repoman/modules/linechecks/emake/__init__.py
deleted file mode 100644
index 9a2c54915be..00000000000
--- a/repoman/lib/repoman/modules/linechecks/emake/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Emake plug-in module for repoman LineChecks.
-Performs emake checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "paralleldisabled-check": {
- "name": "paralleldisabled",
- "sourcefile": "emake",
- "class": "EMakeParallelDisabledViaMAKEOPTS",
- "description": doc,
- },
- "autodefault-check": {
- "name": "autodefault",
- "sourcefile": "emake",
- "class": "WantAutoDefaultValue",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/emake/emake.py b/repoman/lib/repoman/modules/linechecks/emake/emake.py
deleted file mode 100644
index 3bb7fc35b98..00000000000
--- a/repoman/lib/repoman/modules/linechecks/emake/emake.py
+++ /dev/null
@@ -1,25 +0,0 @@
-import re
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class EMakeParallelDisabledViaMAKEOPTS(LineCheck):
- """Check for MAKEOPTS=-j1 that disables parallelization."""
-
- repoman_check_name = "upstream.workaround"
- re = re.compile(r'^\s*MAKEOPTS=(\'|")?.*-j\s*1\b')
- error = "EMAKE_PARALLEL_DISABLED_VIA_MAKEOPTS"
-
-
-class WantAutoDefaultValue(LineCheck):
- """Check setting WANT_AUTO* to latest (default value)."""
-
- repoman_check_name = "ebuild.minorsyn"
- _re = re.compile(r'^WANT_AUTO(CONF|MAKE)=(\'|")?latest')
-
- def check(self, num, line):
- m = self._re.match(line)
- if m is not None:
- return (
- "WANT_AUTO" + m.group(1) + ' redundantly set to default value "latest"'
- )
diff --git a/repoman/lib/repoman/modules/linechecks/gentoo_header/__init__.py b/repoman/lib/repoman/modules/linechecks/gentoo_header/__init__.py
deleted file mode 100644
index 565b43ec2f5..00000000000
--- a/repoman/lib/repoman/modules/linechecks/gentoo_header/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Gentoo-header plug-in module for repoman LineChecks.
-Performs header checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "header-check": {
- "name": "gentooheader",
- "sourcefile": "header",
- "class": "EbuildHeader",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/gentoo_header/header.py b/repoman/lib/repoman/modules/linechecks/gentoo_header/header.py
deleted file mode 100644
index 7ef77ae4483..00000000000
--- a/repoman/lib/repoman/modules/linechecks/gentoo_header/header.py
+++ /dev/null
@@ -1,56 +0,0 @@
-import re
-import time
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class EbuildHeader(LineCheck):
- """Ensure ebuilds have proper headers
- Copyright header errors
- CVS header errors
- License header errors
-
- Args:
- modification_year - Year the ebuild was last modified
- """
-
- repoman_check_name = "ebuild.badheader"
-
- gentoo_copyright = r"^# Copyright ((1999|2\d\d\d)-)?(?P<year2>%s) (?P<author>.*)$"
- gentoo_license = (
- "# Distributed under the terms" " of the GNU General Public License v2"
- )
- id_header_re = re.compile(r".*\$(Id|Header)(:.*)?\$.*")
- blank_line_re = re.compile(r"^$")
- ignore_comment = False
-
- def new(self, pkg):
- if pkg.mtime is None:
- self.modification_year = r"2\d\d\d"
- else:
- self.modification_year = str(time.gmtime(pkg.mtime)[0])
- self.gentoo_copyright_re = re.compile(
- self.gentoo_copyright % self.modification_year
- )
-
- def check(self, num, line):
- if num > 2:
- return
- elif num == 0:
- match = self.gentoo_copyright_re.match(line)
- if match is None:
- return self.errors["COPYRIGHT_ERROR"]
- if not (
- match.group("author") == "Gentoo Authors"
- or (
- int(match.group("year2")) < 2019
- and match.group("author") == "Gentoo Foundation"
- )
- ):
- return self.errors["COPYRIGHT_ERROR"]
- elif num == 1 and line.rstrip("\n") != self.gentoo_license:
- return self.errors["LICENSE_ERROR"]
- elif num == 2 and self.id_header_re.match(line):
- return self.errors["ID_HEADER_ERROR"]
- elif num == 2 and not self.blank_line_re.match(line):
- return self.errors["NO_BLANK_LINE_ERROR"]
diff --git a/repoman/lib/repoman/modules/linechecks/helpers/__init__.py b/repoman/lib/repoman/modules/linechecks/helpers/__init__.py
deleted file mode 100644
index b65b454f1ec..00000000000
--- a/repoman/lib/repoman/modules/linechecks/helpers/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Helpers plug-in module for repoman LineChecks.
-Performs variable helpers checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "nooffset-check": {
- "name": "nooffset",
- "sourcefile": "offset",
- "class": "NoOffsetWithHelpers",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/helpers/offset.py b/repoman/lib/repoman/modules/linechecks/helpers/offset.py
deleted file mode 100644
index 72ece48d585..00000000000
--- a/repoman/lib/repoman/modules/linechecks/helpers/offset.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import re # pylint: disable=unused-import
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class NoOffsetWithHelpers(LineCheck):
- """Check that the image location, the alternate root offset, and the
- offset prefix (D, ROOT, ED, EROOT and EPREFIX) are not used with
- helpers"""
-
- repoman_check_name = "variable.usedwithhelpers"
- # Ignore matches in quoted strings like this:
- # elog "installed into ${ROOT}usr/share/php5/apc/."
- _install_funcs = (
- "docinto|do(compress|dir|hard)" "|exeinto|fowners|fperms|insinto|into"
- )
- _quoted_vars = "D|ROOT|ED|EROOT|EPREFIX"
- re = re.compile(
- r'^[^#"\']*\b(%s)\s+"?\$\{?(%s)\b.*' % (_install_funcs, _quoted_vars)
- )
- error = "NO_OFFSET_WITH_HELPERS"
diff --git a/repoman/lib/repoman/modules/linechecks/nested/__init__.py b/repoman/lib/repoman/modules/linechecks/nested/__init__.py
deleted file mode 100644
index 83d69127dde..00000000000
--- a/repoman/lib/repoman/modules/linechecks/nested/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Nested plug-in module for repoman LineChecks.
-Performs nested subshell checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "nesteddie-check": {
- "name": "nesteddie",
- "sourcefile": "nested",
- "class": "EbuildNestedDie",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/nested/nested.py b/repoman/lib/repoman/modules/linechecks/nested/nested.py
deleted file mode 100644
index fc04bde0165..00000000000
--- a/repoman/lib/repoman/modules/linechecks/nested/nested.py
+++ /dev/null
@@ -1,14 +0,0 @@
-import re
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class EbuildNestedDie(LineCheck):
- """Check ebuild for nested die statements (die statements in subshells)"""
-
- repoman_check_name = "ebuild.nesteddie"
- nesteddie_re = re.compile(r"^[^#]*\s\(\s[^)]*\bdie\b")
-
- def check(self, num, line):
- if self.nesteddie_re.match(line):
- return self.errors["NESTED_DIE_ERROR"]
diff --git a/repoman/lib/repoman/modules/linechecks/nested/nesteddie.py b/repoman/lib/repoman/modules/linechecks/nested/nesteddie.py
deleted file mode 100644
index 4b256bb1fd4..00000000000
--- a/repoman/lib/repoman/modules/linechecks/nested/nesteddie.py
+++ /dev/null
@@ -1,9 +0,0 @@
-class EbuildNestedDie(LineCheck):
- """Check ebuild for nested die statements (die statements in subshells)"""
-
- repoman_check_name = "ebuild.nesteddie"
- nesteddie_re = re.compile(r"^[^#]*\s\(\s[^)]*\bdie\b")
-
- def check(self, num, line):
- if self.nesteddie_re.match(line):
- return errors.NESTED_DIE_ERROR
diff --git a/repoman/lib/repoman/modules/linechecks/patches/__init__.py b/repoman/lib/repoman/modules/linechecks/patches/__init__.py
deleted file mode 100644
index e4aec16a135..00000000000
--- a/repoman/lib/repoman/modules/linechecks/patches/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Patches plug-in module for repoman LineChecks.
-Performs PATCHES variable checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "patches-check": {
- "name": "patches",
- "sourcefile": "patches",
- "class": "EbuildPatches",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/patches/patches.py b/repoman/lib/repoman/modules/linechecks/patches/patches.py
deleted file mode 100644
index ca9a4cada6d..00000000000
--- a/repoman/lib/repoman/modules/linechecks/patches/patches.py
+++ /dev/null
@@ -1,22 +0,0 @@
-import re # pylint: disable=unused-import
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class EbuildPatches(LineCheck):
- """Ensure ebuilds use bash arrays for PATCHES to ensure white space safety"""
-
- repoman_check_name = "ebuild.patches"
- re = re.compile(r"^\s*PATCHES=[^\(]")
- error = "PATCHES_ERROR"
-
- def check_eapi(self, eapi):
- return eapi in (
- "0",
- "1",
- "2",
- "3",
- "4",
- "4-slot-abi",
- "5",
- )
diff --git a/repoman/lib/repoman/modules/linechecks/phases/__init__.py b/repoman/lib/repoman/modules/linechecks/phases/__init__.py
deleted file mode 100644
index 880eac02b28..00000000000
--- a/repoman/lib/repoman/modules/linechecks/phases/__init__.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Phases plug-in module for repoman LineChecks.
-Performs phase dependant checks on ebuilds using a PhaseCheck base class.
-"""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "emakeparallel-check": {
- "name": "emakeparallel",
- "sourcefile": "phase",
- "class": "EMakeParallelDisabled",
- "description": doc,
- },
- "srccompileeconf-check": {
- "name": "srccompileeconf",
- "sourcefile": "phase",
- "class": "SrcCompileEconf",
- "description": doc,
- },
- "srcunpackpatches-check": {
- "name": "srcunpackpatches",
- "sourcefile": "phase",
- "class": "SrcUnpackPatches",
- "description": doc,
- },
- "pmsvariablerefphasescope-check": {
- "name": "pmsvariablerefphasescope",
- "sourcefile": "phase",
- "class": "PMSVariableReference",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/phases/phase.py b/repoman/lib/repoman/modules/linechecks/phases/phase.py
deleted file mode 100644
index 5d89b263d9f..00000000000
--- a/repoman/lib/repoman/modules/linechecks/phases/phase.py
+++ /dev/null
@@ -1,188 +0,0 @@
-import fnmatch
-import re
-import types
-
-from portage.eapi import (
- eapi_has_broot,
- eapi_has_sysroot,
- eapi_has_src_prepare_and_src_configure,
- eapi_exports_AA,
- eapi_exports_replace_vars,
- eapi_exports_ECLASSDIR,
- eapi_exports_PORTDIR,
- eapi_supports_prefix,
- eapi_exports_merge_type,
-)
-from repoman.modules.linechecks.base import LineCheck
-
-
-class PhaseCheck(LineCheck):
- """basic class for function detection"""
-
- func_end_re = re.compile(r"^\}$")
- phase_funcs = (
- "pkg_pretend",
- "pkg_setup",
- "src_unpack",
- "src_prepare",
- "src_configure",
- "src_compile",
- "src_test",
- "src_install",
- "pkg_preinst",
- "pkg_postinst",
- "pkg_prerm",
- "pkg_postrm",
- "pkg_config",
- )
- phases_re = re.compile("(%s)" % "|".join(phase_funcs))
- in_phase = ""
-
- def check(self, num, line):
- m = self.phases_re.match(line)
- if m is not None:
- self.in_phase = m.group(1)
- if self.in_phase != "" and self.func_end_re.match(line) is not None:
- self.in_phase = ""
-
- return self.phase_check(num, line)
-
- def phase_check(self, num, line):
- """override this function for your checks"""
- pass
-
-
-class EMakeParallelDisabled(PhaseCheck):
- """Check for emake -j1 calls which disable parallelization."""
-
- repoman_check_name = "upstream.workaround"
- re = re.compile(r"^\s*emake\s+.*-j\s*1\b")
-
- def phase_check(self, num, line):
- if self.in_phase == "src_compile" or self.in_phase == "src_install":
- if self.re.match(line):
- return self.errors["EMAKE_PARALLEL_DISABLED"]
-
-
-class SrcCompileEconf(PhaseCheck):
- repoman_check_name = "ebuild.minorsyn"
- configure_re = re.compile(r"\s(econf|./configure)")
-
- def check_eapi(self, eapi):
- return eapi_has_src_prepare_and_src_configure(eapi)
-
- def phase_check(self, num, line):
- if self.in_phase == "src_compile":
- m = self.configure_re.match(line)
- if m is not None:
- return ("'%s'" % m.group(1)) + " call should be moved to src_configure"
-
-
-class SrcUnpackPatches(PhaseCheck):
- repoman_check_name = "ebuild.minorsyn"
- src_prepare_tools_re = re.compile(r"\s(e?patch|sed)\s")
-
- def check_eapi(self, eapi):
- return eapi_has_src_prepare_and_src_configure(eapi)
-
- def phase_check(self, num, line):
- if self.in_phase == "src_unpack":
- m = self.src_prepare_tools_re.search(line)
- if m is not None:
- return ("'%s'" % m.group(1)) + " call should be moved to src_prepare"
-
-
-# Refererences
-# - https://projects.gentoo.org/pms/7/pms.html#x1-10900011.1
-# - https://pkgcore.github.io/pkgcheck/_modules/pkgcheck/checks/codingstyle.html#VariableScopeCheck
-_pms_vars = (
- ("A", None, ("src_*", "pkg_nofetch")),
- ("AA", eapi_exports_AA, ("src_*", "pkg_nofetch")),
- ("FILESDIR", None, ("src_*",)),
- ("DISTDIR", None, ("src_*",)),
- ("WORKDIR", None, ("src_*",)),
- ("S", None, ("src_*",)),
- ("PORTDIR", eapi_exports_PORTDIR, ("src_*",)),
- ("ECLASSDIR", eapi_exports_ECLASSDIR, ("src_*",)),
- ("ROOT", None, ("pkg_*",)),
- ("EROOT", eapi_supports_prefix, ("pkg_*",)),
- ("SYSROOT", eapi_has_sysroot, ("src_*", "pkg_setup")),
- ("ESYSROOT", eapi_has_sysroot, ("src_*", "pkg_setup")),
- ("BROOT", eapi_has_broot, ("src_*", "pkg_setup")),
- ("D", None, ("src_install", "pkg_preinst", "pkg_postint")),
- ("ED", eapi_supports_prefix, ("src_install", "pkg_preinst", "pkg_postint")),
- ("DESTTREE", None, ("src_install",)),
- ("INSDESTTREE", None, ("src_install",)),
- ("MERGE_TYPE", eapi_exports_merge_type, ("pkg_*",)),
- ("REPLACING_VERSIONS", eapi_exports_replace_vars, ("pkg_*",)),
- ("REPLACED_BY_VERSION", eapi_exports_replace_vars, ("pkg_prerm", "pkg_postrm")),
-)
-
-
-def _compile_phases():
- phase_vars = {}
- for phase_func in PhaseCheck.phase_funcs:
- for variable, eapi_filter, allowed_scopes in _pms_vars:
- allowed = False
- for scope in allowed_scopes:
- if fnmatch.fnmatch(phase_func, scope):
- allowed = True
- break
-
- if not allowed:
- phase_vars.setdefault(phase_func, []).append((variable, eapi_filter))
-
- phase_info = {}
- for phase_func, prohibited_vars in phase_vars.items():
- phase_func_vars = []
- for variable, eapi_filter in prohibited_vars:
- phase_func_vars.append(variable)
- phase_obj = phase_info[phase_func] = types.SimpleNamespace()
- phase_obj.prohibited_vars = dict(prohibited_vars)
- phase_obj.var_names = "(%s)" % "|".join(
- variable for variable, eapi_filter in prohibited_vars
- )
- phase_obj.var_reference = re.compile(
- r"\$(\{|)%s(\}|\W)" % (phase_obj.var_names,)
- )
-
- return phase_info
-
-
-class PMSVariableReference(PhaseCheck):
- """Check phase scope for references to variables specified by PMS"""
-
- repoman_check_name = "variable.phase"
- phase_info = _compile_phases()
-
- def new(self, pkg):
- self._eapi = pkg.eapi
-
- def end(self):
- self._eapi = None
-
- def phase_check(self, num, line):
- try:
- phase_info = self.phase_info[self.in_phase]
- except KeyError:
- return
-
- eapi = self._eapi
- issues = []
- for m in phase_info.var_reference.finditer(line):
- open_brace = m.group(1)
- var_name = m.group(2)
- close_brace = m.group(3)
- # discard \W if matched by (\}|\W)
- close_brace = close_brace if close_brace == "}" else ""
- if bool(open_brace) != bool(close_brace):
- continue
- var_name = m.group(2)
- eapi_filter = phase_info.prohibited_vars[var_name]
- if eapi_filter is not None and not eapi_filter(eapi):
- continue
- issues.append(
- "phase %s: EAPI %s: variable %s: Forbidden reference to variable specified by PMS"
- % (self.in_phase, eapi, var_name)
- )
- return issues
diff --git a/repoman/lib/repoman/modules/linechecks/portage/__init__.py b/repoman/lib/repoman/modules/linechecks/portage/__init__.py
deleted file mode 100644
index d30877d6dc0..00000000000
--- a/repoman/lib/repoman/modules/linechecks/portage/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Portage plug-in module for repoman LineChecks.
-Performs checks for internal portage variable usage in ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "internal-check": {
- "name": "portageinternal",
- "sourcefile": "internal",
- "class": "PortageInternal",
- "description": doc,
- },
- "portageinternalvariableassignment-check": {
- "name": "portageinternalvariableassignment",
- "sourcefile": "internal",
- "class": "PortageInternalVariableAssignment",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/portage/internal.py b/repoman/lib/repoman/modules/linechecks/portage/internal.py
deleted file mode 100644
index 5d6af108847..00000000000
--- a/repoman/lib/repoman/modules/linechecks/portage/internal.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import re
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class PortageInternal(LineCheck):
- repoman_check_name = "portage.internal"
- ignore_comment = True
- # Match when the command is preceded only by leading whitespace or a shell
- # operator such as (, {, |, ||, or &&. This prevents false positives in
- # things like elog messages, as reported in bug #413285.
-
- internal_portage_func_or_var = (
- "ecompress|ecompressdir|env-update|prepall|prepalldocs|preplib"
- )
- re = re.compile(r"^(\s*|.*[|&{(]+\s*)\b(%s)\b" % internal_portage_func_or_var)
-
- def check(self, num, line):
- """Run the check on line and return error if there is one"""
- m = self.re.match(line)
- if m is not None:
- return "'%s' called" % m.group(2)
-
-
-class PortageInternalVariableAssignment(LineCheck):
- repoman_check_name = "portage.internal"
- internal_assignment = re.compile(r"\s*(export\s+)?(EXTRA_ECONF|EXTRA_EMAKE)\+?=")
-
- def check(self, num, line):
- match = self.internal_assignment.match(line)
- if match is not None:
- return "Assignment to variable %s" % match.group(2)
diff --git a/repoman/lib/repoman/modules/linechecks/quotes/__init__.py b/repoman/lib/repoman/modules/linechecks/quotes/__init__.py
deleted file mode 100644
index deb4ced974b..00000000000
--- a/repoman/lib/repoman/modules/linechecks/quotes/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Nested plug-in module for repoman LineChecks.
-Performs nested subshell checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "quote-check": {
- "name": "quote",
- "sourcefile": "quotes",
- "class": "EbuildQuote",
- "description": doc,
- },
- "quoteda-check": {
- "name": "quoteda",
- "sourcefile": "quoteda",
- "class": "EbuildQuotedA",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/quotes/quoteda.py b/repoman/lib/repoman/modules/linechecks/quotes/quoteda.py
deleted file mode 100644
index f44d4e38eb3..00000000000
--- a/repoman/lib/repoman/modules/linechecks/quotes/quoteda.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import re
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class EbuildQuotedA(LineCheck):
- """Ensure ebuilds have no quoting around ${A}"""
-
- repoman_check_name = "ebuild.minorsyn"
- a_quoted = re.compile(r".*\"\$(\{A\}|A)\"")
-
- def check(self, num, line):
- match = self.a_quoted.match(line)
- if match:
- return 'Quoted "${A}"'
diff --git a/repoman/lib/repoman/modules/linechecks/quotes/quotes.py b/repoman/lib/repoman/modules/linechecks/quotes/quotes.py
deleted file mode 100644
index c170c10ef39..00000000000
--- a/repoman/lib/repoman/modules/linechecks/quotes/quotes.py
+++ /dev/null
@@ -1,92 +0,0 @@
-import re
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class EbuildQuote(LineCheck):
- """Ensure ebuilds have valid quoting around things like D,FILESDIR, etc..."""
-
- repoman_check_name = "ebuild.minorsyn"
- _message_commands = ["die", "echo", "eerror", "einfo", "elog", "eqawarn", "ewarn"]
- _message_re = re.compile(r"\s(" + "|".join(_message_commands) + r')\s+"[^"]*"\s*$')
- _ignored_commands = ["local", "export"] + _message_commands
- ignore_line = re.compile(
- r"(^$)|(^\s*#.*)|(^\s*\w+=.*)"
- + r"|(^\s*("
- + "|".join(_ignored_commands)
- + r")\s+)"
- )
- ignore_comment = False
- var_names = ["D", "DISTDIR", "FILESDIR", "S", "T", "ROOT", "BROOT", "WORKDIR"]
-
- # EAPI=3/Prefix vars
- var_names += ["ED", "EPREFIX", "EROOT"]
-
- # variables for games.eclass
- var_names += [
- "Ddir",
- "GAMES_PREFIX_OPT",
- "GAMES_DATADIR",
- "GAMES_DATADIR_BASE",
- "GAMES_SYSCONFDIR",
- "GAMES_STATEDIR",
- "GAMES_LOGDIR",
- "GAMES_BINDIR",
- ]
-
- # variables for multibuild.eclass
- var_names += ["BUILD_DIR"]
-
- var_names = "(%s)" % "|".join(var_names)
- var_reference = re.compile(r"\$(\{%s\}|%s\W)" % (var_names, var_names))
- missing_quotes = re.compile(r'(\s|^)[^"\'\s]*\$\{?%s\}?[^"\'\s]*(\s|$)' % var_names)
- cond_begin = re.compile(r"(^|\s+)\[\[($|\\$|\s+)")
- cond_end = re.compile(r"(^|\s+)\]\]($|\\$|\s+)")
-
- def check(self, num, line):
- if self.var_reference.search(line) is None:
- return
- # There can be multiple matches / violations on a single line. We
- # have to make sure none of the matches are violators. Once we've
- # found one violator, any remaining matches on the same line can
- # be ignored.
- pos = 0
- while pos <= len(line) - 1:
- missing_quotes = self.missing_quotes.search(line, pos)
- if not missing_quotes:
- break
- # If the last character of the previous match is a whitespace
- # character, that character may be needed for the next
- # missing_quotes match, so search overlaps by 1 character.
- group = missing_quotes.group()
- pos = missing_quotes.end() - 1
-
- # Filter out some false positives that can
- # get through the missing_quotes regex.
- if self.var_reference.search(group) is None:
- continue
-
- # Filter matches that appear to be an
- # argument to a message command.
- # For example: false || ewarn "foo $WORKDIR/bar baz"
- message_match = self._message_re.search(line)
- if (
- message_match is not None
- and message_match.start() < pos
- and message_match.end() > pos
- ):
- break
-
- # This is an attempt to avoid false positives without getting
- # too complex, while possibly allowing some (hopefully
- # unlikely) violations to slip through. We just assume
- # everything is correct if the there is a ' [[ ' or a ' ]] '
- # anywhere in the whole line (possibly continued over one
- # line).
- if self.cond_begin.search(line) is not None:
- continue
- if self.cond_end.search(line) is not None:
- continue
-
- # Any remaining matches on the same line can be ignored.
- return self.errors["MISSING_QUOTES_ERROR"]
diff --git a/repoman/lib/repoman/modules/linechecks/uri/__init__.py b/repoman/lib/repoman/modules/linechecks/uri/__init__.py
deleted file mode 100644
index 4018020c3f3..00000000000
--- a/repoman/lib/repoman/modules/linechecks/uri/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Uri plug-in module for repoman LineChecks.
-Performs HOMEPAGE variable checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "httpsuri-check": {
- "name": "httpsuri",
- "sourcefile": "uri",
- "class": "UriUseHttps",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/uri/uri.py b/repoman/lib/repoman/modules/linechecks/uri/uri.py
deleted file mode 100644
index 9f3e49fe0c4..00000000000
--- a/repoman/lib/repoman/modules/linechecks/uri/uri.py
+++ /dev/null
@@ -1,30 +0,0 @@
-import re # pylint: disable=unused-import
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class UriUseHttps(LineCheck):
- """Check that we use https:// for known good sites."""
-
- repoman_check_name = "uri.https"
- _SITES = (
- r"([-._a-zA-Z0-9]*\.)?apache\.org",
- r"((alioth|packages(\.qa)?|people|www)\.)?debian\.org",
- # Most FDO sites support https, but not all (like tango).
- # List the most common ones here for now.
- r"((anongit|bugs|cgit|dri|patchwork|people|specifications|www|xcb|xorg)\.)?freedesktop\.org",
- r"((bugs|dev|wiki|www)\.)?gentoo\.org",
- r"((wiki)\.)?github\.(io|com)",
- r"savannah\.(non)?gnu\.org",
- r"((gcc|www)\.)?gnu\.org",
- r"curl\.haxx\.se",
- r"((bugzilla|git|mirrors|patchwork|planet|www(\.wiki)?)\.)?kernel\.org",
- r"((bugs|wiki|www)\.)?linuxfoundation\.org",
- r"((docs|pypi|www)\.)?python\.org",
- r"(sf|sourceforge)\.net",
- r"(www\.)?(enlightenment|sourceware|x)\.org",
- )
- # Try to anchor the end of the URL so we don't get false positives
- # with http://github.com.foo.bar.com/. Unlikely, but possible.
- re = re.compile(r'.*\bhttp://(%s)(\s|["\'/]|$)' % r"|".join(_SITES))
- error = "URI_HTTPS"
diff --git a/repoman/lib/repoman/modules/linechecks/use/__init__.py b/repoman/lib/repoman/modules/linechecks/use/__init__.py
deleted file mode 100644
index 0d738c37c72..00000000000
--- a/repoman/lib/repoman/modules/linechecks/use/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Use plug-in module for repoman LineChecks.
-Performs Built-With-Use checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "builtwith-check": {
- "name": "builtwith",
- "sourcefile": "builtwith",
- "class": "BuiltWithUse",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/use/builtwith.py b/repoman/lib/repoman/modules/linechecks/use/builtwith.py
deleted file mode 100644
index 0b16de02802..00000000000
--- a/repoman/lib/repoman/modules/linechecks/use/builtwith.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import re # pylint: disable=unused-import
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class BuiltWithUse(LineCheck):
- repoman_check_name = "ebuild.minorsyn"
- re = re.compile(r"(^|.*\b)built_with_use\b")
- error = "BUILT_WITH_USE"
diff --git a/repoman/lib/repoman/modules/linechecks/useless/__init__.py b/repoman/lib/repoman/modules/linechecks/useless/__init__.py
deleted file mode 100644
index 9be9515841d..00000000000
--- a/repoman/lib/repoman/modules/linechecks/useless/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Useless plug-in module for repoman LineChecks.
-Performs checks for useless operations on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "uselesscds-check": {
- "name": "uselesscds",
- "sourcefile": "cd",
- "class": "EbuildUselessCdS",
- "description": doc,
- },
- "uselessdodoc-check": {
- "name": "uselessdodoc",
- "sourcefile": "dodoc",
- "class": "EbuildUselessDodoc",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/useless/cd.py b/repoman/lib/repoman/modules/linechecks/useless/cd.py
deleted file mode 100644
index 73063209ffd..00000000000
--- a/repoman/lib/repoman/modules/linechecks/useless/cd.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import re
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class EbuildUselessCdS(LineCheck):
- """Check for redundant cd ${S} statements"""
-
- repoman_check_name = "ebuild.minorsyn"
- _src_phases = r"^\s*src_(prepare|configure|compile|install|test)\s*\(\)"
- method_re = re.compile(_src_phases)
- cds_re = re.compile(r'^\s*cd\s+("\$(\{S\}|S)"|\$(\{S\}|S))\s')
-
- def __init__(self, errors):
- self.errors = errors
- self.check_next_line = False
-
- def check(self, num, line):
- if self.check_next_line:
- self.check_next_line = False
- if self.cds_re.match(line):
- return self.errors["REDUNDANT_CD_S_ERROR"]
- elif self.method_re.match(line):
- self.check_next_line = True
diff --git a/repoman/lib/repoman/modules/linechecks/useless/dodoc.py b/repoman/lib/repoman/modules/linechecks/useless/dodoc.py
deleted file mode 100644
index 49f6fde9185..00000000000
--- a/repoman/lib/repoman/modules/linechecks/useless/dodoc.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import re
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class EbuildUselessDodoc(LineCheck):
- """Check ebuild for useless files in dodoc arguments."""
-
- repoman_check_name = "ebuild.minorsyn"
- uselessdodoc_re = re.compile(
- r"^\s*dodoc(\s+|\s+.*\s+)(ABOUT-NLS|COPYING|LICENCE|LICENSE)($|\s)"
- )
-
- def check(self, num, line):
- match = self.uselessdodoc_re.match(line)
- if match:
- return "Useless dodoc '%s'" % match.group(2)
diff --git a/repoman/lib/repoman/modules/linechecks/whitespace/__init__.py b/repoman/lib/repoman/modules/linechecks/whitespace/__init__.py
deleted file mode 100644
index 17b3abab500..00000000000
--- a/repoman/lib/repoman/modules/linechecks/whitespace/__init__.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Whitespace plug-in module for repoman LineChecks.
-Performs checks for useless whitespace in ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "whitespace-check": {
- "name": "whitespace",
- "sourcefile": "whitespace",
- "class": "EbuildWhitespace",
- "description": doc,
- },
- "blankline-check": {
- "name": "blankline",
- "sourcefile": "blank",
- "class": "EbuildBlankLine",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/whitespace/blank.py b/repoman/lib/repoman/modules/linechecks/whitespace/blank.py
deleted file mode 100644
index 89e38c68cb4..00000000000
--- a/repoman/lib/repoman/modules/linechecks/whitespace/blank.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import re
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class EbuildBlankLine(LineCheck):
- repoman_check_name = "ebuild.minorsyn"
- ignore_comment = False
- blank_line = re.compile(r"^$")
-
- def new(self, pkg):
- self.line_is_blank = False
-
- def check(self, num, line):
- if self.line_is_blank and self.blank_line.match(line):
- return "Useless blank line"
- if self.blank_line.match(line):
- self.line_is_blank = True
- else:
- self.line_is_blank = False
-
- def end(self):
- if self.line_is_blank:
- yield "Useless blank line on last line"
diff --git a/repoman/lib/repoman/modules/linechecks/whitespace/whitespace.py b/repoman/lib/repoman/modules/linechecks/whitespace/whitespace.py
deleted file mode 100644
index a1274048d4c..00000000000
--- a/repoman/lib/repoman/modules/linechecks/whitespace/whitespace.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import re
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class EbuildWhitespace(LineCheck):
- """Ensure ebuilds have proper whitespacing"""
-
- repoman_check_name = "ebuild.minorsyn"
-
- ignore_line = re.compile(r"(^$)|(^(\t)*#)")
- ignore_comment = False
- leading_spaces = re.compile(r"^[\S\t]")
- trailing_whitespace = re.compile(r".*([\S]$)")
-
- def check(self, num, line):
- if self.leading_spaces.match(line) is None:
- return self.errors["LEADING_SPACES_ERROR"]
- if self.trailing_whitespace.match(line) is None:
- return self.errors["TRAILING_WHITESPACE_ERROR"]
diff --git a/repoman/lib/repoman/modules/linechecks/workaround/__init__.py b/repoman/lib/repoman/modules/linechecks/workaround/__init__.py
deleted file mode 100644
index eff33cf2339..00000000000
--- a/repoman/lib/repoman/modules/linechecks/workaround/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Workaround plug-in module for repoman LineChecks.
-Performs checks for upstream workarounds in ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "do",
- "description": doc,
- "provides": {
- "noasneeded-check": {
- "name": "noasneeded",
- "sourcefile": "workarounds",
- "class": "NoAsNeeded",
- "description": doc,
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/linechecks/workaround/workarounds.py b/repoman/lib/repoman/modules/linechecks/workaround/workarounds.py
deleted file mode 100644
index 47b6881ffaa..00000000000
--- a/repoman/lib/repoman/modules/linechecks/workaround/workarounds.py
+++ /dev/null
@@ -1,11 +0,0 @@
-import re # pylint: disable=unused-import
-
-from repoman.modules.linechecks.base import LineCheck
-
-
-class NoAsNeeded(LineCheck):
- """Check for calls to the no-as-needed function."""
-
- repoman_check_name = "upstream.workaround"
- re = re.compile(r".*\$\(no-as-needed\)")
- error = "NO_AS_NEEDED"
diff --git a/repoman/lib/repoman/modules/scan/__init__.py b/repoman/lib/repoman/modules/scan/__init__.py
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/repoman/lib/repoman/modules/scan/__init__.py
+++ /dev/null
diff --git a/repoman/lib/repoman/modules/scan/depend/__init__.py b/repoman/lib/repoman/modules/scan/depend/__init__.py
deleted file mode 100644
index cac382b6f2b..00000000000
--- a/repoman/lib/repoman/modules/scan/depend/__init__.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Depend plug-in module for repoman.
-Performs Dependency checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "depend",
- "description": doc,
- "provides": {
- "profile-module": {
- "name": "profile",
- "sourcefile": "profile",
- "class": "ProfileDependsChecks",
- "description": doc,
- "functions": ["check"],
- "func_desc": {},
- "mod_kwargs": [
- "qatracker",
- "portdb",
- "profiles",
- "options",
- "repo_metadata",
- "repo_settings",
- "include_arches",
- "include_profiles",
- "caches",
- "repoman_incrementals",
- "env",
- "have",
- "dev_keywords",
- ],
- "func_kwargs": {
- "ebuild": (None, None),
- "pkg": (None, None),
- },
- "module_runsIn": ["ebuilds"],
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/scan/depend/_depend_checks.py b/repoman/lib/repoman/modules/scan/depend/_depend_checks.py
deleted file mode 100644
index 11a2fbf56d6..00000000000
--- a/repoman/lib/repoman/modules/scan/depend/_depend_checks.py
+++ /dev/null
@@ -1,260 +0,0 @@
-# -*- coding:utf-8 -*-
-
-import collections
-
-from _emerge.Package import Package
-
-from portage.dep import Atom
-
-from repoman.check_missingslot import check_missingslot
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-
-def check_slotop(depstr, is_valid_flag, badsyntax, mytype, qatracker, relative_path):
- """Checks if RDEPEND uses ':=' slot operator
- in '||' style dependencies."""
-
- try:
- # to find use of ':=' in '||' we preserve
- # tree structure of dependencies
- my_dep_tree = portage.dep.use_reduce(
- depstr,
- flat=False,
- matchall=1,
- is_valid_flag=is_valid_flag,
- opconvert=True,
- token_class=portage.dep.Atom,
- )
- except portage.exception.InvalidDependString as e:
- my_dep_tree = None
- badsyntax.append((mytype, str(e)))
-
- def _traverse_tree(dep_tree, in_any_of):
- # leaf
- if isinstance(dep_tree, Atom):
- atom = dep_tree
- if in_any_of and atom.slot_operator == "=":
- qatracker.add_error(
- "dependency.badslotop",
- "%s: %s: '%s' uses ':=' slot operator under '||' dep clause."
- % (relative_path, mytype, atom),
- )
-
- # branches
- if isinstance(dep_tree, list):
- if len(dep_tree) == 0:
- return
- # entering any-of
- if dep_tree[0] == "||":
- _traverse_tree(dep_tree[1:], in_any_of=True)
- else:
- for branch in dep_tree:
- _traverse_tree(branch, in_any_of=in_any_of)
-
- _traverse_tree(my_dep_tree, False)
-
-
-def _depend_checks(ebuild, pkg, portdb, qatracker, repo_metadata, qadata):
- """Checks the ebuild dependencies for errors
-
- @param pkg: Package in which we check (object).
- @param ebuild: Ebuild which we check (object).
- @param portdb: portdb instance
- @param qatracker: QATracker instance
- @param repo_metadata: dictionary of various repository items.
- @returns: (unknown_pkgs, badlicsyntax)
- """
-
- unknown_pkgs = set()
-
- inherited_java_eclass = (
- "java-pkg-2" in ebuild.inherited or "java-pkg-opt-2" in ebuild.inherited
- )
- inherited_wxwidgets_eclass = "wxwidgets" in ebuild.inherited
- # operator_tokens = set(["||", "(", ")"])
- badsyntax = []
- for mytype in Package._dep_keys + ("LICENSE", "PROPERTIES"):
- mydepstr = ebuild.metadata[mytype]
-
- buildtime = mytype in Package._buildtime_keys
- runtime = mytype in Package._runtime_keys
- token_class = None
- if mytype.endswith("DEPEND"):
- token_class = portage.dep.Atom
-
- try:
- atoms = portage.dep.use_reduce(
- mydepstr,
- matchall=1,
- flat=True,
- is_valid_flag=pkg.iuse.is_valid_flag,
- token_class=token_class,
- )
- except portage.exception.InvalidDependString as e:
- atoms = None
- badsyntax.append((mytype, str(e)))
-
- if atoms and mytype.endswith("DEPEND"):
- if runtime and "test?" in mydepstr.split():
- qatracker.add_error(
- mytype + ".suspect",
- "%s: 'test?' USE conditional in %s"
- % (ebuild.relative_path, mytype),
- )
-
- for atom in atoms:
- if atom == "||":
- continue
-
- is_blocker = atom.blocker
-
- # Skip dependency.unknown for blockers, so that we
- # don't encourage people to remove necessary blockers,
- # as discussed in bug 382407. We use atom.without_use
- # due to bug 525376.
- if (
- not is_blocker
- and not portdb.xmatch("match-all", atom.without_use)
- and not atom.cp.startswith("virtual/")
- ):
- unknown_pkgs.add((mytype, atom.unevaluated_atom))
-
- if not atom.blocker:
- all_deprecated = False
- for pkg_match in portdb.xmatch("match-all", atom):
- if any(
- repo_metadata["package.deprecated"].iterAtomsForPackage(
- pkg_match
- )
- ):
- all_deprecated = True
- else:
- all_deprecated = False
- break
-
- if all_deprecated:
- qatracker.add_error(
- "dependency.deprecated",
- ebuild.relative_path + ": '%s'" % atom,
- )
-
- if pkg.category != "virtual":
- if not is_blocker and atom.cp in qadata.suspect_virtual:
- qatracker.add_error(
- "virtual.suspect",
- ebuild.relative_path
- + ": %s: consider using '%s' instead of '%s'"
- % (mytype, qadata.suspect_virtual[atom.cp], atom),
- )
- if not is_blocker and atom.cp.startswith("perl-core/"):
- qatracker.add_error(
- "dependency.perlcore",
- ebuild.relative_path
- + ": %s: please use '%s' instead of '%s'"
- % (
- mytype,
- atom.replace("perl-core/", "virtual/perl-"),
- atom,
- ),
- )
-
- if (
- buildtime
- and not is_blocker
- and not inherited_java_eclass
- and atom.cp == "virtual/jdk"
- ):
- qatracker.add_error("java.eclassesnotused", ebuild.relative_path)
- elif (
- buildtime
- and not is_blocker
- and not inherited_wxwidgets_eclass
- and atom.cp == "x11-libs/wxGTK"
- ):
- qatracker.add_error(
- "wxwidgets.eclassnotused",
- "%s: %ss on x11-libs/wxGTK without inheriting"
- " wxwidgets.eclass" % (ebuild.relative_path, mytype),
- )
- elif runtime:
- if not is_blocker and atom.cp in qadata.suspect_rdepend:
- qatracker.add_error(
- mytype + ".suspect", ebuild.relative_path + ": '%s'" % atom
- )
-
- if (
- atom.operator == "~"
- and portage.versions.catpkgsplit(atom.cpv)[3] != "r0"
- ):
- qacat = "dependency.badtilde"
- qatracker.add_error(
- qacat,
- "%s: %s uses the ~ operator"
- " with a non-zero revision: '%s'"
- % (ebuild.relative_path, mytype, atom),
- )
- # plain =foo-1.2.3 without revision or *
- if atom.operator == "=" and "-r" not in atom.version:
- qacat = "dependency.equalsversion"
- qatracker.add_error(
- qacat,
- "%s: %s uses the = operator with"
- " no revision: '%s'; if any revision is"
- " acceptable, use '~' instead; if only -r0"
- " then please append '-r0' to the dep"
- % (ebuild.relative_path, mytype, atom),
- )
-
- check_missingslot(
- atom,
- mytype,
- ebuild.eapi,
- portdb,
- qatracker,
- ebuild.relative_path,
- ebuild.metadata,
- )
-
- if runtime:
- check_slotop(
- mydepstr,
- pkg.iuse.is_valid_flag,
- badsyntax,
- mytype,
- qatracker,
- ebuild.relative_path,
- )
-
- baddepsyntax = False
- dedup = collections.defaultdict(set)
- for m, b in badsyntax:
- if b in dedup[m]:
- continue
- dedup[m].add(b)
-
- if m.endswith("DEPEND"):
- baddepsyntax = True
- qacat = "dependency.syntax"
- else:
- qacat = m + ".syntax"
- qatracker.add_error(qacat, "%s: %s: %s" % (ebuild.relative_path, m, b))
-
- # Parse the LICENSE variable, remove USE conditions and flatten it.
- licenses = portage.dep.use_reduce(ebuild.metadata["LICENSE"], matchall=1, flat=True)
-
- # Check each entry to ensure that it exists in ${PORTDIR}/licenses/.
- for lic in licenses:
- # Need to check for "||" manually as no portage
- # function will remove it without removing values.
- if lic not in repo_metadata["liclist"] and lic != "||":
- qatracker.add_error(
- "LICENSE.invalid", "%s: %s" % (ebuild.relative_path, lic)
- )
- elif lic in repo_metadata["lic_deprecated"]:
- qatracker.add_error(
- "LICENSE.deprecated", "%s: %s" % (ebuild.relative_path, lic)
- )
-
- return unknown_pkgs, baddepsyntax
diff --git a/repoman/lib/repoman/modules/scan/depend/_gen_arches.py b/repoman/lib/repoman/modules/scan/depend/_gen_arches.py
deleted file mode 100644
index 6e3000014b2..00000000000
--- a/repoman/lib/repoman/modules/scan/depend/_gen_arches.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# -*- coding:utf-8 -*-
-
-
-def _gen_arches(ebuild, options, repo_settings, profiles):
- """Determines the arches for the ebuild following the profile rules
-
- @param ebuild: Ebuild which we check (object).
- @param profiles: dictionary
- @param options: cli options
- @param repo_settings: repository settings instance
- @returns: dictionary, including arches set
- """
- if options.ignore_arches:
- arches = [
- [
- repo_settings.repoman_settings["ARCH"],
- repo_settings.repoman_settings["ARCH"],
- repo_settings.repoman_settings["ACCEPT_KEYWORDS"].split(),
- ]
- ]
- else:
- arches = set()
- for keyword in ebuild.keywords:
- if keyword[0] == "-":
- continue
- elif keyword[0] == "~":
- arch = keyword[1:]
- if arch == "*":
- for expanded_arch in profiles:
- if expanded_arch == "**":
- continue
- arches.add(
- (
- keyword,
- expanded_arch,
- (expanded_arch, "~" + expanded_arch),
- )
- )
- else:
- arches.add((keyword, arch, (arch, keyword)))
- else:
- # For ebuilds with stable keywords, check if the
- # dependencies are satisfiable for unstable
- # configurations, since use.stable.mask is not
- # applied for unstable configurations (see bug
- # 563546).
- if keyword == "*":
- for expanded_arch in profiles:
- if expanded_arch == "**":
- continue
- arches.add((keyword, expanded_arch, (expanded_arch,)))
- arches.add(
- (
- keyword,
- expanded_arch,
- (expanded_arch, "~" + expanded_arch),
- )
- )
- else:
- arches.add((keyword, keyword, (keyword,)))
- arches.add((keyword, keyword, (keyword, "~" + keyword)))
- if not arches:
- # Use an empty profile for checking dependencies of
- # packages that have empty KEYWORDS.
- arches.add(("**", "**", ("**",)))
-
- return arches
diff --git a/repoman/lib/repoman/modules/scan/depend/profile.py b/repoman/lib/repoman/modules/scan/depend/profile.py
deleted file mode 100644
index a0cb3a31437..00000000000
--- a/repoman/lib/repoman/modules/scan/depend/profile.py
+++ /dev/null
@@ -1,427 +0,0 @@
-# -*- coding:utf-8 -*-
-
-
-import copy
-import functools
-import os
-import types
-from pprint import pformat
-
-from _emerge.Package import Package
-
-# import our initialized portage instance
-from repoman._portage import portage
-from repoman.modules.scan.scanbase import ScanBase
-from repoman.modules.scan.depend._depend_checks import _depend_checks
-from repoman.modules.scan.depend._gen_arches import _gen_arches
-from portage.dep import Atom
-from portage.package.ebuild.profile_iuse import iter_iuse_vars
-from portage.util import getconfig
-from portage.util.futures import asyncio
-from portage.util.futures.executor.fork import ForkExecutor
-from portage.util.futures.iter_completed import async_iter_completed
-
-
-def sort_key(item):
- return item[2].sub_path
-
-
-class ProfileDependsChecks(ScanBase):
- """Perform dependency checks for the different profiles"""
-
- def __init__(self, **kwargs):
- """Class init
-
- @param qatracker: QATracker instance
- @param portdb: portdb instance
- @param profiles: dictionary
- @param options: cli options
- @param repo_settings: repository settings instance
- @param include_arches: set
- @param include_profiles: set
- @param caches: dictionary of our caches
- @param repoman_incrementals: tuple
- @param env: the environment
- @param have: dictionary instance
- @param dev_keywords: developer profile keywords
- @param repo_metadata: dictionary of various repository items.
- """
- self.qatracker = kwargs.get("qatracker")
- self.portdb = kwargs.get("portdb")
- self.profiles = kwargs.get("profiles")
- self.options = kwargs.get("options")
- self.repo_settings = kwargs.get("repo_settings")
- self.include_arches = kwargs.get("include_arches")
- self.include_profiles = kwargs.get("include_profiles")
- self.caches = kwargs.get("caches")
- self.repoman_incrementals = kwargs.get("repoman_incrementals")
- self.env = kwargs.get("env")
- self.have = kwargs.get("have")
- self.dev_keywords = kwargs.get("dev_keywords")
- self.repo_metadata = kwargs.get("repo_metadata")
-
- def check(self, **kwargs):
- """Perform profile dependant dependency checks
-
- @param pkg: Package in which we check (object).
- @param ebuild: Ebuild which we check (object).
- @returns: dictionary
- """
- ebuild = kwargs.get("ebuild").get()
- pkg = kwargs.get("pkg").get()
-
- ebuild.unknown_pkgs, ebuild.baddepsyntax = _depend_checks(
- ebuild,
- pkg,
- self.portdb,
- self.qatracker,
- self.repo_metadata,
- self.repo_settings.qadata,
- )
-
- relevant_profiles = []
- for keyword, arch, groups in _gen_arches(
- ebuild, self.options, self.repo_settings, self.profiles
- ):
- if arch not in self.profiles:
- # A missing profile will create an error further down
- # during the KEYWORDS verification.
- continue
-
- if self.include_arches is not None:
- if arch not in self.include_arches:
- continue
-
- for prof in self.profiles[arch]:
- if self.include_profiles is not None:
- if prof.sub_path not in self.include_profiles:
- continue
- relevant_profiles.append((keyword, groups, prof))
-
- relevant_profiles.sort(key=sort_key)
- ebuild.relevant_profiles = relevant_profiles
-
- if self.options.jobs <= 1:
- for task in self._iter_tasks(None, None, ebuild, pkg):
- task, results = task
- for result in results:
- self._check_result(task, result)
-
- loop = asyncio.get_event_loop()
- loop.run_until_complete(self._async_check(loop, **kwargs))
-
- return False
-
- async def _async_check(self, loop, **kwargs):
- """Perform async profile dependant dependency checks
-
- @param arches:
- @param pkg: Package in which we check (object).
- @param ebuild: Ebuild which we check (object).
- @param baddepsyntax: boolean
- @param unknown_pkgs: set of tuples (type, atom.unevaluated_atom)
- @returns: dictionary
- """
- ebuild = kwargs.get("ebuild").get()
- pkg = kwargs.get("pkg").get()
- unknown_pkgs = ebuild.unknown_pkgs
- baddepsyntax = ebuild.baddepsyntax
-
- # Use max_workers=True to ensure immediate fork, since _iter_tasks
- # needs the fork to create a snapshot of current state.
- executor = ForkExecutor(max_workers=self.options.jobs)
-
- if self.options.jobs > 1:
- for future_done_set in async_iter_completed(
- self._iter_tasks(loop, executor, ebuild, pkg),
- max_jobs=self.options.jobs,
- max_load=self.options.load_average,
- ):
- for task in await future_done_set:
- task, results = task.result()
- for result in results:
- self._check_result(task, result)
-
- if not baddepsyntax and unknown_pkgs:
- type_map = {}
- for mytype, atom in unknown_pkgs:
- type_map.setdefault(mytype, set()).add(atom)
- for mytype, atoms in type_map.items():
- self.qatracker.add_error(
- "dependency.unknown",
- "%s: %s: %s"
- % (ebuild.relative_path, mytype, ", ".join(sorted(atoms))),
- )
-
- async def _task(self, task):
- await task.future
- return (task, task.future.result())
-
- def _iter_tasks(self, loop, executor, ebuild, pkg):
- for keyword, groups, prof in ebuild.relevant_profiles:
-
- is_stable_profile = prof.status == "stable"
- is_dev_profile = prof.status == "dev" and self.options.include_dev
- is_exp_profile = (
- prof.status == "exp" and self.options.include_exp_profiles == "y"
- )
- if not (is_stable_profile or is_dev_profile or is_exp_profile):
- continue
-
- dep_settings = self.caches["arch"].get(prof.sub_path)
- if dep_settings is None:
- dep_settings = portage.config(
- config_profile_path=prof.abs_path,
- config_incrementals=self.repoman_incrementals,
- config_root=self.repo_settings.config_root,
- local_config=False,
- _unmatched_removal=self.options.unmatched_removal,
- env=self.env,
- repositories=self.repo_settings.repoman_settings.repositories,
- )
-
- if not prof.abs_path:
- self._populate_implicit_iuse(
- dep_settings, self.repo_settings.repo_config.eclass_db.porttrees
- )
-
- dep_settings.categories = self.repo_settings.repoman_settings.categories
- if self.options.without_mask:
- dep_settings._mask_manager_obj = copy.deepcopy(
- dep_settings._mask_manager
- )
- dep_settings._mask_manager._pmaskdict.clear()
- self.caches["arch"][prof.sub_path] = dep_settings
-
- xmatch_cache_key = (prof.sub_path, tuple(groups))
- xcache = self.caches["arch_xmatch"].get(xmatch_cache_key)
- if xcache is None:
- self.portdb.melt()
- self.portdb.freeze()
- xcache = self.portdb.xcache
- xcache.update(self.caches["shared_xmatch"])
- self.caches["arch_xmatch"][xmatch_cache_key] = xcache
-
- self.repo_settings.trees[self.repo_settings.root][
- "porttree"
- ].settings = dep_settings
- self.portdb.settings = dep_settings
- self.portdb.xcache = xcache
-
- dep_settings["ACCEPT_KEYWORDS"] = " ".join(groups)
- # just in case, prevent config.reset() from nuking these.
- dep_settings.backup_changes("ACCEPT_KEYWORDS")
-
- # This attribute is used in dbapi._match_use() to apply
- # use.stable.{mask,force} settings based on the stable
- # status of the parent package. This is required in order
- # for USE deps of unstable packages to be resolved correctly,
- # since otherwise use.stable.{mask,force} settings of
- # dependencies may conflict (see bug #456342).
- dep_settings._parent_stable = dep_settings._isStable(pkg)
-
- # Handle package.use*.{force,mask) calculation, for use
- # in dep_check.
- dep_settings.useforce = dep_settings._use_manager.getUseForce(
- pkg, stable=dep_settings._parent_stable
- )
- dep_settings.usemask = dep_settings._use_manager.getUseMask(
- pkg, stable=dep_settings._parent_stable
- )
-
- task = types.SimpleNamespace(ebuild=ebuild, prof=prof, keyword=keyword)
-
- target = functools.partial(self._task_subprocess, task, pkg, dep_settings)
-
- if self.options.jobs <= 1:
- yield (task, target())
- else:
- task.future = asyncio.ensure_future(
- loop.run_in_executor(executor, target), loop=loop
- )
- yield asyncio.ensure_future(self._task(task), loop=loop)
-
- def _task_subprocess(self, task, pkg, dep_settings):
- ebuild = task.ebuild
- baddepsyntax = ebuild.baddepsyntax
- results = []
- prof = task.prof
- if not baddepsyntax:
- ismasked = not ebuild.archs or pkg.cpv not in self.portdb.xmatch(
- "match-visible",
- Atom("%s::%s" % (pkg.cp, self.repo_settings.repo_config.name)),
- )
- if ismasked:
- if not self.have["pmasked"]:
- self.have["pmasked"] = bool(
- dep_settings._getMaskAtom(pkg.cpv, ebuild.metadata)
- )
- if self.options.ignore_masked:
- return results
- # we are testing deps for a masked package; give it some lee-way
- suffix = "masked"
- matchmode = "minimum-all-ignore-profile"
- else:
- suffix = ""
- matchmode = "minimum-visible"
-
- if not self.have["dev_keywords"]:
- self.have["dev_keywords"] = bool(
- self.dev_keywords.intersection(ebuild.keywords)
- )
-
- if prof.status == "dev":
- suffix = suffix + "indev"
- elif prof.status == "exp":
- suffix = suffix + "inexp"
-
- for mytype in Package._dep_keys:
-
- mykey = "dependency.bad" + suffix
- myvalue = ebuild.metadata[mytype]
- if not myvalue:
- continue
-
- success, atoms = portage.dep_check(
- myvalue,
- self.portdb,
- dep_settings,
- use="all",
- mode=matchmode,
- trees=self.repo_settings.trees,
- )
-
- results.append(
- types.SimpleNamespace(
- atoms=atoms, success=success, mykey=mykey, mytype=mytype
- )
- )
-
- return results
-
- def _check_result(self, task, result):
- prof = task.prof
- keyword = task.keyword
- ebuild = task.ebuild
- unknown_pkgs = ebuild.unknown_pkgs
-
- success = result.success
- atoms = result.atoms
- mykey = result.mykey
- mytype = result.mytype
-
- if success:
- if atoms:
-
- # Don't bother with dependency.unknown for
- # cases in which *DEPEND.bad is triggered.
- for atom in atoms:
- # dep_check returns all blockers and they
- # aren't counted for *DEPEND.bad, so we
- # ignore them here.
- if not atom.blocker:
- unknown_pkgs.discard((mytype, atom.unevaluated_atom))
-
- if not prof.sub_path:
- # old-style virtuals currently aren't
- # resolvable with empty profile, since
- # 'virtuals' mappings are unavailable
- # (it would be expensive to search
- # for PROVIDE in all ebuilds)
- atoms = [
- atom
- for atom in atoms
- if not (
- atom.cp.startswith("virtual/")
- and not self.portdb.cp_list(atom.cp)
- )
- ]
-
- # we have some unsolvable deps
- # remove ! deps, which always show up as unsatisfiable
- all_atoms = [
- str(atom.unevaluated_atom) for atom in atoms if not atom.blocker
- ]
-
- # if we emptied out our list, continue:
- if not all_atoms:
- return
-
- # Filter out duplicates. We do this by hand (rather
- # than use a set) so the order is stable and better
- # matches the order that's in the ebuild itself.
- atoms = []
- for atom in all_atoms:
- if atom not in atoms:
- atoms.append(atom)
-
- if self.options.output_style in ["column"]:
- self.qatracker.add_error(
- mykey,
- "%s: %s: %s(%s) %s"
- % (ebuild.relative_path, mytype, keyword, prof, repr(atoms)),
- )
- else:
- self.qatracker.add_error(
- mykey,
- "%s: %s: %s(%s)\n%s"
- % (
- ebuild.relative_path,
- mytype,
- keyword,
- prof,
- pformat(atoms, indent=6),
- ),
- )
- else:
- if self.options.output_style in ["column"]:
- self.qatracker.add_error(
- mykey,
- "%s: %s: %s(%s) %s"
- % (ebuild.relative_path, mytype, keyword, prof, repr(atoms)),
- )
- else:
- self.qatracker.add_error(
- mykey,
- "%s: %s: %s(%s)\n%s"
- % (
- ebuild.relative_path,
- mytype,
- keyword,
- prof,
- pformat(atoms, indent=6),
- ),
- )
-
- @property
- def runInEbuilds(self):
- """Ebuild level scans"""
- return (True, [self.check])
-
- @staticmethod
- def _populate_implicit_iuse(config, repo_locations):
- """
- Populate implicit IUSE for the empty profile, see bug 660982.
-
- @param config: config instance for the empty profile
- @type config: portage.config
- @param repo_locations: locations of repositories containing relevant
- implicit IUSE settings
- @type repo_locations: list
- """
- dest = config.configdict["defaults"]
- for location in repo_locations:
- for parent_dir, dirs, files in os.walk(os.path.join(location, "profiles")):
- src = getconfig(os.path.join(parent_dir, "make.defaults"))
- if not src:
- continue
- for k, v in iter_iuse_vars(src):
- v_before = dest.get(k)
- if v_before is not None:
- merged_values = set(v_before.split())
- merged_values.update(v.split())
- v = " ".join(sorted(merged_values))
- dest[k] = v
-
- config.regenerate()
- config._init_iuse()
diff --git a/repoman/lib/repoman/modules/scan/directories/__init__.py b/repoman/lib/repoman/modules/scan/directories/__init__.py
deleted file mode 100644
index 68596267d16..00000000000
--- a/repoman/lib/repoman/modules/scan/directories/__init__.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Directories plug-in module for repoman.
-Performs an FilesChecks check on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "directories",
- "description": doc,
- "provides": {
- "directories-module": {
- "name": "files",
- "sourcefile": "files",
- "class": "FileChecks",
- "description": doc,
- "functions": ["check"],
- "func_kwargs": {},
- "mod_kwargs": [
- "portdb",
- "qatracker",
- "repo_settings",
- "vcs_settings",
- ],
- "func_kwargs": {
- "changed": (None, None),
- "checkdir": (None, None),
- "checkdirlist": (None, None),
- "checkdir_relative": (None, None),
- },
- "module_runsIn": ["pkgs"],
- },
- "mtime-module": {
- "name": "mtime",
- "sourcefile": "mtime",
- "class": "MtimeChecks",
- "description": doc,
- "functions": ["check"],
- "func_kwargs": {},
- "mod_kwargs": [
- "vcs_settings",
- ],
- "func_kwargs": {
- "changed": (None, None),
- "ebuild": (None, None),
- "pkg": (None, None),
- },
- "module_runsIn": ["ebuilds"],
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/scan/directories/files.py b/repoman/lib/repoman/modules/scan/directories/files.py
deleted file mode 100644
index 246d8848333..00000000000
--- a/repoman/lib/repoman/modules/scan/directories/files.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# -*- coding:utf-8 -*-
-
-"""repoman/checks/diretories/files.py
-
-"""
-
-import io
-
-from portage import _encodings, _unicode_encode
-from portage import os
-
-from repoman.modules.vcs.vcs import vcs_new_changed
-from repoman.modules.scan.scanbase import ScanBase
-
-
-class FileChecks(ScanBase):
- """Performs various file checks in the package's directory"""
-
- def __init__(self, **kwargs):
- """
- @param portdb: portdb instance
- @param qatracker: QATracker instance
- @param repo_settings: settings instance
- @param vcs_settings: VCSSettings instance
- """
- super(FileChecks, self).__init__(**kwargs)
- self.portdb = kwargs.get("portdb")
- self.qatracker = kwargs.get("qatracker")
- self.repo_settings = kwargs.get("repo_settings")
- self.repoman_settings = self.repo_settings.repoman_settings
- self.vcs_settings = kwargs.get("vcs_settings")
-
- def check(self, **kwargs):
- """Checks the ebuild sources and files for errors
-
- @param checkdir: string, directory path
- @param checkdir_relative: repolevel determined path
- @param changed: dictionary instance
- @returns: dictionary
- """
- checkdir = kwargs.get("checkdir")
- checkdirlist = kwargs.get("checkdirlist").get()
- checkdir_relative = kwargs.get("checkdir_relative")
- changed = kwargs.get("changed").changed
- new = kwargs.get("changed").new
- for y_file in checkdirlist:
- index = self.repo_settings.repo_config.find_invalid_path_char(y_file)
- if index != -1:
- y_relative = os.path.join(checkdir_relative, y_file)
- invcs = self.vcs_settings.vcs is not None
- inchangeset = vcs_new_changed(y_relative, changed, new)
- if invcs and not inchangeset:
- # If the file isn't in the VCS new or changed set, then
- # assume that it's an irrelevant temporary file (Manifest
- # entries are not generated for file names containing
- # prohibited characters). See bug #406877.
- index = -1
- if index != -1:
- self.qatracker.add_error(
- "file.name", "%s/%s: char '%s'" % (checkdir, y_file, y_file[index])
- )
-
- if not (
- y_file in ("ChangeLog", "metadata.xml") or y_file.endswith(".ebuild")
- ):
- continue
- f = None
- try:
- line = 1
- f = io.open(
- _unicode_encode(
- os.path.join(checkdir, y_file),
- encoding=_encodings["fs"],
- errors="strict",
- ),
- mode="r",
- encoding=_encodings["repo.content"],
- )
- for l in f:
- line += 1
- except UnicodeDecodeError as ue:
- s = ue.object[: ue.start]
- l2 = s.count("\n")
- line += l2
- if l2 != 0:
- s = s[s.rfind("\n") + 1 :]
- self.qatracker.add_error(
- "file.UTF8",
- "%s/%s: line %i, just after: '%s'" % (checkdir, y_file, line, s),
- )
- finally:
- if f is not None:
- f.close()
- return False
-
- @property
- def runInPkgs(self):
- """Package level scans"""
- return (True, [self.check])
diff --git a/repoman/lib/repoman/modules/scan/directories/mtime.py b/repoman/lib/repoman/modules/scan/directories/mtime.py
deleted file mode 100644
index 34e21025705..00000000000
--- a/repoman/lib/repoman/modules/scan/directories/mtime.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from repoman.modules.scan.scanbase import ScanBase
-
-
-class MtimeChecks(ScanBase):
- def __init__(self, **kwargs):
- self.vcs_settings = kwargs.get("vcs_settings")
-
- def check(self, **kwargs):
- """Perform a changelog and untracked checks on the ebuild
-
- @param pkg: Package in which we check (object).
- @param ebuild: Ebuild which we check (object).
- @param changed: dictionary instance
- @returns: dictionary
- """
- ebuild = kwargs.get("ebuild").get()
- changed = kwargs.get("changed")
- pkg = kwargs.get("pkg").get()
- if not self.vcs_settings.vcs_preserves_mtime:
- if (
- ebuild.ebuild_path not in changed.new_ebuilds
- and ebuild.ebuild_path not in changed.ebuilds
- ):
- pkg.mtime = None
- return False
-
- @property
- def runInEbuilds(self):
- """Ebuild level scans"""
- return (True, [self.check])
diff --git a/repoman/lib/repoman/modules/scan/eapi/__init__.py b/repoman/lib/repoman/modules/scan/eapi/__init__.py
deleted file mode 100644
index a86d74b3c92..00000000000
--- a/repoman/lib/repoman/modules/scan/eapi/__init__.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Eapi plug-in module for repoman.
-Performs an IsEbuild check on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "eapi",
- "description": doc,
- "provides": {
- "live-module": {
- "name": "eapi",
- "sourcefile": "eapi",
- "class": "EAPIChecks",
- "description": doc,
- "functions": ["check"],
- "func_kwargs": {},
- "mod_kwargs": ["qatracker", "repo_settings"],
- "func_kwargs": {
- "ebuild": (None, None),
- },
- "module_runsIn": ["ebuilds"],
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/scan/eapi/eapi.py b/repoman/lib/repoman/modules/scan/eapi/eapi.py
deleted file mode 100644
index df7c220e644..00000000000
--- a/repoman/lib/repoman/modules/scan/eapi/eapi.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""eapi.py
-Perform checks on the EAPI variable.
-"""
-
-from repoman.modules.scan.scanbase import ScanBase
-
-
-class EAPIChecks(ScanBase):
- """Perform checks on the EAPI variable."""
-
- def __init__(self, **kwargs):
- """
- @param qatracker: QATracker instance
- @param repo_settings: Repository settings
- """
- self.qatracker = kwargs.get("qatracker")
- self.repo_settings = kwargs.get("repo_settings")
-
- def check(self, **kwargs):
- """
- @param pkg: Package in which we check (object).
- @param ebuild: Ebuild which we check (object).
- @returns: dictionary
- """
- ebuild = kwargs.get("ebuild").get()
-
- if not self._checkBanned(ebuild):
- self._checkDeprecated(ebuild)
- return False
-
- def _checkBanned(self, ebuild):
- if self.repo_settings.repo_config.eapi_is_banned(ebuild.eapi):
- self.qatracker.add_error(
- "repo.eapi-banned", "%s: %s" % (ebuild.relative_path, ebuild.eapi)
- )
- return True
- return False
-
- def _checkDeprecated(self, ebuild):
- if self.repo_settings.repo_config.eapi_is_deprecated(ebuild.eapi):
- self.qatracker.add_error(
- "repo.eapi-deprecated", "%s: %s" % (ebuild.relative_path, ebuild.eapi)
- )
- return True
- return False
-
- @property
- def runInEbuilds(self):
- """Ebuild level scans"""
- return (True, [self.check])
diff --git a/repoman/lib/repoman/modules/scan/ebuild/__init__.py b/repoman/lib/repoman/modules/scan/ebuild/__init__.py
deleted file mode 100644
index 029b5628dd1..00000000000
--- a/repoman/lib/repoman/modules/scan/ebuild/__init__.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Ebuild plug-in module for repoman.
-Performs an IsEbuild check on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "ebuild",
- "description": doc,
- "provides": {
- "ebuild-module": {
- "name": "ebuild",
- "sourcefile": "ebuild",
- "class": "Ebuild",
- "description": doc,
- "functions": ["check"],
- "func_desc": {},
- "mod_kwargs": [
- "qatracker",
- "repo_settings",
- "vcs_settings",
- "checks",
- "portdb",
- ],
- "func_kwargs": {
- "can_force": (None, None),
- "catdir": (None, None),
- "changed": (None, None),
- "changelog_modified": (None, None),
- "checkdir": (None, None),
- "checkdirlist": (None, None),
- "ebuild": ("Future", "UNSET"),
- "pkg": ("Future", "UNSET"),
- "pkgdir": (None, None),
- "pkgs": ("Future", "dict"),
- "repolevel": (None, None),
- "validity_future": (None, None),
- "xpkg": (None, None),
- "y_ebuild": (None, None),
- },
- "module_runsIn": ["pkgs", "ebuilds"],
- },
- "multicheck-module": {
- "name": "multicheck",
- "sourcefile": "multicheck",
- "class": "MultiCheck",
- "description": doc,
- "functions": ["check"],
- "func_kwargs": {},
- "mod_kwargs": [
- "qatracker",
- "options",
- "repo_settings",
- "linechecks",
- ],
- "func_kwargs": {
- "ebuild": (None, None),
- "pkg": (None, None),
- },
- "module_runsIn": ["ebuilds"],
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/scan/ebuild/ebuild.py b/repoman/lib/repoman/modules/scan/ebuild/ebuild.py
deleted file mode 100644
index ae327578004..00000000000
--- a/repoman/lib/repoman/modules/scan/ebuild/ebuild.py
+++ /dev/null
@@ -1,263 +0,0 @@
-# -*- coding:utf-8 -*-
-
-import re
-import stat
-
-from _emerge.Package import Package
-from _emerge.RootConfig import RootConfig
-
-from repoman.modules.scan.scanbase import ScanBase
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage import os
-from portage.exception import InvalidPackageName
-
-pv_toolong_re = re.compile(r"[0-9]{19,}")
-
-
-class Ebuild(ScanBase):
- """Class to run primary checks on ebuilds"""
-
- def __init__(self, **kwargs):
- """Class init
-
- @param qatracker: QATracker instance
- @param portdb: portdb instance
- @param repo_settings: repository settings instance
- @param vcs_settings: VCSSettings instance
- @param checks: checks dictionary
- """
- super(Ebuild, self).__init__(**kwargs)
- self.qatracker = kwargs.get("qatracker")
- self.portdb = kwargs.get("portdb")
- self.repo_settings = kwargs.get("repo_settings")
- self.vcs_settings = kwargs.get("vcs_settings")
- self.checks = kwargs.get("checks")
- self.root_config = RootConfig(
- self.repo_settings.repoman_settings,
- self.repo_settings.trees[self.repo_settings.root],
- None,
- )
- self.changed = None
- self.xpkg = None
- self.y_ebuild = None
- self.pkg = None
- self.metadata = None
- self.eapi = None
- self.inherited = None
- self.live_ebuild = None
- self.keywords = None
- self.pkgs = {}
-
- def _set_paths(self, **kwargs):
- repolevel = kwargs.get("repolevel")
- self.relative_path = os.path.join(self.xpkg, self.y_ebuild + ".ebuild")
- self.full_path = os.path.join(self.repo_settings.repodir, self.relative_path)
- self.ebuild_path = self.y_ebuild + ".ebuild"
- if repolevel < 3:
- self.ebuild_path = os.path.join(kwargs.get("pkgdir"), self.ebuild_path)
- if repolevel < 2:
- self.ebuild_path = os.path.join(kwargs.get("catdir"), self.ebuild_path)
- self.ebuild_path = os.path.join(".", self.ebuild_path)
-
- @property
- def untracked(self):
- """Determines and returns if the ebuild is not tracked by the vcs"""
- do_check = self.vcs_settings.vcs in ("cvs", "svn", "bzr")
- really_notadded = (
- self.checks["ebuild_notadded"]
- and self.y_ebuild not in self.vcs_settings.eadded
- )
- if do_check and really_notadded:
- # ebuild not added to vcs
- return True
- return False
-
- def check(self, **kwargs):
- """Perform a changelog and untracked checks on the ebuild
-
- @param xpkg: Package in which we check (object).
- @param y_ebuild: Ebuild which we check (string).
- @param changed: dictionary instance
- @param repolevel: The depth within the repository
- @param catdir: The category directiory
- @param pkgdir: the package directory
- @returns: dictionary, including {ebuild object}
- """
- self.xpkg = kwargs.get("xpkg")
- self.y_ebuild = kwargs.get("y_ebuild")
- self.changed = kwargs.get("changed")
- changelog_modified = kwargs.get("changelog_modified")
- self._set_paths(**kwargs)
-
- if (
- self.checks["changelog"]
- and not changelog_modified
- and self.ebuild_path in self.changed.new_ebuilds
- ):
- self.qatracker.add_error("changelog.ebuildadded", self.relative_path)
-
- if self.untracked:
- # ebuild not added to vcs
- self.qatracker.add_error(
- "ebuild.notadded", self.xpkg + "/" + self.y_ebuild + ".ebuild"
- )
- # update the dynamic data
- dyn_ebuild = kwargs.get("ebuild")
- dyn_ebuild.set(self)
- return False
-
- def set_pkg_data(self, **kwargs):
- """Sets some classwide data needed for some of the checks
-
- @returns: dictionary
- """
- self.pkg = self.pkgs[self.y_ebuild]
- self.metadata = self.pkg._metadata
- self.eapi = self.metadata["EAPI"]
- self.inherited = self.pkg.inherited
- self.live_ebuild = "live" in self.metadata["PROPERTIES"].split()
- self.keywords = self.metadata["KEYWORDS"].split()
- self.archs = set(
- kw.lstrip("~") for kw in self.keywords if not kw.startswith("-")
- )
- return False
-
- def bad_split_check(self, **kwargs):
- """Checks for bad category/package splits.
-
- @param pkgdir: string: path
- @returns: dictionary
- """
- pkgdir = kwargs.get("pkgdir")
- myesplit = portage.pkgsplit(self.y_ebuild)
- is_bad_split = myesplit is None or myesplit[0] != self.xpkg.split("/")[-1]
- if is_bad_split:
- is_pv_toolong = pv_toolong_re.search(myesplit[1])
- is_pv_toolong2 = pv_toolong_re.search(myesplit[2])
- if is_pv_toolong or is_pv_toolong2:
- self.qatracker.add_error(
- "ebuild.invalidname", self.xpkg + "/" + self.y_ebuild + ".ebuild"
- )
- return True
- elif myesplit[0] != pkgdir:
- print(pkgdir, myesplit[0])
- self.qatracker.add_error(
- "ebuild.namenomatch", self.xpkg + "/" + self.y_ebuild + ".ebuild"
- )
- return True
- return False
-
- def pkg_invalid(self, **kwargs):
- """Sets some pkg info and checks for invalid packages
-
- @param validity_future: Future instance
- @returns: dictionary, including {pkg object}
- """
- fuse = kwargs.get("validity_future")
- dyn_pkg = kwargs.get("pkg")
- if self.pkg.invalid:
- for k, msgs in self.pkg.invalid.items():
- for msg in msgs:
- self.qatracker.add_error(k, "%s: %s" % (self.relative_path, msg))
- # update the dynamic data
- fuse.set(False, ignore_InvalidState=True)
- dyn_pkg.set(self.pkg)
- return True
- # update the dynamic data
- dyn_pkg.set(self.pkg)
- return False
-
- def check_isebuild(self, **kwargs):
- """Test the file for qualifications that is is an ebuild
-
- @param checkdirlist: list of files in the current package directory
- @param checkdir: current package directory path
- @param xpkg: current package directory being checked
- @param validity_future: Future instance
- @returns: dictionary, including {pkgs, can_force}
- """
- checkdirlist = kwargs.get("checkdirlist").get()
- checkdir = kwargs.get("checkdir")
- xpkg = kwargs.get("xpkg")
- fuse = kwargs.get("validity_future")
- can_force = kwargs.get("can_force")
- self.continue_ = False
- ebuildlist = []
- pkgs = {}
- for y in checkdirlist:
- file_is_ebuild = y.endswith(".ebuild")
- file_should_be_non_executable = (
- y in self.repo_settings.qadata.no_exec or file_is_ebuild
- )
-
- if file_should_be_non_executable:
- file_is_executable = (
- stat.S_IMODE(os.stat(os.path.join(checkdir, y)).st_mode) & 0o111
- )
-
- if file_is_executable:
- self.qatracker.add_error(
- "file.executable", os.path.join(checkdir, y)
- )
- if file_is_ebuild:
- pf = y[:-7]
- ebuildlist.append(pf)
- catdir = xpkg.split("/")[0]
- cpv = "%s/%s" % (catdir, pf)
- allvars = self.repo_settings.qadata.allvars
- try:
- myaux = dict(zip(allvars, self.portdb.aux_get(cpv, allvars)))
- except KeyError:
- fuse.set(False, ignore_InvalidState=True)
- self.qatracker.add_error("ebuild.syntax", os.path.join(xpkg, y))
- continue
- except IOError:
- fuse.set(False, ignore_InvalidState=True)
- self.qatracker.add_error("ebuild.output", os.path.join(xpkg, y))
- continue
- except InvalidPackageName:
- fuse.set(False, ignore_InvalidState=True)
- self.qatracker.add_error(
- "ebuild.invalidname", os.path.join(xpkg, y)
- )
- continue
- if not portage.eapi_is_supported(myaux["EAPI"]):
- fuse.set(False, ignore_InvalidState=True)
- self.qatracker.add_error("EAPI.unsupported", os.path.join(xpkg, y))
- continue
- pkgs[pf] = Package(
- cpv=cpv,
- metadata=myaux,
- root_config=self.root_config,
- type_name="ebuild",
- )
-
- if len(pkgs) != len(ebuildlist):
- # If we can't access all the metadata then it's totally unsafe to
- # commit since there's no way to generate a correct Manifest.
- # Do not try to do any more QA checks on this package since missing
- # metadata leads to false positives for several checks, and false
- # positives confuse users.
- self.continue_ = True
- can_force.set(False, ignore_InvalidState=True)
- self.pkgs = pkgs
- # set our updated data
- dyn_pkgs = kwargs.get("pkgs")
- dyn_pkgs.set(pkgs)
- return self.continue_
-
- @property
- def runInPkgs(self):
- """Package level scans"""
- return (True, [self.check_isebuild])
-
- @property
- def runInEbuilds(self):
- """Ebuild level scans"""
- return (
- True,
- [self.check, self.set_pkg_data, self.bad_split_check, self.pkg_invalid],
- )
diff --git a/repoman/lib/repoman/modules/scan/ebuild/multicheck.py b/repoman/lib/repoman/modules/scan/ebuild/multicheck.py
deleted file mode 100644
index 1db0dfc92a9..00000000000
--- a/repoman/lib/repoman/modules/scan/ebuild/multicheck.py
+++ /dev/null
@@ -1,62 +0,0 @@
-"""multicheck.py
-Perform multiple different checks on an ebuild
-"""
-
-import io
-
-from portage import _encodings, _unicode_encode
-
-from repoman.modules.scan.scanbase import ScanBase
-from repoman.modules.linechecks.controller import LineCheckController
-
-
-class MultiCheck(ScanBase):
- """Class to run multiple different checks on an ebuild"""
-
- def __init__(self, **kwargs):
- """Class init
-
- @param qatracker: QATracker instance
- @param options: the run time cli options
- """
- self.qatracker = kwargs.get("qatracker")
- self.options = kwargs.get("options")
- self.controller = LineCheckController(
- kwargs.get("repo_settings"), kwargs.get("linechecks")
- )
- self.controller.checks_init(self.options.experimental_inherit == "y")
-
- def check(self, **kwargs):
- """Check the ebuild for utf-8 encoding
-
- @param pkg: Package in which we check (object).
- @param ebuild: Ebuild which we check (object).
- @returns: dictionary
- """
- ebuild = kwargs.get("ebuild").get()
- pkg = kwargs.get("pkg").get()
- try:
- # All ebuilds should have utf_8 encoding.
- f = io.open(
- _unicode_encode(
- ebuild.full_path, encoding=_encodings["fs"], errors="strict"
- ),
- mode="r",
- encoding=_encodings["repo.content"],
- )
- try:
- for check_name, e in self.controller.run_checks(f, pkg):
- self.qatracker.add_error(
- check_name, ebuild.relative_path + ": %s" % e
- )
- finally:
- f.close()
- except UnicodeDecodeError:
- # A file.UTF8 failure will have already been recorded.
- pass
- return False
-
- @property
- def runInEbuilds(self):
- """Ebuild level scans"""
- return (True, [self.check])
diff --git a/repoman/lib/repoman/modules/scan/eclasses/__init__.py b/repoman/lib/repoman/modules/scan/eclasses/__init__.py
deleted file mode 100644
index 8a14000e8fb..00000000000
--- a/repoman/lib/repoman/modules/scan/eclasses/__init__.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Eclasses plug-in module for repoman.
-Performs an live and ruby eclass checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "eclasses",
- "description": doc,
- "provides": {
- "live-module": {
- "name": "live",
- "sourcefile": "live",
- "class": "LiveEclassChecks",
- "description": doc,
- "functions": ["check"],
- "func_kwargs": {},
- "mod_kwargs": [
- "qatracker",
- "repo_metadata",
- "repo_settings",
- ],
- "func_kwargs": {
- "ebuild": (None, None),
- "pkg": (None, None),
- "xpkg": (None, None),
- "y_ebuild": (None, None),
- },
- "module_runsIn": ["ebuilds"],
- },
- "ruby-module": {
- "name": "ruby",
- "sourcefile": "ruby",
- "class": "RubyEclassChecks",
- "description": doc,
- "functions": ["check"],
- "func_kwargs": {},
- "mod_kwargs": ["qatracker", "repo_settings"],
- "func_kwargs": {
- "ebuild": (None, None),
- "pkg": (None, None),
- },
- "module_runsIn": ["ebuilds"],
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/scan/eclasses/live.py b/repoman/lib/repoman/modules/scan/eclasses/live.py
deleted file mode 100644
index 82ee168ed32..00000000000
--- a/repoman/lib/repoman/modules/scan/eclasses/live.py
+++ /dev/null
@@ -1,77 +0,0 @@
-"""live.py
-Performs Live eclass checks
-"""
-
-from repoman._portage import portage
-from repoman.modules.scan.scanbase import ScanBase
-
-
-class LiveEclassChecks(ScanBase):
- """Performs checks for the usage of Live eclasses in ebuilds"""
-
- def __init__(self, **kwargs):
- """
- @param qatracker: QATracker instance
- """
- self.qatracker = kwargs.get("qatracker")
- self.pmaskdict = kwargs.get("repo_metadata")["pmaskdict"]
- self.repo_settings = kwargs.get("repo_settings")
-
- def check(self, **kwargs):
- """Ebuilds that inherit a "Live" eclass (darcs, subversion, git, cvs,
- etc..) should not be allowed to be marked stable
-
- @param pkg: Package in which we check (object).
- @param xpkg: Package in which we check (string).
- @param ebuild: Ebuild which we check (object).
- @param y_ebuild: Ebuild which we check (string).
- @returns: boolean
- """
- pkg = kwargs.get("pkg").result()
- package = kwargs.get("xpkg")
- ebuild = kwargs.get("ebuild").get()
- y_ebuild = kwargs.get("y_ebuild")
-
- if ebuild.live_ebuild and self.repo_settings.repo_config.name == "gentoo":
- return self.check_live(pkg, package, ebuild, y_ebuild)
- return False
-
- def check_live(self, pkg, package, ebuild, y_ebuild):
- """Perform the live vcs check
-
- @param pkg: Package in which we check (object).
- @param xpkg: Package in which we check (string).
- @param ebuild: Ebuild which we check (object).
- @param y_ebuild: Ebuild which we check (string).
- @returns: boolean
- """
- keywords = ebuild.keywords
- is_stable = lambda kw: not kw.startswith("~") and not kw.startswith("-")
- bad_stable_keywords = list(filter(is_stable, keywords))
-
- if bad_stable_keywords:
- self.qatracker.add_error(
- "LIVEVCS.stable",
- "%s/%s.ebuild with stable keywords: %s"
- % (package, y_ebuild, bad_stable_keywords),
- )
-
- good_keywords_exist = len(bad_stable_keywords) < len(keywords)
- if good_keywords_exist and not self._has_global_mask(pkg, self.pmaskdict):
- self.qatracker.add_error("LIVEVCS.unmasked", ebuild.relative_path)
- return False
-
- @staticmethod
- def _has_global_mask(pkg, global_pmaskdict):
- mask_atoms = global_pmaskdict.get(pkg.cp)
- if mask_atoms:
- pkg_list = [pkg]
- for x in mask_atoms:
- if portage.dep.match_from_list(x, pkg_list):
- return x
- return None
-
- @property
- def runInEbuilds(self):
- """Ebuild level scans"""
- return (True, [self.check])
diff --git a/repoman/lib/repoman/modules/scan/eclasses/ruby.py b/repoman/lib/repoman/modules/scan/eclasses/ruby.py
deleted file mode 100644
index 16043ee0c88..00000000000
--- a/repoman/lib/repoman/modules/scan/eclasses/ruby.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""ruby.py
-Performs Ruby eclass checks
-"""
-
-from repoman.modules.scan.scanbase import ScanBase
-
-
-class RubyEclassChecks(ScanBase):
- """Performs checks for the usage of Ruby eclasses in ebuilds"""
-
- def __init__(self, **kwargs):
- """
- @param qatracker: QATracker instance
- """
- super(RubyEclassChecks, self).__init__(**kwargs)
- self.qatracker = kwargs.get("qatracker")
- self.repo_settings = kwargs.get("repo_settings")
- self.old_ruby_eclasses = ["ruby-ng", "ruby-fakegem", "ruby"]
-
- def check(self, **kwargs):
- """Check ebuilds that inherit the ruby eclasses
-
- @param pkg: Package in which we check (object).
- @param ebuild: Ebuild which we check (object).
- @returns: dictionary
- """
- pkg = kwargs.get("pkg").get()
- ebuild = kwargs.get("ebuild").get()
- is_inherited = lambda eclass: eclass in pkg.inherited
- is_old_ruby_eclass_inherited = filter(is_inherited, self.old_ruby_eclasses)
-
- if is_old_ruby_eclass_inherited:
- ruby_intersection = pkg.iuse.all.intersection(
- self.repo_settings.qadata.ruby_deprecated
- )
-
- if ruby_intersection:
- for myruby in ruby_intersection:
- self.qatracker.add_error(
- "IUSE.rubydeprecated",
- (ebuild.relative_path + ": Deprecated ruby target: %s")
- % myruby,
- )
- return False
-
- @property
- def runInEbuilds(self):
- """Ebuild level scans"""
- return (True, [self.check])
diff --git a/repoman/lib/repoman/modules/scan/fetch/__init__.py b/repoman/lib/repoman/modules/scan/fetch/__init__.py
deleted file mode 100644
index 9bd9d468d48..00000000000
--- a/repoman/lib/repoman/modules/scan/fetch/__init__.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """fetches plug-in module for repoman.
-Performs fetch related checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "fetches",
- "description": doc,
- "provides": {
- "fetches-module": {
- "name": "fetches",
- "sourcefile": "fetches",
- "class": "FetchChecks",
- "description": doc,
- "functions": ["check"],
- "func_desc": {},
- "mod_kwargs": [
- "portdb",
- "qatracker",
- "repo_settings",
- "vcs_settings",
- ],
- "func_kwargs": {
- "changed": (None, None),
- "checkdir": (None, None),
- "checkdir_relative": (None, None),
- "ebuild": (None, None),
- "xpkg": (None, None),
- },
- "module_runsIn": ["pkgs", "ebuilds"],
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/scan/fetch/fetches.py b/repoman/lib/repoman/modules/scan/fetch/fetches.py
deleted file mode 100644
index 56a36a13fab..00000000000
--- a/repoman/lib/repoman/modules/scan/fetch/fetches.py
+++ /dev/null
@@ -1,205 +0,0 @@
-# -*- coding:utf-8 -*-
-
-"""fetches.py
-Performs the src_uri fetchlist and files checks
-"""
-
-from stat import S_ISDIR
-
-# import our initialized portage instance
-from repoman._portage import portage
-from repoman.modules.vcs.vcs import vcs_new_changed
-from repoman.modules.scan.scanbase import ScanBase
-
-from portage import os
-
-
-class FetchChecks(ScanBase):
- """Performs checks on the files needed for the ebuild"""
-
- def __init__(self, **kwargs):
- """
- @param portdb: portdb instance
- @param qatracker: QATracker instance
- @param repo_settings: repository settings instance
- @param vcs_settings: VCSSettings instance
- """
- super(FetchChecks, self).__init__(**kwargs)
- self.portdb = kwargs.get("portdb")
- self.qatracker = kwargs.get("qatracker")
- self.repo_settings = kwargs.get("repo_settings")
- self.repoman_settings = self.repo_settings.repoman_settings
- self.vcs_settings = kwargs.get("vcs_settings")
- self._src_uri_error = False
-
- # TODO: Build a regex instead here, for the SRC_URI.mirror check.
- self.thirdpartymirrors = {}
- profile_thirdpartymirrors = (
- self.repo_settings.repoman_settings.thirdpartymirrors().items()
- )
- for mirror_alias, mirrors in profile_thirdpartymirrors:
- # Skip thirdpartymirrors that do not list more than one mirror
- # anymore. There is no point in using mirror:// there and this
- # means that the thirdpartymirrors entry will most likely
- # be removed anyway.
- if len(mirrors) <= 1:
- continue
- for mirror in mirrors:
- if not mirror.endswith("/"):
- mirror += "/"
- self.thirdpartymirrors[mirror] = mirror_alias
-
- def check(self, **kwargs):
- """Checks the ebuild sources and files for errors
-
- @param xpkg: the pacakge being checked
- @param checkdir: string, directory path
- @param checkdir_relative: repolevel determined path
- @returns: boolean
- """
- xpkg = kwargs.get("xpkg")
- checkdir = kwargs.get("checkdir")
- checkdir_relative = kwargs.get("checkdir_relative")
- changed = kwargs.get("changed").changed
- new = kwargs.get("changed").new
- _digests = self.digests(checkdir)
- fetchlist_dict = portage.FetchlistDict(
- checkdir, self.repoman_settings, self.portdb
- )
- myfiles_all = []
- self._src_uri_error = False
- for mykey in fetchlist_dict:
- try:
- myfiles_all.extend(fetchlist_dict[mykey])
- except portage.exception.InvalidDependString as e:
- self._src_uri_error = True
- try:
- self.portdb.aux_get(mykey, ["SRC_URI"])
- except KeyError:
- # This will be reported as an "ebuild.syntax" error.
- pass
- else:
- self.qatracker.add_error(
- "SRC_URI.syntax", "%s.ebuild SRC_URI: %s" % (mykey, e)
- )
- del fetchlist_dict
- if not self._src_uri_error:
- # This test can produce false positives if SRC_URI could not
- # be parsed for one or more ebuilds. There's no point in
- # producing a false error here since the root cause will
- # produce a valid error elsewhere, such as "SRC_URI.syntax"
- # or "ebuild.sytax".
- myfiles_all = set(myfiles_all)
- for entry in _digests:
- if entry not in myfiles_all:
- self.qatracker.add_error("digest.unused", checkdir + "::" + entry)
- for entry in myfiles_all:
- if entry not in _digests:
- self.qatracker.add_error("digest.missing", checkdir + "::" + entry)
- del myfiles_all
-
- if os.path.exists(checkdir + "/files"):
- filesdirlist = os.listdir(checkdir + "/files")
-
- # Recurse through files directory, use filesdirlist as a stack;
- # appending directories as needed,
- # so people can't hide > 20k files in a subdirectory.
- while filesdirlist:
- y = filesdirlist.pop(0)
- relative_path = os.path.join(xpkg, "files", y)
- full_path = os.path.join(self.repo_settings.repodir, relative_path)
- try:
- mystat = os.stat(full_path)
- except OSError as oe:
- if oe.errno == 2:
- # don't worry about it. it likely was removed via fix above.
- continue
- else:
- raise oe
- if S_ISDIR(mystat.st_mode):
- if self.vcs_settings.status.isVcsDir(y):
- continue
- for z in os.listdir(checkdir + "/files/" + y):
- if self.vcs_settings.status.isVcsDir(z):
- continue
- filesdirlist.append(y + "/" + z)
- # Current policy is no files over 20 KiB, these are the checks.
- # File size over 20 KiB causes an error.
- elif mystat.st_size > 20480:
- self.qatracker.add_error(
- "file.size",
- "(%d KiB) %s/files/%s" % (mystat.st_size // 1024, xpkg, y),
- )
- elif mystat.st_size == 0:
- self.qatracker.add_error("file.empty", "%s/files/%s" % (xpkg, y))
-
- index = self.repo_settings.repo_config.find_invalid_path_char(y)
- if index != -1:
- y_relative = os.path.join(checkdir_relative, "files", y)
- if self.vcs_settings.vcs is not None and not vcs_new_changed(
- y_relative, changed, new
- ):
- # If the file isn't in the VCS new or changed set, then
- # assume that it's an irrelevant temporary file (Manifest
- # entries are not generated for file names containing
- # prohibited characters). See bug #406877.
- index = -1
- if index != -1:
- self.qatracker.add_error(
- "file.name", "%s/files/%s: char '%s'" % (checkdir, y, y[index])
- )
- return False
-
- def digests(self, checkdir):
- """Returns the freshly loaded digests
-
- @param checkdir: string, directory path
- """
- mf = self.repoman_settings.repositories.get_repo_for_location(
- os.path.dirname(os.path.dirname(checkdir))
- )
- mf = mf.load_manifest(checkdir, self.repoman_settings["DISTDIR"])
- _digests = mf.getTypeDigests("DIST")
- del mf
- return _digests
-
- def check_mirrors(self, **kwargs):
- """Check that URIs don't reference a server from thirdpartymirrors
-
- @param ebuild: Ebuild which we check (object).
- @returns: boolean
- """
- ebuild = kwargs.get("ebuild").get()
-
- for uri in portage.dep.use_reduce(
- ebuild.metadata["SRC_URI"],
- matchall=True,
- is_src_uri=True,
- eapi=ebuild.eapi,
- flat=True,
- ):
- contains_mirror = False
- for mirror, mirror_alias in self.thirdpartymirrors.items():
- if uri.startswith(mirror):
- contains_mirror = True
- break
- if not contains_mirror:
- continue
-
- new_uri = "mirror://%s/%s" % (mirror_alias, uri[len(mirror) :])
- self.qatracker.add_error(
- "SRC_URI.mirror",
- "%s: '%s' found in thirdpartymirrors, use '%s'"
- % (ebuild.relative_path, mirror, new_uri),
- )
- return False
-
- @property
- def runInPkgs(self):
- """Package level scans"""
- return (True, [self.check])
-
- @property
- def runInEbuilds(self):
- """Ebuild level scans"""
- return (True, [self.check_mirrors])
diff --git a/repoman/lib/repoman/modules/scan/keywords/__init__.py b/repoman/lib/repoman/modules/scan/keywords/__init__.py
deleted file mode 100644
index a830e35ba62..00000000000
--- a/repoman/lib/repoman/modules/scan/keywords/__init__.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Keywords plug-in module for repoman.
-Performs keywords checks on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "keywords",
- "description": doc,
- "provides": {
- "keywords-module": {
- "name": "keywords",
- "sourcefile": "keywords",
- "class": "KeywordChecks",
- "description": doc,
- "functions": ["prepare", "check"],
- "func_desc": {},
- "mod_kwargs": [
- "qatracker",
- "options",
- "repo_metadata",
- "profiles",
- ],
- "func_kwargs": {
- "changed": (None, None),
- "ebuild": ("Future", "UNSET"),
- "pkg": ("Future", "UNSET"),
- "xpkg": None,
- "y_ebuild": (None, None),
- },
- "module_runsIn": ["pkgs", "ebuilds", "final"],
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/scan/keywords/keywords.py b/repoman/lib/repoman/modules/scan/keywords/keywords.py
deleted file mode 100644
index 1e00421c6c7..00000000000
--- a/repoman/lib/repoman/modules/scan/keywords/keywords.py
+++ /dev/null
@@ -1,179 +0,0 @@
-# -*- coding:utf-8 -*-
-
-"""keywords.py
-Perform KEYWORDS related checks
-
-"""
-
-from repoman.modules.scan.scanbase import ScanBase
-
-
-class KeywordChecks(ScanBase):
- """Perform checks on the KEYWORDS of an ebuild"""
-
- def __init__(self, **kwargs):
- """
- @param qatracker: QATracker instance
- @param options: argparse options instance
- """
- super(KeywordChecks, self).__init__(**kwargs)
- self.qatracker = kwargs.get("qatracker")
- self.options = kwargs.get("options")
- self.repo_metadata = kwargs.get("repo_metadata")
- self.profiles = kwargs.get("profiles")
- self.slot_keywords = {}
-
- def prepare(self, **kwargs):
- """Prepare the checks for the next package."""
- self.slot_keywords = {}
- self.dropped_keywords = {}
- return False
-
- def check(self, **kwargs):
- """Perform the check.
-
- @param pkg: Package in which we check (object).
- @param xpkg: Package in which we check (string).
- @param ebuild: Ebuild which we check (object).
- @param y_ebuild: Ebuild which we check (string).
- @param ebuild_archs: Just the architectures (no prefixes) of the ebuild.
- @param changed: Changes instance
- @returns: dictionary
- """
- pkg = kwargs.get("pkg").get()
- xpkg = kwargs.get("xpkg")
- ebuild = kwargs.get("ebuild").get()
- y_ebuild = kwargs.get("y_ebuild")
- changed = kwargs.get("changed")
- if not self.options.straight_to_stable:
- self._checkAddedWithStableKeywords(
- xpkg, ebuild, y_ebuild, ebuild.keywords, changed
- )
-
- self._checkForDroppedKeywords(pkg, ebuild, ebuild.archs)
-
- self._checkForInvalidKeywords(ebuild, xpkg, y_ebuild)
-
- self._checkForMaskLikeKeywords(xpkg, y_ebuild, ebuild.keywords)
-
- self._checkForUnsortedKeywords(ebuild, xpkg, y_ebuild)
-
- self.slot_keywords[pkg.slot].update(ebuild.archs)
- return False
-
- def check_dropped_keywords(self, **kwargs):
- """Report on any dropped keywords for the latest ebuild in a slot
-
- @returns: boolean
- """
- for ebuild, arches in self.dropped_keywords.values():
- if arches:
- self.qatracker.add_error(
- "KEYWORDS.dropped", "%s: %s" % (ebuild, " ".join(sorted(arches)))
- )
- return False
-
- @staticmethod
- def _isKeywordStable(keyword):
- return not keyword.startswith("~") and not keyword.startswith("-")
-
- def _checkAddedWithStableKeywords(
- self, package, ebuild, y_ebuild, keywords, changed
- ):
- catdir, pkgdir = package.split("/")
-
- stable_keywords = list(filter(self._isKeywordStable, keywords))
- if stable_keywords:
- if ebuild.ebuild_path in changed.new_ebuilds and catdir != "virtual":
- stable_keywords.sort()
- self.qatracker.add_error(
- "KEYWORDS.stable",
- "%s/%s.ebuild added with stable keywords: %s"
- % (package, y_ebuild, " ".join(stable_keywords)),
- )
-
- def _checkForDroppedKeywords(self, pkg, ebuild, ebuild_archs):
- previous_keywords = self.slot_keywords.get(pkg.slot)
- if previous_keywords is None:
- self.slot_keywords[pkg.slot] = set()
- elif ebuild_archs and "*" not in ebuild_archs and not ebuild.live_ebuild:
- self.slot_keywords[pkg.slot].update(ebuild_archs)
- dropped_keywords = previous_keywords.difference(ebuild_archs)
- self.dropped_keywords[pkg.slot] = (
- ebuild.relative_path,
- {arch for arch in dropped_keywords},
- )
-
- def _checkForInvalidKeywords(self, ebuild, xpkg, y_ebuild):
- myuse = ebuild.keywords
-
- for mykey in myuse:
- if mykey not in ("-*", "*", "~*"):
- myskey = mykey
-
- if not self._isKeywordStable(myskey[:1]):
- myskey = myskey[1:]
-
- if myskey not in self.repo_metadata["kwlist"]:
- self.qatracker.add_error(
- "KEYWORDS.invalid", "%s/%s.ebuild: %s" % (xpkg, y_ebuild, mykey)
- )
- elif myskey not in self.profiles:
- self.qatracker.add_error(
- "KEYWORDS.invalid",
- "%s/%s.ebuild: %s (profile invalid)" % (xpkg, y_ebuild, mykey),
- )
-
- def _checkForMaskLikeKeywords(self, xpkg, y_ebuild, keywords):
- # KEYWORDS="-*" is a stupid replacement for package.mask
- # and screws general KEYWORDS semantics
- if "-*" in keywords:
- haskeyword = False
-
- for kw in keywords:
- if kw[0] == "~":
- kw = kw[1:]
- if kw in self.repo_metadata["kwlist"]:
- haskeyword = True
-
- if not haskeyword:
- self.qatracker.add_error(
- "KEYWORDS.stupid", "%s/%s.ebuild" % (xpkg, y_ebuild)
- )
-
- def _checkForUnsortedKeywords(self, ebuild, xpkg, y_ebuild):
- """Ebuilds that contain KEYWORDS
- which are not sorted alphabetically."""
-
- def sort_keywords(kw):
- # Split keywords containing hyphens. The part after
- # the hyphen should be treated as the primary key.
- # This is consistent with ekeyword.
- parts = list(reversed(kw.lstrip("~-").split("-", 1)))
- # Hack to make sure that keywords
- # without hyphens are sorted first
- if len(parts) == 1:
- parts.insert(0, "")
- return parts
-
- sorted_keywords = sorted(ebuild.keywords, key=sort_keywords)
- if sorted_keywords != ebuild.keywords:
- self.qatracker.add_error(
- "KEYWORDS.unsorted",
- "%s/%s.ebuild contains unsorted keywords" % (xpkg, y_ebuild),
- )
-
- @property
- def runInPkgs(self):
- """Package level scans"""
- return (True, [self.prepare])
-
- @property
- def runInEbuilds(self):
- """Ebuild level scans"""
- return (True, [self.check])
-
- @property
- def runInFinal(self):
- """Final package level scans"""
- return (True, [self.check_dropped_keywords])
diff --git a/repoman/lib/repoman/modules/scan/manifest/__init__.py b/repoman/lib/repoman/modules/scan/manifest/__init__.py
deleted file mode 100644
index 2315a2a7e6c..00000000000
--- a/repoman/lib/repoman/modules/scan/manifest/__init__.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Ebuild plug-in module for repoman.
-Performs an IsEbuild check on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "manifest",
- "description": doc,
- "provides": {
- "manifest-module": {
- "name": "manifests",
- "sourcefile": "manifests",
- "class": "Manifests",
- "description": doc,
- "functions": ["check", "create_manifest", "digest_check"],
- "func_desc": {},
- "mod_kwargs": [
- "options",
- "portdb",
- "qatracker",
- "repo_settings",
- ],
- "func_kwargs": {
- "checkdir": (None, None),
- "xpkg": (None, None),
- },
- "module_runsIn": ["pkgs"],
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/scan/manifest/manifests.py b/repoman/lib/repoman/modules/scan/manifest/manifests.py
deleted file mode 100644
index 24b4e7f9b4b..00000000000
--- a/repoman/lib/repoman/modules/scan/manifest/manifests.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# -*- coding:utf-8 -*-
-
-# import our initialized portage instance
-from repoman._portage import portage
-from repoman.modules.scan.scanbase import ScanBase
-
-from portage import os
-
-
-class Manifests(ScanBase):
- """Creates as well as checks pkg Manifest entries/files"""
-
- def __init__(self, **kwargs):
- """Class init
-
- @param options: the run time cli options
- @param portdb: portdb instance
- @param qatracker: QATracker instance
- @param repo_settings: repository settings instance
- """
- self.options = kwargs.get("options")
- self.portdb = kwargs.get("portdb")
- self.qatracker = kwargs.get("qatracker")
- self.repoman_settings = kwargs.get("repo_settings").repoman_settings
-
- def check(self, **kwargs):
- """Perform a changelog and untracked checks on the ebuild
-
- @param xpkg: Package in which we check (object).
- @param checkdir: the current package directory
- @returns: dictionary
- """
- checkdir = kwargs.get("checkdir")
- xpkg = kwargs.get("xpkg")
- if self.options.pretend:
- return False
- self.digest_check(xpkg, checkdir)
- if self.options.mode == "manifest-check":
- return True
- return False
-
- def digest_check(self, xpkg, checkdir):
- """Check the manifest entries, report any Q/A errors
-
- @param xpkg: the cat/pkg name to check
- @param checkdir: the directory path to check"""
- self.repoman_settings["O"] = checkdir
- self.repoman_settings["PORTAGE_QUIET"] = "1"
- if not portage.digestcheck([], self.repoman_settings, strict=1):
- self.qatracker.add_error("manifest.bad", os.path.join(xpkg, "Manifest"))
- self.repoman_settings.pop("PORTAGE_QUIET", None)
-
- @property
- def runInPkgs(self):
- """Package level scans"""
- return (True, [self.check])
diff --git a/repoman/lib/repoman/modules/scan/metadata/__init__.py b/repoman/lib/repoman/modules/scan/metadata/__init__.py
deleted file mode 100644
index c133b1b37dd..00000000000
--- a/repoman/lib/repoman/modules/scan/metadata/__init__.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Metadata plug-in module for repoman.
-Performs metadata checks on packages."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "metadata",
- "description": doc,
- "provides": {
- "pkg-metadata": {
- "name": "pkgmetadata",
- "sourcefile": "pkgmetadata",
- "class": "PkgMetadata",
- "description": doc,
- "functions": ["check"],
- "func_desc": {},
- "mod_kwargs": [
- "repo_settings",
- "qatracker",
- "options",
- "metadata_xsd",
- "uselist",
- ],
- "func_kwargs": {
- "checkdir": (None, None),
- "checkdirlist": (None, None),
- "ebuild": (None, None),
- "pkg": (None, None),
- "repolevel": (None, None),
- "validity_future": (None, None),
- "xpkg": (None, None),
- "y_ebuild": (None, None),
- },
- "module_runsIn": ["pkgs", "ebuilds", "final"],
- },
- "ebuild-metadata": {
- "name": "ebuild_metadata",
- "sourcefile": "ebuild_metadata",
- "class": "EbuildMetadata",
- "description": doc,
- "functions": ["check"],
- "func_desc": {},
- "mod_kwargs": [
- "qatracker",
- "repo_settings",
- ],
- "func_kwargs": {
- "catdir": (None, None),
- "ebuild": (None, None),
- "xpkg": (None, None),
- "y_ebuild": (None, None),
- },
- "module_runsIn": ["ebuilds"],
- },
- "description-metadata": {
- "name": "description",
- "sourcefile": "description",
- "class": "DescriptionChecks",
- "description": doc,
- "functions": ["check"],
- "func_desc": {},
- "mod_kwargs": ["qatracker", "repo_settings"],
- "func_kwargs": {
- "ebuild": (None, None),
- "pkg": ("Future", "UNSET"),
- },
- "module_runsIn": ["ebuilds"],
- },
- "restrict-metadata": {
- "name": "restrict",
- "sourcefile": "restrict",
- "class": "RestrictChecks",
- "description": doc,
- "functions": ["check"],
- "func_desc": {},
- "mod_kwargs": ["qatracker", "repo_settings"],
- "func_kwargs": {
- "ebuild": (None, None),
- "xpkg": (None, None),
- "y_ebuild": (None, None),
- },
- "module_runsIn": ["ebuilds"],
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/scan/metadata/description.py b/repoman/lib/repoman/modules/scan/metadata/description.py
deleted file mode 100644
index c9fb5e7f9ba..00000000000
--- a/repoman/lib/repoman/modules/scan/metadata/description.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""description.py
-Perform checks on the DESCRIPTION variable.
-"""
-
-from repoman.modules.scan.scanbase import ScanBase
-
-
-class DescriptionChecks(ScanBase):
- """Perform checks on the DESCRIPTION variable."""
-
- def __init__(self, **kwargs):
- """
- @param qatracker: QATracker instance
- """
- self.qatracker = kwargs.get("qatracker")
- self.repo_settings = kwargs.get("repo_settings")
-
- def checkTooLong(self, **kwargs):
- """
- @param pkg: Package in which we check (object).
- @param ebuild: Ebuild which we check (object).
- """
- ebuild = kwargs.get("ebuild").get()
- pkg = kwargs.get("pkg").get()
- # 14 is the length of DESCRIPTION=""
- if len(pkg._metadata["DESCRIPTION"]) > self.repo_settings.qadata.max_desc_len:
- self.qatracker.add_error(
- "DESCRIPTION.toolong",
- "%s: DESCRIPTION is %d characters (max %d)"
- % (
- ebuild.relative_path,
- len(pkg._metadata["DESCRIPTION"]),
- self.repo_settings.qadata.max_desc_len,
- ),
- )
- return False
-
- @property
- def runInPkgs(self):
- return (False, [])
-
- @property
- def runInEbuilds(self):
- return (True, [self.checkTooLong])
diff --git a/repoman/lib/repoman/modules/scan/metadata/ebuild_metadata.py b/repoman/lib/repoman/modules/scan/metadata/ebuild_metadata.py
deleted file mode 100644
index fd0552ce72a..00000000000
--- a/repoman/lib/repoman/modules/scan/metadata/ebuild_metadata.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# -*- coding:utf-8 -*-
-
-"""Ebuild Metadata Checks"""
-
-import re
-
-from repoman.modules.scan.scanbase import ScanBase
-
-from portage.dep import use_reduce
-
-NON_ASCII_RE = re.compile(r"[^\x00-\x7f]")
-URISCHEME_RE = re.compile(r"^[a-z][0-9a-z\-\.\+]+://")
-
-
-class EbuildMetadata(ScanBase):
- def __init__(self, **kwargs):
- self.qatracker = kwargs.get("qatracker")
- self.repo_settings = kwargs.get("repo_settings")
-
- def invalidchar(self, **kwargs):
- ebuild = kwargs.get("ebuild").get()
- for k, v in ebuild.metadata.items():
- if not isinstance(v, str):
- continue
- m = NON_ASCII_RE.search(v)
- if m is not None:
- self.qatracker.add_error(
- "variable.invalidchar",
- "%s: %s variable contains non-ASCII "
- "character at position %s"
- % (ebuild.relative_path, k, m.start() + 1),
- )
- return False
-
- def missing(self, **kwargs):
- ebuild = kwargs.get("ebuild").get()
- for pos, missing_var in enumerate(self.repo_settings.qadata.missingvars):
- if not ebuild.metadata.get(missing_var):
- if kwargs.get("catdir") in (
- "acct-group",
- "acct-user",
- "virtual",
- ) and missing_var in ("HOMEPAGE", "LICENSE"):
- continue
- if ebuild.live_ebuild and missing_var == "KEYWORDS":
- continue
- myqakey = self.repo_settings.qadata.missingvars[pos] + ".missing"
- self.qatracker.add_error(
- myqakey,
- "%s/%s.ebuild" % (kwargs.get("xpkg"), kwargs.get("y_ebuild")),
- )
- return False
-
- def virtual(self, **kwargs):
- ebuild = kwargs.get("ebuild").get()
- if kwargs.get("catdir") == "virtual":
- for var in ("HOMEPAGE", "LICENSE"):
- if ebuild.metadata.get(var):
- myqakey = var + ".virtual"
- self.qatracker.add_error(myqakey, ebuild.relative_path)
- return False
-
- def homepage_urischeme(self, **kwargs):
- ebuild = kwargs.get("ebuild").get()
- if kwargs.get("catdir") != "virtual":
- for homepage in use_reduce(
- ebuild.metadata["HOMEPAGE"], matchall=True, flat=True
- ):
- if URISCHEME_RE.match(homepage) is None:
- self.qatracker.add_error(
- "HOMEPAGE.missingurischeme", ebuild.relative_path
- )
- return False
-
- @property
- def runInPkgs(self):
- return (False, [])
-
- @property
- def runInEbuilds(self):
- return (
- True,
- [self.invalidchar, self.missing, self.virtual, self.homepage_urischeme],
- )
diff --git a/repoman/lib/repoman/modules/scan/metadata/pkgmetadata.py b/repoman/lib/repoman/modules/scan/metadata/pkgmetadata.py
deleted file mode 100644
index 0fb97a0dfc0..00000000000
--- a/repoman/lib/repoman/modules/scan/metadata/pkgmetadata.py
+++ /dev/null
@@ -1,221 +0,0 @@
-# -*- coding:utf-8 -*-
-
-"""Package Metadata Checks operations"""
-
-import sys
-import re
-
-from itertools import chain
-from collections import Counter
-
-try:
- from lxml import etree
- from lxml.etree import ParserError
-except (SystemExit, KeyboardInterrupt):
- raise
-except (ImportError, SystemError, RuntimeError, Exception):
- # broken or missing xml support
- # https://bugs.python.org/issue14988
- msg = ["Please emerge dev-python/lxml in order to use repoman."]
- from portage.output import EOutput
-
- out = EOutput()
- for line in msg:
- out.eerror(line)
- sys.exit(1)
-
-# import our initialized portage instance
-from repoman._portage import portage # pylint: disable=unused-import
-from repoman.metadata import metadata_dtd_uri
-from repoman.modules.scan.scanbase import ScanBase
-
-# pylint: disable=ungrouped-imports
-from portage.exception import InvalidAtom
-from portage import os
-from portage.dep import Atom
-from portage.xml.metadata import parse_metadata_use
-
-from .use_flags import USEFlagChecks
-
-metadata_xml_encoding = "UTF-8"
-metadata_xml_declaration = '<?xml version="1.0" encoding="%s"?>' % (
- metadata_xml_encoding,
-)
-metadata_doctype_name = "pkgmetadata"
-
-
-class PkgMetadata(ScanBase, USEFlagChecks):
- """Package metadata.xml checks"""
-
- def __init__(self, **kwargs):
- """PkgMetadata init function
-
- @param repo_settings: settings instance
- @param qatracker: QATracker instance
- @param options: argparse options instance
- @param metadata_xsd: path of metadata.xsd
- """
- super(PkgMetadata, self).__init__(**kwargs)
- repo_settings = kwargs.get("repo_settings")
- self.qatracker = kwargs.get("qatracker")
- self.options = kwargs.get("options")
- self.metadata_xsd = kwargs.get("metadata_xsd")
- self.globalUseFlags = kwargs.get("uselist")
- self.repoman_settings = repo_settings.repoman_settings
- self.musedict = {}
- self.muselist = set()
-
- def check(self, **kwargs):
- """Performs the checks on the metadata.xml for the package
- @param xpkg: the pacakge being checked
- @param checkdir: string, directory path
- @param checkdirlist: list of checkdir's
- @param repolevel: integer
- @returns: boolean
- """
- xpkg = kwargs.get("xpkg")
- checkdir = kwargs.get("checkdir")
- checkdirlist = kwargs.get("checkdirlist").get()
-
- self.musedict = {}
- if self.options.mode in ["manifest"]:
- self.muselist = frozenset(self.musedict)
- return False
-
- # metadata.xml file check
- if "metadata.xml" not in checkdirlist:
- self.qatracker.add_error("metadata.missing", xpkg + "/metadata.xml")
- self.muselist = frozenset(self.musedict)
- return False
-
- # metadata.xml parse check
- metadata_bad = False
-
- # read metadata.xml into memory
- try:
- _metadata_xml = etree.parse(os.path.join(checkdir, "metadata.xml"))
- except (ParserError, SyntaxError, EnvironmentError) as e:
- metadata_bad = True
- self.qatracker.add_error("metadata.bad", "%s/metadata.xml: %s" % (xpkg, e))
- del e
- self.muselist = frozenset(self.musedict)
- return False
-
- indentation_chars = Counter()
- for l in etree.tostring(_metadata_xml).splitlines():
- indentation_chars.update(re.match(rb"\s*", l).group(0))
- if len(indentation_chars) > 1:
- self.qatracker.add_error(
- "metadata.warning",
- "%s/metadata.xml: %s"
- % (xpkg, "inconsistent use of tabs and spaces in indentation"),
- )
-
- xml_encoding = _metadata_xml.docinfo.encoding
- if xml_encoding.upper() != metadata_xml_encoding:
- self.qatracker.add_error(
- "metadata.bad",
- "%s/metadata.xml: "
- "xml declaration encoding should be '%s', not '%s'"
- % (xpkg, metadata_xml_encoding, xml_encoding),
- )
-
- if not _metadata_xml.docinfo.doctype:
- metadata_bad = True
- self.qatracker.add_error(
- "metadata.bad", "%s/metadata.xml: %s" % (xpkg, "DOCTYPE is missing")
- )
- else:
- doctype_system = _metadata_xml.docinfo.system_url
- if doctype_system != metadata_dtd_uri:
- if doctype_system is None:
- system_problem = "but it is undefined"
- else:
- system_problem = "not '%s'" % doctype_system
- self.qatracker.add_error(
- "metadata.bad",
- "%s/metadata.xml: "
- "DOCTYPE: SYSTEM should refer to '%s', %s"
- % (xpkg, metadata_dtd_uri, system_problem),
- )
- doctype_name = _metadata_xml.docinfo.doctype.split(" ")[1]
- if doctype_name != metadata_doctype_name:
- self.qatracker.add_error(
- "metadata.bad",
- "%s/metadata.xml: "
- "DOCTYPE: name should be '%s', not '%s'"
- % (xpkg, metadata_doctype_name, doctype_name),
- )
-
- # load USE flags from metadata.xml
- self.musedict = parse_metadata_use(_metadata_xml)
- for atom in chain(*self.musedict.values()):
- if atom is None:
- continue
- try:
- atom = Atom(atom)
- except InvalidAtom as e:
- self.qatracker.add_error(
- "metadata.bad", "%s/metadata.xml: Invalid atom: %s" % (xpkg, e)
- )
- else:
- if atom.cp != xpkg:
- self.qatracker.add_error(
- "metadata.bad",
- "%s/metadata.xml: Atom contains "
- "unexpected cat/pn: %s" % (xpkg, atom),
- )
-
- # Only carry out if in package directory or check forced
- if not metadata_bad:
- validator = etree.XMLSchema(file=self.metadata_xsd)
- if not validator.validate(_metadata_xml):
- self._add_validate_errors(xpkg, validator.error_log)
- self.muselist = frozenset(self.musedict)
- return False
-
- def check_unused(self, **kwargs):
- """Reports on any unused metadata.xml use descriptions
-
- @param xpkg: the pacakge being checked
- @param used_useflags: use flag list
- @param validity_future: Future instance
- """
- xpkg = kwargs.get("xpkg")
- valid_state = kwargs.get("validity_future").get()
- # check if there are unused local USE-descriptions in metadata.xml
- # (unless there are any invalids, to avoid noise)
- if valid_state:
- for myflag in self.muselist.difference(self.usedUseFlags):
- self.qatracker.add_error(
- "metadata.bad",
- "%s/metadata.xml: unused local USE-description: '%s'"
- % (xpkg, myflag),
- )
- return False
-
- def _add_validate_errors(self, xpkg, log):
- listed = set()
- for error in log:
- msg_prefix = error.message.split(":", 1)[0]
- info = "%s %s" % (error.line, msg_prefix)
- if info not in listed:
- listed.add(info)
- self.qatracker.add_error(
- "metadata.bad",
- "%s/metadata.xml: line: %s, %s" % (xpkg, error.line, error.message),
- )
-
- @property
- def runInPkgs(self):
- """Package level scans"""
- return (True, [self.check])
-
- @property
- def runInEbuilds(self):
- return (True, [self.check_useflags])
-
- @property
- def runInFinal(self):
- """Final scans at the package level"""
- return (True, [self.check_unused])
diff --git a/repoman/lib/repoman/modules/scan/metadata/restrict.py b/repoman/lib/repoman/modules/scan/metadata/restrict.py
deleted file mode 100644
index 036af88f6e7..00000000000
--- a/repoman/lib/repoman/modules/scan/metadata/restrict.py
+++ /dev/null
@@ -1,58 +0,0 @@
-"""restrict.py
-Perform checks on the RESTRICT variable.
-"""
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from repoman.modules.scan.scanbase import ScanBase
-
-
-class RestrictChecks(ScanBase):
- """Perform checks on the RESTRICT variable."""
-
- def __init__(self, **kwargs):
- """
- @param qatracker: QATracker instance
- """
- self.qatracker = kwargs.get("qatracker")
- self.repo_settings = kwargs.get("repo_settings")
- if self.repo_settings.repo_config.restrict_allowed is None:
- self._restrict_allowed = self.repo_settings.qadata.valid_restrict
- else:
- self._restrict_allowed = self.repo_settings.repo_config.restrict_allowed
-
- def check(self, **kwargs):
- xpkg = kwargs.get("xpkg")
- ebuild = kwargs.get("ebuild").get()
- y_ebuild = kwargs.get("y_ebuild")
- myrestrict = None
-
- try:
- myrestrict = portage.dep.use_reduce(
- ebuild.metadata["RESTRICT"], matchall=1, flat=True
- )
- except portage.exception.InvalidDependString as e:
- self.qatracker.add_error(
- "RESTRICT.syntax", "%s: RESTRICT: %s" % (ebuild.relative_path, e)
- )
- del e
-
- if myrestrict:
- myrestrict = set(myrestrict)
- mybadrestrict = myrestrict.difference(self._restrict_allowed)
-
- if mybadrestrict:
- for mybad in mybadrestrict:
- self.qatracker.add_error(
- "RESTRICT.invalid", "%s/%s.ebuild: %s" % (xpkg, y_ebuild, mybad)
- )
- return False
-
- @property
- def runInPkgs(self):
- return (False, [])
-
- @property
- def runInEbuilds(self):
- return (True, [self.check])
diff --git a/repoman/lib/repoman/modules/scan/metadata/use_flags.py b/repoman/lib/repoman/modules/scan/metadata/use_flags.py
deleted file mode 100644
index f2116800e16..00000000000
--- a/repoman/lib/repoman/modules/scan/metadata/use_flags.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# -*- coding:utf-8 -*-
-
-"""use_flags.py
-Performs USE flag related checks
-"""
-
-# import our centrally initialized portage instance
-from repoman._portage import portage
-
-from portage import eapi
-from portage.eapi import eapi_has_iuse_defaults, eapi_has_required_use
-
-
-class USEFlagChecks:
- """Performs checks on USE flags listed in the ebuilds and metadata.xml"""
-
- def __init__(self, **kwargs):
- """Class init
-
- @param qatracker: QATracker instance
- @param globalUseFlags: Global USE flags
- """
- super(USEFlagChecks, self).__init__()
- self.qatracker = None
- self.globalUseFlags = None
- self.useFlags = []
- self.defaultUseFlags = []
- self.usedUseFlags = set()
-
- def check_useflags(self, **kwargs):
- """Perform the check.
-
- @param pkg: Package in which we check (object).
- @param xpkg: Package in which we check (string).
- @param ebuild: Ebuild which we check (object).
- @param y_ebuild: Ebuild which we check (string).
- @returns: dictionary, including {ebuild_UsedUseFlags, used_useflags}
- """
- pkg = kwargs.get("pkg").get()
- package = kwargs.get("xpkg")
- ebuild = kwargs.get("ebuild").get()
- y_ebuild = kwargs.get("y_ebuild")
- # reset state variables for the run
- self.useFlags = []
- self.defaultUseFlags = []
- # perform the checks
- self._checkGlobal(pkg)
- self._checkMetadata(package, ebuild, y_ebuild, self.muselist)
- self._checkRequiredUSE(pkg, ebuild)
- return False
-
- def _checkGlobal(self, pkg):
- for myflag in pkg._metadata["IUSE"].split():
- flag_name = myflag.lstrip("+-")
- self.usedUseFlags.add(flag_name)
- if myflag != flag_name:
- self.defaultUseFlags.append(myflag)
- if flag_name not in self.globalUseFlags:
- self.useFlags.append(flag_name)
-
- def _checkMetadata(self, package, ebuild, y_ebuild, localUseFlags):
- for mypos in range(len(self.useFlags) - 1, -1, -1):
- if self.useFlags[mypos] and (self.useFlags[mypos] in localUseFlags):
- del self.useFlags[mypos]
-
- if self.defaultUseFlags and not eapi_has_iuse_defaults(eapi):
- for myflag in self.defaultUseFlags:
- self.qatracker.add_error(
- "EAPI.incompatible",
- "%s: IUSE defaults"
- " not supported with EAPI='%s': '%s'"
- % (ebuild.relative_path, eapi, myflag),
- )
-
- for mypos in range(len(self.useFlags)):
- self.qatracker.add_error(
- "IUSE.invalid",
- "%s/%s.ebuild: %s" % (package, y_ebuild, self.useFlags[mypos]),
- )
-
- def _checkRequiredUSE(self, pkg, ebuild):
- required_use = pkg._metadata["REQUIRED_USE"]
- if required_use:
- if not eapi_has_required_use(eapi):
- self.qatracker.add_error(
- "EAPI.incompatible",
- "%s: REQUIRED_USE"
- " not supported with EAPI='%s'"
- % (
- ebuild.relative_path,
- eapi,
- ),
- )
- try:
- portage.dep.check_required_use(
- required_use, (), pkg.iuse.is_valid_flag, eapi=eapi
- )
- except portage.exception.InvalidDependString as e:
- self.qatracker.add_error(
- "REQUIRED_USE.syntax",
- "%s: REQUIRED_USE: %s" % (ebuild.relative_path, e),
- )
- del e
diff --git a/repoman/lib/repoman/modules/scan/module.py b/repoman/lib/repoman/modules/scan/module.py
deleted file mode 100644
index 9e67f9bd618..00000000000
--- a/repoman/lib/repoman/modules/scan/module.py
+++ /dev/null
@@ -1,127 +0,0 @@
-"""
-moudules/scan/module.py
-Module loading and run list generator
-"""
-
-import logging
-import os
-import yaml
-
-import portage
-from portage.module import InvalidModuleName, Modules
-from portage.util import stack_lists
-from repoman import _not_installed
-from repoman.config import ConfigError
-
-MODULES_PATH = os.path.dirname(__file__)
-# initial development debug info
-logging.debug("module path: %s", MODULES_PATH)
-
-
-class ModuleConfig:
- """Holds the scan modules configuration information and
- creates the ordered list of modulles to run"""
-
- def __init__(self, configpaths, valid_versions=None, repository_modules=False):
- """Module init
-
- @param configpaths: ordered list of filepaths to load
- """
- if repository_modules:
- self.configpaths = [
- os.path.join(path, "repository.yaml") for path in configpaths
- ]
- elif _not_installed:
- self.configpaths = [
- os.path.realpath(
- os.path.join(
- os.path.dirname(
- os.path.dirname(
- os.path.dirname(
- os.path.dirname(os.path.dirname(__file__))
- )
- )
- ),
- "cnf/repository/repository.yaml",
- )
- )
- ]
- else:
- self.configpaths = [
- os.path.join(
- portage.const.EPREFIX or "/",
- "usr/share/repoman/repository/repository.yaml",
- )
- ]
- logging.debug("ModuleConfig; configpaths: %s", self.configpaths)
-
- self.controller = Modules(path=MODULES_PATH, namepath="repoman.modules.scan")
- logging.debug("ModuleConfig; module_names: %s", self.controller.module_names)
-
- self._configs = None
- self.enabled = []
- self.pkgs_loop = []
- self.ebuilds_loop = []
- self.final_loop = []
- self.modules_forced = ["ebuild", "mtime"]
- self.load_configs(valid_versions=valid_versions)
- for loop in ["pkgs", "ebuilds", "final"]:
- logging.debug("ModuleConfig; Processing loop %s", loop)
- setattr(self, "%s_loop" % loop, self._determine_list(loop))
- self.linechecks = stack_lists(
- c["linechecks_modules"].split() for c in self._configs
- )
-
- def load_configs(self, configpaths=None, valid_versions=None):
- """load the config files in order
-
- @param configpaths: ordered list of filepaths to load
- """
- if configpaths:
- self.configpaths = configpaths
- elif not self.configpaths:
- logging.error("ModuleConfig; Error: No repository.yaml files defined")
- configs = []
- for path in self.configpaths:
- logging.debug("ModuleConfig; Processing: %s", path)
- if os.path.exists(path):
- try:
- with open(path, "r") as inputfile:
- configs.append(yaml.safe_load(inputfile))
- except IOError as error:
- logging, error("Failed to load file: %s", inputfile)
- logging.exception(error)
- else:
- if configs[-1]["version"] not in valid_versions:
- raise ConfigError(
- "Invalid file version: %s in: %s\nPlease upgrade repoman"
- % (configs["version"], path)
- )
- logging.debug("ModuleConfig; completed : %s", path)
- logging.debug("ModuleConfig; new _configs: %s", configs)
- self._configs = configs
-
- def _determine_list(self, loop):
- """Determine the ordered list from the config data and
- the moule_runsIn value in the module_spec
-
- @returns: list of modules
- """
- lists = [c["scan_modules"].split() for c in self._configs]
- stacked = self.modules_forced + stack_lists(lists)
- mlist = []
- try:
- for mod in stacked:
- logging.debug(
- "ModuleConfig; checking loop %s, module: %s, in: %s",
- loop,
- mod,
- self.controller.get_spec(mod, "module_runsIn"),
- )
- if loop in self.controller.get_spec(mod, "module_runsIn"):
- mlist.append(mod)
- except InvalidModuleName:
- logging.error("ModuleConfig; unknown module: %s, skipping", mod)
-
- logging.debug("ModuleConfig; mlist: %s", mlist)
- return mlist
diff --git a/repoman/lib/repoman/modules/scan/options/__init__.py b/repoman/lib/repoman/modules/scan/options/__init__.py
deleted file mode 100644
index ce57cbbfc62..00000000000
--- a/repoman/lib/repoman/modules/scan/options/__init__.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 2015-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Options plug-in module for repoman.
-Performs option related actions on ebuilds."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "options",
- "description": doc,
- "provides": {
- "options-module": {
- "name": "options",
- "sourcefile": "options",
- "class": "Options",
- "description": doc,
- "functions": ["is_forced"],
- "func_desc": {},
- "mod_kwargs": [
- "options",
- ],
- "func_kwargs": {},
- "module_runsIn": ["ebuilds"],
- },
- },
- "version": 1,
-}
diff --git a/repoman/lib/repoman/modules/scan/options/options.py b/repoman/lib/repoman/modules/scan/options/options.py
deleted file mode 100644
index 2a16be7ef2e..00000000000
--- a/repoman/lib/repoman/modules/scan/options/options.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from repoman.modules.scan.scanbase import ScanBase
-
-
-class Options(ScanBase):
- def __init__(self, **kwargs):
- """Class init function
-
- @param options: argparse options instance
- """
- self.options = kwargs.get("options")
-
- def is_forced(self, **kwargs):
- """Simple boolean function to trigger a skip past some additional checks
-
- @returns: dictionary
- """
- if self.options.force:
- # The dep_check() calls are the most expensive QA test. If --force
- # is enabled, there's no point in wasting time on these since the
- # user is intent on forcing the commit anyway.
- return True
- return False
-
- @property
- def runInEbuilds(self):
- """Ebuild level scans"""
- return (True, [self.is_forced])
diff --git a/repoman/lib/repoman/modules/scan/scan.py b/repoman/lib/repoman/modules/scan/scan.py
deleted file mode 100644
index 30de50c3577..00000000000
--- a/repoman/lib/repoman/modules/scan/scan.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# -*- coding:utf-8 -*-
-
-"""
-moudules/scan.py
-Module specific package scan list generator
-"""
-
-import logging
-import os
-import sys
-
-from repoman.errors import caterror
-
-
-def scan(repolevel, reposplit, startdir, categories, repo_settings):
- """Generate a list of pkgs to scan
-
- @param repolevel: integer, number of subdirectories deep from the tree root
- @param reposplit: list of the path subdirs
- @param startdir: the top level directory to begin scanning from
- @param categories: list of known categories
- @param repo_settings: repository settings instance
- @returns: scanlist, sorted list of pkgs to scan
- """
- scanlist = []
- if repolevel == 2:
- # we are inside a category directory
- catdir = reposplit[-1]
- if catdir not in categories:
- caterror(catdir, repo_settings.repodir)
- mydirlist = os.listdir(startdir)
- for x in mydirlist:
- if x == "CVS" or x.startswith("."):
- continue
- if os.path.isdir(startdir + "/" + x):
- scanlist.append(catdir + "/" + x)
- # repo_subdir = catdir + os.sep
- elif repolevel == 1:
- for x in categories:
- if not os.path.isdir(startdir + "/" + x):
- continue
- for y in os.listdir(startdir + "/" + x):
- if y == "CVS" or y.startswith("."):
- continue
- if os.path.isdir(startdir + "/" + x + "/" + y):
- scanlist.append(x + "/" + y)
- # repo_subdir = ""
- elif repolevel == 3:
- catdir = reposplit[-2]
- if catdir not in categories:
- caterror(catdir, repo_settings.repodir)
- scanlist.append(catdir + "/" + reposplit[-1])
- # repo_subdir = scanlist[-1] + os.sep
- else:
- msg = (
- "Repoman is unable to determine PORTDIR or PORTDIR_OVERLAY"
- + " from the current working directory"
- )
- logging.critical(msg)
- sys.exit(1)
-
- # repo_subdir_len = len(repo_subdir)
- scanlist.sort()
-
- logging.debug("Found the following packages to scan:\n%s" % "\n".join(scanlist))
-
- return scanlist
diff --git a/repoman/lib/repoman/modules/scan/scanbase.py b/repoman/lib/repoman/modules/scan/scanbase.py
deleted file mode 100644
index 5a7cd62193b..00000000000
--- a/repoman/lib/repoman/modules/scan/scanbase.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# -*- coding:utf-8 -*-
-
-
-class ScanBase:
- """Skeleton class for performing a scan for one or more items
- to check in a pkg directory or ebuild."""
-
- def __init__(self, **kwargs):
- """Class init
-
- @param kwargs: an optional dictionary of common repository
- wide parameters that may be required.
- """
- # Since no two checks are identicle as to what kwargs are needed,
- # this does not define any from it here.
- super(ScanBase, self).__init__()
-
- """ # sample check
- def check_foo(self, **kwargs):
- '''Class check skeleton function. Define this for a
- specific check to perform.
-
- @param kwargs: an optional dictionary of dynamic package and or ebuild
- specific data that may be required. Dynamic data can
- vary depending what checks have run before it.
- So execution order can be important.
- '''
- # Insert the code for the check here
- # It should return a dictionary of at least {'continue': False}
- # The continue attribute will default to False if not returned.
- # This will allow the loop to continue with the next check in the list.
- # Include any additional dynamic data that needs to be added or updated.
- return False # used as a continue True/False value
- """
-
- @property
- def runInPkgs(self):
- """Package level scans"""
- # default no run (False) and empty list of functions to run
- # override this method to define a function or
- # functions to run in this process loop
- # return a tuple of a boolean or boolean result and an ordered list
- # of functions to run. ie: return (True, [self.check_foo])
- # in this way, it can be dynamically determined at run time, if
- # later stage scans are to be run.
- # This class instance is maintaned for all stages, so data can be
- # carried over from stage to stage
- # next stage is runInEbuilds
- return (False, [])
-
- @property
- def runInEbuilds(self):
- """Ebuild level scans"""
- # default empty list of functions to run
- # override this method to define a function or
- # functions to run in this process loop
- # return a tuple of a boolean or boolean result and an ordered list
- # of functions to run. ie: return (True, [self.check_bar])
- # in this way, it can be dynamically determined at run time, if
- # later stage scans are to be run.
- # This class instance is maintaned for all stages, so data can be
- # carried over from stage to stage
- # next stage is runInFinal
- return (False, [])
-
- @property
- def runInFinal(self):
- """Final scans at the package level"""
- # default empty list of functions to run
- # override this method to define a function or
- # functions to run in this process loop
- # return a tuple of a boolean or boolean result and an ordered list
- # of functions to run. ie: return (True, [self.check_baz])
- # in this way, it can be dynamically determined at run time, if
- # later stage scans are to be run.
- # This class instance is maintaned for all stages, so data can be
- # carried over from stage to stage
- # runInFinal is currently the last stage of scans performed.
- return (False, [])
diff --git a/repoman/lib/repoman/modules/vcs/None/__init__.py b/repoman/lib/repoman/modules/vcs/None/__init__.py
deleted file mode 100644
index dc9eb51ad84..00000000000
--- a/repoman/lib/repoman/modules/vcs/None/__init__.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 2014-2015 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """None (non vcs type) plug-in module for portage.
-Performs various git actions and checks on repositories."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "None",
- "description": doc,
- "provides": {
- "None-module": {
- "name": "None_status",
- "sourcefile": "status",
- "class": "Status",
- "description": doc,
- "functions": ["check", "supports_gpg_sign", "detect_conflicts"],
- "func_desc": {},
- "vcs_preserves_mtime": False,
- "needs_keyword_expansion": False,
- },
- "None-changes": {
- "name": "None_changes",
- "sourcefile": "changes",
- "class": "Changes",
- "description": doc,
- "functions": ["scan"],
- "func_desc": {},
- },
- },
-}
diff --git a/repoman/lib/repoman/modules/vcs/None/changes.py b/repoman/lib/repoman/modules/vcs/None/changes.py
deleted file mode 100644
index 4164c84bf29..00000000000
--- a/repoman/lib/repoman/modules/vcs/None/changes.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""
-None module Changes class submodule
-"""
-
-from repoman.modules.vcs.changes import ChangesBase
-
-
-class Changes(ChangesBase):
- """Class object to scan and hold the resultant data
- for all changes to process.
- """
-
- vcs = "None"
-
- def __init__(self, options, repo_settings):
- """Class init
-
- @param options: the run time cli options
- @param repo_settings: RepoSettings instance
- """
- super(Changes, self).__init__(options, repo_settings)
-
- def scan(self):
- """VCS type scan function, looks for all detectable changes"""
- pass
-
- def add_items(self, autoadd):
- """Add files to the vcs's modified or new index
-
- @param autoadd: the files to add to the vcs modified index"""
- pass
-
- def commit(self, myfiles, commitmessagefile):
- """None commit function
-
- @param commitfiles: list of files to commit
- @param commitmessagefile: file containing the commit message
- @returns: The sub-command exit value or 0
- """
- commit_cmd = []
- # substitute a bogus vcs value for pretend output
- commit_cmd.append("pretend")
- commit_cmd.extend(self.vcs_settings.vcs_global_opts)
- commit_cmd.append("commit")
- commit_cmd.extend(self.vcs_settings.vcs_local_opts)
- commit_cmd.extend(["-F", commitmessagefile])
- commit_cmd.extend(f.lstrip("./") for f in myfiles)
-
- print("(%s)" % (" ".join(commit_cmd),))
- return 0
diff --git a/repoman/lib/repoman/modules/vcs/None/status.py b/repoman/lib/repoman/modules/vcs/None/status.py
deleted file mode 100644
index c5809bc9e29..00000000000
--- a/repoman/lib/repoman/modules/vcs/None/status.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""
-None (non-VCS) module Status class submodule
-"""
-
-
-class Status:
- """Performs status checks on the svn repository"""
-
- def __init__(self, qatracker, eadded):
- """Class init
-
- @param qatracker: QATracker class instance
- @param eadded: list
- """
- self.qatracker = qatracker
- self.eadded = eadded
-
- def check(self, checkdir, checkdir_relative, xpkg):
- """Perform the svn status check
-
- @param checkdir: string of the directory being checked
- @param checkdir_relative: string of the relative directory being checked
- @param xpkg: string of the package being checked
- @returns: boolean
- """
- return True
-
- @staticmethod
- def detect_conflicts(options):
- """Are there any merge conflicts present in the VCS tracking system
-
- @param options: command line options
- @returns: Boolean
- """
- return False
-
- @staticmethod
- def supports_gpg_sign():
- """Does this vcs system support gpg commit signatures
-
- @returns: Boolean
- """
- return False
-
- @staticmethod
- def isVcsDir(dirname):
- """Is the directory belong to the vcs system
-
- @param dirname: string, directory name
- @returns: Boolean
- """
- return False
diff --git a/repoman/lib/repoman/modules/vcs/__init__.py b/repoman/lib/repoman/modules/vcs/__init__.py
deleted file mode 100644
index 85cc979c059..00000000000
--- a/repoman/lib/repoman/modules/vcs/__init__.py
+++ /dev/null
@@ -1,12 +0,0 @@
-import os
-from portage.module import Modules
-
-path = os.path.dirname(__file__)
-# initial development debug info
-# print("module path:", path)
-
-module_controller = Modules(path=path, namepath="repoman.modules.vcs")
-
-# initial development debug info
-# print(module_controller.module_names)
-module_names = module_controller.module_names[:]
diff --git a/repoman/lib/repoman/modules/vcs/bzr/__init__.py b/repoman/lib/repoman/modules/vcs/bzr/__init__.py
deleted file mode 100644
index 982017da67d..00000000000
--- a/repoman/lib/repoman/modules/vcs/bzr/__init__.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 2014-2015 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Bazaar (bzr) plug-in module for portage.
-Performs variaous Bazaar actions and checks on repositories."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "bzr",
- "description": doc,
- "provides": {
- "bzr-module": {
- "name": "bzr_status",
- "sourcefile": "status",
- "class": "Status",
- "description": doc,
- "functions": ["check", "supports_gpg_sign", "detect_conflicts"],
- "func_desc": {},
- "vcs_preserves_mtime": True,
- "needs_keyword_expansion": False,
- },
- "bzr-changes": {
- "name": "bzr_changes",
- "sourcefile": "changes",
- "class": "Changes",
- "description": doc,
- "functions": ["scan"],
- "func_desc": {},
- },
- },
-}
diff --git a/repoman/lib/repoman/modules/vcs/bzr/changes.py b/repoman/lib/repoman/modules/vcs/bzr/changes.py
deleted file mode 100644
index 0366b38621f..00000000000
--- a/repoman/lib/repoman/modules/vcs/bzr/changes.py
+++ /dev/null
@@ -1,77 +0,0 @@
-"""
-Bazaar module Changes class submodule
-"""
-
-from repoman.modules.vcs.changes import ChangesBase
-from repoman._subprocess import repoman_popen
-from repoman._portage import portage # pylint: disable=unused-import
-from portage import os
-from portage.package.ebuild.digestgen import digestgen
-
-
-class Changes(ChangesBase):
- """Class object to scan and hold the resultant data
- for all changes to process.
- """
-
- vcs = "bzr"
-
- def __init__(self, options, repo_settings):
- """Class init
-
- @param options: the run time cli options
- @param repo_settings: RepoSettings instance
- """
- super(Changes, self).__init__(options, repo_settings)
-
- def _scan(self):
- """VCS type scan function, looks for all detectable changes"""
- with repoman_popen("bzr status -S .") as f:
- bzrstatus = f.readlines()
- self.changed = [
- "./" + elem.split()[-1:][0].split("/")[-1:][0]
- for elem in bzrstatus
- if elem and elem[1:2] == "M"
- ]
- self.new = [
- "./" + elem.split()[-1:][0].split("/")[-1:][0]
- for elem in bzrstatus
- if elem and (elem[1:2] == "NK" or elem[0:1] == "R")
- ]
- self.removed = [
- "./" + elem.split()[-3:-2][0].split("/")[-1:][0]
- for elem in bzrstatus
- if elem and (elem[1:2] == "K" or elem[0:1] == "R")
- ]
- self.bzrstatus = bzrstatus
- # Bazaar expands nothing.
-
- @property
- def unadded(self):
- """Bazzar method of getting the unadded files in the repository"""
- if self._unadded is not None:
- return self._unadded
- self._unadded = [
- "./" + elem.rstrip().split()[1].split("/")[-1:][0]
- for elem in self.bzrstatus
- if elem.startswith("?") or elem[0:2] == " D"
- ]
- return self._unadded
-
- def digest_regen(
- self, updates, removed, manifests, scanner, broken_changelog_manifests
- ):
- """Regenerate manifests
-
- @param updates: updated files
- @param removed: removed files
- @param manifests: Manifest files
- @param scanner: The repoman.scanner.Scanner instance
- @param broken_changelog_manifests: broken changelog manifests
- """
- if broken_changelog_manifests:
- for x in broken_changelog_manifests:
- self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
- digestgen(
- mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb
- )
diff --git a/repoman/lib/repoman/modules/vcs/bzr/status.py b/repoman/lib/repoman/modules/vcs/bzr/status.py
deleted file mode 100644
index 5ca18c4f637..00000000000
--- a/repoman/lib/repoman/modules/vcs/bzr/status.py
+++ /dev/null
@@ -1,72 +0,0 @@
-"""
-Bazaar module Status class submodule
-"""
-
-from repoman._portage import portage
-from portage import os
-
-# pylint: disable=ungrouped-imports
-from repoman._subprocess import repoman_popen
-
-
-class Status:
- """Performs status checks on the svn repository"""
-
- def __init__(self, qatracker, eadded):
- """Class init
-
- @param qatracker: QATracker class instance
- @param eadded: list
- """
- self.qatracker = qatracker
- self.eadded = eadded
-
- def check(self, checkdir, checkdir_relative, xpkg):
- """Perform the svn status check
-
- @param checkdir: string of the directory being checked
- @param checkdir_relative: string of the relative directory being checked
- @param xpkg: string of the package being checked
- @returns: boolean
- """
- try:
- myf = repoman_popen(
- "bzr ls -v --kind=file " + portage._shell_quote(checkdir)
- )
- myl = myf.readlines()
- myf.close()
- except IOError:
- raise
- for l in myl:
- if l[1:2] == "?":
- continue
- l = l.split()[-1]
- if l[-7:] == ".ebuild":
- self.eadded.append(os.path.basename(l[:-7]))
- return True
-
- @staticmethod
- def detect_conflicts(options):
- """Are there any merge conflicts present in the VCS tracking system
-
- @param options: command line options
- @returns: Boolean
- """
- return False
-
- @staticmethod
- def supports_gpg_sign():
- """Does this vcs system support gpg commit signatures
-
- @returns: Boolean
- """
- return False
-
- @staticmethod
- def isVcsDir(dirname):
- """Does the directory belong to the vcs system
-
- @param dirname: string, directory name
- @returns: Boolean
- """
- return dirname in [".bzr"]
diff --git a/repoman/lib/repoman/modules/vcs/changes.py b/repoman/lib/repoman/modules/vcs/changes.py
deleted file mode 100644
index c1c7b090965..00000000000
--- a/repoman/lib/repoman/modules/vcs/changes.py
+++ /dev/null
@@ -1,170 +0,0 @@
-"""
-Base Changes class
-"""
-
-import logging
-import os
-import subprocess
-import sys
-from itertools import chain
-
-from repoman._portage import portage
-from portage import _unicode_encode
-from portage.process import spawn
-
-
-class ChangesBase:
- """Base Class object to scan and hold the resultant data
- for all changes to process.
- """
-
- vcs = "None"
-
- def __init__(self, options, repo_settings):
- """Class init function
-
- @param options: the run time cli options
- @param repo_settings: RepoSettings instance
- """
- self.options = options
- self.repo_settings = repo_settings
- self.repoman_settings = repo_settings.repoman_settings
- self.vcs_settings = repo_settings.vcs_settings
- self._reset()
-
- def _reset(self):
- """Reset the class variables for a new run"""
- self.new_ebuilds = set()
- self.ebuilds = set()
- self.changelogs = set()
- self.changed = []
- self.new = []
- self.removed = []
- self.no_expansion = set()
- self._expansion = None
- self._deleted = None
- self._unadded = None
-
- def scan(self):
- """Scan the vcs for detectable changes.
-
- base method which calls the subclassing VCS module's _scan()
- then updates some classwide variables.
- """
- self._reset()
-
- if self.vcs:
- self._scan()
- self.new_ebuilds.update(x for x in self.new if x.endswith(".ebuild"))
- self.ebuilds.update(x for x in self.changed if x.endswith(".ebuild"))
- self.changelogs.update(
- x
- for x in chain(self.changed, self.new)
- if os.path.basename(x) == "ChangeLog"
- )
-
- def _scan(self):
- """Placeholder for subclassing"""
- pass
-
- @property
- def has_deleted(self):
- """Placeholder for VCS that requires manual deletion of files"""
- return self.deleted != []
-
- @property
- def has_changes(self):
- """Placeholder for VCS repo common has changes result"""
- changed = self.changed or self.new or self.removed or self.deleted
- return changed != []
-
- @property
- def unadded(self):
- """Override this function as needed"""
- return []
-
- @property
- def deleted(self):
- """Override this function as needed"""
- return []
-
- @property
- def expansion(self):
- """Override this function as needed"""
- return {}
-
- def thick_manifest(self, updates, headers, no_expansion, expansion):
- """Create a thick manifest
-
- @param updates:
- @param headers:
- @param no_expansion:
- @param expansion:
- """
- pass
-
- def digest_regen(
- self, updates, removed, manifests, scanner, broken_changelog_manifests
- ):
- """Regenerate manifests
-
- @param updates: updated files
- @param removed: removed files
- @param manifests: Manifest files
- @param scanner: The repoman.scanner.Scanner instance
- @param broken_changelog_manifests: broken changelog manifests
- """
- pass
-
- @staticmethod
- def clear_attic(headers):
- """Old CVS leftover
-
- @param headers: file headers"""
- pass
-
- def update_index(self, mymanifests, myupdates):
- """Update the vcs's modified index if it is needed
-
- @param mymanifests: manifest files updated
- @param myupdates: other files updated"""
- pass
-
- def add_items(self, autoadd):
- """Add files to the vcs's modified or new index
-
- @param autoadd: the files to add to the vcs modified index"""
- add_cmd = [self.vcs, "add"]
- add_cmd += autoadd
- if self.options.pretend:
- portage.writemsg_stdout("(%s)\n" % " ".join(add_cmd), noiselevel=-1)
- else:
- add_cmd = [_unicode_encode(arg) for arg in add_cmd]
- retcode = subprocess.call(add_cmd)
- if retcode != os.EX_OK:
- logging.error(
- "Exiting on %s error code: %s\n", self.vcs_settings.vcs, retcode
- )
- sys.exit(retcode)
-
- def commit(self, commitfiles, commitmessagefile):
- """Common generic commit function
-
- @param commitfiles: list of files to commit
- @param commitmessagefile: file containing the commit message
- @returns: The sub-command exit value or 0
- """
- commit_cmd = []
- commit_cmd.append(self.vcs)
- commit_cmd.extend(self.vcs_settings.vcs_global_opts)
- commit_cmd.append("commit")
- commit_cmd.extend(self.vcs_settings.vcs_local_opts)
- commit_cmd.extend(["-F", commitmessagefile])
- commit_cmd.extend(f.lstrip("./") for f in commitfiles)
-
- if self.options.pretend:
- print("(%s)" % (" ".join(commit_cmd),))
- return 0
- else:
- retval = spawn(commit_cmd, env=self.repo_settings.commit_env)
- return retval
diff --git a/repoman/lib/repoman/modules/vcs/cvs/__init__.py b/repoman/lib/repoman/modules/vcs/cvs/__init__.py
deleted file mode 100644
index f71f806fb6a..00000000000
--- a/repoman/lib/repoman/modules/vcs/cvs/__init__.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 2014-2015 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """CVS (cvs) plug-in module for portage.
-Performs variaous CVS actions and checks on repositories."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "cvs",
- "description": doc,
- "provides": {
- "cvs-status": {
- "name": "cvs_status",
- "sourcefile": "status",
- "class": "Status",
- "description": doc,
- "functions": ["check", "supports_gpg_sign", "detect_conflicts"],
- "func_desc": {},
- "vcs_preserves_mtime": True,
- "needs_keyword_expansion": True,
- },
- "cvs-changes": {
- "name": "cvs_changes",
- "sourcefile": "changes",
- "class": "Changes",
- "description": doc,
- "functions": ["scan"],
- "func_desc": {},
- },
- },
-}
diff --git a/repoman/lib/repoman/modules/vcs/cvs/changes.py b/repoman/lib/repoman/modules/vcs/cvs/changes.py
deleted file mode 100644
index be382f291d3..00000000000
--- a/repoman/lib/repoman/modules/vcs/cvs/changes.py
+++ /dev/null
@@ -1,134 +0,0 @@
-"""
-CVS module Changes class submodule
-"""
-
-import re
-from itertools import chain
-
-from repoman._portage import portage
-from repoman.modules.vcs.changes import ChangesBase
-from repoman.modules.vcs.vcs import vcs_files_to_cps
-from repoman._subprocess import repoman_getstatusoutput
-
-from portage import _encodings, _unicode_encode
-from portage import cvstree, os
-from portage.output import green
-from portage.package.ebuild.digestgen import digestgen
-
-
-class Changes(ChangesBase):
- """Class object to scan and hold the resultant data
- for all changes to process.
- """
-
- vcs = "cvs"
-
- def __init__(self, options, repo_settings):
- """Class init
-
- @param options: the run time cli options
- @param repo_settings: RepoSettings instance
- """
- super(Changes, self).__init__(options, repo_settings)
- self._tree = None
-
- def _scan(self):
- """VCS type scan function, looks for all detectable changes"""
- self._tree = portage.cvstree.getentries("./", recursive=1)
- self.changed = cvstree.findchanged(self._tree, recursive=1, basedir="./")
- self.new = cvstree.findnew(self._tree, recursive=1, basedir="./")
- self.removed = cvstree.findremoved(self._tree, recursive=1, basedir="./")
- bin_blob_pattern = re.compile("^-kb$")
- self.no_expansion = set(
- portage.cvstree.findoption(
- self._tree, bin_blob_pattern, recursive=1, basedir="./"
- )
- )
-
- @property
- def unadded(self):
- """VCS method of getting the unadded files in the repository"""
- if self._unadded is not None:
- return self._unadded
- self._unadded = portage.cvstree.findunadded(
- self._tree, recursive=1, basedir="./"
- )
- return self._unadded
-
- @staticmethod
- def clear_attic(headers):
- """Clear the attic (inactive files)
-
- @param headers: file headers
- """
- cvs_header_re = re.compile(rb"^#\s*\$Header.*\$$")
- attic_str = b"/Attic/"
- attic_replace = b"/"
- for x in headers:
- f = open(
- _unicode_encode(x, encoding=_encodings["fs"], errors="strict"),
- mode="rb",
- )
- mylines = f.readlines()
- f.close()
- modified = False
- for i, line in enumerate(mylines):
- if cvs_header_re.match(line) is not None and attic_str in line:
- mylines[i] = line.replace(attic_str, attic_replace)
- modified = True
- if modified:
- portage.util.write_atomic(x, b"".join(mylines), mode="wb")
-
- def thick_manifest(self, updates, headers, no_expansion, expansion):
- """Create a thick manifest
-
- @param updates:
- @param headers:
- @param no_expansion:
- @param expansion:
- """
- headerstring = r"'\$(Header|Id).*\$'"
-
- for _file in updates:
-
- # for CVS, no_expansion contains files that are excluded from expansion
- if _file in no_expansion:
- continue
-
- _out = repoman_getstatusoutput(
- "egrep -q %s %s" % (headerstring, portage._shell_quote(_file))
- )
- if _out[0] == 0:
- headers.append(_file)
-
- print("%s have headers that will change." % green(str(len(headers))))
- print(
- "* Files with headers will"
- " cause the manifests to be changed and committed separately."
- )
-
- def digest_regen(
- self, updates, removed, manifests, scanner, broken_changelog_manifests
- ):
- """Regenerate manifests
-
- @param updates: updated files
- @param removed: removed files
- @param manifests: Manifest files
- @param scanner: The repoman.scanner.Scanner instance
- @param broken_changelog_manifests: broken changelog manifests
- """
- if updates or removed:
- for x in sorted(
- vcs_files_to_cps(
- chain(updates, removed, manifests),
- self.repo_settings.repodir,
- scanner.repolevel,
- scanner.reposplit,
- scanner.categories,
- )
- ):
- self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
- digestgen(
- mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb
- )
diff --git a/repoman/lib/repoman/modules/vcs/cvs/status.py b/repoman/lib/repoman/modules/vcs/cvs/status.py
deleted file mode 100644
index 0d131c75a6c..00000000000
--- a/repoman/lib/repoman/modules/vcs/cvs/status.py
+++ /dev/null
@@ -1,134 +0,0 @@
-"""
-CVS module Status class submodule
-"""
-
-import logging
-import subprocess
-import sys
-
-from repoman._portage import portage # pylint: disable=unused-import
-from portage import os
-from portage.const import BASH_BINARY
-from portage.output import red, green
-from portage import _unicode_encode, _unicode_decode
-
-
-class Status:
- """Performs status checks on the svn repository"""
-
- def __init__(self, qatracker, eadded):
- """Class init
-
- @param qatracker: QATracker class instance
- @param eadded: list
- """
- self.qatracker = qatracker
- self.eadded = eadded
-
- def check(self, checkdir, checkdir_relative, xpkg):
- """Perform the svn status check
-
- @param checkdir: string of the directory being checked
- @param checkdir_relative: string of the relative directory being checked
- @param xpkg: string of the package being checked
- @returns: boolean
- """
- try:
- myf = open(checkdir + "/CVS/Entries", "r")
- myl = myf.readlines()
- myf.close()
- except IOError:
- self.qatracker.add_error("CVS/Entries.IO_error", checkdir + "/CVS/Entries")
- return True
- for l in myl:
- if l[0] != "/":
- continue
- splitl = l[1:].split("/")
- if not len(splitl):
- continue
- if splitl[0][-7:] == ".ebuild":
- self.eadded.append(splitl[0][:-7])
- return True
-
- @staticmethod
- def detect_conflicts(options):
- """Determine if the checkout has cvs conflicts.
-
- TODO(antarus): Also this should probably not call sys.exit() as
- repoman is run on >1 packages and one failure should not cause
- subsequent packages to fail.
-
- Returns:
- None (calls sys.exit on fatal problems)
- """
-
- cmd = (
- r"cvs -n up 2>/dev/null | "
- r"egrep '^[^\?] .*' | "
- r"egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'"
- )
- msg = "Performing a %s with a little magic grep to check for updates." % green(
- "cvs -n up"
- )
-
- logging.info(msg)
- # Use Popen instead of getstatusoutput(), in order to avoid
- # unicode handling problems (see bug #310789).
- args = [BASH_BINARY, "-c", cmd]
- args = [_unicode_encode(x) for x in args]
- proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- out = _unicode_decode(proc.communicate()[0])
- proc.wait()
- mylines = out.splitlines()
- myupdates = []
- for line in mylines:
- if not line:
- continue
-
- # [ ] Unmodified (SVN) [U] Updates [P] Patches
- # [M] Modified [A] Added [R] Removed / Replaced
- # [D] Deleted
- if line[0] not in " UPMARD":
- # Stray Manifest is fine, we will readd it anyway.
- if line[0] == "?" and line[1:].lstrip() == "Manifest":
- continue
- logging.error(
- red(
- "!!! Please fix the following issues reported "
- "from cvs: %s" % green("(U,P,M,A,R,D are ok)")
- )
- )
- logging.error(red("!!! Note: This is a pretend/no-modify pass..."))
- logging.error(out)
- sys.exit(1)
- elif line[0] in "UP":
- myupdates.append(line[2:])
-
- if myupdates:
- logging.info(green("Fetching trivial updates..."))
- if options.pretend:
- logging.info("(cvs update " + " ".join(myupdates) + ")")
- retval = os.EX_OK
- else:
- retval = os.system("cvs update " + " ".join(myupdates))
- if retval != os.EX_OK:
- logging.fatal("!!! cvs exited with an error. Terminating.")
- sys.exit(retval)
- return False
-
- @staticmethod
- def supports_gpg_sign():
- """Does this vcs system support gpg commit signatures
-
- @returns: Boolean
- """
- return False
-
- @staticmethod
- def isVcsDir(dirname):
- """Does the directory belong to the vcs system
-
- @param dirname: string, directory name
- @returns: Boolean
- """
- return dirname in ["CVS"]
diff --git a/repoman/lib/repoman/modules/vcs/git/__init__.py b/repoman/lib/repoman/modules/vcs/git/__init__.py
deleted file mode 100644
index c3005fc4186..00000000000
--- a/repoman/lib/repoman/modules/vcs/git/__init__.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 2014-2015 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Git (git) plug-in module for portage.
-Performs variaous git actions and checks on repositories."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "git",
- "description": doc,
- "provides": {
- "git-module": {
- "name": "git_status",
- "sourcefile": "status",
- "class": "Status",
- "description": doc,
- "functions": ["check", "supports_gpg_sign", "detect_conflicts"],
- "func_desc": {},
- "vcs_preserves_mtime": False,
- "needs_keyword_expansion": False,
- },
- "git-changes": {
- "name": "git_changes",
- "sourcefile": "changes",
- "class": "Changes",
- "description": doc,
- "functions": ["scan"],
- "func_desc": {},
- },
- },
-}
diff --git a/repoman/lib/repoman/modules/vcs/git/changes.py b/repoman/lib/repoman/modules/vcs/git/changes.py
deleted file mode 100644
index 3430cf3ecd6..00000000000
--- a/repoman/lib/repoman/modules/vcs/git/changes.py
+++ /dev/null
@@ -1,145 +0,0 @@
-"""
-Git module Changes class submodule
-"""
-
-import logging
-import sys
-
-from repoman._portage import portage # pylint: disable=unused-import
-from repoman.modules.vcs.changes import ChangesBase
-from repoman._subprocess import repoman_popen
-
-from portage import os
-from portage.package.ebuild.digestgen import digestgen
-from portage.process import spawn
-from portage.util import writemsg_level
-
-
-class Changes(ChangesBase):
- """Class object to scan and hold the resultant data
- for all changes to process.
- """
-
- vcs = "git"
-
- def __init__(self, options, repo_settings):
- """Class init
-
- @param options: the run time cli options
- @param repo_settings: RepoSettings instance
- """
- super(Changes, self).__init__(options, repo_settings)
-
- def _scan(self, _reindex=None):
- """
- VCS type scan function, looks for all detectable changes
-
- @param _reindex: ensure that the git index reflects the state on
- disk for files returned by git diff-index (this parameter is
- used in recursive calls and it's not intended to be used for
- any other reason)
- @type _reindex: bool
- """
- # Automatically reindex for commit mode, but not for other modes
- # were the user might not want changes to be staged in the index.
- if _reindex is None and self.options.mode == "commit":
- _reindex = True
-
- with repoman_popen(
- "git diff-index --name-only " "--relative --diff-filter=M HEAD"
- ) as f:
- changed = f.readlines()
- self.changed = ["./" + elem[:-1] for elem in changed]
- del changed
-
- with repoman_popen(
- "git diff-index --name-only " "--relative --diff-filter=A HEAD"
- ) as f:
- new = f.readlines()
- self.new = ["./" + elem[:-1] for elem in new]
- del new
-
- with repoman_popen(
- "git diff-index --name-only " "--relative --diff-filter=D HEAD"
- ) as f:
- removed = f.readlines()
- self.removed = ["./" + elem[:-1] for elem in removed]
- del removed
- if _reindex and (self.changed or self.new or self.removed):
- self.update_index([], self.changed + self.new + self.removed)
- self._scan(_reindex=False)
-
- @property
- def unadded(self):
- """VCS method of getting the unadded files in the repository"""
- if self._unadded is not None:
- return self._unadded
- # get list of files not under version control or missing
- with repoman_popen("git ls-files --others") as f:
- unadded = f.readlines()
- self._unadded = ["./" + elem[:-1] for elem in unadded]
- del unadded
- return self._unadded
-
- def digest_regen(
- self, updates, removed, manifests, scanner, broken_changelog_manifests
- ):
- """Regenerate manifests
-
- @param updates: updated files
- @param removed: removed files
- @param manifests: Manifest files
- @param scanner: The repoman.scanner.Scanner instance
- @param broken_changelog_manifests: broken changelog manifests
- """
- if broken_changelog_manifests:
- for x in broken_changelog_manifests:
- self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
- digestgen(
- mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb
- )
-
- def update_index(self, mymanifests, myupdates):
- """Update the vcs's modified index if it is needed
-
- @param mymanifests: manifest files updated
- @param myupdates: other files updated"""
- # It's not safe to use the git commit -a option since there might
- # be some modified files elsewhere in the working tree that the
- # user doesn't want to commit. Therefore, call git update-index
- # in order to ensure that the index is updated with the latest
- # versions of all new and modified files in the relevant portion
- # of the working tree.
- myfiles = mymanifests + myupdates
- myfiles.sort()
- update_index_cmd = ["git", "update-index", "--add", "--remove"]
- update_index_cmd.extend(f.lstrip("./") for f in myfiles)
- if self.options.pretend:
- print("(%s)" % (" ".join(update_index_cmd),))
- else:
- retval = spawn(update_index_cmd, env=os.environ)
- if retval != os.EX_OK:
- writemsg_level(
- "!!! Exiting on %s (shell) "
- "error code: %s\n" % (self.vcs_settings.vcs, retval),
- level=logging.ERROR,
- noiselevel=-1,
- )
- sys.exit(retval)
-
- def commit(self, myfiles, commitmessagefile):
- """Git commit function
-
- @param commitfiles: list of files to commit
- @param commitmessagefile: file containing the commit message
- @returns: The sub-command exit value or 0
- """
- retval = super(Changes, self).commit(myfiles, commitmessagefile)
- if retval != os.EX_OK:
- if (
- self.repo_settings.repo_config.sign_commit
- and not self.vcs_settings.status.supports_gpg_sign()
- ):
- # Inform user that newer git is needed (bug #403323).
- logging.error("Git >=1.7.9 is required for signed commits!")
- return retval
diff --git a/repoman/lib/repoman/modules/vcs/git/status.py b/repoman/lib/repoman/modules/vcs/git/status.py
deleted file mode 100644
index ec2e3a65574..00000000000
--- a/repoman/lib/repoman/modules/vcs/git/status.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"""
-Git module Status class submodule
-"""
-
-import re
-
-from repoman._portage import portage
-from portage import os
-
-# pylint: disable=ungrouped-imports
-from repoman._subprocess import repoman_popen, repoman_getstatusoutput
-
-
-class Status:
- """Performs status checks on the git repository"""
-
- def __init__(self, qatracker, eadded):
- """Class init
-
- @param qatracker: QATracker class instance
- @param eadded: list
- """
- self.qatracker = qatracker
- self.eadded = eadded
-
- def check(self, checkdir, checkdir_relative, xpkg):
- """Perform the git status check
-
- @param checkdir: string of the directory being checked
- @param checkdir_relative: string of the relative directory being checked
- @param xpkg: string of the package being checked
- @returns: boolean
- """
- with repoman_popen(
- "git ls-files --others %s" % (portage._shell_quote(checkdir_relative),)
- ) as myf:
- for l in myf:
- if l[:-1][-7:] == ".ebuild":
- self.qatracker.add_error(
- "ebuild.notadded", os.path.join(xpkg, os.path.basename(l[:-1]))
- )
- return True
-
- @staticmethod
- def detect_conflicts(options):
- """Are there any merge conflicts present in the VCS tracking system
-
- @param options: command line options
- @returns: Boolean
- """
- return False
-
- @staticmethod
- def supports_gpg_sign():
- """Does this vcs system support gpg commit signatures
-
- @returns: Boolean
- """
- status, cmd_output = repoman_getstatusoutput("git --version")
- cmd_output = cmd_output.split()
- if cmd_output:
- version = re.match(r"^(\d+)\.(\d+)\.(\d+)", cmd_output[-1])
- if version is not None:
- version = [int(x) for x in version.groups()]
- if (
- version[0] > 1
- or (version[0] == 1 and version[1] > 7)
- or (version[0] == 1 and version[1] == 7 and version[2] >= 9)
- ):
- return True
- return False
-
- @staticmethod
- def isVcsDir(dirname):
- """Does the directory belong to the vcs system
-
- @param dirname: string, directory name
- @returns: Boolean
- """
- return dirname in [".git"]
diff --git a/repoman/lib/repoman/modules/vcs/hg/__init__.py b/repoman/lib/repoman/modules/vcs/hg/__init__.py
deleted file mode 100644
index 4b96b04c826..00000000000
--- a/repoman/lib/repoman/modules/vcs/hg/__init__.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 2014-2015 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Mercurial (hg) plug-in module for portage.
-Performs variaous mercurial actions and checks on repositories."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "hg",
- "description": doc,
- "provides": {
- "hg-module": {
- "name": "hg_status",
- "sourcefile": "status",
- "class": "Status",
- "description": doc,
- "functions": ["check", "supports_gpg_sign", "detect_conflicts"],
- "func_desc": {},
- "vcs_preserves_mtime": False,
- "needs_keyword_expansion": False,
- },
- "hg-changes": {
- "name": "hg_changes",
- "sourcefile": "changes",
- "class": "Changes",
- "description": doc,
- "functions": ["scan"],
- "func_desc": {},
- },
- },
-}
diff --git a/repoman/lib/repoman/modules/vcs/hg/changes.py b/repoman/lib/repoman/modules/vcs/hg/changes.py
deleted file mode 100644
index 3ce1763b762..00000000000
--- a/repoman/lib/repoman/modules/vcs/hg/changes.py
+++ /dev/null
@@ -1,109 +0,0 @@
-"""
-Mercurial module Changes class submodule
-"""
-
-from repoman._portage import portage # pylint: disable=unused-import
-from repoman.modules.vcs.changes import ChangesBase
-from repoman._subprocess import repoman_popen
-
-from portage import os
-from portage.package.ebuild.digestgen import digestgen
-from portage.process import spawn
-
-
-class Changes(ChangesBase):
- """Class object to scan and hold the resultant data
- for all changes to process.
- """
-
- vcs = "hg"
-
- def __init__(self, options, repo_settings):
- """Class init
-
- @param options: the run time cli options
- @param repo_settings: RepoSettings instance
- """
- super(Changes, self).__init__(options, repo_settings)
-
- def _scan(self):
- """VCS type scan function, looks for all detectable changes"""
- with repoman_popen("hg status --no-status --modified .") as f:
- changed = f.readlines()
- self.changed = ["./" + elem.rstrip() for elem in changed]
- del changed
-
- with repoman_popen("hg status --no-status --added .") as f:
- new = f.readlines()
- self.new = ["./" + elem.rstrip() for elem in new]
- del new
-
- with repoman_popen("hg status --no-status --removed .") as f:
- removed = f.readlines()
- self.removed = ["./" + elem.rstrip() for elem in removed]
- del removed
-
- @property
- def unadded(self):
- """VCS method of getting the unadded files in the repository"""
- if self._unadded is not None:
- return self._unadded
- with repoman_popen("hg status --no-status --unknown .") as f:
- unadded = f.readlines()
- self._unadded = ["./" + elem.rstrip() for elem in unadded]
- del unadded
- return self._unadded
-
- @property
- def deleted(self):
- """VCS method of getting the deleted files in the repository"""
- if self._deleted is not None:
- return self._deleted
- # Mercurial doesn't handle manually deleted files as removed from
- # the repository, so the user need to remove them before commit,
- # using "hg remove [FILES]"
- with repoman_popen("hg status --no-status --deleted .") as f:
- deleted = f.readlines()
- self._deleted = ["./" + elem.rstrip() for elem in deleted]
- del deleted
- return self._deleted
-
- def digest_regen(
- self, updates, removed, manifests, scanner, broken_changelog_manifests
- ):
- """Regenerate manifests
-
- @param updates: updated files
- @param removed: removed files
- @param manifests: Manifest files
- @param scanner: The repoman.scanner.Scanner instance
- @param broken_changelog_manifests: broken changelog manifests
- """
- if broken_changelog_manifests:
- for x in broken_changelog_manifests:
- self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
- digestgen(
- mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb
- )
-
- def commit(self, myfiles, commitmessagefile):
- """Hg commit function
-
- @param commitfiles: list of files to commit
- @param commitmessagefile: file containing the commit message
- @returns: The sub-command exit value or 0
- """
- commit_cmd = []
- commit_cmd.append(self.vcs)
- commit_cmd.extend(self.vcs_settings.vcs_global_opts)
- commit_cmd.append("commit")
- commit_cmd.extend(self.vcs_settings.vcs_local_opts)
- commit_cmd.extend(["--logfile", commitmessagefile])
- commit_cmd.extend(myfiles)
-
- if self.options.pretend:
- print("(%s)" % (" ".join(commit_cmd),))
- return 0
- else:
- retval = spawn(commit_cmd, env=self.repo_settings.commit_env)
- return retval
diff --git a/repoman/lib/repoman/modules/vcs/hg/status.py b/repoman/lib/repoman/modules/vcs/hg/status.py
deleted file mode 100644
index 2b56f2e1f21..00000000000
--- a/repoman/lib/repoman/modules/vcs/hg/status.py
+++ /dev/null
@@ -1,68 +0,0 @@
-"""
-Mercurial module Status class submodule
-"""
-
-from repoman._portage import portage
-from portage import os
-
-# pylint: disable=ungrouped-imports
-from repoman._subprocess import repoman_popen
-
-
-class Status:
- """Performs status checks on the svn repository"""
-
- def __init__(self, qatracker, eadded):
- """Class init
-
- @param qatracker: QATracker class instance
- @param eadded: list
- """
- self.qatracker = qatracker
- self.eadded = eadded
-
- def check(self, checkdir, checkdir_relative, xpkg):
- """Perform the svn status check
-
- @param checkdir: string of the directory being checked
- @param checkdir_relative: string of the relative directory being checked
- @param xpkg: string of the package being checked
- @returns: boolean
- """
- myf = repoman_popen(
- "hg status --no-status --unknown %s"
- % (portage._shell_quote(checkdir_relative),)
- )
- for l in myf:
- if l[:-1][-7:] == ".ebuild":
- self.qatracker.add_error(
- "ebuild.notadded", os.path.join(xpkg, os.path.basename(l[:-1]))
- )
- myf.close()
- return True
-
- @staticmethod
- def detect_conflicts(options):
- """Are there any merge conflicts present in the VCS tracking system
-
- @param options: command line options
- @returns: Boolean
- """
- return False
-
- @staticmethod
- def supports_gpg_sign():
- """Does this vcs system support gpg commit signatures
-
- @returns: Boolean
- """
- return False
-
- @staticmethod
- def isVcsDir(dirname):
- """Does the directory belong to the vcs system
-
- @param dirname: string, directory name
- @returns: Boolean
- """
- return dirname in [".hg"]
diff --git a/repoman/lib/repoman/modules/vcs/settings.py b/repoman/lib/repoman/modules/vcs/settings.py
deleted file mode 100644
index b186b70442c..00000000000
--- a/repoman/lib/repoman/modules/vcs/settings.py
+++ /dev/null
@@ -1,113 +0,0 @@
-"""
-Repoman VCSSettings modules
-"""
-
-import logging
-import sys
-
-from portage.output import red
-
-from repoman.modules.vcs import module_controller, module_names
-from repoman.modules.vcs.vcs import FindVCS
-from repoman.qa_tracker import QATracker
-
-
-class VCSSettings:
- """Holds various VCS settings"""
-
- def __init__(self, options=None, repoman_settings=None, repo_settings=None):
- """Class init function
-
- @param options: the run time cli options
- @param repoman_settings: portage.config settings instance
- @param repo_settings: RepoSettings instance
- """
- self.options = options
- self.repoman_settings = repoman_settings
- self.repo_settings = repo_settings
- if options.vcs:
- if options.vcs in module_names:
- self.vcs = options.vcs
- else:
- self.vcs = None
- else:
- vcses = FindVCS()
- if len(vcses) > 1:
- print(
- red(
- "*** Ambiguous workdir -- more than one VCS found"
- " at the same depth: %s." % ", ".join(vcses)
- )
- )
- print(
- red(
- "*** Please either clean up your workdir"
- " or specify --vcs option."
- )
- )
- sys.exit(1)
- elif vcses:
- self.vcs = vcses[0]
- else:
- self.vcs = None
-
- if options.if_modified == "y" and self.vcs is None:
- logging.info(
- "Not in a version controlled repository; " "disabling --if-modified."
- )
- options.if_modified = "n"
-
- # initialize our instance placeholders
- self._status = None
- self._changes = None
- # get our vcs plugin controller and available module names
- self.module_controller = module_controller
- self.module_names = module_names
-
- # Disable copyright/mtime check if vcs does not preserve mtime (bug #324075).
- if str(self.vcs) in self.module_controller.parents:
- self.vcs_preserves_mtime = module_controller.modules[
- "%s_status" % self.vcs
- ]["vcs_preserves_mtime"]
- else:
- self.vcs_preserves_mtime = False
- logging.error("VCSSettings: Unknown VCS type: %s", self.vcs)
- logging.error("Available modules: %s", module_controller.parents)
-
- self.needs_keyword_expansion = module_controller.modules[
- "%s_status" % self.vcs
- ]["needs_keyword_expansion"]
- self.vcs_local_opts = repoman_settings.get("REPOMAN_VCS_LOCAL_OPTS", "").split()
- self.vcs_global_opts = repoman_settings.get("REPOMAN_VCS_GLOBAL_OPTS")
- if self.vcs_global_opts is None:
- if self.vcs in ("cvs", "svn"):
- self.vcs_global_opts = "-q"
- else:
- self.vcs_global_opts = ""
- self.vcs_global_opts = self.vcs_global_opts.split()
-
- if options.mode == "commit" and not options.pretend and not self.vcs:
- logging.info(
- "Not in a version controlled repository; " "enabling pretend mode."
- )
- options.pretend = True
- self.qatracker = QATracker()
- self.eadded = []
-
- @property
- def status(self):
- """Initializes and returns the class instance
- of the vcs's Status class"""
- if not self._status:
- status = self.module_controller.get_class("%s_status" % self.vcs)
- self._status = status(self.qatracker, self.eadded)
- return self._status
-
- @property
- def changes(self):
- """Initializes and returns the class instance
- of the vcs's Changes class"""
- if not self._changes:
- changes = self.module_controller.get_class("%s_changes" % self.vcs)
- self._changes = changes(self.options, self.repo_settings)
- return self._changes
diff --git a/repoman/lib/repoman/modules/vcs/svn/__init__.py b/repoman/lib/repoman/modules/vcs/svn/__init__.py
deleted file mode 100644
index f8da39363c8..00000000000
--- a/repoman/lib/repoman/modules/vcs/svn/__init__.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 2014-2015 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-doc = """Subversion (svn) plug-in module for portage.
-Performs variaous subversion actions and checks on repositories."""
-__doc__ = doc[:]
-
-
-module_spec = {
- "name": "svn",
- "description": doc,
- "provides": {
- "svn-module": {
- "name": "svn_status",
- "sourcefile": "status",
- "class": "Status",
- "description": doc,
- "functions": ["check", "supports_gpg_sign", "detect_conflicts"],
- "func_desc": {},
- "vcs_preserves_mtime": False,
- "needs_keyword_expansion": True,
- },
- "svn-changes": {
- "name": "svn_changes",
- "sourcefile": "changes",
- "class": "Changes",
- "description": doc,
- "functions": ["scan"],
- "func_desc": {},
- },
- },
-}
diff --git a/repoman/lib/repoman/modules/vcs/svn/changes.py b/repoman/lib/repoman/modules/vcs/svn/changes.py
deleted file mode 100644
index e437325dbc7..00000000000
--- a/repoman/lib/repoman/modules/vcs/svn/changes.py
+++ /dev/null
@@ -1,156 +0,0 @@
-"""
-Subversion module Changes class submodule
-"""
-
-from itertools import chain
-
-from repoman.modules.vcs.changes import ChangesBase
-from repoman._subprocess import repoman_popen
-from repoman._subprocess import repoman_getstatusoutput
-from repoman.modules.vcs.vcs import vcs_files_to_cps
-from repoman._portage import portage
-from portage import os
-from portage.output import green
-from portage.package.ebuild.digestgen import digestgen
-
-
-class Changes(ChangesBase):
- """Class object to scan and hold the resultant data
- for all changes to process.
- """
-
- vcs = "svn"
-
- def __init__(self, options, repo_settings):
- """Class init
-
- @param options: the run time cli options
- @param repo_settings: RepoSettings instance
- """
- super(Changes, self).__init__(options, repo_settings)
-
- def _scan(self):
- """VCS type scan function, looks for all detectable changes"""
- with repoman_popen("svn status") as f:
- svnstatus = f.readlines()
- self.changed = [
- "./" + elem.split()[-1:][0]
- for elem in svnstatus
- if elem and elem[:1] in "MR"
- ]
- self.new = [
- "./" + elem.split()[-1:][0] for elem in svnstatus if elem.startswith("A")
- ]
- self.removed = [
- "./" + elem.split()[-1:][0] for elem in svnstatus if elem.startswith("D")
- ]
-
- @property
- def expansion(self):
- """VCS method of getting the expanded keywords in the repository"""
- if self._expansion is not None:
- return self._expansion
- # Subversion expands keywords specified in svn:keywords properties.
- with repoman_popen("svn propget -R svn:keywords") as f:
- props = f.readlines()
- self._expansion = dict(
- ("./" + prop.split(" - ")[0], prop.split(" - ")[1].split())
- for prop in props
- if " - " in prop
- )
- del props
- return self._expansion
-
- @property
- def unadded(self):
- """VCS method of getting the unadded files in the repository"""
- if self._unadded is not None:
- return self._unadded
- with repoman_popen("svn status --no-ignore") as f:
- svnstatus = f.readlines()
- self._unadded = [
- "./" + elem.rstrip().split()[1]
- for elem in svnstatus
- if elem.startswith("?") or elem.startswith("I")
- ]
- del svnstatus
- return self._unadded
-
- def thick_manifest(self, updates, headers, no_expansion, expansion):
- """Create a thick manifest
-
- @param updates:
- @param headers:
- @param no_expansion:
- @param expansion:
- """
- svn_keywords = dict(
- (k.lower(), k)
- for k in [
- "Rev",
- "Revision",
- "LastChangedRevision",
- "Date",
- "LastChangedDate",
- "Author",
- "LastChangedBy",
- "URL",
- "HeadURL",
- "Id",
- "Header",
- ]
- )
-
- for _file in updates:
- # for SVN, expansion contains files that are included in expansion
- if _file not in expansion:
- continue
-
- # Subversion keywords are case-insensitive
- # in svn:keywords properties,
- # but case-sensitive in contents of files.
- enabled_keywords = []
- for k in expansion[_file]:
- keyword = svn_keywords.get(k.lower())
- if keyword is not None:
- enabled_keywords.append(keyword)
-
- headerstring = r"'\$(%s).*\$'" % "|".join(enabled_keywords)
-
- _out = repoman_getstatusoutput(
- "egrep -q %s %s" % (headerstring, portage._shell_quote(_file))
- )
- if _out[0] == 0:
- headers.append(_file)
-
- print("%s have headers that will change." % green(str(len(headers))))
- print(
- "* Files with headers will"
- " cause the manifests to be changed and committed separately."
- )
-
- def digest_regen(
- self, updates, removed, manifests, scanner, broken_changelog_manifests
- ):
- """Regenerate manifests
-
- @param updates: updated files
- @param removed: removed files
- @param manifests: Manifest files
- @param scanner: The repoman.scanner.Scanner instance
- @param broken_changelog_manifests: broken changelog manifests
- """
- if updates or removed:
- for x in sorted(
- vcs_files_to_cps(
- chain(updates, removed, manifests),
- scanner.repo_settings.repodir,
- scanner.repolevel,
- scanner.reposplit,
- scanner.categories,
- )
- ):
- self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
- digestgen(
- mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb
- )
diff --git a/repoman/lib/repoman/modules/vcs/svn/status.py b/repoman/lib/repoman/modules/vcs/svn/status.py
deleted file mode 100644
index 2e6ee927d24..00000000000
--- a/repoman/lib/repoman/modules/vcs/svn/status.py
+++ /dev/null
@@ -1,151 +0,0 @@
-"""
-Subversion module Status class submodule
-"""
-
-import logging
-import subprocess
-import sys
-
-from repoman._portage import portage
-from portage import os
-from portage.const import BASH_BINARY
-from portage.output import red, green
-from portage import _unicode_encode, _unicode_decode
-
-# pylint: disable=ungrouped-imports
-from repoman._subprocess import repoman_popen
-
-
-class Status:
- """Performs status checks on the svn repository"""
-
- def __init__(self, qatracker, eadded):
- """Class init
-
- @param qatracker: QATracker class instance
- @param eadded: list
- """
- self.qatracker = qatracker
- self.eadded = eadded
-
- def check(self, checkdir, checkdir_relative, xpkg):
- """Perform the svn status check
-
- @param checkdir: string of the directory being checked
- @param checkdir_relative: string of the relative directory being checked
- @param xpkg: string of the package being checked
- @returns: boolean
- """
- try:
- myf = repoman_popen(
- "svn status --depth=files --verbose " + portage._shell_quote(checkdir)
- )
- myl = myf.readlines()
- myf.close()
- except IOError:
- raise
- for l in myl:
- if l[:1] == "?":
- continue
- if l[:7] == " >":
- # tree conflict, new in subversion 1.6
- continue
- l = l.split()[-1]
- if l[-7:] == ".ebuild":
- self.eadded.append(os.path.basename(l[:-7]))
- try:
- myf = repoman_popen("svn status " + portage._shell_quote(checkdir))
- myl = myf.readlines()
- myf.close()
- except IOError:
- raise
- for l in myl:
- if l[0] == "A":
- l = l.rstrip().split(" ")[-1]
- if l[-7:] == ".ebuild":
- self.eadded.append(os.path.basename(l[:-7]))
- return True
-
- @staticmethod
- def detect_conflicts(options):
- """Determine if the checkout has problems like cvs conflicts.
-
- If you want more vcs support here just keep adding if blocks...
- This could be better.
-
- TODO(antarus): Also this should probably not call sys.exit() as
- repoman is run on >1 packages and one failure should not cause
- subsequent packages to fail.
-
- Args:
- vcs - A string identifying the version control system in use
- Returns: boolean
- (calls sys.exit on fatal problems)
- """
-
- cmd = "svn status -u 2>&1 | egrep -v '^. +.*/digest-[^/]+' | head -n-1"
- msg = "Performing a %s with a little magic grep to check for updates." % green(
- "svn status -u"
- )
-
- logging.info(msg)
- # Use Popen instead of getstatusoutput(), in order to avoid
- # unicode handling problems (see bug #310789).
- args = [BASH_BINARY, "-c", cmd]
- args = [_unicode_encode(x) for x in args]
- proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- out = _unicode_decode(proc.communicate()[0])
- proc.wait()
- mylines = out.splitlines()
- myupdates = []
- for line in mylines:
- if not line:
- continue
-
- # [ ] Unmodified (SVN) [U] Updates [P] Patches
- # [M] Modified [A] Added [R] Removed / Replaced
- # [D] Deleted
- if line[0] not in " UPMARD":
- # Stray Manifest is fine, we will readd it anyway.
- if line[0] == "?" and line[1:].lstrip() == "Manifest":
- continue
- logging.error(
- red(
- "!!! Please fix the following issues reported "
- "from cvs: %s" % green("(U,P,M,A,R,D are ok)")
- )
- )
- logging.error(red("!!! Note: This is a pretend/no-modify pass..."))
- logging.error(out)
- sys.exit(1)
- elif line[8] == "*":
- myupdates.append(line[9:].lstrip(" 1234567890"))
-
- if myupdates:
- logging.info(green("Fetching trivial updates..."))
- if options.pretend:
- logging.info("(svn update " + " ".join(myupdates) + ")")
- retval = os.EX_OK
- else:
- retval = os.system("svn update " + " ".join(myupdates))
- if retval != os.EX_OK:
- logging.fatal("!!! svn exited with an error. Terminating.")
- sys.exit(retval)
- return False
-
- @staticmethod
- def supports_gpg_sign():
- """Does this vcs system support gpg commit signatures
-
- @returns: Boolean
- """
- return False
-
- @staticmethod
- def isVcsDir(dirname):
- """Does the directory belong to the vcs system
-
- @param dirname: string, directory name
- @returns: Boolean
- """
- return dirname in [".svn"]
diff --git a/repoman/lib/repoman/modules/vcs/vcs.py b/repoman/lib/repoman/modules/vcs/vcs.py
deleted file mode 100644
index 1ee8b52ffb8..00000000000
--- a/repoman/lib/repoman/modules/vcs/vcs.py
+++ /dev/null
@@ -1,145 +0,0 @@
-# -*- coding:utf-8 -*-
-
-import collections
-import logging
-
-from itertools import chain
-
-from portage import os
-
-
-_vcs_type = collections.namedtuple("_vcs_type", "name dir_name file_name")
-
-_FindVCS_data = (
- _vcs_type(name="git", dir_name=".git", file_name=".git"),
- _vcs_type(name="bzr", dir_name=".bzr", file_name=""),
- _vcs_type(name="hg", dir_name=".hg", file_name=""),
- _vcs_type(name="svn", dir_name=".svn", file_name=""),
-)
-
-
-def FindVCS(cwd=None):
- """
- Try to figure out in what VCS' working tree we are.
-
- @param cwd: working directory (default is os.getcwd())
- @type cwd: str
- @return: list of strings describing the discovered vcs types
- @rtype: list
- """
-
- if cwd is None:
- cwd = os.getcwd()
-
- outvcs = []
-
- def seek(depth=None):
- """Seek for VCSes that have a top-level data directory only.
-
- @param depth: integer
- @returns: list of strings
- """
- retvcs = []
- pathprep = cwd
-
- while depth is None or depth > 0:
- for vcs_type in _FindVCS_data:
- vcs_dir = os.path.join(pathprep, vcs_type.dir_name)
- if os.path.isdir(vcs_dir):
- logging.debug(
- "FindVCS: found %(name)s dir: %(vcs_dir)s"
- % {"name": vcs_type.name, "vcs_dir": os.path.abspath(vcs_dir)}
- )
- retvcs.append(vcs_type.name)
- elif vcs_type.file_name:
- vcs_file = os.path.join(pathprep, vcs_type.file_name)
- if os.path.exists(vcs_file):
- logging.debug(
- "FindVCS: found %(name)s file: %(vcs_file)s"
- % {
- "name": vcs_type.name,
- "vcs_file": os.path.abspath(vcs_file),
- }
- )
- retvcs.append(vcs_type.name)
-
- if retvcs:
- break
- pathprep = os.path.join(pathprep, "..")
- if os.path.realpath(pathprep).strip("/") == "":
- break
- if depth is not None:
- depth = depth - 1
-
- return retvcs
-
- # Level zero VCS-es.
- if os.path.isdir(os.path.join(cwd, "CVS")):
- outvcs.append("cvs")
- if os.path.isdir(".svn"): # <1.7
- outvcs.append(os.path.join(cwd, "svn"))
-
- # If we already found one of 'level zeros', just take a quick look
- # at the current directory. Otherwise, seek parents till we get
- # something or reach root.
- if outvcs:
- outvcs.extend(seek(1))
- else:
- outvcs = seek()
-
- if len(outvcs) > 1:
- # eliminate duplicates, like for svn in bug #391199
- outvcs = list(set(outvcs))
-
- return outvcs
-
-
-def vcs_files_to_cps(vcs_file_iter, repodir, repolevel, reposplit, categories):
- """
- Iterate over the given modified file paths returned from the vcs,
- and return a frozenset containing category/pn strings for each
- modified package.
- """
-
- modified_cps = []
-
- if repolevel == 3:
- if reposplit[-2] in categories and next(vcs_file_iter, None) is not None:
- modified_cps.append("/".join(reposplit[-2:]))
-
- elif repolevel == 2:
- category = reposplit[-1]
- if category in categories:
- for filename in vcs_file_iter:
- f_split = filename.split(os.sep)
- # ['.', pn, ...]
- if len(f_split) > 2:
- modified_cps.append(category + "/" + f_split[1])
-
- else:
- # repolevel == 1
- for filename in vcs_file_iter:
- f_split = filename.split(os.sep)
- # ['.', category, pn, ...]
- if len(f_split) > 3 and f_split[1] in categories:
- modified_cps.append("/".join(f_split[1:3]))
-
- # Exclude packages that have been removed, since calling
- # code assumes that the packages exist.
- return frozenset(
- x for x in frozenset(modified_cps) if os.path.exists(os.path.join(repodir, x))
- )
-
-
-def vcs_new_changed(relative_path, mychanged, mynew):
- """Check if any vcs tracked file have been modified
-
- @param relative_path:
- @param mychanged: iterable of changed files
- @param mynew: iterable of new files
- @returns boolean
- """
- for x in chain(mychanged, mynew):
- if x == relative_path:
- return True
- return False
diff --git a/repoman/lib/repoman/profile.py b/repoman/lib/repoman/profile.py
deleted file mode 100644
index b317189effc..00000000000
--- a/repoman/lib/repoman/profile.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# -*- coding:utf-8 -*-
-
-from portage import normalize_path
-from portage import os
-from portage.output import red
-
-
-class ProfileDesc:
- __slots__ = (
- "abs_path",
- "arch",
- "status",
- "sub_path",
- "tree_path",
- )
-
- def __init__(self, arch, status, sub_path, tree_path):
- self.arch = arch
- self.status = status
- if sub_path:
- sub_path = normalize_path(sub_path.lstrip(os.sep))
- self.sub_path = sub_path
- self.tree_path = tree_path
- if tree_path:
- self.abs_path = os.path.join(tree_path, "profiles", self.sub_path)
- else:
- self.abs_path = tree_path
-
- def __str__(self):
- if self.sub_path:
- return self.sub_path
- return "empty profile"
-
-
-valid_profile_types = frozenset(["dev", "exp", "stable"])
-
-
-def dev_profile_keywords(profiles):
- """
- Create a set of KEYWORDS values that exist in 'dev'
- profiles. These are used
- to trigger a message notifying the user when they might
- want to add the --include-dev option.
- """
- type_arch_map = {}
- for arch, arch_profiles in profiles.items():
- for prof in arch_profiles:
- arch_set = type_arch_map.get(prof.status)
- if arch_set is None:
- arch_set = set()
- type_arch_map[prof.status] = arch_set
- arch_set.add(arch)
-
- dev_keywords = type_arch_map.get("dev", set())
- dev_keywords.update(["~" + arch for arch in dev_keywords])
- return frozenset(dev_keywords)
-
-
-def setup_profile(profile_list):
- # Ensure that profile sub_path attributes are unique. Process in reverse order
- # so that profiles with duplicate sub_path from overlays will override
- # profiles with the same sub_path from parent repos.
- profiles = {}
- profile_list.reverse()
- profile_sub_paths = set()
- for prof in profile_list:
- if prof.sub_path in profile_sub_paths:
- continue
- profile_sub_paths.add(prof.sub_path)
- profiles.setdefault(prof.arch, []).append(prof)
-
- # Use an empty profile for checking dependencies of
- # packages that have empty KEYWORDS.
- prof = ProfileDesc("**", "stable", "", "")
- profiles.setdefault(prof.arch, []).append(prof)
- return profiles
-
-
-def check_profiles(profiles, archlist):
- for x in archlist:
- if x[0] == "~":
- continue
- if x not in profiles:
- print(
- red('"%s" doesn\'t have a valid profile listed in profiles.desc.' % x)
- )
- print(
- red(
- 'You need to either "cvs update" your profiles dir'
- " or follow this"
- )
- )
- print(red("up with the " + x + " team."))
- print()
diff --git a/repoman/lib/repoman/qa_data.py b/repoman/lib/repoman/qa_data.py
deleted file mode 100644
index 0892c1f5ced..00000000000
--- a/repoman/lib/repoman/qa_data.py
+++ /dev/null
@@ -1,210 +0,0 @@
-# -*- coding:utf-8 -*-
-
-import logging
-import os
-
-from _emerge.Package import Package
-
-# import our initialized portage instance
-from repoman import _not_installed
-from repoman._portage import portage
-from repoman.config import load_config
-
-
-class QAData:
- def __init__(self):
- # Create the main exported data variables
- self.max_desc_len = None
- self.allowed_filename_chars = None
- self.qahelp = None
- self.qacats = None
- self.qawarnings = None
- self.missingvars = None
- self.allvars = None
- self.valid_restrict = None
- self.suspect_rdepend = None
- self.suspect_virtual = None
- self.ruby_deprecated = None
- self.no_exec = None
-
- def load_repo_config(self, repopaths, options, valid_versions):
- """Load the repository repoman qa_data.yml config
-
- @param repopaths: list of strings, The path of the repository being scanned
- This could be a parent repository using the
- repoman_masters layout.conf variable
- """
- # add our base qahelp
- repository_modules = options.experimental_repository_modules == "y"
- if _not_installed:
- cnfdir = os.path.realpath(
- os.path.join(
- os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
- "cnf/qa_data",
- )
- )
- else:
- cnfdir = os.path.join(
- portage.const.EPREFIX or "/", "usr/share/repoman/qa_data"
- )
- repomanpaths = [os.path.join(cnfdir, _file_) for _file_ in os.listdir(cnfdir)]
- logging.debug("QAData: cnfdir: %s, repomanpaths: %s", cnfdir, repomanpaths)
- if repository_modules:
- repopaths = [os.path.join(path, "qa_data.yaml") for path in repopaths]
- elif _not_installed:
- repopaths = [
- os.path.realpath(
- os.path.join(
- os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
- "cnf/repository/qa_data.yaml",
- )
- )
- ]
- else:
- repopaths = [
- os.path.join(
- portage.const.EPREFIX or "/",
- "usr/share/repoman/repository/qa_data.yaml",
- )
- ]
- infopaths = repomanpaths + repopaths
-
- qadata = load_config(infopaths, None, valid_versions)
- if qadata == {}:
- logging.error(
- "QAData: Failed to load a valid 'qa_data.yaml' file at paths: %s",
- infopaths,
- )
- return False
- self.max_desc_len = qadata.get("max_description_length", 80)
- self.allowed_filename_chars = qadata.get(
- "allowed_filename_chars", "a-zA-Z0-9._-+:"
- )
-
- self.qahelp = qadata["qahelp"]
- logging.debug("qa_help primary keys: %s", sorted(self.qahelp))
-
- self.qacats = []
- for x in sorted(self.qahelp):
- for y in sorted(self.qahelp[x]):
- self.qacats.append(".".join([x, y]))
- self.qacats.sort()
-
- self.qawarnings = set(qadata.get("qawarnings", []))
- if options.experimental_inherit == "y":
- # This is experimental, so it's non-fatal.
- self.qawarnings.add("inherit.missing")
-
- self.missingvars = qadata.get("missingvars", [])
- logging.debug("QAData: missingvars: %s", self.missingvars)
- self.allvars = set(portage.auxdbkeys)
- self.allvars.update(Package.metadata_keys)
- self.allvars = sorted(self.allvars)
-
- for x in self.missingvars:
- x += ".missing"
- if x not in self.qacats:
- logging.warning(
- 'QAData: * missingvars values need to be added to qahelp ("%s")' % x
- )
- self.qacats.append(x)
- self.qawarnings.add(x)
-
- self.valid_restrict = frozenset(qadata.get("valid_restrict", []))
-
- self.suspect_rdepend = frozenset(qadata.get("suspect_rdepend", []))
-
- self.suspect_virtual = qadata.get("suspect_virtual", {})
-
- self.ruby_deprecated = frozenset(qadata.get("ruby_deprecated", []))
-
- # file.executable
- self.no_exec = frozenset(qadata.get("no_exec_files", []))
- logging.debug("QAData: completed loading file: %s", repopaths)
- return True
-
-
-def format_qa_output(formatter, fails, dofull, dofail, options, qawarnings):
- """Helper function that formats output properly
-
- @param formatter: an instance of Formatter
- @type formatter: Formatter
- @param fails: dict of qa status failures
- @type fails: dict
- @param dofull: Whether to print full results or a summary
- @type dofull: boolean
- @param dofail: Whether failure was hard or soft
- @type dofail: boolean
- @param options: The command-line options provided to repoman
- @type options: Namespace
- @param qawarnings: the set of warning types
- @type qawarnings: set
- @return: None (modifies formatter)
- """
- full = options.mode == "full"
- # we only want key value pairs where value > 0
- for category in sorted(fails):
- number = len(fails[category])
- formatter.add_literal_data(" " + category)
- spacing_width = 30 - len(category)
- if category in qawarnings:
- formatter.push_style("WARN")
- else:
- formatter.push_style("BAD")
- formatter.add_literal_data(" [fatal]")
- spacing_width -= 8
-
- formatter.add_literal_data(" " * spacing_width)
- formatter.add_literal_data("%s" % number)
- formatter.pop_style()
- formatter.add_line_break()
- if not dofull:
- if not full and dofail and category in qawarnings:
- # warnings are considered noise when there are failures
- continue
- fails_list = fails[category]
- if not full and len(fails_list) > 12:
- fails_list = fails_list[:12]
- for failure in fails_list:
- formatter.add_literal_data(" " + failure)
- formatter.add_line_break()
-
-
-def format_qa_output_column(formatter, fails, dofull, dofail, options, qawarnings):
- """Helper function that formats output in a machine-parseable column format
-
- @param formatter: an instance of Formatter
- @type formatter: Formatter
- @param fails: dict of qa status failures
- @type fails: dict
- @param dofull: Whether to print full results or a summary
- @type dofull: boolean
- @param dofail: Whether failure was hard or soft
- @type dofail: boolean
- @param options: The command-line options provided to repoman
- @type options: Namespace
- @param qawarnings: the set of warning types
- @type qawarnings: set
- @return: None (modifies formatter)
- """
- full = options.mode == "full"
- for category in sorted(fails):
- number = len(fails[category])
- formatter.add_literal_data("NumberOf " + category + " ")
- if category in qawarnings:
- formatter.push_style("WARN")
- else:
- formatter.push_style("BAD")
- formatter.add_literal_data("%s" % number)
- formatter.pop_style()
- formatter.add_line_break()
- if not dofull:
- if not full and dofail and category in qawarnings:
- # warnings are considered noise when there are failures
- continue
- fails_list = fails[category]
- if not full and len(fails_list) > 12:
- fails_list = fails_list[:12]
- for failure in fails_list:
- formatter.add_literal_data(category + " " + failure)
- formatter.add_line_break()
diff --git a/repoman/lib/repoman/qa_tracker.py b/repoman/lib/repoman/qa_tracker.py
deleted file mode 100644
index 6cb5f320704..00000000000
--- a/repoman/lib/repoman/qa_tracker.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import logging
-import sys
-
-
-class QATracker:
- """Track all occurrances of Q/A problems detected"""
-
- def __init__(self, qacats=None, qawarnings=None):
- self.fails = {}
- self.warns = {}
- self.qacats = qacats
- self.qawarnings = qawarnings
-
- def add_error(self, detected_qa, info):
- """Add the Q/A error to the database of detected problems
-
- @param detected_qa: string, member of qa_data.qacats list
- @param info: string, details of the detected problem
- """
- if detected_qa not in self.qacats:
- logging.error(
- "QATracker: Exiting on error. Unknown detected_qa type passed "
- "in to add_error(): %s, %s" % (detected_qa, info)
- )
- sys.exit(1)
- try:
- self.fails[detected_qa].append(info)
- except KeyError:
- self.fails[detected_qa] = [info]
-
- def add_warning(self, detected_qa, info):
- """Add the Q/A warning to the database of detected problems
-
- @param detected_qa: string, member of qa_data.qawarnings list
- @param info: string, details of the detected problem
- """
- if detected_qa not in self.qawarnings:
- logging.error(
- "QATracker: Exiting on error. Unknown detected_qa type passed "
- "in to add_warning(): %s, %s" % (detected_qa, info)
- )
- sys.exit(1)
- try:
- self.warns[detected_qa].append(info)
- except KeyError:
- self.warns[detected_qa] = [info]
diff --git a/repoman/lib/repoman/repos.py b/repoman/lib/repoman/repos.py
deleted file mode 100644
index d89e0508a26..00000000000
--- a/repoman/lib/repoman/repos.py
+++ /dev/null
@@ -1,377 +0,0 @@
-# -*- coding:utf-8 -*-
-
-
-import io
-import logging
-import re
-import sys
-import textwrap
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage import os
-from portage import _encodings
-from portage import _unicode_encode
-from portage.checksum import get_valid_checksum_keys
-from portage.repository.config import allow_profile_repo_deps
-
-# pylint: disable=ungrouped-imports
-from repoman.errors import err
-from repoman.profile import ProfileDesc, valid_profile_types
-
-GPG_KEY_ID_REGEX = r"(0x)?([0-9a-fA-F]{8}){1,5}!?"
-bad = portage.output.create_color_func("BAD")
-
-
-class RepoSettings:
- """Holds our repo specific settings"""
-
- def __init__(
- self,
- config_root,
- portdir,
- portdir_overlay,
- repoman_settings=None,
- vcs_settings=None,
- options=None,
- qadata=None,
- ):
- self.config_root = config_root
- self.repoman_settings = repoman_settings
- self.vcs_settings = vcs_settings
-
- self.repositories = self.repoman_settings.repositories
-
- # Ensure that current repository is in the list of enabled repositories.
- self.repodir = os.path.realpath(portdir_overlay)
- try:
- self.repositories.get_repo_for_location(self.repodir)
- except KeyError:
- self._add_repo(config_root, portdir_overlay)
-
- # Determine the master config loading list
- self.masters_list = []
- # get out repo masters value
- masters = self.repositories.get_repo_for_location(self.repodir).masters
- for repo in masters:
- self.masters_list.append(os.path.join(repo.location, "metadata", "repoman"))
- self.masters_list.append(os.path.join(self.repodir, "metadata", "repoman"))
-
- logging.debug("RepoSettings: init(); load qadata")
- # load the repo specific configuration
- self.qadata = qadata
- if not self.qadata.load_repo_config(
- self.masters_list, options, repoman_settings.valid_versions
- ):
- logging.error("Aborting...")
- sys.exit(1)
- logging.debug("RepoSettings: qadata loaded: %s", qadata.no_exec)
-
- self.root = self.repoman_settings["EROOT"]
- self.trees = {
- self.root: {"porttree": portage.portagetree(settings=self.repoman_settings)}
- }
- self.portdb = self.trees[self.root]["porttree"].dbapi
-
- # Constrain dependency resolution to the master(s)
- # that are specified in layout.conf.
- self.repo_config = self.repositories.get_repo_for_location(self.repodir)
- self.portdb.porttrees = list(self.repo_config.eclass_db.porttrees)
- self.portdir = self.portdb.porttrees[0]
- self.commit_env = os.environ.copy()
- # list() is for iteration on a copy.
- for repo in list(self.repositories):
- # all paths are canonical
- if repo.location not in self.repo_config.eclass_db.porttrees:
- del self.repositories[repo.name]
-
- if self.repo_config.sign_commit and options.mode in (
- "commit",
- "fix",
- "manifest",
- ):
- if vcs_settings.vcs:
- func = getattr(self, "_vcs_gpg_%s" % vcs_settings.vcs)
- func()
- else:
- logging.warning("No VCS type detected, unable to sign the commit")
-
- # In order to disable manifest signatures, repos may set
- # "sign-manifests = false" in metadata/layout.conf. This
- # can be used to prevent merge conflicts like those that
- # thin-manifests is designed to prevent.
- self.sign_manifests = (
- "sign" in self.repoman_settings.features and self.repo_config.sign_manifest
- )
-
- if (
- self.repo_config.sign_manifest
- and self.repo_config.name == "gentoo"
- and options.mode in ("commit",)
- and not self.sign_manifests
- ):
- msg = (
- "The '%s' repository has manifest signatures enabled, "
- "but FEATURES=sign is currently disabled. In order to avoid this "
- "warning, enable FEATURES=sign in make.conf. Alternatively, "
- "repositories can disable manifest signatures by setting "
- "'sign-manifests = false' in metadata/layout.conf."
- ) % (self.repo_config.name,)
- for line in textwrap.wrap(msg, 60):
- logging.warn(line)
-
- is_commit = options.mode in ("commit",)
- valid_gpg_key = self.repoman_settings.get("PORTAGE_GPG_KEY") and re.match(
- r"^%s$" % GPG_KEY_ID_REGEX, self.repoman_settings["PORTAGE_GPG_KEY"]
- )
-
- if self.sign_manifests and is_commit and not valid_gpg_key:
- logging.error(
- "PORTAGE_GPG_KEY value is invalid: %s"
- % self.repoman_settings["PORTAGE_GPG_KEY"]
- )
- sys.exit(1)
-
- manifest_hashes = self.repo_config.manifest_hashes
- manifest_required_hashes = self.repo_config.manifest_required_hashes
- if manifest_hashes is None:
- manifest_hashes = portage.const.MANIFEST2_HASH_DEFAULTS
- manifest_required_hashes = manifest_hashes
-
- if options.mode in ("commit", "fix", "manifest"):
- missing_required_hashes = manifest_required_hashes.difference(
- manifest_hashes
- )
- if missing_required_hashes:
- msg = (
- "The 'manifest-hashes' setting in the '%s' repository's "
- "metadata/layout.conf does not contain the '%s' hashes which "
- "are listed in 'manifest-required-hashes'. Please fix that "
- "file if you want to generate valid manifests for "
- "this repository."
- ) % (self.repo_config.name, " ".join(missing_required_hashes))
- for line in textwrap.wrap(msg, 70):
- logging.error(line)
- sys.exit(1)
-
- unsupported_hashes = manifest_hashes.difference(get_valid_checksum_keys())
- if unsupported_hashes:
- msg = (
- "The 'manifest-hashes' setting in the '%s' repository's "
- "metadata/layout.conf contains one or more hash types '%s' "
- "which are not supported by this portage version. You will "
- "have to upgrade portage if you want to generate valid "
- "manifests for this repository."
- ) % (self.repo_config.name, " ".join(sorted(unsupported_hashes)))
- for line in textwrap.wrap(msg, 70):
- logging.error(line)
- sys.exit(1)
-
- def _add_repo(self, config_root, portdir_overlay):
- self.repo_conf = portage.repository.config
- self.repo_name = self.repo_conf.RepoConfig._read_valid_repo_name(
- portdir_overlay
- )[0]
- self.layout_conf_data = self.repo_conf.parse_layout_conf(portdir_overlay)[0]
- if self.layout_conf_data["repo-name"]:
- self.repo_name = self.layout_conf_data["repo-name"]
- tmp_conf_file = io.StringIO(
- textwrap.dedent(
- """
- [%s]
- location = %s
- """
- )
- % (self.repo_name, portdir_overlay)
- )
- # Ensure that the repository corresponding to $PWD overrides a
- # repository of the same name referenced by the existing PORTDIR
- # or PORTDIR_OVERLAY settings.
- self.repoman_settings["PORTDIR_OVERLAY"] = "%s %s" % (
- self.repoman_settings.get("PORTDIR_OVERLAY", ""),
- portage._shell_quote(portdir_overlay),
- )
- self.repositories = self.repo_conf.load_repository_config(
- self.repoman_settings, extra_files=[tmp_conf_file]
- )
- # We have to call the config constructor again so that attributes
- # dependent on config.repositories are initialized correctly.
- self.repoman_settings = portage.config(
- config_root=config_root, local_config=False, repositories=self.repositories
- )
-
- ##########
- # future vcs plugin functions
- ##########
-
- def _vcs_gpg_bzr(self):
- pass
-
- def _vcs_gpg_cvs(self):
- pass
-
- def _vcs_gpg_git(self):
- # NOTE: It's possible to use --gpg-sign=key_id to specify the key in
- # the commit arguments. If key_id is unspecified, then it must be
- # configured by `git config user.signingkey key_id`.
- self.vcs_settings.vcs_local_opts.append("--gpg-sign")
- if self.repoman_settings.get("PORTAGE_GPG_DIR"):
- # Pass GNUPGHOME to git for bug #462362.
- self.commit_env["GNUPGHOME"] = self.repoman_settings["PORTAGE_GPG_DIR"]
-
- # Pass GPG_TTY to git for bug #477728.
- try:
- self.commit_env["GPG_TTY"] = os.ttyname(sys.stdin.fileno())
- except OSError:
- pass
-
- def _vcs_gpg_hg(self):
- pass
-
- def _vcs_gpg_svn(self):
- pass
-
-
-def list_checks(kwlist, liclist, uselist, repoman_settings):
- liclist_deprecated = set()
- if "DEPRECATED" in repoman_settings._license_manager._license_groups:
- liclist_deprecated.update(
- repoman_settings._license_manager.expandLicenseTokens(["@DEPRECATED"])
- )
-
- if not liclist:
- logging.fatal("Couldn't find licenses?")
- sys.exit(1)
-
- if not kwlist:
- logging.fatal("Couldn't read KEYWORDS from arch.list")
- sys.exit(1)
-
- if not uselist:
- logging.fatal("Couldn't find use.desc?")
- sys.exit(1)
- return liclist_deprecated
-
-
-def repo_metadata(portdb, repoman_settings):
- # get lists of valid keywords, licenses, and use
- kwlist = set()
- liclist = set()
- uselist = set()
- profile_list = []
- global_pmasklines = []
-
- for repo in portdb.repositories:
- path = repo.location
-
- try:
- liclist.update(os.listdir(os.path.join(path, "licenses")))
- except OSError:
- pass
- kwlist.update(portage.grabfile(os.path.join(path, "profiles", "arch.list")))
-
- use_desc = portage.grabfile(os.path.join(path, "profiles", "use.desc"))
- for x in use_desc:
- x = x.split()
- if x:
- uselist.add(x[0])
-
- expand_desc_dir = os.path.join(path, "profiles", "desc")
- try:
- expand_list = os.listdir(expand_desc_dir)
- except OSError:
- pass
- else:
- for fn in expand_list:
- if not fn[-5:] == ".desc":
- continue
- use_prefix = fn[:-5].lower() + "_"
- for x in portage.grabfile(os.path.join(expand_desc_dir, fn)):
- x = x.split()
- if x:
- uselist.add(use_prefix + x[0])
-
- global_pmasklines.append(
- portage.util.grabfile_package(
- os.path.join(path, "profiles", "package.mask"),
- recursive=1,
- verify_eapi=True,
- allow_repo=allow_profile_repo_deps(repo),
- )
- )
-
- desc_path = os.path.join(path, "profiles", "profiles.desc")
- try:
- desc_file = io.open(
- _unicode_encode(desc_path, encoding=_encodings["fs"], errors="strict"),
- mode="r",
- encoding=_encodings["repo.content"],
- errors="replace",
- )
- except EnvironmentError:
- pass
- else:
- for i, x in enumerate(desc_file):
- if x[0] == "#":
- continue
- arch = x.split()
- if len(arch) == 0:
- continue
- if len(arch) != 3:
- err(
- 'wrong format: "%s" in %s line %d'
- % (
- bad(x.strip()),
- desc_path,
- i + 1,
- )
- )
- elif arch[0] not in kwlist:
- err(
- 'invalid arch: "%s" in %s line %d'
- % (
- bad(arch[0]),
- desc_path,
- i + 1,
- )
- )
- elif arch[2] not in valid_profile_types:
- err(
- 'invalid profile type: "%s" in %s line %d'
- % (
- bad(arch[2]),
- desc_path,
- i + 1,
- )
- )
- profile_desc = ProfileDesc(arch[0], arch[2], arch[1], path)
- if not os.path.isdir(profile_desc.abs_path):
- logging.error(
- "Invalid %s profile (%s) for arch %s in %s line %d",
- arch[2],
- arch[1],
- arch[0],
- desc_path,
- i + 1,
- )
- continue
- if os.path.exists(os.path.join(profile_desc.abs_path, "deprecated")):
- continue
- profile_list.append(profile_desc)
- desc_file.close()
-
- global_pmasklines = portage.util.stack_lists(global_pmasklines, incremental=1)
- global_pmaskdict = {}
- for x in global_pmasklines:
- global_pmaskdict.setdefault(x.cp, []).append(x)
- del global_pmasklines
-
- return (
- kwlist,
- liclist,
- uselist,
- profile_list,
- global_pmaskdict,
- list_checks(kwlist, liclist, uselist, repoman_settings),
- )
diff --git a/repoman/lib/repoman/scanner.py b/repoman/lib/repoman/scanner.py
deleted file mode 100644
index 890950c65bc..00000000000
--- a/repoman/lib/repoman/scanner.py
+++ /dev/null
@@ -1,484 +0,0 @@
-# -*- coding:utf-8 -*-
-
-import logging
-import portage
-
-from itertools import chain
-
-from portage import normalize_path
-from portage import os
-from portage._sets.base import InternalPackageSet
-from portage.output import green
-from portage.util.futures.extendedfutures import ExtendedFuture
-
-from repoman.metadata import get_metadata_xsd
-from repoman.modules.commit import repochecks
-from repoman.modules.commit import manifest
-from repoman.profile import check_profiles, dev_profile_keywords, setup_profile
-from repoman.repos import repo_metadata
-from repoman.modules.scan.module import ModuleConfig
-from repoman.modules.scan.scan import scan
-from repoman.modules.vcs.vcs import vcs_files_to_cps
-
-
-DATA_TYPES = {"dict": dict, "Future": ExtendedFuture, "list": list, "set": set}
-
-
-class Scanner:
- """Primary scan class. Operates all the small Q/A tests and checks"""
-
- def __init__(
- self, repo_settings, myreporoot, config_root, options, vcs_settings, mydir, env
- ):
- """Class __init__"""
- self.repo_settings = repo_settings
- self.config_root = config_root
- self.options = options
- self.vcs_settings = vcs_settings
- self.env = env
-
- # Repoman sets it's own ACCEPT_KEYWORDS and we don't want it to
- # behave incrementally.
- self.repoman_incrementals = tuple(
- x for x in portage.const.INCREMENTALS if x != "ACCEPT_KEYWORDS"
- )
-
- self.categories = []
- for path in self.repo_settings.repo_config.eclass_db.porttrees:
- self.categories.extend(
- portage.util.grabfile(os.path.join(path, "profiles", "categories"))
- )
- self.repo_settings.repoman_settings.categories = frozenset(
- portage.util.stack_lists([self.categories], incremental=1)
- )
- self.categories = self.repo_settings.repoman_settings.categories
-
- self.portdb = repo_settings.portdb
- self.portdb.settings = self.repo_settings.repoman_settings
-
- digest_only = (
- self.options.mode != "manifest-check" and self.options.digest == "y"
- )
- self.generate_manifest = digest_only or self.options.mode in (
- "manifest",
- "commit",
- "fix",
- )
-
- # We really only need to cache the metadata that's necessary for visibility
- # filtering. Anything else can be discarded to reduce memory consumption.
- if not self.generate_manifest:
- # Don't do this when generating manifests, since that uses
- # additional keys if spawn_nofetch is called (RESTRICT and
- # DEFINED_PHASES).
- self.portdb._aux_cache_keys.clear()
- self.portdb._aux_cache_keys.update(
- ["EAPI", "IUSE", "KEYWORDS", "repository", "SLOT"]
- )
-
- self.reposplit = myreporoot.split(os.path.sep)
- self.repolevel = len(self.reposplit)
-
- if self.options.mode == "commit":
- repochecks.commit_check(self.repolevel, self.reposplit)
- repochecks.conflict_check(self.vcs_settings, self.options)
-
- # Make startdir relative to the canonical repodir, so that we can pass
- # it to digestgen and it won't have to be canonicalized again.
- if self.repolevel == 1:
- startdir = self.repo_settings.repodir
- else:
- startdir = normalize_path(mydir)
- startdir = os.path.join(
- self.repo_settings.repodir,
- *startdir.split(os.sep)[-2 - self.repolevel + 3 :]
- )
-
- # get lists of valid keywords, licenses, and use
- new_data = repo_metadata(self.portdb, self.repo_settings.repoman_settings)
- (
- kwlist,
- liclist,
- uselist,
- profile_list,
- global_pmaskdict,
- liclist_deprecated,
- ) = new_data
- self.repo_metadata = {
- "kwlist": kwlist,
- "liclist": liclist,
- "uselist": uselist,
- "profile_list": profile_list,
- "pmaskdict": global_pmaskdict,
- "lic_deprecated": liclist_deprecated,
- "package.deprecated": InternalPackageSet(
- initial_atoms=portage.util.stack_lists(
- [
- portage.util.grabfile_package(
- os.path.join(path, "profiles", "package.deprecated"),
- recursive=True,
- )
- for path in self.portdb.porttrees
- ],
- incremental=True,
- )
- ),
- }
-
- self.repo_settings.repoman_settings["PORTAGE_ARCHLIST"] = " ".join(
- sorted(kwlist)
- )
- self.repo_settings.repoman_settings.backup_changes("PORTAGE_ARCHLIST")
-
- profiles = setup_profile(profile_list)
-
- check_profiles(profiles, self.repo_settings.repoman_settings.archlist())
-
- scanlist = scan(
- self.repolevel,
- self.reposplit,
- startdir,
- self.categories,
- self.repo_settings,
- )
-
- self.dev_keywords = dev_profile_keywords(profiles)
-
- self.qatracker = self.vcs_settings.qatracker
-
- if (
- self.options.echangelog is None
- and self.repo_settings.repo_config.update_changelog
- ):
- self.options.echangelog = "y"
-
- if self.vcs_settings.vcs is None:
- self.options.echangelog = "n"
-
- # Initialize the ModuleConfig class here
- # TODO Add layout.conf masters repository.yml config to the list to load/stack
- self.moduleconfig = ModuleConfig(
- self.repo_settings.masters_list,
- self.repo_settings.repoman_settings.valid_versions,
- repository_modules=self.options.experimental_repository_modules == "y",
- )
-
- checks = {}
- # The --echangelog option causes automatic ChangeLog generation,
- # which invalidates changelog.ebuildadded and changelog.missing
- # checks.
- # Note: Some don't use ChangeLogs in distributed SCMs.
- # It will be generated on server side from scm log,
- # before package moves to the rsync server.
- # This is needed because they try to avoid merge collisions.
- # Gentoo's Council decided to always use the ChangeLog file.
- # TODO: shouldn't this just be switched on the repo, iso the VCS?
- is_echangelog_enabled = self.options.echangelog in ("y", "force")
- self.vcs_settings.vcs_is_cvs_or_svn = self.vcs_settings.vcs in ("cvs", "svn")
- checks["changelog"] = (
- not is_echangelog_enabled and self.vcs_settings.vcs_is_cvs_or_svn
- )
-
- if self.options.mode == "manifest" or self.options.quiet:
- pass
- elif self.options.pretend:
- print(green("\nRepoMan does a once-over of the neighborhood..."))
- else:
- print(green("\nRepoMan scours the neighborhood..."))
-
- self.changed = self.vcs_settings.changes
- # bypass unneeded VCS operations if not needed
- if self.options.if_modified == "y" or self.options.mode not in (
- "manifest",
- "manifest-check",
- ):
- self.changed.scan()
-
- self.have = {
- "pmasked": False,
- "dev_keywords": False,
- }
-
- # NOTE: match-all caches are not shared due to potential
- # differences between profiles in _get_implicit_iuse.
- self.caches = {
- "arch": {},
- "arch_xmatch": {},
- "shared_xmatch": {"cp-list": {}},
- }
-
- self.include_arches = None
- if self.options.include_arches:
- self.include_arches = set()
- self.include_arches.update(
- *[x.split() for x in self.options.include_arches]
- )
- self.include_profiles = None
- if self.options.include_profiles:
- self.include_profiles = set()
- self.include_profiles.update(
- *[x.split() for x in self.options.include_profiles]
- )
-
- # Disable the "self.modules['Ebuild'].notadded" check when not in commit mode and
- # running `svn status` in every package dir will be too expensive.
- checks["ebuild_notadded"] = not (
- self.vcs_settings.vcs == "svn"
- and self.repolevel < 3
- and self.options.mode != "commit"
- )
-
- self.effective_scanlist = scanlist
- if self.options.if_modified == "y":
- self.effective_scanlist = sorted(
- vcs_files_to_cps(
- chain(self.changed.changed, self.changed.new, self.changed.removed),
- self.repo_settings.repodir,
- self.repolevel,
- self.reposplit,
- self.categories,
- )
- )
-
- # Create our kwargs dict here to initialize the plugins with
- self.kwargs = {
- "repo_settings": self.repo_settings,
- "portdb": self.portdb,
- "qatracker": self.qatracker,
- "vcs_settings": self.vcs_settings,
- "options": self.options,
- "metadata_xsd": get_metadata_xsd(self.repo_settings),
- "uselist": uselist,
- "checks": checks,
- "repo_metadata": self.repo_metadata,
- "profiles": profiles,
- "include_arches": self.include_arches,
- "include_profiles": self.include_profiles,
- "caches": self.caches,
- "repoman_incrementals": self.repoman_incrementals,
- "env": self.env,
- "have": self.have,
- "dev_keywords": self.dev_keywords,
- "linechecks": self.moduleconfig.linechecks,
- }
- # initialize the plugin checks here
- self.modules = {}
- self._ext_futures = {}
- self.pkg_level_futures = None
-
- def set_kwargs(self, mod):
- """Creates a limited set of kwargs to pass to the module's __init__()
-
- @param mod: module name string
- @returns: dictionary
- """
- kwargs = {}
- for key in self.moduleconfig.controller.modules[mod]["mod_kwargs"]:
- kwargs[key] = self.kwargs[key]
- return kwargs
-
- def set_func_kwargs(self, mod, dynamic_data=None):
- """Updates the dynamic_data dictionary with any new key, value pairs.
- Creates a limited set of kwargs to pass to the modulefunctions to run
-
- @param mod: module name string
- @param dynamic_data: dictionary structure
- @returns: dictionary
- """
- func_kwargs = self.moduleconfig.controller.modules[mod]["func_kwargs"]
- # determine new keys
- required = set(list(func_kwargs))
- exist = set(list(dynamic_data))
- new = required.difference(exist)
- # update dynamic_data with initialized entries
- for key in new:
- logging.debug("set_func_kwargs(); adding: %s, %s", key, func_kwargs[key])
- if func_kwargs[key][0] in ["Future", "ExtendedFuture"]:
- if key not in self._ext_futures:
- logging.debug(
- "Adding a new key: %s to the ExtendedFuture dict", key
- )
- self._ext_futures[key] = func_kwargs[key]
- self._set_future(dynamic_data, key, func_kwargs[key])
- else: # builtin python data type
- dynamic_data[key] = DATA_TYPES[func_kwargs[key][0]]()
- kwargs = {}
- for key in required:
- kwargs[key] = dynamic_data[key]
- return kwargs
-
- def reset_futures(self, dynamic_data):
- """Reset any Future data types
-
- @param dynamic_data: dictionary
- """
- for key in list(self._ext_futures):
- if key not in self.pkg_level_futures:
- self._set_future(dynamic_data, key, self._ext_futures[key])
-
- @staticmethod
- def _set_future(dynamic_data, key, data):
- """Set a dynamic_data key to a new ExtendedFuture instance
-
- @param dynamic_data: dictionary
- @param key: tuple of (dictionary-key, default-value)
- """
- if data[0] in ["Future", "ExtendedFuture"]:
- if data[1] in ["UNSET"]:
- dynamic_data[key] = ExtendedFuture()
- else:
- if data[1] in DATA_TYPES:
- default = DATA_TYPES[data[1]]()
- else:
- default = data[1]
- dynamic_data[key] = ExtendedFuture(default)
-
- def scan_pkgs(self, can_force):
- for xpkg in self.effective_scanlist:
- xpkg_continue = False
- # ebuilds and digests added to cvs respectively.
- logging.info("checking package %s", xpkg)
- # save memory by discarding xmatch caches from previous package(s)
- self.caches["arch_xmatch"].clear()
- catdir, pkgdir = xpkg.split("/")
- checkdir = self.repo_settings.repodir + "/" + xpkg
- checkdir_relative = ""
- if self.repolevel < 3:
- checkdir_relative = os.path.join(pkgdir, checkdir_relative)
- if self.repolevel < 2:
- checkdir_relative = os.path.join(catdir, checkdir_relative)
- checkdir_relative = os.path.join(".", checkdir_relative)
-
- # Run the status check
- if self.kwargs["checks"]["ebuild_notadded"]:
- self.vcs_settings.status.check(checkdir, checkdir_relative, xpkg)
-
- if self.generate_manifest:
- if not manifest.Manifest(**self.kwargs).update_manifest(checkdir):
- self.qatracker.add_error(
- "manifest.bad", os.path.join(xpkg, "Manifest")
- )
- if self.options.mode == "manifest":
- continue
- checkdirlist = os.listdir(checkdir)
-
- dynamic_data = {
- "changelog_modified": False,
- "checkdirlist": ExtendedFuture(checkdirlist),
- "checkdir": checkdir,
- "xpkg": xpkg,
- "changed": self.changed,
- "checkdir_relative": checkdir_relative,
- "can_force": can_force,
- "repolevel": self.repolevel,
- "catdir": catdir,
- "pkgdir": pkgdir,
- "validity_future": ExtendedFuture(True),
- "y_ebuild": None,
- # this needs to be reset at the pkg level only,
- # easiest is to just initialize it here
- "muselist": ExtendedFuture(set()),
- "src_uri_error": ExtendedFuture(),
- }
- self.pkg_level_futures = [
- "checkdirlist",
- "muselist",
- "pkgs",
- "src_uri_error",
- "validity_future",
- ]
- # need to set it up for ==> self.modules or some other ordered list
- logging.debug("***** starting pkgs_loop: %s", self.moduleconfig.pkgs_loop)
- for mod in self.moduleconfig.pkgs_loop:
- mod_class = self.moduleconfig.controller.get_class(mod)
- logging.debug("Initializing class name: %s", mod_class.__name__)
- self.modules[mod_class.__name__] = mod_class(**self.set_kwargs(mod))
- logging.debug("scan_pkgs; module: %s", mod_class.__name__)
- do_it, functions = self.modules[mod_class.__name__].runInPkgs
- if do_it:
- for func in functions:
- _continue = func(**self.set_func_kwargs(mod, dynamic_data))
- if _continue:
- # If we can't access all the metadata then it's totally unsafe to
- # commit since there's no way to generate a correct Manifest.
- # Do not try to do any more QA checks on this package since missing
- # metadata leads to false positives for several checks, and false
- # positives confuse users.
- xpkg_continue = True
- break
-
- if xpkg_continue:
- continue
-
- # Sort ebuilds in ascending order for the KEYWORDS.dropped check.
- pkgs = dynamic_data["pkgs"].get()
- ebuildlist = sorted(pkgs.values())
- ebuildlist = [pkg.pf for pkg in ebuildlist]
-
- if self.kwargs["checks"]["changelog"] and "ChangeLog" not in checkdirlist:
- self.qatracker.add_error("changelog.missing", xpkg + "/ChangeLog")
-
- changelog_path = os.path.join(checkdir_relative, "ChangeLog")
- dynamic_data["changelog_modified"] = (
- changelog_path in self.changed.changelogs
- )
-
- self._scan_ebuilds(ebuildlist, dynamic_data)
-
- def _scan_ebuilds(self, ebuildlist, dynamic_data):
-
- for y_ebuild in ebuildlist:
- self.reset_futures(dynamic_data)
- dynamic_data["y_ebuild"] = y_ebuild
-
- # initialize per ebuild plugin checks here
- # need to set it up for ==> self.modules_list or some other ordered list
- for mod in self.moduleconfig.ebuilds_loop:
- if mod:
- mod_class = self.moduleconfig.controller.get_class(mod)
- if mod_class.__name__ not in self.modules:
- logging.debug("Initializing class name: %s", mod_class.__name__)
- self.modules[mod_class.__name__] = mod_class(
- **self.set_kwargs(mod)
- )
- logging.debug("scan_ebuilds: module: %s", mod_class.__name__)
- do_it, functions = self.modules[mod_class.__name__].runInEbuilds
- logging.debug(
- "do_it: %s, functions: %s", do_it, [x.__name__ for x in functions]
- )
- if do_it:
- for func in functions:
- logging.debug("\tRunning function: %s", func)
- _continue = func(**self.set_func_kwargs(mod, dynamic_data))
- if _continue:
- # If we can't access all the metadata then it's totally unsafe to
- # commit since there's no way to generate a correct Manifest.
- # Do not try to do any more QA checks on this package since missing
- # metadata leads to false positives for several checks, and false
- # positives confuse users.
- # logging.debug("\t>>> Continuing")
- break
-
- logging.debug("Finished ebuild plugin loop, continuing...")
-
- # Final checks
- # initialize per pkg plugin final checks here
- # need to set it up for ==> self.modules_list or some other ordered list
- for mod in self.moduleconfig.final_loop:
- if mod:
- mod_class = self.moduleconfig.controller.get_class(mod)
- if mod_class.__name__ not in self.modules:
- logging.debug("Initializing class name: %s", mod_class.__name__)
- self.modules[mod_class.__name__] = mod_class(**self.set_kwargs(mod))
- logging.debug("scan_ebuilds final checks: module: %s", mod_class.__name__)
- do_it, functions = self.modules[mod_class.__name__].runInFinal
- logging.debug(
- "do_it: %s, functions: %s", do_it, [x.__name__ for x in functions]
- )
- if do_it:
- for func in functions:
- logging.debug("\tRunning function: %s", func)
- _continue = func(**self.set_func_kwargs(mod, dynamic_data))
- if _continue:
- # logging.debug("\t>>> Continuing")
- break
diff --git a/repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/06B3A311BD775C280D22A9305D90EA06352177F6.rev b/repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/06B3A311BD775C280D22A9305D90EA06352177F6.rev
deleted file mode 100644
index a6752fd30bb..00000000000
--- a/repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/06B3A311BD775C280D22A9305D90EA06352177F6.rev
+++ /dev/null
@@ -1,37 +0,0 @@
-This is a revocation certificate for the OpenPGP key:
-
-pub rsa4096 2020-07-14 [S]
- 06B3A311BD775C280D22A9305D90EA06352177F6
-uid Gentoo Portage Test Trusted Key (Test Only, Do NOT Trust!!!) (Gentoo Test Key) <test@example.org>
-
-A revocation certificate is a kind of "kill switch" to publicly
-declare that a key shall not anymore be used. It is not possible
-to retract such a revocation certificate once it has been published.
-
-Use it to revoke this key in case of a compromise or loss of
-the secret key. However, if the secret key is still accessible,
-it is better to generate a new revocation certificate and give
-a reason for the revocation. For details see the description of
-of the gpg command "--generate-revocation" in the GnuPG manual.
-
-To avoid an accidental use of this file, a colon has been inserted
-before the 5 dashes below. Remove this colon with a text editor
-before importing and publishing this revocation certificate.
-
-:-----BEGIN PGP PUBLIC KEY BLOCK-----
-Comment: This is a revocation certificate
-
-iQI2BCABCAAgFiEEBrOjEb13XCgNIqkwXZDqBjUhd/YFAl8OFTwCHQAACgkQXZDq
-BjUhd/aXCA/+OgzosMDaDe5DNwkSi2yKdC2X18v8JcaYnXBUR93nXA0LVN7iVWkR
-WEH3NuVspQZ5vK+3AHTKabqZFC/buA5oQOH01Ncd4lQISfOOhFiBn5DIPX31BVT0
-iPmVkcxHAD4031ptP4oat6EFclT13SRchtlnAO04JofeHnzQIw3SozQGzXpAA1g4
-BogQ0HWA88HzuEYYE+e/yzZL4D496X1DTaXksg0Py5c4SS6u5pND6lcUtAGxAwa9
-sJFPs+coeURaRV99CrJfdh4u2OkvINTfrKOS6NFBQq6HVH5mLsRXZlcE4Oo4d+fN
-XoPrTZnRUqpJADUdjHFvO/lr0fArJTS5IQCVBNFeCMlvgmUPeKWJ1r6Uiwe/UHor
-9OP/tK97EqpsaXmHbo0jOUkn5iiUwy784+JBSSu/Q2NxqcBr74aaRdfxvs62dmv7
-droCDQi3ebqTdnlDSaeCIWHyVlSroOhZ+ZETVy193K1X7VXFX3hYKiJ3G8QZwy3e
-AlsVGjIHWfC+K+enIn+uwSUvOWPN3upK8kqMRuXvAOppFCE4sTqNbxUnHHXaqo/r
-s1q6zVsWVILBk97BHlJph2IaqhV7iIgPU97/r4U/BT11VqDFdVSHcXcs4PDNs5vh
-6qttaDiyDqZjwMr+0iDoouHxFpqY8e+3M2gycUgGr2XV6ML0pXE6BqA=
-=nIjC
------END PGP PUBLIC KEY BLOCK-----
diff --git a/repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/8DEDA2CDED49C8809287B89D8812797DDF1DD192.rev b/repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/8DEDA2CDED49C8809287B89D8812797DDF1DD192.rev
deleted file mode 100644
index 456e0aa5041..00000000000
--- a/repoman/lib/repoman/tests/.gnupg/openpgp-revocs.d/8DEDA2CDED49C8809287B89D8812797DDF1DD192.rev
+++ /dev/null
@@ -1,37 +0,0 @@
-This is a revocation certificate for the OpenPGP key:
-
-pub rsa4096 2020-07-14 [S]
- 8DEDA2CDED49C8809287B89D8812797DDF1DD192
-uid Gentoo Portage Test Untrusted Key (Test Only, Do NOT Trust!!!) (Gentoo Test Key) <test@example.org>
-
-A revocation certificate is a kind of "kill switch" to publicly
-declare that a key shall not anymore be used. It is not possible
-to retract such a revocation certificate once it has been published.
-
-Use it to revoke this key in case of a compromise or loss of
-the secret key. However, if the secret key is still accessible,
-it is better to generate a new revocation certificate and give
-a reason for the revocation. For details see the description of
-of the gpg command "--generate-revocation" in the GnuPG manual.
-
-To avoid an accidental use of this file, a colon has been inserted
-before the 5 dashes below. Remove this colon with a text editor
-before importing and publishing this revocation certificate.
-
-:-----BEGIN PGP PUBLIC KEY BLOCK-----
-Comment: This is a revocation certificate
-
-iQI2BCABCAAgFiEEje2ize1JyICSh7idiBJ5fd8d0ZIFAl8OFXUCHQAACgkQiBJ5
-fd8d0ZKdwxAAhmkC0V+OLyOU9PCV6ogD9/3b3nVqNIreoc+gxHTLmEvxiMSItqmq
-DkcW9RJKAduA/HiLZQ8Yzxw+ldC6kuWqYEjNpSM54VDkrgOePi8W1bVDTCoSp7bo
-0JOG4frieqIxA6lhAA2UppH7EPRXoODPLYqooNxWAs3xxVrR6eGAb5l8NXzrymvN
-acFfOZ0s5FgADQskQHWVq6TaJn9DrcZxd+b+plSwPYDXqzTChKQ5jw7uMAPUvDkG
-JUWgoKiKSrK64bslUq8aEDEZQ4uxjyEi6G0vO/wPL/ysGhS7KkPgCZsEfNjWjajb
-jAsdvl1raoHxK/O7llMNr9uRAZtC56pJ//SRDc3kylZrkAo0RNoXQFowT739HWei
-2UkCFDfz488VKKrOI8TzTyUvLFEo14ZAXGg1wdHaGnbYMzxpKjP15alOFo6fKIcS
-Kz1f/Mab4wf4Sg0XAjQ9pnai1/U9ZF3/NSnRtYgJkLCrIEtRLrgSHJsLDPxjCfGV
-jWszAbIk167aA0yKsSmuwkpc5bZqqBaTo904r857fxyt5Les6SOHsV7iNXt7F+am
-03Y6u6m2eROba7M67l115vTyYcw5EZVp5j0nI81PXsC9X2DD1ci5xrNmPyEeupC4
-7y7mcGbUYPJAJHJ0kHG4ZYLnNMl42ZYr1ssEeasDwUsLWgVqvx9RkKI=
-=kVUQ
------END PGP PUBLIC KEY BLOCK-----
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
deleted file mode 100644
index 0bd1026ad24..00000000000
--- a/repoman/lib/repoman/tests/.gnupg/private-keys-v1.d/273B030399E7BEA66A9AD42216DE7CA17BA5D42E.key
+++ /dev/null
Binary files differ
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
deleted file mode 100644
index 8e29ef43ca5..00000000000
--- a/repoman/lib/repoman/tests/.gnupg/private-keys-v1.d/C99796FB85B0C3DF03314A11B5850C51167D6282.key
+++ /dev/null
Binary files differ
diff --git a/repoman/lib/repoman/tests/.gnupg/pubring.kbx b/repoman/lib/repoman/tests/.gnupg/pubring.kbx
deleted file mode 100644
index f6367f83bc9..00000000000
--- a/repoman/lib/repoman/tests/.gnupg/pubring.kbx
+++ /dev/null
Binary files differ
diff --git a/repoman/lib/repoman/tests/.gnupg/trustdb.gpg b/repoman/lib/repoman/tests/.gnupg/trustdb.gpg
deleted file mode 100644
index db5b1023b67..00000000000
--- a/repoman/lib/repoman/tests/.gnupg/trustdb.gpg
+++ /dev/null
Binary files differ
diff --git a/repoman/lib/repoman/tests/__init__.py b/repoman/lib/repoman/tests/__init__.py
deleted file mode 100644
index ba0872c5b5b..00000000000
--- a/repoman/lib/repoman/tests/__init__.py
+++ /dev/null
@@ -1,328 +0,0 @@
-# tests/__init__.py -- Portage Unit Test functionality
-# Copyright 2006-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-import argparse
-import sys
-import time
-import unittest
-
-from unittest.runner import TextTestResult as _TextTestResult
-
-import repoman
-from repoman import REPOMAN_BASE_PATH
-from repoman._portage import portage
-
-from portage import os
-from portage import _encodings
-from portage import _unicode_decode
-from portage.const import EPREFIX, GLOBAL_CONFIG_PATH, PORTAGE_BIN_PATH
-
-if repoman._not_installed:
- cnf_path = os.path.join(REPOMAN_BASE_PATH, "cnf")
- cnf_path_repoman = cnf_path
- cnf_etc_path = cnf_path
- cnf_bindir = os.path.join(REPOMAN_BASE_PATH, "bin")
- cnf_sbindir = cnf_bindir
-else:
- cnf_path = os.path.join(EPREFIX or "/", GLOBAL_CONFIG_PATH)
- cnf_path_repoman = os.path.join(
- EPREFIX or "/", sys.prefix.lstrip(os.sep), "share", "repoman"
- )
- cnf_etc_path = os.path.join(EPREFIX or "/", "etc")
- cnf_eprefix = EPREFIX
- cnf_bindir = os.path.join(EPREFIX or "/", "usr", "bin")
- cnf_sbindir = os.path.join(EPREFIX or "/", "usr", "sbin")
-
-
-def main():
- suite = unittest.TestSuite()
- basedir = os.path.dirname(os.path.realpath(__file__))
-
- usage = "usage: %s [options] [tests to run]" % os.path.basename(sys.argv[0])
- parser = argparse.ArgumentParser(usage=usage)
- parser.add_argument(
- "-l", "--list", help="list all tests", action="store_true", dest="list_tests"
- )
- options, args = parser.parse_known_args(args=sys.argv)
-
- if (
- os.environ.get("NOCOLOR") in ("yes", "true")
- or os.environ.get("TERM") == "dumb"
- or not sys.stdout.isatty()
- ):
- portage.output.nocolor()
-
- if options.list_tests:
- testdir = os.path.dirname(sys.argv[0])
- for mydir in getTestDirs(basedir):
- testsubdir = os.path.basename(mydir)
- for name in getTestNames(mydir):
- print("%s/%s/%s.py" % (testdir, testsubdir, name))
- return os.EX_OK
-
- if len(args) > 1:
- suite.addTests(getTestFromCommandLine(args[1:], basedir))
- else:
- for mydir in getTestDirs(basedir):
- suite.addTests(getTests(os.path.join(basedir, mydir), basedir))
-
- result = TextTestRunner(verbosity=2).run(suite)
- if not result.wasSuccessful():
- return 1
- return os.EX_OK
-
-
-def my_import(name):
- mod = __import__(name)
- components = name.split(".")
- for comp in components[1:]:
- mod = getattr(mod, comp)
- return mod
-
-
-def getTestFromCommandLine(args, base_path):
- result = []
- for arg in args:
- realpath = os.path.realpath(arg)
- path = os.path.dirname(realpath)
- f = realpath[len(path) + 1 :]
-
- if not f.startswith("test") or not f.endswith(".py"):
- raise Exception("Invalid argument: '%s'" % arg)
-
- mymodule = f[:-3]
- result.extend(getTestsFromFiles(path, base_path, [mymodule]))
- return result
-
-
-def getTestDirs(base_path):
- TEST_FILE = b"__test__.py"
- testDirs = []
-
- # the os.walk help mentions relative paths as being quirky
- # I was tired of adding dirs to the list, so now we add __test__.py
- # to each dir we want tested.
- for root, dirs, files in os.walk(base_path):
- try:
- root = _unicode_decode(root, encoding=_encodings["fs"], errors="strict")
- except UnicodeDecodeError:
- continue
-
- if TEST_FILE in files:
- testDirs.append(root)
-
- testDirs.sort()
- return testDirs
-
-
-def getTestNames(path):
- files = os.listdir(path)
- files = [f[:-3] for f in files if f.startswith("test") and f.endswith(".py")]
- files.sort()
- return files
-
-
-def getTestsFromFiles(path, base_path, files):
- parent_path = path[len(base_path) + 1 :]
- parent_module = ".".join(("repoman", "tests", parent_path))
- parent_module = parent_module.replace("/", ".")
- result = []
- for mymodule in files:
- # Make the trailing / a . for module importing
- modname = ".".join((parent_module, mymodule))
- mod = my_import(modname)
- result.append(unittest.TestLoader().loadTestsFromModule(mod))
- return result
-
-
-def getTests(path, base_path):
- """
-
- path is the path to a given subdir ( 'portage/' for example)
- This does a simple filter on files in that dir to give us modules
- to import
-
- """
- return getTestsFromFiles(path, base_path, getTestNames(path))
-
-
-class TextTestResult(_TextTestResult):
- """
- We need a subclass of unittest.runner.TextTestResult to handle tests with TODO
-
- This just adds an addTodo method that can be used to add tests
- that are marked TODO; these can be displayed later
- by the test runner.
- """
-
- def __init__(self, stream, descriptions, verbosity):
- super(TextTestResult, self).__init__(stream, descriptions, verbosity)
- self.todoed = []
- self.portage_skipped = []
-
- def addTodo(self, test, info):
- self.todoed.append((test, info))
- if self.showAll:
- self.stream.writeln("TODO")
- elif self.dots:
- self.stream.write(".")
-
- def addPortageSkip(self, test, info):
- self.portage_skipped.append((test, info))
- if self.showAll:
- self.stream.writeln("SKIP")
- elif self.dots:
- self.stream.write(".")
-
- def printErrors(self):
- if self.dots or self.showAll:
- self.stream.writeln()
- self.printErrorList("ERROR", self.errors)
- self.printErrorList("FAIL", self.failures)
- self.printErrorList("TODO", self.todoed)
- self.printErrorList("SKIP", self.portage_skipped)
-
-
-class TestCase(unittest.TestCase):
- """
- We need a way to mark a unit test as "ok to fail"
- This way someone can add a broken test and mark it as failed
- and then fix the code later. This may not be a great approach
- (broken code!!??!11oneone) but it does happen at times.
- """
-
- def __init__(self, *pargs, **kwargs):
- unittest.TestCase.__init__(self, *pargs, **kwargs)
- self.todo = False
- self.portage_skip = None
- self.cnf_path = cnf_path
- self.cnf_etc_path = cnf_etc_path
- self.bindir = cnf_bindir
- self.sbindir = cnf_sbindir
-
- def defaultTestResult(self):
- return TextTestResult()
-
- def run(self, result=None):
- if result is None:
- result = self.defaultTestResult()
- result.startTest(self)
- testMethod = getattr(self, self._testMethodName)
- try:
- try:
- self.setUp()
- except SystemExit:
- raise
- except KeyboardInterrupt:
- raise
- except:
- result.addError(self, sys.exc_info())
- return
-
- ok = False
- try:
- testMethod()
- ok = True
- except unittest.SkipTest as e:
- result.addPortageSkip(self, "%s: SKIP: %s" % (testMethod, str(e)))
- except self.failureException:
- if self.portage_skip is not None:
- if self.portage_skip is True:
- result.addPortageSkip(self, "%s: SKIP" % testMethod)
- else:
- result.addPortageSkip(
- self, "%s: SKIP: %s" % (testMethod, self.portage_skip)
- )
- elif self.todo:
- result.addTodo(self, "%s: TODO" % testMethod)
- else:
- result.addFailure(self, sys.exc_info())
- except (KeyboardInterrupt, SystemExit):
- raise
- except:
- result.addError(self, sys.exc_info())
-
- try:
- self.tearDown()
- except SystemExit:
- raise
- except KeyboardInterrupt:
- raise
- except:
- result.addError(self, sys.exc_info())
- ok = False
- if ok:
- result.addSuccess(self)
- finally:
- result.stopTest(self)
-
- def assertRaisesMsg(self, msg, excClass, callableObj, *args, **kwargs):
- """Fail unless an exception of class excClass is thrown
- by callableObj when invoked with arguments args and keyword
- arguments kwargs. If a different type of exception is
- thrown, it will not be caught, and the test case will be
- deemed to have suffered an error, exactly as for an
- unexpected exception.
- """
- try:
- callableObj(*args, **kwargs)
- except excClass:
- return
- else:
- if hasattr(excClass, "__name__"):
- excName = excClass.__name__
- else:
- excName = str(excClass)
- raise self.failureException("%s not raised: %s" % (excName, msg))
-
- def assertNotExists(self, path):
- """Make sure |path| does not exist"""
- if os.path.exists(path):
- raise self.failureException("path exists when it should not: %s" % path)
-
-
-class TextTestRunner(unittest.TextTestRunner):
- """
- We subclass unittest.TextTestRunner to output SKIP for tests that fail but are skippable
- """
-
- def _makeResult(self):
- return TextTestResult(self.stream, self.descriptions, self.verbosity)
-
- def run(self, test):
- """
- Run the given test case or test suite.
- """
- result = self._makeResult()
- startTime = time.time()
- test(result)
- stopTime = time.time()
- timeTaken = stopTime - startTime
- result.printErrors()
- self.stream.writeln(result.separator2)
- run = result.testsRun
- self.stream.writeln(
- "Ran %d test%s in %.3fs" % (run, run != 1 and "s" or "", timeTaken)
- )
- self.stream.writeln()
- if not result.wasSuccessful():
- self.stream.write("FAILED (")
- failed = len(result.failures)
- errored = len(result.errors)
- if failed:
- self.stream.write("failures=%d" % failed)
- if errored:
- if failed:
- self.stream.write(", ")
- self.stream.write("errors=%d" % errored)
- self.stream.writeln(")")
- else:
- self.stream.writeln("OK")
- return result
-
-
-test_cps = ["sys-apps/portage", "virtual/portage"]
-test_versions = ["1.0", "1.0-r1", "2.3_p4", "1.0_alpha57"]
-test_slots = [None, "1", "gentoo-sources-2.6.17", "spankywashere"]
-test_usedeps = ["foo", "-bar", ("foo", "bar"), ("foo", "-bar"), ("foo?", "!bar?")]
diff --git a/repoman/lib/repoman/tests/__test__.py b/repoman/lib/repoman/tests/__test__.py
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/repoman/lib/repoman/tests/__test__.py
+++ /dev/null
diff --git a/repoman/lib/repoman/tests/changelog/__init__.py b/repoman/lib/repoman/tests/changelog/__init__.py
deleted file mode 100644
index 532918b6a39..00000000000
--- a/repoman/lib/repoman/tests/changelog/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# Copyright 2011 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
diff --git a/repoman/lib/repoman/tests/changelog/__test__.py b/repoman/lib/repoman/tests/changelog/__test__.py
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/repoman/lib/repoman/tests/changelog/__test__.py
+++ /dev/null
diff --git a/repoman/lib/repoman/tests/changelog/test_echangelog.py b/repoman/lib/repoman/tests/changelog/test_echangelog.py
deleted file mode 100644
index f0c43e20b8f..00000000000
--- a/repoman/lib/repoman/tests/changelog/test_echangelog.py
+++ /dev/null
@@ -1,169 +0,0 @@
-# Copyright 2012 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-import tempfile
-import time
-
-from portage import os
-from portage import shutil
-from portage.tests import TestCase
-from repoman.utilities import UpdateChangeLog
-
-
-class RepomanEchangelogTestCase(TestCase):
- def setUp(self):
- super(RepomanEchangelogTestCase, self).setUp()
-
- self.tmpdir = tempfile.mkdtemp(prefix="repoman.echangelog.")
-
- self.skel_changelog = os.path.join(self.tmpdir, "skel.ChangeLog")
- skel = [
- "# ChangeLog for <CATEGORY>/<PACKAGE_NAME>\n",
- "# Copyright 1999-2000 Gentoo Foundation; Distributed under the GPL v2\n",
- "# $Header: $\n",
- ]
- self._writelines(self.skel_changelog, skel)
-
- self.cat = "mycat"
- self.pkg = "mypkg"
- self.pkgdir = os.path.join(self.tmpdir, self.cat, self.pkg)
- os.makedirs(self.pkgdir)
-
- self.header_pkg = "# ChangeLog for %s/%s\n" % (self.cat, self.pkg)
- self.header_copyright = (
- "# Copyright 1999-%s Gentoo Authors; Distributed under the GPL v2\n"
- % time.strftime("%Y", time.gmtime())
- )
- self.header_cvs = "# $Header: $\n"
-
- self.changelog = os.path.join(self.pkgdir, "ChangeLog")
-
- self.user = "Testing User <portage@gentoo.org>"
-
- def tearDown(self):
- super(RepomanEchangelogTestCase, self).tearDown()
- shutil.rmtree(self.tmpdir)
-
- def _readlines(self, file):
- with open(file, "r") as f:
- return f.readlines()
-
- def _writelines(self, file, data):
- with open(file, "w") as f:
- f.writelines(data)
-
- def testRejectRootUser(self):
- self.assertEqual(
- UpdateChangeLog(
- self.pkgdir, "me <root@gentoo.org>", "", "", "", "", quiet=True
- ),
- None,
- )
-
- def testMissingSkelFile(self):
- # Test missing ChangeLog, but with empty skel (i.e. do nothing).
- UpdateChangeLog(
- self.pkgdir,
- self.user,
- "test!",
- "/does/not/exist",
- self.cat,
- self.pkg,
- quiet=True,
- )
- actual_cl = self._readlines(self.changelog)
- self.assertTrue(len(actual_cl[0]) > 0)
-
- def testEmptyChangeLog(self):
- # Make sure we do the right thing with a 0-byte ChangeLog
- open(self.changelog, "w").close()
- UpdateChangeLog(
- self.pkgdir,
- self.user,
- "test!",
- self.skel_changelog,
- self.cat,
- self.pkg,
- quiet=True,
- )
- actual_cl = self._readlines(self.changelog)
- self.assertEqual(actual_cl[0], self.header_pkg)
- self.assertEqual(actual_cl[1], self.header_copyright)
- self.assertEqual(actual_cl[2], self.header_cvs)
-
- def testCopyrightUpdate(self):
- # Make sure updating the copyright line works
- UpdateChangeLog(
- self.pkgdir,
- self.user,
- "test!",
- self.skel_changelog,
- self.cat,
- self.pkg,
- quiet=True,
- )
- actual_cl = self._readlines(self.changelog)
- self.assertEqual(actual_cl[1], self.header_copyright)
-
- def testSkelHeader(self):
- # Test skel.ChangeLog -> ChangeLog
- UpdateChangeLog(
- self.pkgdir,
- self.user,
- "test!",
- self.skel_changelog,
- self.cat,
- self.pkg,
- quiet=True,
- )
- actual_cl = self._readlines(self.changelog)
- self.assertEqual(actual_cl[0], self.header_pkg)
- self.assertNotEqual(actual_cl[-1], "\n")
-
- def testExistingGoodHeader(self):
- # Test existing ChangeLog (correct values)
- self._writelines(self.changelog, [self.header_pkg])
-
- UpdateChangeLog(
- self.pkgdir,
- self.user,
- "test!",
- self.skel_changelog,
- self.cat,
- self.pkg,
- quiet=True,
- )
- actual_cl = self._readlines(self.changelog)
- self.assertEqual(actual_cl[0], self.header_pkg)
-
- def testExistingBadHeader(self):
- # Test existing ChangeLog (wrong values)
- self._writelines(self.changelog, ["# ChangeLog for \n"])
-
- UpdateChangeLog(
- self.pkgdir,
- self.user,
- "test!",
- self.skel_changelog,
- self.cat,
- self.pkg,
- quiet=True,
- )
- actual_cl = self._readlines(self.changelog)
- self.assertEqual(actual_cl[0], self.header_pkg)
-
- def testTrailingNewlines(self):
- # Make sure trailing newlines get chomped.
- self._writelines(self.changelog, ["#\n", "foo\n", "\n", "bar\n", "\n", "\n"])
-
- UpdateChangeLog(
- self.pkgdir,
- self.user,
- "test!",
- self.skel_changelog,
- self.cat,
- self.pkg,
- quiet=True,
- )
- actual_cl = self._readlines(self.changelog)
- self.assertNotEqual(actual_cl[-1], "\n")
diff --git a/repoman/lib/repoman/tests/commit/__init__.py b/repoman/lib/repoman/tests/commit/__init__.py
deleted file mode 100644
index d74fd94a7d8..00000000000
--- a/repoman/lib/repoman/tests/commit/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# Copyright 2011-2018 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
diff --git a/repoman/lib/repoman/tests/commit/__test__.py b/repoman/lib/repoman/tests/commit/__test__.py
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/repoman/lib/repoman/tests/commit/__test__.py
+++ /dev/null
diff --git a/repoman/lib/repoman/tests/commit/test_commitmsg.py b/repoman/lib/repoman/tests/commit/test_commitmsg.py
deleted file mode 100644
index 392d17cb32f..00000000000
--- a/repoman/lib/repoman/tests/commit/test_commitmsg.py
+++ /dev/null
@@ -1,155 +0,0 @@
-# Copyright 2011-2018 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-
-from repoman.actions import Actions
-from repoman.tests import TestCase
-
-
-class CommitMessageVerificationTest(TestCase):
- def assertGood(self, commitmsg):
- res, expl = Actions.verify_commit_message(commitmsg)
- self.assertTrue(
- res,
- """Commit message verification failed for:
-%s
-
-Error:
-%s"""
- % (commitmsg, expl),
- )
-
- def assertBad(self, commitmsg, reason_re):
- res, expl = Actions.verify_commit_message(commitmsg)
- self.assertFalse(
- res,
- """Commit message verification succeeded unexpectedly, for:
-%s
-
-Expected: /%s/"""
- % (commitmsg, reason_re),
- )
- self.assertNotIn(
- "\n",
- expl.strip(),
- """Commit message verification returned multiple errors (one expected):
-%s
-
-Expected: /%s/
-Errors:
-%s"""
- % (commitmsg, reason_re, expl),
- )
- (
- self.assertRegex
- if hasattr(self, "assertRegex")
- else self.assertRegexpMatches
- )(
- expl,
- reason_re,
- """Commit message verification did not return expected error, for:
-%s
-
-Expected: /%s/
-Errors:
-%s"""
- % (commitmsg, reason_re, expl),
- )
-
- def test_summary_only(self):
- self.assertGood("dev-foo/bar: Actually good commit message")
-
- def test_summary_and_body(self):
- self.assertGood(
- """dev-foo/bar: Good commit message
-
-Extended description goes here and is properly wrapped at 72 characters
-which is very nice and blah blah.
-
-Another paragraph for the sake of having one."""
- )
-
- def test_summary_and_footer(self):
- self.assertGood(
- """dev-foo/bar: Good commit message
-
-Closes: https://bugs.gentoo.org/NNNNNN"""
- )
-
- def test_summary_body_and_footer(self):
- self.assertGood(
- """dev-foo/bar: Good commit message
-
-Extended description goes here and is properly wrapped at 72 characters
-which is very nice and blah blah.
-
-Another paragraph for the sake of having one.
-
-Closes: https://bugs.gentoo.org/NNNNNN"""
- )
-
- def test_summary_without_unit_name(self):
- self.assertBad("Version bump", r"summary.*logical unit name")
-
- def test_multiline_summary(self):
- self.assertBad(
- """dev-foo/bar: Commit message with very long summary
-that got wrapped because of length""",
- r"single.*line.*summary",
- )
-
- def test_overlong_summary(self):
- self.assertBad(
- "dev-foo/bar: Commit message with very long summary \
-in a single line that should trigger an explicit error",
- r"summary.*too long",
- )
-
- def test_summary_with_very_long_package_name(self):
- self.assertGood(
- "dev-foo/foo-bar-bar-baz-bar-bar-foo-bar-bar-\
-baz-foo-baz-baz-foo: We do not fail because pkgname was long"
- )
-
- def test_multiple_footers(self):
- self.assertBad(
- """dev-foo/bar: Good summary
-
-Bug: https://bugs.gentoo.org/NNNNNN
-
-Closes: https://github.com/gentoo/gentoo/pull/NNNN""",
- r"multiple footer",
- )
-
- def test_gentoo_bug(self):
- self.assertBad(
- """dev-foo/bar: Good summary
-
-Gentoo-Bug: NNNNNN""",
- r"Gentoo-Bug",
- )
-
- def test_bug_with_number(self):
- self.assertBad(
- """dev-foo/bar: Good summary
-
-Bug: NNNNNN""",
- r"Bug.*full URL",
- )
-
- def test_closes_with_number(self):
- self.assertBad(
- """dev-foo/bar: Good summary
-
-Closes: NNNNNN""",
- r"Closes.*full URL",
- )
-
- def test_body_too_long(self):
- self.assertBad(
- """dev-foo/bar: Good summary
-
-But the body is not wrapped properly and has very long lines that are \
-very hard to read and blah blah blah
-blah blah.""",
- r"body.*wrapped",
- )
diff --git a/repoman/lib/repoman/tests/runTests.py b/repoman/lib/repoman/tests/runTests.py
deleted file mode 100644
index 4a081551ea7..00000000000
--- a/repoman/lib/repoman/tests/runTests.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python
-# runTests.py -- Portage Unit Test Functionality
-# Copyright 2006-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-import os
-import os.path as osp
-import sys
-import grp
-import platform
-import pwd
-import signal
-import tempfile
-from distutils.dir_util import copy_tree
-
-
-def debug_signal(signum, frame):
- import pdb
-
- pdb.set_trace()
-
-
-if platform.python_implementation() == "Jython":
- debug_signum = signal.SIGUSR2 # bug #424259
-else:
- debug_signum = signal.SIGUSR1
-
-signal.signal(debug_signum, debug_signal)
-
-# Pretend that the current user's uid/gid are the 'portage' uid/gid,
-# so things go smoothly regardless of the current user and global
-# user/group configuration.
-os.environ["PORTAGE_USERNAME"] = pwd.getpwuid(os.getuid()).pw_name
-os.environ["PORTAGE_GRPNAME"] = grp.getgrgid(os.getgid()).gr_name
-
-# Insert our parent dir so we can do shiny import "tests"
-# This line courtesy of Marienz and Pkgcore ;)
-repoman_pym = osp.dirname(osp.dirname(osp.dirname(osp.realpath(__file__))))
-sys.path.insert(0, repoman_pym)
-
-# Add in the parent portage python modules
-portage_pym = osp.dirname(osp.dirname(repoman_pym)) + "/lib"
-sys.path.insert(0, portage_pym)
-
-# import our centrally initialized portage instance
-from repoman._portage import portage
-
-portage._internal_caller = True
-import repoman.tests as tests
-
-# Ensure that we don't instantiate portage.settings, so that tests should
-# work the same regardless of global configuration file state/existence.
-portage._disable_legacy_globals()
-from portage.util._eventloop.global_event_loop import global_event_loop
-from portage.const import PORTAGE_BIN_PATH
-
-if os.environ.get("NOCOLOR") in ("yes", "true"):
- portage.output.nocolor()
-
-path = os.environ.get("PATH", "").split(":")
-path = [x for x in path if x]
-
-insert_bin_path = True
-try:
- insert_bin_path = not path or not os.path.samefile(path[0], PORTAGE_BIN_PATH)
-except OSError:
- pass
-
-if insert_bin_path:
- path.insert(0, PORTAGE_BIN_PATH)
- os.environ["PATH"] = ":".join(path)
-
-# Copy GPG test keys to temporary directory
-gpg_path = tempfile.mkdtemp(prefix="gpg_")
-
-copy_tree(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".gnupg"), gpg_path)
-
-os.chmod(gpg_path, 0o700)
-os.environ["PORTAGE_GNUPGHOME"] = gpg_path
-
-if __name__ == "__main__":
- try:
- sys.exit(tests.main())
- finally:
- global_event_loop().close()
diff --git a/repoman/lib/repoman/tests/simple/__init__.py b/repoman/lib/repoman/tests/simple/__init__.py
deleted file mode 100644
index 532918b6a39..00000000000
--- a/repoman/lib/repoman/tests/simple/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# Copyright 2011 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
diff --git a/repoman/lib/repoman/tests/simple/__test__.py b/repoman/lib/repoman/tests/simple/__test__.py
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/repoman/lib/repoman/tests/simple/__test__.py
+++ /dev/null
diff --git a/repoman/lib/repoman/tests/simple/test_simple.py b/repoman/lib/repoman/tests/simple/test_simple.py
deleted file mode 100644
index 41735b8b426..00000000000
--- a/repoman/lib/repoman/tests/simple/test_simple.py
+++ /dev/null
@@ -1,512 +0,0 @@
-# Copyright 2011-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-import collections
-import subprocess
-import sys
-import time
-import types
-
-from repoman._portage import portage
-from portage import os
-from portage.process import find_binary
-from portage.tests.resolver.ResolverPlayground import ResolverPlayground
-from portage.util import ensure_dirs
-from portage.util.futures import asyncio
-from portage.util.futures._asyncio.streams import _reader
-from portage.util._async.AsyncFunction import AsyncFunction
-
-# pylint: disable=ungrouped-imports
-from repoman import REPOMAN_BASE_PATH
-from repoman.copyrights import update_copyright_year
-from repoman.main import _repoman_init, _repoman_scan, _handle_result
-from repoman.tests import TestCase
-
-
-class RepomanRun(types.SimpleNamespace):
- async def run(self):
- self.expected = getattr(self, "expected", None) or {"returncode": 0}
- if self.debug:
- fd_pipes = {}
- pr = None
- pw = None
- else:
- pr, pw = os.pipe()
- fd_pipes = {1: pw, 2: pw}
- pr = open(pr, "rb", 0)
-
- proc = AsyncFunction(
- scheduler=asyncio.get_event_loop(),
- target=self._subprocess,
- args=(self.args, self.cwd, self.env, self.expected, self.debug),
- fd_pipes=fd_pipes,
- )
-
- proc.start()
- if pw is not None:
- os.close(pw)
-
- await proc.async_wait()
-
- if pr is None:
- stdio = None
- else:
- stdio = await _reader(pr)
-
- self.result = {
- "stdio": stdio,
- "result": proc.result,
- }
-
- @staticmethod
- def _subprocess(args, cwd, env, expected, debug):
- os.chdir(cwd)
- os.environ.update(env)
- portage.const.EPREFIX = env["PORTAGE_OVERRIDE_EPREFIX"]
- if debug:
- args = ["-vvvv"] + args
- repoman_vars = _repoman_init(["repoman"] + args)
- if repoman_vars.exitcode is not None:
- return {"returncode": repoman_vars.exitcode}
- result = _repoman_scan(*repoman_vars)
- returncode = _handle_result(*repoman_vars, result)
- qawarnings = repoman_vars.vcs_settings.qatracker.qawarnings
- warns = collections.defaultdict(list)
- fails = collections.defaultdict(list)
- for qacat, issues in repoman_vars.vcs_settings.qatracker.fails.items():
- if qacat in qawarnings:
- warns[qacat].extend(issues)
- else:
- fails[qacat].extend(issues)
- result = {"returncode": returncode}
- if fails:
- result["fails"] = fails
- if warns:
- result["warns"] = warns
- return result
-
-
-class SimpleRepomanTestCase(TestCase):
- def testCopyrightUpdate(self):
- test_cases = (
- (
- "2011",
- "# Copyright 1999-2008 Gentoo Foundation; Distributed under the GPL v2",
- "# Copyright 1999-2011 Gentoo Authors; Distributed under the GPL v2",
- ),
- (
- "2011",
- "# Copyright 1999 Gentoo Foundation; Distributed under the GPL v2",
- "# Copyright 1999-2011 Gentoo Authors; Distributed under the GPL v2",
- ),
- (
- "1999",
- "# Copyright 1999 Gentoo Foundation; Distributed under the GPL v2",
- "# Copyright 1999 Gentoo Foundation; Distributed under the GPL v2",
- ),
- (
- "2018",
- "# Copyright 1999-2008 Gentoo Authors; Distributed under the GPL v2",
- "# Copyright 1999-2018 Gentoo Authors; Distributed under the GPL v2",
- ),
- (
- "2018",
- "# Copyright 2017 Gentoo Authors; Distributed under the GPL v2",
- "# Copyright 2017-2018 Gentoo Authors; Distributed under the GPL v2",
- ),
- )
-
- for year, before, after in test_cases:
- self.assertEqual(update_copyright_year(year, before), after)
-
- def _must_skip(self):
- xmllint = find_binary("xmllint")
- if not xmllint:
- return "xmllint not found"
-
- try:
- __import__("xml.etree.ElementTree")
- __import__("xml.parsers.expat").parsers.expat.ExpatError
- except (AttributeError, ImportError):
- return "python is missing xml support"
-
- def testSimple(self):
- debug = False
-
- skip_reason = self._must_skip()
- if skip_reason:
- self.portage_skip = skip_reason
- self.assertFalse(True, skip_reason)
- return
-
- copyright_header = (
- """# Copyright 1999-%s Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-"""
- % time.gmtime().tm_year
- )
-
- pkg_preinst_references_forbidden_var = """
-pkg_preinst() {
- echo "This ${A} reference is not allowed. Neither is this $BROOT reference."
-}
-"""
-
- repo_configs = {
- "test_repo": {
- "layout.conf": ("update-changelog = true",),
- }
- }
-
- profiles = (
- ("x86", "default/linux/x86/test_profile", "stable"),
- ("x86", "default/linux/x86/test_dev", "dev"),
- ("x86", "default/linux/x86/test_exp", "exp"),
- )
-
- profile = {"eapi": ("5",), "package.use.stable.mask": ("dev-libs/A flag",)}
-
- ebuilds = {
- "dev-libs/A-0": {
- "COPYRIGHT_HEADER": copyright_header,
- "DESCRIPTION": "Desc goes here",
- "EAPI": "5",
- "HOMEPAGE": "https://example.com",
- "IUSE": "flag",
- "KEYWORDS": "x86",
- "LICENSE": "GPL-2",
- "RDEPEND": "flag? ( dev-libs/B[flag] )",
- },
- "dev-libs/A-1": {
- "COPYRIGHT_HEADER": copyright_header,
- "DESCRIPTION": "Desc goes here",
- "EAPI": "4",
- "HOMEPAGE": "https://example.com",
- "IUSE": "flag",
- "KEYWORDS": "~x86",
- "LICENSE": "GPL-2",
- "RDEPEND": "flag? ( dev-libs/B[flag] )",
- },
- "dev-libs/B-1": {
- "COPYRIGHT_HEADER": copyright_header,
- "DESCRIPTION": "Desc goes here",
- "EAPI": "4",
- "HOMEPAGE": "https://example.com",
- "IUSE": "flag",
- "KEYWORDS": "~x86",
- "LICENSE": "GPL-2",
- },
- "dev-libs/C-0": {
- "COPYRIGHT_HEADER": copyright_header,
- "DESCRIPTION": "Desc goes here",
- "EAPI": "7",
- "HOMEPAGE": "https://example.com",
- "IUSE": "flag",
- # must be unstable, since dev-libs/A[flag] is stable masked
- "KEYWORDS": "~x86",
- "LICENSE": "GPL-2",
- "RDEPEND": "flag? ( dev-libs/A[flag] )",
- "MISC_CONTENT": pkg_preinst_references_forbidden_var,
- },
- }
- licenses = ["GPL-2"]
- arch_list = ["x86"]
- metadata_xsd = os.path.join(REPOMAN_BASE_PATH, "cnf/metadata.xsd")
- metadata_xml_files = (
- (
- "dev-libs/A",
- {
- "flags": "<flag name='flag' restrict='&gt;=dev-libs/A-0'>Description of how USE='flag' affects this package</flag>",
- },
- ),
- (
- "dev-libs/B",
- {
- "flags": "<flag name='flag'>Description of how USE='flag' affects this package</flag>",
- },
- ),
- (
- "dev-libs/C",
- {
- "flags": "<flag name='flag'>Description of how USE='flag' affects this package</flag>",
- },
- ),
- )
-
- use_desc = (("flag", "Description of how USE='flag' affects packages"),)
-
- playground = ResolverPlayground(
- ebuilds=ebuilds, profile=profile, repo_configs=repo_configs, debug=debug
- )
-
- loop = asyncio._wrap_loop()
- loop.run_until_complete(
- asyncio.ensure_future(
- self._async_test_simple(
- playground,
- metadata_xml_files,
- profiles,
- profile,
- licenses,
- arch_list,
- use_desc,
- metadata_xsd,
- copyright_header,
- debug,
- ),
- loop=loop,
- )
- )
-
- async def _async_test_simple(
- self,
- playground,
- metadata_xml_files,
- profiles,
- profile,
- licenses,
- arch_list,
- use_desc,
- metadata_xsd,
- copyright_header,
- debug,
- ):
- settings = playground.settings
- eprefix = settings["EPREFIX"]
- eroot = settings["EROOT"]
- portdb = playground.trees[playground.eroot]["porttree"].dbapi
- homedir = os.path.join(eroot, "home")
- distdir = os.path.join(eprefix, "distdir")
- test_repo_location = settings.repositories["test_repo"].location
- profiles_dir = os.path.join(test_repo_location, "profiles")
- license_dir = os.path.join(test_repo_location, "licenses")
-
- repoman_cmd = (
- portage._python_interpreter,
- "-b",
- "-Wd",
- os.path.join(self.bindir, "repoman"),
- )
-
- git_binary = find_binary("git")
- git_cmd = (git_binary,)
-
- cp_binary = find_binary("cp")
- self.assertEqual(cp_binary is None, False, "cp command not found")
- cp_cmd = (cp_binary,)
-
- test_ebuild = portdb.findname("dev-libs/A-1")
- self.assertFalse(test_ebuild is None)
-
- committer_name = "Gentoo Dev"
- committer_email = "gentoo-dev@gentoo.org"
- expected_warnings = {
- "returncode": 0,
- "warns": {
- "variable.phase": [
- "dev-libs/C/C-0.ebuild: line 15: phase pkg_preinst: EAPI 7: variable A: Forbidden reference to variable specified by PMS",
- "dev-libs/C/C-0.ebuild: line 15: phase pkg_preinst: EAPI 7: variable BROOT: Forbidden reference to variable specified by PMS",
- ]
- },
- }
-
- git_test = (
- ("", RepomanRun(args=["--version"])),
- ("", RepomanRun(args=["manifest"])),
- (
- "",
- git_cmd
- + (
- "config",
- "--global",
- "user.name",
- committer_name,
- ),
- ),
- (
- "",
- git_cmd
- + (
- "config",
- "--global",
- "user.email",
- committer_email,
- ),
- ),
- ("", git_cmd + ("init-db",)),
- ("", git_cmd + ("add", ".")),
- ("", git_cmd + ("commit", "-a", "-m", "add whole repo")),
- ("", RepomanRun(args=["full", "-d"], expected=expected_warnings)),
- (
- "",
- RepomanRun(
- args=[
- "full",
- "--include-profiles",
- "default/linux/x86/test_profile",
- ],
- expected=expected_warnings,
- ),
- ),
- ("", cp_cmd + (test_ebuild, test_ebuild[:-8] + "2.ebuild")),
- ("", git_cmd + ("add", test_ebuild[:-8] + "2.ebuild")),
- (
- "",
- RepomanRun(
- args=["commit", "-m", "cat/pkg: bump to version 2"],
- expected=expected_warnings,
- ),
- ),
- ("", cp_cmd + (test_ebuild, test_ebuild[:-8] + "3.ebuild")),
- ("", git_cmd + ("add", test_ebuild[:-8] + "3.ebuild")),
- (
- "dev-libs",
- RepomanRun(
- args=["commit", "-m", "cat/pkg: bump to version 3"],
- expected=expected_warnings,
- ),
- ),
- ("", cp_cmd + (test_ebuild, test_ebuild[:-8] + "4.ebuild")),
- ("", git_cmd + ("add", test_ebuild[:-8] + "4.ebuild")),
- (
- "dev-libs/A",
- RepomanRun(args=["commit", "-m", "cat/pkg: bump to version 4"]),
- ),
- )
-
- env = {
- "PORTAGE_OVERRIDE_EPREFIX": eprefix,
- "DISTDIR": distdir,
- "GENTOO_COMMITTER_NAME": committer_name,
- "GENTOO_COMMITTER_EMAIL": committer_email,
- "HOME": homedir,
- "PATH": os.environ["PATH"],
- "PORTAGE_GRPNAME": os.environ["PORTAGE_GRPNAME"],
- "PORTAGE_USERNAME": os.environ["PORTAGE_USERNAME"],
- "PORTAGE_REPOSITORIES": settings.repositories.config_string(),
- "PYTHONDONTWRITEBYTECODE": os.environ.get("PYTHONDONTWRITEBYTECODE", ""),
- }
-
- if os.environ.get("SANDBOX_ON") == "1":
- # avoid problems from nested sandbox instances
- env["FEATURES"] = "-sandbox -usersandbox"
-
- dirs = [homedir, license_dir, profiles_dir, distdir]
- try:
- for d in dirs:
- ensure_dirs(d)
- with open(os.path.join(test_repo_location, "skel.ChangeLog"), "w") as f:
- f.write(copyright_header)
- with open(os.path.join(profiles_dir, "profiles.desc"), "w") as f:
- for x in profiles:
- f.write("%s %s %s\n" % x)
-
- # ResolverPlayground only created the first profile,
- # so create the remaining ones.
- for x in profiles[1:]:
- sub_profile_dir = os.path.join(profiles_dir, x[1])
- ensure_dirs(sub_profile_dir)
- for config_file, lines in profile.items():
- file_name = os.path.join(sub_profile_dir, config_file)
- with open(file_name, "w") as f:
- for line in lines:
- f.write("%s\n" % line)
-
- for x in licenses:
- open(os.path.join(license_dir, x), "wb").close()
- with open(os.path.join(profiles_dir, "arch.list"), "w") as f:
- for x in arch_list:
- f.write("%s\n" % x)
- with open(os.path.join(profiles_dir, "use.desc"), "w") as f:
- for k, v in use_desc:
- f.write("%s - %s\n" % (k, v))
- for cp, xml_data in metadata_xml_files:
- with open(
- os.path.join(test_repo_location, cp, "metadata.xml"), "w"
- ) as f:
- f.write(playground.metadata_xml_template % xml_data)
- # Use a symlink to test_repo, in order to trigger bugs
- # involving canonical vs. non-canonical paths.
- test_repo_symlink = os.path.join(eroot, "test_repo_symlink")
- os.symlink(test_repo_location, test_repo_symlink)
- metadata_xsd_dest = os.path.join(
- test_repo_location, "metadata/xml-schema/metadata.xsd"
- )
- os.makedirs(os.path.dirname(metadata_xsd_dest))
- os.symlink(metadata_xsd, metadata_xsd_dest)
-
- if debug:
- # The subprocess inherits both stdout and stderr, for
- # debugging purposes.
- stdout = None
- else:
- # The subprocess inherits stderr so that any warnings
- # triggered by python -Wd will be visible.
- stdout = subprocess.PIPE
-
- for cwd in ("", "dev-libs", "dev-libs/A", "dev-libs/B", "dev-libs/C"):
- abs_cwd = os.path.join(test_repo_symlink, cwd)
-
- proc = await asyncio.create_subprocess_exec(
- *(repoman_cmd + ("full",)),
- env=env,
- stderr=None,
- stdout=stdout,
- cwd=abs_cwd
- )
-
- if debug:
- await proc.wait()
- else:
- output, _err = await proc.communicate()
- await proc.wait()
- if proc.returncode != os.EX_OK:
- portage.writemsg(output)
-
- self.assertEqual(
- os.EX_OK, proc.returncode, "repoman failed in %s" % (cwd,)
- )
-
- if git_binary is not None:
- for cwd, cmd in git_test:
- abs_cwd = os.path.join(test_repo_symlink, cwd)
- if isinstance(cmd, RepomanRun):
- cmd.cwd = abs_cwd
- cmd.env = env
- cmd.debug = debug
- await cmd.run()
- if cmd.result["result"] != cmd.expected and cmd.result.get(
- "stdio"
- ):
- portage.writemsg(cmd.result["stdio"])
- try:
- self.assertEqual(cmd.result["result"], cmd.expected)
- except Exception:
- print(cmd.result["result"], file=sys.stderr, flush=True)
- raise
- continue
-
- proc = await asyncio.create_subprocess_exec(
- *cmd, env=env, stderr=None, stdout=stdout, cwd=abs_cwd
- )
-
- if debug:
- await proc.wait()
- else:
- output, _err = await proc.communicate()
- await proc.wait()
- if proc.returncode != os.EX_OK:
- portage.writemsg(output)
-
- self.assertEqual(
- os.EX_OK,
- proc.returncode,
- "%s failed in %s"
- % (
- cmd,
- cwd,
- ),
- )
- finally:
- playground.cleanup()
diff --git a/repoman/lib/repoman/utilities.py b/repoman/lib/repoman/utilities.py
deleted file mode 100644
index 6c541447041..00000000000
--- a/repoman/lib/repoman/utilities.py
+++ /dev/null
@@ -1,590 +0,0 @@
-# -*- coding:utf-8 -*-
-# repoman: Utilities
-# Copyright 2007-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-"""This module contains utility functions to help repoman find ebuilds to
-scan"""
-
-__all__ = [
- "editor_is_executable",
- "FindPackagesToScan",
- "FindPortdir",
- "get_commit_message_with_editor",
- "get_committer_name",
- "have_ebuild_dir",
- "have_profile_dir",
- "UpdateChangeLog",
-]
-
-import errno
-import io
-from itertools import chain
-import logging
-import pwd
-import stat
-import time
-import textwrap
-import difflib
-import tempfile
-
-# import our initialized portage instance
-from repoman._portage import portage
-
-from portage import os
-from portage import shutil
-from portage import _encodings
-from portage import _unicode_decode
-from portage import _unicode_encode
-from portage import util
-from portage.localization import _
-from portage.process import find_binary
-from portage.output import green
-
-# pylint: disable=ungrouped-imports
-from repoman.copyrights import update_copyright_year
-
-
-normalize_path = util.normalize_path
-util.initialize_logger()
-
-
-def have_profile_dir(path, maxdepth=3, filename="profiles.desc"):
- """
- Try to figure out if 'path' has a profiles/
- dir in it by checking for the given filename.
- """
- while path != "/" and maxdepth:
- if os.path.exists(os.path.join(path, "profiles", filename)):
- return normalize_path(path)
- path = normalize_path(path + "/..")
- maxdepth -= 1
-
-
-def have_ebuild_dir(path, maxdepth=3):
- """
- Try to figure out if 'path' or a subdirectory contains one or more
- ebuild files named appropriately for their parent directory.
- """
- stack = [(normalize_path(path), 1)]
- while stack:
- path, depth = stack.pop()
- basename = os.path.basename(path)
- try:
- listdir = os.listdir(path)
- except OSError:
- continue
- for filename in listdir:
- abs_filename = os.path.join(path, filename)
- try:
- st = os.stat(abs_filename)
- except OSError:
- continue
- if stat.S_ISDIR(st.st_mode):
- if depth < maxdepth:
- stack.append((abs_filename, depth + 1))
- elif stat.S_ISREG(st.st_mode):
- if filename.endswith(".ebuild") and filename.startswith(basename + "-"):
- return os.path.dirname(os.path.dirname(path))
-
-
-def FindPackagesToScan(settings, startdir, reposplit):
- """Try to find packages that need to be scanned
-
- Args:
- settings - portage.config instance, preferably repoman_settings
- startdir - directory that repoman was run in
- reposplit - root of the repository
- Returns:
- A list of directories to scan
- """
-
- def AddPackagesInDir(path):
- """Given a list of dirs, add any packages in it"""
- ret = []
- pkgdirs = os.listdir(path)
- for d in pkgdirs:
- if d == "CVS" or d.startswith("."):
- continue
- p = os.path.join(path, d)
-
- if os.path.isdir(p):
- cat_pkg_dir = os.path.join(*p.split(os.path.sep)[-2:])
- logging.debug("adding %s to scanlist" % cat_pkg_dir)
- ret.append(cat_pkg_dir)
- return ret
-
- scanlist = []
- repolevel = len(reposplit)
- if repolevel == 1: # root of the tree, startdir = repodir
- for cat in settings.categories:
- path = os.path.join(startdir, cat)
- if not os.path.isdir(path):
- continue
- scanlist.extend(AddPackagesInDir(path))
- elif repolevel == 2: # category level, startdir = catdir
- # We only want 1 segment of the directory,
- # this is why we use catdir instead of startdir.
- catdir = reposplit[-2]
- if catdir not in settings.categories:
- logging.warn(
- "%s is not a valid category according to profiles/categories, "
- "skipping checks in %s" % (catdir, catdir)
- )
- else:
- scanlist = AddPackagesInDir(catdir)
- elif repolevel == 3: # pkgdir level, startdir = pkgdir
- catdir = reposplit[-2]
- pkgdir = reposplit[-1]
- if catdir not in settings.categories:
- logging.warn(
- "%s is not a valid category according to profiles/categories, "
- "skipping checks in %s" % (catdir, catdir)
- )
- else:
- path = os.path.join(catdir, pkgdir)
- logging.debug("adding %s to scanlist" % path)
- scanlist.append(path)
- return scanlist
-
-
-def editor_is_executable(editor):
- """
- Given an EDITOR string, validate that it refers to
- an executable. This uses shlex_split() to split the
- first component and do a PATH lookup if necessary.
-
- @param editor: An EDITOR value from the environment.
- @type: string
- @rtype: bool
- @return: True if an executable is found, False otherwise.
- """
- editor_split = util.shlex_split(editor)
- if not editor_split:
- return False
- filename = editor_split[0]
- if not os.path.isabs(filename):
- return find_binary(filename) is not None
- return os.access(filename, os.X_OK) and os.path.isfile(filename)
-
-
-def get_commit_message_with_editor(editor, message=None, prefix=""):
- """
- Execute editor with a temporary file as it's argument
- and return the file content afterwards.
-
- @param editor: An EDITOR value from the environment
- @type: string
- @param message: An iterable of lines to show in the editor.
- @type: iterable
- @param prefix: Suggested prefix for the commit message summary line.
- @type: string
- @rtype: string or None
- @return: A string on success or None if an error occurs.
- """
- commitmessagedir = tempfile.mkdtemp(".repoman.msg")
- filename = os.path.join(commitmessagedir, "COMMIT_EDITMSG")
- try:
- with open(filename, "wb") as mymsg:
- mymsg.write(
- _unicode_encode(
- _(
- prefix + "\n\n# Please enter the commit message "
- "for your changes.\n# (Comment lines starting "
- "with '#' will not be included)\n"
- ),
- encoding=_encodings["content"],
- errors="backslashreplace",
- )
- )
- if message:
- mymsg.write(b"#\n")
- for line in message:
- mymsg.write(
- _unicode_encode(
- "#" + line,
- encoding=_encodings["content"],
- errors="backslashreplace",
- )
- )
- retval = os.system(editor + " '%s'" % filename)
- if not (os.WIFEXITED(retval) and os.WEXITSTATUS(retval) == os.EX_OK):
- return None
- try:
- with io.open(
- _unicode_encode(filename, encoding=_encodings["fs"], errors="strict"),
- mode="r",
- encoding=_encodings["content"],
- errors="replace",
- ) as f:
- mylines = f.readlines()
- except OSError as e:
- if e.errno != errno.ENOENT:
- raise
- del e
- return None
- return "".join(line for line in mylines if not line.startswith("#"))
- finally:
- try:
- shutil.rmtree(commitmessagedir)
- except OSError:
- pass
-
-
-def FindPortdir(settings):
- """Try to figure out what repo we are in and whether we are in a regular
- tree or an overlay.
-
- Basic logic is:
-
- 1. Determine what directory we are in (supports symlinks).
- 2. Build a list of directories from / to our current location
- 3. Iterate over PORTDIR_OVERLAY, if we find a match,
- search for a profiles directory in the overlay. If it has one,
- make it portdir, otherwise make it portdir_overlay.
- 4. If we didn't find an overlay in PORTDIR_OVERLAY,
- see if we are in PORTDIR; if so, set portdir_overlay to PORTDIR.
- If we aren't in PORTDIR, see if PWD has a profiles dir, if so,
- set portdir_overlay and portdir to PWD, else make them False.
- 5. If we haven't found portdir_overlay yet,
- it means the user is doing something odd, report an error.
- 6. If we haven't found a portdir yet, set portdir to PORTDIR.
-
- Args:
- settings - portage.config instance, preferably repoman_settings
- Returns:
- list(portdir, portdir_overlay, location)
- """
-
- portdir = None
- portdir_overlay = None
- location = os.getcwd()
- pwd = _unicode_decode(os.environ.get("PWD", ""), encoding=_encodings["fs"])
- if pwd and pwd != location and os.path.realpath(pwd) == location:
- # getcwd() returns the canonical path but that makes it hard for repoman to
- # orient itself if the user has symlinks in their repository structure.
- # We use os.environ["PWD"], if available, to get the non-canonical path of
- # the current working directory (from the shell).
- location = pwd
-
- location = normalize_path(location)
-
- path_ids = {}
- p = location
- s = None
- while True:
- s = os.stat(p)
- path_ids[(s.st_dev, s.st_ino)] = p
- if p == "/":
- break
- p = os.path.dirname(p)
- if location[-1] != "/":
- location += "/"
-
- for overlay in portage.util.shlex_split(settings["PORTDIR_OVERLAY"]):
- overlay = os.path.realpath(overlay)
- try:
- s = os.stat(overlay)
- except OSError:
- continue
- overlay = path_ids.get((s.st_dev, s.st_ino))
- if overlay is None:
- continue
- if overlay[-1] != "/":
- overlay += "/"
- if True:
- portdir_overlay = overlay
- subdir = location[len(overlay) :]
- if subdir and subdir[-1] != "/":
- subdir += "/"
- if have_profile_dir(location, subdir.count("/")):
- portdir = portdir_overlay
- break
-
- # Couldn't match location with anything from PORTDIR_OVERLAY,
- # so fall back to have_profile_dir() checks alone. Assume that
- # an overlay will contain at least a "repo_name" file while a
- # master repo (portdir) will contain at least a "profiles.desc"
- # file.
- if not portdir_overlay:
- portdir_overlay = have_profile_dir(location, filename="repo_name")
- if not portdir_overlay:
- portdir_overlay = have_ebuild_dir(location)
- if portdir_overlay:
- subdir = location[len(portdir_overlay) :]
- if subdir and subdir[-1] != os.sep:
- subdir += os.sep
- if have_profile_dir(location, subdir.count(os.sep)):
- portdir = portdir_overlay
-
- if not portdir_overlay:
- if (settings["PORTDIR"] + os.path.sep).startswith(location):
- portdir_overlay = settings["PORTDIR"]
- else:
- portdir_overlay = have_profile_dir(location)
- portdir = portdir_overlay
-
- if not portdir_overlay:
- msg = (
- "Repoman is unable to determine PORTDIR or PORTDIR_OVERLAY"
- + " from the current working directory"
- )
- logging.critical(msg)
- return (None, None, None)
-
- if not portdir:
- portdir = settings["PORTDIR"]
-
- if not portdir_overlay.endswith("/"):
- portdir_overlay += "/"
-
- if not portdir.endswith("/"):
- portdir += "/"
-
- return [normalize_path(x) for x in (portdir, portdir_overlay, location)]
-
-
-def get_committer_name(env=None):
- """Generate a committer string like echangelog does."""
- if env is None:
- env = os.environ
- if "GENTOO_COMMITTER_NAME" in env and "GENTOO_COMMITTER_EMAIL" in env:
- user = "%s <%s>" % (env["GENTOO_COMMITTER_NAME"], env["GENTOO_COMMITTER_EMAIL"])
- elif "GENTOO_AUTHOR_NAME" in env and "GENTOO_AUTHOR_EMAIL" in env:
- user = "%s <%s>" % (env["GENTOO_AUTHOR_NAME"], env["GENTOO_AUTHOR_EMAIL"])
- elif "ECHANGELOG_USER" in env:
- user = env["ECHANGELOG_USER"]
- else:
- pwd_struct = pwd.getpwuid(os.getuid())
- gecos = pwd_struct.pw_gecos.split(",")[0] # bug #80011
- user = "%s <%s@gentoo.org>" % (gecos, pwd_struct.pw_name)
- return user
-
-
-def UpdateChangeLog(
- pkgdir,
- user,
- msg,
- skel_path,
- category,
- package,
- new=(),
- removed=(),
- changed=(),
- pretend=False,
- quiet=False,
-):
- """
- Write an entry to an existing ChangeLog, or create a new one.
- Updates copyright year on changed files, and updates the header of
- ChangeLog with the contents of skel.ChangeLog.
- """
-
- if "<root@" in user:
- if not quiet:
- logging.critical("Please set ECHANGELOG_USER or run as non-root")
- return None
-
- # ChangeLog times are in UTC
- gmtime = time.gmtime()
- year = time.strftime("%Y", gmtime)
- date = time.strftime("%d %b %Y", gmtime)
-
- cl_path = os.path.join(pkgdir, "ChangeLog")
- clold_lines = []
- clnew_lines = []
- old_header_lines = []
- header_lines = []
-
- clold_file = None
- try:
- clold_file = io.open(
- _unicode_encode(cl_path, encoding=_encodings["fs"], errors="strict"),
- mode="r",
- encoding=_encodings["repo.content"],
- errors="replace",
- )
- except EnvironmentError:
- pass
-
- f, clnew_path = tempfile.mkstemp()
-
- # construct correct header first
- try:
- if clold_file is not None:
- # retain header from old ChangeLog
- first_line = True
- for line in clold_file:
- line_strip = line.strip()
- if line_strip and line[:1] != "#":
- clold_lines.append(line)
- break
- # always make sure cat/pkg is up-to-date in case we are
- # moving packages around, or copied from another pkg, or ...
- if first_line:
- if line.startswith("# ChangeLog for"):
- line = "# ChangeLog for %s/%s\n" % (category, package)
- first_line = False
- old_header_lines.append(line)
- header_lines.append(update_copyright_year(year, line))
- if not line_strip:
- break
-
- clskel_file = None
- if not header_lines:
- # delay opening this until we find we need a header
- try:
- clskel_file = io.open(
- _unicode_encode(
- skel_path, encoding=_encodings["fs"], errors="strict"
- ),
- mode="r",
- encoding=_encodings["repo.content"],
- errors="replace",
- )
- except EnvironmentError:
- pass
-
- if clskel_file is not None:
- # read skel.ChangeLog up to first empty line
- for line in clskel_file:
- line_strip = line.strip()
- if not line_strip:
- break
- line = line.replace("<CATEGORY>", category)
- line = line.replace("<PACKAGE_NAME>", package)
- line = update_copyright_year(year, line)
- header_lines.append(line)
- header_lines.append("\n")
- clskel_file.close()
-
- # write new ChangeLog entry
- clnew_lines.extend(header_lines)
- newebuild = False
- for fn in new:
- if not fn.endswith(".ebuild"):
- continue
- ebuild = fn.split(os.sep)[-1][0:-7]
- clnew_lines.append("*%s (%s)\n" % (ebuild, date))
- newebuild = True
- if newebuild:
- clnew_lines.append("\n")
- trivial_files = ("ChangeLog", "Manifest")
- display_new = ["+" + elem for elem in new if elem not in trivial_files]
- display_removed = ["-" + elem for elem in removed]
- display_changed = [elem for elem in changed if elem not in trivial_files]
- if not (display_new or display_removed or display_changed):
- # If there's nothing else to display, show one of the
- # trivial files.
- for fn in trivial_files:
- if fn in new:
- display_new = ["+" + fn]
- break
- elif fn in changed:
- display_changed = [fn]
- break
-
- display_new.sort()
- display_removed.sort()
- display_changed.sort()
-
- mesg = "%s; %s %s:" % (
- date,
- user,
- ", ".join(chain(display_new, display_removed, display_changed)),
- )
- for line in textwrap.wrap(
- mesg,
- 80,
- initial_indent=" ",
- subsequent_indent=" ",
- break_on_hyphens=False,
- ):
- clnew_lines.append("%s\n" % line)
- for line in textwrap.wrap(msg, 80, initial_indent=" ", subsequent_indent=" "):
- clnew_lines.append("%s\n" % line)
- # Don't append a trailing newline if the file is new.
- if clold_file is not None:
- clnew_lines.append("\n")
-
- f = io.open(
- f, mode="w", encoding=_encodings["repo.content"], errors="backslashreplace"
- )
-
- for line in clnew_lines:
- f.write(line)
-
- # append stuff from old ChangeLog
- if clold_file is not None:
-
- if clold_lines:
- # clold_lines may contain a saved non-header line
- # that we want to write first.
- # Also, append this line to clnew_lines so that the
- # unified_diff call doesn't show it as removed.
- for line in clold_lines:
- f.write(line)
- clnew_lines.append(line)
-
- else:
- # ensure that there is no more than one blank
- # line after our new entry
- for line in clold_file:
- if line.strip():
- f.write(line)
- break
-
- # Now prepend old_header_lines to clold_lines, for use
- # in the unified_diff call below.
- clold_lines = old_header_lines + clold_lines
-
- # Trim any trailing newlines.
- lines = clold_file.readlines()
- clold_file.close()
- while lines and lines[-1] == "\n":
- del lines[-1]
- f.writelines(lines)
- f.close()
-
- # show diff
- if not quiet:
- for line in difflib.unified_diff(
- clold_lines, clnew_lines, fromfile=cl_path, tofile=cl_path, n=0
- ):
- util.writemsg_stdout(line, noiselevel=-1)
- util.writemsg_stdout("\n", noiselevel=-1)
-
- if pretend:
- # remove what we've done
- os.remove(clnew_path)
- else:
- # rename to ChangeLog, and set permissions
- try:
- clold_stat = os.stat(cl_path)
- except OSError:
- clold_stat = None
-
- shutil.move(clnew_path, cl_path)
-
- if clold_stat is None:
- util.apply_permissions(cl_path, mode=0o644)
- else:
- util.apply_stat_permissions(cl_path, clold_stat)
-
- if clold_file is None:
- return True
- else:
- return False
- except IOError as e:
- err = "Repoman is unable to create/write to Changelog.new file: %s" % (e,)
- logging.critical(err)
- # try to remove if possible
- try:
- os.remove(clnew_path)
- except OSError:
- pass
- return None
-
-
-def repoman_sez(msg):
- print(green("RepoMan sez:"), msg)
diff --git a/repoman/man/repoman.1 b/repoman/man/repoman.1
deleted file mode 100644
index 5dbc41560e0..00000000000
--- a/repoman/man/repoman.1
+++ /dev/null
@@ -1,478 +0,0 @@
-.TH "REPOMAN" "1" "March 2021" "Repoman VERSION" "Repoman"
-.SH NAME
-repoman \- Gentoo's program to enforce a minimal level of quality assurance in
-packages added to the ebuild repository
-.SH SYNOPSIS
-\fBrepoman\fR [\fIoption\fR] [\fImode\fR]
-.SH DESCRIPTION
-.BR "Quality is job zero."
-
-.BR repoman
-checks the quality of ebuild repositories.
-
-Note: \fBrepoman commit\fR only works \fIinside local\fR cvs, git, or
-subversion repositories.
-
-Note: Messages pertaining to specific lines may be inaccurate in the
-prescence of continuation lines from use of the \fI\\\fR character in
-BASH.
-.SH OPTIONS
-.TP
-\fB-a\fR, \fB--ask\fR
-Request a confirmation before commiting
-.TP
-\fB-b\fR, \fB--bug\fR
-Include a bug reference in the commit message footer. The argument can
-be either a Gentoo bug number or a full bug URL (either Gentoo
-or upstream). Gentoo bug URLs are automatically shortened to
-the canonical \fBhttps://bugs.gentoo.org/NNNNNN\fR form, and HTTPS
-is forced for known bug trackers.
-
-When pushing to the Gentoo repository, the reference to the commit
-will be automatically added as a comment on the bug.
-.TP
-\fB-c\fR, \fB--closes\fR
-Include a \fBCloses\fR tag in the commit message footer that can be used
-to close bugs and pull requests. The argument can be either a Gentoo bug
-number or a full PR/bug URL. Gentoo bug URLs are automatically shortened
-to the canonical \fBhttps://bugs.gentoo.org/NNNNNN\fR form, and HTTPS
-is forced for known bug trackers.
-
-When pushing to the Gentoo repository, the referenced bugs will be
-closed as RESOLVED/FIXED automatically with a comment referencing
-the commit. Furthermore, GitHub pull requests will be closed as well
-due to the automatic GitHub mirroring.
-
-Other platforms using the \fBCloses\fR tag include GitLab and Bitbucket.
-.TP
-\fB\-\-digest=<y|n>\fR
-Automatically update Manifest digests for modified files. This
-option triggers a behavior that is very similar to that enabled
-by FEATURES="digest" in \fBmake.conf\fR(5). In order to enable
-this behavior by default for repoman alone, add
-\fB\-\-digest=y\fR to the \fIREPOMAN_DEFAULT_OPTS\fR variable in
-\fBmake.conf\fR(5). The \fBmanifest\-check\fR mode will
-automatically ignore the \-\-digest option.
-
-\fBNOTE:\fR
-This option does not trigger update of digests for Manifest DIST
-entries that already exist. Replacement of existing Manifest
-DIST entries can be forced by using the \fBmanifest\fR mode
-together with the \fB\-\-force\fR option.
-.TP
-\fB-f\fR, \fB--force\fR
-Force commit to proceed, regardless of QA issues. For convenience, this option
-causes the most time consuming QA checks to be skipped. The commit message will
-include an indication that this option has been enabled, together with the
-usual portage version stamp.
-
-When used together with \fBmanifest\fR mode, \fB--force\fR causes existing
-digests to be replaced for any files that exist in ${DISTDIR}.
-Existing digests are assumed to be correct for files that would otherwise
-have to be downloaded in order to recompute digests. \fBWARNING:\fR When
-replacing existing digests, it is the user's responsibility to ensure that
-files contained in ${DISTDIR} have the correct identities. Especially beware
-of partially downloaded files.
-.TP
-\fB-S\fR, \fB--straight-to-stable\fR
-Allow committing straight to stable
-.TP
-\fB-q\fR, \fB--quiet\fR
-Be less verbose about extraneous info
-.TP
-\fB-p\fR, \fB--pretend\fR
-Don't commit or fix anything; just show what would be done
-.TP
-\fB\-j\fR, \fB\-\-jobs\fR
-Specifies the number of jobs (processes) to run simultaneously.
-.TP
-\fB\-l\fR, \fB\-\-load-average\fR
-Specifies that no new jobs (processes) should be started if there are others
-jobs running and the load average is at least load (a floating\-point number).
-.TP
-\fB-x\fR, \fB--xmlparse\fR
-Forces the metadata.xml parse check to be carried out
-.TP
-\fB-v\fR, \fB--verbose\fR
-Displays every package name while checking
-.TP
-\fB\-\-echangelog=<y|n|force>\fR
-For commit mode, call echangelog if ChangeLog is unmodified (or
-regardless of modification if 'force' is specified). This option
-can be enabled by default for a particular repository by setting
-"update\-changelog = true" in metadata/layout.conf (see
-\fBportage\fR(5)).
-.TP
-\fB\-\-experimental\-inherit=<y|n>\fR
-Enable experimental inherit.missing checks which may misbehave when the
-internal eclass database becomes outdated.
-.TP
-\fB\-\-experimental\-repository\-modules=<y|n>\fR
-Enable experimental repository modules:
-\fIhttps://wiki.gentoo.org/wiki/Project:Portage/Repoman-Module-specs\fR
-.TP
-\fB\-\-if\-modified=<y|n>\fR
-Only check packages that have uncommitted modifications
-.TP
-\fB\-i\fR, \fB\-\-ignore\-arches\fR
-Ignore arch-specific failures (where arch != host)
-.TP
-\fB\-\-ignore\-default\-opts\fR
-Do not use the \fIREPOMAN_DEFAULT_OPTS\fR environment variable.
-.TP
-\fB\-I\fR, \fB\-\-ignore\-masked\fR
-Ignore masked packages (not allowed with commit mode)
-.TP
-.BR "\-\-include\-arches " ARCHES
-A space separated list of arches used to filter the selection of
-profiles for dependency checks.
-.TP
-.BR "\-\-include\-profiles " PROFILES
-A space separated list of profiles used to
-define the selection of profiles for dependency checks.
-.TP
-\fB\-d\fR, \fB\-\-include\-dev\fR
-Include dev profiles in dependency checks.
-.TP
-\fB\-e <y|n>\fR, \fB\-\-include\-exp\-profiles=<y|n>\fR
-Include exp profiles in dependency checks.
-.TP
-\fB\-\-unmatched\-removal\fR
-Enable strict checking of package.mask and package.unmask files for
-unmatched removal atoms.
-.TP
-\fB\-\-without\-mask\fR
-Behave as if no package.mask entries exist (not allowed with commit mode)
-.TP
-\fB-m\fR, \fB--commitmsg\fR
-Adds a commit message via the command line
-.TP
-\fB-M\fR, \fB--commitmsgfile\fR
-Adds a commit message from the specified file. This option also will perform
-an automatic text substitution of a leading "cat/pkg: " string (upper or lower
-case) with the actual category/package prefix as defined by the required message
-format. Use this option for templating a common commit message for multiple
-package updates.
-.TP
-\fB-V\fR, \fB--version\fR
-Show version info
-.TP
-\fB-h\fR, \fB--help\fR
-Show this screen
-.SH MODES
-.TP
-.B full
-Scan directory tree for QA issues (full listing)
-.TP
-.B help
-Show this screen
-.TP
-.B scan
-Scan directory tree for QA issues (short listing)
-.TP
-.B fix
-Fix simple QA issues (stray digests, missing digests)
-.TP
-.B manifest
-Generate a Manifest (fetches distfiles if necessary). See the \fB\-\-force\fR
-option if you would like to replace existing distfiles digests.
-.TP
-.B manifest-check
-Check Manifests for missing or incorrect digests
-.TP
-.B commit
-Scan directory tree for QA issues; if OK, commit via VCS
-.TP
-.B ci
-Synonym for commit
-.SH QA KEYWORDS
-.TP
-.B CVS/Entries.IO_error
-Attempting to commit, and an IO error was encountered access the Entries file
-.TP
-.B DESCRIPTION.missing
-Ebuilds that have a missing or empty DESCRIPTION variable
-.TP
-.B EAPI.definition
-EAPI definition does not conform to PMS section 7.3.1 (first
-non\-comment, non\-blank line). See bug #402167.
-.TP
-.B EAPI.deprecated
-Ebuilds that use features that are deprecated in the current EAPI
-.TP
-.B EAPI.incompatible
-Ebuilds that use features that are only available with a different EAPI
-.TP
-.B EAPI.unsupported
-Ebuilds that have an unsupported EAPI version (you must upgrade portage)
-.TP
-.B HOMEPAGE.missing
-Ebuilds that have a missing or empty HOMEPAGE variable
-.TP
-.B HOMEPAGE.missingurischeme
-HOMEPAGE is missing an URI scheme
-.TP
-.B HOMEPAGE.virtual
-Virtuals that have a non-empty HOMEPAGE variable
-.TP
-.B IUSE.invalid
-This ebuild has a variable in IUSE that is not in the use.desc or its
-metadata.xml file
-.TP
-.B IUSE.missing
-This ebuild has a USE conditional which references a flag that is not listed in
-IUSE
-.TP
-.B KEYWORDS.dropped
-Ebuilds that appear to have dropped KEYWORDS for some arch
-.TP
-.B KEYWORDS.invalid
-This ebuild contains KEYWORDS that are not listed in profiles/arch.list or for
-which no valid profile was found
-.TP
-.B KEYWORDS.missing
-Ebuilds that have a missing or empty KEYWORDS variable
-.TP
-.B KEYWORDS.stable
-Ebuilds that have been added directly with stable KEYWORDS
-.TP
-.B KEYWORDS.stupid
-Ebuilds that use KEYWORDS=-* instead of package.mask
-.TP
-.B KEYWORDS.unsorted
-Ebuilds that contain KEYWORDS which are not sorted alphabetically.
-.TP
-.B LICENSE.deprecated
-This ebuild is listing a deprecated license.
-.TP
-.B LICENSE.invalid
-This ebuild is listing a license that doesnt exist in portages license/ dir.
-.TP
-.B LICENSE.missing
-Ebuilds that have a missing or empty LICENSE variable
-.TP
-.B LICENSE.syntax
-Syntax error in LICENSE (usually an extra/missing space/parenthesis)
-.TP
-.B LICENSE.virtual
-Virtuals that have a non-empty LICENSE variable
-.TP
-.B LIVEVCS.stable
-Ebuild is a live ebuild (cvs, git, darcs, svn, etc) checkout with stable
-keywords.
-.TP
-.B LIVEVCS.unmasked
-Ebuild is a live ebuild (cvs, git, darcs, svn, etc) checkout but has keywords
-and is not masked in the global package.mask.
-.TP
-.B PDEPEND.suspect
-PDEPEND contains a package that usually only belongs in DEPEND
-.TP
-.B RDEPEND.implicit
-RDEPEND is unset in the ebuild which triggers implicit RDEPEND=$DEPEND
-assignment (prior to EAPI 4)
-.TP
-.B RDEPEND.suspect
-RDEPEND contains a package that usually only belongs in DEPEND
-.TP
-.B PROPERTIES.syntax
-Syntax error in PROPERTIES (usually an extra/missing space/parenthesis)
-.TP
-.B RESTRICT.syntax
-Syntax error in RESTRICT (usually an extra/missing space/parenthesis)
-.B SLOT.invalid
-Ebuilds that have a missing or invalid SLOT variable value
-.TP
-.B SRC_URI.mirror
-A uri listed in profiles/thirdpartymirrors is found in SRC_URI
-.TP
-.B changelog.ebuildadded
-An ebuild was added but the ChangeLog was not modified
-.TP
-.B changelog.missing
-Missing ChangeLog files
-.TP
-.B changelog.notadded
-ChangeLogs that exist but have not been added to the vcs
-.TP
-.B dependency.bad
-User-visible ebuilds with unsatisfied dependencies (matched against *visible*
-ebuilds)
-.TP
-.B dependency.badindev
-User-visible ebuilds with unsatisfied dependencies (matched against *visible*
-ebuilds) in developing arch
-.TP
-.B dependency.badinexp
-User-visible ebuilds with unsatisfied dependencies (matched against *visible*
-ebuilds) in experimental arch
-.TP
-.B dependency.badmasked
-Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds)
-.TP
-.B dependency.badmaskedindev
-Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds) in
-developing arch
-.TP
-.B dependency.badmaskedinexp
-Masked ebuilds with unsatisfied dependencies (matched against *all* ebuilds) in
-experimental arch
-.TP
-.B dependency.badtilde
-Uses the ~ dep operator with a non-zero revision part, which is useless (the
-revision is ignored)
-.TP
-.B dependency.deprecated
-Ebuild has a dependency that refers to a deprecated package
-.TP
-.B dependency.syntax
-Syntax error in dependency string (usually an extra/missing space/parenthesis)
-.TP
-.B dependency.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)
-.TP
-.B digest.assumed
-Existing digest must be assumed correct (Package level only)
-.TP
-.B digest.missing
-Some files listed in SRC_URI aren't referenced in the Manifest
-.TP
-.B digest.unused
-Some files listed in the Manifest aren't referenced in SRC_URI
-.TP
-.B ebuild.absdosym
-Ebuild uses 'dosym' with explicit absolute path where relative path
-could be used
-.TP
-.B ebuild.badheader
-This ebuild has a malformed header
-.TP
-.B ebuild.invalidname
-Ebuild files with a non-parseable or syntactically incorrect name (or using 2.1
-versioning extensions)
-.TP
-.B ebuild.majorsyn
-This ebuild has a major syntax error that may cause the ebuild to fail
-partially or fully
-.TP
-.B ebuild.minorsyn
-This ebuild has a minor syntax error that contravenes gentoo coding style
-.TP
-.B ebuild.namenomatch
-Ebuild files that do not have the same name as their parent directory
-.TP
-.B ebuild.nesteddie
-Placing 'die' inside ( ) prints an error, but doesn't stop the ebuild.
-.TP
-.B ebuild.notadded
-Ebuilds that exist but have not been added to the vcs
-.TP
-.B ebuild.output
-A simple sourcing of the ebuild produces output; this breaks ebuild policy.
-.TP
-.B ebuild.patches
-PATCHES variable should be a bash array to ensure white space safety
-.TP
-.B ebuild.syntax
-Error generating cache entry for ebuild; typically caused by ebuild syntax
-error or digest verification failure.
-.TP
-.B file.UTF8
-File is not UTF8 compliant
-.TP
-.B file.empty
-Empty file in the files directory
-.TP
-.B file.executable
-Ebuilds, digests, metadata.xml, Manifest, and ChangeLog do not need the
-executable bit
-.TP
-.B file.name
-File/dir name must be composed of only the following chars: a-zA-Z0-9._-+:
-.TP
-.B file.size
-Files in the files directory must be under 20 KiB
-.TP
-.B inherit.missing
-Ebuild uses functions from an eclass but does not inherit it
-.TP
-.B inherit.unused
-Ebuild inherits an eclass but does not use it
-.TP
-.B inherit.deprecated
-Ebuild inherits a deprecated eclass
-.TP
-.B java.eclassesnotused
-With virtual/jdk in DEPEND you must inherit a java eclass. Refer to
-\fIhttps://wiki.gentoo.org/wiki/Project:Java\fR for more information.
-.TP
-.B manifest.bad
-Manifest has missing or incorrect digests
-.TP
-.B metadata.bad
-Bad metadata.xml files
-.TP
-.B metadata.missing
-Missing metadata.xml files
-.TP
-.B metadata.warning
-Warnings in metadata.xml files
-.TP
-.B repo.eapi.banned
-The ebuild uses an EAPI which is banned by the repository's
-metadata/layout.conf settings.
-.TP
-.B repo.eapi.deprecated
-The ebuild uses an EAPI which is deprecated by the repository's
-metadata/layout.conf settings.
-.TP
-.B IUSE.rubydeprecated
-The ebuild has set a ruby interpreter in USE_RUBY, that is not available as a ruby target anymore
-.TP
-.B portage.internal
-The ebuild uses an internal Portage function or variable
-.TP
-.B upstream.workaround
-The ebuild works around an upstream bug, an upstream bug should be filed and
-tracked in bugs.gentoo.org
-.TP
-.B usage.obsolete
-The ebuild makes use of an obsolete construct
-.TP
-.B variable.invalidchar
-A variable contains an invalid character that is not part of the ASCII
-character set.
-.TP
-.B variable.phase
-Variable referenced found within scope of incorrect ebuild phase as specified by PMS.
-.TP
-.B variable.readonly
-Assigning a readonly variable
-.TP
-.B variable.usedwithhelpers
-Ebuild uses D, ROOT, BROOT, ED, EROOT or EPREFIX with helpers
-.TP
-.B virtual.suspect
-Ebuild contains a package that usually should be pulled via virtual/,
-not directly.
-.TP
-.B wxwidgets.eclassnotused
-Ebuild DEPENDs on x11-libs/wxGTK without inheriting wxwidgets.eclass. Refer to
-bug #305469 for more information.
-.SH "BEHAVIOR"
-When invoked from a level higher than a package directory, \fBrepoman\fR
-will recurse through a directory tree and execute the given command
-on a per\-package basis, e.g. \fBrepoman manifest\fR at the root of
-the repository will generate manifests for every package within the
-repository.
-.SH "REPORTING BUGS"
-Please report bugs via https://bugs.gentoo.org/
-.SH AUTHORS
-.nf
-Daniel Robbins <drobbins@gentoo.org>
-Saleem Abdulrasool <compnerd@gentoo.org>
-.fi
-.SH "SEE ALSO"
-.BR emerge (1)
diff --git a/repoman/runtests b/repoman/runtests
deleted file mode 100755
index f02bfe87555..00000000000
--- a/repoman/runtests
+++ /dev/null
@@ -1,189 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2010-2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-#
-# Note: We don't want to import portage modules directly because we do things
-# like run the testsuite through multiple versions of python.
-
-"""Helper script to run portage unittests against different python versions.
-
-Note: Any additional arguments will be passed down directly to the underlying
-unittest runner. This lets you select specific tests to execute.
-"""
-
-import argparse
-import os
-import shutil
-import subprocess
-import sys
-import tempfile
-
-
-# These are the versions we fully support and require to pass tests.
-PYTHON_SUPPORTED_VERSIONS = ["2.7", "3.6", "3.7", "3.8", "3.9"]
-# The rest are just "nice to have".
-PYTHON_NICE_VERSIONS = ["pypy3", "3.10"]
-
-EPREFIX = os.environ.get("PORTAGE_OVERRIDE_EPREFIX", "/")
-
-
-class Colors(object):
- """Simple object holding color constants."""
-
- _COLORS_YES = ("y", "yes", "true")
- _COLORS_NO = ("n", "no", "false")
-
- WARN = GOOD = BAD = NORMAL = ""
-
- def __init__(self, colorize=None):
- if colorize is None:
- nocolors = os.environ.get("NOCOLOR", "false")
- # Ugh, look away, for here we invert the world!
- if nocolors in self._COLORS_YES:
- colorize = False
- elif nocolors in self._COLORS_NO:
- colorize = True
- else:
- raise ValueError("$NOCOLORS is invalid: %s" % nocolors)
- else:
- if colorize in self._COLORS_YES:
- colorize = True
- elif colorize in self._COLORS_NO:
- colorize = False
- else:
- raise ValueError("--colors is invalid: %s" % colorize)
-
- if colorize:
- self.WARN = "\033[1;33m"
- self.GOOD = "\033[1;32m"
- self.BAD = "\033[1;31m"
- self.NORMAL = "\033[0m"
-
-
-def get_python_executable(ver):
- """Find the right python executable for |ver|"""
- if ver in ("pypy", "pypy3"):
- prog = ver
- else:
- prog = "python" + ver
- return os.path.join(EPREFIX, "usr", "bin", prog)
-
-
-def get_parser():
- """Return a argument parser for this module"""
- epilog = """Examples:
-List all the available unittests.
-$ %(prog)s --list
-
-Run against specific versions of python.
-$ %(prog)s --python-versions '2.7 3.3'
-
-Run just one unittest.
-$ %(prog)s lib/portage/tests/xpak/test_decodeint.py
-"""
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- epilog=epilog,
- )
- parser.add_argument(
- "--keep-temp",
- default=False,
- action="store_true",
- help="Do not delete the temporary directory when exiting",
- )
- parser.add_argument(
- "--color",
- type=str,
- default=None,
- help="Whether to use colorized output (default is auto)",
- )
- parser.add_argument(
- "--python-versions",
- action="append",
- help="Versions of python to test (default is test available)",
- )
- return parser
-
-
-def main(argv):
- parser = get_parser()
- opts, args = parser.parse_known_args(argv)
- colors = Colors(colorize=opts.color)
-
- # Figure out all the versions we want to test.
- if opts.python_versions is None:
- ignore_missing = True
- pyversions = PYTHON_SUPPORTED_VERSIONS + PYTHON_NICE_VERSIONS
- else:
- ignore_missing = False
- pyversions = []
- for ver in opts.python_versions:
- if ver == "supported":
- pyversions.extend(PYTHON_SUPPORTED_VERSIONS)
- else:
- pyversions.extend(ver.split())
-
- here = os.path.dirname(__file__)
- run_path = os.path.join(here, "lib/repoman/tests/runTests.py")
- tempdir = None
- try:
- # Set up a single tempdir for all the tests to use.
- # This way we know the tests won't leak things on us.
- tempdir = tempfile.mkdtemp(prefix="repoman.runtests.")
- os.environ["TMPDIR"] = tempdir
-
- # Actually test those versions now.
- statuses = []
- for ver in pyversions:
- prog = get_python_executable(ver)
- cmd = [prog, "-b", "-Wd", run_path] + args
- if os.access(prog, os.X_OK):
- print(
- "%sTesting with Python %s...%s" % (colors.GOOD, ver, colors.NORMAL)
- )
- statuses.append((ver, subprocess.call(cmd)))
- elif not ignore_missing:
- print(
- "%sCould not find requested Python %s%s"
- % (colors.BAD, ver, colors.NORMAL)
- )
- statuses.append((ver, 1))
- else:
- print("%sSkip Python %s...%s" % (colors.WARN, ver, colors.NORMAL))
- print()
- finally:
- if tempdir is not None:
- if opts.keep_temp:
- print("Temporary directory left behind:\n%s" % tempdir)
- else:
- # Nuke our tempdir and anything that might be under it.
- shutil.rmtree(tempdir, True)
-
- # Then summarize it all.
- print("\nSummary:\n")
- width = 10
- header = "| %-*s | %s" % (width, "Version", "Status")
- print("%s\n|%s" % (header, "-" * (len(header) - 1)))
- exit_status = 0
- for ver, status in statuses:
- exit_status += status
- if status:
- color = colors.BAD
- msg = "FAIL"
- else:
- color = colors.GOOD
- msg = "PASS"
- print(
- "| %s%-*s%s | %s%s%s"
- % (color, width, ver, colors.NORMAL, color, msg, colors.NORMAL)
- )
- exit(exit_status)
-
-
-if __name__ == "__main__":
- try:
- main(sys.argv[1:])
- except KeyboardInterrupt:
- print("interrupted ...", file=sys.stderr)
- exit(1)
diff --git a/repoman/setup.py b/repoman/setup.py
deleted file mode 100755
index 8231c8f7587..00000000000
--- a/repoman/setup.py
+++ /dev/null
@@ -1,523 +0,0 @@
-#!/usr/bin/env python
-# Copyright 1998-2021 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-try:
- from setuptools.core import setup, Command
- from setuptools.command.build import build
- from setuptools.command.build_scripts import build_scripts
- from setuptools.command.clean import clean
- from setuptools.command.install import install
- from setuptools.command.install_data import install_data
- from setuptools.command.install_lib import install_lib
- from setuptools.command.install_scripts import install_scripts
- from setuptools.command.sdist import sdist
- from setuptools.dep_util import newer
- from setuptools.dir_util import mkpath, remove_tree, copy_tree
- from setuptools.util import change_root, subst_vars
-except ImportError:
- from distutils.core import setup, Command
- from distutils.command.build import build
- from distutils.command.build_scripts import build_scripts
- from distutils.command.clean import clean
- from distutils.command.install import install
- from distutils.command.install_data import install_data
- from distutils.command.install_lib import install_lib
- from distutils.command.install_scripts import install_scripts
- from distutils.command.sdist import sdist
- from distutils.dep_util import newer
- from distutils.dir_util import mkpath, remove_tree, copy_tree
- from distutils.util import change_root, subst_vars
-
-import codecs
-import collections
-import os
-import os.path
-import re
-import subprocess
-import sys
-
-# change the cwd to this one
-os.chdir(os.path.dirname(os.path.realpath(__file__)))
-
-# TODO:
-# - smarter rebuilds of docs w/ 'install_docbook' and 'install_epydoc'.
-
-x_scripts = {
- "bin": [
- "bin/repoman",
- ],
-}
-
-
-class x_build(build):
- """Build command with extra build_man call."""
-
- def run(self):
- build.run(self)
- self.run_command("build_man")
-
-
-class build_man(Command):
- """Perform substitutions in manpages."""
-
- user_options = []
-
- def initialize_options(self):
- self.build_base = None
-
- def finalize_options(self):
- self.set_undefined_options("build", ("build_base", "build_base"))
-
- def run(self):
- for d, files in self.distribution.data_files:
- if not d.startswith("$mandir/"):
- continue
-
- for source in files:
- target = os.path.join(self.build_base, source)
- mkpath(os.path.dirname(target))
-
- if not newer(source, target) and not newer(__file__, target):
- continue
-
- print("copying and updating %s -> %s" % (source, target))
-
- with codecs.open(source, "r", "utf8") as f:
- data = f.readlines()
- data[0] = data[0].replace("VERSION", self.distribution.get_version())
- with codecs.open(target, "w", "utf8") as f:
- f.writelines(data)
-
-
-class x_build_scripts_custom(build_scripts):
- def finalize_options(self):
- build_scripts.finalize_options(self)
- if "dir_name" in dir(self):
- self.build_dir = os.path.join(self.build_dir, self.dir_name)
- if self.dir_name in x_scripts:
- self.scripts = x_scripts[self.dir_name]
- else:
- self.scripts = set(self.scripts)
- for other_files in x_scripts.values():
- self.scripts.difference_update(other_files)
-
- def run(self):
- # group scripts by subdirectory
- split_scripts = collections.defaultdict(list)
- for f in self.scripts:
- dir_name = os.path.dirname(f[len("bin/") :])
- split_scripts[dir_name].append(f)
-
- base_dir = self.build_dir
- base_scripts = self.scripts
- for d, files in split_scripts.items():
- self.build_dir = os.path.join(base_dir, d)
- self.scripts = files
- self.copy_scripts()
-
- # restore previous values
- self.build_dir = base_dir
- self.scripts = base_scripts
-
-
-class x_build_scripts_bin(x_build_scripts_custom):
- dir_name = "bin"
-
-
-class x_build_scripts(build_scripts):
- def initialize_option(self):
- build_scripts.initialize_options(self)
-
- def finalize_options(self):
- build_scripts.finalize_options(self)
-
- def run(self):
- self.run_command("build_scripts_bin")
-
-
-class x_clean(clean):
- """clean extended for doc & post-test cleaning"""
-
- def clean_tests(self):
- # do not remove incorrect dirs accidentally
- top_dir = os.path.normpath(os.path.join(self.build_lib, ".."))
- cprefix = os.path.commonprefix((self.build_base, top_dir))
- if cprefix != self.build_base:
- return
-
- bin_dir = os.path.join(top_dir, "bin")
- if os.path.exists(bin_dir):
- remove_tree(bin_dir)
-
- conf_dir = os.path.join(top_dir, "cnf")
- if os.path.islink(conf_dir):
- print("removing %s symlink" % repr(conf_dir))
- os.unlink(conf_dir)
-
- pni_file = os.path.join(top_dir, ".repoman_not_installed")
- if os.path.exists(pni_file):
- print("removing %s" % repr(pni_file))
- os.unlink(pni_file)
-
- def clean_man(self):
- man_dir = os.path.join(self.build_base, "man")
- if os.path.exists(man_dir):
- remove_tree(man_dir)
-
- def run(self):
- if self.all:
- self.clean_tests()
- self.clean_docs()
- self.clean_man()
-
- clean.run(self)
-
-
-class x_install(install):
- """install command with extra Portage paths"""
-
- user_options = install.user_options + [
- # note: $prefix and $exec_prefix are reserved for Python install
- ("system-prefix=", None, "Prefix for architecture-independent data"),
- ("system-exec-prefix=", None, "Prefix for architecture-specific data"),
- ("bindir=", None, "Install directory for main executables"),
- ("datarootdir=", None, "Data install root directory"),
- ("docdir=", None, "Documentation install directory"),
- ("htmldir=", None, "HTML documentation install directory"),
- ("mandir=", None, "Manpage root install directory"),
- ("portage-base=", "b", "Portage install base"),
- (
- "portage-bindir=",
- None,
- "Install directory for Portage internal-use executables",
- ),
- ("portage-datadir=", None, "Install directory for data files"),
- ("sbindir=", None, "Install directory for superuser-intended executables"),
- ("sysconfdir=", None, "System configuration path"),
- ]
-
- # note: the order is important for proper substitution
- paths = [
- ("system_prefix", "/usr"),
- ("system_exec_prefix", "$system_prefix"),
- ("bindir", "$system_exec_prefix/bin"),
- ("sbindir", "$system_exec_prefix/sbin"),
- ("sysconfdir", "/etc"),
- ("datarootdir", "$system_prefix/share"),
- ("docdir", "$datarootdir/doc/$package-$version"),
- ("htmldir", "$docdir/html"),
- ("mandir", "$datarootdir/man"),
- ("portage_base", "$system_exec_prefix/lib/portage"),
- ("portage_bindir", "$portage_base/bin"),
- ("portage_datadir", "$datarootdir/portage"),
- # not customized at the moment
- ("logrotatedir", "$sysconfdir/logrotate.d"),
- ("portage_confdir", "$portage_datadir/config"),
- ("portage_setsdir", "$portage_confdir/sets"),
- ]
-
- def initialize_options(self):
- install.initialize_options(self)
-
- for key, default in self.paths:
- setattr(self, key, default)
- self.subst_paths = {}
-
- def finalize_options(self):
- install.finalize_options(self)
-
- # substitute variables
- new_paths = {
- "package": self.distribution.get_name(),
- "version": self.distribution.get_version(),
- }
- for key, _default in self.paths:
- new_paths[key] = subst_vars(getattr(self, key), new_paths)
- setattr(self, key, new_paths[key])
- self.subst_paths = new_paths
-
-
-class x_install_data(install_data):
- """install_data with customized path support"""
-
- user_options = install_data.user_options
-
- def initialize_options(self):
- install_data.initialize_options(self)
- self.build_base = None
- self.paths = None
-
- def finalize_options(self):
- install_data.finalize_options(self)
- self.set_undefined_options("build", ("build_base", "build_base"))
- self.set_undefined_options("install", ("subst_paths", "paths"))
-
- def run(self):
- self.run_command("build_man")
-
- def process_data_files(df):
- for d, files in df:
- # substitute man sources
- if d.startswith("$mandir/"):
- files = [os.path.join(self.build_base, v) for v in files]
-
- # substitute variables in path
- d = subst_vars(d, self.paths)
- yield (d, files)
-
- old_data_files = self.data_files
- self.data_files = process_data_files(self.data_files)
-
- install_data.run(self)
- self.data_files = old_data_files
-
-
-class x_install_lib(install_lib):
- """install_lib command with Portage path substitution"""
-
- user_options = install_lib.user_options
-
- def initialize_options(self):
- install_lib.initialize_options(self)
-
- def finalize_options(self):
- install_lib.finalize_options(self)
- self.set_undefined_options(
- "install",
- )
-
- def install(self):
- ret = install_lib.install(self)
-
- def rewrite_file(path, val_dict):
- path = os.path.join(self.install_dir, path)
- print("Rewriting %s" % path)
- with codecs.open(path, "r", "utf-8") as f:
- data = f.read()
-
- for varname, val in val_dict.items():
- regexp = r"(?m)^(%s\s*=).*$" % varname
- repl = r"\1 %s" % repr(val)
-
- data = re.sub(regexp, repl, data)
-
- with codecs.open(path, "w", "utf-8") as f:
- f.write(data)
-
- rewrite_file(
- "repoman/__init__.py",
- {
- "VERSION": self.distribution.get_version(),
- },
- )
-
- return ret
-
-
-class x_install_scripts_custom(install_scripts):
- def initialize_options(self):
- install_scripts.initialize_options(self)
- self.root = None
-
- def finalize_options(self):
- self.set_undefined_options(
- "install", ("root", "root"), (self.var_name, "install_dir")
- )
- install_scripts.finalize_options(self)
- self.build_dir = os.path.join(self.build_dir, self.dir_name)
-
- # prepend root
- if self.root is not None:
- self.install_dir = change_root(self.root, self.install_dir)
-
-
-class x_install_scripts_bin(x_install_scripts_custom):
- dir_name = "bin"
- var_name = "bindir"
-
-
-class x_install_scripts(install_scripts):
- def initialize_option(self):
- pass
-
- def finalize_options(self):
- pass
-
- def run(self):
- self.run_command("install_scripts_bin")
-
-
-class x_sdist(sdist):
- """sdist defaulting to .tar.xz format, and archive files owned by root"""
-
- def initialize_options(self):
- super().initialize_options()
- self.formats = ["xztar"]
-
- def finalize_options(self):
- if self.owner is None:
- self.owner = "root"
- if self.group is None:
- self.group = "root"
-
- sdist.finalize_options(self)
-
-
-class build_tests(x_build_scripts_custom):
- """Prepare build dir for running tests."""
-
- def initialize_options(self):
- x_build_scripts_custom.initialize_options(self)
- self.build_base = None
- self.build_lib = None
-
- def finalize_options(self):
- x_build_scripts_custom.finalize_options(self)
- self.set_undefined_options(
- "build", ("build_base", "build_base"), ("build_lib", "build_lib")
- )
-
- # since we will be writing to $build_lib/.., it is important
- # that we do not leave $build_base
- self.top_dir = os.path.normpath(os.path.join(self.build_lib, ".."))
- cprefix = os.path.commonprefix((self.build_base, self.top_dir))
- if cprefix != self.build_base:
- raise SystemError("build_lib must be a subdirectory of build_base")
-
- self.build_dir = os.path.join(self.top_dir, "bin")
-
- def run(self):
- self.run_command("build_py")
-
- # install all scripts $build_lib/../bin
- # (we can't do a symlink since we want shebangs corrected)
- x_build_scripts_custom.run(self)
-
- # symlink 'cnf' directory
- conf_dir = os.path.join(self.top_dir, "cnf")
- if os.path.exists(conf_dir):
- if not os.path.islink(conf_dir):
- raise SystemError(
- "%s exists and is not a symlink (collision)" % repr(conf_dir)
- )
- os.unlink(conf_dir)
- conf_src = os.path.relpath("cnf", self.top_dir)
- print("Symlinking %s -> %s" % (conf_dir, conf_src))
- os.symlink(conf_src, conf_dir)
-
- # create $build_lib/../.repoman_not_installed
- # to enable proper paths in tests
- with open(os.path.join(self.top_dir, ".repoman_not_installed"), "w"):
- pass
-
-
-class test(Command):
- """run tests"""
-
- user_options = []
-
- def initialize_options(self):
- self.build_lib = None
-
- def finalize_options(self):
- self.set_undefined_options("build", ("build_lib", "build_lib"))
-
- def run(self):
- self.run_command("build_tests")
- # copy GPG test keys
- copy_tree(
- os.path.join(
- self.build_lib, "..", "..", "lib", "repoman", "tests", ".gnupg"
- ),
- os.path.join(self.build_lib, "repoman", "tests", ".gnupg"),
- )
- os.chmod(os.path.join(self.build_lib, "repoman", "tests", ".gnupg"), 0o700)
- subprocess.check_call(
- [
- sys.executable,
- "-bWd",
- os.path.join(self.build_lib, "repoman/tests/runTests.py"),
- ]
- )
-
-
-def find_packages():
- for dirpath, _dirnames, filenames in os.walk("lib"):
- if "__init__.py" in filenames:
- yield os.path.relpath(dirpath, "lib")
-
-
-def find_scripts():
- for dirpath, _dirnames, filenames in os.walk("bin"):
- for f in filenames:
- if f not in ["deprecated-path"]:
- yield os.path.join(dirpath, f)
-
-
-def get_manpages():
- linguas = os.environ.get("LINGUAS")
- if linguas is not None:
- linguas = linguas.split()
-
- for dirpath, _dirnames, filenames in os.walk("man"):
- groups = collections.defaultdict(list)
- for f in filenames:
- _fn, suffix = f.rsplit(".", 1)
- groups[suffix].append(os.path.join(dirpath, f))
-
- topdir = dirpath[len("man/") :]
- if not topdir or linguas is None or topdir in linguas:
- for g, mans in groups.items():
- yield [os.path.join("$mandir", topdir, "man%s" % g), mans]
-
-
-setup(
- name="repoman",
- version="3.0.3",
- url="https://wiki.gentoo.org/wiki/Project:Portage",
- author="Gentoo Portage Development Team",
- author_email="dev-portage@gentoo.org",
- package_dir={"": "lib"},
- packages=list(find_packages()),
- # something to cheat build & install commands
- scripts=list(find_scripts()),
- data_files=list(get_manpages())
- + [
- ["$docdir", ["NEWS", "RELEASE-NOTES"]],
- ["share/repoman/qa_data", ["cnf/qa_data/qa_data.yaml"]],
- ["share/repoman/linechecks", ["cnf/linechecks/linechecks.yaml"]],
- [
- "share/repoman/repository",
- [
- "cnf/repository/linechecks.yaml",
- "cnf/repository/qa_data.yaml",
- "cnf/repository/repository.yaml",
- ],
- ],
- ],
- cmdclass={
- "build": x_build,
- "build_man": build_man,
- "build_scripts": x_build_scripts,
- "build_scripts_bin": x_build_scripts_bin,
- "build_tests": build_tests,
- "clean": x_clean,
- "install": x_install,
- "install_data": x_install_data,
- "install_lib": x_install_lib,
- "install_scripts": x_install_scripts,
- "install_scripts_bin": x_install_scripts_bin,
- "sdist": x_sdist,
- "test": test,
- },
- classifiers=[
- "Development Status :: 5 - Production/Stable",
- "Environment :: Console",
- "Intended Audience :: System Administrators",
- "License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
- "Operating System :: POSIX",
- "Programming Language :: Python :: 3",
- "Topic :: System :: Installation/Setup",
- ],
-)
diff --git a/tox.ini b/tox.ini
index 2281dfa240a..84c24396e9d 100644
--- a/tox.ini
+++ b/tox.ini
@@ -20,6 +20,5 @@ deps =
setenv =
PYTHONPATH={toxinidir}/lib
commands =
- pylint: bash -c 'rm -rf build && PYTHONPATH=$PWD/lib:$PWD/repoman/lib pylint bin/* lib/* repoman/bin/* repoman/lib/*'
+ pylint: bash -c 'rm -rf build && PYTHONPATH=$PWD/lib pylint bin/* lib/*'
python -b -Wd setup.py test
- 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'