return
}
-# Used to generate the /lib/cpp and /usr/bin/cc wrappers
-gen_wrapper() {
- cat > "$1" <<-EOF
- #!${EPREFIX}/bin/sh
- exec $2 "\$@"
- EOF
- chmod 0755 "$1"
-}
-
ebuild_phase() {
[ "$(type -t ${1})" == "function" ] && qa_call ${1}
}
hasv hasq qa_source qa_call addread addwrite adddeny addpredict \
lchown lchgrp esyslog use usev useq has_version portageq \
best_version use_with use_enable register_die_hook check_KV \
- keepdir unpack strip_duplicate_slashes econf einstall gen_wrapper \
+ keepdir unpack strip_duplicate_slashes econf einstall \
dyn_setup dyn_unpack dyn_clean into insinto exeinto docinto \
insopts diropts exeopts libopts abort_handler abort_compile \
abort_test abort_install dyn_compile dyn_test dyn_install \
from repoman.checks import run_checks
from repoman import utilities
+from _emerge import Package, RootConfig
+from portage.sets import load_default_config
+
import portage.checksum
import portage.const
import portage.dep
"file.size":"Files in the files directory must be under 20k",
"file.name":"File/dir name must be composed of only the following chars: %s " % allowed_filename_chars,
"file.UTF8":"File is not UTF8 compliant",
+ "inherit.autotools":"Ebuild inherits autotools but does not call eautomake, eautoconf or eautoreconf",
"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",
"KEYWORDS.missing":"Ebuilds that have a missing or empty KEYWORDS variable",
"variable.readonly":"Assigning a readonly variable",
"LIVEVCS.stable":"This ebuild is a live checkout from a VCS but has stable keywords.",
"IUSE.invalid":"This ebuild has a variable in IUSE that is not in the use.desc or use.local.desc file",
+ "IUSE.undefined":"This ebuild does not define IUSE (style guideline says to define IUSE even when empty)",
"LICENSE.invalid":"This ebuild is listing a license that doesnt exist in portages license/ dir.",
"KEYWORDS.invalid":"This ebuild contains KEYWORDS that are not listed in profiles/arch.list or for which no valid profile was found",
"RDEPEND.suspect":"RDEPEND contains a package that usually only belongs in DEPEND.",
"KEYWORDS.dropped",
"KEYWORDS.stupid",
"KEYWORDS.missing",
+"IUSE.undefined",
"RDEPEND.suspect",
"RESTRICT.invalid",
"ebuild.minorsyn",
"ebuild.badheader",
"ebuild.patches",
"file.size",
+"inherit.autotools",
"java.eclassesnotused",
"metadata.missing",
"metadata.bad",
]
missingvars=["KEYWORDS","LICENSE","DESCRIPTION","HOMEPAGE","SLOT"]
-allvars=portage.auxdbkeys
+allvars = set(portage.auxdbkeys)
+allvars.update(Package.metadata_keys)
+allvars = sorted(allvars)
commitmessage=None
for x in missingvars:
x += ".missing"
trees["/"]["porttree"].settings = repoman_settings
portdb = trees["/"]["porttree"].dbapi
portdb.mysettings = repoman_settings
+setconfig = load_default_config(repoman_settings, trees["/"])
+root_config = RootConfig(repoman_settings, trees["/"], setconfig)
# We really only need to cache the metadata that's necessary for visibility
# filtering. Anything else can be discarded to reduce memory consumption.
for k in ("DEPEND", "LICENCE", "PDEPEND",
checkdirlist=os.listdir(checkdir)
ebuildlist=[]
- ebuild_metadata = {}
+ pkgs = {}
for y in checkdirlist:
if y in no_exec and \
stat.S_IMODE(os.stat(os.path.join(checkdir, y)).st_mode) & 0111:
stats["EAPI.unsupported"] += 1
fails["EAPI.unsupported"].append(os.path.join(x, y))
continue
- ebuild_metadata[pf] = myaux
+ pkgs[pf] = Package(cpv=cpv, metadata=myaux,
+ root_config=root_config)
# Sort ebuilds in ascending order for the KEYWORDS.dropped check.
pkgsplits = {}
slot_keywords = {}
- if len(ebuild_metadata) != len(ebuildlist):
+ 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
fails["ebuild.namenomatch"].append(x+"/"+y+".ebuild")
continue
- myaux = ebuild_metadata[y]
+ pkg = pkgs[y]
+ myaux = pkg.metadata
eapi = myaux["EAPI"]
- inherited = myaux["INHERITED"].split()
+ inherited = pkg.inherited
# Test for negative logic and bad words in the RESTRICT var.
#for x in myaux[allvars.index("RESTRICT")].split():
full_path = os.path.join(repodir, relative_path)
f = open(full_path, 'rb')
try:
- for check_name, e in run_checks(f, os.stat(full_path).st_mtime):
+ for check_name, e in run_checks(f, pkg):
stats[check_name] += 1
fails[check_name].append(relative_path + ': %s' % e)
finally:
.B IUSE.invalid
This build has a variable in IUSE that is not in the use.desc or use.local.desc file
.TP
+.B IUSE.undefined
+This ebuild does not define IUSE (style guideline says to define IUSE even when empty)
+.TP
.B KEYWORDS.dropped
Ebuilds that appear to have dropped KEYWORDS for some arch
.TP
.B filedir.missing
Package lacks a files directory
.TP
+.B inherit.autotools
+Ebuild inherits autotools but does not call eautomake, eautoconf or eautoreconf
+.TP
.B java.eclassesnotused
With virtual/jdk in DEPEND you must inherit a java eclass. Refer to
\fIhttp://www.gentoo.org/proj/en/java/java\-devel.xml\fR for more information.
__slots__ = ("built", "cpv", "depth",
"installed", "metadata", "onlydeps", "operation",
"root_config", "type_name",
- "category", "cp", "cpv_split", "iuse",
+ "category", "counter", "cp", "cpv_split",
+ "inherited", "iuse", "mtime",
"pf", "pv_split", "root", "slot", "slot_atom", "use")
metadata_keys = [
"CHOST", "COUNTER", "DEPEND", "EAPI", "IUSE", "KEYWORDS",
"LICENSE", "PDEPEND", "PROVIDE", "RDEPEND",
- "repository", "RESTRICT", "SLOT", "USE"]
+ "repository", "RESTRICT", "SLOT", "USE", "_mtime_"]
def __init__(self, **kwargs):
Task.__init__(self, **kwargs)
"""
Detect metadata updates and synchronize Package attributes.
"""
- _wrapped_keys = frozenset(["IUSE", "SLOT", "USE"])
+ _wrapped_keys = frozenset(
+ ["COUNTER", "INHERITED", "IUSE", "SLOT", "USE", "_mtime_"])
def __init__(self, pkg, metadata):
dict.__init__(self)
if k in self._wrapped_keys:
getattr(self, "_set_" + k.lower())(k, v)
+ def _set_inherited(self, k, v):
+ if isinstance(v, basestring):
+ v = frozenset(v.split())
+ self._pkg.inherited = v
+
def _set_iuse(self, k, v):
self._pkg.iuse = self._pkg._iuse(
v.split(), self._pkg.root_config.iuse_implicit)
def _set_use(self, k, v):
self._pkg.use = self._pkg._use(v.split())
+ def _set_counter(self, k, v):
+ if isinstance(v, basestring):
+ try:
+ v = int(v.strip())
+ except ValueError:
+ v = 0
+ self._pkg.counter = v
+
+ def _set__mtime_(self, k, v):
+ if isinstance(v, basestring):
+ try:
+ v = float(v.strip())
+ except ValueError:
+ v = 0
+ self._pkg.mtime = v
+
def _get_hash_key(self):
hash_key = getattr(self, "_hash_key", None)
if hash_key is None:
return True
return False
+ def __getitem__(self, k):
+ cpv = getattr(k, "cpv", None)
+ if cpv is None:
+ try:
+ cpv = k[2]
+ except (TypeError, IndexError):
+ raise KeyError(k)
+ if cpv is None:
+ raise KeyError(k)
+ existing = self._cpv_map.get(cpv)
+ if existing is not None and \
+ existing == k:
+ return existing
+ raise KeyError(k)
+
def match_pkgs(self, atom):
return [self._cpv_map[cpv] for cpv in self.match(atom)]
def load_emerge_config(trees=None):
kwargs = {}
for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
- kwargs[k] = os.environ.get(envvar, None)
+ v = os.environ.get(envvar, None)
+ if v and v.strip():
+ kwargs[k] = v
trees = portage.create_trees(trees=trees, **kwargs)
for root, root_trees in trees.iteritems():
# by the constructor argument (from the calling environment).
if target_root is None and "ROOT" in make_conf:
target_root = make_conf["ROOT"]
+ if not target_root.strip():
+ target_root = None
if target_root is None:
target_root = "/"
noiselevel=-1)
if strict:
return 0
+ else:
+ return 1
mf = Manifest(pkgdir, mysettings["DISTDIR"])
eout = portage.output.EOutput()
eout.quiet = mysettings.get("PORTAGE_QUIET", None) == "1"
myroots = [(settings["ROOT"], settings)]
if settings["ROOT"] != "/":
- settings = config(config_root=None, target_root=None,
+ settings = config(config_root=None, target_root="/",
config_incrementals=portage.const.INCREMENTALS)
# When ROOT != "/" we only want overrides from the calling
# environment to apply to the config that's associated
try:
- emtime = os.stat(myebuild)[stat.ST_MTIME]
+ st = os.stat(myebuild)
+ emtime = st[stat.ST_MTIME]
except OSError:
writemsg("!!! aux_get(): ebuild for '%(cpv)s' does not exist at:\n" % {"cpv":mycpv},
noiselevel=-1)
for x in mylist:
if x == "INHERITED":
returnme.append(' '.join(mydata.get("_eclasses_", [])))
+ elif x == "_mtime_":
+ returnme.append(st.st_mtime)
else:
returnme.append(mydata.get(x,""))
mydir_mtime = long(mydir_stat.st_mtime)
pkg_data = self._aux_cache["packages"].get(mycpv)
pull_me = cache_these.union(wants)
- mydata = {}
+ mydata = {"_mtime_" : mydir_mtime}
cache_valid = False
cache_incomplete = False
cache_mtime = None
if pull_me:
# pull any needed data and cache it
aux_keys = list(pull_me)
- for k, v in izip(aux_keys, self._aux_get(mycpv, aux_keys)):
+ for k, v in izip(aux_keys,
+ self._aux_get(mycpv, aux_keys, st=mydir_stat)):
mydata[k] = v
if not cache_valid or cache_these.difference(metadata):
cache_data = {}
self._aux_cache["modified"].add(mycpv)
return [mydata[x] for x in wants]
- def _aux_get(self, mycpv, wants):
+ def _aux_get(self, mycpv, wants, st=None):
mydir = self.getpath(mycpv)
- try:
- if not stat.S_ISDIR(os.stat(mydir).st_mode):
- raise KeyError(mycpv)
- except OSError, e:
- if e.errno == errno.ENOENT:
- raise KeyError(mycpv)
- del e
- raise
+ if st is None:
+ try:
+ st = os.stat(mydir)
+ except OSError, e:
+ if e.errno == errno.ENOENT:
+ raise KeyError(mycpv)
+ elif e.errno == PermissionDenied.errno:
+ raise PermissionDenied(mydir)
+ else:
+ raise
+ if not stat.S_ISDIR(st.st_mode):
+ raise KeyError(mycpv)
results = []
for x in wants:
+ if x == "_mtime_":
+ results.append(st.st_mtime)
+ continue
try:
myf = open(os.path.join(mydir, x), "r")
try:
EbuildUselessCdS, EbuildNestedDie,
EbuildPatches, EbuildQuotedA)))
-def run_checks(contents, st_mtime):
+_iuse_def_re = re.compile(r'^IUSE=.*')
+_comment_re = re.compile(r'(^|\s*)#')
+_autotools_funcs = (
+ "eaclocal", "eautoconf", "eautoheader",
+ "eautomake", "eautoreconf", "_elibtoolize")
+_autotools_func_re = re.compile(r'(^|\s)(' + \
+ "|".join(_autotools_funcs) + ')(\s|$)')
+
+def run_checks(contents, pkg):
checks = list(_constant_checks)
- checks.append(EbuildHeader(st_mtime))
+ checks.append(EbuildHeader(pkg.mtime))
+ iuse_def = None
+ inherit_autotools = "autotools" in pkg.inherited
+ autotools_func_call = None
for num, line in enumerate(contents):
+ comment = _comment_re.match(line)
+ if comment is None:
+ if inherit_autotools and autotools_func_call is None:
+ autotools_func_call = _autotools_func_re.search(line)
+ if iuse_def is None:
+ iuse_def = _iuse_def_re.match(line)
for lc in checks:
ignore = lc.ignore_line
if not ignore or not ignore.match(line):
e = lc.check(num, line)
if e:
yield lc.repoman_check_name, e % (num + 1)
+ if iuse_def is None:
+ yield 'IUSE.undefined', 'IUSE is not defined'
+ if inherit_autotools and autotools_func_call is None:
+ yield 'inherit.autotools', 'no eauto* function called'