From b4aeacb91dab10f6e0d180e8a6cd5e2581a40c0d Mon Sep 17 00:00:00 2001 From: Kito Date: Mon, 27 Feb 2006 16:55:56 +0000 Subject: [PATCH] merge with trunk rev 2719:2794 svn path=/main/branches/prefix/; revision=2795 --- NEWS | 5 + RELEASE-NOTES | 7 + bin/doman | 41 +- bin/ebuild | 4 + bin/ebuild.sh | 2 +- bin/emerge | 109 +--- bin/prepallman | 4 +- bin/prepallstrip | 8 - bin/prepman | 29 +- bin/repoman | 16 +- cnf/make.conf | 3 + cnf/make.conf.alpha | 3 + cnf/make.conf.amd64 | 3 + cnf/make.conf.arm | 3 + cnf/make.conf.hppa | 3 + cnf/make.conf.ia64 | 3 + cnf/make.conf.mips | 3 + cnf/make.conf.ppc | 3 + cnf/make.conf.ppc64 | 3 + cnf/make.conf.s390 | 3 + cnf/make.conf.sparc | 3 + cnf/make.conf.x86 | 3 + cnf/make.conf.x86-fbsd | 3 + cnf/make.globals | 2 +- man/emerge.1 | 15 - man/make.conf.5 | 3 + pym/cache/flat_hash.py | 2 +- pym/cache/metadata.py | 2 +- pym/cache/metadata_overlay.py | 91 +++ pym/cache/template.py | 2 +- pym/emergehelp.py | 6 +- pym/output.py | 18 +- pym/portage.py | 378 +++++------ pym/portage_exception.py | 6 +- pym/portage_locks.py | 3 +- pym/portage_update.py | 46 ++ pym/xpak.py | 89 ++- qa/iuse/iuse.sh | 20 - qa/iuse/iuse2.py | 58 -- spec/emerge.syntax | 1149 --------------------------------- 40 files changed, 531 insertions(+), 1623 deletions(-) create mode 100644 pym/cache/metadata_overlay.py create mode 100644 pym/portage_update.py delete mode 100644 qa/iuse/iuse.sh delete mode 100755 qa/iuse/iuse2.py delete mode 100755 spec/emerge.syntax diff --git a/NEWS b/NEWS index 7503e007b..559e8415c 100644 --- a/NEWS +++ b/NEWS @@ -29,3 +29,8 @@ portage-2.1 (ongoing via pre releases) * Ebuild output is no longer cut off early when using PORT_LOGDIR. * Distfiles indirection- $DISTFILES access goes through a tmp dir to fail access to files not listed in SRC_URI. +* Emerge now uses --resume to restart itself after portage upgrade. +* Atomic file updates via the new atomic_ofstream class. +* Global updates and fixpackages performance optimizations. +* Tests show that file locking is now more reliable. +* A bash call stack is printed when an ebuild dies in ebuild.sh. diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 29dbd6f48..4a2747f5d 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -9,3 +9,10 @@ portage-2.1 * USE flag output ordering has changed. The old ordering is now an option by the name of --alphabetical. Adding the option to EMERGE_DEFAULT_OPTS in make.conf will restore the old behaviour permanently. +* The deprecated --inject has been removed, use /etc/portage/profile/package.provided +* The deprecated --upgradeonly has been removed, use /etc/portage/package.* + instead. +* 'emerge sync' has been deprecated, use 'emerge --sync' instead (same + for other actions) +* Tools that call emerge should override the EMERGE_DEFAULT_OPTS environment + variable or use the emerge --ignore-default-opts option. diff --git a/bin/doman b/bin/doman index 8fb66d2b1..665e7fdc2 100755 --- a/bin/doman +++ b/bin/doman @@ -3,51 +3,50 @@ # Distributed under the terms of the GNU General Public License v2 # $Id: /var/cvsroot/gentoo-src/portage/bin/doman,v 1.13.2.2 2005/07/29 05:55:34 vapier Exp $ -if [ $# -lt 1 ] ; then +if [[ $# -lt 1 ]] ; then echo "$0: at least one argument needed" 1>&2 exit 1 fi -BASE="/usr/share" i18n="" +ret=0 + for x in "$@" ; do - if [ "${x:0:6}" == "-i18n=" ] ; then - i18n="${x:6}/" + if [[ ${x:0:6} == "-i18n=" ]] ; then + i18n=${x:6}/ continue fi - if [ "${x}" == ".keep" ] ; then + if [[ ${x} == ".keep" ]] ; then continue fi suffix=${x##*.} - if [ "$suffix" == "gz" ] ; then - compressed="gz" - realname="${x%.*}" - suffix="${realname##*.}" - else - realname="$x" - compressed="" + if [[ ${suffix} == "gz" ]] ; then + realname=${x%.*} + suffix=${realname##*.} + echo "QA Notice: you should let portage compress '${realname}' for you" 2>&1 fi mandir=${i18n}man${suffix:0:1} if echo ${mandir} | @EGREP@ -q 'man[0-9n](|f|p|pm)$' -; then - if [ -s "${x}" ] ; then - if [ ! -d "${D}${BASE}/man/${mandir}" ] ; then - install -d "${D}${BASE}/man/${mandir}" + if [[ -s ${x} ]] ; then + if [[ ! -d ${D}/usr/share/man/${mandir} ]] ; then + install -d "${D}/usr/share/man/${mandir}" fi - install -m0644 "${x}" "${D}${BASE}/man/${mandir}" - - if [ -z "${compressed}" ] ; then - gzip -f -9 "${D}${BASE}/man/${mandir}/${x##*/}" - fi - else + install -m0644 "${x}" "${D}/usr/share/man/${mandir}" + ((ret+=$?)) + elif [[ ! -e ${x} ]] ; then echo "doman: ${x} does not exist" 1>&2 + ((++ret)) fi else echo "doman: '${x}' is probably not a man page; skipping" 1>&2 + ((++ret)) fi done + +exit ${ret} diff --git a/bin/ebuild b/bin/ebuild index ff6f740a6..b6b124e46 100755 --- a/bin/ebuild +++ b/bin/ebuild @@ -25,6 +25,10 @@ sys.path = ["@PORTAGE_BASE@/pym"]+sys.path import portage, portage_util, portage_const +if portage.settings["NOCOLOR"] in ("yes","true") or not sys.stdout.isatty(): + import output + output.nocolor() + ebuild = os.path.realpath(pargs.pop(0)) if not os.path.exists(ebuild): diff --git a/bin/ebuild.sh b/bin/ebuild.sh index 5480dbb9a..69917e7ff 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -1274,7 +1274,7 @@ dyn_install() { # are supported at the moment. Keep this list in sync with # http://hardened.gentoo.org/gnu-stack.xml (Arch Status) case ${CTARGET:-${CHOST}} in - i?86*|ia64*|m68k*|s390*|x86_64*) + i?86*|ia64*|m68k*|powerpc64*|s390*|x86_64*) f=$(scanelf -qyRF '%e %p' "${D}") ;; *) f="" ;; diff --git a/bin/emerge b/bin/emerge index 66fd56c9e..799c4c493 100755 --- a/bin/emerge +++ b/bin/emerge @@ -169,8 +169,8 @@ merged=0 params=["selective", "deep", "self", "recurse", "empty"] actions=[ "clean", "config", "depclean", -"info", "inject", "metadata", -"prune", "regen", "rsync", "search", +"info", "metadata", +"prune", "regen", "search", "sync", "system", "unmerge", "world", ] options=[ @@ -192,7 +192,7 @@ options=[ "--searchdesc", "--selective", "--skipfirst", "--skip-first", "--tree", -"--update", "--upgradeonly", +"--update", "--usepkg", "--usepkgonly", "--verbose", "--version" ] @@ -207,7 +207,6 @@ shortmapping={ "f":"--fetchonly", "F":"--fetch-all-uri", "g":"--getbinpkg", "G":"--getbinpkgonly", "h":"--help", -"i":"--inject", "k":"--usepkg", "K":"--usepkgonly", "l":"--changelog", "n":"--noreplace", "N":"--newuse", @@ -216,7 +215,7 @@ shortmapping={ "q":"--quiet", "s":"--search", "S":"--searchdesc", 't':"--tree", -"u":"--update", "U":"--upgradeonly", +"u":"--update", "v":"--verbose", "V":"--version" } @@ -255,15 +254,9 @@ for x in cmdline: elif x == "--skip-first": x = "--skipfirst" if x in options: - myopts.append(x) + if x not in myopts: + myopts.append(x) elif x[2:] in actions: - if x[2:]=="rsync" or x=="rsync": - # "emerge --rsync" - print - print red("*** '--rsync' has been deprecated.") - print red("*** Please use '--sync' instead.") - print - x="--sync" if myaction: if myaction not in ["system", "world"]: myaction="--"+myaction @@ -278,15 +271,7 @@ for x in cmdline: sys.exit(1) elif (not myaction) and (x in actions): if x not in ["system", "world"]: - #print red("*** Deprecated use of action '"+x+"'") - if x=="rsync": - # "emerge rsync" - print - print red("*** 'rsync' will now install the package rsync.") - print red("*** To sync the tree, please use '--sync' instead.") - print - myfiles.append(x) - continue + print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x)) if myaction: print print red("!!!")+green(" Multiple actions requested... Please choose one only.") @@ -383,17 +368,6 @@ if ("--newuse" in myopts) and not ("--update" in myopts): print ">>> --newuse implies --update... adding --update to options." myopts.append("--update") -# Print deprecation warning for -U -if ("--upgradeonly" in myopts): - print - print red("*** Warning: --upgradeonly is a deprecated option in portage-"+portage.VERSION) - print red("*** and will likely be removed in a future version.") - print - # Also allow -U to apply --update/-u - if not ("--update" in myopts): - print ">>> --upgradeonly implies --update... adding --update to options." - myopts.append("--update") - # Also allow -l to apply --pretend/-p, but if already in --ask mode if ("--changelog" in myopts) and not (("--pretend" in myopts) or ("--ask" in myopts)): print ">>> --changelog implies --pretend... adding --pretend to options." @@ -447,17 +421,6 @@ if portage.settings["CLEAN_DELAY"]: if portage.settings["EMERGE_WARNING_DELAY"]: EMERGE_WARNING_DELAY = string.atoi("0"+portage.settings["EMERGE_WARNING_DELAY"]) -if "inject" == myaction: - print - print red("*** --inject has been deprecated.") - print red("*** If you manage a piece of software yourself, add it's name and") - print red("*** version (eg foo/bar-1.0) to /etc/portage/profile/package.provided.") - print red("*** If you want to prevent portage from upgrading a package, add it to") - print red("*** /etc/portage/package.mask prepending it with '>' (eg >foo/bar-1.0)") - print red("*** For more information on fine-grained portage control, please see") - print red("*** the portage man page.") - print - def emergelog(mystr,short_msg=None): if "notitles" not in portage.features: if short_msg: @@ -1330,26 +1293,6 @@ class depgraph: else: myeb_pkg = None - if "--upgradeonly" in myopts: - # Check that there isn't a newer version of this package already installed - cand = None - try: - # XXX: This can throw an exception if the ebuild doesn't exist - if myeb: - cand=self.is_newer_ver_installed(myroot,x,myeb) - elif myeb_pkg: - cand=self.is_newer_ver_installed(myroot,x,myeb_pkg) - except SystemExit, e: - raise # Needed else can't exit - except Exception, e: - print "Warning: "+str(e) - if cand: - # --newuse can't work because the installed version isn't available - # just pretend like the package doesn't matter - # XXX: hidden assumption here that the higher versioned package - # satisfies the atom that was given - continue - if myeb: myk=["ebuild",myroot,myeb] elif myeb_pkg: @@ -1983,7 +1926,7 @@ class depgraph: y=portage.portdb.findname(x[pkgindex]) if not "--pretend" in myopts: print ">>> Emerging ("+str(mergecount)+" of "+str(len(mymergelist))+")",x[pkgindex],"to",x[1] - emergelog(" >>> Emerging ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" to "+x[1]) + emergelog(" >>> emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" to "+x[1]) self.pkgsettings["EMERGE_FROM"] = x[0][:] self.pkgsettings.backup_changes("EMERGE_FROM") @@ -2515,7 +2458,7 @@ def chk_updated_cfg_files(): if "--debug" in myopts: edebug=1 -if myaction in ["sync","rsync","metadata"] and (not "--help" in myopts): +if myaction in ["sync","metadata"] and (not "--help" in myopts): if "--pretend" in myopts: print "emerge: \"sync\" actions do not support \"--pretend.\"" sys.exit(1) @@ -2774,6 +2717,11 @@ if myaction in ["sync","rsync","metadata"] and (not "--help" in myopts): except: pass + if updatecache_flg and \ + myaction != "metadata" and \ + "metadata-transfer" not in portage.settings.features: + updatecache_flg = False + if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg: if "--quiet" not in myopts: print "\n>>> Updating Portage cache: ", @@ -3061,35 +3009,6 @@ elif "search"==myaction: print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment ) sys.exit(1) searchinstance.output() -elif "inject"==myaction: - if not myfiles: - print "emerge: please specify at least one cat/pkg-ver to inject." - sys.exit(1) - if "--pretend" in myopts: - print "emerge: the \"inject\" action does not support \"--pretend.\"" - sys.exit(1) - for x in myfiles: - if x[0] in [">","<","=","!"]: - print "!!! '"+x+"' is an invalid specification." - print "!!! Must be 'category/package-version' with no other symbols." - print - continue - mycps=portage.catpkgsplit(x) - if (not mycps) or (mycps[0]=="null"): - print "!!!",x,"is not a specific cat/pkg-version, skipping..." - continue - if portage.db["/"]["vartree"].exists_specific(x): - print "!!! Not injecting",x+"; Package already exists." - else: - if "--ask" in myopts: - if userquery("Do you want to inject the package %s?" % x)=="No": - print - print "Quitting." - print - sys.exit(0) - portage.db["/"]["vartree"].dbapi.cpv_inject(x) - print ">>> Injected",x+"." - emergelog(" === inject: "+x) elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction: if 1==unmerge(myaction, myfiles): post_emerge() diff --git a/bin/prepallman b/bin/prepallman index f9235ce68..c9857d328 100755 --- a/bin/prepallman +++ b/bin/prepallman @@ -8,7 +8,9 @@ ret=0 echo "man:" for x in "${D}"/opt/*/man "${D}"/usr/share/man "${D}"/usr/local/man "${D}"/usr/X11R6/man ; do if [[ -d ${x} ]] ; then - prepman "`echo "${x}" | sed -e "s:${D}::" -e "s:/man[/]*$::"`" + x=${x#${D}} + x=${x%/man} + prepman "${x}" ((ret+=$?)) fi done diff --git a/bin/prepallstrip b/bin/prepallstrip index e1958a58c..3a89b96ff 100755 --- a/bin/prepallstrip +++ b/bin/prepallstrip @@ -3,12 +3,4 @@ # Distributed under the terms of the GNU General Public License v2 # $Id: /var/cvsroot/gentoo-src/portage/bin/prepallstrip,v 1.12 2004/10/04 13:56:50 vapier Exp $ -if [[ " ${FEATURES} " == *" nostrip "* ]] || \ - [[ " ${RESTRICT} " == *" nostrip "* ]] || \ - [[ " ${RESTRICT} " == *" strip "* ]] -then - exit 0 -fi - -echo "prepallstrip:" exec prepstrip "${D}" diff --git a/bin/prepman b/bin/prepman index f40cfccef..03327aeb5 100755 --- a/bin/prepman +++ b/bin/prepman @@ -3,41 +3,44 @@ # Distributed under the terms of the GNU General Public License v2 # $Id: /var/cvsroot/gentoo-src/portage/bin/prepman,v 1.10.2.3 2005/05/29 12:40:08 jstubbs Exp $ -if [ -z "$1" ] ; then +if [[ -z $1 ]] ; then z="${D}/usr/share/man" else z="${D}$1/man" fi -[ ! -d "${z}" ] && exit 0 +if [[ ! -d ${z} ]] ; then + echo "QA Notice: prepman called with non-existent dir '${z#${D}}'" 2>&1 + exit 0 +fi -for x in `find "${z}"/ -type d 2>/dev/null` ; do - for y in `find "${x}"/ -mindepth 1 -maxdepth 1 \( -type f -or -type l \) ! -name '.keep' 2>/dev/null` ; do - if [ -L "${y}" ] ; then +for x in $(find "${z}"/ -type d 2>/dev/null) ; do + for y in $(find "${x}"/ -mindepth 1 -maxdepth 1 \( -type f -or -type l \) ! -name '.keep' 2>/dev/null) ; do + if [[ -L ${y} ]] ; then # Symlink ... - mylink="${y}" - linkto="`readlink "${y}"`" + mylink=${y} + linkto=$(readlink "${y}") # Do NOT change links to directories - if [ -d "${z}/${linkto}" ] ; then + if [[ -d ${z}/${linkto} ]] ; then continue fi - - if [ "${linkto##*.}" != "gz" ] && [ "${linkto##*.}" != "bz2" ]; then + + if [[ ${linkto##*.} != "gz" ]] && [[ ${linkto##*.} != "bz2" ]] ; then linkto="${linkto}.gz" fi - if [ "${mylink##*.}" != "gz" ] && [ "${mylink##*.}" != "bz2" ]; then + if [[ ${mylink##*.} != "gz" ]] && [[ ${mylink##*.} != "bz2" ]] ; then mylink="${mylink}.gz" fi echo "fixing man page symlink: ${mylink##*/}" ln -snf "${linkto}" "${mylink}" - if [ "${y}" != "${mylink}" ] ; then + if [[ ${y} != "${mylink}" ]] ; then echo "removing old symlink: ${y##*/}" rm -f "${y}" fi else - if [ "${y##*.}" != "gz" ] && [ "${y##*.}" != "bz2" ] && [ ! -d "${y}" ]; then + if [[ ${y##*.} != "gz" ]] && [[ ${y##*.} != "bz2" ]] && [[ ! -d ${y} ]] ; then echo "gzipping man page: ${y##*/}" gzip -f -9 "${y}" fi diff --git a/bin/repoman b/bin/repoman index 7d15cb3f4..e7aae73e7 100755 --- a/bin/repoman +++ b/bin/repoman @@ -47,6 +47,7 @@ def warn(txt): def err(txt): warn(txt) sys.exit(1) + def err_help(txt): help(exitstatus=-1,helpfulness=0) warn(txt) @@ -204,10 +205,6 @@ for x in missingvars: qawarnings.append(x) -def err(txt): - print exename+": "+txt - sys.exit(1) - ven_cat = r'[\w0-9-]+' # Category ven_nam = r'([+a-z0-9-]+(?:[+_a-z0-9-]*[+a-z0-9-]+)*)' # Name ven_ver = r'((?:\d+\.)*\d+[a-z]?)' # Version @@ -238,6 +235,7 @@ def valid_ebuild_name(name): def show_version(): print exename+" "+version sys.exit(0) + def help(exitstatus=1,helpfulness=1): if quiet: helpfulness=0 @@ -1021,7 +1019,7 @@ for x in scanlist: fails["ebuild.namenomatch"].append(x+"/"+y+".ebuild") continue try: - myaux=portage.db["/"]["porttree"].dbapi.aux_get(catdir+"/"+y,allvars) + myaux = dict( zip(allvars, portage.db["/"]["porttree"].dbapi.aux_get(catdir+"/"+y, allvars ) ) ) except KeyError: stats["ebuild.syntax"]=stats["ebuild.syntax"]+1 fails["ebuild.syntax"].append(x+"/"+y+".ebuild") @@ -1031,14 +1029,6 @@ for x in scanlist: fails["ebuild.output"].append(x+"/"+y+".ebuild") continue - mynewaux = {} - for idx in range(len(allvars)): - if idx < len(myaux): - mynewaux[allvars[idx]] = myaux[idx] - else: - mynewaux[allvars[idx]] = "" - myaux = mynewaux - # Test for negative logic and bad words in the RESTRICT var. #for x in myaux[allvars.index("RESTRICT")].split(): # if x.startswith("no"): diff --git a/cnf/make.conf b/cnf/make.conf index 0e9388fe0..67af62b10 100644 --- a/cnf/make.conf +++ b/cnf/make.conf @@ -290,6 +290,9 @@ CHOST="i686-pc-linux-gnu" # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.conf.alpha b/cnf/make.conf.alpha index ece799831..9f1d9f162 100644 --- a/cnf/make.conf.alpha +++ b/cnf/make.conf.alpha @@ -276,6 +276,9 @@ CFLAGS="-mcpu=ev5 -O3 -pipe " # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.conf.amd64 b/cnf/make.conf.amd64 index f5ee4b048..0d084cc54 100644 --- a/cnf/make.conf.amd64 +++ b/cnf/make.conf.amd64 @@ -287,6 +287,9 @@ CHOST="x86_64-pc-linux-gnu" # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.conf.arm b/cnf/make.conf.arm index 1c1c6c20f..b725b8d25 100644 --- a/cnf/make.conf.arm +++ b/cnf/make.conf.arm @@ -284,6 +284,9 @@ CHOST="armv4l-unknown-linux-gnu" # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.conf.hppa b/cnf/make.conf.hppa index eb526e65f..3dc0a2c09 100644 --- a/cnf/make.conf.hppa +++ b/cnf/make.conf.hppa @@ -293,6 +293,9 @@ CHOST="hppa-unknown-linux-gnu" # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.conf.ia64 b/cnf/make.conf.ia64 index 3f6808b83..9aa4e5a82 100644 --- a/cnf/make.conf.ia64 +++ b/cnf/make.conf.ia64 @@ -255,6 +255,9 @@ CHOST="ia64-unknown-linux-gnu" # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.conf.mips b/cnf/make.conf.mips index dc71e3309..b96e3c8d7 100644 --- a/cnf/make.conf.mips +++ b/cnf/make.conf.mips @@ -273,6 +273,9 @@ CHOST="mips-unknown-linux-gnu" # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.conf.ppc b/cnf/make.conf.ppc index 6c38b1028..345088146 100644 --- a/cnf/make.conf.ppc +++ b/cnf/make.conf.ppc @@ -313,6 +313,9 @@ CHOST="powerpc-unknown-linux-gnu" # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.conf.ppc64 b/cnf/make.conf.ppc64 index a636928a7..64f4f7631 100644 --- a/cnf/make.conf.ppc64 +++ b/cnf/make.conf.ppc64 @@ -291,6 +291,9 @@ CHOST="powerpc64-unknown-linux-gnu" # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.conf.s390 b/cnf/make.conf.s390 index fe2f8bcce..cb570c799 100644 --- a/cnf/make.conf.s390 +++ b/cnf/make.conf.s390 @@ -255,6 +255,9 @@ CHOST="s390-ibm-linux-gnu" # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.conf.sparc b/cnf/make.conf.sparc index f58ba4bb6..0784f8091 100644 --- a/cnf/make.conf.sparc +++ b/cnf/make.conf.sparc @@ -291,6 +291,9 @@ # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.conf.x86 b/cnf/make.conf.x86 index 98ba6a957..37813afae 100644 --- a/cnf/make.conf.x86 +++ b/cnf/make.conf.x86 @@ -290,6 +290,9 @@ CHOST="i686-pc-linux-gnu" # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.conf.x86-fbsd b/cnf/make.conf.x86-fbsd index 1149e4161..64be779a2 100644 --- a/cnf/make.conf.x86-fbsd +++ b/cnf/make.conf.x86-fbsd @@ -278,6 +278,9 @@ CHOST="i686-unknown-freebsd5.3" # 'keepwork' prevents the clean phase from deleting the WORKDIR. # 'test' causes ebuilds to perform testing phases if they are capable # of it. Some packages support this automaticaly via makefiles. +# 'metadata-transfer' +# automatically perform a metadata transfer when `emerge --sync` +# is run. # 'noauto' causes ebuild to perform only the action requested and # not any other required actions like clean or unpack -- for # debugging purposes only. diff --git a/cnf/make.globals b/cnf/make.globals index c6e79b1c3..7c29d0230 100644 --- a/cnf/make.globals +++ b/cnf/make.globals @@ -33,7 +33,7 @@ FETCHCOMMAND="/usr/bin/wget -t 5 --passive-ftp -P \${DISTDIR} \${URI}" RESUMECOMMAND="/usr/bin/wget -c -t 5 --passive-ftp -P \${DISTDIR} \${URI}" # Default user options -FEATURES="sandbox distlocks" +FEATURES="sandbox distlocks metadata-transfer" # Default chunksize for binhost comms PORTAGE_BINHOST_CHUNKSIZE="3000" diff --git a/man/emerge.1 b/man/emerge.1 index a9050f79a..746e70456 100644 --- a/man/emerge.1 +++ b/man/emerge.1 @@ -112,14 +112,6 @@ developers with fixing any problems you may report. \fBPlease include this information when submitting a bug report.\fR Expanded output can be obtained with the \fI\-\-verbose\fR option. .TP -.BR "\-\-inject " (\fB\-i\fR) -Injecting a package inserts a 'stub' for that package so that Portage -thinks that it is installed. It is handy if you need, say, a binary -version of XFree86 for esoteric hardware, or you just like to roll -your own packages. You \fBmust\fR specify a category and particular -version of a package for injecting. For example, -\fBemerge \-\-inject sys\-kernel/gentoo\-sources\-2.4.19\fR. -.TP .BR \-\-metadata Causes portage to process all the metacache files as is normally done on the tail end of an rsync update using \fBemerge \-\-sync\fR. The processing @@ -186,13 +178,6 @@ highest version number due to masking for testing and development. This will also update direct dependencies which may not be what you want. In general, use this option only in combination with the world or system target. .TP -.BR "\-\-upgradeonly " (\fB\-U\fR) -Updates packages, but excludes updates that would result in a lower version of -the package being installed. \fBSLOT\fRs are considered at a basic level. -.br -This option is deprecated and should not be used anymore. Please use the -/etc/portage/package.* files from now on. -.TP .BR "\-\-version " (\fB\-V\fR) Displays the version number of \fBemerge\fR. .TP diff --git a/man/make.conf.5 b/man/make.conf.5 index fca815ccd..16ca627bd 100644 --- a/man/make.conf.5 +++ b/man/make.conf.5 @@ -174,6 +174,9 @@ Do not delete the ${T} directory after the merge process. .B keepwork Do not delete the ${WORKDIR} directory after the merge process. .TP +.B metadata-transfer +Automatically perform a metadata transfer when `emerge --sync` is run. +.TP .B mirror This will cause \fBFETCHCOMMAND\fR to always be run even if the file already exists in \fBDISTDIR\fR. diff --git a/pym/cache/flat_hash.py b/pym/cache/flat_hash.py index 6882afd7e..1bdc7cd5b 100644 --- a/pym/cache/flat_hash.py +++ b/pym/cache/flat_hash.py @@ -81,7 +81,7 @@ class database(fs_template.FsBased): raise cache_errors.CacheCorruption(cpv, e) for k, v in values.items(): - if k != "_mtime_": + if k != "_mtime_" and (k == "_eclasses_" or k in self._known_keys): myf.writelines("%s=%s\n" % (k, v)) myf.close() diff --git a/pym/cache/metadata.py b/pym/cache/metadata.py index 5e5f0bde7..99a7ad6db 100644 --- a/pym/cache/metadata.py +++ b/pym/cache/metadata.py @@ -50,7 +50,7 @@ class database(flat_hash.database): if not c.isalpha(): if c == "=" and idx > 0: hashed = True - d[line[:idx]] = line[idx + 1:] + d[line[:idx]] = line[idx + 1:].rstrip("\n") elif c == "_" or c.isdigit(): continue break diff --git a/pym/cache/metadata_overlay.py b/pym/cache/metadata_overlay.py new file mode 100644 index 000000000..557855a52 --- /dev/null +++ b/pym/cache/metadata_overlay.py @@ -0,0 +1,91 @@ +# Copyright 1999-2006 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +import time +if not hasattr(__builtins__, "set"): + from sets import Set as set +import template +from flat_hash import database as db_rw +from metadata import database as db_ro + +class database(template.database): + + autocommits = True + serialize_eclasses = False + + def __init__(self, location, label, auxdbkeys, **config): + super(database, self).__init__(location, label, auxdbkeys) + self.db_rw = db_rw(location, label, auxdbkeys, **config) + self.db_ro = db_ro(label,"metadata/cache",auxdbkeys) + + def __getitem__(self, cpv): + """funnel whiteout validation through here, since value needs to be fetched""" + try: + value = self.db_rw[cpv] + except KeyError: + return self.db_ro[cpv] # raises a KeyError when necessary + if self._is_whiteout(value): + if self._is_whiteout_valid(cpv, value): + raise KeyError(cpv) + else: + del self.db_rw[cpv] + return self.db_ro[cpv] # raises a KeyError when necessary + else: + return value + + def _setitem(self, name, values): + try: + value_ro = self.db_ro[name] + if self._are_values_identical(value_ro,values): + # we have matching values in the underlying db_ro + # so it is unnecessary to store data in db_rw + try: + del self.db_rw[name] # delete unwanted whiteout when necessary + except KeyError: + pass + except KeyError: + self.db_rw[name] = values + + def _delitem(self, cpv): + value = self[cpv] # validates whiteout and/or raises a KeyError when necessary + if self.db_ro.has_key(cpv): + self.db_rw[cpv] = self._create_whiteout(value) + else: + del self.db_rw[cpv] + + def has_key(self, cpv): + try: + self[cpv] # validates whiteout when necessary + except KeyError: + return False + return True + + def iterkeys(self): + s = set() + for cpv in self.db_rw.iterkeys(): + if self.has_key(cpv): # validates whiteout when necessary + yield cpv + # set includes whiteouts so they won't be yielded later + s.add(cpv) + for cpv in self.db_ro.iterkeys(): + if cpv not in s: + yield cpv + + def _is_whiteout(self, value): + return value["EAPI"] == "whiteout" + + def _create_whiteout(self, value): + return {"EAPI":"whiteout","_eclasses_":value["_eclasses_"],"_mtime_":value["_mtime_"]} + + def _is_whiteout_valid(self, name, value_rw): + try: + value_ro = self.db_ro[name] + return self._are_values_identical(value_rw,value_ro) + except KeyError: + return False + + def _are_values_identical(self, value1, value2): + if long(value1["_mtime_"]) != long(value2["_mtime_"]): + return False + return value1["_eclasses_"] == value2["_eclasses_"] diff --git a/pym/cache/template.py b/pym/cache/template.py index f9c613b50..097ebed8d 100644 --- a/pym/cache/template.py +++ b/pym/cache/template.py @@ -11,7 +11,7 @@ class database(object): # basically flags the cache needs be updated when transfered cache to cache. # leave this. - complete_eclass_entries_ = True + complete_eclass_entries = True autocommits = False cleanse_keys = False serialize_eclasses = True diff --git a/pym/emergehelp.py b/pym/emergehelp.py index 9a80de50d..28a78a126 100644 --- a/pym/emergehelp.py +++ b/pym/emergehelp.py @@ -14,8 +14,8 @@ def shorthelp(): print " "+turquoise("emerge")+" [ "+green("options")+" ] [ "+green("action")+" ] < "+turquoise("system")+" | "+turquoise("world")+" >" print " "+turquoise("emerge")+" < "+turquoise("--sync")+" | "+turquoise("--metadata")+" | "+turquoise("--info")+" >" print " "+turquoise("emerge")+" "+turquoise("--resume")+" [ "+green("--pretend")+" | "+green("--ask")+" | "+green("--skipfirst")+" ]" - print " "+turquoise("emerge")+" "+turquoise("--help")+" [ "+green("system")+" | "+green("config")+" | "+green("sync")+" ] " - print bold("Options:")+" "+green("-")+"["+green("abcCdDefhikKlnNoOpPsSuUvV")+"] ["+green("--oneshot")+"] ["+green("--newuse")+"] ["+green("--noconfmem")+"]" + print " "+turquoise("emerge")+" "+turquoise("--help")+" [ "+green("system")+" | "+green("config")+" | "+green("--sync")+" ] " + print bold("Options:")+" "+green("-")+"["+green("abcCdDefhikKlnNoOpPsSuvV")+"] ["+green("--oneshot")+"] ["+green("--newuse")+"] ["+green("--noconfmem")+"]" print " ["+green("--columns")+"] ["+green("--nospinner")+"]" print bold("Actions:")+" [ "+green("--clean")+" | "+green("--depclean")+" | "+green("--prune")+" | "+green("--regen")+" | "+green("--search")+" | "+green("--unmerge")+" ]" print @@ -302,7 +302,7 @@ def help(myaction,myopts,havecolor=1): print " other information useful for quick reference on a system. See" print " "+bold("emerge info")+" for more advanced information." print - elif myaction in ["rsync","sync"]: + elif myaction == "sync": print print bold("Usage: ")+turquoise("emerge")+" "+turquoise("--sync") print diff --git a/pym/output.py b/pym/output.py index ac57fe366..f23bac263 100644 --- a/pym/output.py +++ b/pym/output.py @@ -95,18 +95,28 @@ def nc_len(mystr): def xtermTitle(mystr): if havecolor and dotitles and os.environ.has_key("TERM") and sys.stderr.isatty(): myt=os.environ["TERM"] - legal_terms = ["xterm","Eterm","aterm","rxvt","screen","kterm","rxvt-unicode"] + legal_terms = ["xterm","Eterm","aterm","rxvt","screen","kterm","rxvt-unicode","gnome"] for term in legal_terms: if myt.startswith(term): sys.stderr.write("\x1b]2;"+str(mystr)+"\x07") sys.stderr.flush() break -prompt_command = os.getenv("PROMPT_COMMAND", 'echo -ne "${USER}@${HOSTNAME%%.*}:${PWD/$HOME/~}"') -default_xterm_title = commands.getoutput(prompt_command) -del prompt_command +default_xterm_title = None def xtermTitleReset(): + global default_xterm_title + if default_xterm_title is None: + prompt_command = os.getenv('PROMPT_COMMAND') + if prompt_command is not None: + default_xterm_title = commands.getoutput(prompt_command) + else: + pwd = os.getenv('PWD','') + home = os.getenv('HOME', '') + if home != '' and pwd.startswith(home): + pwd = '~' + pwd[len(home):] + default_xterm_title = '%s@%s:%s' % ( + os.getenv('LOGNAME', ''), os.getenv('HOSTNAME', '').split('.', 1)[0], pwd) xtermTitle(default_xterm_title) def notitles(): diff --git a/pym/portage.py b/pym/portage.py index 3628e0a95..7e6c3d2e0 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -106,6 +106,7 @@ try: from portage_checksum import perform_md5,perform_checksum,prelink_capable import eclass_cache from portage_localization import _ + from portage_update import fixdbentries, update_dbentries # Need these functions directly in portage namespace to not break every external tool in existence from portage_versions import ververify,vercmp,catsplit,catpkgsplit,pkgsplit,pkgcmp @@ -1595,21 +1596,7 @@ class config: match = x[mykey] break - if 0 and match and mykey in ["PORTAGE_BINHOST"]: - # These require HTTP Encoding - try: - import urllib - if urllib.unquote(match) != match: - writemsg("Note: %s already contains escape codes." % (mykey)) - else: - match = urllib.quote(match) - except SystemExit, e: - raise - except: - writemsg("Failed to fix %s using urllib, attempting to continue.\n" % (mykey)) - pass - - elif mykey == "CONFIG_PROTECT_MASK": + if mykey == "CONFIG_PROTECT_MASK": match += " "+portage_const.PREFIX+"/etc/env.d" return match @@ -3659,23 +3646,6 @@ def getmaskingstatus(mycpv): rValue.append(kmask+" keyword") return rValue -def fixdbentries(old_value, new_value, dbdir): - """python replacement for the fixdbentries script, replaces old_value - with new_value for package names in files in dbdir.""" - for myfile in [f for f in os.listdir(dbdir) if not f == "CONTENTS"]: - file_path = os.path.join(dbdir, myfile) - f = open(file_path, "r") - mycontent = f.read() - f.close() - if not mycontent.count(old_value): - continue - old_value = re.escape(old_value); - mycontent = re.sub(old_value+"$", new_value, mycontent) - mycontent = re.sub(old_value+"(\\s)", new_value+"\\1", mycontent) - mycontent = re.sub(old_value+"(-[^a-zA-Z])", new_value+"\\1", mycontent) - mycontent = re.sub(old_value+"([^a-zA-Z0-9-])", new_value+"\\1", mycontent) - write_atomic(file_path, mycontent) - class packagetree: def __init__(self,virtual,clone=None): if clone: @@ -4361,15 +4331,20 @@ class vardbapi(dbapi): os.rename(old_eb_path+".ebuild", new_eb_path+".ebuild") write_atomic(os.path.join(newpath, "CATEGORY"), mynewcat+"\n") + fixdbentries([mylist], newpath) - dbdir = self.root+VDB_PATH + def update_ents(self, update_iter): + """Run fixdbentries on all installed packages (time consuming). Like + fixpackages, this should be run from a helper script and display + a progress indicator.""" + dbdir = os.path.join(self.root, VDB_PATH) for catdir in listdir(dbdir): catdir = dbdir+"/"+catdir if os.path.isdir(catdir): for pkgdir in listdir(catdir): pkgdir = catdir+"/"+pkgdir if os.path.isdir(pkgdir): - fixdbentries(origcp, newcp, pkgdir) + fixdbentries(update_iter, pkgdir) def move_slot_ent(self,mylist): pkg=mylist[1] @@ -5297,21 +5272,16 @@ class binarytree(packagetree): #print ">>> Updating data in:",mycpv sys.stdout.write("%") sys.stdout.flush() - mytmpdir=settings["PORTAGE_TMPDIR"]+"/tbz2" - mytbz2=xpak.tbz2(tbz2path) - mytbz2.decompose(mytmpdir, cleanup=1) - fixdbentries(origcp, newcp, mytmpdir) - - write_atomic(os.path.join(mytmpdir, "CATEGORY"), mynewcat+"\n") - try: - os.rename(mytmpdir+"/"+string.split(mycpv,"/")[1]+".ebuild", mytmpdir+"/"+string.split(mynewcpv, "/")[1]+".ebuild") - except SystemExit, e: - raise - except Exception, e: - pass - - mytbz2.recompose(mytmpdir, cleanup=1) + mytbz2 = xpak.tbz2(tbz2path) + mydata = mytbz2.get_data() + updated_items = update_dbentries([mylist], mydata) + mydata.update(updated_items) + mydata["CATEGORY"] = mynewcat+"\n" + if mynewpkg != myoldpkg: + mydata[mynewpkg+".ebuild"] = mydata[myoldpkg+".ebuild"] + del mydata[myoldpkg+".ebuild"] + mytbz2.recompose_mem(xpak.xpak_mem(mydata)) self.dbapi.cpv_remove(mycpv) if (mynewpkg != myoldpkg): @@ -5319,9 +5289,7 @@ class binarytree(packagetree): self.dbapi.cpv_inject(mynewcpv) return 1 - def move_slot_ent(self,mylist,mytmpdir): - #mytmpdir=settings["PORTAGE_TMPDIR"]+"/tbz2" - mytmpdir=mytmpdir+"/tbz2" + def move_slot_ent(self, mylist): if not self.populated: self.populate() pkg=mylist[1] @@ -5343,10 +5311,10 @@ class binarytree(packagetree): continue #print ">>> Updating data in:",mycpv - mytbz2=xpak.tbz2(tbz2path) - mytbz2.decompose(mytmpdir, cleanup=1) + mytbz2 = xpak.tbz2(tbz2path) + mydata = mytbz2.get_data() - slot=grabfile(mytmpdir+"/SLOT"); + slot = mydata["SLOT"] if (not slot): continue @@ -5355,15 +5323,16 @@ class binarytree(packagetree): sys.stdout.write("S") sys.stdout.flush() - - write_atomic(os.path.join(mytmpdir, "SLOT"), newslot+"\n") - mytbz2.recompose(mytmpdir, cleanup=1) + mydata["SLOT"] = newslot+"\n" + mytbz2.recompose_mem(xpak.xpak_mem(mydata)) return 1 - def update_ents(self,mybiglist,mytmpdir): - #XXX mytmpdir=settings["PORTAGE_TMPDIR"]+"/tbz2" + def update_ents(self, update_iter): + if len(update_iter) == 0: + return if not self.populated: self.populate() + for mycpv in self.dbapi.cp_all(): tbz2path=self.getname(mycpv) if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK): @@ -5371,14 +5340,12 @@ class binarytree(packagetree): continue #print ">>> Updating binary data:",mycpv writemsg("*") - mytbz2=xpak.tbz2(tbz2path) - mytbz2.decompose(mytmpdir,cleanup=1) - for mylist in mybiglist: - mylist=string.split(mylist) - if mylist[0] != "move": - continue - fixdbentries(mylist[1], mylist[2], mytmpdir) - mytbz2.recompose(mytmpdir,cleanup=1) + mytbz2 = xpak.tbz2(tbz2path) + mydata = mytbz2.get_data() + updated_items = update_dbentries(update_iter, mydata) + if len(updated_items) > 0: + mydata.update(updated_items) + mytbz2.recompose_mem(xpak.xpak_mem(mydata)) return 1 def populate(self, getbinpkgs=0,getbinpkgsonly=0): @@ -5397,6 +5364,7 @@ class binarytree(packagetree): if not mycat: #old-style or corrupt package writemsg("!!! Invalid binary package: "+mypkg+"\n") + writemsg("!!! This binary package is not recoverable and should be deleted.\n") self.invalids.append(mypkg) continue mycat=string.strip(mycat) @@ -6797,16 +6765,85 @@ for x in mtimedb.keys(): #,"porttree":portagetree(root,virts),"bintree":binarytree(root,virts)} features=settings["FEATURES"].split() -do_upgrade_packagesmessage=0 def do_upgrade(mykey): - global do_upgrade_packagesmessage + """Valid updates are returned as a list of split update commands.""" writemsg("\n\n") writemsg(green("Performing Global Updates: ")+bold(mykey)+"\n") writemsg("(Could take a couple of minutes if you have a lot of binary packages.)\n") writemsg(" "+bold(".")+"='update pass' "+bold("*")+"='binary update' "+bold("@")+"='/var/db move'\n"+" "+bold("s")+"='/var/db SLOT move' "+bold("S")+"='binary SLOT move' "+bold("p")+"='update /etc/portage/package.*'\n") processed=1 - #remove stale virtual entries (mappings for packages that no longer exist) + myupd = [] + mylines = grabfile(mykey) + for myline in mylines: + mysplit = myline.split() + if len(mysplit) == 0: + continue + if mysplit[0] not in ("move", "slotmove"): + writemsg("portage: Update type \""+mysplit[0]+"\" not recognized.\n") + processed=0 + continue + if mysplit[0]=="move": + if len(mysplit)!=3: + writemsg("portage: Update command \""+myline+"\" invalid; skipping.\n") + processed=0 + continue + orig_value, new_value = mysplit[1], mysplit[2] + for cp in (orig_value, new_value): + if not (isvalidatom(cp) and isjustname(cp)): + writemsg("\nERROR: Malformed update entry '%s'\n" % myline) + processed=0 + continue + if mysplit[0]=="slotmove": + if len(mysplit)!=4: + writemsg("portage: Update command \""+myline+"\" invalid; skipping.\n") + processed=0 + continue + pkg, origslot, newslot = mysplit[1], mysplit[2], mysplit[3] + if not isvalidatom(pkg): + writemsg("\nERROR: Malformed update entry '%s'\n" % myline) + processed=0 + continue + + # The list of valid updates is filtered by continue statements above. + myupd.append(mysplit) + sys.stdout.write(".") + sys.stdout.flush() + return myupd, processed == 1 + +def commit_mtimedb(): + if mtimedb: + # Store mtimedb + mymfn=mtimedbfile + f = None + try: + mtimedb["version"]=VERSION + f = atomic_ofstream(mymfn) + cPickle.dump(mtimedb, f, -1) + f.close() + except SystemExit, e: + raise + except Exception, e: + if f is not None: + f.abort() + + try: + os.chown(mymfn,uid,portage_gid) + os.chmod(mymfn,0664) + except SystemExit, e: + raise + except Exception, e: + pass +def portageexit(): + global uid,portage_gid,portdb,db + if secpass and not os.environ.has_key("SANDBOX_ACTIVE"): + close_portdbapi_caches() + commit_mtimedb() + +atexit_register(portageexit) + +def update_config_files(update_iter): + """Perform global updates on /etc/portage/package.* and the world file.""" update_files={} file_contents={} myxfiles = ["package.mask","package.unmask","package.keywords","package.use"] @@ -6827,155 +6864,118 @@ def do_upgrade(mykey): if file_contents.has_key(x): del file_contents[x] continue + worldlist = grabfile(WORLD_FILE) - worldlist=grabfile("/"+WORLD_FILE) - myupd=grabfile(mykey) - db["/"]["bintree"]=binarytree("/",settings["PKGDIR"],virts) - for myline in myupd: - mysplit=myline.split() - if not len(mysplit): - continue - if mysplit[0]!="move" and mysplit[0]!="slotmove": - writemsg("portage: Update type \""+mysplit[0]+"\" not recognized.\n") - processed=0 - continue - if mysplit[0]=="move" and len(mysplit)!=3: - writemsg("portage: Update command \""+myline+"\" invalid; skipping.\n") - processed=0 - continue - if mysplit[0]=="slotmove" and len(mysplit)!=4: - writemsg("portage: Update command \""+myline+"\" invalid; skipping.\n") - processed=0 - continue - sys.stdout.write(".") - sys.stdout.flush() - - if mysplit[0]=="move": - try: - db["/"]["vartree"].dbapi.move_ent(mysplit) - db["/"]["bintree"].move_ent(mysplit) - except portage_exception.InvalidPackageName, e: - writemsg("\nERROR: Malformed update entry '%s'\n" % myline) - continue + for update_cmd in update_iter: + if update_cmd[0] == "move": + old_value, new_value = update_cmd[1], update_cmd[2] #update world entries: for x in range(0,len(worldlist)): #update world entries, if any. - worldlist[x]=dep_transform(worldlist[x],mysplit[1],mysplit[2]) + worldlist[x] = dep_transform(worldlist[x], old_value, new_value) #update /etc/portage/packages.* for x in file_contents: for mypos in range(0,len(file_contents[x])): - line=file_contents[x][mypos] - if line[0]=="#" or string.strip(line)=="": + line = file_contents[x][mypos] + if line[0] == "#" or string.strip(line) == "": continue - key=dep_getkey(line.split()[0]) - if key==mysplit[1]: - file_contents[x][mypos]=string.replace(line,mysplit[1],mysplit[2]) - update_files[x]=1 + key = dep_getkey(line.split()[0]) + if key == old_value: + file_contents[x][mypos] = string.replace(line, old_value, new_value) + update_files[x] = 1 sys.stdout.write("p") sys.stdout.flush() - elif mysplit[0]=="slotmove": - try: - db["/"]["vartree"].dbapi.move_slot_ent(mysplit) - db["/"]["bintree"].move_slot_ent(mysplit,settings["PORTAGE_TMPDIR"]+"/tbz2") - except portage_exception.InvalidAtom, e: - writemsg("\nERROR: Malformed update entry '%s'\n" % myline) + write_atomic(WORLD_FILE,"\n".join(worldlist)) for x in update_files: mydblink = dblink('','','/',settings) - if mydblink.isprotected(USER_CONFIG_PATH+os.path.sep+x): - updating_file=new_protect_filename(USER_CONFIG_PATH+os.path.sep+x)[0] - else: - updating_file=USER_CONFIG_PATH+os.path.sep+x + updating_file = os.path.join(USER_CONFIG_PATH, x) + if mydblink.isprotected(updating_file): + updating_file = new_protect_filename(updating_file)[0] try: write_atomic(updating_file, "".join(file_contents[x])) except IOError: continue - # We gotta do the brute force updates for these now. - if (settings["PORTAGE_CALLER"] in ["fixpackages"]) or \ - ("fixpackages" in features): - db["/"]["bintree"].update_ents(myupd,settings["PORTAGE_TMPDIR"]+"/tbz2") - else: - do_upgrade_packagesmessage = 1 - - if processed: - #update our internal mtime since we processed all our directives. - mtimedb["updates"][mykey]=os.stat(mykey)[stat.ST_MTIME] - write_atomic(WORLD_FILE,"\n".join(worldlist)) - print "" +def global_updates(): + updpath = os.path.join(settings["PORTDIR"], "profiles", "updates") + mylist = listdir(updpath, EmptyOnError=1) + # validate the file name (filter out CVS directory, etc...) + mylist = [myfile for myfile in mylist if len(myfile) == 7 and myfile[1:3] == "Q-"] + if len(mylist) > 0: + # resort the list + mylist = [myfile[3:]+"-"+myfile[:2] for myfile in mylist] + mylist.sort() + mylist = [myfile[5:]+"-"+myfile[:4] for myfile in mylist] -def commit_mtimedb(): - if mtimedb: - # Store mtimedb - mymfn=mtimedbfile - f = None - try: - mtimedb["version"]=VERSION - f = atomic_ofstream(mymfn) - cPickle.dump(mtimedb, f, -1) - f.close() - except SystemExit, e: - raise - except Exception, e: - if f is not None: - f.abort() - - try: - os.chown(mymfn,uid,portage_gid) - os.chmod(mymfn,0664) - except SystemExit, e: - raise - except Exception, e: - pass - -def portageexit(): - global uid,portage_gid,portdb,db - if secpass and not os.environ.has_key("SANDBOX_ACTIVE"): - close_portdbapi_caches() - commit_mtimedb() - -atexit_register(portageexit) - -if (secpass==2) and (not os.environ.has_key("SANDBOX_ACTIVE")): - if settings["PORTAGE_CALLER"] in ["emerge","fixpackages"]: - #only do this if we're root and not running repoman/ebuild digest - updpath=os.path.normpath(settings["PORTDIR"]+"///profiles/updates") - didupdate=0 if not mtimedb.has_key("updates"): - mtimedb["updates"]={} - try: - mylist=listdir(updpath,EmptyOnError=1) - # resort the list - mylist=[myfile[3:]+"-"+myfile[:2] for myfile in mylist] - mylist.sort() - mylist=[myfile[5:]+"-"+myfile[:4] for myfile in mylist] - for myfile in mylist: - mykey=updpath+"/"+myfile - if not os.path.isfile(mykey): - continue - if (not mtimedb["updates"].has_key(mykey)) or \ - (mtimedb["updates"][mykey] != os.stat(mykey)[stat.ST_MTIME]) or \ - (settings["PORTAGE_CALLER"] == "fixpackages"): - didupdate=1 - do_upgrade(mykey) - commit_mtimedb() # This lets us save state for C-c. - except OSError: - #directory doesn't exist - pass + mtimedb["updates"] = {} + + didupdate = 0 + do_upgrade_packagesmessage = 0 + myupd = [] + timestamps = {} + for myfile in mylist: + mykey = os.path.join(updpath, myfile) + mystat = os.stat(mykey) + if not stat.S_ISREG(mystat.st_mode): + continue + if mykey not in mtimedb["updates"] or \ + mtimedb["updates"][mykey] != mystat.st_mtime or \ + settings["PORTAGE_CALLER"] == "fixpackages": + didupdate = 1 + valid_updates, no_errors = do_upgrade(mykey) + myupd.extend(valid_updates) + if no_errors: + # Update our internal mtime since we + # processed all of our directives. + timestamps[mykey] = mystat.st_mtime + update_config_files(myupd) + + db["/"]["bintree"] = binarytree("/", settings["PKGDIR"], virts) + for update_cmd in myupd: + if update_cmd[0] == "move": + db["/"]["vartree"].dbapi.move_ent(update_cmd) + db["/"]["bintree"].move_ent(update_cmd) + elif update_cmd[0] == "slotmove": + db["/"]["vartree"].dbapi.move_slot_ent(update_cmd) + db["/"]["bintree"].move_slot_ent(update_cmd) + + print + + # The above global updates proceed quickly, so they + # are considered a single mtimedb transaction. + if len(timestamps) > 0: + # We do not update the mtime in the mtimedb + # until after _all_ of the above updates have + # been processed because the mtimedb will + # automatically commit when killed by ctrl C. + for mykey, mtime in timestamps.iteritems(): + mtimedb["updates"][mykey] = mtime + commit_mtimedb() + + # We gotta do the brute force updates for these now. + if settings["PORTAGE_CALLER"] == "fixpackages" or \ + "fixpackages" in features: + db["/"]["bintree"].update_ents(myupd) + else: + do_upgrade_packagesmessage = 1 + if didupdate: #make sure our internal databases are consistent; recreate our virts and vartree do_vartree(settings) if do_upgrade_packagesmessage and \ - listdir(settings["PKGDIR"]+"/All/",EmptyOnError=1): + listdir(os.path.join(settings["PKGDIR"], "All"), EmptyOnError=1): writemsg("\n\n\n ** Skipping packages. Run 'fixpackages' or set it in FEATURES to fix the") writemsg("\n tbz2's in the packages directory. "+bold("Note: This can take a very long time.")) writemsg("\n") - - - +if (secpass==2) and (not os.environ.has_key("SANDBOX_ACTIVE")): + if settings["PORTAGE_CALLER"] in ["emerge","fixpackages"]: + #only do this if we're root and not running repoman/ebuild digest + global_updates() #continue setting up other trees db["/"]["porttree"]=portagetree("/",virts) diff --git a/pym/portage_exception.py b/pym/portage_exception.py index ae3a9db4f..27294da6e 100644 --- a/pym/portage_exception.py +++ b/pym/portage_exception.py @@ -23,11 +23,13 @@ class SecurityViolation(PortageException): """An incorrect formatting was passed instead of the expected one""" class IncorrectParameter(PortageException): - """An parameter of the wrong type was passed""" + """A parameter of the wrong type was passed""" class MissingParameter(PortageException): - """An parameter is required for the action requested but was not passed""" + """A parameter is required for the action requested but was not passed""" +class ParseError(PortageException): + """An error was generated while attempting to parse the request""" class InvalidData(PortageException): """An incorrect formatting was passed instead of the expected one""" diff --git a/pym/portage_locks.py b/pym/portage_locks.py index ee2e0b0d4..8b40100b9 100644 --- a/pym/portage_locks.py +++ b/pym/portage_locks.py @@ -123,7 +123,8 @@ def lockfile(mypath,wantnewlockfile=0,unlinkfile=0): raise - if type(lockfilename) == types.StringType and os.fstat(myfd).st_nlink != 1: + if type(lockfilename) == types.StringType and \ + myfd != HARDLINK_FD and os.fstat(myfd).st_nlink != 1: # The file was deleted on us... Keep trying to make one... os.close(myfd) portage_util.writemsg("lockfile recurse\n",1) diff --git a/pym/portage_update.py b/pym/portage_update.py new file mode 100644 index 000000000..0aadae1b3 --- /dev/null +++ b/pym/portage_update.py @@ -0,0 +1,46 @@ + +import os, re + +from portage_util import write_atomic + +ignored_dbentries = ("CONTENTS", "environment.bz2") + +def update_dbentry(update_cmd, mycontent): + if update_cmd[0] == "move": + old_value, new_value = update_cmd[1], update_cmd[2] + if mycontent.count(old_value): + old_value = re.escape(old_value); + mycontent = re.sub(old_value+"$", new_value, mycontent) + mycontent = re.sub(old_value+"(\\s)", new_value+"\\1", mycontent) + mycontent = re.sub(old_value+"(-[^a-zA-Z])", new_value+"\\1", mycontent) + mycontent = re.sub(old_value+"([^a-zA-Z0-9-])", new_value+"\\1", mycontent) + return mycontent + +def update_dbentries(update_iter, mydata): + """Performs update commands and returns a + dict containing only the updated items.""" + updated_items = {} + for k, mycontent in mydata.iteritems(): + if k not in ignored_dbentries: + orig_content = mycontent + for update_cmd in update_iter: + mycontent = update_dbentry(update_cmd, mycontent) + if mycontent is not orig_content: + updated_items[k] = mycontent + return updated_items + +def fixdbentries(update_iter, dbdir): + """Performs update commands which result in search and replace operations + for each of the files in dbdir (excluding CONTENTS and environment.bz2). + Returns True when actual modifications are necessary and False otherwise.""" + mydata = {} + for myfile in [f for f in os.listdir(dbdir) if f not in ignored_dbentries]: + file_path = os.path.join(dbdir, myfile) + f = open(file_path, "r") + mydata[myfile] = f.read() + f.close() + updated_items = update_dbentries(update_iter, mydata) + for myfile, mycontent in updated_items.iteritems(): + file_path = os.path.join(dbdir, myfile) + write_atomic(file_path, mycontent) + return len(updated_items) > 0 diff --git a/pym/xpak.py b/pym/xpak.py index ef6d2905a..c5c487e0a 100644 --- a/pym/xpak.py +++ b/pym/xpak.py @@ -16,7 +16,7 @@ # (integer) == encodeint(integer) ===> 4 characters (big-endian copy) # '+' means concatenate the fields ===> All chunks are strings -import sys,os,string +import sys,os,string,shutil,errno from stat import * def addtolist(mylist,curdir): @@ -66,34 +66,39 @@ def xpak(rootdir,outfile=None): addtolist(mylist,"") mylist.sort() + mydata = {} + for x in mylist: + a = open(x, "r") + mydata[x] = a.read() + a.close() + os.chdir(origdir) - #Our list index has been created - + xpak_segment = xpak_mem(mydata) + if outfile: + outf = open(outfile, "w") + outf.write(xpak_segment) + outf.close() + else: + return xpak_segment + +def xpak_mem(mydata): + """Create an xpack segement from a map object.""" indexglob="" indexpos=0 dataglob="" datapos=0 - for x in mylist: - a=open(x,"r") - newglob=a.read() - a.close() + for x, newglob in mydata.iteritems(): mydatasize=len(newglob) indexglob=indexglob+encodeint(len(x))+x+encodeint(datapos)+encodeint(mydatasize) indexpos=indexpos+4+len(x)+4+4 dataglob=dataglob+newglob datapos=datapos+mydatasize - os.chdir(origdir) - if outfile: - outf=open(outfile,"w") - outf.write("XPAKPACK"+encodeint(len(indexglob))+encodeint(len(dataglob))) - outf.write(indexglob) - outf.write(dataglob) - outf.write("XPAKSTOP") - outf.close() - else: - myret="XPAKPACK"+encodeint(len(indexglob))+encodeint(len(dataglob)) - myret=myret+indexglob+dataglob+"XPAKSTOP" - return myret + return "XPAKPACK" \ + + encodeint(len(indexglob)) \ + + encodeint(len(dataglob)) \ + + indexglob \ + + dataglob \ + + "XPAKSTOP" def xsplit(infile): """(infile) -- Splits the infile into two files. @@ -239,9 +244,8 @@ class tbz2: Returns result of upackinfo().""" if not self.scan(): raise IOError - if cleanup and os.path.exists(datadir): - # XXX: Potentially bad - os.system("rm -Rf "+datadir+"/*") + if cleanup: + self.cleanup(datadir) if not os.path.exists(datadir): os.makedirs(datadir) return self.unpackinfo(datadir) @@ -252,21 +256,36 @@ class tbz2: """Creates an xpak segment from the datadir provided, truncates the tbz2 to the end of regular data if an xpak segment already exists, and adds the new segment to the file with terminating info.""" + xpdata = xpak(datadir) + self.recompose_mem(xpdata) + if cleanup: + self.cleanup(datadir) + + def recompose_mem(self, xpdata): self.scan() # Don't care about condition... We'll rewrite the data anyway. myfile=open(self.file,"a+") if not myfile: raise IOError myfile.seek(-self.xpaksize,2) # 0,2 or -0,2 just mean EOF. myfile.truncate() - xpdata=xpak(datadir) myfile.write(xpdata+encodeint(len(xpdata))+"STOP") myfile.flush() myfile.close() - if cleanup: - # XXX: Potentially bad - os.system("rm -Rf "+datadir) return 1 + def cleanup(self, datadir): + datadir_split = os.path.split(datadir) + if len(datadir_split) >= 2 and len(datadir_split[1]) > 0: + # This is potentially dangerous, + # thus the above sanity check. + try: + shutil.rmtree(datadir) + except OSError, oe: + if oe.errno == errno.ENOENT: + pass + else: + raise oe + def scan(self): """Scans the tbz2 to locate the xpak segment and setup internal values. This function is called by relevant functions already.""" @@ -370,6 +389,24 @@ class tbz2: os.chdir(origdir) return 1 + def get_data(self): + """Returns all the files from the dataSegment as a map object.""" + if not self.scan(): + return 0 + a = open(self.file, "r") + mydata = {} + startpos=0 + while ((startpos+8) $myout - -done diff --git a/qa/iuse/iuse2.py b/qa/iuse/iuse2.py deleted file mode 100755 index 7944b9327..000000000 --- a/qa/iuse/iuse2.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/python2.2 -import portage,sys -portdir=portage.settings["PORTDIR"] -for cp in portage.portdb.cp_all(): - for cpv in portage.portdb.cp_list(cp): - try: - myaux=portage.portdb.aux_get(cpv,["DEPEND","RDEPEND","SRC_URI"]) - except KeyError: - pass - myuse={} - for str in myaux: - mysplit=str.split() - for part in mysplit: - if part[-1]=="?": - if part[0]=="!": - if not myuse.has_key(part[1:-1]): - myuse[part[1:-1]]=None - else: - if not myuse.has_key(part[:-1]): - myuse[part[:-1]]=None - if not myuse: - continue - cpsplit=cpv.split("/") - mypath=portdir+"/"+cp+"/.use-"+cpsplit[1] - print mypath - myfile=open(mypath,"r") - for x in myfile.readlines(): - if x[:-1]: - if not myuse.has_key(x[:-1]): - myuse[x[:-1]]=None - print myuse.keys() - myfile.close() - if not myuse.keys(): - #no IUSE to add - continue - myepath=portdir+"/"+cp+"/"+cpsplit[1]+".ebuild" - myefile=open(myepath,"r") - mylines=myefile.readlines() - myefile.close() - mynewlines=[] - pos=0 - while (pos (satisfy dep by merging most recent version of app available that satisfies dep) -# NOTE: this will cause something to be merged again if the dep happens to be already satisfied -# "unslotted" is invalid for a package class here because it only applies to already-installed ebuilds. -# pkgclass support: "system", "world", , , , - -# no changes here except we use "update" rather than "--update" -# emerge update -# emerge update (defaults to "world") -# "emerge update doesn't make too much sense. -# But it should do the same thing are "emerge ". - -# rebuild is like "update" except that all packages will be rebuilt even if they currently are installed. -# emerge rebuild (defaults to "world") -# emerge rebuild -# "emerge rebuild doesn't make too much sense. -# But it should do the same thing are "emerge ". - -# emerge search (invalid) -# emerge search - -# clean does "cleaning" only; it does not do anything that would generally be considered dangerous -# emerge clean (defaults to "world"; apply default AUTOCLEAN behavior defined in make.conf) -# emerge --rev clean (defaults to "world", cleans out old revisions) -# emerge --slot clean (defaults to "world", cleans out old stuff from slots) -# emerge [--rev/--slot] clean -# AUTOCLEAN var can be set to "slot", "rev", or "none/off/etc". - -# zap flat out removes stuff. No holds barred. Can be dangerous. -# emerge zap (only "unslotted" is valid, which is still dangerous. Or a dep "=foo/bar") -# NOTE: of course, "emerge zap" alone is invalid and will *not* default to a "world" package class - -pkgclass=["world","system","unslotted"] -helpclass=["config"] - -# These next options are the only long options for Portage 1.8.9 except for "--help" (equiv. to "help") - -options=["--autoclean", - "--buildpkg", - "--debug", - "--fetchonly", - "--noreplace", - "--onlydeps", - "--pretend", - "--usepkg", - "--verbose", - "--emptytree", - "--rev", - "--slot", - "--help"] - -# Here are the currently supported short mappings. - -shortmapping={"a":"--autoclean", - "b":"--buildpkg", - "d":"--debug", - "f":"--fetchonly", - "h":"--help", - "k":"--usepkg", - "n":"--noreplace", - "o":"--onlydeps", - "p":"--pretend", - "v":"--verbose" } - -# end of spec - -myaction=None -myopts=[] -mymode=[] -myfiles=[] -edebug=0 - -# process short actions and options -for x in sys.argv[1:]: - if x[0:1]=="-"and not x[1:2]=="-": - for y in x[1:]: - if shortmapping.has_key(y): - sys.argv.append(shortmapping[y]) - else: - print y - print "!!! Error: -"+y+" is an invalid short action or option." - sys.argv.remove(x) - -# process the command arguments -for x in sys.argv[1:]: - if x=="update" or x=="--unmerge" or x=="--world": - print - if x=="update": - print " "+red("* WARNING:"),green("emerge update"),"has been deprecated, use",green("emerge --update"),"instead." - elif x=="--unmerge": - print " "+red("* WARNING:"),green("emerge --unmerge"),"has been deprecated, use",green("emerge --zap"),"instead." - elif x=="--world": - print " "+red("* WARNING:"),green("emerge --world"),"has been deprecated, use",green("emerge world"),"instead." - print " "+red("*"),"Read",green("emerge --help"),"to get a complete overview of the interface changes." - print - sys.exit(1) - - if len(x)>=2: - if x[0:1]=="-": - if x[1:2]=="-": - if x in actions: - if myaction: - print "!!! Error: more than one action specified on command-line." - print "!!! Available actions:",actions - sys.exit(1) - else: - myaction=x - elif x in options: - myopts.append(x) - else: - print "!!! Error:",x,"is an invalid action or option." - sys.exit(1) - else: - for y in x[1:]: - if shortmapping.has_key(y): - myopts.append(shortmapping[y]) - else: - print y - print "!!! Error: -"+y+" is an invalid short action or option." - elif x in modes: - if len(mymode)>=1: - print "!!! Error: more than one mode specified on command-line." - print "!!! Available modes:",modes - sys.exit(1) - else: - mymode.append(x) - else: - # this little conditional helps tab completion - if x[-1]=="/": - myfiles.append(x[:-1]) - else: - myfiles.append(x) - -# check if root user is the current user for the actions where emerge needs this -if os.getuid()!=0 and "--help"!=myaction and "--search"!=myaction: - print "!!! to be able to perform the requested action, emerge must be run by root." - sys.exit(1) - -# search functionality -class search: - - # - # class constants - # - VERSION_SHORT=1 - VERSION_RELEASE=2 - - # - # public interface - # - def __init__(self,searchkey=""): - """Searches the available and installed packages for the supplied search key. - The list of available and installed packages is created at object instantiation. - This makes successive searches faster.""" - self.searchkey = searchkey - self.treecache = portage.portagetree() - self.treecache.populate() - self.installcache = portage.vartree() - self.installcache.populate() - self.re_portagedir = re.compile('/usr/portage/') - self.re_description = re.compile('DESCRIPTION="') - self.initResults() - - def setKey(self,searchkey): - """changes the search key""" - self.searchkey = searchkey - self.initResults() - - def execute(self): - """Performs the saerch for the supplied search key""" - if self.searchkey: - self.initResults() - for package in self.treecache.getallnodes(): - package_parts=package.split("/") - if package_parts: - if self.searchkey != "*": - if re.search(self.searchkey.lower(), package_parts[1].lower()): - self.packagematches.append(package) - else: - self.packagematches.append(package) - - def output(self): - """Outputs the results of the search.""" - print "[ Results for search key : "+white(self.searchkey)+" ]" - print "[ Applications found : "+white(str(len(self.packagematches)))+" ]" - print " " - for match in self.packagematches: - full_package = strip(self.treecache.dep_bestmatch(match)) - if len(full_package) > 1: - print green("*")+" "+white(match) - print " ", "Latest version Available:",self.getVersion(full_package, search.VERSION_RELEASE) - print " ", self.getInstallationStatus(match) - print " ", "Description:",self.getDescription(self.getFullPath(match, full_package),self.getVersion(full_package, search.VERSION_SHORT)) - print " " - else: - print green("*")+" "+white(match)+" "+red("[ Masked ]") - print " " - - # - # private interface - # - def initResults(self): - self.packagematches = [] - - def getInstallationStatus(self,package): - installed_package = self.installcache.dep_bestmatch(package) - result = "" - version = self.getVersion(installed_package,search.VERSION_RELEASE) - if len(version) > 1: - result = "Latest version Installed: "+version - else: - result = "Latest version Installed: [ Not Installed ]" - return result - - def getDescription(self,ebuildPath,packageVersion): ## Gets description from latest ebuild ## - file = open(ebuildPath) - result = ""; - indescription=0 - while 1: - data = file.readline() - if data: - if self.re_description.match(data.upper()): - indescription=1 - p = self.re_description.split(data) - p = p[1].split('"') - result = p[0].strip() - if len(p)>1: - break - elif indescription==1: - if '"' in data: - p = data.split('"') - result = result+" "+p[0].strip() - indescription = 0 - else: - result = result+" "+data.strip() - else: - break; - result = replace(result, "${PV}", packageVersion) - result = replace(result, "${pv}", packageVersion) - result = replace(result, "${description}", "KDE " + packageVersion + " ") - result = replace(result, "\n", "") - file.close() - # format and wrap the description text nicely - wraplength=60 - formatted_result="" - while len(result)>wraplength: - lineposition=0 - position=wraplength - while result[lineposition+position]!=' ' and position != 0: - position = position-1 - if position==0: - position=wraplength - if len(formatted_result)==0: - formatted_result=result[:position] - else: - formatted_result=formatted_result+"\n "+result[:position] - result=result[position+1:] - if wraplength==60: - wraplength=73 - formatted_result=formatted_result+"\n "+result - return formatted_result - - def getFullPath(self,packageShortName,packageFullName): ## Returns the full path of the ebuild ## - absolute_path = '/usr/portage/' + strip(packageShortName) - package_parts = packageFullName.split("/") - result = absolute_path + "/" + package_parts[1] + ".ebuild" - return result - - def getVersion(self,full_package,detail): - if len(full_package) > 1: - package_parts = portage.catpkgsplit(full_package) - if detail == search.VERSION_RELEASE and package_parts[3] != 'r0': - result = package_parts[2]+ "-" + package_parts[3] - else: - result = package_parts[2] - else: - result = "" - return result - -#build our package digraph -def getsyslist(): - if os.path.exists(portage.profiledir+"/packages"): - pfile=portage.profiledir+"/packages" - else: - print "!!! Couldn't find",portage.profiledir+"/packages;" - print "\"system\" mode unavailable." - sys.exit(1) - myfile=open(pfile,"r") - mylines=myfile.readlines() - myfile.close() - - mynewlines=[] - for x in mylines: - myline=string.join(string.split(x)) - if not len(myline): - continue - elif myline[0]=="#": - continue - elif myline[0]!="*": - continue - myline=myline[1:] - mynewlines.append(myline.strip()) - - return mynewlines - -class depgraph: - - def __init__(self,mymode,myaction,myopts): - self.mymode=mymode - self.myaction=myaction - self.myopts=myopts - virts=portage.getvirtuals("/") - self.db={} - self.db["/"]={"virtuals":virts,"vartree":portage.vartree("/",virts),"porttree":portage.portagetree("/",virts),"bintree":portage.binarytree("/",virts)} - if portage.root!="/": - pr=portage.root - virts=portage.getvirtuals(pr) - self.db[pr]={"virtuals":virts,"vartree":portage.vartree(pr,virts),"porttree":portage.portagetree(pr,virts),"bintree":portage.binarytree(pr,virts)} - self.digraph=portage.digraph() - self.orderedkeys=[] - #the following is so we have an empty vartree (used in emerge update calculations) - self.emptytree=portage.vartree("/",virts,self.db["/"]["vartree"]) - self.emptytree.tree={} - if "--emptytree" in myopts: - print "Running in empty tree mode" - self.db["/"]["vartree"].tree=self.emptytree.tree - self.db["/"]["vartree"].populated=1 - self.db["/"]["vartree"].inject("virtual/glibc-1.0") - self.outdatedpackages=[] - def create(self,mybigkey,myparent=None,addme=1): - """creates the actual digraph of packages to merge. return 1 on success, 0 on failure - mybigkey = specification of package to merge; myparent = parent package (one depending on me); - addme = should I be added to the tree? (for the --onlydeps mode)""" - if mybigkey==None: - return - sys.stdout.write(".") - sys.stdout.flush() - if self.digraph.hasnode(mybigkey): - #if we've already hit this node before, we're already recursing on the dependencies. - #no need to recurse again. - if addme: - if myparent: - self.digraph.addnode(mybigkey,myparent) - return 1 - mytype,myroot,mykey=string.split(mybigkey) - if "--noreplace" in self.myopts: - if self.db[myroot]["vartree"].exists_specific(mykey): - print "\n>>>",mykey,"already merged in",myroot+", skipping...\n" - return 1 - if mytype=="binary": - if not self.db[portage.root]["bintree"].exists_specific(mykey): - print "\n\n!!!",mytype,mykey,"not found (possibly blocked by package.mask)\n" - sys.exit(1) - mypkgparts=portage.catpkgsplit(mykey) - mytbz2=xpak.tbz2(self.db[portage.root]["bintree"].getname(mykey)) - edepend=["",string.join(mytbz2.getelements("RDEPEND")," "),mytbz2.getfile("SLOT",mypkgparts[2])] - elif mytype=="ebuild": - if not self.db[myroot]["porttree"].exists_specific(mykey): - print "\n\n!!!",mytype,mykey,"not found (possibly blocked by package.mask)\n" - sys.exit(1) - mydep={} - myebuild=self.db[myroot]["porttree"].getname(mykey) - edepend=portage.doebuild(myebuild,"depend",myroot,1,edebug) - if edepend==1: - print "!!! emerge aborting." - sys.exit(1) - elif mytype=="blocks": - edepend=None - parenttype,parentroot,parentkey=string.split(myparent) - mykeyparts=portage.catpkgsplit(mykey) - parentkeyparts=portage.catpkgsplit(parentkey) - # only add blocking deps that aren't from the same package that is installing - if mykeyparts[0]!=parentkeyparts[0] or mykeyparts[1]!=parentkeyparts[1]: - self.digraph.addnode(mybigkey,myparent) - - if edepend: - mydep={} - if myroot=="/": - mydep["/"]=edepend[0]+" "+edepend[1] - else: - mydep["/"],mydep[myroot]=edepend - if addme: - self.digraph.addnode(mybigkey,myparent) - for dep in mydep.keys(): - if "--update"==self.myaction: - mycheck=self.emptytree.depcheck(mydep[dep]) - else: - mycheck=self.db[dep]["vartree"].depcheck(mydep[dep]) - if mycheck[0]==0: - print "!!! depgraph.create() error: string format:",mydep - return 0 - for x in mycheck[1]: - mynew=self.match(x,dep,mykey) - if not self.digraph.hasnode(mynew): - if addme: - if not self.create(mynew,mybigkey): - return 0 - else: - if not self.create(mynew,None): - return 0 - else: - self.digraph.addnode(mynew,mybigkey) - - return 1 - - def altlist(self): - mygraph=self.digraph.copy() - dolist=["/"] - retlist=[] - for x in self.db.keys(): - self.db[x]["merge"]=[] - if x not in dolist: - dolist.append(x) - while (not mygraph.empty()): - mycurkey=mygraph.firstzero() - if not mycurkey: - print "!!! Error: circular dependencies" - sys.exit(1) - splitski=string.split(mycurkey) - if "--update"==self.myaction: - if not self.db["/"]["vartree"].exists_specific(splitski[2]): - self.db["/"]["merge"].append(splitski) - else: - self.db[splitski[1]]["merge"].append(splitski) - mygraph.delnode(mycurkey) - for x in dolist: - for y in self.db[x]["merge"]: - retlist.append(y) - return retlist - - def syscreate(self,mylines=[]): - for myline in mylines: - if "--update"==self.myaction or "--rebuild"==self.myaction: - self.create(self.match(myline,mykey="update (likely old /var/db/pkg entry)")) - else: - mycheck=self.db[portage.root]["vartree"].depcheck(myline) - if mycheck[0]==0: - print "\n!!! Warning:",myline,"has an invalid depstring\n" - continue - if mycheck[1]==None: - continue - for x in mycheck[1]: - self.create(self.match(myline,mykey="syscreate1")) - - def match(self,mydep,myroot=portage.root,mykey=None): - # support mutual exclusive deps - mydep2=mydep - if mydep2[0]=="!": - mydep2=mydep[1:] - - if self.myaction=="--rebuild": - myeb=self.db[portage.root]["vartree"].dep_bestmatch(mydep2) - if not self.db[portage.root]["porttree"].exists_specific(myeb): - self.outdatedpackages.append(myeb) - return None - else: - myeb=self.db[portage.root]["porttree"].dep_bestmatch(mydep2) - if not myeb: - if not mykey: - print "\n!!! Warning: couldn't find match for",mydep - else: - print "\n!!! Warning: couldn't find match for",mydep,"in",mykey - return None - - # handle filtering of virtual deps for the rebuild action - if self.myaction=="--rebuild" and myeb[0:len("virtual")]=="virtual": - return None - - # handle filtering of non slot packages - if "noslot" in mymode and self.db[portage.root]["vartree"].slotted(myeb)==1: - return None - - if mydep[0]=="!": - myk="blocks "+myroot+" "+myeb - else: - if "--usepkg" in self.myopts: - mypk=self.db[portage.root]["bintree"].dep_bestmatch(mydep) - if myeb==mypk: - myk="binary "+portage.root+" "+mypk - else: - myk="ebuild "+myroot+" "+myeb - else: - myk="ebuild "+myroot+" "+myeb - - return myk - - def display(self,mylist): - for x in mylist: - if x[0]=="blocks": - addl=""+red("B")+" " - print "["+x[0]+" "+addl+"]",red(x[2]) - else: - if self.db[x[1]]["vartree"].exists_specific(x[2]): - addl=" "+yellow("R")+" " - elif self.db[x[1]]["vartree"].exists_specific_cat(x[2]): - addl=" "+turquoise("U")+" " - else: - addl=" "+green("N")+" " - print "["+x[0]+" "+addl+"]",x[2],"to",x[1] - - def outdated(self): - return self.outdatedpackages - - def merge(self,mylist): - returnme=0 - #check for blocking dependencies - for x in mylist: - if x[0]=="blocks": - print "\n!!! Error: the "+x[2]+" package conflicts with this package and both can't be installed on the same system together." - sys.exit(1) - - #above line used by --fetchonly - for x in mylist: - myroot=x[1] - print ">>> emerge",x[2],"to",x[1] - #the last argument in the portage.doebuild() tells doebuild to *not* do dep checking - #(emerge is already handling that) - y=self.db[myroot]["porttree"].getname(x[2]) - if x[0]=="ebuild": - if "--fetchonly" in self.myopts: - retval=portage.doebuild(y,"fetch",myroot,0,edebug) - if retval: - print - print "!!! Fetch for",y,"failed, continuing..." - print - returnme=1 - elif "--buildpkg" in self.myopts: - #create pkg, then merge pkg - retval=portage.doebuild(y,"clean",myroot,0,edebug) - if retval: - print "!!! emerge aborting on ",y,"." - sys.exit(1) - retval=portage.doebuild(y,"package",myroot,0,edebug) - if retval: - print "!!! emerge aborting on ",y,"." - sys.exit(1) - #dynamically update our database - self.db[portage.root]["bintree"].inject(x[2]) - mytbz2=self.db[portage.root]["bintree"].getname(x[2]) - retval=portage.pkgmerge(mytbz2,myroot) - if retval==None: - print "!!! emerge aborting on ",y,"." - sys.exit(1) - else: - retval=portage.doebuild(y,"clean",myroot,0,edebug) - if retval: - print "!!! emerge aborting on ",y,"." - sys.exit(1) - retval=portage.doebuild(y,"merge",myroot,0,edebug) - if retval: - print "!!! emerge aborting on ",y,"." - sys.exit(1) - #dynamically update our database - elif x[0]=="binary": - #merge the tbz2 - mytbz2=self.db[portage.root]["bintree"].getname(x[2]) - retval=portage.pkgmerge(mytbz2,x[1]) - if retval==None: - print "!!! emerge aborting on ",y,"." - sys.exit(1) - #need to check for errors - self.db[x[1]]["vartree"].inject(x[2]) - if "--autoclean" in self.myopts: - retval=portage.doebuild(y,"clean",myroot,0,edebug) - if retval: - print "!!! emerge aborting on ",y,"." - sys.exit(1) - #my doing an exit this way, --fetchonly can continue to try to - #fetch everything even if a particular download fails. - if "--fetchonly" in self.myopts: - if returnme: - print "\n\n!!! Some fetch errors were encountered. Please see above for details.\n\n" - sys.exit(returnme) - else: - sys.exit(0) - -def post_emerge(retval=0): - auxpat=re.compile('^([^-]*)(-\d+)?\.info(-\d+)?(\.gz)?') - global myopts - print - if "--pretend" in myopts: - sys.exit(retval) - root=portage.root - if not os.path.isdir(root+"usr/share/info"): - print " "+root+"usr/share/info doesn't exist, skipping info regeneration." - elif not os.path.exists("/usr/bin/install-info"): - print " /usr/bin/install-info doesn't exist; skipping info regeneration." - else: - print " "+green("*")+" Regenerating GNU info directory index..." - if os.path.exists(root+"usr/share/info/dir"): - os.rename(root+"usr/share/info/dir",root+"usr/share/info/dir.old") - icount=0 - badcount=0 - for x in os.listdir(root+"usr/share/info"): - aux=auxpat.search(x) - if not aux: - continue - auxgroups=aux.groups() - if not (auxgroups[1] or auxgroups[2]): - myso=commands.getstatusoutput("/usr/bin/install-info --dir-file="+root+"usr/share/info/dir "+root+"usr/share/info/"+x)[1] - if myso!="": - print auxgroups - badcount=badcount+1 - if "--verbose" in myopts: - print myso - icount=icount+1 - if badcount: - if "--verbose" not in myopts: - print " "+yellow("*")+" Processed",icount,"info files:",badcount,"errors; type "+green("emerge --verbose")+" to view errors." - else: - print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors." - - else: - print " "+green("*")+" Processed",icount,"info files." - if portage.settings["CONFIG_PROTECT"]: - #number of directories with some protect files in them - procount=0 - for x in string.split(portage.settings["CONFIG_PROTECT"]): - if os.path.isdir(x): - a=commands.getstatusoutput("cd "+x+"; find -iname '._cfg????_*'") - if a[0]!=0: - print " "+red("*")+" error scanning",x - else: - files=string.split(a[1]) - if files: - procount=procount+1 - print " "+yellow("* IMPORTANT:")+"",len(files),"config files in",x,"need updating." - if procount: - print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files." - print - sys.exit(retval) - -# general options that should be taken into account before any action -if not portage.settings.has_key("MAINTAINER_noclean"): - if not "--autoclean" in myopts: - myopts.append("--autoclean") -if "--debug" in myopts: - edebug=1 - -# process modes that aren't in the universal emerge interface format first -# this format is 'emerge --action --option --option [packageset]' -if "rsync" in mymode and not myaction: - if not os.path.exists("/usr/bin/rsync"): - print "!!! /usr/bin/rsync does not exist, so rsync support is disabled." - sys.exit(1) - rclean=0 - myportdir=portage.settings["PORTDIR"] - if myportdir[-1]=="/": - myportdir=myportdir[:-1] - if not os.path.exists(myportdir): - print ">>>",myportdir,"not found, creating it." - os.makedirs(myportdir,0755) - if "--clean" in myopts: - #we'll --delete files when we rsync - rclean=1 - mycommand="/usr/bin/rsync -rlptDv --stats --progress " - if rclean: - mycommand=mycommand+"--delete --exclude='distfiles/*' --exclude='packages/*' " - mycommand=mycommand+"rsync://cvs.gentoo.org/gentoo-x86-portage/* "+myportdir - print ">>> starting rsync with cvs.gentoo.org..." - #protect users that did not set a default umask - os.umask(022) - sys.exit(os.system(mycommand)) - -# HELP action -elif "--help"==myaction: - if len(mymode)==0: - print - print bold("Usage: ")+turquoise("emerge")+" [ "+green("action")+" ] [ "+green("options")+" ] [ "+turquoise("ebuildfile")+" | "+turquoise("tbz2file")+" | "+turquoise("dependency")+" ] ..." - print " "+turquoise("emerge")+" [ "+green("action")+" ] [ "+green("options")+" ] [ "+turquoise("system")+" | "+turquoise("world")+" | "+turquoise("noslot")+" ]" - print " "+turquoise("emerge")+" [ "+green("--clean")+" "+green("-c")+" ] "+turquoise("rsync") - print " "+turquoise("emerge")+" "+green("--help")+" "" "+green("-h")+" [ "+turquoise("rsync")+" | "+turquoise("system")+" | "+turquoise("world")+" | "+turquoise("noslot")+" | "+turquoise("config")+" ] " - print - print turquoise("Actions:") - print " "+green("--help")+" "+green("-h") - print " displays this help, an additional mode specifier provides" - print " detailed help about that mode instead" - print - print " "+green("--update")+" "+green("-u") - print " updates installed packages, this is typically used with",bold("world") - print " and",bold("system") - print - print " "+green("--zap")+" "+green("-z") - print " removes an installed package. the arguments can be in two" - print " different formats : /var/db/pkg/category/package-version" - print " or category/package." - print - print " "+green("--rebuild")+" "+green("-r") - print " forcably rebuild installed packages, this is typically used with" - print " "+bold("world"),"and",bold("system") - print - print " "+green("--search")+" "+green("-s") - print " searches for matches of the supplied string in the current local" - print " portage tree. The search string is a regular expression." - print " A few examples: " - print " "+bold("emerge --search \"^kde\"") - print " list all packages starting with kde" - print " "+bold("emerge --search \"gcc$\"") - print " list all packages ending with gcc" - print " "+bold("emerge --search \"\"")+" or" - print " "+bold("emerge --search \"*\"") - print " list all available packages " - print - print turquoise("Options:") - print " "+green("--autoclean")+" "+green("-a") - print " emerge normally cleans out the package-specific temporary" - print " build directory before it starts the building a package. With" - print " --autoclean, it will also clean the directory *after* the" - print " build completes. This option is automatically enabled for" - print " normal users, but maintainers can use this option to enable" - print " autocleaning." - print - print " "+green("--buildpkg")+" "+green("-b") - print " tell emerge to build binary packages for all ebuilds processed" - print " (in addition to actually merging the packages. Useful for" - print " maintainers or if you administrate multiple Gentoo Linux" - print " systems (build once, emerge tbz2s everywhere)." - print - print " "+green("--debug")+" "+green("-d") - print " Tell emerge to run the ebuild command in --debug mode. In this" - print " mode, the bash build environment will run with the -x option," - print " causing it to output verbose debug information print to stdout." - print " --debug is great for finding bash syntax errors." - print - print " "+green("--fetchonly")+" "+green("-f") - print " Instead of doing any package building, just perform fetches for" - print " all packages (main package as well as all dependencies.)" - print - print " "+green("--onlydeps")+" "+green("-o") - print " Only merge (or pretend to merge) the dependencies of the" - print " specified packages, not the packages themselves." - print - print " "+green("--pretend")+" "+green("-p") - print " instead of actually performing the merge, simply display what" - print " ebuilds and tbz2s *would* have been installed if --pretend" - print " weren't used. Using --pretend is strongly recommended before" - print " installing an unfamiliar package. In the printout, N = new," - print " U = upgrading, R = replacing" - print - print " "+green("--noreplace")+" "+green("-n") - print " Skip the packages specified on the command-line that have" - print " already been installed. Without this option, any packages," - print " ebuilds, or deps you specify on on the command-line *will* cause" - print " Portage to remerge the package, even if it is already installed." - print " Note that Portage will never remerge dependencies automatically." - print - print " "+green("--usepkg")+" "+green("-k") - print " tell emerge to use binary packages (from $PKGDIR) if they are" - print " available, thus possibly avoiding some time-consuming compiles." - print " This option is useful for CD installs; you can export" - print " PKGDIR=/mnt/cdrom/packages and then use this option to have" - print " emerge \"pull\" binary packages from the CD in order to satisfy" - print " dependencies." - print - print " "+green("--verbose")+" "+green("-v") - print " Tell emerge to run in verbose mode. Currently, this causes" - print " emerge to print out GNU info errors, if any." - print - elif "rsync" in mymode: - print - print bold("Usage: ")+turquoise("emerge")+" [ "+green("--clean")+" "+green("-c")+" ] "+turquoise("rsync") - print - print " \"emerge rsync\" initiates an rsync update with cvs.gentoo.org," - print " updating your Portage tree (typically in /usr/portage). This option" - print " will erase any changes that you have made to existing Portage files" - print " so be careful. \"emerge --clean rsync\" does the same thing as \"emerge" - print " rsync\", but files that no longer exist on our server are removed." - print - elif "system" in mymode: - print - print bold("Usage: ")+turquoise("emerge")+" [ "+green("action")+" ] "+" [ "+green("options")+" ] "+turquoise("system") - print - print " \"emerge system\" is the Portage system update command. When run, it" - print " will scan the etc/make.profile/packages file and determine what" - print " packages need to be installed so that your system meets the minimum" - print " requirements of your current system profile. Note that this doesn't" - print " necessarily bring your system up-to-date at all; instead, it just" - print " ensures that you have no missing parts. For example, if your system" - print " profile specifies that you should have sys-apps/iptables installed" - print " and you don't, then \"emerge system\" will install it (the most" - print " recent version that matches the profile spec) for you. It's always a" - print " good idea to do an \"emerge --pretend system\" before an \"emerge" - print " system\", just so you know what emerge is planning to do." - print - elif "world" in mymode: - print - print bold("Usage: ")+turquoise("emerge")+" [ "+green("action")+" ] "+" [ "+green("options")+" ] "+turquoise("world") - print - elif "noslot" in mymode: - print - print bold("Usage: ")+turquoise("emerge")+" [ "+green("action")+" ] "+" [ "+green("options")+" ] "+turquoise("noslot") - print - elif "config" in mymode: - outstuff=green("Config file management support (preliminary)")+""" - -Portage has a special feature called "config file protection". The purpose of -this feature is to prevent new package installs from clobbering existig -configuration files. By default, config file protection is turned on for /etc -and the KDE configuration dirs; more may be added in the future. - -When Portage installs a file into a protected directory tree like /etc, any -existing files will not be overwritten. If a file of the same name already -exists, Portage will change the name of the to-be- installed file from 'foo' to -'._cfg0000_foo'. If '._cfg0000_foo' already exists, this name becomes -'._cfg0001_foo', etc. In this way, existing files are not overwritten, -allowing the administrator to manually merge the new config files and avoid any -unexpected changes. - -In addition to protecting overwritten files, Portage will not delete any files -from a protected directory when a package is unmerged. While this may be a -little bit untidy, it does prevent potentially valuable config files from being -deleted, which is of paramount importance. - -Protected directories are set using the CONFIG_PROTECT variable, normally -defined in /etc/make.globals. Directory exceptions to the CONFIG_PROTECTed -directories can be specified using the CONFIG_PROTECT_MASK variable. To find -files that need to be updated in /etc, type: - -# find /etc -iname '._cfg????_*' - -You can disable this feature by setting CONFIG_PROTECT="" in /etc/make.conf. -Then, Portage will mercilessly auto-update your config files. Alternatively, -you can leave Config File Protection on but tell Portage that it can overwrite -files in certain specific /etc subdirectories. For example, if you wanted -Portage to automatically update your rc scripts and your wget configuration, -but didn't want any other changes made without your explicit approval, you'd -add this to /etc/make.conf: - -CONFIG_PROTECT_MASK="/etc/wget /etc/rc.d" - -""" - print outstuff - -# SEARCH action -elif "--search"==myaction: - if not myfiles: - print - print "No search terms provided." - print - else: - searchinstance = search() - for mysearch in myfiles: - searchinstance.setKey(mysearch) - searchinstance.execute() - searchinstance.output() - -# ZAP action -elif "--zap"==myaction: - if not myfiles and not "noslot" in mymode: - print - print "No packages to unmerge have been provided." - print - else: - full_paths={} - full_ebuild_paths={} - full_package_paths={} - non_slot_packages=[] - - var_path=portage.root+"var/db/pkg" - if "noslot" in mymode: - localtree=portage.vartree(portage.root) - for x in localtree.getallnodes(): - if localtree.slotted(x)==0: - mymatches=localtree.dep_match(x) - for package in mymatches: - myfullpaths=localtree.getebuildpaths(package) - for full_path in myfullpaths : - if not os.path.exists(full_path): - print "The ebuild '"+full_path+"' couldn't be found." - print "Your portage installation tree seems to be corrupted." - else: - full_package_paths[full_path]=package - else: - # process all arguments, verify if they can be resolved to an installed - # ebuild file and add the absolute paths of these ebuild to a list - for x in myfiles: - - # an absolute path has been given - if (x[0]=='/'): - path_parts=split(x, '/') - if len(path_parts) != 6: - print "When providing an absolute path it should be" - print "in the following format : "+var_path+"/category/package" - print "The path '"+x+"' doesn't respect this." - sys.exit(1) - elif not os.path.exists(x): - print "The path '"+x+"' doesn't exist." - sys.exit(1) - elif -1 == find(x, var_path): - print "The path '"+x+"' didn't commence with '"+var_path+"'." - sys.exit(1) - else: - # check if the SLOT file is present, and get the package version - # from the PF file in that case - package_slot_path=strip(x)+"/SLOT" - package_pf_path=strip(x)+"/PF" - if os.path.exists(package_pf_path): - package_pf_file=open(package_pf_path) - package_pf=package_pf_file.readline().strip() - package_pf_file.close() - else: - package_pf=path_parts[5] - full_path=strip(x)+"/"+package_pf+".ebuild" - if not os.path.exists(full_path): - print "The ebuild '"+full_path+"' couldn't be found." - print "Your portage installation tree seems to be corrupted." - else: - path_parts=split(full_path, "/") - full_ebuild_paths[full_path]=path_parts[4]+"/"+package_pf - - # a category and package name have been given - else: - localtree=portage.vartree(portage.root) - mymatches=localtree.dep_match(x) - # if no matches were found, try again by adding a '=' dep symbol if no - # dep symbols are already present - if not mymatches and x[0] not in ('<','>','=','~'): - mymatches=localtree.dep_match("="+x) - - # only loops over the matches if they were found - if mymatches: - for package in mymatches: - myfullpaths=localtree.getebuildpaths(package) - for full_path in myfullpaths : - if not os.path.exists(full_path): - print "The ebuild '"+full_path+"' couldn't be found." - print "Your portage installation tree seems to be corrupted." - else: - full_package_paths[full_path]=package - - # determine what the non slot packages are - if len(full_package_paths) > 0: - # determine the latest installed packages of each cat/pkg key - full_paths_keys=full_package_paths.keys() - # sort the ebuild paths - full_paths_keys.sort() - previous_package_set=None - for full_path in full_paths_keys: - # construct the key that will be used to determine when a new package set - # is being processed, the package slot is taken into account for this - package_parts=portage.pkgsplit(full_package_paths[full_path]) - slot_path=dirname(full_path)+"/SLOT" - if not os.path.exists(slot_path): - package_slot=package_parts[1] - non_slot_packages.append(package_parts[0]+"-"+package_parts[1]) - - full_paths=full_ebuild_paths.keys() - full_paths.extend(full_package_paths.keys()) - - if len(full_paths)==0: - print "Couldn't find any matching installed packages." - sys.exit(1) - else: - if "--pretend" in myopts: - print - print "The are the packages that I would unmerge :" - print - else: - print - print "The following packages are going to be unmerged :" - print - # this makes revisions come before slot versions - # and therefor unmerges the older packages first - full_paths.sort() - for full_path in full_paths: - path_parts=split(full_path, "/") - print " "+path_parts[4]+"/"+path_parts[5] - - if len(non_slot_packages)>0: - print - if "--verbose" not in myopts: - print " "+yellow("* IMPORTANT:"),len(non_slot_packages),"non slot packages; use "+green("--verbose")+" to view details." - else: - print " "+yellow("* IMPORTANT:"),len(non_slot_packages),"non slot packages" - print " "+yellow("*")+" These packages have been merged with an old version of portage that didn't" - print " "+yellow("*")+" support binary compatibility slots. This means that each package with a" - print " "+yellow("*")+" different version number will be considered different and only older versions" - print " "+yellow("*")+" of different releases will be unmerged automatically." - print " "+yellow("*")+" To get rid of all non slot packages, you can rebuild your system with" - print " "+yellow("*")+" "+green("emerge --noslot rebuild")+"." - print - for non_slot_package in non_slot_packages: - print " "+non_slot_package - - if "--pretend" in myopts: - print - else: - secs=string.atoi(portage.settings["UNMERGE_DELAY"]) - if secs > 0: - print - print "Waiting",secs,"seconds to make sure that you want these" - print "packages to be removed ..." - while secs > 0: - sys.stdout.write(str(secs)+" ") - sys.stdout.flush() - time.sleep(1) - secs = secs-1 - print secs - for full_path in full_paths: - print "Unmerging "+os.path.basename(full_path)+" ..." - retval=portage.doebuild(full_path,"unmerge",portage.root,0,edebug) - post_emerge() - -# REBUILD action -elif "--rebuild"==myaction: - if not "system" in mymode and not "world" in mymode and not "noslot" in mymode: - print - print " "+red("* WARNING:"),green("emerge --rebuild"),"shouldn't be used for regular packages" - print " "+red("*"),"it's only intended to be used with",green("system")+", "+green("world")+", and",green("noroot") - print - else: - if "--pretend" in myopts: - print - print "These are the packages that I would rebuild, in order." - print - - if "system" in mymode: - mydepgraph=depgraph(mymode,myaction,myopts) - print "Calculating system dependencies", - mydepgraph.syscreate(getsyslist()) - print " done!" - elif "world" in mymode or "noslot" in mymode: - mydepgraph=depgraph(mymode,myaction,myopts) - print "Calculating world dependencies", - mydepgraph.syscreate(mydepgraph.db["/"]["vartree"].getallnodes()) - print " done!" - - if "--pretend" in myopts: - mydepgraph.display(mydepgraph.altlist()) - - myoutdated=mydepgraph.outdated() - if len(myoutdated): - if "--verbose" not in myopts: - print - print " "+yellow("* IMPORTANT:"),len(myoutdated),"packages aren't available anymore; use "+green("--verbose")+" for details." - else: - print - print " "+yellow("* IMPORTANT:"),len(myoutdated),"packages aren't available anymore" - print " "+yellow("*")+" Your portage tree doesn't contain the ebuilds anymore that correspond to the" - print " "+yellow("*")+" following packages. This means that portage is unable to rebuild them." - print " "+yellow("*")+" Instead you should upgrade to the latest versions or install possible" - print " "+yellow("*")+" alternative packages that provide the same functionalities." - myoutdated.sort() - for mypackage in myoutdated: - print " "+mypackage - else: - mydepgraph.merge(mydepgraph.altlist()) - post_emerge() - -# INSTALL and UPDATE action -elif "--update"==myaction or not myaction: - if not myaction and "world" in mymode: - print - print " "+red("* WARNING:"),green("emerge world"),"can't be used without an action" - print " "+red("*"),green("world"),"is only intended to be used with",green("emerge --update") - print - else: - if "--pretend" in myopts: - print - print "These are the packages that I would merge, in order." - print - - if "system" in mymode: - mydepgraph=depgraph(mymode,myaction,myopts) - print "Calculating system dependencies", - mydepgraph.syscreate(getsyslist()) - print " done!" - elif "world" in mymode: - mydepgraph=depgraph(mymode,myaction,myopts) - print "Calculating world dependencies", - mydepgraph.syscreate(mydepgraph.db["/"]["vartree"].getallnodes()) - print " done!" - elif "noslot" in mymode: - mydepgraph=depgraph(mymode,myaction,myopts) - print "Calculating noslot dependencies", - mydepgraph.syscreate(mydepgraph.db["/"]["vartree"].getallnodes()) - print " done!" - else: - mydepgraph=depgraph(mymode,myaction,myopts) - if not myfiles: - post_emerge() - #we don't have any files to process; skip this step and exit - print "Calculating dependencies", - for mypkg in myfiles: - if mypkg[-5:]==".tbz2": - mytype="binary" - mytbz2=xpak.tbz2(mypkg) - mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.basename(mypkg)[:-5] - elif mypkg[-7:]==".ebuild": - mytype="ebuild" - mykey=os.path.basename(os.path.abspath(mypkg+"/../.."))+"/"+os.path.basename(mypkg)[:-7] - else: - mykey="" - if "--usepkg" in myopts: - mykey=mydepgraph.db[portage.root]["bintree"].dep_bestmatch(mypkg) - mytype="binary" - if not mykey: - mykey=mydepgraph.db[portage.root]["porttree"].dep_bestmatch(mypkg) - mytype="ebuild" - if not mykey: - print "!!! Couldn't find match for",mypkg+"; aborting." - sys.exit(1) - # else: - # print "!!! Error:",x,"is neither an ebuild nor a .tbz2 package." - # sys.exit(1) - mydepgraph.create(mytype+" "+portage.root+" "+mykey,None,"--onlydeps" not in myopts) - print " done!" - - if "--pretend" in myopts: - mydepgraph.display(mydepgraph.altlist()) - else: - mydepgraph.merge(mydepgraph.altlist()) - post_emerge() - -- 2.26.2