From 80841f886cbf18d77e0e87c135fae1afa964f1d0 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Sat, 14 Feb 2009 11:07:30 +0000 Subject: [PATCH] Merged from trunk -r12593:12605 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit |12594 |Remove support for deprecated 2_pre* EAPI values. | |zmedico| | |12595 |Keep 2_pre* EAPI values in the deprecated list so that uninstalls still work | |zmedico|normally. | |12596 |Add new EAPI 3_pre1 value, and disable unpack() support for *.xz for earlier EAPI | |zmedico|values. | |12597 |Document EAPI 3_pre1. | |zmedico| | |12598 |Bug #258433 - Note FETCHCOMMAND and RESUMECOMMAND requirements wrt ${FILE} for | |zmedico|compatibility with EAPI 2. | |12599 |Inside depgraph._select_atoms(), only trigger the circular dependency avoidance | |zmedico|code for buildtime dependencies. This solves a problem with virtual/mysql | | |inappropriately pulling in mysql-community from PDEPEND when satisfying deps of | | |plain mysql. Thanks to Krzysiek Pawlik for reporting this issue: | | |http://archives.gentoo.org/gentoo-dev/msg_efce154d642fe6ede38d084a33c7f949.xml | |12600 |Bug #258433 - In portage.fetch(), check for missing ${FILE} parameter in | |zmedico|FETCHCOMMAND or RESUMECOMMAND and bail out early if necessary. | |12601 |Inside portage.fetch(), check for the case where FETCOMMAND creates a directory | |zmedico|where a file is expected. This can happen if FETCHCOMMAND erroneously contains | | |wget's -P option where it should instead have -O, as reported in bug #258433, | | |comment #16. | |12602 |* Remove outdated comment about qa_source() return value (with typo). * Update | |zmedico|copyright header. Thanks to Jeremy Olexa for reporting. | |12603 |Add a new "portage.internal" warning for prepalldocs usage since the council ruled| |zmedico|that it shouldn't be used in ebuilds. Thanks to Petteri Räty for| | |the initial patch. | |12604 |Fix Scheduler._prevent_builddir_collisions() to skip non-Package instances when | |zmedico|necessary. | |12605 |In depgraph._serialize_tasks(), verify that an uninstall task has at least one | |zmedico|theoretically mergeable parent before choosing to reverse it's edges. | svn path=/main/branches/prefix/; revision=12608 --- RELEASE-NOTES | 4 ++ bin/ebuild.sh | 23 ++++--- bin/repoman | 1 + doc/package/ebuild.docbook | 1 + doc/package/ebuild/eapi/3.docbook | 15 +++++ doc/portage.docbook | 1 + man/repoman.1 | 3 + pym/_emerge/__init__.py | 91 ++++++++++++++++++-------- pym/portage/__init__.py | 103 ++++++++++++++++++++++++------ pym/repoman/checks.py | 11 +++- pym/repoman/errors.py | 1 + 11 files changed, 196 insertions(+), 58 deletions(-) create mode 100644 doc/package/ebuild/eapi/3.docbook diff --git a/RELEASE-NOTES b/RELEASE-NOTES index c5a5dc6c2..4e6900595 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -52,6 +52,10 @@ portage-2.1.6 force digests to be updated, run `ebuild --force manifest`. This is a safety measure which protects valid distfiles digests from being accidentally replaced by invalid digests. +* If you have overridden FETCHCOMMAND or RESUMECOMMAND variables, for + compatibility with EAPI 2, you must ensure that these variables are written + such that the downloaded file will be placed at \"\${DISTDIR}/\${FILE}\". + Refer to make.conf(5) for information about FETCHCOMMAND and RESUMECOMMAND. portage-2.1.5 ================================== diff --git a/bin/ebuild.sh b/bin/ebuild.sh index e5df919bc..1add4fb1f 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -1,5 +1,5 @@ #!@PORTAGE_BASH@ -# Copyright 1999-2007 Gentoo Foundation +# Copyright 1999-2009 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Id$ @@ -29,7 +29,7 @@ fi # These two functions wrap sourcing and calling respectively. At present they # perform a qa check to make sure eclasses and ebuilds and profiles don't mess # with shell opts (shopts). Ebuilds/eclasses changing shopts should reset them -# when they are done. Note: For now these shoudl always return success. +# when they are done. qa_source() { local shopts=$(shopt) OLDIFS="$IFS" @@ -334,6 +334,7 @@ unpack() { local y local myfail local tar_opts="" + local eapi=${EAPI:-0} [ -z "$*" ] && die "Nothing passed to the 'unpack' command" for x in "$@"; do @@ -435,11 +436,15 @@ unpack() { fi ;; xz) - if [ "${y}" == "tar" ]; then - xz -dc "${srcdir}${x}" | tar xof - ${tar_opts} - assert "$myfail" + if hasq $eapi 0 1 2 ; then + vecho "unpack ${x}: file format not recognized. Ignoring." else - xz -dc "${srcdir}${x}" > ${x%.*} || die "$myfail" + if [ "${y}" == "tar" ]; then + xz -dc "${srcdir}${x}" | tar xof - ${tar_opts} + assert "$myfail" + else + xz -dc "${srcdir}${x}" > ${x%.*} || die "$myfail" + fi fi ;; *) @@ -1388,11 +1393,11 @@ _ebuild_arg_to_phase() { phase_func=src_unpack ;; prepare) - ! hasq $eapi 0 1 2_pre1 2_pre2 && \ + ! hasq $eapi 0 1 && \ phase_func=src_prepare ;; configure) - ! hasq $eapi 0 1 2_pre1 && \ + ! hasq $eapi 0 1 && \ phase_func=src_configure ;; compile) @@ -1438,7 +1443,7 @@ _ebuild_phase_funcs() { case $eapi in - 0|1|2_pre1) + 0|1) if [[ $(type -t src_compile) != function ]] ; then case $eapi in diff --git a/bin/repoman b/bin/repoman index 03fc80c13..8d0cfaf25 100755 --- a/bin/repoman +++ b/bin/repoman @@ -315,6 +315,7 @@ qahelp={ "metadata.missing":"Missing metadata.xml files", "metadata.bad":"Bad metadata.xml files", "metadata.warning":"Warnings in metadata.xml files", + "portage.internal":"The ebuild uses an internal Portage function", "virtual.versioned":"PROVIDE contains virtuals with versions", "virtual.exists":"PROVIDE contains existing package names", "virtual.unavailable":"PROVIDE contains a virtual which contains no profile default", diff --git a/doc/package/ebuild.docbook b/doc/package/ebuild.docbook index ecd88017a..04baa22d6 100644 --- a/doc/package/ebuild.docbook +++ b/doc/package/ebuild.docbook @@ -7,5 +7,6 @@ &package_ebuild_eapi_0; &package_ebuild_eapi_1; &package_ebuild_eapi_2; +&package_ebuild_eapi_3; diff --git a/doc/package/ebuild/eapi/3.docbook b/doc/package/ebuild/eapi/3.docbook new file mode 100644 index 000000000..7be24f29c --- /dev/null +++ b/doc/package/ebuild/eapi/3.docbook @@ -0,0 +1,15 @@ +
+EAPI 3_pre1 +
+Helpers +
+unpack +
+Support for the xz file extension + +The xz file extension is now supported. + +
+
+
+
diff --git a/doc/portage.docbook b/doc/portage.docbook index bfe9750d3..999103a10 100644 --- a/doc/portage.docbook +++ b/doc/portage.docbook @@ -18,6 +18,7 @@ + diff --git a/man/repoman.1 b/man/repoman.1 index 5b5aec6ff..aca5587c0 100644 --- a/man/repoman.1 +++ b/man/repoman.1 @@ -270,6 +270,9 @@ Missing metadata.xml files .B metadata.warning Warnings in metadata.xml files .TP +.B portage.internal +The ebuild uses an internal Portage function +.TP .B upstream.workaround The ebuild works around an upstream bug, an upstream bug should be filed and tracked in bugs.gentoo.org diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 6526194b9..84ab989f2 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -2873,12 +2873,9 @@ class EbuildExecuter(CompositeTask): pkg = self.pkg phases = self._phases eapi = pkg.metadata["EAPI"].replace(EAPIPREFIX, "").strip() - if eapi in ("0", "1", "2_pre1"): + if eapi in ("0", "1"): # skip src_prepare and src_configure phases = phases[2:] - elif eapi in ("2_pre2",): - # skip src_prepare - phases = phases[1:] for phase in phases: ebuild_phases.add(EbuildPhase(background=self.background, @@ -5148,7 +5145,8 @@ class depgraph(object): vardb = self.roots[dep_root].trees["vartree"].dbapi try: selected_atoms = self._select_atoms(dep_root, - dep_string, myuse=myuse, parent=pkg, strict=strict) + dep_string, myuse=myuse, parent=pkg, strict=strict, + priority=dep_priority) except portage.exception.InvalidDependString, e: show_invalid_depstring_notice(jbigkey, dep_string, str(e)) return 0 @@ -5781,12 +5779,20 @@ class depgraph(object): return self._select_atoms_highest_available(*pargs, **kwargs) def _select_atoms_highest_available(self, root, depstring, - myuse=None, parent=None, strict=True, trees=None): + myuse=None, parent=None, strict=True, trees=None, priority=None): """This will raise InvalidDependString if necessary. If trees is None then self._filtered_trees is used.""" pkgsettings = self.pkgsettings[root] if trees is None: trees = self._filtered_trees + if not getattr(priority, "buildtime", False): + # The parent should only be passed to dep_check() for buildtime + # dependencies since that's the only case when it's appropriate + # to trigger the circular dependency avoidance code which uses it. + # It's important not to trigger the same circular dependency + # avoidance code for runtime dependencies since it's not needed + # and it can promote an incorrect package choice. + parent = None if True: try: if parent is not None: @@ -6887,6 +6893,41 @@ class depgraph(object): runtime_deps.update(atom for atom in portage_rdepend \ if not atom.startswith("!")) + def gather_deps(ignore_priority, mergeable_nodes, + selected_nodes, node): + """ + Recursively gather a group of nodes that RDEPEND on + eachother. This ensures that they are merged as a group + and get their RDEPENDs satisfied as soon as possible. + """ + if node in selected_nodes: + return True + if node not in mergeable_nodes: + return False + if node == replacement_portage and \ + mygraph.child_nodes(node, + ignore_priority=DepPriority.MEDIUM_SOFT): + # Make sure that portage always has all of it's + # RDEPENDs installed first. + return False + selected_nodes.add(node) + for child in mygraph.child_nodes(node, + ignore_priority=ignore_priority): + if not gather_deps(ignore_priority, + mergeable_nodes, selected_nodes, child): + return False + return True + + def ignore_uninst_or_med(priority): + if priority is BlockerDepPriority.instance: + return True + return priority <= DepPriority.MEDIUM + + def ignore_uninst_or_med_soft(priority): + if priority is BlockerDepPriority.instance: + return True + return priority <= DepPriority.MEDIUM_SOFT + ignore_priority_soft_range = [None] ignore_priority_soft_range.extend( xrange(DepPriority.MIN, DepPriority.MEDIUM_SOFT + 1)) @@ -6965,28 +7006,6 @@ class depgraph(object): if not selected_nodes: nodes = get_nodes(ignore_priority=DepPriority.MEDIUM) if nodes: - """Recursively gather a group of nodes that RDEPEND on - eachother. This ensures that they are merged as a group - and get their RDEPENDs satisfied as soon as possible.""" - def gather_deps(ignore_priority, - mergeable_nodes, selected_nodes, node): - if node in selected_nodes: - return True - if node not in mergeable_nodes: - return False - if node == replacement_portage and \ - mygraph.child_nodes(node, - ignore_priority=DepPriority.MEDIUM_SOFT): - # Make sure that portage always has all of it's - # RDEPENDs installed first. - return False - selected_nodes.add(node) - for child in mygraph.child_nodes(node, - ignore_priority=ignore_priority): - if not gather_deps(ignore_priority, - mergeable_nodes, selected_nodes, child): - return False - return True mergeable_nodes = set(nodes) if prefer_asap and asap_nodes: nodes = asap_nodes @@ -7044,6 +7063,10 @@ class depgraph(object): if not selected_nodes and not myblocker_uninstalls.is_empty(): # An Uninstall task needs to be executed in order to # avoid conflict if possible. + + mergeable_nodes = get_nodes( + ignore_priority=ignore_uninst_or_med) + min_parent_deps = None uninst_task = None for task in myblocker_uninstalls.leaf_nodes(): @@ -7169,10 +7192,19 @@ class depgraph(object): # best possible choice, but the current algorithm # is simple and should be near optimal for most # common cases. + mergeable_parent = False parent_deps = set() for parent in mygraph.parent_nodes(task): parent_deps.update(mygraph.child_nodes(parent, ignore_priority=DepPriority.MEDIUM_SOFT)) + if parent in mergeable_nodes and \ + gather_deps(ignore_uninst_or_med_soft, + mergeable_nodes, set(), parent): + mergeable_parent = True + + if not mergeable_parent: + continue + parent_deps.remove(task) if min_parent_deps is None or \ len(parent_deps) < min_parent_deps: @@ -10076,6 +10108,9 @@ class Scheduler(PollScheduler): """ cpv_map = {} for pkg in self._mergelist: + if not isinstance(pkg, Package): + # a satisfied blocker + continue if pkg.installed: continue if pkg.cpv not in cpv_map: diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 60fe960d5..729bbd06f 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -3670,10 +3670,6 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks", if listonly: can_fetch = False - for var_name in ("FETCHCOMMAND", "RESUMECOMMAND"): - if not mysettings.get(var_name, None): - can_fetch = False - if can_fetch and not fetch_to_ro: global _userpriv_test_write_file_cache dirmode = 02070 @@ -3839,6 +3835,14 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks", pass if mystat is not None: + if stat.S_ISDIR(mystat.st_mode): + portage.util.writemsg_level( + ("!!! Unable to fetch file since " + \ + "a directory is in the way: \n" + \ + "!!! %s\n") % myfile_path, + level=logging.ERROR, noiselevel=-1) + return 0 + if mystat.st_size == 0: if distdir_writable: try: @@ -3988,14 +3992,56 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks", continue # allow different fetchcommands per protocol protocol = loc[0:loc.find("://")] - if "FETCHCOMMAND_" + protocol.upper() in mysettings: - fetchcommand=mysettings["FETCHCOMMAND_"+protocol.upper()] - else: - fetchcommand=mysettings["FETCHCOMMAND"] - if "RESUMECOMMAND_" + protocol.upper() in mysettings: - resumecommand=mysettings["RESUMECOMMAND_"+protocol.upper()] - else: - resumecommand=mysettings["RESUMECOMMAND"] + + missing_file_param = False + fetchcommand_var = "FETCHCOMMAND_" + protocol.upper() + fetchcommand = mysettings.get(fetchcommand_var) + if fetchcommand is None: + fetchcommand_var = "FETCHCOMMAND" + fetchcommand = mysettings.get(fetchcommand_var) + if fetchcommand is None: + portage.util.writemsg_level( + ("!!! %s is unset. It should " + \ + "have been defined in\n!!! %s/make.globals.\n") \ + % (fetchcommand_var, + portage.const.GLOBAL_CONFIG_PATH), + level=logging.ERROR, noiselevel=-1) + return 0 + if "${FILE}" not in fetchcommand: + portage.util.writemsg_level( + ("!!! %s does not contain the required ${FILE}" + \ + " parameter.\n") % fetchcommand_var, + level=logging.ERROR, noiselevel=-1) + missing_file_param = True + + resumecommand_var = "RESUMECOMMAND_" + protocol.upper() + resumecommand = mysettings.get(resumecommand_var) + if resumecommand is None: + resumecommand_var = "RESUMECOMMAND" + resumecommand = mysettings.get(resumecommand_var) + if resumecommand is None: + portage.util.writemsg_level( + ("!!! %s is unset. It should " + \ + "have been defined in\n!!! %s/make.globals.\n") \ + % (resumecommand_var, + portage.const.GLOBAL_CONFIG_PATH), + noiselevel=-1) + return 0 + if "${FILE}" not in resumecommand: + portage.util.writemsg_level( + ("!!! %s does not contain the required ${FILE}" + \ + " parameter.\n") % resumecommand_var, + level=logging.ERROR, noiselevel=-1) + missing_file_param = True + + if missing_file_param: + portage.util.writemsg_level( + "!!! Refer to the make.conf(5) man page for " + \ + "information about how to\n!!! correctly specify " + \ + "FETCHCOMMAND and RESUMECOMMAND.\n", + level=logging.ERROR, noiselevel=-1) + if myfile != os.path.basename(loc): + return 0 if not can_fetch: if fetched != 2: @@ -4016,11 +4062,6 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks", else: writemsg(("!!! File %s is incorrect size, " + \ "but unable to retry.\n") % myfile, noiselevel=-1) - for var_name in ("FETCHCOMMAND", "RESUMECOMMAND"): - if not mysettings.get(var_name, None): - writemsg(("!!! %s is unset. It should " + \ - "have been defined in /etc/make.globals.\n") \ - % var_name, noiselevel=-1) return 0 else: continue @@ -4051,9 +4092,11 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks", #resume mode: writemsg(">>> Resuming download...\n") locfetch=resumecommand + command_var = resumecommand_var else: #normal mode: locfetch=fetchcommand + command_var = fetchcommand_var writemsg_stdout(">>> Downloading '%s'\n" % \ re.sub(r'//(.+):.+@(.+)/',r'//\1:*password*@\2/', loc)) variables = { @@ -4101,6 +4144,25 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks", del e fetched = 0 else: + + if stat.S_ISDIR(mystat.st_mode): + # This can happen if FETCHCOMMAND erroneously + # contains wget's -P option where it should + # instead have -O. + portage.util.writemsg_level( + ("!!! The command specified in the " + \ + "%s variable appears to have\n!!! " + \ + "created a directory instead of a " + \ + "normal file.\n") % command_var, + level=logging.ERROR, noiselevel=-1) + portage.util.writemsg_level( + "!!! Refer to the make.conf(5) " + \ + "man page for information about how " + \ + "to\n!!! correctly specify " + \ + "FETCHCOMMAND and RESUMECOMMAND.\n", + level=logging.ERROR, noiselevel=-1) + return 0 + # no exception? file exists. let digestcheck() report # an appropriately for size or checksum errors @@ -4559,10 +4621,10 @@ def spawnebuild(mydo, actionmap, mysettings, debug, alwaysdep=0, eapi = mysettings["EAPI"] - if mydo == "configure" and eapi in ("0", "1", "2_pre1"): + if mydo == "configure" and eapi in ("0", "1"): return os.EX_OK - if mydo == "prepare" and eapi in ("0", "1", "2_pre1", "2_pre2"): + if mydo == "prepare" and eapi in ("0", "1"): return os.EX_OK kwargs = actionmap[mydo]["args"] @@ -4838,6 +4900,7 @@ def _spawn_misc_sh(mysettings, commands, **kwargs): eerror(l, phase=mydo, key=mysettings.mycpv) return rval +_testing_eapis = frozenset(["3_pre1"]) _deprecated_eapis = frozenset(["2_pre3", "2_pre2", "2_pre1"]) def _eapi_is_deprecated(eapi): @@ -4872,7 +4935,7 @@ def eapi_is_supported(eapi): eapi.remove(prop) # now check if what's left is supported (can) - properties = set(_deprecated_eapis) # another clumpsy solution + properties = set(_testing_eapis) # another clumpsy solution for i in range(portage.const.EAPI + 1): properties.add(str(i)) diff --git a/pym/repoman/checks.py b/pym/repoman/checks.py index e89020980..aee6d7c97 100644 --- a/pym/repoman/checks.py +++ b/pym/repoman/checks.py @@ -339,6 +339,15 @@ class WantAutoDefaultValue(LineCheck): return 'WANT_AUTO' + m.group(1) + \ ' redundantly set to default value "latest" on line: %d' +class PortageInternal(LineCheck): + """ + In February 2009 the Gentoo council ruled that + prepalldocs is a Portage internal. + """ + repoman_check_name = 'portage.internal' + re = re.compile(r'[^#]*\bprepalldocs\b') + error = errors.PREPALLDOCS_ERROR + _constant_checks = tuple((c() for c in ( EbuildHeader, EbuildWhitespace, EbuildQuote, EbuildAssignment, EbuildUselessDodoc, @@ -346,7 +355,7 @@ _constant_checks = tuple((c() for c in ( EbuildPatches, EbuildQuotedA, IUseUndefined, ImplicitRuntimeDeps, InheritAutotools, EMakeParallelDisabled, DeprecatedBindnowFlags, - WantAutoDefaultValue))) + WantAutoDefaultValue, PortageInternal))) def run_checks(contents, pkg): checks = _constant_checks diff --git a/pym/repoman/errors.py b/pym/repoman/errors.py index 7f45bea21..205913951 100644 --- a/pym/repoman/errors.py +++ b/pym/repoman/errors.py @@ -15,3 +15,4 @@ PATCHES_ERROR = 'PATCHES is not a bash array on line: %d' REDUNDANT_CD_S_ERROR = 'Ebuild has redundant cd ${S} statement on line: %d' EMAKE_PARALLEL_DISABLED = 'Upstream parallel compilation bug (ebuild calls emake -j1 on line: %d)' DEPRECATED_BINDNOW_FLAGS = 'Deprecated bindnow-flags call on line: %d' +PREPALLDOCS_ERROR = 'prepalldocs called on line: %d' -- 2.26.2