ebuild = portage.normalize_path(ebuild)
# portdbapi uses the canonical path for the base of the portage tree, but
# subdirectories of the base can be built from symlinks (like crossdev does).
-ebuild_portdir = os.path.realpath(os.path.dirname(os.path.dirname(ebuild)))
-ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-2:])
+ebuild_portdir = os.path.realpath(
+ os.path.dirname(os.path.dirname(os.path.dirname(ebuild))))
+ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-3:])
+
+# Make sure that portdb.findname() returns the correct ebuild.
+if ebuild_portdir not in portage.portdb.porttrees:
+ os.environ["PORTDIR_OVERLAY"] = \
+ os.environ.get("PORTDIR_OVERLAY","") + " " + ebuild_portdir
+ print "Appending %s to PORTDIR_OVERLAY..." % ebuild_portdir
+ portage.close_portdbapi_caches()
+ reload(portage)
+del portage.portdb.porttrees[1:]
+if ebuild_portdir != portage.portdb.porttree_root:
+ portage.portdb.porttrees.append(ebuild_portdir)
if not os.path.exists(ebuild):
print "'%s' does not exist." % ebuild
portage_ebuild = portage.portdb.findname(cpv)
if not portage_ebuild or portage_ebuild != ebuild:
- overlay = "/".join(ebuild_split[:-2])
- os.environ["PORTDIR_OVERLAY"] = os.environ.get("PORTDIR_OVERLAY","") + " " + overlay
- print "Appending %s to PORTDIR_OVERLAY..." % overlay
- portage.close_portdbapi_caches()
- reload(portage)
- portage_ebuild = portage.portdb.findname(cpv)
-
- if not portage_ebuild or portage_ebuild != ebuild:
- print "!!! %s does not seem to have a valid PORTDIR structure." % overlay
- sys.exit(1)
-
+ print "!!! %s does not seem to have a valid PORTDIR structure." % ebuild
+ sys.exit(1)
if len(pargs) > 1 and "config" in pargs:
print "config must be called on it's own, not combined with any other phase"
fi
if [ -x "${ECONF_SOURCE}/configure" ]; then
if [ -e "${EPREFIX}"/usr/share/gnuconfig/ ]; then
- for x in $(find "${WORKDIR}" -type f '(' -name config.guess -o -name config.sub ')') ; do
+ find "${WORKDIR}" -type f '(' \
+ -name config.guess -o -name config.sub ')' -print0 | \
+ while read -d $'\0' x ; do
vecho " * econf: updating ${x/${WORKDIR}\/} with ${EPREFIX}/usr/share/gnuconfig/${x##*/}"
- cp -f "${EPREFIX}"/usr/share/gnuconfig/${x##*/} ${x}
+ cp -f "${EPREFIX}"/usr/share/gnuconfig/"${x##*/}" "${x}"
done
fi
*) abort="yes";;
esac
fi
+ if [[ ${abort} == "yes" ]] || ; then
+ echo "Please do not file a Gentoo bug and instead" \
+ "report the above QA issues directly to the upstream" \
+ "developers of this software." | fmt -w 70 | \
+ while read line ; do eqawarn "${line}" ; done
+ eqawarn "Homepage: ${HOMEPAGE}"
+ fi
[[ ${abort} == "yes" ]] && hasq stricter ${FEATURES} && die "poor code kills airplanes"
fi
save_elf_sources() {
hasq installsources ${FEATURES} || return 0
+ hasq installsources ${RESTRICT} && return 0
type -P debugedit >/dev/null || return 0
local x=$1
initialize_logger()
+# 14 is the length of DESCRIPTION=""
+max_desc_len = 80 - 14
allowed_filename_chars="a-zA-Z0-9._-+:"
allowed_filename_chars_set = {}
map(allowed_filename_chars_set.setdefault, map(chr, range(ord('a'), ord('z')+1)))
"KEYWORDS.stupid":"Ebuilds that use KEYWORDS=-* instead of package.mask",
"LICENSE.missing":"Ebuilds that have a missing or empty LICENSE variable",
"DESCRIPTION.missing":"Ebuilds that have a missing or empty DESCRIPTION variable",
+ "DESCRIPTION.toolong":"DESCRIPTION line is over 80 characters",
"EAPI.unsupported":"Ebuilds that have an unsupported EAPI version (you must upgrade portage)",
"SLOT.missing":"Ebuilds that have a missing or empty SLOT variable",
"HOMEPAGE.missing":"Ebuilds that have a missing or empty HOMEPAGE variable",
"ebuild.majorsyn":"This ebuild has a major syntax error that may cause the ebuild to fail partially or fully",
"ebuild.minorsyn":"This ebuild has a minor syntax error that contravenes gentoo coding style",
"ebuild.badheader":"This ebuild has a malformed header",
+ "ebuild.autotools":"Ebuild calls autotools directly instead of using autotools.eclass",
"metadata.missing":"Missing metadata.xml files",
"metadata.bad":"Bad metadata.xml files",
"virtual.versioned":"PROVIDE contains virtuals with versions",
"ebuild.notadded",
"ebuild.nostable",
"ebuild.allmasked",
+"ebuild.autotools",
"ebuild.nesteddie",
"desktop.invalid",
"digest.assumed",
"DEPEND.badmasked","RDEPEND.badmasked","PDEPEND.badmasked",
"DEPEND.badindev","RDEPEND.badindev","PDEPEND.badindev",
"DEPEND.badmaskedindev","RDEPEND.badmaskedindev","PDEPEND.badmaskedindev",
+"DESCRIPTION.toolong",
"IUSE.invalid",
"KEYWORDS.stupid",
"KEYWORDS.missing",
stats[myqakey]=stats[myqakey]+1
fails[myqakey].append(x+"/"+y+".ebuild")
+ # 14 is the length of DESCRIPTION=""
+ if len(myaux['DESCRIPTION']) > max_desc_len:
+ stats['DESCRIPTION.toolong'] += 1
+ fails['DESCRIPTION.toolong'].append(
+ "%s: DESCRIPTION is %d characters (max %d)" % \
+ (relative_path, len(myaux['DESCRIPTION']), max_desc_len))
+
keywords = myaux["KEYWORDS"].split()
stable_keywords = []
for keyword in keywords:
# Number of seconds rsync will wait before timing out.
#RSYNC_TIMEOUT="180"
-PORTAGE_RSYNC_OPTS="--recursive --links --safe-links --perms --times --compress --force --whole-file --delete --delete-after --stats --timeout=180 --exclude=/distfiles --exclude=/local --exclude=/packages --filter=H_**/files/digest-*"
+PORTAGE_RSYNC_OPTS="--recursive --links --safe-links --perms --times --compress --force --whole-file --delete --stats --timeout=180 --exclude=/distfiles --exclude=/local --exclude=/packages --filter=H_**/files/digest-*"
# Minimal CONFIG_PROTECT
CONFIG_PROTECT="/etc"
.I fetch
like \fImirror\fR but the files will not be fetched via \fBSRC_URI\fR either.
.TP
+.I installsources
+Disables installsources for specific packages. This is for packages with
+binaries that are not compatible with debugedit.
+.TP
.I mirror
files in \fBSRC_URI\fR will not be downloaded from the \fBGENTOO_MIRRORS\fR.
.TP
"--force", # Force deletion on non-empty dirs
"--whole-file", # Don't do block transfers, only entire files
"--delete", # Delete files that aren't in the master tree
- "--delete-after", # Delete only after everything else is done
"--stats", # Show final statistics about what was transfered
"--timeout="+str(mytimeout), # IO timeout if not done in X seconds
"--exclude=/distfiles", # Exclude distfiles from consideration
dirmode = 02070
filemode = 060
modemask = 02
+ restrict = mysettings.get("PORTAGE_RESTRICT","").split()
+ from portage.data import secpass
+ droppriv = secpass >= 2 and \
+ "userpriv" in mysettings.features and \
+ "userpriv" not in restrict
for myfeature, kwargs in features_dirs.iteritems():
if myfeature in mysettings.features:
basedir = mysettings[kwargs["basedir_var"]]
# Generally, we only want to apply permissions for
# initial creation. Otherwise, we don't know exactly what
# permissions the user wants, so should leave them as-is.
- if modified or kwargs["always_recurse"]:
+ droppriv_fix = False
+ if droppriv:
+ st = os.stat(mydir)
+ if st.st_gid != portage_gid or \
+ not stat.S_IMODE(st.st_mode) & dirmode:
+ droppriv_fix = True
+ if modified or kwargs["always_recurse"] or droppriv_fix:
if modified:
writemsg("Adjusting permissions recursively: '%s'\n" % mydir,
noiselevel=-1)
return 0
operator = get_operator(atom)
if operator:
- if operator[0] in "<>" and atom[-1] == "*":
+ if operator[0] in "<>" and remove_slot(atom).endswith("*"):
return 0
if mycpv_cps and mycpv_cps[0] != "null":
# >=cat/pkg-1.0
def testVerCmpGreater(self):
- tests = [ ( "6.0", "5.0"), ("5.0","5")]
+ tests = [ ( "6.0", "5.0"), ("5.0","5"),
+ ("1.0-r1", "1.0-r0"),
+ ("1.0-r1", "1.0")]
for test in tests:
self.failIf( vercmp( test[0], test[1] ) <= 0, msg="%s < %s? Wrong!" % (test[0],test[1]) )
("1.0_alpha2", "1.0_p2"),("1.0_alpha1", "1.0_beta1"),("1.0_beta3","1.0_rc3"),
("1.001000000000000000001", "1.001000000000000000002"),
("1.00100000000", "1.0010000000000000001"),
- ("1.01", "1.1")]
+ ("1.01", "1.1"),
+ ("1.0-r0", "1.0-r1"),
+ ("1.0", "1.0-r1")]
for test in tests:
self.failIf( vercmp( test[0], test[1]) >= 0, msg="%s > %s? Wrong!" % (test[0],test[1]))
def testVerCmpEqual(self):
- tests = [ ("4.0", "4.0") ]
+ tests = [ ("4.0", "4.0"),
+ ("1.0", "1.0"),
+ ("1.0-r0", "1.0"),
+ ("1.0", "1.0-r0"),
+ ("1.0-r0", "1.0-r0"),
+ ("1.0-r1", "1.0-r1")]
for test in tests:
self.failIf( vercmp( test[0], test[1]) != 0, msg="%s != %s? Wrong!" % (test[0],test[1]))
def testVerNotEqual(self):
tests = [ ("1","2"),("1.0_alpha","1.0_pre"),("1.0_beta","1.0_alpha"),
- ("0", "0.0")]
+ ("0", "0.0"),
+ ("1.0-r0", "1.0-r1"),
+ ("1.0-r1", "1.0-r0"),
+ ("1.0", "1.0-r1"),
+ ("1.0-r1", "1.0")]
for test in tests:
self.failIf( vercmp( test[0], test[1]) == 0, msg="%s == %s? Wrong!" % (test[0],test[1]))
"""
if pkg1[0] != pkg2[0]:
return None
- mycmp=vercmp(pkg1[1],pkg2[1])
+ mycmp = vercmp("-".join(pkg1[1:]), "-".join(pkg2[1:]))
if mycmp>0:
return 1
if mycmp<0:
return -1
- r1=float(pkg1[2][1:])
- r2=float(pkg2[2][1:])
- if r1>r2:
- return 1
- if r2>r1:
- return -1
return 0
elif self.method_re.match(line):
self.check_next_line = True
+class Autotools(LineCheck):
+ """Check for direct calls to autotools"""
+ repoman_check_name = 'ebuild.autotools'
+ re = re.compile(r'^[^#]*([^e]|^)(autoconf|automake|aclocal|libtoolize)')
+
+ 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 ("Direct calls to '%s'" % m.group(2)) + \
+ " instead of using autotools.eclass on line: %d"
+
+_constant_checks = tuple((c() for c in (Autotools,
+ EbuildWhitespace, EbuildQuote,
+ EbuildAssignment, EbuildUselessDodoc,
+ EbuildUselessCdS, EbuildNestedDie)))
+
def run_checks(contents, st_mtime):
- checks = []
- for c in (EbuildWhitespace, EbuildQuote, EbuildAssignment,
- EbuildUselessDodoc, EbuildUselessCdS, EbuildNestedDie):
- checks.append(c())
+ checks = list(_constant_checks)
checks.append(EbuildHeader(st_mtime))
for num, line in enumerate(contents):
for lc in checks: