Merged from trunk 9159:9179
authorFabian Groffen <grobian@gentoo.org>
Sun, 13 Jan 2008 11:05:32 +0000 (11:05 -0000)
committerFabian Groffen <grobian@gentoo.org>
Sun, 13 Jan 2008 11:05:32 +0000 (11:05 -0000)
   | 9160    | Bug #162542 - When dropping privileges for                   |
   | zmedico | FEATURES=userpriv, automatically detect permission problems  |
   |         | with CCACHE_DIR and recursively adjust permissions only when |
   |         | necessary.                                                   |

   | 9162    | Bug#204668 - Fix WORKDIR quoting in econf() when updating    |
   | zmedico | config.guess and config.sub.                                 |

   | 9163    | Bug #204425 - Remove --delete-after from the default         |
   | zmedico | PORTAGE_RSYNC_OPTS. This allows the rsync program to choose  |
   |         | the preferred --delete algorithm, or the user can choose one |
   |         | via PORTAGE_RSYNC_EXTRA_OPTS.                                |

   | 9164    | Make sure that portdb.findname() returns the correct ebuild. |
   | zmedico |                                                              |

   | 9165    | Fix the "Appending to PORTDIR_OVERLAY..." feature which was  |
   | zmedico | broken by the previous commit.                               |

   | 9166    | Bug #203316 - Fix isvalidatom() to properly detect invalid   |
   | zmedico | operators used together with slot atoms. Thanks to Arfrever  |
   |         | Frehtes Taifersar Arahesis <Arfrever.FTA@GMail.Com> for the  |
   |         | patch.                                                       |

   | 9167    | Bug #203887 - Implement RESTRICT=installsources for binaries |
   | zmedico | that are not compatible with debugedit.                      |

   | 9176    | Bug #162450 - Try to avoid having so many bugs marked        |
   | zmedico | UPSTREAM by encouraging users to report 'poor programming    |
   |         | practices' QA issues upstream and show them the $HOMEPAGE    |
   |         | for convenience.                                             |

   | 9177    | Add a DESCRIPTION.toolong warning for when the DESCRIPTION   |
   | zmedico | line is over 80 characters long. Thanks to Betelgeuse for    |
   |         | the patch.                                                   |

   | 9178    | * Make pkgcmp() pass the ebuild revision directly into       |
   | zmedico | vercmp() since there is code there to handle it already.     |
   |         | This eliminates some redundant revision comparison code.     |
   |         | Thanks to peper for the patch. * Add some vercmp() test      |
   |         | cases for comparison of ebuild revisions.                    |

   | 9179    | Add a new "ebuild.autotools" check for when ebuilds call     |
   | zmedico | autotools directly instead of using autotools.eclass. Thanks |
   |         | to Betelgeuse for the initial patch.                         |

svn path=/main/branches/prefix/; revision=9202

13 files changed:
bin/ebuild
bin/ebuild.sh
bin/misc-functions.sh
bin/prepstrip
bin/repoman
cnf/make.globals
man/ebuild.5
pym/_emerge/__init__.py
pym/portage/__init__.py
pym/portage/dep.py
pym/portage/tests/versions/test_vercmp.py
pym/portage/versions.py
pym/repoman/checks.py

index eb5976315fcbdcf9e76c11e08aef6bb79397addd..c3dcd8a32dd45569ca7bc810bfbbf40f51d4ab79 100755 (executable)
@@ -60,8 +60,20 @@ if not os.path.isabs(ebuild):
 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
@@ -90,17 +102,8 @@ else:
        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"
index 6c748bdedc5eaaa9130fa8e2fa8bc2ea4010bca6..d97745569cfdf1322f8ba55bda8e07651e5c9c6a 100755 (executable)
@@ -422,9 +422,11 @@ econf() {
        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
 
index f1a52e71dd44523b4e6827aa991054a5b13486e1..5e8ed6fc6173702052e16de9722788a39de3743f 100644 (file)
@@ -406,6 +406,13 @@ install_qa_check() {
                                *) 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
 
index 2ccf84c991db4a539a4b5ee9a1a3ff312df1f6bf..e89f67f2624e5086cb2c962ac1b647576ba61cf0 100755 (executable)
@@ -32,6 +32,7 @@ fi
 
 save_elf_sources() {
        hasq installsources ${FEATURES} || return 0
+       hasq installsources ${RESTRICT} && return 0
        type -P debugedit >/dev/null || return 0
 
        local x=$1
index a0a0322b48166bbfd366d99b43461593ac631859..22e1051fd7bdf2c57d970436db68bbb109e4f708 100755 (executable)
@@ -72,6 +72,8 @@ from portage.output import ConsoleStyleFile, StyleWriter
 
 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)))
@@ -258,6 +260,7 @@ qahelp={
        "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",
@@ -294,6 +297,7 @@ qahelp={
        "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",
@@ -311,6 +315,7 @@ qawarnings=[
 "ebuild.notadded",
 "ebuild.nostable",
 "ebuild.allmasked",
+"ebuild.autotools",
 "ebuild.nesteddie",
 "desktop.invalid",
 "digest.assumed",
@@ -319,6 +324,7 @@ qawarnings=[
 "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",
@@ -1350,6 +1356,13 @@ for x in scanlist:
                                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:
index 8ea92f18967d1ac04f0df283662e30f85c523d30..9d1179c8e7c67cef11e5e31c1d0798503ca2c643 100644 (file)
@@ -57,7 +57,7 @@ PORTAGE_RSYNC_RETRIES="3"
 # 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"
index cbd9e95286075c9ced7dbf3e2951e71f5701cc71..5623d9084fc5901eccf7b78cb5ec9147f5a7ddf1 100644 (file)
@@ -364,6 +364,10 @@ Distribution of binary packages is restricted.
 .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
index e705bd3e092a40023afbac386459fd728ddfdab9..61fcbb2232036cf6035b992d4313c9b392a70616 100644 (file)
@@ -5385,7 +5385,6 @@ def action_sync(settings, trees, mtimedb, myopts, myaction):
                                "--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
index e22e8074c127a2f1d16cf349223cadc131ddd132..f39f6660560691c64a8789b1b9cf1db4d4eadb14 100644 (file)
@@ -4118,6 +4118,11 @@ def prepare_build_dirs(myroot, mysettings, cleanup):
        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"]]
@@ -4134,7 +4139,13 @@ def prepare_build_dirs(myroot, mysettings, cleanup):
                                        # 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)
index da0bb64279556cf94fca9efe1de4cc0c8e0e6337..bf42d2ba85cfe70e0adbbf646f8b315e283a6158 100644 (file)
@@ -480,7 +480,7 @@ def isvalidatom(atom, allow_blockers=False):
                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
index c25ed954b42ad75cd6999f19d91061f6b408dabd..d8837b85243b603ba3091b0a6824fb0942b061e2 100644 (file)
@@ -12,7 +12,9 @@ class VerCmpTestCase(TestCase):
        
        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]) )
 
@@ -24,20 +26,31 @@ class VerCmpTestCase(TestCase):
                        ("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]))
index 131aa628c5ffbd9d2d06226c1a3b1438929d4fb8..ba7ad24d3aba312cf827c5eb0b8a8c19e3f0f8dc 100644 (file)
@@ -210,17 +210,11 @@ def pkgcmp(pkg1, pkg2):
        """
        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
 
 
index 916003e7eb318749005e60dad4dedb494ceb7cb1..b4f1b016e6d1a87b13693774a62ecaf43218b4a9 100644 (file)
@@ -178,11 +178,25 @@ class EbuildUselessCdS(LineCheck):
                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: