From: Fabian Groffen Date: Tue, 28 Oct 2008 18:51:42 +0000 (-0000) Subject: Merged from trunk -r11713:11724 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=2b5d73dbf53a8c4eac7d6a28a54f393433971c88;p=portage.git Merged from trunk -r11713:11724 | 11714 | Split dep validation out of doebuild() and skip it when | | zmedico | called by emerge since there's no need to do this every time | | | emerge executes a phase. | | 11715 | Bug #233296 - Add minimal PROPERTIES=interactive support by | | zmedico | simply forcing all package output to stdio whenever the | | | merge list contains one or more interactive packages. | | 11716 | Document PROPERTIES=interactive. | | zmedico | | | 11717 | Add a PROPERTIES.syntax check. | | zmedico | | | 11718 | Fix grammar. | | zmedico | | | 11719 | Bug #243224 - Add an exemption to the inherit.autotools | | zmedico | check for ebuilds that inherit git.eclass since the | | | GIT_BOOTSTRAP variable may be used to call one of autotools | | | functions. | | 11720 | Add "bzr" to the lists of live eclasses. | | zmedico | | | 11721 | Add "bzr" to the lists of live eclasses. | | zmedico | | | 11722 | Add "subversion" to InheritAutotools._exempt_eclasses. | | zmedico | Thanks to Arfrever. | | 11723 | When populating the fake $DISTDIR inside doebuild(), reuse | | zmedico | existing symlinks when possible, instead of recreating the | | | whole directory from scratch. | | 11724 | Fix preserve-libs code inside dblink.unmerge() so that it | | zmedico | will join paths correctly when ROOT != /. | svn path=/main/branches/prefix/; revision=11735 --- diff --git a/bin/repoman b/bin/repoman index 2ed9fc90f..a6c4553ac 100755 --- a/bin/repoman +++ b/bin/repoman @@ -289,6 +289,7 @@ qahelp={ "PDEPEND.syntax":"Syntax error in PDEPEND (usually an extra/missing space/parenthesis)", "LICENSE.syntax":"Syntax error in LICENSE (usually an extra/missing space/parenthesis)", "PROVIDE.syntax":"Syntax error in PROVIDE (usually an extra/missing space/parenthesis)", + "PROPERTIES.syntax":"Syntax error in PROPERTIES (usually an extra/missing space/parenthesis)", "RESTRICT.syntax":"Syntax error in RESTRICT (usually an extra/missing space/parenthesis)", "SRC_URI.syntax":"Syntax error in SRC_URI (usually an extra/missing space/parenthesis)", "SRC_URI.mirror":"A uri listed in profiles/thirdpartymirrors is found in SRC_URI", @@ -375,6 +376,7 @@ valid_restrict = frozenset(["binchecks", "bindist", "primaryuri", "strip", "test", "userpriv"]) live_eclasses = frozenset([ + "bzr", "cvs", "darcs", "git", @@ -1230,7 +1232,8 @@ for x in scanlist: "java-pkg-opt-2" in inherited operator_tokens = set(["||", "(", ")"]) type_list, badsyntax = [], [] - for mytype in ("DEPEND", "RDEPEND", "PDEPEND", "LICENSE", "PROVIDE"): + for mytype in ("DEPEND", "RDEPEND", "PDEPEND", + "LICENSE", "PROPERTIES", "PROVIDE"): mydepstr = myaux[mytype] if mydepstr.find(" ?") != -1: diff --git a/cnf/sets.conf b/cnf/sets.conf index f9f351be8..dd2ccb410 100644 --- a/cnf/sets.conf +++ b/cnf/sets.conf @@ -51,7 +51,7 @@ world-candidate = False class = portage.sets.dbapi.VariableSet world-candidate = False variable = INHERITED -includes = cvs darcs git mercurial subversion +includes = bzr cvs darcs git mercurial subversion # Installed packages that own files inside /lib/modules. [module-rebuild] diff --git a/man/ebuild.5 b/man/ebuild.5 index ef5f2136e..0235f7be2 100644 --- a/man/ebuild.5 +++ b/man/ebuild.5 @@ -401,6 +401,16 @@ Disables userpriv for specific packages. .RE .PD 1 .TP +\fBPROPERTIES\fR = \fI[interactive]\fR +A space delimited list of properties, with conditional syntax support. +.PD 0 +.RS +.TP +.I interactive +One or more ebuild phases will produce a prompt that requires user interaction. +.RE +.PD 1 +.TP \fBPROVIDE\fR = \fI"virtual/TARGET"\fR This variable should only be used when a package provides a virtual target. For example, blackdown\-jdk and sun\-jdk provide \fIvirtual/jdk\fR. This diff --git a/man/repoman.1 b/man/repoman.1 index dc9cb30e2..a4a92a731 100644 --- a/man/repoman.1 +++ b/man/repoman.1 @@ -177,6 +177,12 @@ RDEPEND contains a package that usually only belongs in DEPEND .B RDEPEND.syntax Syntax error in RDEPEND (usually an extra/missing space/parenthesis) .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) +.TP .B SLOT.missing Ebuilds that have a missing or empty SLOT variable .TP diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 6837cf0fa..82e08cef4 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -2702,6 +2702,7 @@ class EbuildExecuter(CompositeTask): _phases = ("prepare", "configure", "compile", "test", "install") _live_eclasses = frozenset([ + "bzr", "cvs", "darcs", "git", @@ -9237,6 +9238,28 @@ class Scheduler(PollScheduler): self._max_jobs > 1 or "--quiet" in self.myopts) and \ not bool(self._opts_no_background.intersection(self.myopts)) + if background: + interactive_tasks = self._get_interactive_tasks() + if interactive_tasks: + background = False + writemsg_level(">>> Sending package output to stdio due " + \ + "to interactive package(s):\n", + level=logging.INFO, noiselevel=-1) + msg = [""] + for pkg in interactive_tasks: + pkg_str = " " + colorize("INFORM", str(pkg.cpv)) + if pkg.root != "/": + pkg_str += " for " + pkg.root + msg.append(pkg_str) + msg.append("") + writemsg_level("".join("%s\n" % (l,) for l in msg), + level=logging.INFO, noiselevel=-1) + if self._max_jobs is True or self._max_jobs > 1: + self._set_max_jobs(1) + writemsg_level(">>> Setting --jobs=1 due " + \ + "to the above interactive package(s)\n", + level=logging.INFO, noiselevel=-1) + self._status_display.quiet = \ not background or \ ("--quiet" in self.myopts and \ @@ -9248,6 +9271,20 @@ class Scheduler(PollScheduler): return background + def _get_interactive_tasks(self): + from portage import flatten + from portage.dep import use_reduce, paren_reduce + interactive_tasks = [] + for task in self._mergelist: + if not (isinstance(task, Package) and \ + task.operation == "merge"): + continue + properties = flatten(use_reduce(paren_reduce( + task.metadata["PROPERTIES"]), uselist=task.use.enabled)) + if "interactive" in properties: + interactive_tasks.append(task) + return interactive_tasks + def _set_digraph(self, digraph): if self._max_jobs is not True and \ self._max_jobs < 2: diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 2f6712d21..575a59511 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -5427,46 +5427,13 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, droppriv=droppriv) # Validate dependency metadata here to ensure that ebuilds with invalid - # data are never installed (even via the ebuild command). - invalid_dep_exempt_phases = \ - set(["clean", "cleanrm", "help", "prerm", "postrm"]) - mycpv = mysettings["CATEGORY"] + "/" + mysettings["PF"] - dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"] - misc_keys = ["LICENSE", "PROPERTIES", "PROVIDE", "RESTRICT", "SRC_URI"] - other_keys = ["SLOT"] - all_keys = dep_keys + misc_keys + other_keys - metadata = dict(izip(all_keys, mydbapi.aux_get(mycpv, all_keys))) - class FakeTree(object): - def __init__(self, mydb): - self.dbapi = mydb - dep_check_trees = {myroot:{}} - dep_check_trees[myroot]["porttree"] = \ - FakeTree(fakedbapi(settings=mysettings)) - for dep_type in dep_keys: - mycheck = dep_check(metadata[dep_type], None, mysettings, - myuse="all", myroot=myroot, trees=dep_check_trees) - if not mycheck[0]: - writemsg("%s: %s\n%s\n" % ( - dep_type, metadata[dep_type], mycheck[1]), noiselevel=-1) - if mydo not in invalid_dep_exempt_phases: - return 1 - del dep_type, mycheck - for k in misc_keys: - try: - portage.dep.use_reduce( - portage.dep.paren_reduce(metadata[k]), matchall=True) - except portage.exception.InvalidDependString, e: - writemsg("%s: %s\n%s\n" % ( - k, metadata[k], str(e)), noiselevel=-1) - del e - if mydo not in invalid_dep_exempt_phases: - return 1 - del k - if not metadata["SLOT"]: - writemsg("SLOT is undefined\n", noiselevel=-1) - if mydo not in invalid_dep_exempt_phases: - return 1 - del mycpv, dep_keys, metadata, misc_keys, FakeTree, dep_check_trees + # data are never installed via the ebuild command. Don't bother when + # returnpid == True since there's no need to do this every time emerge + # executes a phase. + if not returnpid: + rval = _validate_deps(mysettings, myroot, mydo, mydbapi) + if rval != os.EX_OK: + return rval if "PORTAGE_TMPDIR" not in mysettings or \ not os.path.isdir(mysettings["PORTAGE_TMPDIR"]): @@ -5737,24 +5704,31 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, mysettings["PORTAGE_ACTUAL_DISTDIR"] = orig_distdir edpath = mysettings["DISTDIR"] = \ os.path.join(mysettings["PORTAGE_BUILDDIR"], "distdir") - if os.path.exists(edpath): + portage.util.ensure_dirs(edpath, uid=portage_uid, mode=0755) + + # Remove any unexpected files or directories. + for x in os.listdir(edpath): + symlink_path = os.path.join(edpath, x) + st = os.lstat(symlink_path) + if x in alist and stat.S_ISLNK(st.st_mode): + continue + if stat.S_ISDIR(st.st_mode): + shutil.rmtree(symlink_path) + else: + os.unlink(symlink_path) + + # Check for existing symlinks and recreate if necessary. + for x in alist: + symlink_path = os.path.join(edpath, x) + target = os.path.join(orig_distdir, x) try: - if os.path.isdir(edpath) and not os.path.islink(edpath): - shutil.rmtree(edpath) - else: - os.unlink(edpath) + link_target = os.readlink(symlink_path) except OSError: - print "!!! Failed reseting ebuild distdir path, " + edpath - raise - os.mkdir(edpath) - apply_secpass_permissions(edpath, uid=portage_uid, mode=0755) - try: - for file in alist: - os.symlink(os.path.join(orig_distdir, file), - os.path.join(edpath, file)) - except OSError: - print "!!! Failed symlinking in '%s' to ebuild distdir" % file - raise + os.symlink(target, symlink_path) + else: + if link_target != target: + os.unlink(symlink_path) + os.symlink(target, symlink_path) #initial dep checks complete; time to process main commands @@ -5879,6 +5853,50 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, # and the exemption is no longer needed. _doebuild_manifest_exempt_depend -= 1 +def _validate_deps(mysettings, myroot, mydo, mydbapi): + + invalid_dep_exempt_phases = \ + set(["clean", "cleanrm", "help", "prerm", "postrm"]) + dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"] + misc_keys = ["LICENSE", "PROPERTIES", "PROVIDE", "RESTRICT", "SRC_URI"] + other_keys = ["SLOT"] + all_keys = dep_keys + misc_keys + other_keys + metadata = dict(izip(all_keys, + mydbapi.aux_get(mysettings.mycpv, all_keys))) + + class FakeTree(object): + def __init__(self, mydb): + self.dbapi = mydb + dep_check_trees = {myroot:{}} + dep_check_trees[myroot]["porttree"] = \ + FakeTree(fakedbapi(settings=mysettings)) + + for dep_type in dep_keys: + mycheck = dep_check(metadata[dep_type], None, mysettings, + myuse="all", myroot=myroot, trees=dep_check_trees) + if not mycheck[0]: + writemsg("%s: %s\n%s\n" % ( + dep_type, metadata[dep_type], mycheck[1]), noiselevel=-1) + if mydo not in invalid_dep_exempt_phases: + return 1 + + for k in misc_keys: + try: + portage.dep.use_reduce( + portage.dep.paren_reduce(metadata[k]), matchall=True) + except portage.exception.InvalidDependString, e: + writemsg("%s: %s\n%s\n" % ( + k, metadata[k], str(e)), noiselevel=-1) + if mydo not in invalid_dep_exempt_phases: + return 1 + + if not metadata["SLOT"]: + writemsg("SLOT is undefined\n", noiselevel=-1) + if mydo not in invalid_dep_exempt_phases: + return 1 + + return os.EX_OK + expandcache={} def _movefile(src, dest, **kwargs): diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 078503e7d..996fa517b 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -2373,6 +2373,8 @@ class dblink(object): # their real target before the object is found not to be # in the reverse NEEDED map def symlink_compare(x, y): + x = os.path.join(self.myroot, x.lstrip(os.path.sep)) + y = os.path.join(self.myroot, y.lstrip(os.path.sep)) if os.path.islink(x): if os.path.islink(y): return 0 @@ -2385,20 +2387,23 @@ class dblink(object): plib_dict[cpv].sort(symlink_compare) for f in plib_dict[cpv]: - if not os.path.exists(f): + f_abs = os.path.join(self.myroot, f.lstrip(os.path.sep)) + if not os.path.exists(f_abs): continue unlink_list = [] consumers = self.vartree.dbapi.linkmap.findConsumers(f) if not consumers: - unlink_list.append(f) + unlink_list.append(f_abs) else: keep=False for c in consumers: + c = os.path.join(self.myroot, + c.lstrip(os.path.sep)) if c not in self.getcontents(): keep=True break if not keep: - unlink_list.append(f) + unlink_list.append(f_abs) for obj in unlink_list: try: if os.path.islink(obj): diff --git a/pym/repoman/checks.py b/pym/repoman/checks.py index f4a7733a0..dd81d8716 100644 --- a/pym/repoman/checks.py +++ b/pym/repoman/checks.py @@ -232,12 +232,21 @@ class InheritAutotools(LineCheck): "eautomake", "eautoreconf", "_elibtoolize") _autotools_func_re = re.compile(r'(^|\s)(' + \ "|".join(_autotools_funcs) + ')(\s|$)') + # 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 = frozenset(["git", "subversion"]) def new(self, pkg): self._inherit_autotools = None self._autotools_func_call = None + self._disabled = self._exempt_eclasses.intersection(pkg.inherited) def check(self, num, line): + if self._disabled: + return if self._inherit_autotools is None: self._inherit_autotools = self._inherit_autotools_re.match(line) if self._inherit_autotools is not None and \