From d9fc4acc572c6647a4f27b838d35d27d805d190e Mon Sep 17 00:00:00 2001 From: Jason Stubbs Date: Sun, 28 Aug 2005 08:37:44 +0000 Subject: Migration (without history) of the current stable line to subversion. svn path=/main/branches/2.0/; revision=1941 --- bin/archive-conf | 101 ++ bin/chkcontents | 62 + bin/clean_locks | 36 + bin/dispatch-conf | 311 +++++ bin/dobin | 28 + bin/doconfd | 15 + bin/dodir | 8 + bin/dodoc | 23 + bin/doenvd | 15 + bin/doexe | 26 + bin/dohard | 13 + bin/dohtml | 159 +++ bin/doinfo | 21 + bin/doinitd | 15 + bin/doins | 53 + bin/dojar | 54 + bin/dolib | 41 + bin/dolib.a | 7 + bin/dolib.so | 7 + bin/doman | 52 + bin/domo | 26 + bin/dopython | 23 + bin/dosbin | 27 + bin/dosed | 22 + bin/dosym | 13 + bin/ebuild | 61 + bin/ebuild.sh | 1868 ++++++++++++++++++++++++++ bin/emake | 14 + bin/emerge | 3213 ++++++++++++++++++++++++++++++++++++++++++++ bin/emerge-webrsync | 141 ++ bin/emerge.orig | 3227 +++++++++++++++++++++++++++++++++++++++++++++ bin/env-update | 11 + bin/env-update.sh | 221 ++++ bin/etc-update | 407 ++++++ bin/find-requires | 44 + bin/fix-db.py | 175 +++ bin/fixdbentries | 20 + bin/fixpackages | 14 + bin/fowners | 15 + bin/fperms | 15 + bin/md5check.py | 102 ++ bin/md5check.sh | 31 + bin/mirror.py | 167 +++ bin/newbin | 13 + bin/newconfd | 13 + bin/newdoc | 13 + bin/newenvd | 13 + bin/newexe | 13 + bin/newinitd | 13 + bin/newins | 13 + bin/newlib.a | 13 + bin/newlib.so | 13 + bin/newman | 13 + bin/newsbin | 13 + bin/pemerge.py | 44 + bin/pkgmerge | 59 + bin/pkgmerge.new | 84 ++ bin/pkgname | 17 + bin/portage_gpg_update.sh | 6 + bin/portageq | 256 ++++ bin/prepall | 39 + bin/prepalldocs | 33 + bin/prepallinfo | 9 + bin/prepallman | 12 + bin/prepallstrip | 11 + bin/prepinfo | 45 + bin/preplib | 25 + bin/preplib.so | 10 + bin/prepman | 46 + bin/prepstrip | 48 + bin/quickpkg | 148 +++ bin/regenworld | 93 ++ bin/repoman | 1522 +++++++++++++++++++++ bin/xpak | 14 + 74 files changed, 13568 insertions(+) create mode 100755 bin/archive-conf create mode 100755 bin/chkcontents create mode 100755 bin/clean_locks create mode 100755 bin/dispatch-conf create mode 100755 bin/dobin create mode 100755 bin/doconfd create mode 100755 bin/dodir create mode 100755 bin/dodoc create mode 100755 bin/doenvd create mode 100755 bin/doexe create mode 100755 bin/dohard create mode 100755 bin/dohtml create mode 100755 bin/doinfo create mode 100755 bin/doinitd create mode 100755 bin/doins create mode 100755 bin/dojar create mode 100755 bin/dolib create mode 100755 bin/dolib.a create mode 100755 bin/dolib.so create mode 100755 bin/doman create mode 100755 bin/domo create mode 100755 bin/dopython create mode 100755 bin/dosbin create mode 100755 bin/dosed create mode 100755 bin/dosym create mode 100755 bin/ebuild create mode 100755 bin/ebuild.sh create mode 100755 bin/emake create mode 100755 bin/emerge create mode 100755 bin/emerge-webrsync create mode 100755 bin/emerge.orig create mode 100755 bin/env-update create mode 100755 bin/env-update.sh create mode 100755 bin/etc-update create mode 100755 bin/find-requires create mode 100755 bin/fix-db.py create mode 100755 bin/fixdbentries create mode 100755 bin/fixpackages create mode 100755 bin/fowners create mode 100755 bin/fperms create mode 100755 bin/md5check.py create mode 100755 bin/md5check.sh create mode 100755 bin/mirror.py create mode 100755 bin/newbin create mode 100755 bin/newconfd create mode 100755 bin/newdoc create mode 100755 bin/newenvd create mode 100755 bin/newexe create mode 100755 bin/newinitd create mode 100755 bin/newins create mode 100755 bin/newlib.a create mode 100755 bin/newlib.so create mode 100755 bin/newman create mode 100755 bin/newsbin create mode 100755 bin/pemerge.py create mode 100755 bin/pkgmerge create mode 100755 bin/pkgmerge.new create mode 100755 bin/pkgname create mode 100755 bin/portage_gpg_update.sh create mode 100755 bin/portageq create mode 100755 bin/prepall create mode 100755 bin/prepalldocs create mode 100755 bin/prepallinfo create mode 100755 bin/prepallman create mode 100755 bin/prepallstrip create mode 100755 bin/prepinfo create mode 100755 bin/preplib create mode 100755 bin/preplib.so create mode 100755 bin/prepman create mode 100755 bin/prepstrip create mode 100755 bin/quickpkg create mode 100755 bin/regenworld create mode 100755 bin/repoman create mode 100755 bin/xpak (limited to 'bin') diff --git a/bin/archive-conf b/bin/archive-conf new file mode 100755 index 000000000..6e198f49f --- /dev/null +++ b/bin/archive-conf @@ -0,0 +1,101 @@ +#!/usr/bin/python +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/archive-conf,v 1.7 2004/10/04 13:57:36 vapier Exp $ + +# +# archive-conf -- save off a config file in the dispatch-conf archive dir +# +# Written by Wayne Davison with code snagged from +# Jeremy Wohl's dispatch-conf script and the portage chkcontents script. +# + +import os, sys, string +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage, dispatch_conf + +FIND_EXTANT_CONTENTS = "find %s -name CONTENTS" + +MANDATORY_OPTS = [ 'archive-dir' ] + +try: + import fchksum + def perform_checksum(filename): return fchksum.fmd5t(filename) +except ImportError: + import md5 + def md5_to_hex(md5sum): + hexform = "" + for ix in xrange(len(md5sum)): + hexform = hexform + "%02x" % ord(md5sum[ix]) + return string.lower(hexform) + + def perform_checksum(filename): + f = open(filename, 'rb') + blocksize=32768 + data = f.read(blocksize) + size = 0L + sum = md5.new() + while data: + sum.update(data) + size = size + len(data) + data = f.read(blocksize) + return (md5_to_hex(sum.digest()),size) + +def archive_conf(): + args = [] + content_files = [] + md5_match_hash = {} + + options = dispatch_conf.read_config(MANDATORY_OPTS) + + for conf in sys.argv[1:]: + if not os.path.isabs(conf): + conf = os.path.abspath(conf) + args += [ conf ] + md5_match_hash[conf] = '' + + # Find all the CONTENT files in VDB_PATH. + content_files += os.popen(FIND_EXTANT_CONTENTS % (portage.root+portage.VDB_PATH)).readlines() + + # Search for the saved md5 checksum of all the specified config files + # and see if the current file is unmodified or not. + try: + todo_cnt = len(args) + for file in content_files: + file = file.rstrip() + try: + contents = open(file, "r") + except IOError, e: + print >> sys.stderr, 'archive-conf: Unable to open %s: %s' % (file, e) + sys.exit(1) + lines = contents.readlines() + for line in lines: + items = string.split(line) + if items[0] == 'obj': + for conf in args: + if items[1] == conf: + stored = string.lower(items[2]) + real = string.lower(perform_checksum(conf)[0]) + if stored == real: + md5_match_hash[conf] = conf + todo_cnt -= 1 + if todo_cnt == 0: + raise "Break" + except "Break": + pass + + for conf in args: + archive = os.path.join(options['archive-dir'], conf.lstrip('/')) + if options['use-rcs'] == 'yes': + dispatch_conf.rcs_archive(archive, conf, md5_match_hash[conf], '') + dispatch_conf.rcs_archive_post_process(archive) + else: + dispatch_conf.file_archive(archive, conf, md5_match_hash[conf], '') + dispatch_conf.file_archive_post_process(archive) + +# run +if len(sys.argv) > 1: + archive_conf() +else: + print >> sys.stderr, 'Usage: archive-conf /CONFIG/FILE [/CONFIG/FILE...]' diff --git a/bin/chkcontents b/bin/chkcontents new file mode 100755 index 000000000..eebf868cd --- /dev/null +++ b/bin/chkcontents @@ -0,0 +1,62 @@ +#!/usr/bin/python +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/chkcontents,v 1.11 2004/10/04 13:56:50 vapier Exp $ + +# Very simple program to compare the md5sums of a package as listed +# in VDB_PATH/category/package/CONTENTS with the md5sums of the +# actual programs on the system (and makes sure that symlinks point to +# the right files). + +import string, os.path, os, sys +sys.path = ["/usr/lib/portage/pym"]+sys.path +import portage + +def CONTENTScheck(path): + try: + contents = open(path, "r") + except IOError, e: + print "Unable to open %s: %s" % (path, e) + sys.exit(1) + lines = contents.readlines() + for line in lines: + items = string.split(line) + # items is a list w/ size depending on the type of item listed in item[0] + # if items[0] = 'dir' then items[1] is the path of a directory + # if items[0] = 'obj' then items[1] is the path of a file, + # items[2] is the file's md5sum, + # items[3] is the file's size + # if items[0] = 'sym' then items[1] is the path of a symbolic link, + # items[2] is '->' + # items[3] is the file the symlink should point to + # items[4] is the symlink mtime + if (items[0] == 'obj'): + md5stored = string.lower(items[2]) + # fchksum.fmdft(file) returns the file's md5sum and the file's size + md5real = string.lower(portage.perform_checksum(items[1])[0]) + if (md5stored != md5real): + if md5real: + print "%s has md5sum of %s instead of %s" % (items[1], md5real, md5stored) + else: + print "%s is missing!" % items[1] + elif (items[0] == 'sym'): + link = items[1] + target = items[3] + if (not os.path.islink(link)): + print "%s is not a symbolic link" % link + continue + actualtarget = os.readlink(link) + if (os.path.normpath(actualtarget) != os.path.normpath(target)): + print "%s points to %s, not %s" % (link, actualtarget, target) + + +if __name__ == '__main__': + import sys + if (len(sys.argv) != 2 or sys.argv[1] == "--help"): + print "This program compares md5sums in the file VDB_PATH/category/package/CONTENTS" + print "with the md5sums of the actual files on the filesystem" + print "(and makes sure that symlinks point to the right files)." + print "\nUsage: chkcontents path/to/CONTENTS" + sys.exit(1) + CONTENTScheck(sys.argv[1]) + diff --git a/bin/clean_locks b/bin/clean_locks new file mode 100755 index 000000000..aa6669c16 --- /dev/null +++ b/bin/clean_locks @@ -0,0 +1,36 @@ +#!/usr/bin/python -O +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/clean_locks,v 1.1 2004/09/26 10:44:31 carpaski Exp $ + +import os,sys +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage_locks + +if not sys.argv[1:] or "--help" in sys.argv or "-h" in sys.argv: + print + print "You must specify directories with hardlink-locks to clean." + print "You may optionally specify --force, which will remove all" + print "of the locks, even if we can't establish if they are in use." + print "Please attempt cleaning without force first." + print + print sys.argv[0]+" /usr/portage/distfiles/.locks" + print sys.argv[0]+" --force /usr/portage/distfiles/.locks" + print + sys.exit(1) + +force = False +if "--force" in sys.argv[1:]: + force=True + +for x in sys.argv[1:]: + if x == "--force": + continue + for y in portage_locks.hardlock_cleanup(x, remove_all_locks=force): + print y + print + + + + \ No newline at end of file diff --git a/bin/dispatch-conf b/bin/dispatch-conf new file mode 100755 index 000000000..2db6a329a --- /dev/null +++ b/bin/dispatch-conf @@ -0,0 +1,311 @@ +#!/usr/bin/python -O +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dispatch-conf,v 1.7.2.10 2005/05/12 15:20:22 jstubbs Exp $ + +# +# dispatch-conf -- Integrate modified configs, post-emerge +# +# Jeremy Wohl (http://igmus.org) +# +# TODO +# dialog menus +# + +from stat import * +from random import * +import os, shutil, sys, string, re, commands, atexit +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage, dispatch_conf + +FIND_EXTANT_CONFIGS = "find %s/ -iname '._cfg????_*' | sed -e 's://:/:g'" +DIFF_CONTENTS = 'diff -Nu %s %s' +DIFF_CVS_INTERP = 'diff -Nu %s %s | grep "^[+-][^+-]" | grep -v "# .Header:.*"' +DIFF_WSCOMMENTS = 'diff -Nu %s %s | grep "^[+-][^+-]" | grep -v "^[-+]#" | grep -v "^[-+][:space:]*$"' + +# We need a secure scratch dir and python does silly verbose errors on the use of tempnam +oldmask = os.umask(0077) +SCRATCH_DIR = None +while SCRATCH_DIR is None: + try: + mydir = "/tmp/dispatch-conf." + for x in range(0,8): + if int(random() * 3) == 0: + mydir += chr(int(65+random()*26.0)) + elif int(random() * 2) == 0: + mydir += chr(int(97+random()*26.0)) + else: + mydir += chr(int(48+random()*10.0)) + if os.path.exists(mydir): + continue + os.mkdir(mydir) + SCRATCH_DIR = mydir + except OSError, e: + if e.errno != 17: + raise +os.umask(oldmask) + +# Ensure the scratch dir is deleted +def cleanup(mydir=SCRATCH_DIR): + shutil.rmtree(SCRATCH_DIR) +atexit.register(cleanup) + +MANDATORY_OPTS = [ 'archive-dir', 'diff', 'replace-cvs', 'replace-wscomments', 'merge' ] + +class dispatch: + options = {} + + def grind (self, config_paths): + confs = [] + count = 0 + + + self.options = dispatch_conf.read_config(MANDATORY_OPTS) + + if self.options.has_key("log-file"): + if os.path.exists(self.options["log-file"]): + shutil.copyfile(self.options["log-file"], self.options["log-file"] + '.old') + os.remove(self.options["log-file"]) + else: + self.options["log-file"] = "/dev/null" + + # + # Build list of extant configs + # + + for path in config_paths.split (): + if not os.path.exists (path): + continue + + confs += self.massage (os.popen (FIND_EXTANT_CONFIGS % (path,)).readlines ()) + + if self.options['use-rcs'] == 'yes' and ((os.system( "which rcs >/dev/null 2>&1" ) == 256) + or (os.system( "which ci >/dev/null 2>&1" ) == 256) + or (os.system( "which co >/dev/null 2>&1" ) == 256) + or (os.system( "which rcsmerge >/dev/null 2>&1" ) == 256)): + print >> sys.stderr, 'dispatch-conf: Error finding all RCS utils and use-rcs=yes in config; fatal' + return False + + + # + # Remove new configs identical to current + # and + # Auto-replace configs a) whose differences are simply CVS interpolations, + # or b) whose differences are simply ws or comments, + # or c) in paths now unprotected by CONFIG_PROTECT_MASK, + # + + def f (conf): + mrgconf = re.sub(r'\._cfg', '._mrg', conf['new']) + archive = os.path.join(self.options['archive-dir'], conf['current'].lstrip('/')) + if self.options['use-rcs'] == 'yes': + mrgfail = dispatch_conf.rcs_archive(archive, conf['current'], conf['new'], mrgconf) + else: + mrgfail = dispatch_conf.file_archive(archive, conf['current'], conf['new'], mrgconf) + if os.path.exists(archive + '.dist'): + unmodified = len(commands.getoutput(DIFF_CONTENTS % (conf['current'], archive + '.dist'))) == 0 + else: + unmodified = 0 + if os.path.exists(mrgconf): + if mrgfail or len(commands.getoutput(DIFF_CONTENTS % (conf['new'], mrgconf))) == 0: + os.unlink(mrgconf) + newconf = conf['new'] + else: + newconf = mrgconf + else: + newconf = conf['new'] + + same_file = len(commands.getoutput (DIFF_CONTENTS % (conf ['current'], newconf))) == 0 + same_cvs = len(commands.getoutput (DIFF_CVS_INTERP % (conf ['current'], newconf))) == 0 + same_wsc = len(commands.getoutput (DIFF_WSCOMMENTS % (conf ['current'], newconf))) == 0 + + # Do options permit? + same_cvs = same_cvs and self.options['replace-cvs'] == 'yes' + same_wsc = same_wsc and self.options['replace-wscomments'] == 'yes' + unmodified = unmodified and self.options['replace-unmodified'] == 'yes' + + if same_file: + os.unlink (conf ['new']) + self.post_process(conf['current']) + if os.path.exists(mrgconf): + os.unlink(mrgconf) + return False + elif unmodified or same_cvs or same_wsc or conf ['dir'] in portage.settings ['CONFIG_PROTECT_MASK'].split (): + self.replace(newconf, conf['current']) + self.post_process(conf['current']) + if newconf == mrgconf: + os.unlink(conf['new']) + elif os.path.exists(mrgconf): + os.unlink(mrgconf) + return False + else: + return True + + confs = filter (f, confs) + + # + # Interactively process remaining + # + + for conf in confs: + count = count + 1 + + newconf = conf['new'] + mrgconf = re.sub(r'\._cfg', '._mrg', newconf) + if os.path.exists(mrgconf): + newconf = mrgconf + show_new_diff = 0 + + while 1: + if show_new_diff: + os.system((self.options['diff']) % (conf['new'], mrgconf)) + show_new_diff = 0 + else: + os.system((self.options['diff']) % (conf['current'], newconf)) + + print + print '>> (%i of %i) -- %s' % (count, len(confs), conf ['current']) + print '>> q quit, h help, n next, e edit-new, z zap-new, u use-new\n m merge, t toggle-merge, l look-merge: ', + + c = getch () + + if c == 'q': + sys.exit (0) + if c == 'h': + self.do_help () + continue + elif c == 't': + if newconf == mrgconf: + newconf = conf['new'] + elif os.path.exists(mrgconf): + newconf = mrgconf + continue + elif c == 'n': + break + elif c == 'm': + merged = SCRATCH_DIR+"/"+os.path.basename(conf['current']) + print + os.system (self.options['merge'] % (merged, conf ['current'], newconf)) + shutil.copyfile(merged, mrgconf) + os.remove(merged) + mystat = os.lstat(conf['new']) + os.chmod(mrgconf, mystat[ST_MODE]) + os.chown(mrgconf, mystat[ST_UID], mystat[ST_GID]) + newconf = mrgconf + continue + elif c == 'l': + show_new_diff = 1 + continue + elif c == 'e': + os.system(os.environ['EDITOR'] + ' ' + newconf) + continue + elif c == 'z': + os.unlink(conf['new']) + if os.path.exists(mrgconf): + os.unlink(mrgconf) + break + elif c == 'u': + self.replace(newconf, conf ['current']) + self.post_process(conf['current']) + if newconf == mrgconf: + os.unlink(conf['new']) + elif os.path.exists(mrgconf): + os.unlink(mrgconf) + break + else: + continue + + + def replace (self, newconf, curconf): + """Replace current config with the new/merged version. Also logs + the diff of what changed into the configured log file.""" + os.system((DIFF_CONTENTS % (curconf, newconf)) + '>>' + self.options["log-file"]) + try: + shutil.copyfile(newconf, curconf) + os.remove(newconf) + except (IOError, os.error), why: + print >> sys.stderr, 'dispatch-conf: Error renaming %s to %s: %s; fatal' % \ + (newconf, curconf, str(why)) + + + def post_process(self, curconf): + archive = os.path.join(self.options['archive-dir'], curconf.lstrip('/')) + if self.options['use-rcs'] == 'yes': + dispatch_conf.rcs_archive_post_process(archive) + else: + dispatch_conf.file_archive_post_process(archive) + + + def massage (self, newconfigs): + """Sort, rstrip, remove old versions, break into triad hash. + + Triad is dictionary of current (/etc/make.conf), new (/etc/._cfg0003_make.conf) + and dir (/etc). + + We keep ._cfg0002_conf over ._cfg0001_conf and ._cfg0000_conf. + """ + h = {} + + newconfigs.sort () + + for nconf in newconfigs: + nconf = nconf.rstrip () + conf = re.sub (r'\._cfg\d+_', '', nconf) + dir = re.match (r'^(.+)/', nconf).group (1) + + if h.has_key (conf): + mrgconf = re.sub(r'\._cfg', '._mrg', h[conf]['new']) + if os.path.exists(mrgconf): + os.unlink(mrgconf) + os.unlink(h[conf]['new']) + + h [conf] = { 'current' : conf, 'dir' : dir, 'new' : nconf } + + configs = h.values () + configs.sort (lambda a, b: cmp(a ['current'], b ['current'])) + + return configs + + + def do_help (self): + print; print + + print ' u -- update current config with new config and continue' + print ' z -- zap (delete) new config and continue' + print ' n -- skip to next config, leave all intact' + print ' e -- edit new config' + print ' m -- interactively merge current and new configs' + print ' l -- look at diff between pre-merged and merged configs' + print ' t -- toggle new config between merged and pre-merged state' + print ' h -- this screen' + print ' q -- quit' + + print; print 'press any key to return to diff...', + + getch () + + +def getch (): + # from ASPN - Danny Yoo + # + import sys, tty, termios + + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(sys.stdin.fileno()) + ch = sys.stdin.read(1) + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + return ch + + +# run +d = dispatch () + +if len(sys.argv) > 1: + # for testing + d.grind (string.join (sys.argv [1:])) +else: + d.grind (portage.settings ['CONFIG_PROTECT']) diff --git a/bin/dobin b/bin/dobin new file mode 100755 index 000000000..4c070d95b --- /dev/null +++ b/bin/dobin @@ -0,0 +1,28 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dobin,v 1.13 2004/10/04 13:56:50 vapier Exp $ + +if [ ${#} -lt 1 ] ; then + echo "${0}: at least one argument needed" + exit 1 +fi + +if [ ! -d "${D}${DESTTREE}/bin" ] ; then + install -d "${D}${DESTTREE}/bin" || exit 2 +fi + +for x in "$@" ; do + if [ -x "${x}" ] ; then + #if executable, use existing perms + install "${x}" "${D}${DESTTREE}/bin" || exit 3 + else + #otherwise, use reasonable defaults + echo ">>> dobin: making ${x} executable..." + if [ "$USERLAND" == "GNU" ]; then + install -m0755 -o root -g root "${x}" "${D}${DESTTREE}/bin" || exit 4 + else + install -m0755 -o root -g wheel "${x}" "${D}${DESTTREE}/bin" || exit 4 + fi + fi +done diff --git a/bin/doconfd b/bin/doconfd new file mode 100755 index 000000000..73d5cedcf --- /dev/null +++ b/bin/doconfd @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright 1999-2005 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/doconfd,v 1.2.2.1 2005/01/13 04:51:56 vapier Exp $ + +if [ ${#} -lt 1 ] ; then + echo "doconfd: at least one argument needed" + exit 1 +fi + +tmp_INSDESTTREE="${INSDESTTREE}" +INSDESTTREE=/etc/conf.d/ +doins "$@" +INSDESTTREE="${tmp_INSDESTTREE}" +unset tmp_INSDESTTREE diff --git a/bin/dodir b/bin/dodir new file mode 100755 index 000000000..6df8f4031 --- /dev/null +++ b/bin/dodir @@ -0,0 +1,8 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dodir,v 1.5 2004/10/04 13:56:50 vapier Exp $ + +for x in "$@" ; do + install -d ${DIROPTIONS} "${D}${x}" +done diff --git a/bin/dodoc b/bin/dodoc new file mode 100755 index 000000000..a25aeddb9 --- /dev/null +++ b/bin/dodoc @@ -0,0 +1,23 @@ +#!/bin/bash +# Copyright 1999-2005 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dodoc,v 1.6.2.2 2005/05/15 11:04:21 jstubbs Exp $ + +if [ $# -lt 1 ] ; then + echo "$0: at least one argument needed" 1>&2 + exit 1 +fi + +dir="${D}usr/share/doc/${PF}/${DOCDESTTREE}" +if [ ! -d "${dir}" ] ; then + install -d "${dir}" +fi + +for x in "$@" ; do + if [ -s "${x}" ] ; then + install -m0644 "${x}" "${dir}" + gzip -f -9 "${dir}/${x##*/}" + elif [ ! -e "${x}" ] ; then + echo "dodoc: ${x} does not exist" 1>&2 + fi +done diff --git a/bin/doenvd b/bin/doenvd new file mode 100755 index 000000000..8a794d7f6 --- /dev/null +++ b/bin/doenvd @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright 1999-2005 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/doenvd,v 1.2.2.1 2005/01/13 04:51:56 vapier Exp $ + +if [ ${#} -lt 1 ] ; then + echo "doenvd: at least one argument needed" + exit 1 +fi + +tmp_INSDESTTREE="${INSDESTTREE}" +INSDESTTREE=/etc/env.d/ +doins "$@" +INSDESTTREE="${tmp_INSDESTTREE}" +unset tmp_INSDESTTREE diff --git a/bin/doexe b/bin/doexe new file mode 100755 index 000000000..9c2f41093 --- /dev/null +++ b/bin/doexe @@ -0,0 +1,26 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/doexe,v 1.10.2.1 2004/12/06 03:01:43 carpaski Exp $ + +mynum=${#} +if [ ${mynum} -lt 1 ] ; then + echo "doexe: at least one argument needed" + exit 1 +fi +if [ ! -d "${D}${EXEDESTTREE}" ] ; then + install -d "${D}${EXEDESTTREE}" +fi + +for x in "$@" ; do + if [ -L "${x}" ] ; then + cp "${x}" "${T}" + mysrc="${T}"/`/usr/bin/basename "${x}"` + elif [ -d "${x}" ] ; then + echo "doexe: warning, skipping directory ${x}" + continue + else + mysrc="${x}" + fi + install ${EXEOPTIONS} "${mysrc}" "${D}${EXEDESTTREE}" +done diff --git a/bin/dohard b/bin/dohard new file mode 100755 index 000000000..7313e2f24 --- /dev/null +++ b/bin/dohard @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dohard,v 1.6 2004/10/04 13:56:50 vapier Exp $ + +if [ ${#} -ne 2 ] ; then + echo "${0}: two arguments needed" + exit 1 +fi + +mysrc="${1}" +mydest="${2}" +ln -f "${D}${mysrc}" "${D}${mydest}" diff --git a/bin/dohtml b/bin/dohtml new file mode 100755 index 000000000..50e13924a --- /dev/null +++ b/bin/dohtml @@ -0,0 +1,159 @@ +#!/usr/bin/python +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dohtml,v 1.14.2.1 2004/10/27 14:39:29 jstubbs Exp $ + +# +# Typical usage: +# dohtml -r docs/* +# - put all files and directories in docs into /usr/share/doc/${PF}/html +# dohtml foo.html +# - put foo.html into /usr/share/doc/${PF}/html +# +# +# Detailed usage: +# dohtml +# - will install the files in the list of files (space-separated list) into +# /usr/share/doc/${PF}/html, provided the file ends in .html, .png, .jpg +# or .css +# dohtml -r +# - will do as 'dohtml', but recurse into all directories, as long as the +# directory name is not CVS +# dohtml -A jpe,java [-r] +# - will do as 'dohtml' but add .jpe,.java (default filter list is +# added to your list) +# dohtml -a png,gif,html,htm [-r] +# - will do as 'dohtml' but filter on .png,.gif,.html,.htm (default filter +# list is ignored) +# dohtml -x CVS,SCCS,RCS -r +# - will do as 'dohtml -r', but ignore directories named CVS, SCCS, RCS +# + +import os +import string +import sys +import types + +def dodir(path): + os.system("install -d '%s'" % path) + +def dofile(src,dst): + + os.system("install -m0644 '%s' '%s'" % (src, dst)) + +def install(basename, dirname, options, prefix=""): + + fullpath = basename + if prefix: fullpath = prefix + "/" + fullpath + if dirname: fullpath = dirname + "/" + fullpath + + if options.DOCDESTTREE: + destdir = options.D + "usr/share/doc/" + options.PF + "/" + options.DOCDESTTREE + "/" + options.doc_prefix + "/" + prefix + else: + destdir = options.D + "usr/share/doc/" + options.PF + "/html/" + options.doc_prefix + "/" + prefix + + if os.path.isfile(fullpath): + ext = os.path.splitext(basename)[1] + if (len(ext) and ext[1:] in options.allowed_exts) or basename in options.allowed_files: + dodir(destdir) + dofile(fullpath, destdir + "/" + basename) + elif options.recurse and os.path.isdir(fullpath) and \ + basename not in options.disallowed_dirs: + for i in os.listdir(fullpath): + pfx = basename + if prefix: pfx = prefix + "/" + pfx + install(i, dirname, options, pfx) + +class OptionsClass: + def __init__(self): + self.PF = "" + self.D = "" + self.DOCDESTTREE = "" + + if os.environ.has_key("PF"): + self.PF = os.environ["PF"] + if os.environ.has_key("D"): + self.D = os.environ["D"] + if os.environ.has_key("DOCDESTTREE"): + self.DOCDESTTREE = os.environ["DOCDESTTREE"] + + self.allowed_exts = [ 'png', 'gif', 'html', 'htm', 'jpg', 'css', 'js' ] + self.allowed_files = [] + self.disallowed_dirs = [ 'CVS' ] + self.recurse = False + self.verbose = False + self.doc_prefix = "" + +def print_help(): + opts = OptionsClass() + + print "dohtml [-a .foo,.bar] [-A .foo,.bar] [-f foo,bar] [-x foo,bar]" + print " [-r] [-V] [file ...]" + print + print " -a Set the list of allowed to those that are specified." + print " Default:", string.join(opts.allowed_exts, ",") + print " -A Extend the list of allowed file types." + print " -f Set list of allowed extensionless file names." + print " -x Set directories to be excluded from recursion." + print " Default:", string.join(opts.disallowed_dirs, ",") + print " -r Install files and directories recursively." + print " -V Be verbose." + print + +def parse_args(): + options = OptionsClass() + args = [] + + x = 1 + while x < len(sys.argv): + arg = sys.argv[x] + if arg in ["-h","-r","-V"]: + if arg == "-h": + print_help() + sys.exit(0) + elif arg == "-r": + options.recurse = True + elif arg == "-V": + options.verbose = True + elif sys.argv[x] in ["-A","-a","-f","-x","-p"]: + x += 1 + if x == len(sys.argv): + print_help() + sys.exit(0) + elif arg == "-p": + options.doc_prefix = sys.argv[x] + else: + values = string.split(sys.argv[x], ",") + if arg == "-A": + options.allowed_exts.extend(values) + elif arg == "-a": + options.allowed_exts = values + elif arg == "-f": + options.allowed_files = values + elif arg == "-x": + options.disallowed_dirs = values + else: + args.append(sys.argv[x]) + x += 1 + + return (options, args) + +def main(): + + (options, args) = parse_args() + + if type(options.allowed_exts) == types.StringType: + options.allowed_exts = options.allowed_exts.split(",") + + if options.verbose: + print "Allowed extensions:", options.allowed_exts + print "Document prefix : '" + options.doc_prefix + "'" + print "Allowed files :", options.allowed_files + + for x in args: + basename = os.path.basename(x) + dirname = os.path.dirname(x) + install(basename, dirname, options) + +if __name__ == "__main__": + main() diff --git a/bin/doinfo b/bin/doinfo new file mode 100755 index 000000000..a8d7f4d7e --- /dev/null +++ b/bin/doinfo @@ -0,0 +1,21 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/doinfo,v 1.7 2004/10/04 13:56:50 vapier Exp $ + +if [ ${#} -lt 1 ] ; then + echo "doinfo: at least one argument needed" + exit 1 +fi +if [ ! -d "${D}usr/share/info" ] ; then + install -d "${D}usr/share/info" +fi + +for x in "$@" ; do + if [ -e "${x}" ] ; then + install -m0644 "${x}" "${D}usr/share/info" + gzip -f -9 "${D}usr/share/info/${x##*/}" + else + echo "doinfo: ${x} does not exist" + fi +done diff --git a/bin/doinitd b/bin/doinitd new file mode 100755 index 000000000..d4f725ab4 --- /dev/null +++ b/bin/doinitd @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright 1999-2005 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/doinitd,v 1.2.2.1 2005/01/13 04:51:56 vapier Exp $ + +if [ ${#} -lt 1 ] ; then + echo "doinitd: at least one argument needed" + exit 1 +fi + +tmp_EXEDESTTREE="${EXEDESTTREE}" +EXEDESTTREE=/etc/init.d/ +doexe "$@" +EXEDESTTREE="${tmp_EXEDESTTREE}" +unset tmp_EXEDESTTREE diff --git a/bin/doins b/bin/doins new file mode 100755 index 000000000..551905e93 --- /dev/null +++ b/bin/doins @@ -0,0 +1,53 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/doins,v 1.7.2.2 2004/12/17 22:25:13 carpaski Exp $ + +if [ $# -lt 1 ] ; then + echo "${0}: at least one argument needed" + exit 1 +fi + +if [ "${1}" == "-r" ] ; then + DOINSRECUR=y + shift +else + DOINSRECUR=n +fi +[ -z "${INSDEPTH}" ] && declare -i INSDEPTH=0 +if [ ${INSDEPTH} -gt 30 ] ; then + echo "${0}: sanity check ... 30 directories is too much :(" + exit 1 +fi + +if [ "${INSDESTTREE%${D}*}" == "" ]; then + echo "-------------------------------------------------------" 1>&2 + echo "You should not use \${D} with helpers." 1>&2 + echo " --> ${INSDESTTREE}" 1>&2 + echo "-------------------------------------------------------" 1>&2 + #exit 1 +fi + +[ ! -d "${D}${INSDESTTREE}" ] && dodir "${INSDESTTREE}" + +for x in "$@" ; do + if [ -L "$x" ] ; then + cp "$x" "${T}" + mysrc="${T}/$(/usr/bin/basename "${x}")" + elif [ -d "$x" ] ; then + if [ "${DOINSRECUR}" == "n" ] ; then + continue + fi + + mydir="${INSDESTTREE}/$(basename "${x}")" + find "${x}" -mindepth 1 -maxdepth 1 -exec \ + env \ + INSDESTTREE="${mydir}" \ + INSDEPTH=$((INSDEPTH+1)) \ + doins -r {} \; + continue + else + mysrc="${x}" + fi + install ${INSOPTIONS} "${mysrc}" "${D}${INSDESTTREE}" +done diff --git a/bin/dojar b/bin/dojar new file mode 100755 index 000000000..77dadfee0 --- /dev/null +++ b/bin/dojar @@ -0,0 +1,54 @@ +#!/bin/sh +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dojar,v 1.8 2004/10/04 13:56:50 vapier Exp $ +# Author Karl Trygve Kalleberg + +# +# Typical usage: +# dojar foo.jar bar.jar +# - installs foo.jar and bar.jar into /usr/share/${PN}/lib, and adds them +# both to /usr/share/${PN}/classpath.env +# +# Detailed usage +# dojar +# - installs into /usr/share/${PN}/lib and adds each to +# /usr/share/${PN}/classpath.env. +# +# The classpath.env file is currently merely a convenience for the user as +# it allows him to: +# export CLASSPATH=${CLASSPATH}:`cat /usr/share/foo/classpath.env` +# +# For many packages that set FOO_HOME, placing the jar files into +# lib will allow the user to set FOO_HOME=/usr/share/foo and have the +# scripts work as expected. +# +# Possibly a jarinto will be needed in the future. +# + +if [ -z "$JARDESTTREE" ] ; then + JARDESTTREE="lib" +fi + +jarroot="${DESTTREE}/share/${PN}/" +jardest="${DESTTREE}/share/${PN}/${JARDESTTREE}/" +pf="${D}${jarroot}/package.env" + +dodir "${jardest}" + +for i in $* ; do + bn="$(basename $i)" + + if [ -f "$pf" ] ; then + oldcp=`grep "CLASSPATH=" "$pf" | sed "s/CLASSPATH=//"` + grep -v "CLASSPATH=" "$pf" > "${pf}.new" + echo "CLASSPATH=${oldcp}:${jardest}${bn}" >> "${pf}.new" + mv "${pf}.new" "$pf" + else + echo "DESCRIPTION=\"${DESCRIPTION}\"" > "$pf" + echo "CLASSPATH=${jardest}${bn}" >> "$pf" + fi + + cp "$i" "${D}${jardest}/" + chmod 0444 "${D}${jardest}/${bn}" +done diff --git a/bin/dolib b/bin/dolib new file mode 100755 index 000000000..51b2327d3 --- /dev/null +++ b/bin/dolib @@ -0,0 +1,41 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dolib,v 1.8.2.2 2005/01/12 02:07:15 carpaski Exp $ + +LIBDIR_VAR="LIBDIR_${ABI}" +if [ -n "${ABI}" -a -n "${!LIBDIR_VAR}" ]; then + CONF_LIBDIR="${!LIBDIR_VAR}" +fi +unset LIBDIR_VAR + +if [ -z "${CONF_LIBDIR}" ]; then + # we need this to default to lib so that things dont break + CONF_LIBDIR="lib" +fi +libdir="${D}${DESTTREE}/${CONF_LIBDIR}" +for X in 1 2 3; do + # The escaping is weird. It will break if you escape the last one. + libdir="${libdir//\/\///}" +done + + +if [ ${#} -lt 1 ] ; then + echo "${0}: at least one argument needed" + exit 1 +fi +if [ ! -d "${libdir}" ] ; then + install -d "${libdir}" +fi + +for x in "$@" ; do + if [ -e "${x}" ] ; then + if [ ! -L "${x}" ] ; then + install ${LIBOPTIONS} "${x}" "${libdir}" + else + ln -s "$(readlink "${x}")" "${libdir}/${x}" + fi + else + echo "${0}: ${x} does not exist" + fi +done diff --git a/bin/dolib.a b/bin/dolib.a new file mode 100755 index 000000000..f7cced1c6 --- /dev/null +++ b/bin/dolib.a @@ -0,0 +1,7 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dolib.a,v 1.8 2004/10/10 10:07:20 carpaski Exp $ + +exec env LIBOPTIONS="-m0644" \ + dolib "$@" diff --git a/bin/dolib.so b/bin/dolib.so new file mode 100755 index 000000000..aa6df7db8 --- /dev/null +++ b/bin/dolib.so @@ -0,0 +1,7 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dolib.so,v 1.12 2004/10/10 10:07:20 carpaski Exp $ + +exec env LIBOPTIONS="-m0755" \ + dolib "$@" diff --git a/bin/doman b/bin/doman new file mode 100755 index 000000000..5c23ea0d2 --- /dev/null +++ b/bin/doman @@ -0,0 +1,52 @@ +#!/bin/bash +# Copyright 1999-2005 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/doman,v 1.13.2.2 2005/07/29 05:55:34 vapier Exp $ + +if [ $# -lt 1 ] ; then + echo "$0: at least one argument needed" 1>&2 + exit 1 +fi + +BASE="/usr/share" +i18n="" + +for x in "$@" ; do + if [ "${x:0:6}" == "-i18n=" ] ; then + i18n="${x:6}/" + fi + if [ "${x}" == ".keep" ] ; then + continue + fi + + suffix=${x##*.} + + if [ "$suffix" == "gz" ] ; then + compressed="gz" + realname="${x%.*}" + suffix="${realname##*.}" + else + realname="$x" + compressed="" + 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}" + fi + + install -m0644 "${x}" "${D}${BASE}/man/${mandir}" + + if [ -z "${compressed}" ] ; then + gzip -f -9 "${D}${BASE}/man/${mandir}/${x##*/}" + fi + else + echo "doman: ${x} does not exist" 1>&2 + fi + else + echo "doman: '${x}' is probably not a man page; skipping" 1>&2 + fi +done diff --git a/bin/domo b/bin/domo new file mode 100755 index 000000000..ca3cf4b4e --- /dev/null +++ b/bin/domo @@ -0,0 +1,26 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/domo,v 1.6 2004/10/04 13:56:50 vapier Exp $ + +mynum=${#} +if [ ${mynum} -lt 1 ] ; then + echo "${0}: at least one argument needed" + exit 1 +fi +if [ ! -d "${D}${DESTTREE}/share/locale" ] ; then + install -d "${D}${DESTTREE}/share/locale/" +fi + +for x in "$@" ; do + if [ -e "${x}" ] ; then + mytiny="${x##*/}" + mydir="${D}${DESTTREE}/share/locale/${mytiny%.*}/LC_MESSAGES" + if [ ! -d "${mydir}" ] ; then + install -d "${mydir}" + fi + install -m0644 "${x}" "${mydir}/${MOPREFIX}.mo" + else + echo "${0}: ${x} does not exist" + fi +done diff --git a/bin/dopython b/bin/dopython new file mode 100755 index 000000000..a3ffab968 --- /dev/null +++ b/bin/dopython @@ -0,0 +1,23 @@ +#!/usr/bin/python +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dopython,v 1.8 2004/10/04 13:56:50 vapier Exp $ + +import sys +sys.path = ["/usr/lib/portage/pym"]+sys.path + +from sys import * +import portage +import types +mycommand=argv[1]+"(" +x=2 +while (x>> dosbin: making ${x} executable..." + if [ "$USERLAND" == "GNU" ]; then + install -m0755 -o root -g root "${x}" "${D}${DESTTREE}/sbin" || exit 4 + else + install -m0755 -o root -g wheel "${x}" "${D}${DESTTREE}/sbin" || exit 4 + fi + fi +done diff --git a/bin/dosed b/bin/dosed new file mode 100755 index 000000000..2c53b22d3 --- /dev/null +++ b/bin/dosed @@ -0,0 +1,22 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dosed,v 1.7 2004/10/04 13:56:50 vapier Exp $ + +mysed="s:${D}::g" + +for x in "$@" ; do + y="${D}${x}" + if [ -a "${y}" ] ; then + if [ -f "${y}" ] ; then + mysrc="${T}/${y##*/}" + cp "${y}" "${mysrc}" + sed -e "${mysed}" "${mysrc}" > "${y}" + else + echo "${y} is not a regular file!" + exit 1 + fi + else + mysed="${x}" + fi +done diff --git a/bin/dosym b/bin/dosym new file mode 100755 index 000000000..ca8cb713f --- /dev/null +++ b/bin/dosym @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/dosym,v 1.7 2004/10/04 13:56:50 vapier Exp $ + +if [ ${#} -ne 2 ] ; then + echo "${0}: two arguments needed" + exit 1 +fi + +target="${1}" +linkname="${2}" +ln -snf "${target}" "${D}${linkname}" diff --git a/bin/ebuild b/bin/ebuild new file mode 100755 index 000000000..2c4ed713d --- /dev/null +++ b/bin/ebuild @@ -0,0 +1,61 @@ +#!/usr/bin/python -O +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/ebuild,v 1.18.2.3 2005/05/07 04:32:59 ferringb Exp $ + +import os,sys +sys.path = ["/usr/lib/portage/pym"]+sys.path +import portage_util + +def getroot(): + try: + a=os.environ["ROOT"] + if a == '/': + return '/' + except SystemExit, e: + raise # Needed else we can't exit. + except: + return '/' + return os.path.normpath(a)+'/' + +os.environ["PORTAGE_CALLER"]="ebuild" + +if len(sys.argv)<=2: + print "expecting two arguments." + sys.exit(1) + +import getopt + +debug=0 + +opts,pargs=getopt.getopt(sys.argv[1:],'',['debug']) +for opt in opts: + if opt[0]=='--debug': + debug=1 + +if "merge" in pargs: + print "Disabling noauto in features... merge disables it. (qmerge doesn't)" + os.environ["FEATURES"] = os.environ.get("FEATURES", "") + " -noauto" + +import portage + +for x in pargs[1:]: + try: + tmpsettings = portage.config(clone=portage.settings) + + if x in ['clean','config']: + cleanup=1 + else: + cleanup=0 + a=portage.doebuild(pargs[0],x,getroot(),tmpsettings,debug=debug,cleanup=cleanup) + except KeyboardInterrupt: + print "(interrupted by user -- ctrl-C?)" + a=1 + except IOError: + a=1 + print "ebuild: this ebuild generated output during the depend phase (bad)" + if a == None: + portage_util.writemsg("Could not run the required binary?\n") + sys.exit(127) + if a: + sys.exit(a) diff --git a/bin/ebuild.sh b/bin/ebuild.sh new file mode 100755 index 000000000..3271859ea --- /dev/null +++ b/bin/ebuild.sh @@ -0,0 +1,1868 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/ebuild.sh,v 1.201.2.42 2005/08/20 17:24:30 jstubbs Exp $ + +export SANDBOX_PREDICT="${SANDBOX_PREDICT}:/proc/self/maps:/dev/console:/usr/lib/portage/pym:/dev/random" +export SANDBOX_WRITE="${SANDBOX_WRITE}:/dev/shm:${PORTAGE_TMPDIR}" +export SANDBOX_READ="${SANDBOX_READ}:/dev/shm:${PORTAGE_TMPDIR}" + +if [ ! -z "${PORTAGE_GPG_DIR}" ]; then + SANDBOX_PREDICT="${SANDBOX_PREDICT}:${PORTAGE_GPG_DIR}" +fi + +if [ "$*" != "depend" ] && [ "$*" != "clean" ] && [ "$*" != "nofetch" ]; then + if [ -f "${T}/environment" ]; then + source "${T}/environment" &>/dev/null + fi +fi + +if [ -n "$#" ]; then + ARGS="${*}" +fi + +declare -rx EBUILD_PHASE="$*" + +# Prevent aliases from causing portage to act inappropriately. +# Make sure it's before everything so we don't mess aliases that follow. +unalias -a + +# Unset some variables that break things. +unset GZIP BZIP BZIP2 CDPATH GREP_OPTIONS GREP_COLOR GLOBIGNORE + +# We need this next line for "die" and "assert". It expands +# It _must_ preceed all the calls to die and assert. +shopt -s expand_aliases +alias die='diefunc "$FUNCNAME" "$LINENO" "$?"' +alias assert='_pipestatus="${PIPESTATUS[*]}"; [[ "${_pipestatus// /}" -eq 0 ]] || diefunc "$FUNCNAME" "$LINENO" "$_pipestatus"' +alias save_IFS='[ "${IFS:-unset}" != "unset" ] && old_IFS="${IFS}"' +alias restore_IFS='if [ "${old_IFS:-unset}" != "unset" ]; then IFS="${old_IFS}"; unset old_IFS; else unset IFS; fi' + +OCC="$CC" +OCXX="$CXX" +source /etc/profile.env &>/dev/null +if [ -f "${PORTAGE_BASHRC}" ]; then + source "${PORTAGE_BASHRC}" +fi +[ ! -z "$OCC" ] && export CC="$OCC" +[ ! -z "$OCXX" ] && export CXX="$OCXX" + +export PATH="/sbin:/usr/sbin:/usr/lib/portage/bin:/bin:/usr/bin:${ROOTPATH}" +[ ! -z "$PREROOTPATH" ] && export PATH="${PREROOTPATH%%:}:$PATH" + +if [ -e /etc/init.d/functions.sh ]; then + source /etc/init.d/functions.sh &>/dev/null +elif [ -e /etc/rc.d/config/functions ]; then + source /etc/rc.d/config/functions &>/dev/null +else + #Mac OS X + source /usr/lib/portage/bin/functions.sh &>/dev/null +fi + +# the sandbox is disabled by default except when overridden in the relevant stages +export SANDBOX_ON="0" + +# sandbox support functions; defined prior to profile.bashrc srcing, since the profile might need to add a default exception (/usr/lib64/conftest fex, bug #60147) +addread() +{ + export SANDBOX_READ="$SANDBOX_READ:$1" +} + +addwrite() +{ + export SANDBOX_WRITE="$SANDBOX_WRITE:$1" +} + +adddeny() +{ + export SANDBOX_DENY="$SANDBOX_DENY:$1" +} + +addpredict() +{ + export SANDBOX_PREDICT="$SANDBOX_PREDICT:$1" +} + + +# source the existing profile.bashrc's. +save_IFS +IFS=$'\n' +for dir in ${PROFILE_PATHS}; do + # Must unset it so that it doesn't mess up assumptions in the RCs. + unset IFS + if [ -f "${dir}/profile.bashrc" ]; then + source "${dir}/profile.bashrc" + fi +done +restore_IFS + + +esyslog() { + # Custom version of esyslog() to take care of the "Red Star" bug. + # MUST follow functions.sh to override the "" parameter problem. + return 0 +} + + +use() { + if useq ${1}; then + return 0 + fi + return 1 +} + +usev() { + if useq ${1}; then + echo "${1}" + return 0 + fi + return 1 +} + +useq() { + local u="${1}" + local neg=0 + if [ "${u:0:1}" == "!" ]; then + u="${u:1}" + neg=1 + fi + local x + + # Make sure we have this USE flag in IUSE + if ! hasq "${u}" ${IUSE} ${E_IUSE} && ! hasq "${u}" ${PORTAGE_ARCHLIST} selinux; then + echo "QA Notice: USE Flag '${u}' not in IUSE for ${CATEGORY}/${PF}" >&2 + fi + + for x in ${USE}; do + if [ "${x}" == "${u}" ]; then + if [ ${neg} -eq 1 ]; then + return 1 + else + return 0 + fi + fi + done + if [ ${neg} -eq 1 ]; then + return 0 + else + return 1 + fi +} + +has() { + if hasq "$@"; then + return 0 + fi + return 1 +} + +hasv() { + if hasq "$@"; then + echo "${1}" + return 0 + fi + return 1 +} + +hasq() { + local x + + local me=$1 + shift + + # All the TTY checks really only help out depend. Which is nice. + # Logging kills all this anyway. Everything becomes a pipe. --NJ + for x in "$@"; do + if [ "${x}" == "${me}" ]; then + return 0 + fi + done + return 1 +} + +has_version() { + if [ "${EBUILD_PHASE}" == "depend" ]; then + echo -n "QA Notice: has_version() in global scope: " >&2 + if [ ${ECLASS_DEPTH} -gt 0 ]; then + echo "eclass ${ECLASS}" >&2 + else + echo "${CATEGORY}/${PF}" >&2 + fi + fi + # return shell-true/shell-false if exists. + # Takes single depend-type atoms. + if /usr/lib/portage/bin/portageq 'has_version' "${ROOT}" "$1"; then + return 0 + else + return 1 + fi +} + +portageq() { + if [ "${EBUILD_PHASE}" == "depend" ]; then + echo -n "QA Notice: portageq in global scope: " >&2 + if [ ${ECLASS_DEPTH} -gt 0 ]; then + echo "eclass ${ECLASS}" >&2 + else + echo "${CATEGORY}/${PF}" >&2 + fi + fi + /usr/lib/portage/bin/portageq "$@" +} + + +# ---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- + + +best_version() { + if [ "${EBUILD_PHASE}" == "depend" ]; then + echo -n "QA Notice: best_version() in global scope: " >&2 + if [ ${ECLASS_DEPTH} -gt 0 ]; then + echo "eclass ${ECLASS}" >&2 + else + echo "${CATEGORY}/${PF}" >&2 + fi + fi + # returns the best/most-current match. + # Takes single depend-type atoms. + /usr/lib/portage/bin/portageq 'best_version' "${ROOT}" "$1" +} + +use_with() { + if [ -z "$1" ]; then + echo "!!! use_with() called without a parameter." >&2 + echo "!!! use_with [ [value]]" >&2 + return 1 + fi + + local UW_SUFFIX="" + if [ ! -z "${3}" ]; then + UW_SUFFIX="=${3}" + fi + + local UWORD="$2" + if [ -z "${UWORD}" ]; then + UWORD="$1" + fi + + if useq $1; then + echo "--with-${UWORD}${UW_SUFFIX}" + else + echo "--without-${UWORD}" + fi + return 0 +} + +use_enable() { + if [ -z "$1" ]; then + echo "!!! use_enable() called without a parameter." >&2 + echo "!!! use_enable [ [value]]" >&2 + return 1 + fi + + local UE_SUFFIX="" + if [ ! -z "${3}" ]; then + UE_SUFFIX="=${3}" + fi + + local UWORD="$2" + if [ -z "${UWORD}" ]; then + UWORD="$1" + fi + + if useq $1; then + echo "--enable-${UWORD}${UE_SUFFIX}" + else + echo "--disable-${UWORD}" + fi + return 0 +} + +diefunc() { + local funcname="$1" lineno="$2" exitcode="$3" + shift 3 + echo >&2 + echo "!!! ERROR: $CATEGORY/$PF failed." >&2 + echo "!!! Function $funcname, Line $lineno, Exitcode $exitcode" >&2 + echo "!!! ${*:-(no error message)}" >&2 + echo "!!! If you need support, post the topmost build error, NOT this status message." >&2 + echo >&2 + exit 1 +} + +#if no perms are specified, dirs/files will have decent defaults +#(not secretive, but not stupid) +umask 022 +export DESTTREE=/usr +export INSDESTTREE="" +export EXEDESTTREE="" +export DOCDESTTREE="" +export INSOPTIONS="-m0644" +export EXEOPTIONS="-m0755" +export LIBOPTIONS="-m0644" +export DIROPTIONS="-m0755" +export MOPREFIX=${PN} + +check_KV() +{ + if [ -z "${KV}" ]; then + eerror "" + eerror "Could not determine your kernel version." + eerror "Make sure that you have /usr/src/linux symlink." + eerror "And that said kernel has been configured." + eerror "You can also simply run the following command" + eerror "in the kernel referenced by /usr/src/linux:" + eerror " make include/linux/version.h" + eerror "" + die + fi +} + +# adds ".keep" files so that dirs aren't auto-cleaned +keepdir() +{ + dodir "$@" + local x + if [ "$1" == "-R" ] || [ "$1" == "-r" ]; then + shift + find "$@" -type d -printf "${D}/%p/.keep\n" | tr "\n" "\0" | $XARGS -0 -n100 touch || die "Failed to recursive create .keep files" + else + for x in "$@"; do + touch "${D}/${x}/.keep" || die "Failed to create .keep in ${D}/${x}" + done + fi +} + +strip_duplicate_slashes () { + if [ -n "${1}" ]; then + local removed="${1/\/\///}" + [ "${removed}" != "${removed/\/\///}" ] && removed=$(strip_duplicate_slashes "${removed}") + echo ${removed} + fi +} + +econf() { + local LOCAL_EXTRA_ECONF="${EXTRA_ECONF}" + + if [ -z "${ECONF_SOURCE}" ]; then + ECONF_SOURCE="." + fi + if [ -x "${ECONF_SOURCE}/configure" ]; then + if [ -e /usr/share/gnuconfig/ ]; then + local x + for x in $(find "${WORKDIR}" -type f '(' -name config.guess -o -name config.sub ')') ; do + echo " * econf: updating ${x/${WORKDIR}\/} with /usr/share/gnuconfig/${x##*/}" + cp -f /usr/share/gnuconfig/${x##*/} ${x} + done + fi + + if [ ! -z "${CBUILD}" ]; then + LOCAL_EXTRA_ECONF="--build=${CBUILD} ${LOCAL_EXTRA_ECONF}" + fi + + if [ ! -z "${CTARGET}" ]; then + LOCAL_EXTRA_ECONF="--target=${CTARGET} ${LOCAL_EXTRA_ECONF}" + fi + + # if the profile defines a location to install libs to aside from default, pass it on. + # if the ebuild passes in --libdir, they're responsible for the conf_libdir fun. + LIBDIR_VAR="LIBDIR_${ABI}" + if [ -n "${ABI}" -a -n "${!LIBDIR_VAR}" ]; then + CONF_LIBDIR="${!LIBDIR_VAR}" + fi + unset LIBDIR_VAR + if [ -n "${CONF_LIBDIR}" ] && [ "${*/--libdir}" == "$*" ]; then + if [ "${*/--exec-prefix}" != "$*" ]; then + local args="$(echo $*)" + local -a pref=($(echo ${args/*--exec-prefix[= ]})) + CONF_PREFIX=${pref} + [ "${CONF_PREFIX:0:1}" != "/" ] && CONF_PREFIX="/${CONF_PREFIX}" + elif [ "${*/--prefix}" != "$*" ]; then + local args="$(echo $*)" + local -a pref=($(echo ${args/*--prefix[= ]})) + CONF_PREFIX=${pref} + [ "${CONF_PREFIX:0:1}" != "/" ] && CONF_PREFIX="/${CONF_PREFIX}" + else + CONF_PREFIX="/usr" + fi + export CONF_PREFIX + [ "${CONF_LIBDIR:0:1}" != "/" ] && CONF_LIBDIR="/${CONF_LIBDIR}" + + CONF_LIBDIR_RESULT="${CONF_PREFIX}${CONF_LIBDIR}" + for X in 1 2 3; do + # The escaping is weird. It will break if you escape the last one. + CONF_LIBDIR_RESULT="${CONF_LIBDIR_RESULT//\/\///}" + done + + LOCAL_EXTRA_ECONF="--libdir=${CONF_LIBDIR_RESULT} ${LOCAL_EXTRA_ECONF}" + fi + + echo "${ECONF_SOURCE}/configure" \ + --prefix=/usr \ + --host=${CHOST} \ + --mandir=/usr/share/man \ + --infodir=/usr/share/info \ + --datadir=/usr/share \ + --sysconfdir=/etc \ + --localstatedir=/var/lib \ + "$@" \ + ${LOCAL_EXTRA_ECONF} + + if ! "${ECONF_SOURCE}/configure" \ + --prefix=/usr \ + --host=${CHOST} \ + --mandir=/usr/share/man \ + --infodir=/usr/share/info \ + --datadir=/usr/share \ + --sysconfdir=/etc \ + --localstatedir=/var/lib \ + "$@" \ + ${LOCAL_EXTRA_ECONF}; then + + if [ -s config.log ]; then + echo + echo "!!! Please attach the config.log to your bug report:" + echo "!!! ${PWD}/config.log" + fi + die "econf failed" + fi + else + die "no configure script found" + fi +} + +einstall() { + # CONF_PREFIX is only set if they didn't pass in libdir above. + LIBDIR_VAR="LIBDIR_${ABI}" + if [ -n "${ABI}" -a -n "${!LIBDIR_VAR}" ]; then + CONF_LIBDIR="${!LIBDIR_VAR}" + fi + unset LIBDIR_VAR + if [ -n "${CONF_LIBDIR}" ] && [ "${CONF_PREFIX:-unset}" != "unset" ]; then + EI_DESTLIBDIR="${D}/${CONF_PREFIX}/${CONF_LIBDIR}" + EI_DESTLIBDIR="$(strip_duplicate_slashes ${EI_DESTLIBDIR})" + EXTRA_EINSTALL="libdir=${EI_DESTLIBDIR} ${EXTRA_EINSTALL}" + unset EI_DESTLIBDIR + fi + + if [ -f ./[mM]akefile -o -f ./GNUmakefile ] ; then + if [ ! -z "${PORTAGE_DEBUG}" ]; then + make -n prefix=${D}/usr \ + datadir=${D}/usr/share \ + infodir=${D}/usr/share/info \ + localstatedir=${D}/var/lib \ + mandir=${D}/usr/share/man \ + sysconfdir=${D}/etc \ + ${EXTRA_EINSTALL} \ + "$@" install + fi + make prefix=${D}/usr \ + datadir=${D}/usr/share \ + infodir=${D}/usr/share/info \ + localstatedir=${D}/var/lib \ + mandir=${D}/usr/share/man \ + sysconfdir=${D}/etc \ + ${EXTRA_EINSTALL} \ + "$@" install || die "einstall failed" + else + die "no Makefile found" + fi +} + +pkg_setup() +{ + return +} + +pkg_nofetch() +{ + [ -z "${SRC_URI}" ] && return + + echo "!!! The following are listed in SRC_URI for ${PN}:" + for MYFILE in `echo ${SRC_URI}`; do + echo "!!! $MYFILE" + done +} + +src_unpack() { + if [ "${A}" != "" ]; then + unpack ${A} + fi +} + +src_compile() { + if [ -x ./configure ]; then + econf + fi + if [ -f Makefile ] || [ -f GNUmakefile ] || [ -f makefile ]; then + emake || die "emake failed" + fi +} + +src_test() +{ + addpredict / + if make check -n &> /dev/null; then + echo ">>> Test phase [check]: ${CATEGORY}/${PF}" + if ! make check; then + hasq test $FEATURES && die "Make check failed. See above for details." + hasq test $FEATURES || eerror "Make check failed. See above for details." + fi + elif make test -n &> /dev/null; then + echo ">>> Test phase [test]: ${CATEGORY}/${PF}" + if ! make test; then + hasq test $FEATURES && die "Make test failed. See above for details." + hasq test $FEATURES || eerror "Make test failed. See above for details." + fi + else + echo ">>> Test phase [none]: ${CATEGORY}/${PF}" + fi + SANDBOX_PREDICT="${SANDBOX_PREDICT%:/}" +} + +src_install() +{ + return +} + +pkg_preinst() +{ + return +} + +pkg_postinst() +{ + return +} + +pkg_prerm() +{ + return +} + +pkg_postrm() +{ + return +} + +pkg_config() +{ + eerror "This ebuild does not have a config function." +} + +# Used to generate the /lib/cpp and /usr/bin/cc wrappers +gen_wrapper() { + cat > $1 << END +#!/bin/sh + +$2 "\$@" +END + + chmod 0755 $1 +} + +dyn_setup() +{ + pkg_setup +} + +dyn_unpack() { + trap "abort_unpack" SIGINT SIGQUIT + local newstuff="no" + if [ -e "${WORKDIR}" ]; then + local x + local checkme + for x in ${AA}; do + echo ">>> Checking ${x}'s mtime..." + if [ "${DISTDIR}/${x}" -nt "${WORKDIR}" ]; then + echo ">>> ${x} has been updated; recreating WORKDIR..." + newstuff="yes" + rm -rf "${WORKDIR}" + break + fi + done + if [ "${EBUILD}" -nt "${WORKDIR}" ]; then + echo ">>> ${EBUILD} has been updated; recreating WORKDIR..." + newstuff="yes" + rm -rf "${WORKDIR}" + elif [ ! -f "${BUILDDIR}/.unpacked" ]; then + echo ">>> Not marked as unpacked; recreating WORKDIR..." + newstuff="yes" + rm -rf "${WORKDIR}" + fi + fi + if [ -e "${WORKDIR}" ]; then + if [ "$newstuff" == "no" ]; then + echo ">>> WORKDIR is up-to-date, keeping..." + return 0 + fi + fi + + install -m0700 -d "${WORKDIR}" || die "Failed to create dir '${WORKDIR}'" + [ -d "$WORKDIR" ] && cd "${WORKDIR}" + echo ">>> Unpacking source..." + src_unpack + touch "${BUILDDIR}/.unpacked" || die "IO Failure -- Failed 'touch .unpacked' in BUILDIR" + echo ">>> Source unpacked." + cd "$BUILDDIR" + trap SIGINT SIGQUIT +} + +dyn_clean() { + if [ "$USERLAND" == "BSD" ] && type -p chflags &>/dev/null; then + chflags -R noschg,nouchg,nosappnd,nouappnd,nosunlnk,nouunlnk \ + "${BUILDDIR}" + fi + + if [ "$USERLAND" == "Darwin" ] && type -p chflags &>/dev/null; then + chflags -R noschg,nouchg,nosappnd,nouappnd "${BUILDDIR}" + fi + + rm -rf "${BUILDDIR}/image" + + if ! hasq keeptemp $FEATURES; then + rm -rf "${T}" + else + mv "${T}/environment" "${T}/environment.keeptemp" + fi + + if ! hasq keepwork $FEATURES; then + rm -rf "${BUILDDIR}/.unpacked" + rm -rf "${BUILDDIR}/.compiled" + rm -rf "${BUILDDIR}/.tested" + rm -rf "${BUILDDIR}/.installed" + rm -rf "${BUILDDIR}/.packaged" + rm -rf "${BUILDDIR}/build-info" + rm -rf "${WORKDIR}" + fi + + if [ -f "${BUILDDIR}/.unpacked" ]; then + find "${BUILDDIR}" -type d ! -regex "^${WORKDIR}" | sort -r | tr "\n" "\0" | $XARGS -0 rmdir &>/dev/null + fi + + if [ -z "$(find "${BUILDDIR}" -mindepth 1 -maxdepth 1)" ]; then + rmdir "${BUILDDIR}" + fi + true +} + +into() { + if [ $1 == "/" ]; then + export DESTTREE="" + else + export DESTTREE=$1 + if [ ! -d "${D}${DESTTREE}" ]; then + install -d "${D}${DESTTREE}" + fi + fi +} + +insinto() { + if [ "$1" == "/" ]; then + export INSDESTTREE="" + else + export INSDESTTREE=$1 + if [ ! -d "${D}${INSDESTTREE}" ]; then + install -d "${D}${INSDESTTREE}" + fi + fi +} + +exeinto() { + if [ "$1" == "/" ]; then + export EXEDESTTREE="" + else + export EXEDESTTREE="$1" + if [ ! -d "${D}${EXEDESTTREE}" ]; then + install -d "${D}${EXEDESTTREE}" + fi + fi +} + +docinto() { + if [ "$1" == "/" ]; then + export DOCDESTTREE="" + else + export DOCDESTTREE="$1" + if [ ! -d "${D}usr/share/doc/${PF}/${DOCDESTTREE}" ]; then + install -d "${D}usr/share/doc/${PF}/${DOCDESTTREE}" + fi + fi +} + +insopts() { + INSOPTIONS="" + for x in $*; do + #if we have a debug build, let's not strip anything + if hasq nostrip $FEATURES $RESTRICT && [ "$x" == "-s" ]; then + continue + else + INSOPTIONS="$INSOPTIONS $x" + fi + done + export INSOPTIONS +} + +diropts() { + DIROPTIONS="" + for x in $*; do + DIROPTIONS="${DIROPTIONS} $x" + done + export DIROPTIONS +} + +exeopts() { + EXEOPTIONS="" + for x in $*; do + #if we have a debug build, let's not strip anything + if hasq nostrip $FEATURES $RESTRICT && [ "$x" == "-s" ]; then + continue + else + EXEOPTIONS="$EXEOPTIONS $x" + fi + done + export EXEOPTIONS +} + +libopts() { + LIBOPTIONS="" + for x in $*; do + #if we have a debug build, let's not strip anything + if hasq nostrip $FEATURES $RESTRICT && [ "$x" == "-s" ]; then + continue + else + LIBOPTIONS="$LIBOPTIONS $x" + fi + done + export LIBOPTIONS +} + +abort_handler() { + local msg + if [ "$2" != "fail" ]; then + msg="${EBUILD}: ${1} aborted; exiting." + else + msg="${EBUILD}: ${1} failed; exiting." + fi + echo + echo "$msg" + echo + eval ${3} + #unset signal handler + trap SIGINT SIGQUIT +} + +abort_compile() { + abort_handler "src_compile" $1 + rm -f "${BUILDDIR}/.compiled" + exit 1 +} + +abort_unpack() { + abort_handler "src_unpack" $1 + rm -f "${BUILDDIR}/.unpacked" + rm -rf "${BUILDDIR}/work" + exit 1 +} + +abort_package() { + abort_handler "dyn_package" $1 + rm -f "${BUILDDIR}/.packaged" + rm -f "${PKGDIR}"/All/${PF}.t* + exit 1 +} + +abort_test() { + abort_handler "dyn_test" $1 + rm -f "${BUILDDIR}/.tested" + exit 1 +} + +abort_install() { + abort_handler "src_install" $1 + rm -rf "${BUILDDIR}/image" + exit 1 +} + +dyn_compile() { + trap "abort_compile" SIGINT SIGQUIT + [ "${CFLAGS-unset}" != "unset" ] && export CFLAGS + [ "${CXXFLAGS-unset}" != "unset" ] && export CXXFLAGS + [ "${LIBCFLAGS-unset}" != "unset" ] && export LIBCFLAGS + [ "${LIBCXXFLAGS-unset}" != "unset" ] && export LIBCXXFLAGS + [ "${LDFLAGS-unset}" != "unset" ] && export LDFLAGS + [ "${ASFLAGS-unset}" != "unset" ] && export ASFLAGS + + [ "${CCACHE_DIR-unset}" != "unset" ] && export CCACHE_DIR + [ "${CCACHE_SIZE-unset}" != "unset" ] && export CCACHE_SIZE + + [ "${DISTCC_DIR-unset}" == "unset" ] && export DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc" + [ ! -z "${DISTCC_DIR}" ] && addwrite "${DISTCC_DIR}" + + if hasq noauto $FEATURES &>/dev/null && [ ! -f ${BUILDDIR}/.unpacked ]; then + echo + echo "!!! We apparently haven't unpacked... This is probably not what you" + echo "!!! want to be doing... You are using FEATURES=noauto so I'll assume" + echo "!!! that you know what you are doing... You have 5 seconds to abort..." + echo + + echo -ne "\a"; sleep 0.25 &>/dev/null; echo -ne "\a"; sleep 0.25 &>/dev/null + echo -ne "\a"; sleep 0.25 &>/dev/null; echo -ne "\a"; sleep 0.25 &>/dev/null + echo -ne "\a"; sleep 0.25 &>/dev/null; echo -ne "\a"; sleep 0.25 &>/dev/null + echo -ne "\a"; sleep 0.25 &>/dev/null; echo -ne "\a"; sleep 0.25 &>/dev/null + + echo -ne "\a"; sleep 0,25 &>/dev/null; echo -ne "\a"; sleep 0,25 &>/dev/null + echo -ne "\a"; sleep 0,25 &>/dev/null; echo -ne "\a"; sleep 0,25 &>/dev/null + echo -ne "\a"; sleep 0,25 &>/dev/null; echo -ne "\a"; sleep 0,25 &>/dev/null + echo -ne "\a"; sleep 0,25 &>/dev/null; echo -ne "\a"; sleep 0,25 &>/dev/null + sleep 3 + fi + + cd "${BUILDDIR}" + if [ ! -e "build-info" ]; then + mkdir build-info + fi + cp "${EBUILD}" "build-info/${PF}.ebuild" + + if [ ${BUILDDIR}/.compiled -nt "${WORKDIR}" ]; then + echo ">>> It appears that ${PN} is already compiled; skipping." + echo ">>> (clean to force compilation)" + trap SIGINT SIGQUIT + return + fi + if [ -d "${S}" ]; then + cd "${S}" + fi + #our custom version of libtool uses $S and $D to fix + #invalid paths in .la files + export S D + #some packages use an alternative to $S to build in, cause + #our libtool to create problematic .la files + export PWORKDIR="$WORKDIR" + src_compile + #|| abort_compile "fail" + cd "${BUILDDIR}" + touch .compiled + cd build-info + + echo "$ASFLAGS" > ASFLAGS + echo "$CATEGORY" > CATEGORY + echo "$CBUILD" > CBUILD + echo "$CC" > CC + echo "$CDEPEND" > CDEPEND + echo "$CFLAGS" > CFLAGS + echo "$CHOST" > CHOST + echo "$CTARGET" > CTARGET + echo "$CXX" > CXX + echo "$CXXFLAGS" > CXXFLAGS + echo "$DEPEND" > DEPEND + echo "$EXTRA_ECONF" > EXTRA_ECONF + echo "$EXTRA_EINSTALL" > EXTRA_EINSTALL + echo "$EXTRA_EMAKE" > EXTRA_MAKE + echo "$FEATURES" > FEATURES + echo "$INHERITED" > INHERITED + echo "$IUSE" > IUSE + echo "$PKGUSE" > PKGUSE + echo "$LDFLAGS" > LDFLAGS + echo "$LIBCFLAGS" > LIBCFLAGS + echo "$LIBCXXFLAGS" > LIBCXXFLAGS + echo "$LICENSE" > LICENSE + echo "$PDEPEND" > PDEPEND + echo "$PF" > PF + echo "$PROVIDE" > PROVIDE + echo "$RDEPEND" > RDEPEND + echo "$RESTRICT" > RESTRICT + echo "$SLOT" > SLOT + echo "$USE" > USE + + set > environment + export -p | sed 's:declare -rx:declare -x:' >> environment + bzip2 -9 environment + + cp "${EBUILD}" "${PF}.ebuild" + if hasq nostrip $FEATURES $RESTRICT; then + touch DEBUGBUILD + fi + trap SIGINT SIGQUIT +} + +dyn_package() { + trap "abort_package" SIGINT SIGQUIT + cd "${BUILDDIR}/image" + tar cpvf - ./ | bzip2 -f > ../bin.tar.bz2 || die "Failed to create tarball" + cd .. + xpak build-info inf.xpak + tbz2tool join bin.tar.bz2 inf.xpak "${PF}.tbz2" + mv "${PF}.tbz2" "${PKGDIR}/All" || die "Failed to move tbz2 to ${PKGDIR}/All" + rm -f inf.xpak bin.tar.bz2 + if [ ! -d "${PKGDIR}/${CATEGORY}" ]; then + install -d "${PKGDIR}/${CATEGORY}" + fi + ln -sf "../All/${PF}.tbz2" "${PKGDIR}/${CATEGORY}/${PF}.tbz2" || die "Failed to create symlink in ${PKGDIR}/${CATEGORY}" + echo ">>> Done." + cd "${BUILDDIR}" + touch .packaged || die "Failed to 'touch .packaged' in ${BUILDDIR}" + trap SIGINT SIGQUIT +} + + +dyn_test() { + if [ ${BUILDDIR}/.tested -nt "${WORKDIR}" ]; then + echo ">>> It appears that ${PN} has already been tested; skipping." + return + fi + trap "abort_test" SIGINT SIGQUIT + if [ -d "${S}" ]; then + cd "${S}" + fi + if hasq maketest $RESTRICT || hasq test $RESTRICT; then + ewarn "Skipping make test/check due to ebuild restriction." + echo ">>> Test phase [explicitly disabled]: ${CATEGORY}/${PF}" + elif ! hasq test $FEATURES; then + echo ">>> Test phase [not enabled]: ${CATEGORY}/${PF}" + else + echo ">>> Test phase [enabled]: ${CATEGORY}/${PF}" + src_test + fi + + cd "${BUILDDIR}" + touch .tested || die "Failed to 'touch .tested' in ${BUILDDIR}" + trap SIGINT SIGQUIT +} + + + +dyn_install() { + trap "abort_install" SIGINT SIGQUIT + rm -rf "${BUILDDIR}/image" + mkdir "${BUILDDIR}/image" + if [ -d "${S}" ]; then + cd "${S}" + fi + echo + echo ">>> Install ${PF} into ${D} category ${CATEGORY}" + #our custom version of libtool uses $S and $D to fix + #invalid paths in .la files + export S D + #some packages uses an alternative to $S to build in, cause + #our libtool to create problematic .la files + export PWORKDIR="$WORKDIR" + src_install + #|| abort_install "fail" + prepall + cd "${D}" + + declare -i UNSAFE=0 + for i in $(find "${D}/" -type f -perm -2002); do + ((UNSAFE++)) + echo "UNSAFE SetGID: $i" + done + for i in $(find "${D}/" -type f -perm -4002); do + ((UNSAFE++)) + echo "UNSAFE SetUID: $i" + done + + if type -p scanelf > /dev/null ; then + # Make sure we disallow insecure RUNPATH/RPATH's + # Don't want paths that point to the tree where the package was built + # (older, broken libtools would do this). Also check for null paths + # because the loader will search $PWD when it finds null paths. + f=$(scanelf -qyRF '%r %p' "${D}" | grep -E "(${BUILDDIR}|: |::|^ )") + if [[ -n ${f} ]] ; then + echo -ne '\a\n' + echo "QA Notice: the following files contain insecure RUNPATH's" + echo " Please file a bug about this at http://bugs.gentoo.org/" + echo " For more information on this issue, kindly review:" + echo " http://bugs.gentoo.org/81745" + echo "${f}" + echo -ne '\a\n' + die "Insecure binaries detected" + fi + + # Check for setid binaries but are not built with BIND_NOW + f=$(scanelf -qyRF '%b %p' "${D}") + if [[ -n ${f} ]] ; then + echo -ne '\a\n' + echo "QA Notice: the following files are setXid, dyn linked, and using lazy bindings" + echo " This combination is generally discouraged. Try re-emerging the package:" + echo " LDFLAGS='-Wl,-z,now' emerge ${PN}" + echo "${f}" + echo -ne '\a\n' + [[ ${FEATURES/stricter} != "${FEATURES}" ]] \ + && die "Aborting due to lazy bindings" + sleep 1 + fi + + # TEXTREL's are baaaaaaaad + f=$(scanelf -qyRF '%t %p' "${D}") + if [[ -n ${f} ]] ; then + echo -ne '\a\n' + echo "QA Notice: the following files contain runtime text relocations" + echo " Text relocations require a lot of extra work to be preformed by the" + echo " dynamic linker which will cause serious performance impact on IA-32" + echo " and might not function properly on other architectures hppa for example." + echo " If you are a programmer please take a closer look at this package and" + echo " consider writing a patch which addresses this problem." + echo "${f}" + echo -ne '\a\n' + [[ ${FEATURES/stricter} != "${FEATURES}" ]] \ + && die "Aborting due to textrels" + sleep 1 + fi + + # Check for files with executable stacks + f=$(scanelf -qyRF '%e %p' "${D}") + if [[ -n ${f} ]] ; then + echo -ne '\a\n' + echo "QA Notice: the following files contain executable stacks" + echo " Files with executable stacks will not work properly (or at all!)" + echo " on some architectures/operating systems. A bug should be filed" + echo " at http://bugs.gentoo.org/ to make sure the file is fixed." + echo "${f}" + echo -ne '\a\n' + [[ ${FEATURES/stricter} != "${FEATURES}" ]] \ + && die "Aborting due to +x stack" + sleep 1 + fi + + # Save NEEDED information + scanelf -qyRF '%p %n' "${D}" | sed -e 's:^:/:' > "${BUILDDIR}"/build-info/NEEDED + fi + + if [[ ${UNSAFE} > 0 ]] ; then + die "There are ${UNSAFE} unsafe files. Portage will not install them." + fi + + # dumps perms to stdout. if error, no perms dumped. + function stat_perms() { + local f + # only define do_stat if it hasn't been already + if ! type -p do_stat &> /dev/null; then + if ! type -p stat &>/dev/null; then + do_stat() { + # Generic version -- Octal result + python -c "import os,stat; print '%o' % os.stat('$1')[stat.ST_MODE]" + } + else + if [ "${USERLAND}" == "BSD" ] || [ "${USERLAND}" == "Darwin" ]; then + do_stat() { + # BSD version -- Octal result + $(type -p stat) -f '%p' "$1" + } + else + do_stat() { + # Linux version -- Hex result converted to Octal + f=$($(type -p stat) -c '%f' "$1") || return $? + printf '%o' "0x$f" + } + fi + fi + fi + + f=$(do_stat "$@") || return + f="${f:2:4}" + echo $f + } + + local file s + local count=0 + find "${D}/" -user portage | while read file; do + count=$(( $count + 1 )) + [[ ! -L "${file}" ]] && s=$(stat_perms "$file") + if [ -z "${s}" ]; then + ewarn "failed stat_perm'ing $file. User intervention during install isn't wise..." + continue + fi + chown root "$file" + [[ ! -L "${file}" ]] && chmod "$s" "$file" + done + if (( $count > 0 )); then + ewarn "$count files were installed with user portage!" + fi + + count=0 + find "${D}/" -group portage | while read file; do + count=$(( $count + 1 )) + [[ ! -L "${file}" ]] && s=$(stat_perms "$file") + if [ -z "${s}" ]; then + echo "failed stat_perm'ing '$file' . User intervention during install isn't wise..." + continue + fi + chgrp 0 "${file}" + [[ ! -L "${file}" ]] && chmod "$s" "$file" + done + if (( $count > 0 )); then + ewarn "$count files were installed with group portage!" + fi + + unset -f stat_perms + + # Portage regenerates this on the installed system. + if [ -f "${D}/usr/share/info/dir.gz" ]; then + rm -f "${D}/usr/share/info/dir.gz" + fi + + if hasq multilib-strict ${FEATURES} && [ -x /usr/bin/file -a -x /usr/bin/find -a \ + -n "${MULTILIB_STRICT_DIRS}" -a -n "${MULTILIB_STRICT_DENY}" ]; then + MULTILIB_STRICT_EXEMPT=${MULTILIB_STRICT_EXEMPT:-"(perl5|gcc|gcc-lib)"} + for dir in ${MULTILIB_STRICT_DIRS}; do + [ -d "${D}/${dir}" ] || continue + for file in $(find ${D}/${dir} -type f | egrep -v "^${D}/${dir}/${MULTILIB_STRICT_EXEMPT}"); do + file ${file} | egrep -q "${MULTILIB_STRICT_DENY}" && die "File ${file} matches a file type that is not allowed in ${dir}" + done + done + fi + + touch "${BUILDDIR}/.installed" + echo ">>> Completed installing ${PF} into ${D}" + echo + cd ${BUILDDIR} + trap SIGINT SIGQUIT +} + +dyn_preinst() { + # set IMAGE depending if this is a binary or compile merge + [ "${EMERGE_FROM}" == "binary" ] && IMAGE=${PKG_TMPDIR}/${PF}/bin \ + || IMAGE=${D} + + pkg_preinst + + # hopefully this will someday allow us to get rid of the no* feature flags + # we don't want globbing for initial expansion, but afterwards, we do + local shopts=$- + set -o noglob + for no_inst in ${INSTALL_MASK}; do + set +o noglob + einfo "Removing ${no_inst}" + # normal stuff + rm -Rf ${IMAGE}/${no_inst} >&/dev/null + + # we also need to handle globs (*.a, *.h, etc) + find "${IMAGE}" -name ${no_inst} -exec rm -fR {} \; >&/dev/null + done + # set everything back the way we found it + set +o noglob + set -${shopts} + + # remove man pages + if hasq noman $FEATURES; then + rm -fR "${IMAGE}/usr/share/man" + fi + + # remove info pages + if hasq noinfo $FEATURES; then + rm -fR "${IMAGE}/usr/share/info" + fi + + # remove docs + if hasq nodoc $FEATURES; then + rm -fR "${IMAGE}/usr/share/doc" + fi + + # remove share dir if unnessesary + if hasq nodoc $FEATURES -o hasq noman $FEATURES -o hasq noinfo $FEATURES; then + rmdir "${IMAGE}/usr/share" &> /dev/null + fi + + # Smart FileSystem Permissions + if hasq sfperms $FEATURES; then + for i in $(find ${IMAGE}/ -type f -perm -4000); do + ebegin ">>> SetUID: [chmod go-r] $i " + chmod go-r "$i" + eend $? + done + for i in $(find ${IMAGE}/ -type f -perm -2000); do + ebegin ">>> SetGID: [chmod o-r] $i " + chmod o-r "$i" + eend $? + done + fi + + # total suid control. + if hasq suidctl $FEATURES > /dev/null ; then + sfconf=/etc/portage/suidctl.conf + echo ">>> Preforming suid scan in ${IMAGE}" + for i in $(find ${IMAGE}/ -type f \( -perm -4000 -o -perm -2000 \) ); do + if [ -s "${sfconf}" ]; then + suid="`grep ^${i/${IMAGE}/}$ ${sfconf}`" + if [ "${suid}" = "${i/${IMAGE}/}" ]; then + echo "- ${i/${IMAGE}/} is an approved suid file" + else + echo ">>> Removing sbit on non registered ${i/${IMAGE}/}" + for x in 5 4 3 2 1 0; do echo -ne "\a"; sleep 0.25 ; done + echo -ne "\a" + chmod ugo-s "${i}" + grep ^#${i/${IMAGE}/}$ ${sfconf} > /dev/null || { + # sandbox prevents us from writing directly + # to files outside of the sandbox, but this + # can easly be bypassed using the addwrite() function + addwrite "${sfconf}" + echo ">>> Appending commented out entry to ${sfconf} for ${PF}" + ls_ret=`ls -ldh "${i}"` + echo "## ${ls_ret%${IMAGE}*}${ls_ret#*${IMAGE}}" >> ${sfconf} + echo "#${i/${IMAGE}/}" >> ${sfconf} + # no delwrite() eh? + # delwrite ${sconf} + } + fi + else + echo "suidctl feature set but you are lacking a ${sfconf}" + fi + done + fi + + # SELinux file labeling (needs to always be last in dyn_preinst) + if useq selinux; then + # only attempt to label if setfiles is executable + # and 'context' is available on selinuxfs. + if [ -f /selinux/context -a -x /usr/sbin/setfiles ]; then + echo ">>> Setting SELinux security labels" + if [ -f ${POLICYDIR}/file_contexts/file_contexts ]; then + cp -f "${POLICYDIR}/file_contexts/file_contexts" "${T}" + else + make -C "${POLICYDIR}" FC=${T}/file_contexts "${T}/file_contexts" + fi + + addwrite /selinux/context + /usr/sbin/setfiles -r "${IMAGE}" "${T}/file_contexts" "${IMAGE}" \ + || die "Failed to set SELinux security labels." + else + # nonfatal, since merging can happen outside a SE kernel + # like during a recovery situation + echo "!!! Unable to set SELinux security labels" + fi + fi + trap SIGINT SIGQUIT +} + +dyn_spec() { + tar czf "/usr/src/redhat/SOURCES/${PF}.tar.gz" "${O}/${PF}.ebuild" "${O}/files" || die "Failed to create base rpm tarball." + + cat <<__END1__ > ${PF}.spec +Summary: ${DESCRIPTION} +Name: ${PN} +Version: ${PV} +Release: ${PR} +Copyright: GPL +Group: portage/${CATEGORY} +Source: ${PF}.tar.gz +Buildroot: ${D} +%description +${DESCRIPTION} + +${HOMEPAGE} + +%prep +%setup -c + +%build + +%install + +%clean + +%files +/ +__END1__ + +} + +dyn_rpm() { + dyn_spec + rpmbuild -bb "${PF}.spec" || die "Failed to integrate rpm spec file" + install -D "/usr/src/redhat/RPMS/i386/${PN}-${PV}-${PR}.i386.rpm" "${RPMDIR}/${CATEGORY}/${PN}-${PV}-${PR}.rpm" || die "Failed to move rpm" +} + +dyn_help() { + echo + echo "Portage" + echo "Copyright 1999-2004 Gentoo Foundation" + echo + echo "How to use the ebuild command:" + echo + echo "The first argument to ebuild should be an existing .ebuild file." + echo + echo "One or more of the following options can then be specified. If more" + echo "than one option is specified, each will be executed in order." + echo + echo " help : show this help screen" + echo " setup : execute package specific setup actions" + echo " fetch : download source archive(s) and patches" + echo " digest : creates a digest and a manifest file for the package" + echo " manifest : creates a manifest file for the package" + echo " unpack : unpack/patch sources (auto-fetch if needed)" + echo " compile : compile sources (auto-fetch/unpack if needed)" + echo " test : test package (auto-fetch/unpack/compile if needed)" + echo " preinst : execute pre-install instructions" + echo " postinst : execute post-install instructions" + echo " install : installs the package to the temporary install directory" + echo " qmerge : merge image into live filesystem, recording files in db" + echo " merge : does fetch, unpack, compile, install and qmerge" + echo " prerm : execute pre-removal instructions" + echo " postrm : execute post-removal instructions" + echo " unmerge : remove package from live filesystem" + echo " config : execute package specific configuration actions" + echo " package : create tarball package in ${PKGDIR}/All" + echo " rpm : builds a RedHat RPM package" + echo " clean : clean up all source and temporary files" + echo + echo "The following settings will be used for the ebuild process:" + echo + echo " package : ${PF}" + echo " slot : ${SLOT}" + echo " category : ${CATEGORY}" + echo " description : ${DESCRIPTION}" + echo " system : ${CHOST}" + echo " c flags : ${CFLAGS}" + echo " c++ flags : ${CXXFLAGS}" + echo " make flags : ${MAKEOPTS}" + echo -n " build mode : " + if hasq nostrip $FEATURES $RESTRICT; then + echo "debug (large)" + else + echo "production (stripped)" + fi + echo " merge to : ${ROOT}" + echo + if [ -n "$USE" ]; then + echo "Additionally, support for the following optional features will be enabled:" + echo + echo " ${USE}" + fi + echo +} + +# debug-print() gets called from many places with verbose status information useful +# for tracking down problems. The output is in $T/eclass-debug.log. +# You can set ECLASS_DEBUG_OUTPUT to redirect the output somewhere else as well. +# The special "on" setting echoes the information, mixing it with the rest of the +# emerge output. +# You can override the setting by exporting a new one from the console, or you can +# set a new default in make.*. Here the default is "" or unset. + +# in the future might use e* from /etc/init.d/functions.sh if i feel like it +debug-print() { + # if $T isn't defined, we're in dep calculation mode and + # shouldn't do anything + [ -z "$T" ] && return 0 + + while [ "$1" ]; do + + # extra user-configurable targets + if [ "$ECLASS_DEBUG_OUTPUT" == "on" ]; then + echo "debug: $1" + elif [ -n "$ECLASS_DEBUG_OUTPUT" ]; then + echo "debug: $1" >> $ECLASS_DEBUG_OUTPUT + fi + + # default target + echo "$1" >> "${T}/eclass-debug.log" + # let the portage user own/write to this file + chmod g+w "${T}/eclass-debug.log" &>/dev/null + + shift + done +} + +# The following 2 functions are debug-print() wrappers + +debug-print-function() { + str="$1: entering function" + shift + debug-print "$str, parameters: $*" +} + +debug-print-section() { + debug-print "now in section $*" +} + +# Sources all eclasses in parameters +declare -ix ECLASS_DEPTH=0 +inherit() { + ECLASS_DEPTH=$(($ECLASS_DEPTH + 1)) + if [[ $ECLASS_DEPTH > 1 ]]; then + debug-print "*** Multiple Inheritence (Level: ${ECLASS_DEPTH})" + fi + + local location + local PECLASS + + local B_IUSE + local B_DEPEND + local B_RDEPEND + local B_CDEPEND + local B_PDEPEND + while [ "$1" ]; do + location="${ECLASSDIR}/${1}.eclass" + + # PECLASS is used to restore the ECLASS var after recursion. + PECLASS="$ECLASS" + export ECLASS="$1" + + if [ "$EBUILD_PHASE" != "depend" ]; then + if ! hasq $ECLASS $INHERITED; then + echo + echo "QA Notice: ECLASS '$ECLASS' inherited illegally in $CATEGORY/$PF" >&2 + echo + fi + fi + + # any future resolution code goes here + if [ -n "$PORTDIR_OVERLAY" ]; then + local overlay + for overlay in ${PORTDIR_OVERLAY}; do + olocation="${overlay}/eclass/${1}.eclass" + if [ -e "$olocation" ]; then + location="${olocation}" + debug-print " eclass exists: ${location}" + fi + done + fi + debug-print "inherit: $1 -> $location" + + #We need to back up the value of DEPEND and RDEPEND to B_DEPEND and B_RDEPEND + #(if set).. and then restore them after the inherit call. + + #turn off glob expansion + set -f + + # Retain the old data and restore it later. + unset B_IUSE B_DEPEND B_RDEPEND B_CDEPEND B_PDEPEND + [ "${IUSE-unset}" != "unset" ] && B_IUSE="${IUSE}" + [ "${DEPEND-unset}" != "unset" ] && B_DEPEND="${DEPEND}" + [ "${RDEPEND-unset}" != "unset" ] && B_RDEPEND="${RDEPEND}" + [ "${CDEPEND-unset}" != "unset" ] && B_CDEPEND="${CDEPEND}" + [ "${PDEPEND-unset}" != "unset" ] && B_PDEPEND="${PDEPEND}" + unset IUSE DEPEND RDEPEND CDEPEND PDEPEND + #turn on glob expansion + set +f + + source "$location" || export ERRORMSG="died sourcing $location in inherit()" + [ -z "${ERRORMSG}" ] || die "${ERRORMSG}" + + #turn off glob expansion + set -f + + # If each var has a value, append it to the global variable E_* to + # be applied after everything is finished. New incremental behavior. + [ "${IUSE-unset}" != "unset" ] && export E_IUSE="${E_IUSE} ${IUSE}" + [ "${DEPEND-unset}" != "unset" ] && export E_DEPEND="${E_DEPEND} ${DEPEND}" + [ "${RDEPEND-unset}" != "unset" ] && export E_RDEPEND="${E_RDEPEND} ${RDEPEND}" + [ "${CDEPEND-unset}" != "unset" ] && export E_CDEPEND="${E_CDEPEND} ${CDEPEND}" + [ "${PDEPEND-unset}" != "unset" ] && export E_PDEPEND="${E_PDEPEND} ${PDEPEND}" + + [ "${B_IUSE-unset}" != "unset" ] && IUSE="${B_IUSE}" + [ "${B_IUSE-unset}" != "unset" ] || unset IUSE + + [ "${B_DEPEND-unset}" != "unset" ] && DEPEND="${B_DEPEND}" + [ "${B_DEPEND-unset}" != "unset" ] || unset DEPEND + + [ "${B_RDEPEND-unset}" != "unset" ] && RDEPEND="${B_RDEPEND}" + [ "${B_RDEPEND-unset}" != "unset" ] || unset RDEPEND + + [ "${B_CDEPEND-unset}" != "unset" ] && CDEPEND="${B_CDEPEND}" + [ "${B_CDEPEND-unset}" != "unset" ] || unset CDEPEND + + [ "${B_PDEPEND-unset}" != "unset" ] && PDEPEND="${B_PDEPEND}" + [ "${B_PDEPEND-unset}" != "unset" ] || unset PDEPEND + + #turn on glob expansion + set +f + + hasq $1 $INHERITED || export INHERITED="$INHERITED $1" + + export ECLASS="$PECLASS" + + shift + done + ECLASS_DEPTH=$(($ECLASS_DEPTH - 1)) +} + +# Exports stub functions that call the eclass's functions, thereby making them default. +# For example, if ECLASS="base" and you call "EXPORT_FUNCTIONS src_unpack", the following +# code will be eval'd: +# src_unpack() { base_src_unpack; } +EXPORT_FUNCTIONS() { + if [ -z "$ECLASS" ]; then + echo "EXPORT_FUNCTIONS without a defined ECLASS" >&2 + exit 1 + fi + while [ "$1" ]; do + debug-print "EXPORT_FUNCTIONS: ${1} -> ${ECLASS}_${1}" + eval "$1() { ${ECLASS}_$1 "\$@" ; }" > /dev/null + shift + done +} + +# adds all parameters to E_DEPEND and E_RDEPEND, which get added to DEPEND +# and RDEPEND after the ebuild has been processed. This is important to +# allow users to use DEPEND="foo" without frying dependencies added by an +# earlier inherit. It also allows RDEPEND to work properly, since a lot +# of ebuilds assume that an unset RDEPEND gets its value from DEPEND. +# Without eclasses, this is true. But with them, the eclass may set +# RDEPEND itself (or at least used to) which would prevent RDEPEND from +# getting its value from DEPEND. This is a side-effect that made eclasses +# have unreliable dependencies. + +newdepend() { + debug-print-function newdepend $* + debug-print "newdepend: E_DEPEND=$E_DEPEND E_RDEPEND=$E_RDEPEND" + + while [ -n "$1" ]; do + case $1 in + "/autotools") + do_newdepend DEPEND sys-devel/autoconf sys-devel/automake sys-devel/make + ;; + "/c") + do_newdepend DEPEND sys-devel/gcc virtual/libc + do_newdepend RDEPEND virtual/libc + ;; + *) + do_newdepend DEPEND $1 + ;; + esac + shift + done +} + +newrdepend() { + debug-print-function newrdepend $* + do_newdepend RDEPEND $1 +} + +newcdepend() { + debug-print-function newcdepend $* + do_newdepend CDEPEND $1 +} + +newpdepend() { + debug-print-function newpdepend $* + do_newdepend PDEPEND $1 +} + +do_newdepend() { + # This function does a generic change determining whether we're in an + # eclass or not. If we are, we change the E_* variables for deps. + debug-print-function do_newdepend $* + [ -z "$1" ] && die "do_newdepend without arguments" + + # Grab what we're affecting... Figure out if we're affecting eclasses. + [[ ${ECLASS_DEPTH} > 0 ]] && TARGET="E_$1" + [[ ${ECLASS_DEPTH} > 0 ]] || TARGET="$1" + shift # $1 was a variable name. + + while [ -n "$1" ]; do + # This bit of evil takes TARGET and uses it to evaluate down to a + # variable. This is a sneaky way to make this infinately expandable. + # The normal translation of this would look something like this: + # E_DEPEND="${E_DEPEND} $1" :::::: Cool, huh? :) + eval export ${TARGET}=\"\${${TARGET}} \$1\" + shift + done +} + +# this is a function for removing any directory matching a passed in pattern from +# PATH +remove_path_entry() { + save_IFS + IFS=":" + stripped_path="${PATH}" + while [ -n "$1" ]; do + cur_path="" + for p in ${stripped_path}; do + if [ "${p/${1}}" == "${p}" ]; then + cur_path="${cur_path}:${p}" + fi + done + stripped_path="${cur_path#:*}" + shift + done + restore_IFS + PATH="${stripped_path}" +} + +# === === === === === === === === === === === === === === === === === === +# === === === === === functions end, main part begins === === === === === +# === === === === === functions end, main part begins === === === === === +# === === === === === functions end, main part begins === === === === === +# === === === === === === === === === === === === === === === === === === + +if [ "$*" != "depend" ] && [ "$*" != "clean" ]; then + cd ${PORTAGE_TMPDIR} &> /dev/null + cd ${BUILD_PREFIX} &> /dev/null + + if [ "$(id -nu)" == "portage" ] ; then + export USER=portage + fi + + if hasq distcc ${FEATURES} &>/dev/null; then + if [ -d /usr/lib/distcc/bin ]; then + #We can enable distributed compile support + if [ -z "${PATH/*distcc*/}" ]; then + # Remove the other reference. + remove_path_entry "distcc" + fi + export PATH="/usr/lib/distcc/bin:${PATH}" + [ ! -z "${DISTCC_LOG}" ] && addwrite "$(dirname ${DISTCC_LOG})" + elif which distcc &>/dev/null; then + export CC="distcc $CC" + export CXX="distcc $CXX" + fi + fi + + if hasq ccache ${FEATURES} &>/dev/null; then + #We can enable compiler cache support + if [ -z "${PATH/*ccache*/}" ]; then + # Remove the other reference. + remove_path_entry "ccache" + fi + + if [ -d /usr/lib/ccache/bin ]; then + export PATH="/usr/lib/ccache/bin:${PATH}" + elif [ -d /usr/bin/ccache ]; then + export PATH="/usr/bin/ccache:${PATH}" + fi + + [ -z "${CCACHE_DIR}" ] && export CCACHE_DIR="/root/.ccache" + + addread "${CCACHE_DIR}" + addwrite "${CCACHE_DIR}" + + [ -n "${CCACHE_SIZE}" ] && ccache -M ${CCACHE_SIZE} &> /dev/null + fi + + # XXX: Load up the helper functions. +# for X in /usr/lib/portage/bin/functions/*.sh; do +# source ${X} || die "Failed to source ${X}" +# done + +else + +killparent() { + trap INT + kill ${PORTAGE_MASTER_PID} +} +trap "killparent" INT + +fi # "$*"!="depend" && "$*"!="clean" + +export SANDBOX_ON="1" +export S=${WORKDIR}/${P} + +unset E_IUSE E_DEPEND E_RDEPEND E_CDEPEND E_PDEPEND + +declare -r T P PN PV PVR PR A D EBUILD EMERGE_FROM O PPID FILESDIR +declare -r PORTAGE_TMPDIR + +# Turn of extended glob matching so that g++ doesn't get incorrectly matched. +shopt -u extglob + +QA_INTERCEPTORS="javac java-config python python-config perl grep egrep fgrep sed gcc g++ cc bash awk nawk gawk pkg-config" +# level the QA interceptors if we're in depend +if hasq "depend" "$@"; then + for BIN in ${QA_INTERCEPTORS}; do + BIN_PATH=`type -pf ${BIN}` + if [ "$?" != "0" ]; then + BODY="echo \"*** missing command: ${BIN}\" >&2; return 127" + else + BODY="${BIN_PATH} \"\$@\"; return \$?" + fi + FUNC_SRC="${BIN}() { + echo -n \"QA Notice: ${BIN} in global scope: \" >&2 + if [ \$ECLASS_DEPTH -gt 0 ]; then + echo \"eclass \${ECLASS}\" >&2 + else + echo \"\${CATEGORY}/\${PF}\" >&2 + fi + ${BODY} + }"; + eval "$FUNC_SRC" || echo "error creating QA interceptor ${BIN}" >&2 + done + unset src bin_path body +fi +source ${EBUILD} || die "error sourcing ebuild" +if ! hasq depend $EBUILD_PHASE; then + RESTRICT="${PORTAGE_RESTRICT}" + unset PORTAGE_RESTRICT +fi +[ -z "${ERRORMSG}" ] || die "${ERRORMSG}" + +# Expand KEYWORDS +# We need to turn off pathname expansion for -* in KEYWORDS and +# we need to escape ~ to avoid tilde expansion +set -f +KEYWORDS="`eval echo ${KEYWORDS//~/\\~}`" +set +f + +hasq nostrip ${RESTRICT} && export DEBUGBUILD=1 + +#a reasonable default for $S +if [ "$S" = "" ]; then + export S=${WORKDIR}/${P} +fi + +#wipe the interceptors. we don't want saved. +if hasq "depend" "$@"; then + unset -f $QA_INTERCEPTORS + unset QA_INTERCEPTORS +fi + +#some users have $TMP/$TMPDIR to a custom dir in their home ... +#this will cause sandbox errors with some ./configure +#scripts, so set it to $T. +export TMP="${T}" +export TMPDIR="${T}" + +# Note: this next line is not the same as export RDEPEND=${RDEPEND:-${DEPEND}} +# That will test for unset *or* NULL (""). We want just to set for unset... + +#turn off glob expansion from here on in to prevent *'s and ? in the DEPEND +#syntax from getting expanded :) Fixes bug #1473 +#check eclass rdepends also. bug #58819 +set -f +if [ "${RDEPEND-unset}" == "unset" ] && [ "${E_RDEPEND-unset}" == "unset" ] ; then + export RDEPEND="${DEPEND} ${E_DEPEND}" + debug-print "RDEPEND: not set... Setting to: ${DEPEND}" +fi + +#add in dependency info from eclasses +IUSE="$IUSE $E_IUSE" +DEPEND="$DEPEND $E_DEPEND" +RDEPEND="$RDEPEND $E_RDEPEND" +CDEPEND="$CDEPEND $E_CDEPEND" +PDEPEND="$PDEPEND $E_PDEPEND" + +unset E_IUSE E_DEPEND E_RDEPEND E_CDEPEND E_PDEPEND + +if [ "${EBUILD_PHASE}" != "depend" ]; then + # Lock the dbkey variables after the global phase + declare -r DEPEND RDEPEND SLOT SRC_URI RESTRICT HOMEPAGE LICENSE DESCRIPTION + declare -r KEYWORDS INHERITED IUSE CDEPEND PDEPEND PROVIDE +fi + +set +f + +for myarg in $*; do + case $myarg in + nofetch) + pkg_nofetch + exit 1 + ;; + prerm|postrm|postinst|config) + export SANDBOX_ON="0" + if [ "$PORTAGE_DEBUG" != "1" ]; then + pkg_${myarg} + #Allow non-zero return codes since they can be caused by && + else + set -x + pkg_${myarg} + #Allow non-zero return codes since they can be caused by && + set +x + fi + ;; + unpack|compile|test|clean|install) + if [ "${SANDBOX_DISABLED="0"}" == "0" ]; then + export SANDBOX_ON="1" + else + export SANDBOX_ON="0" + fi + if [ "$PORTAGE_DEBUG" != "1" ]; then + dyn_${myarg} + #Allow non-zero return codes since they can be caused by && + else + set -x + dyn_${myarg} + #Allow non-zero return codes since they can be caused by && + set +x + fi + export SANDBOX_ON="0" + ;; + help|clean|setup|preinst) + #pkg_setup needs to be out of the sandbox for tmp file creation; + #for example, awking and piping a file in /tmp requires a temp file to be created + #in /etc. If pkg_setup is in the sandbox, both our lilo and apache ebuilds break. + export SANDBOX_ON="0" + if [ "$PORTAGE_DEBUG" != "1" ]; then + dyn_${myarg} + else + set -x + dyn_${myarg} + set +x + fi + ;; + package|rpm) + export SANDBOX_ON="0" + if [ "$PORTAGE_DEBUG" != "1" ]; then + dyn_${myarg} + else + set -x + dyn_${myarg} + set +x + fi + ;; + depend) + export SANDBOX_ON="0" + set -f + + # Handled in portage.py now + #dbkey=${PORTAGE_CACHEDIR}/${CATEGORY}/${PF} + + if [ ! -d "${dbkey%/*}" ]; then + install -d -g ${PORTAGE_GID} -m2775 "${dbkey%/*}" + fi + + # Make it group writable. 666&~002==664 + umask 002 + + #the extra `echo` commands remove newlines + echo `echo "$DEPEND"` > $dbkey + echo `echo "$RDEPEND"` >> $dbkey + echo `echo "$SLOT"` >> $dbkey + echo `echo "$SRC_URI"` >> $dbkey + echo `echo "$RESTRICT"` >> $dbkey + echo `echo "$HOMEPAGE"` >> $dbkey + echo `echo "$LICENSE"` >> $dbkey + echo `echo "$DESCRIPTION"` >> $dbkey + echo `echo "$KEYWORDS"` >> $dbkey + echo `echo "$INHERITED"` >> $dbkey + echo `echo "$IUSE"` >> $dbkey + echo `echo "$CDEPEND"` >> $dbkey + echo `echo "$PDEPEND"` >> $dbkey + echo `echo "$PROVIDE"` >> $dbkey + echo `echo "$UNUSED_01"` >> $dbkey + echo `echo "$UNUSED_02"` >> $dbkey + echo `echo "$UNUSED_03"` >> $dbkey + echo `echo "$UNUSED_04"` >> $dbkey + echo `echo "$UNUSED_05"` >> $dbkey + echo `echo "$UNUSED_06"` >> $dbkey + echo `echo "$UNUSED_07"` >> $dbkey + echo `echo "$UNUSED_08"` >> $dbkey + set +f + #make sure it is writable by our group: + exit 0 + ;; + *) + export SANDBOX_ON="1" + echo "Please specify a valid command." + echo + dyn_help + exit 1 + ;; + esac + + #if [ $? -ne 0 ]; then + # exit 1 + #fi +done + +if [ "$myarg" != "clean" ]; then + # Save current environment and touch a success file. (echo for success) + umask 002 + set | egrep -v "^SANDBOX_" > "${T}/environment" 2>/dev/null + chown portage:portage "${T}/environment" &>/dev/null + chmod g+w "${T}/environment" &>/dev/null +fi + +exit 0 diff --git a/bin/emake b/bin/emake new file mode 100755 index 000000000..44fe83402 --- /dev/null +++ b/bin/emake @@ -0,0 +1,14 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/emake,v 1.9.2.1 2005/05/18 15:19:52 jstubbs Exp $ +# +# emake: Supplies some default parameters to GNU make. At the moment the +# only parameter supplied is -jN, where N is a number of +# parallel processes that should be ideal for the running host +# (e.g. on a single-CPU machine, N=2). The MAKEOPTS variable +# is set in /etc/make.globals. We don't source +# /etc/make.globals here because emake is only called from an +# ebuild. + +${MAKE:-make} ${MAKEOPTS} ${EXTRA_EMAKE} "$@" diff --git a/bin/emerge b/bin/emerge new file mode 100755 index 000000000..5ae171963 --- /dev/null +++ b/bin/emerge @@ -0,0 +1,3213 @@ +#!/usr/bin/python -O +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/emerge,v 1.345.2.38 2005/08/13 17:25:26 ferringb Exp $ + +import os,sys +os.environ["PORTAGE_CALLER"]="emerge" +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage + +import emergehelp,xpak,string,re,commands,time,shutil,traceback,atexit,signal,socket,types +from stat import * +from output import * + +import portage_util +import portage_locks +import portage_exception + + +spinner_msgs = ["Gentoo Rocks ("+os.uname()[0]+")", + "Thank you for using Gentoo. :)", + "Are you actually trying to read this?", + "How many times have you stared at this?", + "We are generating the cache right now", + "You are paying too much attention.", + "A theory is better than its explanation.", + "Phasers locked on target, Captain.", + "Thrashing is just virtual crashing.", + "To be is to program.", + "Real Users hate Real Programmers.", + "When all else fails, read the instructions.", + "Functionality breeds Contempt.", + "The future lies ahead.", + "3.1415926535897932384626433832795028841971694", + "Sometimes insanity is the only alternative.", + "Inaccuracy saves a world of explanation.", + ] + + +def update_basic_spinner(): + global spinner, spinpos + spinpos = (spinpos+1) % 500 + if (spinpos % 100) == 0: + if spinpos == 0: + sys.stdout.write(". ") + else: + sys.stdout.write(".") + sys.stdout.flush() + +def update_scroll_spinner(): + global spinner, spinpos + if(spinpos >= len(spinner)): + sys.stdout.write(darkgreen(" \b\b\b"+spinner[len(spinner)-1-(spinpos%len(spinner))])) + else: + sys.stdout.write(green("\b "+spinner[spinpos])) + sys.stdout.flush() + spinpos = (spinpos+1) % (2*len(spinner)) + +def update_twirl_spinner(): + global spinner, spinpos + spinpos = (spinpos+1) % len(spinner) + sys.stdout.write("\b\b "+spinner[spinpos]) + sys.stdout.flush() + +spinpos = 0 +spinner = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|" +update_spinner = update_twirl_spinner +if "candy" in portage.settings.features: + spinner = spinner_msgs[int(time.time()*100)%len(spinner_msgs)] + update_spinner = update_scroll_spinner +if not sys.stdout.isatty() or ("--nospinner" in sys.argv): + update_spinner = update_basic_spinner + + +if (not sys.stdout.isatty()) or (portage.settings["NOCOLOR"] in ["yes","true"]): + nocolor() + +def normpath(mystr): + if mystr and (mystr[0]=='/'): + return os.path.normpath("///"+mystr) + else: + return os.path.normpath(mystr) + +def userquery(prompt, responses=None, colours=None): + """Displays a prompt and a set of responses, then waits for a response + which is checked against the responses and the first to match is + returned. + + prompt: a String. + responses: a List of Strings. + colours: a List of Functions taking and returning a String, used to + process the responses for display. Typically these will be functions + like red() but could be e.g. lambda x: "DisplayString". + If responses is omitted, defaults to ["Yes", "No"], [green, red]. + If only colours is omitted, defaults to [bold, ...]. + + Returns a member of the List responses. (If called without optional + arguments, returns "Yes" or "No".) + KeyboardInterrupt is converted to SystemExit to avoid tracebacks being + printed.""" + if responses is None: + responses, colours = ["Yes", "No"], [green, red] + elif colours is None: + colours=[bold] + colours=(colours*len(responses))[:len(responses)] + print bold(prompt), + try: + while True: + response=raw_input("["+string.join([colours[i](responses[i]) for i in range(len(responses))],"/")+"] ") + for key in responses: + if response.upper()==key[:len(response)].upper(): + return key + print "Sorry, response '%s' not understood." % response, + except (EOFError, KeyboardInterrupt): + print "Interrupted." + sys.exit(1) + +def sorted_versions(verlist): + ret = [] + for ver in verlist: + verparts = ver.split("-") + if len(verparts) == 2: + verrev = int(verparts[1][1:]) + else: + verrev = 0 + x = 0 + while x < len(ret): + retparts = ret[x].split("-") + verdiff = portage.vercmp(retparts[0], verparts[0]) + if verdiff > 0: + break + elif verdiff == 0: + if len(retparts) == 2: + retrev = int(retparts[1][1:]) + else: + retrev = 0 + if retrev >= verrev: + break + x += 1 + ret.insert(x, ver) + return ret + +if portage.settings.has_key("PORTAGE_NICENESS"): + try: + os.nice(int(portage.settings["PORTAGE_NICENESS"])) + except SystemExit, e: + raise # Needed else can't exit + except Exception,e: + print "!!! Failed to change nice value to '"+str(portage.settings["PORTAGE_NICENESS"])+"'" + print "!!!",e + +#Freeze the portdbapi for enhanced performance: +portage.portdb.freeze() + +# Kill noauto as it will break merges otherwise. +while 'noauto' in portage.features: + del portage.features[portage.features.index('noauto')] + +#number of ebuilds merged +merged=0 +params=["selective", "deep", "self", "recurse", "empty"] +actions=[ +"clean", "config", "depclean", +"info", "inject", "metadata", +"prune", "regen", "rsync", "search", +"sync", "system", "unmerge", "world", +] +options=[ +"--ask", +"--buildpkg", "--buildpkgonly", +"--changelog", "--columns", +"--debug", "--deep", +"--digest", +"--emptytree", +"--fetchonly", "--fetch-all-uri", +"--getbinpkg", "--getbinpkgonly", +"--help", "--noconfmem", +"--newuse", "--nocolor", +"--nodeps", "--noreplace", +"--nospinner", "--oneshot", +"--onlydeps", "--pretend", +"--quiet", "--resume", +"--searchdesc", "--selective", +"--skipfirst", +"--tree", +"--update", "--upgradeonly", +"--usepkg", "--usepkgonly", +"--verbose", "--version" +] + +shortmapping={ +"1":"--oneshot", +"a":"--ask", +"b":"--buildpkg", "B":"--buildpkgonly", +"c":"--clean", "C":"--unmerge", +"d":"--debug", "D":"--deep", +"e":"--emptytree", +"f":"--fetchonly", "F":"--fetch-all-uri", +"g":"--getbinpkg", "G":"--getbinpkgonly", +"h":"--help", +"i":"--inject", +"k":"--usepkg", "K":"--usepkgonly", +"l":"--changelog", +"n":"--noreplace", "N":"--newuse", +"o":"--onlydeps", "O":"--nodeps", +"p":"--pretend", "P":"--prune", +"q":"--quiet", +"s":"--search", "S":"--searchdesc", +'t':"--tree", +"u":"--update", "U":"--upgradeonly", +"v":"--verbose", "V":"--version" +} + +myaction=None +myopts=[] +myfiles=[] +edebug=0 + +# process short actions +tmpcmdline=sys.argv[1:] +#tmpcmdline.extend(portage.settings["EMERGE_OPTS"].split()) +cmdline=[] +for x in tmpcmdline: + if x[0:1]=="-"and x[1:2]!="-": + for y in x[1:]: + if shortmapping.has_key(y): + if shortmapping[y] in cmdline: + print + print "*** Warning: Redundant use of",shortmapping[y] + else: + cmdline.append(shortmapping[y]) + else: + print "!!! Error: -"+y+" is an invalid short action or option." + sys.exit(1) + else: + cmdline.append(x) + +# process the options and command arguments +for x in cmdline: + if not x: + continue + if len(x)>=2 and x[0:2]=="--": + if x in options: + 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 + print + print red("!!!")+green(" Multiple actions requested... Please choose one only.") + print red("!!!")+" '"+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'" + print + sys.exit(1) + myaction=x[2:] + else: + print "!!! Error:",x,"is an invalid option." + 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 + if myaction: + print + print red("!!!")+green(" Multiple actions requested... Please choose one only.") + print red("!!! '")+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'" + print + sys.exit(1) + myaction=x + elif x[-1]=="/": + # this little conditional helps tab completion + myfiles.append(x[:-1]) + else: + myfiles.append(x) + + +if "moo" in myfiles: + print """ + + Gentoo (""" + os.uname()[0] + """) + + _______________________ +< Have you mooed today? > + ----------------------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || + +""" + +if (myaction in ["world", "system"]) and myfiles: + print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both." + sys.exit(1) + +for x in myfiles: + if (x[-7:] == ".ebuild" or x[-5:] == ".tbz2") and os.path.exists(os.path.abspath(x)): + print "emerging by path implies --oneshot... adding --oneshot to options." + print red("\n*** emerging by path is broken and may not always work!!!\n") + break + +if ("--tree" in myopts) and ("--columns" in myopts): + print "emerge: can't specify both of \"--tree\" and \"--columns\"." + sys.exit(1) + +# Always create packages if FEATURES=buildpkg +# Imply --buildpkg if --buildpkgonly +if ("buildpkg" in portage.features) or ("--buildpkgonly" in myopts): + if "--buildpkg" not in myopts: + myopts.append("--buildpkg") + +# --tree only makes sense with --pretend +if "--tree" in myopts and not (("--pretend" in myopts) or ("--ask" in myopts)): + print ">>> --tree implies --pretend... adding --pretend to options." + myopts.append("--pretend") + +# Also allow -S to invoke search action (-sS) +if ("--searchdesc" in myopts): + if myaction and myaction != "search": + myfiles.append(myaction) + if "--search" not in myopts: + myopts.append("--search") + myaction = "search" + +# Always try and fetch binary packages if FEATURES=getbinpkg +if ("getbinpkg" in portage.features): + myopts.append("--getbinpkg") + +if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts): + myopts.append("--usepkgonly") + +if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts): + myopts.append("--getbinpkg") + +if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts): + myopts.append("--usepkg") + +# Also allow -K to apply --usepkg/-k +if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts): + myopts.append("--usepkg") + +# 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." + myopts.append("--pretend") + +# Allow -p to remove --ask +if ("--pretend" in myopts) and ("--ask" in myopts): + print ">>> --pretend disables --ask... removing --ask from options." + myopts.remove("--ask") + +# forbid --ask when not in a terminal +# note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway. +if ("--ask" in myopts) and (not sys.stdin.isatty()): + portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n") + sys.exit(1) + +# Set so that configs will be merged regardless of remembered status +if ("--noconfmem" in myopts): + portage.settings.unlock() + portage.settings["NOCONFMEM"]="1" + portage.settings.backup_changes("NOCONFMEM") + portage.settings.lock() + +# Set various debug markers... They should be merged somehow. +if ("--debug" in myopts): + portage.settings.unlock() + portage.settings["PORTAGE_DEBUG"]="1" + portage.settings.backup_changes("PORTAGE_DEBUG") + portage.debug=1 + portage.settings.lock() + +if ("--resume" in myopts): + if "--verbose" in myopts: + print "* --verbose is currently broken with --resume. Disabling..." + myopts.remove("--verbose") + if "--tree" in myopts: + print "* --tree is currently broken with --resume. Disabling..." + myopts.remove("--tree") + +# Set color output +if ("--nocolor" in myopts) and (sys.stdout.isatty()): + nocolor() + +CLEAN_DELAY = 5 +EMERGE_WARNING_DELAY = 10 +if portage.settings["CLEAN_DELAY"]: + CLEAN_DELAY = string.atoi("0"+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: + xtermTitle(short_msg) + else: + xtermTitle(mystr) + try: + #seems odd opening a file each write... + if not os.path.exists("/var/log/emerge.log"): + mylogfile=open("/var/log/emerge.log", "w") + os.chmod("/var/log/emerge.log", S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) + os.chown("/var/log/emerge.log", portage.portage_uid, portage.portage_gid) + else: + mylogfile=open("/var/log/emerge.log", "a") + + l=portage_locks.lockfile(mylogfile) + # seek because we may have gotten held up by the lock. + # if so, we may not be positioned at the end of the file. + mylogfile.seek(0,2) + mylogfile.write(str(time.time())[:10]+": "+mystr+"\n") + mylogfile.flush() + portage_locks.unlockfile(l) + mylogfile.close() + except SystemExit, e: + raise # Needed else can't exit + except Exception, e: + if edebug: + print "emergelog():",e + pass + +def emergeexit(): + """This gets out final log message in before we quit.""" + if "--pretend" not in myopts: + emergelog(" *** terminating.") + if "notitles" not in portage.features: + xtermTitleReset() +atexit.register(emergeexit) + +def emergeexitsig(signum, frame): + signal.signal(signal.SIGINT, signal.SIG_IGN) + portage.portageexit() + portage_util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum}) + sys.exit(100+signum) +signal.signal(signal.SIGINT, emergeexitsig) + +def countdown(secs=5, doing="Starting"): + if secs: + print ">>> Waiting",secs,"seconds before starting..." + print ">>> (Control-C to abort)...\n"+doing+" in: ", + ticks=range(secs) + ticks.reverse() + for sec in ticks: + sys.stdout.write(red(str(sec+1)+" ")) + sys.stdout.flush() + time.sleep(1) + print + +# formats a size given in bytes nicely +def format_size(mysize): + if type(mysize) not in [types.IntType,types.LongType]: + return str(mysize) + mystr=str(mysize/1024) + mycount=len(mystr) + while (mycount > 3): + mycount-=3 + mystr=mystr[:mycount]+","+mystr[mycount:] + return mystr+" kB" + + +def getgccversion(): + """ + rtype: C{str} + return: the current in-use gcc version + """ + + gcc_env_dir = os.path.join('/', 'etc', 'env.d', 'gcc') + gcc_config_config = os.path.join(gcc_env_dir, 'config') + gcc_ver_command = 'gcc -dumpversion' + gcc_ver_prefix = 'gcc-' + + gcc_not_found_error = red( + "!!! No gcc found. You probably need to 'source /etc/profile'\n" + + "!!! to update the environment of this terminal and possibly\n" + + "!!! other terminals also." + ) + + gcc_distcc_broken_error = green( + '!!! Relying on the shell to locate gcc, this may break\n' + + '!!! DISTCC, installing gcc-config and setting your current gcc\n' + + '!!! profile will fix this' + ) + + def fallback(): + + print >>sys.stderr, gcc_distcc_broken_error + + gccout = commands.getstatusoutput(gcc_ver_command) + + if gccout[0] != 0: + print >>sys.stderr, gcc_not_found_error + gccver = "[unavailable]" + else: + gccver = gcc_ver_prefix + gccout[1] + + return gccver + + if os.path.isfile(gcc_config_config): + try: + gccver_str = open(gcc_config_config).read().strip() + gccver = gcc_ver_prefix + string.join(gccver_str.split('-')[4:], '-') + except IndexError: + gccver = fallback() + + else: + import glob + dir_l = glob.glob(os.path.join(gcc_env_dir, '*-*')) + + if len(dir_l) == 1: + try: + gccver = gcc_ver_prefix + dir_l[0].split('-')[-1] + except IndexError: + gccver = fallback() + + else: + # There was no "config" file in /etc/env.d/gcc and there was more + # than one profile in /etc/env.d/gcc so we can't actively + # determine what version of gcc we are using so we fall back on the + # old way that breaks distcc + + gccver = fallback() + + return gccver + +def getportageversion(): + try: + import re + profilever = os.path.normpath("///"+os.readlink("/etc/make.profile")) + basepath = os.path.normpath("///"+portage.settings["PORTDIR"]+"/profiles") + if re.match(basepath,profilever): + profilever = profilever[len(basepath)+1:] + else: + profilever = "!"+profilever + del basepath + except SystemExit, e: + raise # Needed else can't exit + except: + profilever="unavailable" + libcver=[] + libclist = portage.vardbapi(portage.root).match("virtual/libc") + libclist += portage.vardbapi(portage.root).match("virtual/glibc") + libclist = portage_util.unique_array(libclist) + for x in libclist: + xs=portage.catpkgsplit(x) + if libcver: + libcver+=","+string.join(xs[1:], "-") + else: + libcver=string.join(xs[1:], "-") + if libcver==[]: + libcver="unavailable" + + gccver = getgccversion() + unameout=os.uname()[2]+" "+os.uname()[4] + + return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")" + +def help(): + # Move all the help stuff out of this file. + emergehelp.help(myaction,myopts,havecolor) + +# check if root user is the current user for the actions where emerge needs this +if ("--pretend" in myopts) or ("--fetchonly" in myopts or "--fetch-all-uri" in myopts) or (myaction=="search"): + if not portage.secpass: + if portage.wheelgid==portage.portage_gid: + print "emerge: wheel group membership required for \"--pretend\" and search." + print "emerge: wheel group use is being deprecated. Please update group and passwd to" + print " include the portage user as noted above, and then use group portage." + else: + print "emerge: portage group membership required for \"--pretend\" and search." + sys.exit(1) +elif "--version" in myopts: + print getportageversion() + sys.exit(0) +elif "--help" in myopts: + help() + sys.exit(0) +elif portage.secpass!=2: + if myaction in ["search", "info", "regen"]: + pass + elif (not myaction) and (not myfiles): + pass + elif ("--pretend" in myopts) and (myaction in ["world","system","clean","prune","unmerge"]): + pass + else: + if "--debug" in myopts: + print "myaction",myaction + print "myopts",myopts + print "emerge: root access required." + sys.exit(1) + +if not "--pretend" in myopts: + emergelog("Started emerge on: "+time.strftime("%b %d, %Y %H:%M:%S", time.localtime())) + myelogstr="" + if myopts: + myelogstr=string.join(myopts, " ") + if myaction: + myelogstr+=" "+myaction + if myfiles: + myelogstr+=" "+string.join(myfiles, " ") + emergelog(" *** emerge "+myelogstr) + +#configure emerge engine parameters +# +# self: include _this_ package regardless of if it is merged. +# selective: exclude the package if it is merged +# recurse: go into the dependencies +# empty: pretend nothing is merged +myparams=["self","recurse"] +add=[] +sub=[] +if "--update" in myopts: + add.extend(["selective","empty"]) +if "--emptytree" in myopts: + add.extend(["empty"]) + sub.extend(["selective"]) +if "--nodeps" in myopts: + sub.extend(["recurse"]) +if "--noreplace" in myopts: + add.extend(["selective"]) +if "--deep" in myopts: + add.extend(["deep"]) +if "--selective" in myopts: + add.extend(["selective"]) +if myaction in ["world","system"]: + add.extend(["selective"]) +elif myaction in ["depclean"]: + add.extend(["empty"]) + sub.extend(["selective"]) +for x in add: + if (x not in myparams) and (x not in sub): + myparams.append(x) +for x in sub: + if x in myparams: + myparams.remove(x) + +# search functionality +class search: + + # + # class constants + # + VERSION_SHORT=1 + VERSION_RELEASE=2 + + # + # public interface + # + def __init__(self): + """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.installcache = portage.db["/"]["vartree"] + + def execute(self,searchkey): + """Performs the search for the supplied search key""" + global myopts + match_category = 0 + self.searchkey=searchkey + self.packagematches = [] + if "--searchdesc" in myopts: + self.searchdesc=1 + self.matches = {"pkg":[], "desc":[]} + else: + self.searchdesc=0 + self.matches = {"pkg":[]} + print "Searching... ", + + if self.searchkey[0] == '@': + match_category = 1 + self.searchkey = self.searchkey[1:] + if self.searchkey=="*": + #hack for people who aren't regular expression gurus + self.searchkey==".*" + if re.search("\+\+", self.searchkey): + #hack for people who aren't regular expression gurus + self.searchkey=re.sub("\+\+","\+\+",self.searchkey) + self.searchre=re.compile(self.searchkey.lower(),re.I) + for package in portage.portdb.cp_all(): + update_spinner() + + if match_category: + match_string = package[:] + else: + match_string = package.split("/")[-1] + + masked=0 + if self.searchre.search(match_string): + if not portage.portdb.xmatch("match-visible",package): + masked=1 + self.matches["pkg"].append([package,masked]) + elif self.searchdesc: # DESCRIPTION searching + full_package = portage.portdb.xmatch("bestmatch-visible",package) + if not full_package: + #no match found; we don't want to query description + full_package=portage.best(portage.portdb.xmatch("match-all",package)) + if not full_package: + continue + else: + masked=1 + try: + full_desc = portage.portdb.aux_get(full_package,["DESCRIPTION"])[0] + except KeyError: + print "emerge: search: aux_get() failed, skipping" + continue + if self.searchre.search(full_desc): + self.matches["desc"].append([full_package,masked]) + self.mlen=0 + for mtype in self.matches.keys(): + self.matches[mtype].sort() + self.mlen += len(self.matches[mtype]) + + def output(self): + """Outputs the results of the search.""" + print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]" + print "[ Applications found : "+white(str(self.mlen))+" ]" + print " " + for mtype in self.matches.keys(): + for match,masked in self.matches[mtype]: + if mtype=="pkg": + catpack=match + full_package = portage.portdb.xmatch("bestmatch-visible",match) + if not full_package: + #no match found; we don't want to query description + masked=1 + full_package=portage.best(portage.portdb.xmatch("match-all",match)) + else: + full_package = match + match = portage.pkgsplit(match)[0] + + if full_package: + try: + desc, homepage, license = portage.portdb.aux_get(full_package,["DESCRIPTION","HOMEPAGE","LICENSE"]) + except KeyError: + print "emerge: search: aux_get() failed, skipping" + continue + if masked: + print green("*")+" "+white(match)+" "+red("[ Masked ]") + else: + print green("*")+" "+white(match) + myversion = self.getVersion(full_package, search.VERSION_RELEASE) + + mysum = [0,0] + mycat = match.split("/")[0] + mypkg = match.split("/")[1] + + mydigest = portage.db["/"]["porttree"].dbapi.finddigest(mycat+"/"+mypkg + "-" + myversion) + + try: + myfile = open(mydigest,"r") + for line in myfile.readlines(): + mysum[0] += int(line.split(" ")[3]) + myfile.close() + mystr = str(mysum[0]/1024) + mycount=len(mystr) + while (mycount > 3): + mycount-=3 + mystr=mystr[:mycount]+","+mystr[mycount:] + mysum[0]=mystr+" kB" + except SystemExit, e: + raise # Needed else can't exit + except Exception, e: + if edebug: + print "!!! Exception:",e + mysum[0]=" [no/bad digest]" + + if "--quiet" not in myopts: + print " ", darkgreen("Latest version available:"),myversion + print " ", self.getInstallationStatus(mycat+'/'+mypkg) + print " ", darkgreen("Size of downloaded files:"),mysum[0] + print " ", darkgreen("Homepage:")+" ",homepage + print " ", darkgreen("Description:"),desc + print " ", darkgreen("License:")+" ",license + print + print + # + # private interface + # + def getInstallationStatus(self,package): + installed_package = self.installcache.dep_bestmatch(package) + result = "" + version = self.getVersion(installed_package,search.VERSION_RELEASE) + if len(version) > 0: + result = darkgreen("Latest version installed:")+" "+version + else: + result = darkgreen("Latest version installed:")+" [ Not Installed ]" + 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 getlist(mode): + if mode=="system": + mylines=portage.settings.packages + elif mode=="world": + try: + myfile=open(portage.root+portage.WORLD_FILE,"r") + mylines=myfile.readlines() + myfile.close() + except OSError: + print "!!! Couldn't open "+pfile+"; exiting." + sys.exit(1) + except IOError: + #world file doesn't exist + mylines=[] + mynewlines=[] + for x in mylines: + myline=string.join(string.split(x)) + if not len(myline): + continue + elif myline[0]=="#": + continue + elif mode=="system": + if myline[0]!="*": + continue + myline=myline[1:] + mynewlines.append(myline.strip()) + return mynewlines + +def genericdict(mylist): + mynewdict={} + for x in mylist: + mynewdict[portage.dep_getkey(x)]=x + return mynewdict + +olddbapi=None +class depgraph: + + def __init__(self,myaction,myopts): + global olddbapi + self.pkgsettings = portage.config(clone=portage.settings) + if not self.pkgsettings["ARCH"]: + portage.writemsg(red("\a!!! ARCH is not set... Are you missing the /etc/make.profile symlink?\n")) + portage.writemsg(red("\a!!! Is the symlink correct? Is your portage tree complete?\n\n")) + sys.exit(9) + self.applied_useflags = {} + + self.missingbins=[] + self.myaction=myaction + self.digraph=portage.digraph() + self.orderedkeys=[] + self.outdatedpackages=[] + self.mydbapi={} + self.mydbapi["/"] = portage.fakedbapi() + if "empty" not in myparams: + for pkg in portage.db["/"]["vartree"].getallcpv(): + self.mydbapi["/"].cpv_inject(pkg) + if portage.root != "/": + self.mydbapi[portage.root] = portage.fakedbapi() + if "empty" not in myparams: + for pkg in portage.db[portage.root]["vartree"].getallcpv(): + self.mydbapi[portage.root].cpv_inject(pkg) + + if "--usepkg" in myopts: + portage.db["/"]["bintree"].populate(("--getbinpkg" in myopts), ("--getbinpkgonly" in myopts)) + + def create(self,mybigkey,myparent=None,addme=1,myuse=None): + """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)""" + #stuff to add: + #SLOT-aware emerge + #IUSE-aware emerge + #"no downgrade" emerge + #print "mybigkey:",mybigkey + + jbigkey=string.join(mybigkey) + if self.digraph.hasnode(jbigkey+" merge") or self.digraph.hasnode(jbigkey+" nomerge"): + #this conditional is needed to prevent infinite recursion on already-processed deps + return 1 + + update_spinner() + + mytype,myroot,mykey=mybigkey + # select the correct /var database that we'll be checking against + vardbapi=portage.db[myroot]["vartree"].dbapi + + if addme: + # if the package is already on the system, we add a "nomerge" + # directive, otherwise we add a "merge" directive. + if mytype=="blocks": + # we've encountered a "blocks" node. We will totally ignore this + # node and not add it to our digraph if it doesn't apply to us. + if "--buildpkgonly" not in myopts and myparent and (self.mydbapi[myroot].match(mykey) or vardbapi.match(mykey)): + mybigkey.append(myparent.split()[2]) + self.digraph.addnode(string.join(mybigkey),myparent) + return 1 + + if myuse == None: + self.pkgsettings.setcpv(mykey) + myuse=string.split(self.pkgsettings["USE"], " ") + + self.applied_useflags[mykey] = myuse + + merging=1 + if addme: + # this is where we add the node to the list of packages to merge + if not myparent: + # command-line specified or part of a world list... + if ("self" not in myparams) or (("selective" in myparams) and vardbapi.cpv_exists(mykey)): + # the package is on the system, so don't merge it. + merging=0 + elif ("selective" in myparams) and vardbapi.cpv_exists(mykey): + merging=0 + + if (merging==0 and mytype=="ebuild" and "--newuse" in myopts and vardbapi.cpv_exists(mykey)): + iuses=string.split(portage.portdb.aux_get(mykey, ["IUSE"])[0]) + old_use=string.split(vardbapi.aux_get(mykey, ["USE"])[0]) + now_use=string.split(self.pkgsettings["USE"]) + for x in iuses: + if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)): + merging=1 + break + else: + #onlydeps mode; don't merge + merging=2 + if merging==1: + mybigkey.append("merge") + else: + mybigkey.append("nomerge") + + # whatever the case, we need to add the node to our digraph so + # that children can depend upon it. + self.digraph.addnode(string.join(mybigkey),myparent) + if ("deep" not in myparams) and (not merging): + return 1 + elif "recurse" not in myparams: + return 1 + + edepend={} + if mytype=="binary": + mypkgparts=portage.catpkgsplit(mykey) + tbz2name = string.split(mykey, "/")[1]+".tbz2" + if tbz2name in portage.db[portage.root]["bintree"].invalids: + sys.stderr.write("\nINVALID PACKAGE (is required to continue): "+str(mykey)+"\n") + sys.exit(1) + if portage.db[portage.root]["bintree"].isremote(mykey): + edepend = portage.db[portage.root]["bintree"].remotepkgs[tbz2name] + edepend["DEPEND"] ="" + edepend["RDEPEND"]=string.join(string.split(edepend["RDEPEND"])," ") + edepend["PDEPEND"]=string.join(string.split(edepend["PDEPEND"])," ") + edepend["CDEPEND"]=string.join(string.split(edepend["CDEPEND"])," ") + edepend["SLOT"] =string.strip(edepend["SLOT"]) + #portage.db[portage.root]["bintree"].gettbz2(mykey) + else: # It's local. + mytbz2=xpak.tbz2(portage.db[portage.root]["bintree"].getname(mykey)) + edepend["DEPEND"] ="" + edepend["RDEPEND"]=string.join(mytbz2.getelements("RDEPEND")," ") + edepend["PDEPEND"]=string.join(mytbz2.getelements("PDEPEND")," ") + edepend["CDEPEND"]=string.join(mytbz2.getelements("CDEPEND")," ") + edepend["SLOT"] =mytbz2.getfile("SLOT",mypkgparts[2]) + elif mytype=="ebuild": + try: + mymeta = ["DEPEND","RDEPEND","PDEPEND","CDEPEND"] + myfoo = portage.portdb.aux_get(mykey, mymeta) + for index in range(0,len(mymeta)): + edepend[mymeta[index]] = myfoo[index] + except (KeyError,IOError): + print "emerge: create(): aux_get() error on",mykey+"; aborting..." + sys.exit(1) + mydep={} + mp=string.join(mybigkey) + + if myroot=="/": + mydep["/"]=edepend["DEPEND"]+" "+edepend["RDEPEND"] + if not self.select_dep("/",mydep["/"],myparent=mp,myuse=myuse): + return 0 + else: + mydep["/"]=edepend["DEPEND"] + mydep[myroot]=edepend["RDEPEND"] + if not self.select_dep("/",mydep["/"],myparent=mp,myuse=myuse): + return 0 + if not self.select_dep(myroot,mydep[myroot],myparent=mp,myuse=myuse): + return 0 + + if edepend.has_key("PDEPEND") and edepend["PDEPEND"]: + # Post Depend -- Add to the list without a parent, as it depends + # on a package being present AND must be built after that package. + if not self.select_dep(myroot,edepend["PDEPEND"],myuse=myuse): + return 0 + + return 1 + + def select_files(self,myfiles): + "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list" + myfavorites=[] + for x in myfiles: + if x[-5:]==".tbz2": + if not os.path.exists(x): + if os.path.exists(self.pkgsettings["PKGDIR"]+"/All/"+x): + x=self.pkgsettings["PKGDIR"]+"/All/"+x + elif os.path.exists(self.pkgsettings["PKGDIR"]+"/"+x): + x=self.pkgsettings["PKGDIR"]+"/"+x + else: + print "\n\n!!! Binary package '"+str(x)+"' does not exist." + print "!!! Please ensure the tbz2 exists as specified.\n" + sys.exit(1) + mytbz2=xpak.tbz2(x) + mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.basename(x)[:-5] + if os.path.realpath(portage.db["/"]["bintree"].getname(mykey)) != os.path.realpath(x): + print red("\n*** You need to adjust PKGDIR to emerge this package.\n") + sys.exit(1) + if not self.create(["binary",portage.root,mykey],None,"--onlydeps" not in myopts): + return (0,myfavorites) + elif not "--oneshot" in myopts: + myfavorites.append(mykey) + elif x[-7:]==".ebuild": + x = os.path.realpath(x) + mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.basename(x)[:-7] + ebuild_path = portage.db["/"]["porttree"].dbapi.findname(mykey) + if ebuild_path: + if os.path.realpath(ebuild_path) != x: + print red("\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n") + sys.exit(1) + if mykey not in portage.db["/"]["porttree"].dbapi.xmatch("match-visible", portage.dep_getkey(mykey)): + print red("\n*** You are emerging a masked package. It is MUCH better to use") + print red("*** /etc/portage/package.* to accomplish this. See portage(5) man") + print red("*** page for details.") + countdown(EMERGE_WARNING_DELAY, "Continuing...") + else: + print red("\n*** "+x+" does not exist") + sys.exit(1) + if not self.create(["ebuild",portage.root,mykey],None,"--onlydeps" not in myopts): + return (0,myfavorites) + elif not "--oneshot" in myopts: + myfavorites.append(mykey) + else: + try: + mykey=portage.dep_expand(x,mydb=portage.portdb) + except ValueError, errpkgs: + print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify" + print "!!! one of the following fully-qualified ebuild names instead:\n" + for i in errpkgs[0]: + print " " + green(i) + print + sys.exit(1) + + # select needs to return 0 on dep_check failure + + sys.stdout.flush() + sys.stderr.flush() + + try: + self.mysd = self.select_dep(portage.root,mykey,arg=x) + except portage_exception.MissingSignature, e: + portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n") + portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n") + portage.writemsg("!!! to aid in the detection of malicious intent.\n\n") + portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF A TAMPERED FILES -- CHECK CAREFULLY.\n") + portage.writemsg("!!! Affected file: %s\n" % (e)) + sys.exit(1) + except portage_exception.InvalidSignature, e: + portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n") + portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n") + portage.writemsg("!!! to aid in the detection of malicious intent.\n\n") + portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF A TAMPERED FILES -- CHECK CAREFULLY.\n") + portage.writemsg("!!! Affected file: %s\n" % (e)) + sys.exit(1) + except SystemExit, e: + raise # Needed else can't exit + except Exception, e: + if "--debug" in myopts: + raise + print "\n\n!!! Problem in",mykey,"dependencies." + print "!!!",str(e),e.__module__ + sys.exit(1) + + if not self.mysd: + return (0,myfavorites) + elif not "--oneshot" in myopts: + myfavorites.append(mykey) + + missing=0 + if "--usepkgonly" in myopts: + for x in self.digraph.dict.keys(): + xs=string.split(x," ") + if (xs[0] != "binary") and (xs[3]=="merge"): + if missing == 0: + print + missing += 1 + print "Missing binary for:",xs[2] + + # We're true here unless we are missing binaries. + return (not missing,myfavorites) + + def is_newer_ver_installed(self,myroot,pkg,pkgver): + "if there is a version of pkg installed newer than pkgver, return it" + vardbapi=portage.db[myroot]["vartree"].dbapi + + matches=portage.db[myroot]["vartree"].dbapi.match(pkg) + if matches: + myslot=portage.db["/"]["porttree"].getslot(pkgver) + for match in matches: + if portage.pkgcmp(portage.catpkgsplit(pkgver)[1:], portage.catpkgsplit(match)[1:]) < 0: + curslot=portage.db[myroot]["vartree"].getslot(match) + if curslot == myslot: + return match + + def select_dep(self,myroot,depstring,myparent=None,arg=None,myuse=None): + "given a dependency string, create the appropriate depgraph and return 1 on success and 0 on failure" + if "--debug" in myopts: + print + print "Parent: ",myparent + print "Depstring:",depstring + if not arg: + #processing dependencies + mycheck=portage.dep_check(depstring,self.mydbapi[myroot],self.pkgsettings,myuse=myuse,use_binaries=("--usepkg" in myopts)) + #mycheck=portage.dep_check(depstring,self.mydbapi[myroot],self.pkgsettings,myuse=myuse) + + if not mycheck[0]: + mymerge=[] + else: + mymerge=mycheck[1] + + else: + #we're processing a command-line argument; unconditionally merge it even if it's already merged + mymerge=[depstring] + + # dep_check has been run so we can now add our parent to our + # build state to update virtuals and other settings. This + # happens after the package is added to the tree so that a + # package can depend on a virtual which it satisfies. + if myparent: + myp = myparent.split() + if myp[3]=="merge": + self.mydbapi[myroot].cpv_inject(myp[2]) + if myp[0]=="binary": + self.pkgsettings.setinst(myp[2],portage.db["/"]["bintree"].dbapi) + else: + self.pkgsettings.setinst(myp[2],portage.db[myroot]["porttree"].dbapi) + + if not mymerge: + return 1 + + if "--debug" in myopts: + print "Candidates:",mymerge + for x in mymerge: + myk=None + binpkguseflags=None + if x[0]=="!": + # if this package is myself, don't append it to block list. + if "--debug" in myopts: + print "Myparent",myparent + if (myparent): + if myparent.split()[2] in portage.portdb.xmatch("match-all", x[1:]): + # myself, so exit. + continue + # adding block + myk=["blocks",myroot,x[1:]] + else: + #We are not processing a blocker but a normal dependency + myeb=None + myeb_matches = portage.portdb.xmatch("match-visible",x) + if ("--usepkgonly" not in myopts): + myeb=portage.best(myeb_matches) + + myeb_pkg=None + if ("--usepkg" in myopts): + # The next line assumes the binarytree has been populated. + # XXX: Need to work out how we use the binary tree with roots. + myeb_pkg_matches=portage.db["/"]["bintree"].dbapi.match(x) + if ("--usepkgonly" not in myopts): + # Remove any binary package entries that are masked in the portage tree (#55871) + for idx in range(len(myeb_pkg_matches)-1,-1,-1): + if myeb_pkg_matches[idx] not in myeb_matches: + del myeb_pkg_matches[idx] + myeb_pkg = portage.best(myeb_pkg_matches) + + if not myeb_pkg: + myeb_pkg = None + elif ("--newuse" in myopts): + iuses=string.split(portage.db["/"]["bintree"].dbapi.aux_get(myeb_pkg, ["IUSE"])[0]) + old_use=string.split(portage.db["/"]["bintree"].dbapi.aux_get(myeb_pkg, ["USE"])[0]) + self.pkgsettings.setcpv(myeb_pkg) + now_use=string.split(self.pkgsettings["USE"]) + self.pkgsettings.reset() + for x in iuses: + if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)): + myeb_pkg = None + break + + if (not myeb) and (not myeb_pkg): + if not arg: + xinfo='"'+x+'"' + else: + xinfo='"'+arg+'"' + if myparent: + xfrom = '(dependency required by '+green('"'+myparent.split()[2]+'"')+red(' ['+myparent.split()[0]+"])") + alleb=portage.portdb.xmatch("match-all",x) + if alleb: + if "--usepkgonly" not in myopts: + print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.") + print "!!! One of the following masked packages is required to complete your request:" + oldcomment = "" + for p in alleb: + mreasons = portage.getmaskingstatus(p) + print "- "+p+" (masked by: "+string.join(mreasons, ", ")+")" + comment = portage.getmaskingreason(p) + if comment and comment != oldcomment: + print comment + oldcomment = comment + print + print "For more information, see MASKED PACKAGES section in the emerge man page or " + print "section 2.2 \"Software Availability\" in the Gentoo Handbook." + if myparent: + print "!!! "+red(xfrom) + print + else: + print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo) + print "!!! Either add a suitable binary package or compile from an ebuild." + else: + print "\nemerge: there are no ebuilds to satisfy "+xinfo+"." + print + return 0 + + if "--debug" in myopts: + print "ebuild:",myeb + print "binpkg:",myeb_pkg + + if myeb and myeb_pkg: + myeb_s = portage.catpkgsplit(myeb) + myeb_s = [myeb_s[0]+"/"+myeb_s[1], myeb_s[2], myeb_s[3]] + myeb_pkg_s = portage.catpkgsplit(myeb_pkg) + myeb_pkg_s = [myeb_pkg_s[0]+"/"+myeb_pkg_s[1], myeb_pkg_s[2], myeb_pkg_s[3]] + + if portage.pkgcmp(myeb_s, myeb_pkg_s) == 0: # pkg is same version as ebuild + myeb = None + 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: + myeb=cand + + if myeb: + myk=["ebuild",myroot,myeb] + elif myeb_pkg: + binpkguseflags=portage.db[portage.root]["bintree"].get_use(myeb_pkg) + myk=["binary",myroot,myeb_pkg] + else: + sys.stderr.write("!!! Confused... Don't know what I'm using for dependency info. :(\n") + sys.exit(1) + + #if "--usepkg" in myopts: + # #If we want to use packages, see if we have a pre-built one... + # mypk=portage.db["/"]["bintree"].dbapi.match(x) + # if myeb in mypk: + # #Use it only if it's exactly the version we want. + # myk=["binary",myroot,myeb] + # else: + # myk=["ebuild",myroot,myeb] + #else: + # myk=["ebuild",myroot,myeb] + if myparent: + #we are a dependency, so we want to be unconditionally added + if not self.create(myk,myparent,myuse=binpkguseflags): + return 0 + else: + #if mysource is not set, then we are a command-line dependency and should not be added + #if --onlydeps is specified. + if not self.create(myk,myparent,"--onlydeps" not in myopts,myuse=binpkguseflags): + return 0 + + if "--debug" in myopts: + print "Exiting...",myparent + return 1 + + + def altlist(self): + mygraph=self.digraph.copy() + dolist=["/"] + retlist=[] + for x in portage.db.keys(): + portage.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:" + print + for x in mygraph.dict.keys(): + for y in mygraph.dict[x][1]: + print y,"depends on",x + print + sys.exit(1) + splitski=string.split(mycurkey) + #I'm not sure of the significance of the following lines (vestigal?) so I'm commenting 'em out. + #These lines remove already-merged things from our alt-list + #if "--update" in myopts: + # if not portage.db["/"]["vartree"].exists_specific(splitski[2]): + # portage.db["/"]["merge"].append(splitski) + #else: + portage.db[splitski[1]]["merge"].append(splitski) + mygraph.delnode(mycurkey) + for x in dolist: + for y in portage.db[x]["merge"]: + retlist.append(y) + return retlist + + def xcreate(self,mode="system"): + global syslist + if mode=="system": + mylist=syslist + else: + #world mode + worldlist=getlist("world") + sysdict=genericdict(syslist) + worlddict=genericdict(worldlist) + #we're effectively upgrading sysdict to contain all new deps from worlddict + for x in worlddict.keys(): + #only add the world node if the package is: + #actually installed -- this prevents the remerging of already unmerged packages when we do a world --update; + #actually available -- this prevents emerge from bombing out due to no match being found (we want a silent ignore) + if "empty" in myparams: + if portage.db["/"]["vartree"].dbapi.match(x): + sysdict[x]=worlddict[x] + elif portage.db[portage.root]["vartree"].dbapi.match(x): + #package is installed + sysdict[x]=worlddict[x] + else: + print "\n*** Package in world file is not installed: "+x + mylist = sysdict.keys() + + for mydep in mylist: + myeb=portage.portdb.xmatch("bestmatch-visible",mydep) + if not myeb: + #this is an unavailable world entry; just continue + continue + + if "--upgradeonly" in myopts: + cand=self.is_newer_ver_installed(portage.root,mydep,myeb) + if cand: + myeb=cand + + #THIS NEXT BUNCH OF CODE NEEDS TO BE REPLACED TO SUPPORT WORLD ANTI-DEPS + #if mydep2[0]=="!":, etc. + binpkguseflags = None + if "--usepkg" in myopts: + mypk=portage.db[portage.root]["bintree"].dep_bestmatch(mydep) + if myeb==mypk: + myk=["binary",portage.root,mypk] + binpkguseflags=portage.db[portage.root]["bintree"].get_use(mypk) + if ("--newuse" in myopts): + iuses=string.split(portage.db["/"]["bintree"].dbapi.aux_get(mypk, ["IUSE"])[0]) + old_use=string.split(portage.db["/"]["bintree"].dbapi.aux_get(mypk, ["USE"])[0]) + self.pkgsettings.setcpv(mypk) + now_use=string.split(self.pkgsettings["USE"]) + self.pkgsettings.reset() + for x in iuses: + if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)): + myk=["ebuild",portage.root,myeb] + binpkguseflags=None + break + elif "--usepkgonly" in myopts: + if not mypk: + self.missingbins += [myeb] + myk=["binary",portage.root,myeb] + else: + myk=["binary",portage.root,mypk] + else: + myk=["ebuild",portage.root,myeb] + else: + myk=["ebuild",portage.root,myeb] + + if not self.create(myk,myuse=binpkguseflags): + print + print "!!! Problem with",myk[0],myk[2] + print "!!! Possibly a DEPEND/*DEPEND problem." + print + return 0 + return 1 + + def match(self,mydep,myroot=portage.root,mykey=None): + # support mutual exclusive deps + mydep2=mydep + if mydep2[0]=="!": + mydep2=mydep[1:] + + if mydep[0]=="!": + #add our blocker; it will be ignored later if necessary (if we are remerging the same pkg, for example) + myk="blocks "+myroot+" "+mydep2 + else: + myeb=portage.db[portage.root]["porttree"].dep_bestmatch(mydep2) + if not myeb: + if not mykey: + print "\n!!! Error: couldn't find match for",mydep + else: + print "\n!!! Error: couldn't find match for",mydep,"in",mykey + print + sys.exit(1) + + if "--usepkg" in myopts: + mypk=portage.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): + changelogs=[] + p=[] + totalsize=0 + + if "--verbose" in myopts: + overlays = string.split(portage.settings['PORTDIR_OVERLAY']) + + if "--tree" in myopts: + mylist.reverse() + mygraph=self.digraph.copy() + + i = 0 + while i < len(mylist): + if mylist[i][-1]=="nomerge": + if not ("--tree" in myopts): + # we don't care about this elements + mylist.pop(i) + continue + if (i == (len(mylist) - 1)) \ + or (mygraph.depth(string.join(mylist[i])) \ + >= mygraph.depth(string.join(mylist[i+1]))): + # end of a useless branch (may be the last one) + # -> delete the element and test the previous one + mylist.pop(i) + if i > 0: + i -= 1 + continue + # the branch continues, or we've found a good element. + # -> let's see what's next, if anything + i += 1 + + display_overlays=False + # files to fetch list - avoids counting a same file twice + # in size display (verbose mode) + myfetchlist=[] + for x in mylist: + fetch=" " + + if x[0]=="blocks": + addl=""+red("B")+" "+fetch+" " + resolved=portage.db[x[1]]["vartree"].resolve_key(x[2]) + print "["+x[0]+" "+addl+"]",red(resolved), + if resolved!=x[2]: + if x[3]: + print red("(\""+x[2]+"\" is blocking "+x[3]+")") + else: + print red("(\""+x[2]+"\")") + else: + if x[3]: + print red("(is blocking "+x[3]+")") + else: + print + else: + if (x[0]!="binary") and ("fetch" in string.split(portage.portdb.aux_get(x[2],["RESTRICT"])[0])): + fetch = red("F") + if portage.portdb.fetch_check(x[2], portage.settings): + fetch = green("f") + + #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty" + #param is used for -u, where you still *do* want to see when something is being upgraded. + myoldbest="" + if (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific(x[2]): + addl=" "+yellow("R")+fetch+" " + elif (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific_cat(x[2]): + if x[0] == "binary": + mynewslot=portage.db["/"]["bintree"].getslot(x[2]) + elif x[0] == "ebuild": + mynewslot=portage.db["/"]["porttree"].getslot(x[2]) + myoldlist=portage.db[x[1]]["vartree"].dbapi.match(portage.pkgsplit(x[2])[0]) + myinslotlist=filter((lambda p: portage.db[portage.root]["vartree"].getslot(p)==mynewslot),myoldlist) + if myinslotlist: + myoldbest=portage.best(myinslotlist) + addl=" "+fetch + if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0: + # Downgrade in slot + addl+=turquoise("U")+blue("D") + else: + # Update in slot + addl+=turquoise("U")+" " + else: + # New slot, mark it new. + addl=" "+green("NS")+fetch+" " + + if "--changelog" in myopts: + changelogs.extend(self.calc_changelog( + portage.portdb.findname(x[2]), + portage.db["/"]["vartree"].dep_bestmatch('/'.join(portage.catpkgsplit(x[2])[:2])), + x[2] + )) + else: + addl=" "+green("N")+" "+fetch+" " + + verboseadd="" + if "--verbose" in myopts: + # iuse verbose + try: + if x[0] == "binary": + iuse_split = string.split(portage.db["/"]["bintree"].dbapi.aux_get(x[2],["IUSE"])[0]) + elif x[0] == "ebuild": + iuse_split = string.split(portage.portdb.aux_get(x[2],["IUSE"])[0]) + else: + iuse_split = [] + except SystemExit, e: + raise # Needed else can't exit + except: + portage.writemsg("!!! Error getting IUSE (report this to bugs.gentoo.org)\n") + portage.writemsg("!!! %s\n" % x) + iuse_split = [] + iuse_split.sort() + old_use=None + if myoldbest: + pkg=myoldbest + else: + pkg=x[2] + if portage.db["/"]["vartree"].dbapi.cpv_exists(pkg): + try: + old_use=string.split(portage.db["/"]["vartree"].dbapi.aux_get(pkg, ["USE"])[0]) + except SystemExit, e: + raise # Needed else can't exit + except: + pass + iuse="" + now_use=self.applied_useflags[x[2]] + for ebuild_iuse in portage_util.unique_array(iuse_split): + usechange="" + if old_use: + if (old_use.count(ebuild_iuse) and not now_use.count(ebuild_iuse)) or (not old_use.count(ebuild_iuse) and now_use.count(ebuild_iuse)): + usechange="*" + + if ebuild_iuse in self.applied_useflags[x[2]]: + if usechange == "*": + iuse=green("+"+ebuild_iuse) + else: + iuse=red("+"+ebuild_iuse) + elif ebuild_iuse in portage.settings.usemask: + iuse=blue("(-"+ebuild_iuse+")") + else: + iuse=blue("-"+ebuild_iuse) + verboseadd+=iuse+usechange+" " + + # size verbose + mysize=0 + if x[0] == "ebuild" and x[-1]!="nomerge": + myfilesdict=portage.portdb.getfetchsizes(x[2], useflags=self.applied_useflags[x[2]], debug=edebug) + if myfilesdict==None: + myfilesdict="[empty/missing/bad digest]" + else: + for myfetchfile in myfilesdict.keys(): + if myfetchfile not in myfetchlist: + mysize+=myfilesdict[myfetchfile] + myfetchlist.append(myfetchfile) + totalsize+=mysize + verboseadd+=format_size(mysize)+" " + + # overlay verbose + # XXX: Invalid binaries have caused tracebacks here. 'if file_name' + # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge'] + file_name=portage.portdb.findname(x[2]) + if file_name: # It might not exist in the tree + dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..") + if (overlays.count(dir_name)>0): + verboseadd+=teal("["+str(overlays.index(os.path.normpath(dir_name))+1)+"]")+" " + display_overlays=True + else: + verboseadd += "[No ebuild?]" + + xs=portage.pkgsplit(x[2]) + if xs[2]=="r0": + xs[2]="" + else: + xs[2]="-"+xs[2] + + if self.pkgsettings.has_key("COLUMNWIDTH"): + mywidth=int(self.pkgsettings.settings["COLUMNWIDTH"]) + else: + mywidth=130 + oldlp=mywidth-30 + newlp=oldlp-30 + + indent="" + if ("--tree" in myopts): + indent=" "*mygraph.depth(string.join(x)) + + if myoldbest: + myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2] + if myoldbest[-3:]=="-r0": + myoldbest=myoldbest[:-3] + myoldbest=blue("["+myoldbest+"]") + + if x[1]!="/": + if "--columns" in myopts: + myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0]) + if (newlp-nc_len(myprint)) > 0: + myprint=myprint+(" "*(newlp-nc_len(myprint))) + myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] " + if (oldlp-nc_len(myprint)) > 0: + myprint=myprint+" "*(oldlp-nc_len(myprint)) + myprint=myprint+myoldbest + myprint=myprint+darkgreen(" to "+x[1])+" "+verboseadd + else: + myprint="["+x[0]+" "+addl+"] "+darkgreen(x[2])+" "+myoldbest+" "+darkgreen("to "+x[1])+" "+verboseadd + else: + if "--columns" in myopts: + myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0]) + if (newlp-nc_len(myprint)) > 0: + myprint=myprint+(" "*(newlp-nc_len(myprint))) + myprint=myprint+green(" ["+xs[1]+xs[2]+"] ") + if (oldlp-nc_len(myprint)) > 0: + myprint=myprint+(" "*(oldlp-nc_len(myprint))) + myprint=myprint+myoldbest+" "+verboseadd + else: + if x[3]=="nomerge": + myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd + else: + myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd + p.append(myprint) + + if ("--tree" not in myopts): + mysplit=portage.pkgsplit(x[2]) + + # XXX mysplit _can_ be None.... Why? + if mysplit and (len(mysplit)==3): + if "--emptytree" not in myopts: + if mysplit[0]=="sys-apps/portage": + if ((mysplit[1]+mysplit[2]) != portage.VERSION) and \ + ("livecvsportage" not in portage.settings.features): + if mylist.index(x)>> Recording",myfavkey,"in \"world\" favorites file..." + if not "--fetchonly" in myopts: + portage.writedict(myfavdict,portage.root+portage.WORLD_FILE,writekey=0) + + portage.mtimedb["resume"]["mergelist"]=mymergelist[:] + + # We need to yank the harmful-to-new-builds settings from features. + myorigfeat=self.pkgsettings["FEATURES"] + myfeat=myorigfeat.split() + while ("keeptemp" in myfeat): + del myfeat[myfeat.index("keeptemp")] + while ("keepwork" in myfeat): + del myfeat[myfeat.index("keepwork")] + + self.pkgsettings["FEATURES"]=string.join(myfeat) + + mergecount=0 + for x in mymergelist: + mergecount+=1 + myroot=x[1] + pkgindex=2 + if x[0]=="blocks": + pkgindex=3 + y=portage.portdb.findname(x[pkgindex]) + if not "--pretend" in myopts: + print ">>> emerge ("+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") + + #buildsyspkg: Check if we need to _force_ binary package creation + issyspkg = ("buildsyspkg" in myfeat) \ + and x[0] != "blocks" \ + and mysysdict.has_key(portage.cpv_getkey(x[2])) \ + and not ("--buildpkg" in myopts) + if x[0] in ["ebuild","blocks"]: + if (x[0]=="blocks") and ("--fetchonly" not in myopts): + raise Exception, "Merging a blocker" + elif ("--fetchonly" in myopts) or ("--fetch-all-uri" in myopts): + if ("--fetch-all-uri" in myopts): + retval=portage.doebuild(y,"fetch",myroot,self.pkgsettings,edebug,("--pretend" in myopts),fetchonly=1,fetchall=1) + else: + retval=portage.doebuild(y,"fetch",myroot,self.pkgsettings,edebug,("--pretend" in myopts),fetchonly=1) + if (retval == None) or retval: + print + print "!!! Fetch for",y,"failed, continuing..." + print + returnme=1 + continue + elif "--buildpkg" in myopts or issyspkg: + #buildsyspkg: Sounds useful to display something, but I don't know if we should also log it + if issyspkg: + print ">>> This is a system package, let's pack a rescue tarball." + #emergelog(">>> This is a system package, let's pack a rescue tarball.") + #create pkg, then merge pkg + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg) + retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1) + if (retval == None): + portage_util.writemsg("Unable to run required binary.\n") + sys.exit(127) + if retval: + sys.exit(retval) + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Compile" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Packaging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg) + retval=portage.doebuild(y,"package",myroot,self.pkgsettings,edebug) + if (retval == None): + portage_util.writemsg("Unable to run required binary.\n") + sys.exit(127) + if retval: + sys.exit(retval) + #dynamically update our database + if "--buildpkgonly" not in myopts: + portage.db[portage.root]["bintree"].inject(x[2]) + mytbz2=portage.db[portage.root]["bintree"].getname(x[2]) + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg) + + self.pkgsettings["EMERGE_FROM"] = "binary" + self.pkgsettings.backup_changes("EMERGE_FROM") + + retval=portage.pkgmerge(mytbz2,myroot,self.pkgsettings) + if retval==None: + sys.exit(1) + else: + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg) + retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1) + if (retval == None): + portage_util.writemsg("Unable to run required binary.\n") + sys.exit(127) + if retval: + sys.exit(retval) + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Compile" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Merging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg) + retval=portage.doebuild(y,"merge",myroot,self.pkgsettings,edebug) + if (retval == None): + portage_util.writemsg("Unable to run required binary.\n") + sys.exit(127) + if retval: + sys.exit(retval) + #dynamically update our database + elif x[0]=="binary": + #merge the tbz2 + mytbz2=portage.db[portage.root]["bintree"].getname(x[2]) + if portage.db[portage.root]["bintree"].isremote(x[2]): + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Fetch" + emergelog(" --- ("+str(mergecount)+" of "+str(len(mymergelist))+") Fetching Binary ("+x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg) + portage.db[portage.root]["bintree"].gettbz2(x[2]) + + if ("--fetchonly" in myopts) or ("--fetch-all-uri" in myopts): + continue + + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging Binary ("+x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg) + retval=portage.pkgmerge(mytbz2,x[1],self.pkgsettings) + if retval==None: + sys.exit(1) + #need to check for errors + if "--buildpkgonly" not in myopts: + portage.db[x[1]]["vartree"].inject(x[2]) + myfavkey=portage.cpv_getkey(x[2]) + if "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts and myfavkey in favorites: + myfavs=portage.grabfile(myroot+portage.WORLD_FILE) + myfavdict=genericdict(myfavs) + mysysdict=genericdict(syslist) + #don't record if already in system profile or already recorded + if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)): + #we don't have a favorites entry for this package yet; add one + myfavdict[myfavkey]=myfavkey + print ">>> Recording",myfavkey,"in \"world\" favorites file..." + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Updating world file ("+x[pkgindex]+")") + portage.writedict(myfavdict,myroot+portage.WORLD_FILE,writekey=0) + + if ("noclean" not in portage.features) and (x[0] != "binary"): + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean Post" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Post-Build Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg) + retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1) + if (retval == None): + portage_util.writemsg("Unable to run required binary.\n") + sys.exit(127) + if retval: + sys.exit(retval) + + if ("--pretend" not in myopts) and ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts): + # Clean the old package that we have merged over top of it. + if self.pkgsettings["AUTOCLEAN"]=="yes": + xsplit=portage.pkgsplit(x[2]) + emergelog(" >>> AUTOCLEAN: "+xsplit[0]) + retval=unmerge("clean", [xsplit[0]]) + if not retval: + emergelog(" --- AUTOCLEAN: Nothing unmerged.") + + # Figure out if we need a restart. + mysplit=portage.pkgsplit(x[2]) + if mysplit[0]=="sys-apps/portage": + myver=mysplit[1]+"-"+mysplit[2] + if myver[-3:]=='-r0': + myver=myver[:-3] + if (myver != portage.VERSION) and \ + ("livecvsportage" not in portage.settings.features): + if len(mymergelist) > mergecount: + myargv=sys.argv + myr=0 + for myra in range(len(myargv)): + if myargv[myr][0:len("portage")]=="portage": + del myargv[myr] + myr-=1 + if myargv[myr][0:len("sys-apps/portage")]=="sys-apps/portage": + del myargv[myr] + myr-=1 + myr+=1 + emergelog(" *** RESTARTING emerge via exec() after change of portage version.") + portage.portageexit() + # Remove --ask from options before restarting + mynewargv=[] + badlongopts = ["--ask","--tree","--changelog"] + badshortopts = ["a","t","l"] + for arg in myargv: + if arg[0:2] == "--": + if arg in badlongopts: + continue + mynewargv += [arg] + elif arg[0] == "-": + myarg = "-" + for ch in arg[1:]: + if ch in badshortopts: + continue + myarg += ch + mynewargv += [myarg] + else: + mynewargv += [arg] + os.execv("/usr/lib/portage/bin/emerge", mynewargv) + + if ("--pretend" not in myopts) and ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts): + emergelog(" ::: completed emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[2]+" to "+x[1]) + + # Unsafe for parallel merges + del portage.mtimedb["resume"]["mergelist"][0] + + emergelog(" *** Finished. Cleaning up...") + + # We're out of the loop... We're done. Delete the resume data. + if portage.mtimedb.has_key("resume"): + del portage.mtimedb["resume"] + + if ("--pretend" not in myopts): + if ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts): + if (mergecount>0): + if retval: + portage.env_update() + + #by doing an exit this way, --fetchonly can continue to try to + #fetch everything even if a particular download fails. + if "--fetchonly" in myopts or "--fetch-all-uri" in 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 unmerge(unmerge_action, unmerge_files): + candidate_catpkgs=[] + global_unmerge=0 + + realsyslist = getlist("system") + syslist = [] + for x in realsyslist: + mycp = portage.dep_getkey(x) + if mycp in portage.settings.virtuals: + syslist.extend(portage.settings.virtuals[mycp]) + syslist.append(mycp) + + global myopts + mysettings = portage.config(clone=portage.settings) + + if not unmerge_files or "world" in unmerge_files or "system" in unmerge_files: + if "unmerge"==unmerge_action: + print + print bold("emerge unmerge")+" can only be used with specific package names, not with "+bold("world")+" or" + print bold("system")+" targets." + print + return 0 + else: + global_unmerge=1 + + localtree=portage.db[portage.root]["vartree"] + # process all arguments and add all valid db entries to candidate_catpkgs + if global_unmerge: + if not unmerge_files or "world" in unmerge_files: + candidate_catpkgs.extend(localtree.getallnodes()) + elif "system" in unmerge_files: + candidate_catpkgs.extend(getlist("system")) + else: + #we've got command-line arguments + if not unmerge_files: + print "\nNo packages to unmerge have been provided.\n" + return 0 + for x in unmerge_files: + arg_parts=x.split('/') + if (x[0] not in [".","/"]) and (arg_parts[-1][-7:] != ".ebuild"): + #possible cat/pkg or dep; treat as such + candidate_catpkgs.append(x) + elif unmerge_action in ["prune","clean"]: + print "\n!!! Prune and clean do not accept individual ebuilds as arguments;\n skipping.\n" + continue + else: + # it appears that the user is specifying an installed ebuild and we're in "unmerge" mode, so it's + # ok. + if not os.path.exists(x): + print "\n!!! The path '"+x+"' doesn't exist.\n" + return 0 + + absx = os.path.abspath(x) + sp_absx = absx.split("/") + if sp_absx[-1][-7:] == ".ebuild": + del sp_absx[-1] + absx = string.join(sp_absx,"/") + + sp_absx_len = len(sp_absx) + + vdb_path = portage.root+portage.VDB_PATH + vdb_len = len(vdb_path) + + sp_vdb = vdb_path.split("/") + sp_vdb_len = len(sp_vdb) + + if not os.path.exists(absx+"/CONTENTS"): + print "!!! Not a valid db dir: "+str(absx) + return 0 + + if sp_absx_len <= sp_vdb_len: + # The Path is shorter... so it can't be inside the vdb. + print spabsx + print absx + print "\n!!!",x,"cannot be inside "+(portage.root+portage.VDB_PATH)+"; aborting.\n" + return 0 + + for idx in range(0,sp_vdb_len): + if (idx >= sp_absx_len) or (sp_vdb[idx] != sp_absx[idx]): + print sp_absx + print absx + print "\n!!!",x,"is not inside "+(portage.root+portage.VDB_PATH)+"; aborting.\n" + return 0 + + print "="+string.join(sp_absx[sp_vdb_len:],"/") + candidate_catpkgs.append("="+string.join(sp_absx[sp_vdb_len:],"/")) + + if ("--pretend" in myopts) or ("--ask" in myopts): + print darkgreen("\n>>> These are the packages that I would unmerge:") + + pkgmap={} + numselected=0 + for x in candidate_catpkgs: + #cycle through all our candidate deps and determine what will and will not get unmerged + try: + mymatch=localtree.dep_match(x) + except KeyError: + mymatch=None + except ValueError, errpkgs: + print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify" + print "!!! one of the following fully-qualified ebuild names instead:\n" + for i in errpkgs[0]: + print " " + green(i) + print + sys.exit(1) + + if not mymatch and x[0] not in "<>=~": + #add a "=" if missing + mymatch=localtree.dep_match("="+x) + if not mymatch: + print "\n--- Couldn't find " + white(x) + " to "+unmerge_action+"." + continue + mykey=portage.key_expand(portage.dep_getkey(mymatch[0]),portage.db["/"]["vartree"].dbapi) + if not pkgmap.has_key(mykey): + pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] } + if unmerge_action=="unmerge": + for y in mymatch: + if y not in pkgmap[mykey]["selected"]: + pkgmap[mykey]["selected"].append(y) + numselected=numselected+len(mymatch) + + else: + #unmerge_action in ["prune", clean"] + slotmap={} + for mypkg in mymatch: + if unmerge_action=="clean": + myslot=localtree.getslot(mypkg) + else: + #since we're pruning, we don't care about slots and put all the pkgs in together + myslot=0 + if not slotmap.has_key(myslot): + slotmap[myslot]={} + slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg + for myslot in slotmap.keys(): + counterkeys=slotmap[myslot].keys() + counterkeys.sort() + if not counterkeys: + continue + counterkeys.sort() + pkgmap[mykey]["protected"].append(slotmap[myslot][counterkeys[-1]]) + del counterkeys[-1] + #be pretty and get them in order of merge: + for ckey in counterkeys: + pkgmap[mykey]["selected"].append(slotmap[myslot][ckey]) + numselected=numselected+1 + #ok, now the last-merged package is protected, and the rest are selected + if global_unmerge and not numselected: + print "\n>>> No outdated packages were found on your system.\n" + return 0 + + if not numselected: + print "\n>>>",unmerge_action+": No packages selected for removal.\n" + return 0 + + for x in pkgmap.keys(): + for y in localtree.dep_match(x): + if y not in pkgmap[x]["omitted"] and \ + y not in pkgmap[x]["selected"] and \ + y not in pkgmap[x]["protected"]: + pkgmap[x]["omitted"].append(y) + if global_unmerge and not pkgmap[x]["selected"]: + #avoid cluttering the preview printout with stuff that isn't getting unmerged + continue + if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist): + print red("\a\n\n!!! '%s' is part of your system profile. '%s'" % (mykey)) + print yellow("\a!!! Unmerging it may be damaging to your system.\n") + if "--pretend" not in myopts and "--ask" not in myopts: + global EMERGE_WARNING_DELAY + countdown(EMERGE_WARNING_DELAY,red("Press Ctrl-C to Stop")) + print "\n "+white(x) + for mytype in ["selected","protected","omitted"]: + print string.rjust(mytype,12)+":", + if pkgmap[x][mytype]: + for mypkg in pkgmap[x][mytype]: + mysplit=portage.catpkgsplit(mypkg) + if mysplit[3]=="r0": + myversion=mysplit[2] + else: + myversion=mysplit[2]+"-"+mysplit[3] + if mytype=="selected": + print red(myversion), + else: + print green(myversion), + else: + print "none", + print + + print "\n>>>",red("'Selected'"),"packages are slated for removal." + print ">>>",green("'Protected'"),"and",green("'omitted'"),"packages will not be removed.\n" + + if "--pretend" in myopts: + #we're done... return + return 0 + if "--ask" in myopts: + if userquery("Do you want me to unmerge these packages?")=="No": + # enter pretend mode for correct formatting of results + myopts+=["--pretend"] + print + print "Quitting." + print + return 0 + #the real unmerging begins, after a short delay.... + + global CLEAN_DELAY + countdown(CLEAN_DELAY, ">>> Unmerging") + + for x in pkgmap.keys(): + for y in pkgmap[x]["selected"]: + print ">>> Unmerging "+y+"..." + emergelog("=== Unmerging... ("+y+")") + mysplit=string.split(y,"/") + #unmerge... + retval=portage.unmerge(mysplit[0],mysplit[1],portage.root,mysettings,unmerge_action not in ["clean","prune"]) + if retval: + emergelog(" !!! unmerge FAILURE: "+y) + else: + emergelog(" >>> unmerge success: "+y) + #run ldconfig, etc... + portage.env_update() + if not numselected: + return 0 + else: + return 1 + + +def chk_updated_info_files(retval): + root=portage.root + + infodirs=[] + infodirs.extend(string.split(portage.settings["INFOPATH"], ":")) + infodirs.extend(string.split(portage.settings["INFODIR"], ":")) + + print + if os.path.exists("/usr/bin/install-info"): + regen_infodirs=[] + for z in infodirs: + if z=='': + continue + inforoot=normpath(root+z) + if os.path.isdir(inforoot): + try: + infomtime=os.stat(inforoot)[ST_MTIME] + except SystemExit, e: + raise # Needed else can't exit + except: + infomtime=0 + + if not portage.mtimedb.has_key("info"): + portage.mtimedb["info"]={} + if portage.mtimedb["info"].has_key(inforoot): + if portage.mtimedb["info"][inforoot]==infomtime: + pass + else: + portage.mtimedb["info"][inforoot]=infomtime + regen_infodirs.append(inforoot) + else: + regen_infodirs.append(inforoot) + + if not regen_infodirs: + print " "+green("*")+" GNU info directory index is up-to-date." + else: + print " "+green("*")+" Regenerating GNU info directory index..." + + icount=0 + badcount=0 + for inforoot in regen_infodirs: + if inforoot=='': + continue + try: + os.rename(inforoot+"/dir",inforoot+"/dir.old") + except SystemExit, e: + raise # Needed else can't exit + except: + pass + + if not os.path.isdir(inforoot): + continue + errmsg = "" + for x in os.listdir(inforoot): + if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)): + continue + myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1] + existsstr="already exists, for file `" + if myso!="": + if re.search(existsstr,myso): + # Already exists... Don't increment the count for this. + pass + elif myso[:44]=="install-info: warning: no info dir entry in ": + # This info file doesn't contain a DIR-header: install-info produces this + # (harmless) warning (the --quiet switch doesn't seem to work). + # Don't increment the count for this. + pass + else: + badcount=badcount+1 + errmsg += myso + "\n" + icount=icount+1 + + #update mtime so we can potentially avoid regenerating. + portage.mtimedb["info"][inforoot]=os.stat(inforoot)[ST_MTIME] + + if badcount: + print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors." + print errmsg + else: + print " "+green("*")+" Processed",icount,"info files." + + +def post_emerge(retval=0): + global myopts + os.chdir("/") + if "--pretend" in myopts: + sys.exit(retval) + + emergelog(" *** exiting successfully.") + + if "noinfo" not in portage.settings.features: + chk_updated_info_files(retval) + + chk_updated_cfg_files() + sys.exit(retval) + + +def chk_updated_cfg_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 " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files." + print + +# general options that should be taken into account before any action +if "--debug" in myopts: + edebug=1 + +if myaction in ["sync","rsync","metadata"] and (not "--help" in myopts): + if "--pretend" in myopts: + print "emerge: \"sync\" actions do not support \"--pretend.\"" + sys.exit(1) + + emergelog(" === "+str(myaction)) + 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) + syncuri=string.rstrip(portage.settings["SYNC"]) + os.umask(0022) + if myaction == "metadata": + if "--ask" in myopts: + if userquery("Are you sure?") == "No": + sys.exit(1) + print "skipping sync" + updatecache_flg = True + tmpservertimestampfile = None + elif syncuri[:8]=="rsync://": + if not os.path.exists("/usr/bin/rsync"): + print "!!! /usr/bin/rsync does not exist, so rsync support is disabled." + print "!!! Type \"emerge net-misc/rsync\" to enable rsync support." + sys.exit(1) + mytimeout=180 + if portage.settings.has_key("RSYNC_TIMEOUT"): + try: + mytimeout=int(portage.settings["RSYNC_TIMEOUT"]) + except SystemExit, e: + raise # Needed else can't exit + except: + pass + + rsync_flags = [ + "--recursive", # Recurse directories + "--links", # Consider symlinks + "--safe-links", # Ignore links outside of tree + "--perms", # Preserve permissions + "--times", # Preserive mod times + "--compress", # Compress the data transmitted + "--force", # Force deletion on non-empty dirs + "--whole-file", # Don't do block transfers, only entire files + "--delete", # Delete files that aren't in the master tree + "--delete-after", # Delete only after everything else is done + "--stats", # Show final statistics about what was transfered + "--timeout="+str(mytimeout), # IO timeout if not done in X seconds + "--exclude='/distfiles'", # Exclude distfiles from consideration + "--exclude='/local'", # Exclude local from consideration + "--exclude='/packages'", # Exclude packages from consideration + ] + + if "--quiet" in myopts: + rsync_flags.append("--quiet") # Shut up a lot + else: + rsync_flags.append("--progress") # Progress meter for each file + + if "--verbose" in myopts: + rsync_flags.append("--verbose") # More noise? Not really sure what + + if "--debug" in myopts: + rsync_flags.append("--checksum") # Force checksum on all files + + if portage.settings.has_key("RSYNC_EXCLUDEFROM"): + if os.path.exists(portage.settings["RSYNC_EXCLUDEFROM"]): + rsync_flags.append("--exclude-from="+portage.settings["RSYNC_EXCLUDEFROM"]) + else: + print "!!! RSYNC_EXCLUDEFROM specified, but file does not exist." + + if portage.settings.has_key("RSYNC_RATELIMIT"): + rsync_flags.append("--bwlimit="+portage.settings["RSYNC_RATELIMIT"]) + + rsynccommand = "/usr/bin/rsync " + string.join(rsync_flags, " ") + + servertimestampdir = portage.settings.depcachedir+"/" + servertimestampfile = portage.settings.depcachedir+"/timestamp.chk" + tmpservertimestampdir = portage.settings["PORTAGE_TMPDIR"]+"/" + tmpservertimestampfile = portage.settings["PORTAGE_TMPDIR"]+"/timestamp.chk" + + # We only use the backup if a timestamp exists in the portdir. + content=None + if os.path.exists(myportdir+"/metadata/timestamp.chk"): + content=portage.grabfile(servertimestampfile) + if (not content): + content=portage.grabfile(myportdir+"/metadata/timestamp.chk") + + if (content): + try: + mytimestamp=time.mktime(time.strptime(content[0], "%a, %d %b %Y %H:%M:%S +0000")) + except ValueError: + mytimestamp=0 + else: + mytimestamp=0 + + if not os.path.exists(servertimestampdir): + os.mkdir(servertimestampdir) + os.chown(servertimestampdir, os.getuid(), portage.portage_gid) + os.chmod(servertimestampdir, 02775) + + #exitcode=0 + try: + maxretries=int(portage.settings["RSYNC_RETRIES"]) + except SystemExit, e: + raise # Needed else can't exit + except: + maxretries=3 #default number of retries + + retries=0 + hostname, port=re.split("rsync://([^:/]*)(:[0-9]+)?", syncuri)[1:3]; + if port==None: + port="" + updatecache_flg=True + + ips=[] + while (1): + if ips: + del ips[0] + if ips==[]: + try: + ips=socket.gethostbyname_ex(hostname)[2] + except SystemExit, e: + raise # Needed else can't exit + except Exception, e: + print "Notice:",str(e) + dosyncuri=syncuri + + if ips: + try: + dosyncuri=string.replace(syncuri, "//"+hostname+port+"/", "//"+ips[0]+port+"/", 1) + except SystemExit, e: + raise # Needed else can't exit + except Exception, e: + print "Notice:",str(e) + dosyncuri=syncuri + + if (retries==0): + if "--ask" in myopts: + if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No": + print + print "Quitting." + print + sys.exit(0) + emergelog(">>> starting rsync with "+dosyncuri) + if "--quiet" not in myopts: + print ">>> starting rsync with "+dosyncuri+"..." + else: + emergelog(">>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)) + print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri) + + if "--quiet" not in myopts: + print ">>> checking server timestamp ..." + mycommand=rsynccommand+" "+dosyncuri+"/metadata/timestamp.chk "+tmpservertimestampdir + exitcode=portage.spawn(mycommand,portage.settings,free=1) + if (exitcode==0): + try: + servertimestamp = time.mktime(time.strptime(portage.grabfile(tmpservertimestampfile)[0], "%a, %d %b %Y %H:%M:%S +0000")) + except SystemExit, e: + raise # Needed else can't exit + except: + servertimestamp = 0 + + if (servertimestamp != 0) and (servertimestamp == mytimestamp): + emergelog(">>> Cancelling sync -- Already current.") + print + print ">>>" + print ">>> Timestamps on the server and in the local repository are the same." + print ">>> Cancelling all further sync action. You are already up to date." + print ">>>" + print + sys.exit(0) + elif (servertimestamp != 0) and (servertimestamp < mytimestamp): + emergelog(">>> Server out of date: %s" % dosyncuri) + print + print ">>>" + print ">>> SERVER OUT OF DATE: %s" % dosyncuri + print ">>>" + print + elif (servertimestamp == 0) or (servertimestamp > mytimestamp): + # actual sync + mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir + exitcode=portage.spawn(mycommand,portage.settings,free=1) + if exitcode in [0,1,2,3,4,11,14,20,21]: + break + elif exitcode in [0,1,2,3,4,11,14,20,21]: + break + + retries=retries+1 + + if retries<=maxretries: + print ">>> retry ..." + time.sleep(11) + else: + # over retries + # exit loop + updatecache_flg=False + break + + if (exitcode==0): + emergelog("=== Sync completed with %s" % dosyncuri) + elif (exitcode>0): + print + if exitcode==1: + print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure") + print darkred("!!!")+green(" that your SYNC statement is proper.") + print darkred("!!!")+green(" SYNC="+portage.settings["SYNC"]) + elif exitcode==11: + print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally") + print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption") + print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate") + print darkred("!!!")+green(" and try again after the problem has been fixed.") + print darkred("!!!")+green(" PORTDIR="+portage.settings["PORTDIR"]) + elif exitcode==20: + print darkred("!!!")+green(" Rsync was killed before it finished.") + else: + print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep") + print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable") + print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a") + print darkred("!!!")+green(" temporary problem unless complications exist with your network") + print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.") + print + sys.exit(exitcode) + elif syncuri[:6]=="cvs://": + if not os.path.exists("/usr/bin/cvs"): + print "!!! /usr/bin/cvs does not exist, so rsync support is disabled." + print "!!! Type \"emerge dev-util/cvs\" to enable CVS support." + sys.exit(1) + cvsroot=syncuri[6:] + cvsdir=os.path.dirname(myportdir) + if not os.path.exists(myportdir+"/CVS"): + #initial checkout + print ">>> starting initial cvs checkout with "+syncuri+"..." + if not portage.spawn("cd "+cvsdir+"; cvs -d "+cvsroot+" login",portage.settings,free=1): + print "!!! cvs login error; exiting." + sys.exit(1) + if os.path.exists(cvsdir+"/gentoo-x86"): + print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting." + sys.exit(1) + if not portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",portage.settings,free=1): + print "!!! cvs checkout error; exiting." + sys.exit(1) + if cvsdir!=myportdir: + portage.movefile(cvsdir,portage.settings["PORTDIR"]) + sys.exit(0) + else: + #cvs update + print ">>> starting cvs update with "+syncuri+"..." + sys.exit(portage.spawn("cd "+myportdir+"; cvs -z0 -q update -dP",portage.settings,free=1)) + else: + print "!!! rsync setting: ",syncuri,"not recognized; exiting." + sys.exit(1) + + try: # Prevent users from affecting ebuild.sh. + os.close(sys.stdin.fileno()) + except SystemExit, e: + raise # Needed else can't exit + except: + pass + + if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg: + if "--quiet" not in myopts: + print "\n>>> Updating Portage cache: ", + os.umask(0002) + cachedir = os.path.normpath(portage.settings.depcachedir) + if cachedir in ["/", "/bin", "/dev", "/etc", "/home", + "/lib", "/opt", "/proc", "/root", "/sbin", + "/sys", "/tmp", "/usr", "/var"]: + print "!!! PORTAGE_CACHEDIR IS SET TO A PRIMARY ROOT DIRECTORY ON YOUR SYSTEM." + print "!!! This is ALMOST CERTAINLY NOT what you want: "+str(cachedir) + sys.exit(73) + if not os.path.exists(cachedir): + os.mkdir(cachedir) + + # Potentially bad + #if os.path.exists(cachedir+"/"+myportdir): + # portage.spawn("rm -Rf "+cachedir+"/"+myportdir+"/*",portage.settings,free=1) + + # save timestamp.chk for next timestamp check. + try: + if tmpservertimestampfile != None: + portage.movefile(tmpservertimestampfile, servertimestampfile) + except SystemExit, e: + raise # Needed else can't exit + except Exception, e: + print "!!! Failed to save current timestamp." + print "!!!",e + + portage.portdb.flush_cache() + + try: + os.umask(002) + os.chown(cachedir, os.getuid(), portage.portage_gid) + os.chmod(cachedir, 02775) + except SystemExit, e: + raise # Needed else can't exit + except: + pass + # we don't make overlay trees cache here, plus we don't trust portage.settings.categories + porttree_root = portage.portdb.porttree_root + pdb = portage.portdbapi(porttree_root, portage.config(config_profile_path=portage.settings.profile_path[:], \ + config_incrementals=portage.settings.incrementals[:])) + cp_list = pdb.cp_all() + if len(cp_list) == 0: + print "no metadata to transfer, exiting" + sys.exit(0) + cp_list.sort() + pcnt=0 + pcntstr="" + pcntcount=len(cp_list)/100.0 + nextupdate=pcntcount + current=1 + + def cleanse_cache(pdb, cat, saves, porttree_root=porttree_root): + if len(saves): + d={} + for v in saves: + d[portage.catsplit(v)[1]] = True + for pv in pdb.auxdb[porttree_root][cat].keys(): + if pv not in d: + pdb.auxdb[porttree_root][cat].del_key(pv) + else: + try: + pdb.auxdb[porttree_root][cat].clear() + del pdb.auxdb[porttree_root][cat] + except KeyError: + pass + + savelist = [] + catlist = [] + oldcat = portage.catsplit(cp_list[0])[0] + for cp in cp_list: + current += 1 + if current >= nextupdate: + pcnt += 1 + nextupdate += pcntcount + if "--quiet" not in myopts: + pcntstr = str(pcnt) + sys.stdout.write("\b"*(len(pcntstr)+1)+pcntstr+"%") + sys.stdout.flush() + cat = portage.catsplit(cp)[0] + if cat != oldcat: + catlist.append(oldcat) + cleanse_cache(pdb, oldcat, savelist) + savelist = [] + oldcat = cat + mymatches = pdb.xmatch("match-all", cp) + savelist.extend(mymatches) + for cpv in mymatches: + try: pdb.aux_get(cpv, ["IUSE"],metacachedir=myportdir+"/metadata/cache",debug=("cachedebug" in portage.features)) + except SystemExit: raise + except Exception, e: print "\nFailed cache update:",cpv,e + catlist.append(oldcat) + catlist.append("local") + cleanse_cache(pdb, oldcat, savelist) + filelist = portage.listdir(cachedir+"/"+myportdir) + for x in filelist: + found = False + for y in catlist: + if x.startswith(y): + found = True + break + if not found: + portage.spawn("cd /; rm -Rf "+cachedir+"/"+myportdir+"/"+x,portage.settings,free=1,droppriv=1) + + + sys.stdout.write("\n\n") + sys.stdout.flush() + + portage.portageexit() + reload(portage) + mybestpv=portage.portdb.xmatch("bestmatch-visible","sys-apps/portage") + mypvs=portage.best(portage.db[portage.root]["vartree"].dbapi.match("sys-apps/portage")) + + chk_updated_cfg_files() + + if(mybestpv != mypvs): + print + print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended" + print red(" * ")+"that you update portage now, before any other packages are updated." + print red(" * ")+"Please do so and then update "+bold("ALL")+" of your configuration files." + print +elif myaction=="regen": + emergelog(" === regen") + #regenerate cache entries + print "Regenerating cache entries... " + try: + os.close(sys.stdin.fileno()) + except SystemExit, e: + raise # Needed else can't exit + except: + pass + sys.stdout.flush() + mynodes=portage.portdb.cp_all() + for x in mynodes: + mymatches=portage.portdb.xmatch("match-all",x) + if not "--quiet" in myopts: + print "processing",x + for y in mymatches: + try: + foo=portage.portdb.aux_get(y,["DEPEND"],debug=1) + except SystemExit, e: + # sys.exit is an exception... And consequently, we can't catch it. + raise + except Exception, e: + print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)} + print "done!" +# HELP action +elif "config"==myaction: + if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles: + print red("!!! config can only take a single package atom at this time\n") + sys.exit(1) + + print + pkgs = portage.db[portage.root]["vartree"].dbapi.match(myfiles[0]) + if len(pkgs) == 0: + print "No packages found.\n" + sys.exit(0) + elif len(pkgs) > 1: + if "--ask" in myopts: + options = [] + print "Please select a package to configure:" + idx = 0 + for pkg in pkgs: + idx += 1 + options.append(str(idx)) + print options[-1]+") "+pkg + print "X) Cancel" + options.append("X") + idx = userquery("Selection?", options) + if idx == "X": + sys.exit(0) + pkg = pkgs[int(idx)-1] + else: + print "The following packages available:" + for pkg in pkgs: + print "* "+pkg + print "\nPlease use a specific atom or the --ask option." + sys.exit(1) + else: + pkg = pkgs[0] + + print + if "--ask" in myopts: + if userquery("Ready to configure "+pkg+"?") == "No": + sys.exit(0) + else: + print "Configuring pkg..." + print + ebuildpath = portage.db[portage.root]["vartree"].dbapi.findname(pkg) + mysettings = portage.config(clone=portage.settings) + portage.doebuild(ebuildpath,"config",portage.root,mysettings,debug=("--debug" in myopts),cleanup=True) + print + +# INFO action +elif "info"==myaction: + unameout=commands.getstatusoutput("uname -mrp")[1] + print getportageversion() + print "=================================================================" + print "System uname: "+unameout + if os.path.exists("/etc/gentoo-release"): + os.system("cat /etc/gentoo-release") + else: + print "Unknown Host Operating System" + + output=commands.getstatusoutput("distcc --version") + if not output[0]: + print str(string.split(output[1],"\n",1)[0]), + if "distcc" in portage.features: + print "[enabled]" + else: + print "[disabled]" + + output=commands.getstatusoutput("ccache -V") + if not output[0]: + print str(string.split(output[1],"\n",1)[0]), + if "ccache" in portage.features: + print "[enabled]" + else: + print "[disabled]" + + myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers", + "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"] + myvars += portage_util.grabfile(portage.settings["PORTDIR"]+"/profiles/info_pkgs") + myvars = portage_util.unique_array(myvars) + myvars.sort() + + for x in myvars: + if portage.isvalidatom(x): + pkg_matches = portage.db["/"]["vartree"].dbapi.match(x) + pkgs = [] + for y in pkg_matches: + mycpv = portage.catpkgsplit(y) + if(mycpv[3] != "r0"): + pkgs += [mycpv[2] + "-" + mycpv[3]] + else: + pkgs += [mycpv[2]] + if not pkgs: + pkgs = "[Not Present]" + else: + pkgs = ", ".join(sorted_versions(pkgs)) + print "%-20s %s" % (x+":", pkgs) + else: + print "%-20s %s" % (x+":", "[NOT VALID]") + + libtool_vers = string.join(portage.db["/"]["vartree"].dbapi.match("sys-devel/libtool"), ",") + + if "--verbose" in myopts: + myvars=portage.settings.keys() + else: + myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK', + 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR', + 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS', + 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES'] + + myvars.extend(portage_util.grabfile(portage.settings["PORTDIR"]+"/profiles/info_vars")) + + myvars = portage_util.unique_array(myvars) + unset_vars = [] + myvars.sort() + for x in myvars: + if portage.settings.has_key(x): + print x+'="'+portage.settings[x]+'"' + else: + unset_vars.append(x) + if unset_vars: + print "Unset: "+", ".join(unset_vars) + print + + if "--debug" in myopts: + for x in dir(portage): + module = getattr(portage, x) + if "cvs_id_string" in dir(module): + print "%s: %s" % (str(x), str(module.cvs_id_string)) + +# SEARCH action +elif "search"==myaction: + if not myfiles: + print "emerge: no search terms provided." + else: + searchinstance = search() + for mysearch in myfiles: + try: + searchinstance.execute(mysearch) + except re.error, comment: + 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() + +elif "depclean"==myaction: + # Kill packages that aren't explicitly merged or are required as a + # dependency of another package. World file is explicit. + + print + print red("*** WARNING ***")+" : DEPCLEAN CAN SERIOUSLY IMPAIR YOUR SYSTEM. USE CAUTION." + print red("*** WARNING ***")+" : (Cancel: CONTROL-C) -- ALWAYS VERIFY ALL PACKAGES IN THE" + print red("*** WARNING ***")+" : CANDIDATE LIST FOR SANITY BEFORE ALLOWING DEPCLEAN TO" + print red("*** WARNING ***")+" : UNMERGE ANY PACKAGES." + print red("*** WARNING ***")+" :" + print red("*** WARNING ***")+" : USE FLAGS MAY HAVE AN EXTREME EFFECT ON THE OUTPUT." + print red("*** WARNING ***")+" : SOME LIBRARIES MAY BE USED BY PACKAGES BUT ARE NOT" + print red("*** WARNING ***")+" : CONSIDERED TO BE A DEPEND DUE TO USE FLAG SETTINGS." + print red("*** WARNING ***")+" : emerge --update --deep --newuse world TO VERIFY" + print red("*** WARNING ***")+" : SANITY IN THIS REGARD." + print red("*** WARNING ***")+" :" + print red("*** WARNING ***")+" : Packages in the list that are desired may be added" + print red("*** WARNING ***")+" : directly to the world file to cause them to be ignored" + print red("*** WARNING ***")+" : by depclean and maintained in the future. BREAKAGES DUE" + print red("*** WARNING ***")+" : TO UNMERGING AN ==IN-USE LIBRARY== MAY BE REPAIRED BY" + print red("*** WARNING ***")+" : MERGING *** THE PACKAGE THAT COMPLAINS *** ABOUT THE" + print red("*** WARNING ***")+" : MISSING LIBRARY." + print + if ("--pretend" not in myopts) and ("--ask" not in myopts): + countdown(EMERGE_WARNING_DELAY, ">>> Depclean") + emergelog(" >>> depclean") + + mydepgraph=depgraph(myaction,myopts) + syslist=getlist("system") + worldlist=getlist("world") + + print "Calculating",myaction,"dependencies ", + if not mydepgraph.xcreate("world"): + print "\n!!! Failed to create deptree." + sys.exit(1) + print "\b\b ... done!" + + if ("--usepkgonly" in myopts) and mydepgraph.missingbins: + sys.stderr.write(red("The following binaries are not available for merging...\n")) + for x in mydepgraph.missingbins: + sys.stderr.write(" "+str(x)+"\n") + sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n") + sys.exit(1) + + alldeps=mydepgraph.digraph.allnodes() + myvarlist=portage.vardbapi(portage.root).cp_all() + + if not syslist: + print "!!! You have no system list. Cannot determine system from world." + if not worldlist: + print "!!! You have no world file. Cannot determine explicit merges." + if not myvarlist: + print "!!! You have no installed package tree (%s). This is a problem." % portage.VDB_PATH + if not alldeps: + print "!!! You have no dependencies. Impossible. Bug." + + if not (syslist and worldlist and myvarlist and alldeps): + print + sys.exit(1) + + reallist=[] + for x in alldeps: + myparts=portage.catpkgsplit(string.split(x)[2]) + if not myparts: + sys.stderr.write( + red("!!! There appears to be a problem with the following package:\n")+ + red("!!! "+str(string.split(x)[2])+"\n\n")+ + "!!! Please ensure that blocking/conflicting packages are not merged."+ + "!!! 'emerge -p "+str(string.split(x)[2])+"\n\n") + if ("--pretend" not in myopts) and ("--ask" not in myopts): + countdown(EMERGE_WARNING_DELAY, "*** Continuing") + continue + + catpack=myparts[0]+"/"+myparts[1] + if catpack not in reallist: + reallist.append(catpack) + + cleanlist=[] + for x in myvarlist: + if x not in reallist: + if x not in cleanlist: + cleanlist.append(x) + + for x in syslist+worldlist: + myparts = portage.catpkgsplit(x) + if myparts: + if myparts[0][0] in ('<','>','='): + myparts[0] = myparts[0][1:] + if myparts[0][0] in ('<','>','='): + myparts[0] = myparts[0][1:] + catpack=myparts[0]+"/"+myparts[1] + else: + catpack=x + if catpack in cleanlist: + cleanlist.remove(catpack) + + #print "\n\n\nCleaning: " + #for x in cleanlist: + # print x + #print + + if len(cleanlist): + unmerge("unmerge", cleanlist) + + print + print "Packages installed: "+str(len(myvarlist)) + print "Packages in world: "+str(len(worldlist)) + print "Packages in system: "+str(len(syslist)) + print "Unique package names: "+str(len(reallist)) + print "Required packages: "+str(len(alldeps)) + if "--pretend" in myopts: + print "Number to remove: "+str(len(cleanlist)) + else: + print "Number removed: "+str(len(cleanlist)) + post_emerge() + +# "update", "system", or just process files: +else: + favorites=[] + syslist=getlist("system") + if (("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts)) or ("--ask" in myopts): + if "--tree" in myopts: + print + print darkgreen("These are the packages that I would merge, in reverse order:") + print + else: + print + print darkgreen("These are the packages that I would merge, in order:") + print + + if ("--resume" in myopts) and portage.mtimedb.has_key("resume"): + myresumeopts=portage.mtimedb["resume"]["myopts"][:] + + while "--skipfirst" in myresumeopts: + myresumeopts.remove("--skipfirst") + while "--ask" in myresumeopts: + myresumeopts.remove("--ask") + + for myopt in myopts: + if myopt not in myresumeopts: + myresumeopts.append(myopt) + myopts=myresumeopts + mydepgraph=depgraph("resume",myopts) + if "--resume" not in myopts: + myopts+=["--resume"] + else: + if ("--resume" in myopts): + del myopts[myopts.index("--resume")] + print darkgreen("emerge: It seems we have nothing to resume...") + sys.exit(0) + + mydepgraph=depgraph(myaction,myopts) + if myaction in ["system","world"]: + print "Calculating",myaction,"dependencies ", + sys.stdout.flush() + if not mydepgraph.xcreate(myaction): + print "!!! Depgraph creation failed." + sys.exit(1) + print "\b\b ...done!" + else: + if not myfiles: + print "emerge: please tell me what to do." + help() + sys.exit(1) + #we don't have any files to process; skip this step and exit + print "Calculating dependencies ", + sys.stdout.flush() + retval,favorites=mydepgraph.select_files(myfiles) + if not retval: + sys.exit(1) + print "\b\b ...done!" + + if ("--usepkgonly" in myopts) and mydepgraph.missingbins: + sys.stderr.write(red("The following binaries are not available for merging...\n")) + + if mydepgraph.missingbins: + for x in mydepgraph.missingbins: + sys.stderr.write(" "+str(x)+"\n") + sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n") + sys.exit(1) + + if "--ask" in myopts: + if "--resume" in myopts: + mydepgraph.display(portage.mtimedb["resume"]["mergelist"]) + prompt="Do you want me to resume merging these packages?" + else: + mydepgraph.display(mydepgraph.altlist()) + mergecount=0 + for x in mydepgraph.altlist(): + if x[3]!="nomerge": + mergecount+=1 + #check for blocking dependencies + if x[0]=="blocks": + print "\n!!! Error: The above package list contains packages which cannot be installed" + print "!!! on the same system." + print + sys.exit(1) + if mergecount==0: + if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]: + prompt="Nothing to merge; do you want me to auto-clean packages?" + else: + print + print "Nothing to merge; quitting." + print + sys.exit(0) + elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts: + prompt="Do you want me to fetch the source files for these packages?" + else: + prompt="Do you want me to merge these packages?" + print + if userquery(prompt)=="No": + print + print "Quitting." + print + sys.exit(0) + # Don't ask again (e.g. when auto-cleaning packages after merge) + myopts.remove("--ask") + + if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts): + if ("--resume" in myopts): + mydepgraph.display(portage.mtimedb["resume"]["mergelist"]) + else: + mydepgraph.display(mydepgraph.altlist()) + else: + if ("--buildpkgonly" in myopts): + if not mydepgraph.digraph.hasallzeros(): + print "\n!!! --buildpkgonly requires all dependencies to be merged." + print "!!! Cannot merge requested packages. Merge deps and try again.\n" + sys.exit(1) + + if ("--resume" in myopts): + favorites=portage.mtimedb["resume"]["favorites"] + mydepgraph.merge(portage.mtimedb["resume"]["mergelist"]) + else: + portage.mtimedb["resume"]={} + portage.mtimedb["resume"]["myopts"]=myopts + portage.mtimedb["resume"]["favorites"]=favorites + if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts): + for pkgline in mydepgraph.altlist(): + if pkgline[0]=="ebuild" and pkgline[3]=="merge": + y=portage.portdb.findname(pkgline[2]) + tmpsettings = portage.config(clone=portage.settings) + retval=portage.doebuild(y,"digest",portage.root,tmpsettings,edebug,("--pretend" in myopts)) + mydepgraph.merge(mydepgraph.altlist()) + + if portage.mtimedb.has_key("resume"): + del portage.mtimedb["resume"] + if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]: + print ">>> Auto-cleaning packages ..." + unmerge("clean", ["world"]) + post_emerge() diff --git a/bin/emerge-webrsync b/bin/emerge-webrsync new file mode 100755 index 000000000..024af23e8 --- /dev/null +++ b/bin/emerge-webrsync @@ -0,0 +1,141 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/Attic/emerge-webrsync,v 1.8.2.4 2005/02/26 11:22:38 carpaski Exp $ +# Author: Karl Trygve Kalleberg +# Rewritten from the old, Perl-based emerge-webrsync script + +GENTOO_MIRRORS="${GENTOO_MIRRORS} $(/usr/lib/portage/bin/portageq gentoo_mirrors)" +PORTDIR="$(/usr/lib/portage/bin/portageq portdir)" +FETCHCOMMAND="$(/usr/lib/portage/bin/portageq envvar FETCHCOMMAND)" +USERLAND="$(/usr/lib/portage/bin/portageq envvar USERLAND)" +DISTDIR="$(/usr/lib/portage/bin/portageq envvar PORTAGE_TMPDIR)/emerge-webrsync" + +if [ ! -d $DISTDIR ] ; then + mkdir -p $DISTDIR +fi + +cd "$DISTDIR" + +found=0 +if [ "$1" == "-v" ] ; then + wgetops= +else + #this sucks. probably better to do 1> /dev/null + #that said, waiting on the refactoring. + if [ "${FETCHCOMMAND/wget}" != "${FETCHCOMMAND}" ]; then + wgetops="-q" + elif [ "${FETCHCOMMAND/curl}" != "${FETCHCOMMAND}" ]; then + wgetops="-s -f" + fi +fi + +if type -p md5sum > /dev/null; then + md5_com='md5sum -c "${FILE}.md5sum"' +elif type -p md5 > /dev/null; then + md5_com='[ "$(md5 -q ${FILE})" == "$(cut -d \ -f 1 ${FILE}.md5sum)" ]' +else + echo "warning, unable to do md5 verification of the snapshot!" + echo "no suitable md5/md5sum binary was found!" + md5_com='true' +fi + +sync_local() { + echo Syncing local tree... + if ! tar jxf $FILE; then + echo "Tar failed to extract the image. Please review the output." + echo "Executed command: tar jxf $FILE" + exit 1 + fi + rm -f $FILE + # Make sure user and group file ownership is root + chown -R 0:0 portage + cd portage + rsync -av --progress --stats --delete --delete-after \ + --exclude='/distfiles' --exclude='/packages' \ + --exclude='/local' . ${PORTDIR%%/} + cd .. + echo "cleaning up" + rm -rf portage + echo "transferring metadata/cache" + emerge metadata +} + +echo "Fetching most recent snapshot" + +declare -i attempts=-1 +while (( $attempts < 40 )) ; do + attempts=$(( attempts + 1 )) + + #this too, sucks. it works in the interim though. + if [ "$USERLAND" == "BSD" ] || [ "$USERLAND" == "Darwin" ] ; then + daysbefore=$(expr $(date +"%s") - 86400 \* $attempts) + day=$(date -r $daysbefore +"%d") + month=$(date -r $daysbefore +"%m") + year=$(date -r $daysbefore +"%Y") + else + day=$(date -d "-$attempts day" +"%d") + month=$(date -d "-$attempts day" +"%m") + year=$(date -d "-$attempts day" +"%Y") + fi + + FILE_ORIG="portage-${year}${month}${day}.tar.bz2" + + echo "Attempting to fetch file dated: ${year}${month}${day}" + + got_md5=0 + + if [ ! -e "${FILE_ORIG}.md5sum" ]; then + FILE="${FILE_ORIG}.md5sum" + for i in $GENTOO_MIRRORS ; do + URI="${i}/snapshots/${FILE}" + if (eval "$FETCHCOMMAND $wgetops") && [ -s "${FILE}" ]; then + got_md5=1 + break + fi + done + else + got_md5=1 + fi + FILE="${FILE_ORIG}" + + if (($got_md5 == 0 )); then + echo " --- No md5sum present on the mirror. (Not yet available.)" + continue + elif [ -s "${FILE}" ]; then + if eval "$md5_com"; then + echo " === snapshot $FILE is correct, using it" + sync_local + echo + echo " === Snapshot has beed sync'd" + echo + exit 0 + else + rm $FILE + fi + fi + + for i in $GENTOO_MIRRORS ; do + URI="${i}/snapshots/$FILE" + rm -f "$FILE" + if (eval "$FETCHCOMMAND $wgetops") && [ -s "$FILE" ]; then + if ! eval "$md5_com"; then + echo "md5 failed on $FILE" + rm ${FILE} + continue + else + sync_local + echo + echo " *** Completed websync, please now perform a normal rsync if possible." + echo " Update is current as of the of YYYYMMDD: ${year}${month}${day}" + echo + exit 0 + fi + fi + + done +done + +rm -rf portage + +exit 1 diff --git a/bin/emerge.orig b/bin/emerge.orig new file mode 100755 index 000000000..c66f32eae --- /dev/null +++ b/bin/emerge.orig @@ -0,0 +1,3227 @@ +#!/usr/bin/python -O +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/emerge,v 1.345.2.33 2005/06/02 00:57:52 vapier Exp $ + +import os,sys +os.environ["PORTAGE_CALLER"]="emerge" +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage + +import emergehelp,xpak,string,re,commands,time,shutil,traceback,atexit,signal,socket,types +from stat import * +from output import * + +import portage_util +import portage_locks +import portage_exception + + +spinner_msgs = ["Gentoo Rocks ("+os.uname()[0]+")", + "Thank you for using Gentoo. :)", + "Are you actually trying to read this?", + "How many times have you stared at this?", + "We are generating the cache right now", + "You are paying too much attention.", + "A theory is better than its explanation.", + "Phasers locked on target, Captain.", + "Thrashing is just virtual crashing.", + "To be is to program.", + "Real Users hate Real Programmers.", + "When all else fails, read the instructions.", + "Functionality breeds Contempt.", + "The future lies ahead.", + "3.1415926535897932384626433832795028841971694", + "Sometimes insanity is the only alternative.", + "Inaccuracy saves a world of explanation.", + ] + + +def update_basic_spinner(): + global spinner, spinpos + spinpos = (spinpos+1) % 500 + if (spinpos % 100) == 0: + if spinpos == 0: + sys.stdout.write(". ") + else: + sys.stdout.write(".") + sys.stdout.flush() + +def update_scroll_spinner(): + global spinner, spinpos + if(spinpos >= len(spinner)): + sys.stdout.write(darkgreen(" \b\b\b"+spinner[len(spinner)-1-(spinpos%len(spinner))])) + else: + sys.stdout.write(green("\b "+spinner[spinpos])) + sys.stdout.flush() + spinpos = (spinpos+1) % (2*len(spinner)) + +def update_twirl_spinner(): + global spinner, spinpos + spinpos = (spinpos+1) % len(spinner) + sys.stdout.write("\b\b "+spinner[spinpos]) + sys.stdout.flush() + +spinpos = 0 +spinner = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|" +update_spinner = update_twirl_spinner +if "candy" in portage.settings.features: + spinner = spinner_msgs[int(time.time()*100)%len(spinner_msgs)] + update_spinner = update_scroll_spinner +if not sys.stdout.isatty() or ("--nospinner" in sys.argv): + update_spinner = update_basic_spinner + + +if (not sys.stdout.isatty()) or (portage.settings["NOCOLOR"] in ["yes","true"]): + nocolor() + +def normpath(mystr): + if mystr and (mystr[0]=='/'): + return os.path.normpath("///"+mystr) + else: + return os.path.normpath(mystr) + +def userquery(prompt, responses=None, colours=None): + """Displays a prompt and a set of responses, then waits for a response + which is checked against the responses and the first to match is + returned. + + prompt: a String. + responses: a List of Strings. + colours: a List of Functions taking and returning a String, used to + process the responses for display. Typically these will be functions + like red() but could be e.g. lambda x: "DisplayString". + If responses is omitted, defaults to ["Yes, "No"], [green, red]. + If only colours is omitted, defaults to [bold, ...]. + + Returns a member of the List responses. (If called without optional + arguments, returns "Yes" or "No".) + KeyboardInterrupt is converted to SystemExit to avoid tracebacks being + printed.""" + if responses is None: + responses, colours = ["Yes", "No"], [green, red] + elif colours is None: + colours=[bold] + colours=(colours*len(responses))[:len(responses)] + print bold(prompt), + try: + while True: + response=raw_input("["+string.join([colours[i](responses[i]) for i in range(len(responses))],"/")+"] ") + for key in responses: + if response.upper()==key[:len(response)].upper(): + return key + print "Sorry, response '%s' not understood." % response, + except (EOFError, KeyboardInterrupt): + print "Interrupted." + sys.exit(1) + +def sorted_versions(verlist): + ret = [] + for ver in verlist: + verparts = ver.split("-") + if len(verparts) == 2: + verrev = int(verparts[1][1:]) + else: + verrev = 0 + x = 0 + while x < len(ret): + retparts = ret[x].split("-") + verdiff = portage.vercmp(retparts[0], verparts[0]) + if verdiff > 0: + break + elif verdiff == 0: + if len(retparts) == 2: + retrev = int(retparts[1][1:]) + else: + retrev = 0 + if retrev >= verrev: + break + x += 1 + ret.insert(x, ver) + return ret + +if portage.settings.has_key("PORTAGE_NICENESS"): + try: + os.nice(int(portage.settings["PORTAGE_NICENESS"])) + except SystemExit, e: + raise # Needed else can't exit + except Exception,e: + print "!!! Failed to change nice value to '"+str(portage.settings["PORTAGE_NICENESS"])+"'" + print "!!!",e + +#Freeze the portdbapi for enhanced performance: +portage.portdb.freeze() + +# Kill noauto as it will break merges otherwise. +while 'noauto' in portage.features: + del portage.features[portage.features.index('noauto')] + +#number of ebuilds merged +merged=0 +params=["selective", "deep", "self", "recurse", "empty"] +actions=[ +"clean", "config", "depclean", +"info", "inject", "metadata", +"prune", "regen", "rsync", "search", +"sync", "system", "unmerge", "world", +] +options=[ +"--ask", +"--buildpkg", "--buildpkgonly", +"--changelog", "--columns", +"--debug", "--deep", +"--digest", +"--emptytree", +"--fetchonly", "--fetch-all-uri", +"--getbinpkg", "--getbinpkgonly", +"--help", "--noconfmem", +"--newuse", "--nocolor", +"--nodeps", "--noreplace", +"--nospinner", "--oneshot", +"--onlydeps", "--pretend", +"--quiet", "--resume", +"--searchdesc", "--selective", +"--skipfirst", +"--tree", +"--update", "--upgradeonly", +"--usepkg", "--usepkgonly", +"--verbose", "--version" +] + +shortmapping={ +"1":"--oneshot", +"a":"--ask", +"b":"--buildpkg", "B":"--buildpkgonly", +"c":"--clean", "C":"--unmerge", +"d":"--debug", "D":"--deep", +"e":"--emptytree", +"f":"--fetchonly", "F":"--fetch-all-uri", +"g":"--getbinpkg", "G":"--getbinpkgonly", +"h":"--help", +"i":"--inject", +"k":"--usepkg", "K":"--usepkgonly", +"l":"--changelog", +"n":"--noreplace", "N":"--newuse", +"o":"--onlydeps", "O":"--nodeps", +"p":"--pretend", "P":"--prune", +"q":"--quiet", +"s":"--search", "S":"--searchdesc", +'t':"--tree", +"u":"--update", "U":"--upgradeonly", +"v":"--verbose", "V":"--version" +} + +myaction=None +myopts=[] +myfiles=[] +edebug=0 + +# process short actions +tmpcmdline=sys.argv[1:] +#tmpcmdline.extend(portage.settings["EMERGE_OPTS"].split()) +cmdline=[] +for x in tmpcmdline: + if x[0:1]=="-"and x[1:2]!="-": + for y in x[1:]: + if shortmapping.has_key(y): + if shortmapping[y] in cmdline: + print + print "*** Warning: Redundant use of",shortmapping[y] + else: + cmdline.append(shortmapping[y]) + else: + print "!!! Error: -"+y+" is an invalid short action or option." + sys.exit(1) + else: + cmdline.append(x) + +# process the options and command arguments +for x in cmdline: + if not x: + continue + if len(x)>=2 and x[0:2]=="--": + if x in options: + 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 + print + print red("!!!")+green(" Multiple actions requested... Please choose one only.") + print red("!!!")+" '"+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'" + print + sys.exit(1) + myaction=x[2:] + else: + print "!!! Error:",x,"is an invalid option." + 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 + if myaction: + print + print red("!!!")+green(" Multiple actions requested... Please choose one only.") + print red("!!! '")+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'" + print + sys.exit(1) + myaction=x + elif x[-1]=="/": + # this little conditional helps tab completion + myfiles.append(x[:-1]) + else: + myfiles.append(x) + + +if "moo" in myfiles: + print """ + + Gentoo (""" + os.uname()[0] + """) + + _______________________ +< Have you mooed today? > + ----------------------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || + +""" + +if (myaction in ["world", "system"]) and myfiles: + print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both." + sys.exit(1) + +for x in myfiles: + if (x[-7:] == ".ebuild" or x[-5:] == ".tbz2") and os.path.exists(os.path.abspath(x)): + print "emerging by path implies --oneshot... adding --oneshot to options." + print red("\n*** emerging by path is broken and may not always work!!!\n") + break + +if ("--tree" in myopts) and ("--columns" in myopts): + print "emerge: can't specify both of \"--tree\" and \"--columns\"." + sys.exit(1) + +# Always create packages if FEATURES=buildpkg +# Imply --buildpkg if --buildpkgonly +if ("buildpkg" in portage.features) or ("--buildpkgonly" in myopts): + if "--buildpkg" not in myopts: + myopts.append("--buildpkg") + +# --tree only makes sense with --pretend +if "--tree" in myopts and not (("--pretend" in myopts) or ("--ask" in myopts)): + print ">>> --tree implies --pretend... adding --pretend to options." + myopts.append("--pretend") + +# Also allow -S to invoke search action (-sS) +if ("--searchdesc" in myopts): + if myaction and myaction != "search": + myfiles.append(myaction) + if "--search" not in myopts: + myopts.append("--search") + myaction = "search" + +# Always try and fetch binary packages if FEATURES=getbinpkg +if ("getbinpkg" in portage.features): + myopts.append("--getbinpkg") + +if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts): + myopts.append("--usepkgonly") + +if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts): + myopts.append("--getbinpkg") + +if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts): + myopts.append("--usepkg") + +# Also allow -K to apply --usepkg/-k +if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts): + myopts.append("--usepkg") + +# 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." + myopts.append("--pretend") + +# Allow -p to remove --ask +if ("--pretend" in myopts) and ("--ask" in myopts): + print ">>> --pretend disables --ask... removing --ask from options." + myopts.remove("--ask") + +# forbid --ask when not in a terminal +# note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway. +if ("--ask" in myopts) and (not sys.stdin.isatty()): + portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n") + sys.exit(1) + +# Set so that configs will be merged regardless of remembered status +if ("--noconfmem" in myopts): + portage.settings.unlock() + portage.settings["NOCONFMEM"]="1" + portage.settings.backup_changes("NOCONFMEM") + portage.settings.lock() + +# Set various debug markers... They should be merged somehow. +if ("--debug" in myopts): + portage.settings.unlock() + portage.settings["PORTAGE_DEBUG"]="1" + portage.settings.backup_changes("PORTAGE_DEBUG") + portage.debug=1 + portage.settings.lock() + +if ("--resume" in myopts): + if "--verbose" in myopts: + print "* --verbose is currently broken with --resume. Disabling..." + myopts.remove("--verbose") + if "--tree" in myopts: + print "* --tree is currently broken with --resume. Disabling..." + myopts.remove("--tree") + +# Set color output +if ("--nocolor" in myopts) and (sys.stdout.isatty()): + nocolor() + +CLEAN_DELAY = 5 +EMERGE_WARNING_DELAY = 10 +if portage.settings["CLEAN_DELAY"]: + CLEAN_DELAY = string.atoi("0"+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: + xtermTitle(short_msg) + else: + xtermTitle(mystr) + try: + #seems odd opening a file each write... + if not os.path.exists("/var/log/emerge.log"): + mylogfile=open("/var/log/emerge.log", "w") + os.chmod("/var/log/emerge.log", S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) + os.chown("/var/log/emerge.log", portage.portage_uid, portage.portage_gid) + else: + mylogfile=open("/var/log/emerge.log", "a") + + l=portage_locks.lockfile(mylogfile) + # seek because we may have gotten held up by the lock. + # if so, we may not be positioned at the end of the file. + mylogfile.seek(0,2) + mylogfile.write(str(time.time())[:10]+": "+mystr+"\n") + mylogfile.flush() + portage_locks.unlockfile(l) + mylogfile.close() + except SystemExit, e: + raise # Needed else can't exit + except Exception, e: + if edebug: + print "emergelog():",e + pass + +def emergeexit(): + """This gets out final log message in before we quit.""" + if "--pretend" not in myopts: + emergelog(" *** terminating.") + if "notitles" not in portage.features: + xtermTitleReset() +atexit.register(emergeexit) + +def emergeexitsig(signum, frame): + signal.signal(signal.SIGINT, signal.SIG_IGN) + portage.portageexit() + portage_util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum}) + sys.exit(100+signum) +signal.signal(signal.SIGINT, emergeexitsig) + +def countdown(secs=5, doing="Starting"): + if secs: + print ">>> Waiting",secs,"seconds before starting..." + print ">>> (Control-C to abort)...\n"+doing+" in: ", + ticks=range(secs) + ticks.reverse() + for sec in ticks: + sys.stdout.write(red(str(sec+1)+" ")) + sys.stdout.flush() + time.sleep(1) + print + +# formats a size given in bytes nicely +def format_size(mysize): + if type(mysize) not in [types.IntType,types.LongType]: + return str(mysize) + mystr=str(mysize/1024) + mycount=len(mystr) + while (mycount > 3): + mycount-=3 + mystr=mystr[:mycount]+","+mystr[mycount:] + return mystr+" kB" + + +def getgccversion(): + """ + rtype: C{str} + return: the current in-use gcc version + """ + + gcc_env_dir = os.path.join('/', 'etc', 'env.d', 'gcc') + gcc_config_config = os.path.join(gcc_env_dir, 'config') + gcc_ver_command = 'gcc -dumpversion' + gcc_ver_prefix = 'gcc-' + + gcc_not_found_error = red( + "!!! No gcc found. You probably need to 'source /etc/profile'\n" + + "!!! to update the environment of this terminal and possibly\n" + + "!!! other terminals also." + ) + + gcc_distcc_broken_error = green( + '!!! Relying on the shell to locate gcc, this may break\n' + + '!!! DISTCC, installing gcc-config and setting your current gcc\n' + + '!!! profile will fix this' + ) + + def fallback(): + + print >>sys.stderr, gcc_distcc_broken_error + + gccout = commands.getstatusoutput(gcc_ver_command) + + if gccout[0] != 0: + print >>sys.stderr, gcc_not_found_error + gccver = "[unavailable]" + else: + gccver = gcc_ver_prefix + gccout[1] + + return gccver + + if os.path.isfile(gcc_config_config): + try: + gccver_str = open(gcc_config_config).read().strip() + gccver = gcc_ver_prefix + string.join(gccver_str.split('-')[4:], '-') + except IndexError: + gccver = fallback() + + else: + import glob + dir_l = glob.glob(os.path.join(gcc_env_dir, '*-*')) + + if len(dir_l) == 1: + try: + gccver = gcc_ver_prefix + dir_l[0].split('-')[-1] + except IndexError: + gccver = fallback() + + else: + # There was no "config" file in /etc/env.d/gcc and there was more + # than one profile in /etc/env.d/gcc so we can't actively + # determine what version of gcc we are using so we fall back on the + # old way that breaks distcc + + gccver = fallback() + + return gccver + +def getportageversion(): + try: + import re + profilever = os.path.normpath("///"+os.readlink("/etc/make.profile")) + basepath = os.path.normpath("///"+portage.settings["PORTDIR"]+"/profiles") + if re.match(basepath,profilever): + profilever = profilever[len(basepath)+1:] + else: + profilever = "!"+profilever + del basepath + except SystemExit, e: + raise # Needed else can't exit + except: + profilever="unavailable" + libcver=[] + libclist = portage.vardbapi(portage.root).match("virtual/libc") + libclist += portage.vardbapi(portage.root).match("virtual/glibc") + libclist = portage_util.unique_array(libclist) + for x in libclist: + xs=portage.catpkgsplit(x) + if libcver: + libcver+=","+string.join(xs[1:], "-") + else: + libcver=string.join(xs[1:], "-") + if libcver==[]: + libcver="unavailable" + + gccver = getgccversion() + unameout=os.uname()[2]+" "+os.uname()[4] + + return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")" + +def help(): + # Move all the help stuff out of this file. + emergehelp.help(myaction,myopts,havecolor) + +# check if root user is the current user for the actions where emerge needs this +if ("--pretend" in myopts) or ("--fetchonly" in myopts or "--fetch-all-uri" in myopts) or (myaction=="search"): + if not portage.secpass: + if portage.wheelgid==portage.portage_gid: + print "emerge: wheel group membership required for \"--pretend\" and search." + print "emerge: wheel group use is being deprecated. Please update group and passwd to" + print " include the portage user as noted above, and then use group portage." + else: + print "emerge: portage group membership required for \"--pretend\" and search." + sys.exit(1) +elif "--version" in myopts: + print getportageversion() + sys.exit(0) +elif "--help" in myopts: + help() + sys.exit(0) +elif portage.secpass!=2: + if myaction in ["search", "info", "regen"]: + pass + elif (not myaction) and (not myfiles): + pass + elif ("--pretend" in myopts) and (myaction in ["world","system","clean","prune","unmerge"]): + pass + else: + if "--debug" in myopts: + print "myaction",myaction + print "myopts",myopts + print "emerge: root access required." + sys.exit(1) + +if not "--pretend" in myopts: + emergelog("Started emerge on: "+time.strftime("%b %d, %Y %H:%M:%S", time.localtime())) + myelogstr="" + if myopts: + myelogstr=string.join(myopts, " ") + if myaction: + myelogstr+=" "+myaction + if myfiles: + myelogstr+=" "+string.join(myfiles, " ") + emergelog(" *** emerge "+myelogstr) + +#configure emerge engine parameters +# +# self: include _this_ package regardless of if it is merged. +# selective: exclude the package if it is merged +# recurse: go into the dependencies +# empty: pretend nothing is merged +myparams=["self","recurse"] +add=[] +sub=[] +if "--update" in myopts: + add.extend(["selective","empty"]) +if "--emptytree" in myopts: + add.extend(["empty"]) + sub.extend(["selective"]) +if "--nodeps" in myopts: + sub.extend(["recurse"]) +if "--noreplace" in myopts: + add.extend(["selective"]) +if "--deep" in myopts: + add.extend(["deep"]) +if "--selective" in myopts: + add.extend(["selective"]) +if myaction in ["world","system"]: + add.extend(["selective"]) +elif myaction in ["depclean"]: + add.extend(["empty"]) + sub.extend(["selective"]) +for x in add: + if (x not in myparams) and (x not in sub): + myparams.append(x) +for x in sub: + if x in myparams: + myparams.remove(x) + +# search functionality +class search: + + # + # class constants + # + VERSION_SHORT=1 + VERSION_RELEASE=2 + + # + # public interface + # + def __init__(self): + """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.installcache = portage.db["/"]["vartree"] + + def execute(self,searchkey): + """Performs the search for the supplied search key""" + global myopts + match_category = 0 + self.searchkey=searchkey + self.packagematches = [] + if "--searchdesc" in myopts: + self.searchdesc=1 + self.matches = {"pkg":[], "desc":[]} + else: + self.searchdesc=0 + self.matches = {"pkg":[]} + print "Searching... ", + + if self.searchkey[0] == '@': + match_category = 1 + self.searchkey = self.searchkey[1:] + if self.searchkey=="*": + #hack for people who aren't regular expression gurus + self.searchkey==".*" + if re.search("\+\+", self.searchkey): + #hack for people who aren't regular expression gurus + self.searchkey=re.sub("\+\+","\+\+",self.searchkey) + self.searchre=re.compile(self.searchkey.lower(),re.I) + for package in portage.portdb.cp_all(): + update_spinner() + + if match_category: + match_string = package[:] + else: + match_string = package.split("/")[-1] + + masked=0 + if self.searchre.search(match_string): + if not portage.portdb.xmatch("match-visible",package): + masked=1 + self.matches["pkg"].append([package,masked]) + elif self.searchdesc: # DESCRIPTION searching + full_package = portage.portdb.xmatch("bestmatch-visible",package) + if not full_package: + #no match found; we don't want to query description + full_package=portage.best(portage.portdb.xmatch("match-all",package)) + if not full_package: + continue + else: + masked=1 + try: + full_desc = portage.portdb.aux_get(full_package,["DESCRIPTION"])[0] + except KeyError: + print "emerge: search: aux_get() failed, skipping" + continue + if self.searchre.search(full_desc): + self.matches["desc"].append([full_package,masked]) + self.mlen=0 + for mtype in self.matches.keys(): + self.matches[mtype].sort() + self.mlen += len(self.matches[mtype]) + + def output(self): + """Outputs the results of the search.""" + print "\b\b \n[ Results for search key : "+white(self.searchkey)+" ]" + print "[ Applications found : "+white(str(self.mlen))+" ]" + print " " + for mtype in self.matches.keys(): + for match,masked in self.matches[mtype]: + if mtype=="pkg": + catpack=match + full_package = portage.portdb.xmatch("bestmatch-visible",match) + if not full_package: + #no match found; we don't want to query description + masked=1 + full_package=portage.best(portage.portdb.xmatch("match-all",match)) + else: + full_package = match + match = portage.pkgsplit(match)[0] + + if full_package: + try: + desc, homepage, license = portage.portdb.aux_get(full_package,["DESCRIPTION","HOMEPAGE","LICENSE"]) + except KeyError: + print "emerge: search: aux_get() failed, skipping" + continue + if masked: + print green("*")+" "+white(match)+" "+red("[ Masked ]") + else: + print green("*")+" "+white(match) + myversion = self.getVersion(full_package, search.VERSION_RELEASE) + + mysum = [0,0] + mycat = match.split("/")[0] + mypkg = match.split("/")[1] + + mydigest = portage.db["/"]["porttree"].dbapi.finddigest(mycat+"/"+mypkg + "-" + myversion) + + try: + myfile = open(mydigest,"r") + for line in myfile.readlines(): + mysum[0] += int(line.split(" ")[3]) + myfile.close() + mystr = str(mysum[0]/1024) + mycount=len(mystr) + while (mycount > 3): + mycount-=3 + mystr=mystr[:mycount]+","+mystr[mycount:] + mysum[0]=mystr+" kB" + except SystemExit, e: + raise # Needed else can't exit + except Exception, e: + if edebug: + print "!!! Exception:",e + mysum[0]=" [no/bad digest]" + + if "--quiet" not in myopts: + print " ", darkgreen("Latest version available:"),myversion + print " ", self.getInstallationStatus(mycat+'/'+mypkg) + print " ", darkgreen("Size of downloaded files:"),mysum[0] + print " ", darkgreen("Homepage:")+" ",homepage + print " ", darkgreen("Description:"),desc + print " ", darkgreen("License:")+" ",license + print + print + # + # private interface + # + def getInstallationStatus(self,package): + installed_package = self.installcache.dep_bestmatch(package) + result = "" + version = self.getVersion(installed_package,search.VERSION_RELEASE) + if len(version) > 0: + result = darkgreen("Latest version installed:")+" "+version + else: + result = darkgreen("Latest version installed:")+" [ Not Installed ]" + 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 getlist(mode): + if mode=="system": + mylines=portage.settings.packages + elif mode=="world": + try: + myfile=open(portage.root+portage.WORLD_FILE,"r") + mylines=myfile.readlines() + myfile.close() + except OSError: + print "!!! Couldn't open "+pfile+"; exiting." + sys.exit(1) + except IOError: + #world file doesn't exist + mylines=[] + mynewlines=[] + for x in mylines: + myline=string.join(string.split(x)) + if not len(myline): + continue + elif myline[0]=="#": + continue + elif mode=="system": + if myline[0]!="*": + continue + myline=myline[1:] + mynewlines.append(myline.strip()) + + # Remove everything that is package.provided from our list + for myatom in mynewlines[:]: + mykey = portage.dep_getkey(myatom) + if portage.settings.pprovideddict.has_key(mykey) and \ + portage.match_from_list(myatom, portage.settings.pprovideddict[mykey]): + mynewlines.remove(myatom) + + return mynewlines + +def genericdict(mylist): + mynewdict={} + for x in mylist: + mynewdict[portage.dep_getkey(x)]=x + return mynewdict + +olddbapi=None +class depgraph: + + def __init__(self,myaction,myopts): + global olddbapi + self.pkgsettings = portage.config(clone=portage.settings) + if not self.pkgsettings["ARCH"]: + portage.writemsg(red("\a!!! ARCH is not set... Are you missing the /etc/make.profile symlink?\n")) + portage.writemsg(red("\a!!! Is the symlink correct? Is your portage tree complete?\n\n")) + sys.exit(9) + self.applied_useflags = {} + + self.missingbins=[] + self.myaction=myaction + self.digraph=portage.digraph() + self.orderedkeys=[] + self.outdatedpackages=[] + self.mydbapi={} + self.mydbapi["/"] = portage.fakedbapi() + if "empty" not in myparams: + for pkg in portage.db["/"]["vartree"].getallcpv(): + self.mydbapi["/"].cpv_inject(pkg) + if portage.root != "/": + self.mydbapi[portage.root] = portage.fakedbapi() + if "empty" not in myparams: + for pkg in portage.db[portage.root]["vartree"].getallcpv(): + self.mydbapi[portage.root].cpv_inject(pkg) + + if "--usepkg" in myopts: + portage.db["/"]["bintree"].populate(("--getbinpkg" in myopts), ("--getbinpkgonly" in myopts)) + + def create(self,mybigkey,myparent=None,addme=1,myuse=None): + """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)""" + #stuff to add: + #SLOT-aware emerge + #IUSE-aware emerge + #"no downgrade" emerge + #print "mybigkey:",mybigkey + + jbigkey=string.join(mybigkey) + if self.digraph.hasnode(jbigkey+" merge") or self.digraph.hasnode(jbigkey+" nomerge"): + #this conditional is needed to prevent infinite recursion on already-processed deps + return 1 + + update_spinner() + + mytype,myroot,mykey=mybigkey + # select the correct /var database that we'll be checking against + vardbapi=portage.db[myroot]["vartree"].dbapi + + if addme: + # if the package is already on the system, we add a "nomerge" + # directive, otherwise we add a "merge" directive. + if mytype=="blocks": + # we've encountered a "blocks" node. We will totally ignore this + # node and not add it to our digraph if it doesn't apply to us. + if "--buildpkgonly" not in myopts and myparent and (self.mydbapi[myroot].match(mykey) or vardbapi.match(mykey)): + mybigkey.append(myparent.split()[2]) + self.digraph.addnode(string.join(mybigkey),myparent) + return 1 + + if myuse == None: + self.pkgsettings.setcpv(mykey) + myuse=string.split(self.pkgsettings["USE"], " ") + + self.applied_useflags[mykey] = myuse + + merging=1 + if addme: + # this is where we add the node to the list of packages to merge + if not myparent: + # command-line specified or part of a world list... + if ("self" not in myparams) or (("selective" in myparams) and vardbapi.cpv_exists(mykey)): + # the package is on the system, so don't merge it. + merging=0 + elif ("selective" in myparams) and vardbapi.cpv_exists(mykey): + merging=0 + + if (merging==0 and mytype=="ebuild" and "--newuse" in myopts and vardbapi.cpv_exists(mykey)): + iuses=string.split(portage.portdb.aux_get(mykey, ["IUSE"])[0]) + old_use=string.split(vardbapi.aux_get(mykey, ["USE"])[0]) + now_use=string.split(self.pkgsettings["USE"]) + for x in iuses: + if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)): + merging=1 + break + else: + #onlydeps mode; don't merge + merging=2 + if merging==1: + mybigkey.append("merge") + else: + mybigkey.append("nomerge") + + # whatever the case, we need to add the node to our digraph so + # that children can depend upon it. + self.digraph.addnode(string.join(mybigkey),myparent) + if ("deep" not in myparams) and (not merging): + return 1 + elif "recurse" not in myparams: + return 1 + + edepend={} + if mytype=="binary": + mypkgparts=portage.catpkgsplit(mykey) + tbz2name = string.split(mykey, "/")[1]+".tbz2" + if tbz2name in portage.db[portage.root]["bintree"].invalids: + sys.stderr.write("\nINVALID PACKAGE (is required to continue): "+str(mykey)+"\n") + sys.exit(1) + if portage.db[portage.root]["bintree"].isremote(mykey): + edepend = portage.db[portage.root]["bintree"].remotepkgs[tbz2name] + edepend["DEPEND"] ="" + edepend["RDEPEND"]=string.join(string.split(edepend["RDEPEND"])," ") + edepend["PDEPEND"]=string.join(string.split(edepend["PDEPEND"])," ") + edepend["SLOT"] =string.strip(edepend["SLOT"]) + #portage.db[portage.root]["bintree"].gettbz2(mykey) + else: # It's local. + mytbz2=xpak.tbz2(portage.db[portage.root]["bintree"].getname(mykey)) + edepend["DEPEND"] ="" + edepend["RDEPEND"]=string.join(mytbz2.getelements("RDEPEND")," ") + edepend["PDEPEND"]=string.join(mytbz2.getelements("PDEPEND")," ") + edepend["SLOT"] =mytbz2.getfile("SLOT",mypkgparts[2]) + elif mytype=="ebuild": + try: + mymeta = ["DEPEND","RDEPEND","PDEPEND"] + myfoo = portage.portdb.aux_get(mykey, mymeta) + for index in range(0,len(mymeta)): + edepend[mymeta[index]] = myfoo[index] + if "--buildpkgonly" in myopts: + edepend["RDEPEND"] = "" + except (KeyError,IOError): + print "emerge: create(): aux_get() error on",mykey+"; aborting..." + sys.exit(1) + mydep={} + mp=string.join(mybigkey) + + if myroot=="/": + mydep["/"]=edepend["DEPEND"]+" "+edepend["RDEPEND"] + if not self.select_dep("/",mydep["/"],myparent=mp,myuse=myuse): + return 0 + else: + mydep["/"]=edepend["DEPEND"] + mydep[myroot]=edepend["RDEPEND"] + if not self.select_dep("/",mydep["/"],myparent=mp,myuse=myuse): + return 0 + if not self.select_dep(myroot,mydep[myroot],myparent=mp,myuse=myuse): + return 0 + + if edepend.has_key("PDEPEND") and edepend["PDEPEND"]: + # Post Depend -- Add to the list without a parent, as it depends + # on a package being present AND must be built after that package. + if not self.select_dep(myroot,edepend["PDEPEND"],myuse=myuse): + return 0 + + return 1 + + def select_files(self,myfiles): + "given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list" + myfavorites=[] + for x in myfiles: + if x[-5:]==".tbz2": + if not os.path.exists(x): + if os.path.exists(self.pkgsettings["PKGDIR"]+"/All/"+x): + x=self.pkgsettings["PKGDIR"]+"/All/"+x + elif os.path.exists(self.pkgsettings["PKGDIR"]+"/"+x): + x=self.pkgsettings["PKGDIR"]+"/"+x + else: + print "\n\n!!! Binary package '"+str(x)+"' does not exist." + print "!!! Please ensure the tbz2 exists as specified.\n" + sys.exit(1) + mytbz2=xpak.tbz2(x) + mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.basename(x)[:-5] + if os.path.realpath(portage.db["/"]["bintree"].getname(mykey)) != os.path.realpath(x): + print red("\n*** You need to adjust PKGDIR to emerge this package.\n") + sys.exit(1) + if not self.create(["binary",portage.root,mykey],None,"--onlydeps" not in myopts): + return (0,myfavorites) + elif not "--oneshot" in myopts: + myfavorites.append(mykey) + elif x[-7:]==".ebuild": + x = os.path.realpath(x) + mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.basename(x)[:-7] + ebuild_path = portage.db["/"]["porttree"].dbapi.findname(mykey) + if ebuild_path: + if os.path.realpath(ebuild_path) != x: + print red("\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n") + sys.exit(1) + if mykey not in portage.db["/"]["porttree"].dbapi.xmatch("match-visible", portage.dep_getkey(mykey)): + print red("\n*** You are emerging a masked package. It is MUCH better to use") + print red("*** /etc/portage/package.* to accomplish this. See portage(5) man") + print red("*** page for details.") + countdown(EMERGE_WARNING_DELAY, "Continuing...") + else: + print red("\n*** "+x+" does not exist") + sys.exit(1) + if not self.create(["ebuild",portage.root,mykey],None,"--onlydeps" not in myopts): + return (0,myfavorites) + elif not "--oneshot" in myopts: + myfavorites.append(mykey) + else: + try: + mykey=portage.dep_expand(x,mydb=portage.portdb) + except ValueError, errpkgs: + print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify" + print "!!! one of the following fully-qualified ebuild names instead:\n" + for i in errpkgs[0]: + print " " + green(i) + print + sys.exit(1) + + # select needs to return 0 on dep_check failure + + sys.stdout.flush() + sys.stderr.flush() + + try: + self.mysd = self.select_dep(portage.root,mykey,arg=x) + except portage_exception.MissingSignature, e: + portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n") + portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n") + portage.writemsg("!!! to aid in the detection of malicious intent.\n\n") + portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF A TAMPERED FILES -- CHECK CAREFULLY.\n") + portage.writemsg("!!! Affected file: %s\n" % (e)) + sys.exit(1) + except portage_exception.InvalidSignature, e: + portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n") + portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n") + portage.writemsg("!!! to aid in the detection of malicious intent.\n\n") + portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF A TAMPERED FILES -- CHECK CAREFULLY.\n") + portage.writemsg("!!! Affected file: %s\n" % (e)) + sys.exit(1) + except SystemExit, e: + raise # Needed else can't exit + except Exception, e: + if "--debug" in myopts: + raise + print "\n\n!!! Problem in",mykey,"dependencies." + print "!!!",str(e),e.__module__ + sys.exit(1) + + if not self.mysd: + return (0,myfavorites) + elif not "--oneshot" in myopts: + myfavorites.append(mykey) + + missing=0 + if "--usepkgonly" in myopts: + for x in self.digraph.dict.keys(): + xs=string.split(x," ") + if (xs[0] != "binary") and (xs[3]=="merge"): + if missing == 0: + print + missing += 1 + print "Missing binary for:",xs[2] + + # We're true here unless we are missing binaries. + return (not missing,myfavorites) + + def is_newer_ver_installed(self,myroot,pkg,pkgver): + "if there is a version of pkg installed newer than pkgver, return it" + vardbapi=portage.db[myroot]["vartree"].dbapi + + matches=portage.db[myroot]["vartree"].dbapi.match(pkg) + if matches: + myslot=portage.db["/"]["porttree"].getslot(pkgver) + for match in matches: + if portage.pkgcmp(portage.catpkgsplit(pkgver)[1:], portage.catpkgsplit(match)[1:]) < 0: + curslot=portage.db[myroot]["vartree"].getslot(match) + if curslot == myslot: + return match + + def select_dep(self,myroot,depstring,myparent=None,arg=None,myuse=None): + "given a dependency string, create the appropriate depgraph and return 1 on success and 0 on failure" + if "--debug" in myopts: + print + print "Parent: ",myparent + print "Depstring:",depstring + if not arg: + #processing dependencies + mycheck=portage.dep_check(depstring,self.mydbapi[myroot],self.pkgsettings,myuse=myuse,use_binaries=("--usepkg" in myopts)) + #mycheck=portage.dep_check(depstring,self.mydbapi[myroot],self.pkgsettings,myuse=myuse) + + if not mycheck[0]: + mymerge=[] + else: + mymerge=mycheck[1] + + else: + #we're processing a command-line argument; unconditionally merge it even if it's already merged + mymerge=[depstring] + + # dep_check has been run so we can now add our parent to our + # build state to update virtuals and other settings. This + # happens after the package is added to the tree so that a + # package can depend on a virtual which it satisfies. + if myparent: + myp = myparent.split() + if myp[3]=="merge": + self.mydbapi[myroot].cpv_inject(myp[2]) + if myp[0]=="binary": + self.pkgsettings.setinst(myp[2],portage.db["/"]["bintree"].dbapi) + else: + self.pkgsettings.setinst(myp[2],portage.db[myroot]["porttree"].dbapi) + + if not mymerge: + return 1 + + if "--debug" in myopts: + print "Candidates:",mymerge + for x in mymerge: + myk=None + binpkguseflags=None + if x[0]=="!": + # if this package is myself, don't append it to block list. + if "--debug" in myopts: + print "Myparent",myparent + if (myparent): + if myparent.split()[2] in portage.portdb.xmatch("match-all", x[1:]): + # myself, so exit. + continue + # adding block + myk=["blocks",myroot,x[1:]] + else: + #We are not processing a blocker but a normal dependency + myeb=None + myeb_matches = portage.portdb.xmatch("match-visible",x) + if ("--usepkgonly" not in myopts): + myeb=portage.best(myeb_matches) + + myeb_pkg=None + if ("--usepkg" in myopts): + # The next line assumes the binarytree has been populated. + # XXX: Need to work out how we use the binary tree with roots. + myeb_pkg_matches=portage.db["/"]["bintree"].dbapi.match(x) + if ("--usepkgonly" not in myopts): + # Remove any binary package entries that are masked in the portage tree (#55871) + for idx in range(len(myeb_pkg_matches)-1,-1,-1): + if myeb_pkg_matches[idx] not in myeb_matches: + del myeb_pkg_matches[idx] + myeb_pkg = portage.best(myeb_pkg_matches) + + if not myeb_pkg: + myeb_pkg = None + elif ("--newuse" in myopts): + iuses=string.split(portage.db["/"]["bintree"].dbapi.aux_get(myeb_pkg, ["IUSE"])[0]) + old_use=string.split(portage.db["/"]["bintree"].dbapi.aux_get(myeb_pkg, ["USE"])[0]) + self.pkgsettings.setcpv(myeb_pkg) + now_use=string.split(self.pkgsettings["USE"]) + self.pkgsettings.reset() + for x in iuses: + if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)): + myeb_pkg = None + break + + if (not myeb) and (not myeb_pkg): + if not arg: + xinfo='"'+x+'"' + else: + xinfo='"'+arg+'"' + if myparent: + xfrom = '(dependency required by '+green('"'+myparent.split()[2]+'"')+red(' ['+myparent.split()[0]+"])") + alleb=portage.portdb.xmatch("match-all",x) + if alleb: + if "--usepkgonly" not in myopts: + print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.") + print "!!! One of the following masked packages is required to complete your request:" + oldcomment = "" + for p in alleb: + mreasons = portage.getmaskingstatus(p) + print "- "+p+" (masked by: "+string.join(mreasons, ", ")+")" + comment = portage.getmaskingreason(p) + if comment and comment != oldcomment: + print comment + oldcomment = comment + print + print "For more information, see MASKED PACKAGES section in the emerge man page or " + print "section 2.2 \"Software Availability\" in the Gentoo Handbook." + if myparent: + print "!!! "+red(xfrom) + print + else: + print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo) + print "!!! Either add a suitable binary package or compile from an ebuild." + else: + print "\nemerge: there are no ebuilds to satisfy "+xinfo+"." + if myparent: + print xfrom + print + return 0 + + if "--debug" in myopts: + print "ebuild:",myeb + print "binpkg:",myeb_pkg + + if myeb and myeb_pkg: + myeb_s = portage.catpkgsplit(myeb) + myeb_s = [myeb_s[0]+"/"+myeb_s[1], myeb_s[2], myeb_s[3]] + myeb_pkg_s = portage.catpkgsplit(myeb_pkg) + myeb_pkg_s = [myeb_pkg_s[0]+"/"+myeb_pkg_s[1], myeb_pkg_s[2], myeb_pkg_s[3]] + + if portage.pkgcmp(myeb_s, myeb_pkg_s) == 0: # pkg is same version as ebuild + myeb = None + 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: + myeb=cand + + if myeb: + myk=["ebuild",myroot,myeb] + elif myeb_pkg: + binpkguseflags=portage.db[portage.root]["bintree"].get_use(myeb_pkg) + myk=["binary",myroot,myeb_pkg] + else: + sys.stderr.write("!!! Confused... Don't know what I'm using for dependency info. :(\n") + sys.exit(1) + + #if "--usepkg" in myopts: + # #If we want to use packages, see if we have a pre-built one... + # mypk=portage.db["/"]["bintree"].dbapi.match(x) + # if myeb in mypk: + # #Use it only if it's exactly the version we want. + # myk=["binary",myroot,myeb] + # else: + # myk=["ebuild",myroot,myeb] + #else: + # myk=["ebuild",myroot,myeb] + if myparent: + #we are a dependency, so we want to be unconditionally added + if not self.create(myk,myparent,myuse=binpkguseflags): + return 0 + else: + #if mysource is not set, then we are a command-line dependency and should not be added + #if --onlydeps is specified. + if not self.create(myk,myparent,"--onlydeps" not in myopts,myuse=binpkguseflags): + return 0 + + if "--debug" in myopts: + print "Exiting...",myparent + return 1 + + + def altlist(self): + mygraph=self.digraph.copy() + dolist=["/"] + retlist=[] + for x in portage.db.keys(): + portage.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:" + print + for x in mygraph.dict.keys(): + for y in mygraph.dict[x][1]: + print y,"depends on",x + print + sys.exit(1) + splitski=string.split(mycurkey) + #I'm not sure of the significance of the following lines (vestigal?) so I'm commenting 'em out. + #These lines remove already-merged things from our alt-list + #if "--update" in myopts: + # if not portage.db["/"]["vartree"].exists_specific(splitski[2]): + # portage.db["/"]["merge"].append(splitski) + #else: + portage.db[splitski[1]]["merge"].append(splitski) + mygraph.delnode(mycurkey) + for x in dolist: + for y in portage.db[x]["merge"]: + retlist.append(y) + return retlist + + def xcreate(self,mode="system"): + global syslist + if mode=="system": + mylist=syslist + else: + #world mode + worldlist=getlist("world") + sysdict=genericdict(syslist) + worlddict=genericdict(worldlist) + #we're effectively upgrading sysdict to contain all new deps from worlddict + for x in worlddict.keys(): + #only add the world node if the package is: + #actually installed -- this prevents the remerging of already unmerged packages when we do a world --update; + #actually available -- this prevents emerge from bombing out due to no match being found (we want a silent ignore) + if "empty" in myparams: + if portage.db["/"]["vartree"].dbapi.match(x): + sysdict[x]=worlddict[x] + elif portage.db[portage.root]["vartree"].dbapi.match(x): + #package is installed + sysdict[x]=worlddict[x] + else: + print "\n*** Package in world file is not installed: "+x + mylist = sysdict.keys() + + for mydep in mylist: + myeb=portage.portdb.xmatch("bestmatch-visible",mydep) + if not myeb: + #this is an unavailable world entry; just continue + continue + + if "--upgradeonly" in myopts: + cand=self.is_newer_ver_installed(portage.root,mydep,myeb) + if cand: + myeb=cand + + #THIS NEXT BUNCH OF CODE NEEDS TO BE REPLACED TO SUPPORT WORLD ANTI-DEPS + #if mydep2[0]=="!":, etc. + binpkguseflags = None + if "--usepkg" in myopts: + mypk=portage.db[portage.root]["bintree"].dep_bestmatch(mydep) + if myeb==mypk: + myk=["binary",portage.root,mypk] + binpkguseflags=portage.db[portage.root]["bintree"].get_use(mypk) + if ("--newuse" in myopts): + iuses=string.split(portage.db["/"]["bintree"].dbapi.aux_get(mypk, ["IUSE"])[0]) + old_use=string.split(portage.db["/"]["bintree"].dbapi.aux_get(mypk, ["USE"])[0]) + self.pkgsettings.setcpv(mypk) + now_use=string.split(self.pkgsettings["USE"]) + self.pkgsettings.reset() + for x in iuses: + if (old_use.count(x) and not now_use.count(x)) or (not old_use.count(x) and now_use.count(x)): + myk=["ebuild",portage.root,myeb] + binpkguseflags=None + break + elif "--usepkgonly" in myopts: + if not mypk: + self.missingbins += [myeb] + myk=["binary",portage.root,myeb] + else: + myk=["binary",portage.root,mypk] + else: + myk=["ebuild",portage.root,myeb] + else: + myk=["ebuild",portage.root,myeb] + + if not self.create(myk,myuse=binpkguseflags): + print + print "!!! Problem with dependencies under ",myk[0],myk[2] + print "!!! Possibly a DEPEND/*DEPEND problem." + print + return 0 + return 1 + + def match(self,mydep,myroot=portage.root,mykey=None): + # support mutual exclusive deps + mydep2=mydep + if mydep2[0]=="!": + mydep2=mydep[1:] + + if mydep[0]=="!": + #add our blocker; it will be ignored later if necessary (if we are remerging the same pkg, for example) + myk="blocks "+myroot+" "+mydep2 + else: + myeb=portage.db[portage.root]["porttree"].dep_bestmatch(mydep2) + if not myeb: + if not mykey: + print "\n!!! Error: couldn't find match for",mydep + else: + print "\n!!! Error: couldn't find match for",mydep,"in",mykey + print + sys.exit(1) + + if "--usepkg" in myopts: + mypk=portage.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): + changelogs=[] + p=[] + totalsize=0 + + if "--verbose" in myopts: + overlays = string.split(portage.settings['PORTDIR_OVERLAY']) + + if "--tree" in myopts: + mylist.reverse() + mygraph=self.digraph.copy() + + i = 0 + while i < len(mylist): + if mylist[i][-1]=="nomerge": + if not ("--tree" in myopts): + # we don't care about this elements + mylist.pop(i) + continue + if (i == (len(mylist) - 1)) \ + or (mygraph.depth(string.join(mylist[i])) \ + >= mygraph.depth(string.join(mylist[i+1]))): + # end of a useless branch (may be the last one) + # -> delete the element and test the previous one + mylist.pop(i) + if i > 0: + i -= 1 + continue + # the branch continues, or we've found a good element. + # -> let's see what's next, if anything + i += 1 + + display_overlays=False + # files to fetch list - avoids counting a same file twice + # in size display (verbose mode) + myfetchlist=[] + for x in mylist: + fetch=" " + + if x[0]=="blocks": + addl=""+red("B")+" "+fetch+" " + resolved=portage.db[x[1]]["vartree"].resolve_key(x[2]) + print "["+x[0]+" "+addl+"]",red(resolved), + if resolved!=x[2]: + if x[3]: + print red("(\""+x[2]+"\" is blocking "+x[3]+")") + else: + print red("(\""+x[2]+"\")") + else: + if x[3]: + print red("(is blocking "+x[3]+")") + else: + print + else: + if (x[0]!="binary") and ("fetch" in string.split(portage.portdb.aux_get(x[2],["RESTRICT"])[0])): + fetch = red("F") + if portage.portdb.fetch_check(x[2], portage.settings): + fetch = green("f") + + #we need to use "--emptrytree" testing here rather than "empty" param testing because "empty" + #param is used for -u, where you still *do* want to see when something is being upgraded. + myoldbest="" + if (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific(x[2]): + addl=" "+yellow("R")+fetch+" " + elif (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific_cat(x[2]): + if x[0] == "binary": + mynewslot=portage.db["/"]["bintree"].getslot(x[2]) + elif x[0] == "ebuild": + mynewslot=portage.db["/"]["porttree"].getslot(x[2]) + myoldlist=portage.db[x[1]]["vartree"].dbapi.match(portage.pkgsplit(x[2])[0]) + myinslotlist=filter((lambda p: portage.db[portage.root]["vartree"].getslot(p)==mynewslot),myoldlist) + if myinslotlist: + myoldbest=portage.best(myinslotlist) + addl=" "+fetch + if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0: + # Downgrade in slot + addl+=turquoise("U")+blue("D") + else: + # Update in slot + addl+=turquoise("U")+" " + else: + # New slot, mark it new. + addl=" "+green("NS")+fetch+" " + + if "--changelog" in myopts: + changelogs.extend(self.calc_changelog( + portage.portdb.findname(x[2]), + portage.db["/"]["vartree"].dep_bestmatch('/'.join(portage.catpkgsplit(x[2])[:2])), + x[2] + )) + else: + addl=" "+green("N")+" "+fetch+" " + + verboseadd="" + if "--verbose" in myopts: + # iuse verbose + try: + if x[0] == "binary": + iuse_split = string.split(portage.db["/"]["bintree"].dbapi.aux_get(x[2],["IUSE"])[0]) + elif x[0] == "ebuild": + iuse_split = string.split(portage.portdb.aux_get(x[2],["IUSE"])[0]) + else: + iuse_split = [] + except SystemExit, e: + raise # Needed else can't exit + except: + portage.writemsg("!!! Error getting IUSE (report this to bugs.gentoo.org)\n") + portage.writemsg("!!! %s\n" % x) + iuse_split = [] + iuse_split.sort() + old_use=None + if myoldbest: + pkg=myoldbest + else: + pkg=x[2] + if portage.db["/"]["vartree"].dbapi.cpv_exists(pkg): + try: + old_use=string.split(portage.db["/"]["vartree"].dbapi.aux_get(pkg, ["USE"])[0]) + except SystemExit, e: + raise # Needed else can't exit + except: + pass + iuse="" + now_use=self.applied_useflags[x[2]] + for ebuild_iuse in portage_util.unique_array(iuse_split): + usechange="" + if old_use: + if (old_use.count(ebuild_iuse) and not now_use.count(ebuild_iuse)) or (not old_use.count(ebuild_iuse) and now_use.count(ebuild_iuse)): + usechange="*" + + if ebuild_iuse in self.applied_useflags[x[2]]: + if usechange == "*": + iuse=green("+"+ebuild_iuse) + else: + iuse=red("+"+ebuild_iuse) + elif ebuild_iuse in portage.settings.usemask: + iuse=blue("(-"+ebuild_iuse+")") + else: + iuse=blue("-"+ebuild_iuse) + verboseadd+=iuse+usechange+" " + + # size verbose + mysize=0 + if x[0] == "ebuild" and x[-1]!="nomerge": + myfilesdict=portage.portdb.getfetchsizes(x[2], useflags=self.applied_useflags[x[2]], debug=edebug) + if myfilesdict==None: + myfilesdict="[empty/missing/bad digest]" + else: + for myfetchfile in myfilesdict.keys(): + if myfetchfile not in myfetchlist: + mysize+=myfilesdict[myfetchfile] + myfetchlist.append(myfetchfile) + totalsize+=mysize + verboseadd+=format_size(mysize)+" " + + # overlay verbose + # XXX: Invalid binaries have caused tracebacks here. 'if file_name' + # x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge'] + file_name=portage.portdb.findname(x[2]) + if file_name: # It might not exist in the tree + dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..") + if (overlays.count(dir_name)>0): + verboseadd+=teal("["+str(overlays.index(os.path.normpath(dir_name))+1)+"]")+" " + display_overlays=True + else: + verboseadd += "[No ebuild?]" + + xs=portage.pkgsplit(x[2]) + if xs[2]=="r0": + xs[2]="" + else: + xs[2]="-"+xs[2] + + if self.pkgsettings.has_key("COLUMNWIDTH"): + mywidth=int(self.pkgsettings.settings["COLUMNWIDTH"]) + else: + mywidth=130 + oldlp=mywidth-30 + newlp=oldlp-30 + + indent="" + if ("--tree" in myopts): + indent=" "*mygraph.depth(string.join(x)) + + if myoldbest: + myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2] + if myoldbest[-3:]=="-r0": + myoldbest=myoldbest[:-3] + myoldbest=blue("["+myoldbest+"]") + + if x[1]!="/": + if "--columns" in myopts: + myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0]) + if (newlp-nc_len(myprint)) > 0: + myprint=myprint+(" "*(newlp-nc_len(myprint))) + myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] " + if (oldlp-nc_len(myprint)) > 0: + myprint=myprint+" "*(oldlp-nc_len(myprint)) + myprint=myprint+myoldbest + myprint=myprint+darkgreen(" to "+x[1])+" "+verboseadd + else: + myprint="["+x[0]+" "+addl+"] "+darkgreen(x[2])+" "+myoldbest+" "+darkgreen("to "+x[1])+" "+verboseadd + else: + if "--columns" in myopts: + myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0]) + if (newlp-nc_len(myprint)) > 0: + myprint=myprint+(" "*(newlp-nc_len(myprint))) + myprint=myprint+green(" ["+xs[1]+xs[2]+"] ") + if (oldlp-nc_len(myprint)) > 0: + myprint=myprint+(" "*(oldlp-nc_len(myprint))) + myprint=myprint+myoldbest+" "+verboseadd + else: + if x[3]=="nomerge": + myprint=darkblue("[nomerge ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd + else: + myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd + p.append(myprint) + + if ("--tree" not in myopts): + mysplit=portage.pkgsplit(x[2]) + + # XXX mysplit _can_ be None.... Why? + if mysplit and (len(mysplit)==3): + if "--emptytree" not in myopts: + if mysplit[0]=="sys-apps/portage": + if ((mysplit[1]+mysplit[2]) != portage.VERSION) and \ + ("livecvsportage" not in portage.settings.features): + if mylist.index(x)>> Recording",myfavkey,"in \"world\" favorites file..." + if not "--fetchonly" in myopts: + portage.writedict(myfavdict,portage.root+portage.WORLD_FILE,writekey=0) + + portage.mtimedb["resume"]["mergelist"]=mymergelist[:] + + # We need to yank the harmful-to-new-builds settings from features. + myorigfeat=self.pkgsettings["FEATURES"] + myfeat=myorigfeat.split() + while ("keeptemp" in myfeat): + del myfeat[myfeat.index("keeptemp")] + while ("keepwork" in myfeat): + del myfeat[myfeat.index("keepwork")] + + self.pkgsettings["FEATURES"]=string.join(myfeat) + + mergecount=0 + if "--fetchonly" in myopts: + mynewmergelist = [] + for x in mymergelist: + if x[0] != "blocks": + mynewmergelist.append(x) + mymergelist = mynewmergelist + for x in mymergelist: + mergecount+=1 + myroot=x[1] + pkgindex=2 + if x[0]=="blocks": + pkgindex=3 + y=portage.portdb.findname(x[pkgindex]) + if not "--pretend" in myopts: + print ">>> emerge ("+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") + + #buildsyspkg: Check if we need to _force_ binary package creation + issyspkg = ("buildsyspkg" in myfeat) \ + and x[0] != "blocks" \ + and mysysdict.has_key(portage.cpv_getkey(x[2])) \ + and not ("--buildpkg" in myopts) + if x[0] in ["ebuild","blocks"]: + if (x[0]=="blocks") and ("--fetchonly" not in myopts): + raise Exception, "Merging a blocker" + elif ("--fetchonly" in myopts) or ("--fetch-all-uri" in myopts): + if x[0] == "blocks": + continue + if ("--fetch-all-uri" in myopts): + retval=portage.doebuild(y,"fetch",myroot,self.pkgsettings,edebug,("--pretend" in myopts),fetchonly=1,fetchall=1) + else: + retval=portage.doebuild(y,"fetch",myroot,self.pkgsettings,edebug,("--pretend" in myopts),fetchonly=1) + if (retval == None) or retval: + print + print "!!! Fetch for",y,"failed, continuing..." + print + returnme=1 + continue + elif "--buildpkg" in myopts or issyspkg: + #buildsyspkg: Sounds useful to display something, but I don't know if we should also log it + if issyspkg: + print ">>> This is a system package, let's pack a rescue tarball." + #emergelog(">>> This is a system package, let's pack a rescue tarball.") + #create pkg, then merge pkg + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg) + retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1) + if (retval == None): + portage_util.writemsg("Unable to run required binary.\n") + sys.exit(127) + if retval: + sys.exit(retval) + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Compile" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Packaging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg) + retval=portage.doebuild(y,"package",myroot,self.pkgsettings,edebug) + if (retval == None): + portage_util.writemsg("Unable to run required binary.\n") + sys.exit(127) + if retval: + sys.exit(retval) + #dynamically update our database + if "--buildpkgonly" not in myopts: + portage.db[portage.root]["bintree"].inject(x[2]) + mytbz2=portage.db[portage.root]["bintree"].getname(x[2]) + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg) + + self.pkgsettings["EMERGE_FROM"] = "binary" + self.pkgsettings.backup_changes("EMERGE_FROM") + + retval=portage.pkgmerge(mytbz2,myroot,self.pkgsettings) + if retval==None: + sys.exit(1) + else: + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg) + retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1) + if (retval == None): + portage_util.writemsg("Unable to run required binary.\n") + sys.exit(127) + if retval: + sys.exit(retval) + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Compile" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Merging ("+x[pkgindex]+"::"+y+")", short_msg=short_msg) + retval=portage.doebuild(y,"merge",myroot,self.pkgsettings,edebug) + if (retval == None): + portage_util.writemsg("Unable to run required binary.\n") + sys.exit(127) + if retval: + sys.exit(retval) + #dynamically update our database + elif x[0]=="binary": + #merge the tbz2 + mytbz2=portage.db[portage.root]["bintree"].getname(x[2]) + if portage.db[portage.root]["bintree"].isremote(x[2]): + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Fetch" + emergelog(" --- ("+str(mergecount)+" of "+str(len(mymergelist))+") Fetching Binary ("+x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg) + portage.db[portage.root]["bintree"].gettbz2(x[2]) + + if ("--fetchonly" in myopts) or ("--fetch-all-uri" in myopts): + continue + + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging Binary ("+x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg) + retval=portage.pkgmerge(mytbz2,x[1],self.pkgsettings) + if retval==None: + sys.exit(1) + #need to check for errors + if "--buildpkgonly" not in myopts: + portage.db[x[1]]["vartree"].inject(x[2]) + myfavkey=portage.cpv_getkey(x[2]) + if "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts and myfavkey in favorites: + myfavs=portage.grabfile(myroot+portage.WORLD_FILE) + myfavdict=genericdict(myfavs) + mysysdict=genericdict(syslist) + #don't record if already in system profile or already recorded + if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)): + #we don't have a favorites entry for this package yet; add one + myfavdict[myfavkey]=myfavkey + print ">>> Recording",myfavkey,"in \"world\" favorites file..." + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Updating world file ("+x[pkgindex]+")") + portage.writedict(myfavdict,myroot+portage.WORLD_FILE,writekey=0) + + if ("noclean" not in portage.features) and (x[0] != "binary"): + short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Clean Post" + emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Post-Build Cleaning ("+x[pkgindex]+"::"+y+")", short_msg=short_msg) + retval=portage.doebuild(y,"clean",myroot,self.pkgsettings,edebug,cleanup=1) + if (retval == None): + portage_util.writemsg("Unable to run required binary.\n") + sys.exit(127) + if retval: + sys.exit(retval) + + if ("--pretend" not in myopts) and ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts): + # Clean the old package that we have merged over top of it. + if self.pkgsettings["AUTOCLEAN"]=="yes": + xsplit=portage.pkgsplit(x[2]) + emergelog(" >>> AUTOCLEAN: "+xsplit[0]) + retval=unmerge("clean", [xsplit[0]]) + if not retval: + emergelog(" --- AUTOCLEAN: Nothing unmerged.") + + # Figure out if we need a restart. + mysplit=portage.pkgsplit(x[2]) + if mysplit[0]=="sys-apps/portage": + myver=mysplit[1]+"-"+mysplit[2] + if myver[-3:]=='-r0': + myver=myver[:-3] + if (myver != portage.VERSION) and \ + ("livecvsportage" not in portage.settings.features): + if len(mymergelist) > mergecount: + myargv=sys.argv + myr=0 + for myra in range(len(myargv)): + if myargv[myr][0:len("portage")]=="portage": + del myargv[myr] + myr-=1 + if myargv[myr][0:len("sys-apps/portage")]=="sys-apps/portage": + del myargv[myr] + myr-=1 + myr+=1 + emergelog(" *** RESTARTING emerge via exec() after change of portage version.") + portage.portageexit() + # Remove --ask from options before restarting + mynewargv=[] + badlongopts = ["--ask","--tree","--changelog"] + badshortopts = ["a","t","l"] + for arg in myargv: + if arg[0:2] == "--": + if arg in badlongopts: + continue + mynewargv += [arg] + elif arg[0] == "-": + myarg = "-" + for ch in arg[1:]: + if ch in badshortopts: + continue + myarg += ch + mynewargv += [myarg] + else: + mynewargv += [arg] + os.execv("/usr/lib/portage/bin/emerge", mynewargv) + + if ("--pretend" not in myopts) and ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts): + emergelog(" ::: completed emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[2]+" to "+x[1]) + + # Unsafe for parallel merges + del portage.mtimedb["resume"]["mergelist"][0] + + emergelog(" *** Finished. Cleaning up...") + + # We're out of the loop... We're done. Delete the resume data. + if portage.mtimedb.has_key("resume"): + del portage.mtimedb["resume"] + + if ("--pretend" not in myopts): + if ("--fetchonly" not in myopts) and ("--fetch-all-uri" not in myopts): + if (mergecount>0): + if retval: + portage.env_update() + + #by doing an exit this way, --fetchonly can continue to try to + #fetch everything even if a particular download fails. + if "--fetchonly" in myopts or "--fetch-all-uri" in 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 unmerge(unmerge_action, unmerge_files): + candidate_catpkgs=[] + global_unmerge=0 + + realsyslist = getlist("system") + syslist = [] + for x in realsyslist: + mycp = portage.dep_getkey(x) + if mycp in portage.settings.virtuals: + syslist.extend(portage.settings.virtuals[mycp]) + syslist.append(mycp) + + global myopts + mysettings = portage.config(clone=portage.settings) + + if not unmerge_files or "world" in unmerge_files or "system" in unmerge_files: + if "unmerge"==unmerge_action: + print + print bold("emerge unmerge")+" can only be used with specific package names, not with "+bold("world")+" or" + print bold("system")+" targets." + print + return 0 + else: + global_unmerge=1 + + localtree=portage.db[portage.root]["vartree"] + # process all arguments and add all valid db entries to candidate_catpkgs + if global_unmerge: + if not unmerge_files or "world" in unmerge_files: + candidate_catpkgs.extend(localtree.getallnodes()) + elif "system" in unmerge_files: + candidate_catpkgs.extend(getlist("system")) + else: + #we've got command-line arguments + if not unmerge_files: + print "\nNo packages to unmerge have been provided.\n" + return 0 + for x in unmerge_files: + arg_parts=x.split('/') + if (x[0] not in [".","/"]) and (arg_parts[-1][-7:] != ".ebuild"): + #possible cat/pkg or dep; treat as such + candidate_catpkgs.append(x) + elif unmerge_action in ["prune","clean"]: + print "\n!!! Prune and clean do not accept individual ebuilds as arguments;\n skipping.\n" + continue + else: + # it appears that the user is specifying an installed ebuild and we're in "unmerge" mode, so it's + # ok. + if not os.path.exists(x): + print "\n!!! The path '"+x+"' doesn't exist.\n" + return 0 + + absx = os.path.abspath(x) + sp_absx = absx.split("/") + if sp_absx[-1][-7:] == ".ebuild": + del sp_absx[-1] + absx = string.join(sp_absx,"/") + + sp_absx_len = len(sp_absx) + + vdb_path = portage.root+portage.VDB_PATH + vdb_len = len(vdb_path) + + sp_vdb = vdb_path.split("/") + sp_vdb_len = len(sp_vdb) + + if not os.path.exists(absx+"/CONTENTS"): + print "!!! Not a valid db dir: "+str(absx) + return 0 + + if sp_absx_len <= sp_vdb_len: + # The Path is shorter... so it can't be inside the vdb. + print spabsx + print absx + print "\n!!!",x,"cannot be inside "+(portage.root+portage.VDB_PATH)+"; aborting.\n" + return 0 + + for idx in range(0,sp_vdb_len): + if (idx >= sp_absx_len) or (sp_vdb[idx] != sp_absx[idx]): + print sp_absx + print absx + print "\n!!!",x,"is not inside "+(portage.root+portage.VDB_PATH)+"; aborting.\n" + return 0 + + print "="+string.join(sp_absx[sp_vdb_len:],"/") + candidate_catpkgs.append("="+string.join(sp_absx[sp_vdb_len:],"/")) + + if ("--pretend" in myopts) or ("--ask" in myopts): + print darkgreen("\n>>> These are the packages that I would unmerge:") + + pkgmap={} + numselected=0 + for x in candidate_catpkgs: + #cycle through all our candidate deps and determine what will and will not get unmerged + try: + mymatch=localtree.dep_match(x) + except KeyError: + mymatch=None + except ValueError, errpkgs: + print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous. Please specify" + print "!!! one of the following fully-qualified ebuild names instead:\n" + for i in errpkgs[0]: + print " " + green(i) + print + sys.exit(1) + + if not mymatch and x[0] not in "<>=~": + #add a "=" if missing + mymatch=localtree.dep_match("="+x) + if not mymatch: + print "\n--- Couldn't find " + white(x) + " to "+unmerge_action+"." + continue + mykey=portage.key_expand(portage.dep_getkey(mymatch[0]),portage.db["/"]["vartree"].dbapi) + if not pkgmap.has_key(mykey): + pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] } + if unmerge_action=="unmerge": + for y in mymatch: + if y not in pkgmap[mykey]["selected"]: + pkgmap[mykey]["selected"].append(y) + numselected=numselected+len(mymatch) + + else: + #unmerge_action in ["prune", clean"] + slotmap={} + for mypkg in mymatch: + if unmerge_action=="clean": + myslot=localtree.getslot(mypkg) + else: + #since we're pruning, we don't care about slots and put all the pkgs in together + myslot=0 + if not slotmap.has_key(myslot): + slotmap[myslot]={} + slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg + for myslot in slotmap.keys(): + counterkeys=slotmap[myslot].keys() + counterkeys.sort() + if not counterkeys: + continue + counterkeys.sort() + pkgmap[mykey]["protected"].append(slotmap[myslot][counterkeys[-1]]) + del counterkeys[-1] + #be pretty and get them in order of merge: + for ckey in counterkeys: + pkgmap[mykey]["selected"].append(slotmap[myslot][ckey]) + numselected=numselected+1 + #ok, now the last-merged package is protected, and the rest are selected + if global_unmerge and not numselected: + print "\n>>> No outdated packages were found on your system.\n" + return 0 + + if not numselected: + print "\n>>>",unmerge_action+": No packages selected for removal.\n" + return 0 + + for x in pkgmap.keys(): + for y in localtree.dep_match(x): + if y not in pkgmap[x]["omitted"] and \ + y not in pkgmap[x]["selected"] and \ + y not in pkgmap[x]["protected"]: + pkgmap[x]["omitted"].append(y) + if global_unmerge and not pkgmap[x]["selected"]: + #avoid cluttering the preview printout with stuff that isn't getting unmerged + continue + if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist): + print red("\a\n\n!!! '%s' is part of your system profile. '%s'" % (mykey)) + print yellow("\a!!! Unmerging it may be damaging to your system.\n") + if "--pretend" not in myopts and "--ask" not in myopts: + global EMERGE_WARNING_DELAY + countdown(EMERGE_WARNING_DELAY,red("Press Ctrl-C to Stop")) + print "\n "+white(x) + for mytype in ["selected","protected","omitted"]: + print string.rjust(mytype,12)+":", + if pkgmap[x][mytype]: + for mypkg in pkgmap[x][mytype]: + mysplit=portage.catpkgsplit(mypkg) + if mysplit[3]=="r0": + myversion=mysplit[2] + else: + myversion=mysplit[2]+"-"+mysplit[3] + if mytype=="selected": + print red(myversion), + else: + print green(myversion), + else: + print "none", + print + + print "\n>>>",red("'Selected'"),"packages are slated for removal." + print ">>>",green("'Protected'"),"and",green("'omitted'"),"packages will not be removed.\n" + + if "--pretend" in myopts: + #we're done... return + return 0 + if "--ask" in myopts: + if userquery("Do you want me to unmerge these packages?")=="No": + # enter pretend mode for correct formatting of results + myopts+=["--pretend"] + print + print "Quitting." + print + return 0 + #the real unmerging begins, after a short delay.... + + global CLEAN_DELAY + countdown(CLEAN_DELAY, ">>> Unmerging") + + for x in pkgmap.keys(): + for y in pkgmap[x]["selected"]: + print ">>> Unmerging "+y+"..." + emergelog("=== Unmerging... ("+y+")") + mysplit=string.split(y,"/") + #unmerge... + retval=portage.unmerge(mysplit[0],mysplit[1],portage.root,mysettings,unmerge_action not in ["clean","prune"]) + if retval: + emergelog(" !!! unmerge FAILURE: "+y) + else: + emergelog(" >>> unmerge success: "+y) + #run ldconfig, etc... + portage.env_update() + if not numselected: + return 0 + else: + return 1 + + +def chk_updated_info_files(retval): + root=portage.root + + infodirs=[] + infodirs.extend(string.split(portage.settings["INFOPATH"], ":")) + infodirs.extend(string.split(portage.settings["INFODIR"], ":")) + + print + if os.path.exists("/usr/bin/install-info"): + regen_infodirs=[] + for z in infodirs: + if z=='': + continue + inforoot=normpath(root+z) + if os.path.isdir(inforoot): + try: + infomtime=os.stat(inforoot)[ST_MTIME] + except SystemExit, e: + raise # Needed else can't exit + except: + infomtime=0 + + if not portage.mtimedb.has_key("info"): + portage.mtimedb["info"]={} + if portage.mtimedb["info"].has_key(inforoot): + if portage.mtimedb["info"][inforoot]==infomtime: + pass + else: + portage.mtimedb["info"][inforoot]=infomtime + regen_infodirs.append(inforoot) + else: + regen_infodirs.append(inforoot) + + if not regen_infodirs: + print " "+green("*")+" GNU info directory index is up-to-date." + else: + print " "+green("*")+" Regenerating GNU info directory index..." + + icount=0 + badcount=0 + for inforoot in regen_infodirs: + if inforoot=='': + continue + try: + os.rename(inforoot+"/dir",inforoot+"/dir.old") + except SystemExit, e: + raise # Needed else can't exit + except: + pass + + if not os.path.isdir(inforoot): + continue + errmsg = "" + for x in os.listdir(inforoot): + if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)): + continue + myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1] + existsstr="already exists, for file `" + if myso!="": + if re.search(existsstr,myso): + # Already exists... Don't increment the count for this. + pass + elif myso[:44]=="install-info: warning: no info dir entry in ": + # This info file doesn't contain a DIR-header: install-info produces this + # (harmless) warning (the --quiet switch doesn't seem to work). + # Don't increment the count for this. + pass + else: + badcount=badcount+1 + errmsg += myso + "\n" + icount=icount+1 + + #update mtime so we can potentially avoid regenerating. + portage.mtimedb["info"][inforoot]=os.stat(inforoot)[ST_MTIME] + + if badcount: + print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors." + print errmsg + else: + print " "+green("*")+" Processed",icount,"info files." + + +def post_emerge(retval=0): + global myopts + os.chdir("/") + if "--pretend" in myopts: + sys.exit(retval) + + emergelog(" *** exiting successfully.") + + if "noinfo" not in portage.settings.features: + chk_updated_info_files(retval) + + chk_updated_cfg_files() + sys.exit(retval) + + +def chk_updated_cfg_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 " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files." + print + +# general options that should be taken into account before any action +if "--debug" in myopts: + edebug=1 + +if myaction in ["sync","rsync","metadata"] and (not "--help" in myopts): + if "--pretend" in myopts: + print "emerge: \"sync\" actions do not support \"--pretend.\"" + sys.exit(1) + + emergelog(" === "+str(myaction)) + 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) + syncuri=string.rstrip(portage.settings["SYNC"]) + os.umask(0022) + if myaction == "metadata": + if "--ask" in myopts: + if userquery("Are you sure?") == "No": + sys.exit(1) + print "skipping sync" + updatecache_flg = True + tmpservertimestampfile = None + elif syncuri[:8]=="rsync://": + if not os.path.exists("/usr/bin/rsync"): + print "!!! /usr/bin/rsync does not exist, so rsync support is disabled." + print "!!! Type \"emerge net-misc/rsync\" to enable rsync support." + sys.exit(1) + mytimeout=180 + if portage.settings.has_key("RSYNC_TIMEOUT"): + try: + mytimeout=int(portage.settings["RSYNC_TIMEOUT"]) + except SystemExit, e: + raise # Needed else can't exit + except: + pass + + rsync_flags = [ + "--recursive", # Recurse directories + "--links", # Consider symlinks + "--safe-links", # Ignore links outside of tree + "--perms", # Preserve permissions + "--times", # Preserive mod times + "--compress", # Compress the data transmitted + "--force", # Force deletion on non-empty dirs + "--whole-file", # Don't do block transfers, only entire files + "--delete", # Delete files that aren't in the master tree + "--delete-after", # Delete only after everything else is done + "--stats", # Show final statistics about what was transfered + "--timeout="+str(mytimeout), # IO timeout if not done in X seconds + "--exclude='/distfiles'", # Exclude distfiles from consideration + "--exclude='/local'", # Exclude local from consideration + "--exclude='/packages'", # Exclude packages from consideration + ] + + if "--quiet" in myopts: + rsync_flags.append("--quiet") # Shut up a lot + else: + rsync_flags.append("--progress") # Progress meter for each file + + if "--verbose" in myopts: + rsync_flags.append("--verbose") # More noise? Not really sure what + + if "--debug" in myopts: + rsync_flags.append("--checksum") # Force checksum on all files + + if portage.settings.has_key("RSYNC_EXCLUDEFROM"): + if os.path.exists(portage.settings["RSYNC_EXCLUDEFROM"]): + rsync_flags.append("--exclude-from="+portage.settings["RSYNC_EXCLUDEFROM"]) + else: + print "!!! RSYNC_EXCLUDEFROM specified, but file does not exist." + + if portage.settings.has_key("RSYNC_RATELIMIT"): + rsync_flags.append("--bwlimit="+portage.settings["RSYNC_RATELIMIT"]) + + rsynccommand = "/usr/bin/rsync " + string.join(rsync_flags, " ") + + servertimestampdir = portage.settings.depcachedir+"/" + servertimestampfile = portage.settings.depcachedir+"/timestamp.chk" + tmpservertimestampdir = portage.settings["PORTAGE_TMPDIR"]+"/" + tmpservertimestampfile = portage.settings["PORTAGE_TMPDIR"]+"/timestamp.chk" + + # We only use the backup if a timestamp exists in the portdir. + content=None + if os.path.exists(myportdir+"/metadata/timestamp.chk"): + content=portage.grabfile(servertimestampfile) + if (not content): + content=portage.grabfile(myportdir+"/metadata/timestamp.chk") + + if (content): + try: + mytimestamp=time.mktime(time.strptime(content[0], "%a, %d %b %Y %H:%M:%S +0000")) + except ValueError: + mytimestamp=0 + else: + mytimestamp=0 + + if not os.path.exists(servertimestampdir): + os.mkdir(servertimestampdir) + os.chown(servertimestampdir, os.getuid(), portage.portage_gid) + os.chmod(servertimestampdir, 02775) + + #exitcode=0 + try: + maxretries=int(portage.settings["RSYNC_RETRIES"]) + except SystemExit, e: + raise # Needed else can't exit + except: + maxretries=3 #default number of retries + + retries=0 + hostname, port=re.split("rsync://([^:/]*)(:[0-9]+)?", syncuri)[1:3]; + if port==None: + port="" + updatecache_flg=True + + ips=[] + while (1): + if ips: + del ips[0] + if ips==[]: + try: + ips=socket.gethostbyname_ex(hostname)[2] + except SystemExit, e: + raise # Needed else can't exit + except Exception, e: + print "Notice:",str(e) + dosyncuri=syncuri + + if ips: + try: + dosyncuri=string.replace(syncuri, "//"+hostname+port+"/", "//"+ips[0]+port+"/", 1) + except SystemExit, e: + raise # Needed else can't exit + except Exception, e: + print "Notice:",str(e) + dosyncuri=syncuri + + if (retries==0): + if "--ask" in myopts: + if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No": + print + print "Quitting." + print + sys.exit(0) + emergelog(">>> starting rsync with "+dosyncuri) + if "--quiet" not in myopts: + print ">>> starting rsync with "+dosyncuri+"..." + else: + emergelog(">>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)) + print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri) + + if "--quiet" not in myopts: + print ">>> checking server timestamp ..." + mycommand=rsynccommand+" "+dosyncuri+"/metadata/timestamp.chk "+tmpservertimestampdir + exitcode=portage.spawn(mycommand,portage.settings,free=1) + if (exitcode==0): + try: + servertimestamp = time.mktime(time.strptime(portage.grabfile(tmpservertimestampfile)[0], "%a, %d %b %Y %H:%M:%S +0000")) + except SystemExit, e: + raise # Needed else can't exit + except: + servertimestamp = 0 + + if (servertimestamp != 0) and (servertimestamp == mytimestamp): + emergelog(">>> Cancelling sync -- Already current.") + print + print ">>>" + print ">>> Timestamps on the server and in the local repository are the same." + print ">>> Cancelling all further sync action. You are already up to date." + print ">>>" + print + sys.exit(0) + elif (servertimestamp != 0) and (servertimestamp < mytimestamp): + emergelog(">>> Server out of date: %s" % dosyncuri) + print + print ">>>" + print ">>> SERVER OUT OF DATE: %s" % dosyncuri + print ">>>" + print + elif (servertimestamp == 0) or (servertimestamp > mytimestamp): + # actual sync + mycommand=rsynccommand+" "+dosyncuri+"/ "+myportdir + exitcode=portage.spawn(mycommand,portage.settings,free=1) + if exitcode in [0,1,2,3,4,11,14,20,21]: + break + elif exitcode in [0,1,2,3,4,11,14,20,21]: + break + + retries=retries+1 + + if retries<=maxretries: + print ">>> retry ..." + time.sleep(11) + else: + # over retries + # exit loop + updatecache_flg=False + break + + if (exitcode==0): + emergelog("=== Sync completed with %s" % dosyncuri) + elif (exitcode>0): + print + if exitcode==1: + print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure") + print darkred("!!!")+green(" that your SYNC statement is proper.") + print darkred("!!!")+green(" SYNC="+portage.settings["SYNC"]) + elif exitcode==11: + print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally") + print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption") + print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate") + print darkred("!!!")+green(" and try again after the problem has been fixed.") + print darkred("!!!")+green(" PORTDIR="+portage.settings["PORTDIR"]) + elif exitcode==20: + print darkred("!!!")+green(" Rsync was killed before it finished.") + else: + print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep") + print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable") + print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a") + print darkred("!!!")+green(" temporary problem unless complications exist with your network") + print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.") + print + sys.exit(exitcode) + elif syncuri[:6]=="cvs://": + if not os.path.exists("/usr/bin/cvs"): + print "!!! /usr/bin/cvs does not exist, so rsync support is disabled." + print "!!! Type \"emerge dev-util/cvs\" to enable CVS support." + sys.exit(1) + cvsroot=syncuri[6:] + cvsdir=os.path.dirname(myportdir) + if not os.path.exists(myportdir+"/CVS"): + #initial checkout + print ">>> starting initial cvs checkout with "+syncuri+"..." + if not portage.spawn("cd "+cvsdir+"; cvs -d "+cvsroot+" login",portage.settings,free=1): + print "!!! cvs login error; exiting." + sys.exit(1) + if os.path.exists(cvsdir+"/gentoo-x86"): + print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting." + sys.exit(1) + if not portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",portage.settings,free=1): + print "!!! cvs checkout error; exiting." + sys.exit(1) + if cvsdir!=myportdir: + portage.movefile(cvsdir,portage.settings["PORTDIR"]) + sys.exit(0) + else: + #cvs update + print ">>> starting cvs update with "+syncuri+"..." + sys.exit(portage.spawn("cd "+myportdir+"; cvs -z0 -q update -dP",portage.settings,free=1)) + else: + print "!!! rsync setting: ",syncuri,"not recognized; exiting." + sys.exit(1) + + try: # Prevent users from affecting ebuild.sh. + os.close(sys.stdin.fileno()) + except SystemExit, e: + raise # Needed else can't exit + except: + pass + + if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg: + if "--quiet" not in myopts: + print "\n>>> Updating Portage cache: ", + os.umask(0002) + cachedir = os.path.normpath(portage.settings.depcachedir) + if cachedir in ["/", "/bin", "/dev", "/etc", "/home", + "/lib", "/opt", "/proc", "/root", "/sbin", + "/sys", "/tmp", "/usr", "/var"]: + print "!!! PORTAGE_CACHEDIR IS SET TO A PRIMARY ROOT DIRECTORY ON YOUR SYSTEM." + print "!!! This is ALMOST CERTAINLY NOT what you want: "+str(cachedir) + sys.exit(73) + if not os.path.exists(cachedir): + os.mkdir(cachedir) + + # Potentially bad + #if os.path.exists(cachedir+"/"+myportdir): + # portage.spawn("rm -Rf "+cachedir+"/"+myportdir+"/*",portage.settings,free=1) + + # save timestamp.chk for next timestamp check. + try: + if tmpservertimestampfile != None: + portage.movefile(tmpservertimestampfile, servertimestampfile) + except SystemExit, e: + raise # Needed else can't exit + except Exception, e: + print "!!! Failed to save current timestamp." + print "!!!",e + + portage.portdb.flush_cache() + + try: + os.umask(002) + os.chown(cachedir, os.getuid(), portage.portage_gid) + os.chmod(cachedir, 02775) + except SystemExit, e: + raise # Needed else can't exit + except: + pass + # we don't make overlay trees cache here. + backup_porttrees=portage.portdb.porttrees + porttree_root = portage.portdb.porttree_root + portage.portdb.porttrees=[porttree_root] + cp_list=portage.portdb.cp_all() + cp_list.sort() + pcnt=0 + pcntstr="" + pcntcount=len(cp_list)/100.0 + nextupdate=pcntcount + current=1 + def cleanse_cache(cat, saves, porttree_root=porttree_root): + if len(saves): + d={} + for v in saves: + d[portage.catsplit(v)[1]] = True + for pv in portage.db["/"]["porttree"].dbapi.auxdb[porttree_root][cat].keys(): + if pv not in d: + portage.db["/"]["porttree"].dbapi.auxdb[porttree_root][cat].del_key(pv) + else: + portage.db["/"]["porttree"].dbapi.auxdb[porttree_root][cat].clear() + del portage.db["/"]["porttree"].dbapi.auxdb[porttree_root][cat] + savelist = [] + catlist = [] + oldcat = portage.catsplit(cp_list[0])[0] + for cp in cp_list: + current += 1 + if current >= nextupdate: + pcnt += 1 + nextupdate += pcntcount + if "--quiet" not in myopts: + pcntstr = str(pcnt) + sys.stdout.write("\b"*(len(pcntstr)+1)+pcntstr+"%") + sys.stdout.flush() + cat = portage.catsplit(cp)[0] + if cat != oldcat: + catlist.append(oldcat) + cleanse_cache(oldcat, savelist) + savelist = [] + oldcat = cat + mymatches = portage.db["/"]["porttree"].dbapi.xmatch("match-all", cp) + savelist.extend(mymatches) + for cpv in mymatches: + try: portage.db["/"]["porttree"].dbapi.aux_get(cpv, ["IUSE"],metacachedir=myportdir+"/metadata/cache",debug=("cachedebug" in portage.features)) + except SystemExit: raise + except Exception, e: print "\nFailed cache update:",cpv,e + catlist.append(oldcat) + catlist.append("local") + cleanse_cache(oldcat, savelist) + filelist = portage.listdir(cachedir+"/"+myportdir) + for x in filelist: + found = False + for y in catlist: + if x.startswith(y): + found = True + break + if not found: + portage.spawn("cd /; rm -Rf "+cachedir+"/"+myportdir+"/"+x,portage.settings,free=1,droppriv=1) + + + portage.portdb.porttrees=backup_porttrees + sys.stdout.write("\n\n") + sys.stdout.flush() + + portage.portageexit() + reload(portage) + mybestpv=portage.portdb.xmatch("bestmatch-visible","sys-apps/portage") + mypvs=portage.best(portage.db[portage.root]["vartree"].dbapi.match("sys-apps/portage")) + + chk_updated_cfg_files() + + if(mybestpv != mypvs): + print + print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended" + print red(" * ")+"that you update portage now, before any other packages are updated." + print red(" * ")+"Please do so and then update "+bold("ALL")+" of your configuration files." + print +elif myaction=="regen": + emergelog(" === regen") + #regenerate cache entries + print "Regenerating cache entries... " + try: + os.close(sys.stdin.fileno()) + except SystemExit, e: + raise # Needed else can't exit + except: + pass + sys.stdout.flush() + mynodes=portage.portdb.cp_all() + for x in mynodes: + mymatches=portage.portdb.xmatch("match-all",x) + if not "--quiet" in myopts: + print "processing",x + for y in mymatches: + try: + foo=portage.portdb.aux_get(y,["DEPEND"],debug=1) + except SystemExit, e: + # sys.exit is an exception... And consequently, we can't catch it. + raise + except Exception, e: + print "\n error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)} + print "done!" +# HELP action +elif "config"==myaction: + if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles: + print red("!!! config can only take a single package atom at this time\n") + sys.exit(1) + + print + pkgs = portage.db[portage.root]["vartree"].dbapi.match(myfiles[0]) + if len(pkgs) == 0: + print "No packages found.\n" + sys.exit(0) + elif len(pkgs) > 1: + if "--ask" in myopts: + options = [] + print "Please select a package to configure:" + idx = 0 + for pkg in pkgs: + idx += 1 + options.append(str(idx)) + print options[-1]+") "+pkg + print "X) Cancel" + options.append("X") + idx = userquery("Selection?", options) + if idx == "X": + sys.exit(0) + pkg = pkgs[int(idx)-1] + else: + print "The following packages available:" + for pkg in pkgs: + print "* "+pkg + print "\nPlease use a specific atom or the --ask option." + sys.exit(1) + else: + pkg = pkgs[0] + + print + if "--ask" in myopts: + if userquery("Ready to configure "+pkg+"?") == "No": + sys.exit(0) + else: + print "Configuring pkg..." + print + ebuildpath = portage.db[portage.root]["vartree"].dbapi.findname(pkg) + mysettings = portage.config(clone=portage.settings) + portage.doebuild(ebuildpath,"config",portage.root,mysettings,debug=("--debug" in myopts),cleanup=True) + print + +# INFO action +elif "info"==myaction: + unameout=commands.getstatusoutput("uname -mrp")[1] + print getportageversion() + print "=================================================================" + print "System uname: "+unameout + if os.path.exists("/etc/gentoo-release"): + os.system("cat /etc/gentoo-release") + else: + print "Unknown Host Operating System" + + output=commands.getstatusoutput("distcc --version") + if not output[0]: + print str(string.split(output[1],"\n",1)[0]), + if "distcc" in portage.features: + print "[enabled]" + else: + print "[disabled]" + + output=commands.getstatusoutput("ccache -V") + if not output[0]: + print str(string.split(output[1],"\n",1)[0]), + if "ccache" in portage.features: + print "[enabled]" + else: + print "[disabled]" + + myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers", + "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"] + myvars += portage_util.grabfile(portage.settings["PORTDIR"]+"/profiles/info_pkgs") + myvars = portage_util.unique_array(myvars) + myvars.sort() + + for x in myvars: + if portage.isvalidatom(x): + pkg_matches = portage.db["/"]["vartree"].dbapi.match(x) + pkgs = [] + for y in pkg_matches: + mycpv = portage.catpkgsplit(y) + if(mycpv[3] != "r0"): + pkgs += [mycpv[2] + "-" + mycpv[3]] + else: + pkgs += [mycpv[2]] + if not pkgs: + pkgs = "[Not Present]" + else: + pkgs = ", ".join(sorted_versions(pkgs)) + print "%-20s %s" % (x+":", pkgs) + else: + print "%-20s %s" % (x+":", "[NOT VALID]") + + libtool_vers = string.join(portage.db["/"]["vartree"].dbapi.match("sys-devel/libtool"), ",") + + if "--verbose" in myopts: + myvars=portage.settings.keys() + else: + myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK', + 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR', + 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS', + 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES'] + + myvars.extend(portage_util.grabfile(portage.settings["PORTDIR"]+"/profiles/info_vars")) + + myvars = portage_util.unique_array(myvars) + unset_vars = [] + myvars.sort() + for x in myvars: + if portage.settings.has_key(x): + print x+'="'+portage.settings[x]+'"' + else: + unset_vars.append(x) + if unset_vars: + print "Unset: "+", ".join(unset_vars) + print + + if "--debug" in myopts: + for x in dir(portage): + module = getattr(portage, x) + if "cvs_id_string" in dir(module): + print "%s: %s" % (str(x), str(module.cvs_id_string)) + +# SEARCH action +elif "search"==myaction: + if not myfiles: + print "emerge: no search terms provided." + else: + searchinstance = search() + for mysearch in myfiles: + try: + searchinstance.execute(mysearch) + except re.error, comment: + 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() + +elif "depclean"==myaction: + # Kill packages that aren't explicitly merged or are required as a + # dependency of another package. World file is explicit. + + print + print red("*** WARNING ***")+" : DEPCLEAN CAN SERIOUSLY IMPAIR YOUR SYSTEM. USE CAUTION." + print red("*** WARNING ***")+" : (Cancel: CONTROL-C) -- ALWAYS VERIFY ALL PACKAGES IN THE" + print red("*** WARNING ***")+" : CANDIDATE LIST FOR SANITY BEFORE ALLOWING DEPCLEAN TO" + print red("*** WARNING ***")+" : UNMERGE ANY PACKAGES." + print red("*** WARNING ***")+" :" + print red("*** WARNING ***")+" : USE FLAGS MAY HAVE AN EXTREME EFFECT ON THE OUTPUT." + print red("*** WARNING ***")+" : SOME LIBRARIES MAY BE USED BY PACKAGES BUT ARE NOT" + print red("*** WARNING ***")+" : CONSIDERED TO BE A DEPEND DUE TO USE FLAG SETTINGS." + print red("*** WARNING ***")+" : emerge --update --deep --newuse world TO VERIFY" + print red("*** WARNING ***")+" : SANITY IN THIS REGARD." + print red("*** WARNING ***")+" :" + print red("*** WARNING ***")+" : Packages in the list that are desired may be added" + print red("*** WARNING ***")+" : directly to the world file to cause them to be ignored" + print red("*** WARNING ***")+" : by depclean and maintained in the future. BREAKAGES DUE" + print red("*** WARNING ***")+" : TO UNMERGING AN ==IN-USE LIBRARY== MAY BE REPAIRED BY" + print red("*** WARNING ***")+" : MERGING *** THE PACKAGE THAT COMPLAINS *** ABOUT THE" + print red("*** WARNING ***")+" : MISSING LIBRARY." + print + if ("--pretend" not in myopts) and ("--ask" not in myopts): + countdown(EMERGE_WARNING_DELAY, ">>> Depclean") + emergelog(" >>> depclean") + + mydepgraph=depgraph(myaction,myopts) + syslist=getlist("system") + worldlist=getlist("world") + + print "Calculating",myaction,"dependencies ", + if not mydepgraph.xcreate("world"): + print "\n!!! Failed to create deptree." + sys.exit(1) + print "\b\b ... done!" + + if ("--usepkgonly" in myopts) and mydepgraph.missingbins: + sys.stderr.write(red("The following binaries are not available for merging...\n")) + for x in mydepgraph.missingbins: + sys.stderr.write(" "+str(x)+"\n") + sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n") + sys.exit(1) + + alldeps=mydepgraph.digraph.allnodes() + myvarlist=portage.vardbapi(portage.root).cp_all() + + if not syslist: + print "!!! You have no system list. Cannot determine system from world." + if not worldlist: + print "!!! You have no world file. Cannot determine explicit merges." + if not myvarlist: + print "!!! You have no installed package tree (%s). This is a problem." % portage.VDB_PATH + if not alldeps: + print "!!! You have no dependencies. Impossible. Bug." + + if not (syslist and worldlist and myvarlist and alldeps): + print + sys.exit(1) + + reallist=[] + for x in alldeps: + myparts=portage.catpkgsplit(string.split(x)[2]) + if not myparts: + sys.stderr.write( + red("!!! There appears to be a problem with the following package:\n")+ + red("!!! "+str(string.split(x)[2])+"\n\n")+ + "!!! Please ensure that blocking/conflicting packages are not merged."+ + "!!! 'emerge -p "+str(string.split(x)[2])+"\n\n") + if ("--pretend" not in myopts) and ("--ask" not in myopts): + countdown(EMERGE_WARNING_DELAY, "*** Continuing") + continue + + catpack=myparts[0]+"/"+myparts[1] + if catpack not in reallist: + reallist.append(catpack) + + cleanlist=[] + for x in myvarlist: + if x not in reallist: + if x not in cleanlist: + cleanlist.append(x) + + for x in syslist+worldlist: + myparts = portage.catpkgsplit(x) + if myparts: + if myparts[0][0] in ('<','>','='): + myparts[0] = myparts[0][1:] + if myparts[0][0] in ('<','>','='): + myparts[0] = myparts[0][1:] + catpack=myparts[0]+"/"+myparts[1] + else: + catpack=x + if catpack in cleanlist: + cleanlist.remove(catpack) + + #print "\n\n\nCleaning: " + #for x in cleanlist: + # print x + #print + + if len(cleanlist): + unmerge("unmerge", cleanlist) + + print + print "Packages installed: "+str(len(myvarlist)) + print "Packages in world: "+str(len(worldlist)) + print "Packages in system: "+str(len(syslist)) + print "Unique package names: "+str(len(reallist)) + print "Required packages: "+str(len(alldeps)) + if "--pretend" in myopts: + print "Number to remove: "+str(len(cleanlist)) + else: + print "Number removed: "+str(len(cleanlist)) + post_emerge() + +# "update", "system", or just process files: +else: + favorites=[] + syslist=getlist("system") + if (("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts)) or ("--ask" in myopts): + if "--tree" in myopts: + print + print darkgreen("These are the packages that I would merge, in reverse order:") + print + else: + print + print darkgreen("These are the packages that I would merge, in order:") + print + + if ("--resume" in myopts) and portage.mtimedb.has_key("resume"): + myresumeopts=portage.mtimedb["resume"]["myopts"][:] + + while "--skipfirst" in myresumeopts: + myresumeopts.remove("--skipfirst") + while "--ask" in myresumeopts: + myresumeopts.remove("--ask") + + for myopt in myopts: + if myopt not in myresumeopts: + myresumeopts.append(myopt) + myopts=myresumeopts + mydepgraph=depgraph("resume",myopts) + if "--resume" not in myopts: + myopts+=["--resume"] + else: + if ("--resume" in myopts): + del myopts[myopts.index("--resume")] + print darkgreen("emerge: It seems we have nothing to resume...") + sys.exit(0) + + mydepgraph=depgraph(myaction,myopts) + if myaction in ["system","world"]: + print "Calculating",myaction,"dependencies ", + sys.stdout.flush() + if not mydepgraph.xcreate(myaction): + print "!!! Depgraph creation failed." + sys.exit(1) + print "\b\b ...done!" + else: + if not myfiles: + print "emerge: please tell me what to do." + help() + sys.exit(1) + #we don't have any files to process; skip this step and exit + print "Calculating dependencies ", + sys.stdout.flush() + retval,favorites=mydepgraph.select_files(myfiles) + if not retval: + sys.exit(1) + print "\b\b ...done!" + + if ("--usepkgonly" in myopts) and mydepgraph.missingbins: + sys.stderr.write(red("The following binaries are not available for merging...\n")) + + if mydepgraph.missingbins: + for x in mydepgraph.missingbins: + sys.stderr.write(" "+str(x)+"\n") + sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n") + sys.exit(1) + + if "--ask" in myopts: + if "--resume" in myopts: + mydepgraph.display(portage.mtimedb["resume"]["mergelist"]) + prompt="Do you want me to resume merging these packages?" + else: + mydepgraph.display(mydepgraph.altlist()) + mergecount=0 + hasblocks = False + for x in mydepgraph.altlist(): + if x[3]!="nomerge": + mergecount+=1 + #check for blocking dependencies + if x[0]=="blocks": + hasblocks = True + if mergecount==0: + if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]: + prompt="Nothing to merge; do you want me to auto-clean packages?" + else: + print + print "Nothing to merge; quitting." + print + sys.exit(0) + elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts: + prompt="Do you want me to fetch the source files for these packages?" + elif hasblocks: + print "\n!!! Error: The above package list contains packages which cannot be installed" + print "!!! on the same system." + print + sys.exit(1) + else: + prompt="Do you want me to merge these packages?" + print + if userquery(prompt)=="No": + print + print "Quitting." + print + sys.exit(0) + # Don't ask again (e.g. when auto-cleaning packages after merge) + myopts.remove("--ask") + + if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts): + if ("--resume" in myopts): + mydepgraph.display(portage.mtimedb["resume"]["mergelist"]) + else: + mydepgraph.display(mydepgraph.altlist()) + else: + if ("--buildpkgonly" in myopts): + if not mydepgraph.digraph.hasallzeros(): + print "\n!!! --buildpkgonly requires all dependencies to be merged." + print "!!! Cannot merge requested packages. Merge deps and try again.\n" + sys.exit(1) + + if ("--resume" in myopts): + favorites=portage.mtimedb["resume"]["favorites"] + mydepgraph.merge(portage.mtimedb["resume"]["mergelist"]) + else: + portage.mtimedb["resume"]={} + portage.mtimedb["resume"]["myopts"]=myopts + portage.mtimedb["resume"]["favorites"]=favorites + if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts): + for pkgline in mydepgraph.altlist(): + if pkgline[0]=="ebuild" and pkgline[3]=="merge": + y=portage.portdb.findname(pkgline[2]) + tmpsettings = portage.config(clone=portage.settings) + retval=portage.doebuild(y,"digest",portage.root,tmpsettings,edebug,("--pretend" in myopts)) + mydepgraph.merge(mydepgraph.altlist()) + + if portage.mtimedb.has_key("resume"): + del portage.mtimedb["resume"] + if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]: + print ">>> Auto-cleaning packages ..." + unmerge("clean", ["world"]) + post_emerge() diff --git a/bin/env-update b/bin/env-update new file mode 100755 index 000000000..a60428767 --- /dev/null +++ b/bin/env-update @@ -0,0 +1,11 @@ +#!/usr/bin/python -O +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/env-update,v 1.9 2004/10/04 13:56:50 vapier Exp $ + +import os,sys +os.environ["PORTAGE_CALLER"] = "env-update" +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage +portage.env_update() diff --git a/bin/env-update.sh b/bin/env-update.sh new file mode 100755 index 000000000..5edc2da6b --- /dev/null +++ b/bin/env-update.sh @@ -0,0 +1,221 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/env-update.sh,v 1.2 2004/10/04 13:56:50 vapier Exp $ + +############################################ +############################################ +# ENVIRONMENT SETUP +############################################ + +if [[ ${EUID} -ne 0 ]] ; then + echo "$0: must be root." + exit 1 +fi + +# Make sure our environment is sane +if [[ ! -z "${MAKELINKS}" ]] ; then + export MAKELINKS=0 +else + export MAKELINKS=1 +fi +export ROOT="${ROOT:=/}" +[[ ${ROOT} == */ ]] || export ROOT="${ROOT}/" + +export ENVDIR="${ROOT}etc/env.d" +mkdir -p ${ENVDIR} +chmod 755 ${ENVDIR} +specials=" + KDEDIRS PATH CLASSPATH LDPATH MANPATH INFODIR INFOPATH ROOTPATH + CONFIG_PROTECT CONFIG_PROTECT_MASK PRELINK_PATH PYTHONPATH + PRELINK_PATH_MASK ADA_INCLUDE_PATH ADA_OBJECTS_PATH" +colon_separated=" + ADA_INCLUDE_PATH ADA_OBJECTS_PATH LDPATH PATH MANPATH ROOTPATH + PRELINK_PATH PRELINK_PATH_MASK PYTHON_PATH" + +export LDSOCONF="${ROOT}etc/ld.so.conf" + +export PRELINKCONF="${ROOT}etc/prelink.conf" +defaultprelinkpaths=":/bin:/sbin:/usr/bin:/usr/sbin:/lib:/usr/lib" + +export PROFILEENV="${ROOT}etc/profile.env" +export CSHENV="${ROOT}etc/csh.env" + +# make sure we aren't tricked with previous 'my_envd_' variables +unset $(set | grep '^my_envd_' | cut -d= -f1) + +############################################ +############################################ +# ENV.D PARSING +############################################ + +do_has() { + local x + local me="$1" + shift + + for x in "$@" ; do + [[ ${x} == ${me} ]] && return 0 + done + return 1 +} +has() { + local ret + local ifs="${IFS}" + unset IFS + do_has $1 ${!2} + ret=$? + export IFS="${ifs}" + return ${ret} +} +is_special() { + has $1 specials +} +is_colon_separated() { + has $1 colon_separated +} + +for envd in $(ls ${ENVDIR} | sort) ; do + # make sure file is a vaild env'd entry and not a backup file + num="${envd:0:2}" + if [[ ! -z ${num//[0-9]} ]] ; then + continue + elif [[ ${envd} == *~ || ${envd} == *.bak ]] ; then + continue + fi + + # use bash to make sure the file is valid + envd="${ENVDIR}/${envd}" + if ! (source "${envd}") ; then + echo "!!! Error parsing ${envd}!" + exit 1 + fi + + # parse env.d entries + cnfvars="$(grep '^[[:alpha:]_][[:alnum:]_]*=' "${envd}")" + export IFS=$'\n' + for cnfv in ${cnfvars} ; do + var="${cnfv/=*}" + val="${cnfv:${#var}+1}" + if [ "${val:0:1}" == "\"" ] ; then + val="${val:1:${#val}-2}" + fi + myvar="my_envd_${var}" + if is_special ${var} ; then + if [[ ! -z "${!myvar}" ]] ; then + if is_colon_separated ${var} ; then + sep=":" + else + sep=" " + fi + else + sep="" + fi + export ${myvar}="${!myvar}${sep}${val}" + else + export ${myvar}="${val}" + fi + done + unset IFS +done + +############################################ +############################################ +# LD.SO.CONF HANDLING +############################################ + +# create a : sep list from ld.so.conf +export OLD_LDPATH="" +if [ -s "${LDSOCONF}" ] ; then + while read line ; do + if [[ "${line:0:1}" == "#" ]] ; then + continue + fi + export OLD_LDPATH="${OLD_LDPATH}:${line}" + done < ${LDSOCONF} + export OLD_LDPATH="${OLD_LDPATH:1}" +fi + +# has the ldpath changed ? if so, recreate +if [[ "${OLD_LDPATH}" != "${my_envd_LDPATH}" ]] ; then + cat << EOF > ${LDSOCONF} +# ld.so.conf autogenerated by env-update; make all changes to +# contents of /etc/env.d directory +${my_envd_LDPATH//:/ +} +EOF +fi + +############################################ +############################################ +# HANDLE PRELINK PATHS +############################################ + +if prelink --version >& /dev/null ; then + # we assume LDPATH and PATH aren't empty ... if they were, we got other problems + envdprelinkcheckpaths="${my_envd_LDPATH}:${my_envd_PATH}" + if [[ ! -z "${my_envd_PRELINK_PATH}" ]] ; then + envdprelinkcheckpaths="${envdprelinkcheckpaths}:${my_envd_PRELINK_PATH}" + fi + + if [[ ! -z "${my_envd_PRELINK_PATH_MASK}" ]] ; then + export prelink_mask=":${PRELINK_PATH_MASK}:" + envdprelinkpaths="" + export IFS=":" + for dir in ${envdprelinkcheckpaths} ; do + if [[ ${dir:0-1} == / ]] ; then + noslashdir="${dir:0:${#dir}-1}" + else + dir="${dir}/" + noslashdir="${dir}" + fi + if [[ ${prelink_mask/:${dir}:/} == ${prelink_mask} \ + && ${prelink_mask/:${noslashdir}:/} == ${prelink_mask} ]] ; then + envdprelinkpaths="${envdprelinkpaths}:${dir}" + fi + done + unset IFS + else + envdprelinkpaths=":${envdprelinkcheckpaths}" + fi + + cat << EOF > ${PRELINKCONF} +# prelink.conf autogenerated by env-update; make all changes to +# contents of /etc/env.d directory +${defaultprelinkpaths//:/ +-l } +${envdprelinkpaths//:/ +-h } +EOF +fi +unset my_envd_LDPATH + +############################################ +############################################ +# RUN EXTERNAL PROGRAMS NOW +############################################ + +echo ">>> Regenerating ${ROOT}etc/ld.so.cache..." +if [[ ${MAKELINKS} -eq 0 ]] ; then + (cd / ; /sbin/ldconfig -X -r ${ROOT} >& /dev/null) +else + (cd / ; /sbin/ldconfig -r ${ROOT} >& /dev/null) +fi + +cat << EOF > ${PROFILEENV} +# THIS FILE IS AUTOMATICALLY GENERATED BY env-update. +# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES +# GO INTO /etc/profile NOT /etc/profile.env + +$(set | grep '^my_envd_' | sed -e 's:^my_envd_:export :') +EOF + +cat << EOF > ${CSHENV} +# THIS FILE IS AUTOMATICALLY GENERATED BY env-update. +# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES +# GO INTO /etc/csh.cshrc NOT /etc/csh.env + +$(set | grep '^my_envd_' | sed -e 's:^my_envd_\([[:alpha:]_][[:alnum:]_]*\)=:setenv \1 :') +EOF + +[[ ${ROOT} == / ]] && /sbin/depscan.sh diff --git a/bin/etc-update b/bin/etc-update new file mode 100755 index 000000000..e8ea9376b --- /dev/null +++ b/bin/etc-update @@ -0,0 +1,407 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/etc-update,v 1.23.2.5 2005/05/29 12:40:08 jstubbs Exp $ + +# Author Brandon Low +# +# Previous version (from which I've borrowed a few bits) by: +# Jochem Kossen +# Leo Lipelis +# Karl Trygve Kalleberg + +export PORTAGE_CALLER="etc-update" + +eval $(python -c 'import portage; print "export PORTAGE_TMPDIR="+portage.settings["PORTAGE_TMPDIR"]; print "export USERLAND="+portage.settings["USERLAND"]') + +if [ "$USERLAND" == "BSD" ] ; then + function sed() { gsed "$@"; } +elif [ "$USERLAND" == "Darwin" ] && [ -x /bin/gsed ]; then + function sed() { gsed "$@"; } +fi + +function get_config() { + item=$1 + + # First strip off comment lines, then grab the configuration + # item. If there's more than one of the same configuration item, + # then allow the last setting to take precedence. + cut -d'#' -f1-1 /etc/etc-update.conf | \ + sed -ne "s/^ *$item *= *\([\"']\{0,1\}\)\(.*\)\1/\2/p" |sed -e '$p;d' +} + +function scan() { + + echo "Scanning Configuration files..." + rm -rf ${TMP}/files > /dev/null 2>&1 + mkdir ${TMP}/files || die "Failed mkdir command!" 1 + count=0 + input=0 + + for path in ${CONFIG_PROTECT}; do if [ -d ${path} ]; then + ofile="" + for file in `find ${path}/ -iname "._cfg????_*" | + sed -e "s:\(^.*/\)\(\._cfg[0-9]*_\)\(.*$\):\1\2\3\%\2\%\3:" | + sort -t'%' -k3 -k2 | LANG=POSIX LC_ALL=POSIX cut -f1 -d'%'`; do + rpath=`echo "${file/\/\///}" | sed -e "s:/[^/]*$::"` + rfile=`echo "${file/\/\///}" | sed -e "s:^.*/::"` + for mpath in ${CONFIG_PROTECT_MASK}; do + if [[ "${rpath}" == "${mpath}"* ]]; then + mv ${rpath}/${rfile} ${rpath}/${rfile:10} + break + fi + done + [ ! -f ${file} ] && continue + + + if [[ "${ofile:10}" != "${rfile:10}" ]] || + [[ ${opath} != ${rpath} ]]; then + MATCHES=0 + if [[ "${EU_AUTOMERGE}" == "yes" ]]; then + if [ ! -e "${rpath}/${rfile}" ] || [ ! -e "${rpath}/${rfile:10}" ]; then + MATCHES=0 + else + diff -Bbua ${rpath}/${rfile} ${rpath}/${rfile:10} | egrep '^[+-]' | egrep -v '^[+-][\t ]*#|^--- |^\+\+\+ ' | egrep -qv '^[-+][\t ]*$' + MATCHES=$? + fi + elif [[ -z `diff -Nua ${rpath}/${rfile} ${rpath}/${rfile:10}| + grep "^[+-][^+-]"|grep -v '# .Header:.*'` ]]; then + MATCHES=1 + fi + if [[ "${MATCHES}" == "1" ]]; then + echo "Automerging trivial changes in: ${rfile:10}" + mv ${rpath}/${rfile} ${rpath}/${rfile:10} + continue + else + count=${count}+1 + echo "${rpath}/${rfile:10}" > ${TMP}/files/${count} + echo "${rpath}/${rfile}" >> ${TMP}/files/${count} + ofile="${rfile}" + opath="${rpath}" + continue + fi + fi + + if [[ -z `diff -Nua ${rpath}/${rfile} ${rpath}/${ofile}| + grep "^[+-][^+-]"|grep -v '# .Header:.*'` ]]; then + mv ${rpath}/${rfile} ${rpath}/${ofile} + continue + else + echo "${rpath}/${rfile}" >> ${TMP}/files/${count} + ofile="${rfile}" + opath="${rpath}" + fi + done + fi; done + +} + +function sel_file() { + local -i isfirst=0 + until [ -f ${TMP}/files/${input} ] || [ ${input} == -1 ] || [ ${input} == -3 ]; do + for file in `ls ${TMP}/files|sort -n`; do + if (( ${isfirst} == 0 )); then + isfirst=${file} + fi + echo -n "${file}${PAR} " + if (( ${mode} == 0 )); then + for word in `cat ${TMP}/files/${file}`; do + echo ${word} + done + else + head -n1 ${TMP}/files/${file} + fi + done > ${TMP}/menuitems + + if [ "${OVERWRITE_ALL}" == "yes" ]; then + input=0 + else + if (( ${mode} == 0 )); then + echo "The following is the list of files which need updating, each +configuration file is followed by a list of possible replacement files." + else + local my_title="Please select a file to update" + fi + + if (( ${mode} == 0 )); then + cat ${TMP}/menuitems + echo "Please select a file to edit by entering the corresponding number." + echo " (don't use -3 or -5 if you're unsure what to do)" + echo " (-1 to exit) (-3 to auto merge all remaining files)" + echo -n " (-5 to auto-merge AND not use 'mv -i'): " + read input + else + dialog --title "${title}" --menu "${my_title}" \ + 0 0 0 `echo "-1 Exit";cat ${TMP}/menuitems` \ + 2> ${TMP}/input + input=`cat ${TMP}/input` + fi + if (( ${input} == -5 )); then + input=-3 + export mv_opts="" + fi + if (( ${input} == -3 )); then + input=0 + export OVERWRITE_ALL="yes" + fi + fi # -3 automerge + if (( ${input} == 0 )); then + input=${isfirst} + fi + done +} + +function do_file() { + echo + local -i my_input + local -i fcount=0 + until (( `cat ${TMP}/files/${input}|wc -l` < 2 )); do + my_input=0 + if (( `cat ${TMP}/files/${input}|wc -l` == 2 )); then + my_input=1 + fi + until (( ${my_input} > 0 )) && (( ${my_input} < `cat ${TMP}/files/${input}|wc -l` )); do + fcount=0 + + if [ "${OVERWRITE_ALL}" == "yes" ]; then + my_input=0 + else + for line in `cat ${TMP}/files/${input}`; do + if (( ${fcount} > 0 )); then + echo -n "${fcount}${PAR} " + echo "${line}" + else + if (( ${mode} == 0 )); then + echo "Below are the new config files for ${line}:" + else + local my_title="Please select a file to process for ${line}" + fi + fi + fcount=${fcount}+1 + done > ${TMP}/menuitems + + if (( ${mode} == 0 )); then + cat ${TMP}/menuitems + echo -n "Please select a file to process (-1 to exit this file): " + read my_input + else + dialog --title "${title}" --menu "${my_title}" \ + 0 0 0 `cat ${TMP}/menuitems;echo "${fcount} Exit"` \ + 2> ${TMP}/input + my_input=`cat ${TMP}/input` + fi + fi # OVERWRITE_ALL + + if (( ${my_input} == 0 )); then + my_input=1 + elif (( ${my_input} == -1 )); then + input=0 + return + elif (( ${my_input} == ${fcount} )); then + break + fi + done + if (( ${my_input} == ${fcount} )); then + break + fi + + fcount=${my_input}+1 + + file=`cat ${TMP}/files/${input} | sed -e "${fcount}p;d"` + ofile=`head -n1 ${TMP}/files/${input}` + + do_cfg "${file}" "${ofile}" + + cat ${TMP}/files/${input}|sed -e "${fcount}!p;d" > ${TMP}/files/sed + mv ${TMP}/files/sed ${TMP}/files/${input} + + if (( ${my_input} == -1 )); then + break + fi + done + echo + rm ${TMP}/files/${input} + count=${count}-1 +} + +function do_cfg() { + + local file="${1}" + local ofile="${2}" + local -i my_input=0 + + until (( ${my_input} == -1 )) || [ ! -f ${file} ]; do + if [ "${OVERWRITE_ALL}" == "yes" ]; then + my_input=1 + else + showdiffcmd=$(echo "${diff_command}" | + sed -e "s:%file1:${ofile}:" -e "s:%file2:${file}:") + + if [ "${using_editor}" == 0 ]; then + ( + echo "Showing differences between ${ofile} and ${file}" + ${showdiffcmd} + ) | ${pager} + else + echo "Beginning of differences between ${ofile} and ${file}" + ${showdiffcmd} + echo "End of differences between ${ofile} and ${file}" + fi + if [ -L "${file}" ]; then + echo + echo "-------------------------------------------------------------" + echo "NOTE: File is a symlink to another file. REPLACE recommended." + echo " The original file may simply have moved. Please review." + echo "-------------------------------------------------------------" + echo + fi + echo -n "1) Replace original with update +2) Delete update, keeping original as is +3) Interactively merge original with update +4) Show differences again +Please select from the menu above (-1 to ignore this update): " + read my_input + fi + + case ${my_input} in + 1) echo "Replacing ${ofile} with ${file}" + mv ${mv_opts} ${file} ${ofile} + my_input=-1 + continue + ;; + 2) echo "Deleting ${file}" + rm ${rm_opts} ${file} + continue + ;; + 3) do_merge "${file}" "${ofile}" + my_input=${?} +# [ ${my_input} == 255 ] && my_input=-1 + continue + ;; + 4) continue + ;; + *) continue + ;; + esac + done +} + +function do_merge() { + + local file="${1}" + local ofile="${2}" + local mfile="${2}.merged" + local -i my_input=0 + echo "${file} ${ofile} ${mfile}" + + if [ -e ${mfile} ] ; then + echo "A previous version of the merged file exists, cleaning..." + rm ${rm_opts} ${mfile} + fi + + until (( ${my_input} == -1 )); do + echo "Merging ${file} and ${ofile}" + `echo "${merge_command}" | + sed -e "s:%merged:${mfile}:g" \ + -e "s:%orig:${ofile}:g" \ + -e "s:%new:${file}:g"` + until (( ${my_input} == -1 )); do + echo -n "1) Replace ${ofile} with merged file +2) Show differences between merged file and original +3) Remerge original with update +4) Edit merged file +5) Return to the previous menu +Please select from the menu above (-1 to exit, losing this merge): " + read my_input + case ${my_input} in + 1) echo "Replacing ${ofile} with ${mfile}" + chmod --reference=${ofile} ${mfile} + mv ${mv_opts} ${mfile} ${ofile} + rm ${rm_opts} ${file} + return 255 + ;; + 2) ( echo "Showing differences between ${ofile} and ${mfile}" + `echo "${diff_command}" | \ + sed -e "s:%file1:${ofile}:" \ + -e "s:%file2:${mfile}:"` ) | ${pager} + continue + ;; + 3) break + ;; + 4) ${EDITOR:-nano -w} "${mfile}" + continue + ;; + 5) rm ${rm_opts} ${mfile} + return 0 + ;; + *) continue + ;; + esac + done + done + rm ${rm_opts} ${mfile} + return 255 +} + +function die() { + trap "" term + trap "" kill + echo "Exiting: ${1}" + rm -rf ${TMP} + exit ${2} +} + +# +# Run the script +# +scriptname=`basename $0` + +trap die term + +TMP="${PORTAGE_TMPDIR}/$$" +rm -rf ${TMP} 2> /dev/null +mkdir ${TMP} || die "failed mkdir command!" 1 + +# I need the CONFIG_PROTECT value +CONFIG_PROTECT=$(/usr/lib/portage/bin/portageq config_protect) +CONFIG_PROTECT_MASK=$(/usr/lib/portage/bin/portageq config_protect_mask) + +# load etc-config's configuration +EU_AUTOMERGE=`get_config eu_automerge` +rm_opts=`get_config rm_opts` +mv_opts=`get_config mv_opts` +cp_opts=`get_config cp_opts` +pager=`get_config pager` +diff_command=`get_config diff_command` +using_editor=`get_config using_editor` +merge_command=`get_config merge_command` +declare -i mode=`get_config mode` +[ -z ${mode} ] && mode=0 +[ -z "${pager}" ] && pager="cat" + +#echo "rm_opts: $rm_opts, mv_opts: $mv_opts, cp_opts: $cp_opts" +#echo "pager: $pager, diff_command: $diff_command, merge_command: $merge_command" + +if (( ${mode} == 0 )); then + PAR=")" +else + PAR="" +fi + +declare -i count=0 +declare -i input=0 +declare title="Gentoolkit's etc-update tool!" + +scan + +until (( ${input} == -1 )); do + if (( ${count} == 0 )); then + die "Nothing left to do; exiting. :)" 0 + fi + sel_file + if (( ${input} != -1 )); then + do_file + fi +done + +die "User termination!" 0 diff --git a/bin/find-requires b/bin/find-requires new file mode 100755 index 000000000..44bc51dae --- /dev/null +++ b/bin/find-requires @@ -0,0 +1,44 @@ +#!/bin/sh +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/find-requires,v 1.5 2004/10/04 13:56:50 vapier Exp $ + +# note this works for both a.out and ELF executables +# it also auto-generates requirment lines for shell scripts + +ulimit -c 0 + +filelist=`sed "s/['\"]/\\\&/g"` +exelist=`echo $filelist | $XARGS file | grep ":.*executable" | cut -d: -f1 ` +scriptlist=`echo $filelist | $XARGS file | egrep ":.* (commands|script) " | cut -d: -f1 ` +liblist=`echo $filelist | $XARGS file | grep ":.*shared object" | cut -d : -f1 ` + +for f in $exelist; do + if [ -x $f ]; then + ldd $f | awk '/=>/ { print $1 }' + fi +done | sort -u | sed "s/['\"]/\\\&/g" | $XARGS -n 1 basename | grep -v 'libNoVersion.so' | sort -u + +for f in $liblist; do + ldd $f | awk '/=>/ { print $1 }' +done | sort -u | sed "s/['\"]/\\\&/g" | $XARGS -n 1 basename | grep -v 'libNoVersion.so' | sort -u + +for f in $scriptlist; do + if [ -x $f ]; then + head -1 $f | sed -e 's/^\#\![ ]*//' | cut -d" " -f1 + fi +done | sort -u + +#for f in $liblist $exelist ; do +# objdump -p $f | awk ' +# BEGIN { START=0; LIBNAME=""; } +# /Version References:/ { START=1; } +# /required from/ && (START==1) { +# sub(/:/, "", $3); +# LIBNAME=$3; +# } +# (START==1) && (LIBNAME!="") && ($4~/^GLIBC_*/) { print LIBNAME "(" $4 ")"; } +# /^$/ { START=0; } +# ' +#done | sort -u + diff --git a/bin/fix-db.py b/bin/fix-db.py new file mode 100755 index 000000000..d185580fa --- /dev/null +++ b/bin/fix-db.py @@ -0,0 +1,175 @@ +#!/usr/bin/python +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/fix-db.py,v 1.8 2004/10/11 04:01:00 jstubbs Exp $ + +import os,sys,re +sys.path = ["/usr/lib/portage/pym"]+sys.path + +from stat import * +from output import * +from portage import lockfile,unlockfile,VDB_PATH,root + + +mylog = open("/var/log/emerge_fix-db.log", "a") +def writemsg(msg): + if msg[-1] != '\n': + msg += "\n" + sys.stderr.write(msg) + sys.stderr.flush() + mylog.write(msg) + mylog.flush() + +def fix_global_counter(value): + myf = open("/var/cache/edb/counter") + newvalue = value+1000 + myf.write(str(newvalue)) + myf.flush() + myf.close() + return newvalue + +bad = {} +counters = {} +times = {} + +try: + real_counter = long(open("/var/cache/edb/counter").read()) +except SystemExit, e: + raise # This needs to be propogated +except: + writemsg("ERROR: Real counter is invalid.\n") + real_counter = 0 + +vardbdir = root+VDB_PATH+"/" +for cat in os.listdir(vardbdir): + catdir = vardbdir+cat+"/" + if not os.path.isdir(catdir): + writemsg("Invalid file: '%s'\n" % catdir[:-1]) + continue + for pkg in os.listdir(catdir): + pkgdir = catdir+pkg+"/" + catpkg = cat+"/"+pkg + + if not os.path.isdir(catdir): + writemsg("Invalid file: '%s'\n" % pkgdir) + continue + + bad[catpkg] = [] + + pkgdirlist = os.listdir(pkgdir) + if not pkgdirlist: + writemsg("ERROR: Package directory is empty for '%s'\n" % catpkg) + writemsg(" Deleting this directory. Remerge if you want it back.\n") + os.rmdir(pkgdir) + del bad[catpkg] + continue + + if "CONTENTS" not in pkgdirlist: + bad[catpkg] += ["CONTENTS is missing"] + times[catpkg] = -1 + writemsg("ERROR: Contents file is missing from the package directory.\n") + writemsg(" '%s' is corrupt and should be deleted.\n" % catpkg) + else: + times[catpkg] = None + for line in open(pkgdir+"CONTENTS").readlines(): + mysplit = line.split() + if mysplit[0] == "obj": + try: + times[catpkg] = long(mysplit[-1]) + except SystemExit, e: + raise # This needs to be propogated + except: + times[catpkg] = -1 + bad[catpkg] += ["CONTENTS is corrupt"] + writemsg("ERROR: Corrupt CONTENTS file in '%s'\n" % catpkg) + writemsg(" This package should be deleted.\n") + break + if times[catpkg] == None: + times[catpkg] = os.stat(pkgdir+"CONTENTS")[ST_MTIME] + + if "COUNTER" not in pkgdirlist: + bad[catpkg] += ["COUNTER is missing"] + writemsg("ERROR: COUNTER file missing from '%s'.\n" % catpkg) + counters[catpkg] = -1 + else: + try: + counters[catpkg] = long(open(pkgdir+"COUNTER").read().strip()) + if counters[catpkg] > real_counter: + writemsg("ERROR: Global counter is lower than the '%s' COUNTER." % catpkg) + real_counter = fix_global_counter(counters[catpkg]) + except SystemExit, e: + raise # This needs to be propogated + except: + bad[catpkg] += ["COUNTER is corrupt"] + counters[catpkg] = -1 + + if "SLOT" not in pkgdirlist: + writemsg("ERROR: SLOT file missing from '%s'.\n" % catpkg) + writemsg(" RE-MERGE this exact package version or unmerge and remerge.\n") + bad[catpkg] += ["SLOT is missing"] + else: + myslot = open(pkgdir+"SLOT").read() + if myslot and myslot[-1]=="\n": + #writemsg("WARN: SLOT file has a newline. '%s'\n" % catpkg) + myslot = myslot[:-1] + if not myslot: + bad[catpkg] += ["SLOT is empty"] + writemsg("ERROR: SLOT file is empty for '%s'.\n" % catpkg) + writemsg(" RE-MERGE this exact package version or unmerge and remerge it.\n") + elif re.search("[^-a-zA-Z0-9\._]", myslot): + bad[catpkg] += ["SLOT is corrupt"] + writemsg("ERROR: SLOT file is corrupt for '%s'.\n" % catpkg) + writemsg(" RE-MERGE this exact package version or unmerge and remerge it.\n") + elif myslot.strip() != myslot: + writemsg("WARN: SLOT file has invalid characters. '%s'\n" % catpkg) + bad[catpkg] += ["SLOT is invalid"] + + if not bad[catpkg]: + del bad[catpkg] + + +actions = {} +writemsg("\n\n") +for catpkg in bad.keys(): + bad[catpkg].sort() + + mystr = "" + for x in bad[catpkg]: + mystr += " "+str(x)+"\n" + + if bad[catpkg] == ["CONTENTS is missing", "SLOT is missing"]: + writemsg("%s: (possibly injected)\n%s\n" % (green(catpkg), mystr)) + actions[catpkg] = ["ignore"] + elif bad[catpkg] == ["SLOT is empty"]: + writemsg("%s: (old package) []\n%s\n" % (yellow(catpkg), mystr)) + actions[catpkg] = ["remerge"] + else: + writemsg("%s: (damaged/invalid) []\n%s\n" % (red(catpkg), mystr)) + actions[catpkg] = ["merge exact"] + +if (len(sys.argv) > 1) and (sys.argv[1] == "--fix"): + writemsg("These are only directions, at the moment.") + for catpkg in actions.keys(): + action = actions[catpkg] + writemsg("We will now '%s' '%s'..." % (action, catpkg)) + #if action == +else: + #writemsg("Run with '--fix' to attempt automatic correction.") + pass + + + + + + + + + + + + + + + + + diff --git a/bin/fixdbentries b/bin/fixdbentries new file mode 100755 index 000000000..a9c3e1844 --- /dev/null +++ b/bin/fixdbentries @@ -0,0 +1,20 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/fixdbentries,v 1.3 2004/10/04 13:56:50 vapier Exp $ + +# Script to adjust the contents of the DB entries after a package move. +# Fairly straight forward... ./movedbentry 'from/here' 'to/here' /over/here + +VAR=$1 +NEW=$2 +SPATH=$3 + +grep -FrZl "${VAR}" "${SPATH}" | +sed "s#${SPATH}[^\d000]\+/CONTENTS\d000##g" | +$XARGS -0 sed -i -e " +s#${VAR}\$#${NEW}#g; +s#${VAR}\([[:space:]]\)#${NEW}\1#g; +s#${VAR}\(-[^a-zA-Z]\)#${NEW}\1#g; +s#${VAR}\([^a-zA-Z0-9-]\)#${NEW}\1#g +" diff --git a/bin/fixpackages b/bin/fixpackages new file mode 100755 index 000000000..f8d1948ac --- /dev/null +++ b/bin/fixpackages @@ -0,0 +1,14 @@ +#!/usr/bin/python +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/fixpackages,v 1.6 2004/10/04 13:56:50 vapier Exp $ + +import os,sys +os.environ["PORTAGE_CALLER"]="fixpackages" +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage + +print +print "Done." +print diff --git a/bin/fowners b/bin/fowners new file mode 100755 index 000000000..cc13372a7 --- /dev/null +++ b/bin/fowners @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/fowners,v 1.6 2004/10/04 13:56:50 vapier Exp $ + +if [ ${#} -lt 2 ] ; then + echo "${0}: at least two arguments needed" + exit 1 +fi + +OWNER="${1}" +shift +for FILE in $*; do + chown "${OWNER}" "${D}${FILE}" +done diff --git a/bin/fperms b/bin/fperms new file mode 100755 index 000000000..ce72126e2 --- /dev/null +++ b/bin/fperms @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/fperms,v 1.6 2004/10/04 13:56:50 vapier Exp $ + +if [ ${#} -lt 2 ] ; then + echo "${0}: at least two arguments needed" + exit 1 +fi + +PERM="${1}" +shift +for FILE in $*; do + chmod "${PERM}" "${D}${FILE}" +done diff --git a/bin/md5check.py b/bin/md5check.py new file mode 100755 index 000000000..e64d54a96 --- /dev/null +++ b/bin/md5check.py @@ -0,0 +1,102 @@ +#!/usr/bin/python -O +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/md5check.py,v 1.4 2004/10/10 10:07:20 carpaski Exp $ + +import os,sys,string +os.environ["PORTAGE_CALLER"]="mirror" +os.environ["FEATURES"]="mirror cvs" +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage +from threading import * +from output import red,green,blue,bold +from random import shuffle +from time import sleep + + +def cstrip(mystr,mychars): + newstr = "" + for x in mystr: + if x not in mychars: + newstr += x + return newstr + +md5_list = {} +bn_list = [] +col_list = [] + +hugelist = [] +for mycp in portage.db["/"]["porttree"].dbapi.cp_all(): + hugelist += portage.db["/"]["porttree"].dbapi.cp_list(mycp) +hugelist.sort() + +for mycpv in hugelist: + pv = string.split(mycpv, "/")[-1] + + newuri = portage.db["/"]["porttree"].dbapi.aux_get(mycpv,["SRC_URI"])[0] + newuri = string.split(newuri) + + digestpath = portage.db["/"]["porttree"].dbapi.findname(mycpv) + digestpath = os.path.dirname(digestpath)+"/files/digest-"+pv + md5sums = portage.digestParseFile(digestpath) + + if md5sums == None: + portage.writemsg("Missing digest: %s\n" % mycpv) + md5sums = {} + + for x in md5sums.keys(): + if x[0] == '/': + del md5sums[x] + + #portage.writemsg("\n\ndigestpath: %s\n" % digestpath) + #portage.writemsg("md5sums: %s\n" % md5sums) + #portage.writemsg("newuri: %s\n" % newuri) + + bn_list = [] + for x in newuri: + if not x: + continue + if (x in [")","(",":","||"]) or (x[-1] == "?"): + # ignore it. :) + continue + x = cstrip(x,"()|?") + if not x: + continue + + mybn = os.path.basename(x) + if mybn not in bn_list: + bn_list += [mybn] + else: + continue + + if mybn not in md5sums.keys(): + portage_util.writemsg("Missing md5sum: %s in %s\n" % (mybn, mycpv)) + else: + if mybn in md5_list.keys(): + if (md5_list[mybn]["MD5"] != md5sums[mybn]["MD5"]) or \ + (md5_list[mybn]["size"] != md5sums[mybn]["size"]): + + # This associates teh md5 with each file. [md5/size] + md5joins = string.split(md5_list[mybn][2],",") + md5joins = string.join(md5joins," ["+md5_list[mybn][0]+"/"+md5_list[mybn][1]+"],") + md5joins += " ["+md5_list[mybn][0]+"/"+md5_list[mybn][1]+"]" + + portage.writemsg("Colliding md5: %s of %s [%s/%s] and %s\n" % (mybn,mycpv,md5sums[mybn][0],md5sums[mybn][1],md5joins)) + col_list += [mybn] + else: + md5_list[mybn][2] += ","+mycpv + else: + md5_list[mybn] = md5sums[mybn]+[mycpv] + del md5sums[mybn] + + #portage.writemsg(str(bn_list)+"\n") + for x in md5sums.keys(): + if x not in bn_list: + portage.writemsg("Extra md5sum: %s in %s\n" % (x, mycpv)) + + +print col_list +print +print str(len(md5_list.keys()))+" unique distfile md5s." +print str(len(bn_list))+" unique distfile names." diff --git a/bin/md5check.sh b/bin/md5check.sh new file mode 100755 index 000000000..a4f9f3fda --- /dev/null +++ b/bin/md5check.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/md5check.sh,v 1.2 2004/10/04 13:56:50 vapier Exp $ + +# pipe in the data. + +sort -u - > md5check.tmp +grep '^Extra' md5check.tmp > md5check.tmp.extra +grep '^Missing' md5check.tmp > md5check.tmp.missing +grep '^Coll' md5check.tmp > md5check.tmp.colliding + +sed -i " +s:^Col:\nCol: +s:,:\n :g +s: of :\n :g +s: and :\n :g" md5check.tmp.colliding +sed -i "s/^[^ ]\+ md5sum: \(.*\) in \(.*\)$/ \2: \1/g" md5check.tmp.missing +sed -i "s/^[^ ]\+ md5sum: \(.*\) in \(.*\)$/ \2: \1/g" md5check.tmp.extra + +#echo "Colliding files:" > md5check.colliding +#sort -u md5check.tmp.colliding >> md5check.colliding +cp md5check.tmp.colliding md5check.colliding + +echo "Missing from digest:" > md5check.missing +sort -u md5check.tmp.missing >> md5check.missing + +echo "Extra files in digest:" > md5check.extra +sort -u md5check.tmp.extra >> md5check.extra + +rm md5check.tmp* diff --git a/bin/mirror.py b/bin/mirror.py new file mode 100755 index 000000000..1e08574a4 --- /dev/null +++ b/bin/mirror.py @@ -0,0 +1,167 @@ +#!/usr/bin/python -O +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/mirror.py,v 1.3 2004/10/10 10:07:20 carpaski Exp $ + +# Defines the number of threads carrying out the downloading. +maxsems=5 + +import os,sys,string +os.environ["PORTAGE_CALLER"]="mirror" +os.environ["FEATURES"]="mirror cvs" +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage +from threading import * +from output import red,green,blue,bold +from random import shuffle +from time import sleep + + +def cstrip(mystr,mychars): + newstr = "" + for x in mystr: + if x not in mychars: + newstr += x + return newstr + +class fetcher(Thread): + def __init__(self, filename, urilist, dest, md5sum): + self.filename = filename + self.myurilist = urilist + self.myuri = None + self.mydest = dest + self.destpath = self.mydest+"/"+self.filename + self.md5sum = md5sum + self.result = None + Thread.__init__(self) + + def fetch(self): + #print "Started",self.filename + sys.stderr.write(".") + sys.stderr.flush() + portage.spawn("wget -q -P "+str(self.mydest)+" "+self.myuri, free=1) + + def finished(self): + if os.path.exists(self.destpath) and self.md5sum: + ok,reason = portage_checksum.verify_all(self.destpath, md5sum) + if not ok: + portage_util.writemsg("Failed verification:" + reason + "\n") + return 1 + return 0 + + def delete(self): + if os.path.exists(self.destpath): + #print "Unlink:",self.destpath + os.unlink(self.destpath) + + def run(self): + if not self.finished(): + self.delete() + + while not self.finished(): + if self.myurilist: + self.myuri = self.myurilist.pop(0)+"/"+self.filename + self.fetch() + else: + self.delete() + self.result = 0 + #print "Failed:",self.filename + return 1 + + #print "Finished:",self.filename + self.result = 1 + return 0 + + +uri_list = {} +fetchers = [] +fetcher_sem = BoundedSemaphore(value=maxsems) +failures = 0 +successes = 0 + +def clean_fetchers(): + global fetcher_sem,fetchers,uri_list,failures,successes,maxsems + while len(fetchers) == maxsems: + for x in fetchers: + if not x.isAlive(): + failures += (x.result == 0) + successes += (x.result == 1) + if x.filename in uri_list.keys(): + del uri_list[x.filename] + del fetchers[fetchers.index(x)] + fetcher_sem.release() + if len(fetchers) == maxsems: + sleep(1) + + +def start_fetcher(fname, urilist, dest, md5sum): + global fetcher_sem,fetchers,uri_list,failures,successes + fetcher_sem.acquire() + fetchers.append(fetcher(fname, urilist, dest, md5sum)) + fetchers[-1].start() + + +tpm = portage.thirdpartymirrors +destdir = portage.settings["DISTDIR"][:] + +hugelist = [] +for mycp in portage.db["/"]["porttree"].dbapi.cp_all(): + hugelist += portage.db["/"]["porttree"].dbapi.cp_list(mycp) +shuffle(hugelist) + +mycount = -1 +for mycpv in hugelist: + pv = string.split(mycpv, "/")[-1] + + clean_fetchers() + + mycount += 1 + if ((mycount % 20) == 0): + sys.stdout.write("\nCompleted: %s\n" % mycount) + sys.stdout.flush() + newuri = portage.db["/"]["porttree"].dbapi.aux_get(mycpv,["SRC_URI"])[0] + newuri = string.split(newuri) + + digestpath = portage.db["/"]["porttree"].dbapi.findname(mycpv) + digestpath = os.path.dirname(digestpath)+"/files/digest-"+pv + md5sums = portage.digestParseFile(digestpath) + + for x in newuri: + clean_fetchers() + if not x: + continue + if (x in [")","(",":","||"]) or (x[-1] == "?"): + # ignore it. :) + continue + x = cstrip(x,"()|?") + if not x: + continue + mybn = os.path.basename(x) + mydn = os.path.dirname(x) + if mybn not in uri_list.keys(): + if (len(mybn) > len("mirror://")) and (mybn[:len("mirror://")] == "mirror://"): + mysite = string.split(x[len("mirror://"):], "/")[0] + shuffle(tpm[mysite]) + uri_list[mybn] = tpm[mysite][:] + else: + uri_list[mybn] = [os.path.dirname(x)] + clean_fetchers() + if (not md5sums) or (mybn not in md5sums.keys()): + start_fetcher(mybn, uri_list[mybn], destdir, None) + else: + start_fetcher(mybn, uri_list[mybn], destdir, md5sums[mybn]) + else: + break + +sys.stderr.write("\n\nWaiting last set\n") +sys.stderr.flush() +while fetchers: + if fetchers[0].isAlive(): + fetchers[0].join() + clean_fetchers() + +print +print +print "Successes:",successes +print "Failures: ",failures diff --git a/bin/newbin b/bin/newbin new file mode 100755 index 000000000..6c7904cd8 --- /dev/null +++ b/bin/newbin @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/newbin,v 1.7 2004/10/04 13:56:50 vapier Exp $ + +if [ -z "${T}" ] || [ -z "${2}" ] ; then + echo "Nothing defined to do." + exit 1 +fi + +rm -rf "${T}/${2}" +cp "${1}" "${T}/${2}" +dobin "${T}/${2}" diff --git a/bin/newconfd b/bin/newconfd new file mode 100755 index 000000000..662b40ede --- /dev/null +++ b/bin/newconfd @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/newconfd,v 1.2 2004/10/04 13:56:50 vapier Exp $ + +if [ -z "${T}" ] || [ -z "${2}" ] ; then + echo "Nothing defined to do." + exit 1 +fi + +rm -rf "${T}/${2}" +cp "${1}" "${T}/${2}" +doconfd "${T}/${2}" diff --git a/bin/newdoc b/bin/newdoc new file mode 100755 index 000000000..a3c43a2ff --- /dev/null +++ b/bin/newdoc @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/newdoc,v 1.7 2004/10/04 13:56:50 vapier Exp $ + +if [ -z "${T}" ] || [ -z "${2}" ] ; then + echo "Nothing defined to do." + exit 1 +fi + +rm -rf "${T}/${2}" +cp "${1}" "${T}/${2}" +dodoc "${T}/${2}" diff --git a/bin/newenvd b/bin/newenvd new file mode 100755 index 000000000..0ceec650f --- /dev/null +++ b/bin/newenvd @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/newenvd,v 1.2 2004/10/04 13:56:50 vapier Exp $ + +if [ -z "${T}" ] || [ -z "${2}" ] ; then + echo "Nothing defined to do." + exit 1 +fi + +rm -rf "${T}/${2}" +cp "${1}" "${T}/${2}" +doenvd "${T}/${2}" diff --git a/bin/newexe b/bin/newexe new file mode 100755 index 000000000..a2585b3f5 --- /dev/null +++ b/bin/newexe @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/newexe,v 1.7 2004/10/04 13:56:50 vapier Exp $ + +if [ -z "${T}" ] || [ -z "${2}" ] ; then + echo "Nothing defined to do." + exit 1 +fi + +rm -rf "${T}/${2}" +cp "${1}" "${T}/${2}" +doexe "${T}/${2}" diff --git a/bin/newinitd b/bin/newinitd new file mode 100755 index 000000000..cb23dd798 --- /dev/null +++ b/bin/newinitd @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/newinitd,v 1.2 2004/10/04 13:56:50 vapier Exp $ + +if [ -z "${T}" ] || [ -z "${2}" ] ; then + echo "Nothing defined to do." + exit 1 +fi + +rm -rf "${T}/${2}" +cp "${1}" "${T}/${2}" +doinitd "${T}/${2}" diff --git a/bin/newins b/bin/newins new file mode 100755 index 000000000..965ff94b3 --- /dev/null +++ b/bin/newins @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/newins,v 1.7 2004/10/04 13:56:50 vapier Exp $ + +if [ -z "${T}" ] || [ -z "${2}" ] ; then + echo "Error: Nothing defined to do." + exit 1 +fi + +rm -rf "${T}/${2}" +cp "${1}" "${T}/${2}" +doins "${T}/${2}" diff --git a/bin/newlib.a b/bin/newlib.a new file mode 100755 index 000000000..3ec62a3e9 --- /dev/null +++ b/bin/newlib.a @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/newlib.a,v 1.7 2004/10/04 13:56:50 vapier Exp $ + +if [ -z "${T}" ] || [ -z "${2}" ] ; then + echo "Error: Nothing defined to do." + exit 1 +fi + +rm -rf "${T}/${2}" +cp "${1}" "${T}/${2}" +dolib.a "${T}/${2}" diff --git a/bin/newlib.so b/bin/newlib.so new file mode 100755 index 000000000..aa9f9a174 --- /dev/null +++ b/bin/newlib.so @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/newlib.so,v 1.7 2004/10/04 13:56:50 vapier Exp $ + +if [ -z "${T}" ] || [ -z "${2}" ] ; then + echo "Error: Nothing defined to do." + exit 1 +fi + +rm -rf "${T}/${2}" +cp "${1}" "${T}/${2}" +dolib.so "${T}/${2}" diff --git a/bin/newman b/bin/newman new file mode 100755 index 000000000..227411a56 --- /dev/null +++ b/bin/newman @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/newman,v 1.7 2004/10/04 13:56:50 vapier Exp $ + +if [ -z "${T}" ] || [ -z "${2}" ] ; then + echo "Nothing defined to do." + exit 1 +fi + +rm -rf "${T}/${2}" +cp "${1}" "${T}/${2}" +doman "${T}/${2}" diff --git a/bin/newsbin b/bin/newsbin new file mode 100755 index 000000000..eadfba220 --- /dev/null +++ b/bin/newsbin @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/newsbin,v 1.7 2004/10/04 13:56:50 vapier Exp $ + +if [ -z "${T}" ] || [ -z "${2}" ] ; then + echo "Nothing defined to do." + exit 1 +fi + +rm -rf "${T}/${2}" +cp "${1}" "${T}/${2}" +dosbin "${T}/${2}" diff --git a/bin/pemerge.py b/bin/pemerge.py new file mode 100755 index 000000000..08de6eda3 --- /dev/null +++ b/bin/pemerge.py @@ -0,0 +1,44 @@ +#!/usr/bin/python -O + +import profile,time,sys,os +sys.path = ["/usr/lib/portage/bin","/usr/lib/portage/pym"]+sys.path + +def clock(): + return time.time() +profile.time.clock = clock + +profile.run("import emerge", os.getcwd()+"/prof") + +class StatsProcesser: + def __init__(self, stats): + self.output = [] + self.last = "" + import sys + sys.stdout = self + stats.print_stats() + sys.stdout = sys.__stdout__ + funcs = ["?"] + for line in self.output: + spline = line.split() + if len(spline) == 6 and spline[0][0].isdigit(): + func = spline[5][spline[5].index("(")+1:-1] + print line + if func not in funcs: + funcs.append(func) + func = "\\(" + func + "\\)" + stats.print_callers(func) + + def write(self, text): + new = self.last + text + new = new.split("\n") + if len(new) > 1: + self.output += new[:-1] + self.last = new[-1] + +import pstats +p = pstats.Stats("prof") +dir(p) +p.sort_stats("time") +p.print_stats() + +sp = StatsProcesser(p) diff --git a/bin/pkgmerge b/bin/pkgmerge new file mode 100755 index 000000000..2bbb5f680 --- /dev/null +++ b/bin/pkgmerge @@ -0,0 +1,59 @@ +#!/usr/bin/python +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/pkgmerge,v 1.8 2004/10/04 13:56:50 vapier Exp $ + +import sys,os,string +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage,xpak + +#build our package digraph + +def digraph_create(digraph,mykey,myprovides=None): + mytbz2=xpak.tbz2(bintree.getname(mykey)) + mydep=mytbz2.getelements("RDEPEND") + digraph.addnode(mykey,myprovides) + mycheck=roottree.depcheck(string.join(mydep," ")) + if mycheck[0]==0: + print "!!! Error: RDEPEND string formatted incorrectly:",mydep + return None + for x in mycheck[1]: + mymatch=bintree.dep_bestmatch(x) + if mymatch=="": + print "!!! Error: can't resolve dependency --",x + return None + if not digraph_create(digraph,mymatch,mykey): + return None + return 1 + +#main program loop +myvirtuals=portage.getvirtuals(portage.root) +roottree=portage.vartree(portage.root,myvirtuals) +bintree=portage.binarytree("/",myvirtuals) +pretend=0 +if len(sys.argv)>=2: + if sys.argv[1]=="--pretend": + print "These are the packages that I would merge, in order:" + pretend=1 + del sys.argv[1] + elif sys.argv[1]=="--help": + print "Usage: pkgmerge [--pretend] pkg1.tbz2 [pkg2.tbz2]..." + sys.exit(1) +for mypkg in sys.argv[1:]: + digraph=portage.digraph() + mytbz2=xpak.tbz2(mypkg) + mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.basename(mypkg)[:-5] + digraph_create(digraph,mykey) + while not digraph.empty(): + mykey=digraph.firstzero() + if not mykey: + print "!!! Error: circular dependencies" + sys.exit(1) + mytbz2=bintree.getname(mykey) + if pretend: + print mytbz2 + else: + portage.pkgmerge(mytbz2,portage.settings["ROOT"]) + digraph.delnode(mykey) + diff --git a/bin/pkgmerge.new b/bin/pkgmerge.new new file mode 100755 index 000000000..66dbe1676 --- /dev/null +++ b/bin/pkgmerge.new @@ -0,0 +1,84 @@ +#!/usr/bin/python +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/pkgmerge.new,v 1.7 2004/10/04 13:56:50 vapier Exp $ + +import os,string,sys +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage,xpak + +#beautiful directed graph functions + +def dig_addnode(digraph,mykey,myprovides): + if not digraph.has_key(mykey): + if myprovides==None: + digraph[mykey]=[0,[]] + else: + digraph[mykey]=[0,[myprovides]] + digraph[myprovides][0]=digraph[myprovides][0]+1 + return + digraph[mykey]=[digraph[mykey][0],digraph[mykey][1].append(myprovides)] + +def dig_delnode(digraph,mykey): + if not digraph.has_key(mykey): + return + for x in digraph[mykey][1]: + digraph[x][0]=digraph[x][0]-1 + del digraph[mykey] + +def dig_firstzero(digraph): + for x in digraph.keys(): + if digraph[x][0]==0: + return x + return None + +#build our package digraph + +def digraph_create(digraph,mykey,myprovides=None): + mytbz2=xpak.tbz2(bintree.getname(mykey)) + mydep=mytbz2.getelements("RDEPEND") + dig_addnode(digraph,mykey,myprovides) + mycheck=roottree.depcheck(string.join(mydep," ")) + if mycheck[0]==0: + print "!!! Error: RDEPEND string formatted incorrectly:",mydep + return None + for x in mycheck[1]: + mymatch=bintree.dep_bestmatch(x) + if mymatch=="": + print "!!! Error: can't resolve dependency --",x + return None + if not digraph_create(digraph,mymatch,mykey): + return None + return 1 + +#main program loop +myvirtuals=portage.getvirtual(portage.root) +roottree=portage.vartree(portage.root,myvirtuals) +bintree=portage.binarytree("/",myvirtuals) +pretend=0 +if len(sys.argv)>=2: + if sys.argv[1]=="--pretend": + print "These are the packages that I would merge, in order:" + pretend=1 + del sys.argv[1] + elif sys.argv[1]=="--help": + print "Usage: pkgmerge [--pretend] pkg1.tbz2 [pkg2.tbz2]..." + sys.exit(1) +for mypkg in sys.argv[1:]: + digraph={} + mytbz2=xpak.tbz2(mypkg) + mykey=mytbz2.getelements("CATEGORY")[0]+"/"+mypkg[:-5] + digraph_create(digraph,mykey) + while (len(digraph)): + mykey=dig_firstzero(digraph) + if not mykey: + print "!!! Error: circular dependencies" + sys.exit(1) + mytbz2=bintree.getname(mykey) + if pretend: + print mytbz2 + else: + portage.pkgmerge(mytbz2) + dig_delnode(digraph,mykey) + diff --git a/bin/pkgname b/bin/pkgname new file mode 100755 index 000000000..22be6f1da --- /dev/null +++ b/bin/pkgname @@ -0,0 +1,17 @@ +#!/usr/bin/python +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/pkgname,v 1.8 2004/10/04 13:56:50 vapier Exp $ + +import sys +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage + +a=portage.pkgsplit(sys.argv[1]) +if a: + print a[0],a[1],a[2][1:] + sys.exit(0) +else: + print '!!! Error: package name is invalid.' + sys.exit(1) diff --git a/bin/portage_gpg_update.sh b/bin/portage_gpg_update.sh new file mode 100755 index 000000000..a20d9bc1b --- /dev/null +++ b/bin/portage_gpg_update.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/portage_gpg_update.sh,v 1.2 2004/10/04 13:56:50 vapier Exp $ + +wget -O - http://www.gentoo.org/proj/en/devrel/roll-call/userinfo.xml | sed 's:.*\(0x[0-9a-fA-F]\+\)[^0-9a-fA-F].*:\1:gp;d' | xargs gpg -vvv --no-default-keyring --no-permission-warning --homedir /usr/portage/metadata --keyring "gentoo.gpg" --keyserver subkeys.pgp.net --recv-keys &> gpg.log diff --git a/bin/portageq b/bin/portageq new file mode 100755 index 000000000..6bd6c402e --- /dev/null +++ b/bin/portageq @@ -0,0 +1,256 @@ +#!/usr/bin/python -O +# Copyright 1999-2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-src/portage/bin/portageq,v 1.13.2.1 2005/04/12 12:23:41 jstubbs Exp $ + +import sys, os +os.environ["PORTAGE_CALLER"] = "portageq" +sys.path = ["/usr/lib/portage/pym"]+sys.path + +import portage,types,string + + +#----------------------------------------------------------------------------- +# +# To add functionality to this tool, add a function below. +# +# The format for functions is: +# +# def function(argv): +# """ +# +# """ +# +# +# "argv" is an array of the command line parameters provided after the command. +# +# Make sure you document the function in the right format. The documentation +# is used to display help on the function. +# +# You do not need to add the function to any lists, this tool is introspective, +# and will automaticly add a command by the same name as the function! +# + + +def has_version(argv): + """ + Return code 0 if it's available, 1 otherwise. + """ + if (len(argv) < 2): + print "ERROR: insufficient parameters!" + sys.exit(2) + try: + mylist=portage.db[argv[0]]["vartree"].dbapi.match(argv[1]) + if mylist: + sys.exit(0) + else: + sys.exit(1) + except KeyError: + sys.exit(1) + + +def best_version(argv): + """ + Returns category/package-version (without .ebuild). + """ + if (len(argv) < 2): + print "ERROR: insufficient parameters!" + sys.exit(2) + try: + mylist=portage.db[argv[0]]["vartree"].dbapi.match(argv[1]) + print portage.best(mylist) + except KeyError: + sys.exit(1) + + +def mass_best_version(argv): + """ []+ + Returns category/package-version (without .ebuild). + """ + if (len(argv) < 2): + print "ERROR: insufficient parameters!" + sys.exit(2) + try: + for pack in argv[1:]: + mylist=portage.db[argv[0]]["vartree"].dbapi.match(pack) + print pack+":"+portage.best(mylist) + except KeyError: + sys.exit(1) + + +def best_visible(argv): + """ []+ + Returns category/package-version (without .ebuild). + """ + if (len(argv) < 2): + print "ERROR: insufficient parameters!" + sys.exit(2) + try: + mylist=portage.db[argv[0]]["porttree"].dbapi.match(argv[1]) + print portage.best(mylist) + except KeyError: + sys.exit(1) + + +def mass_best_visible(argv): + """ []+ + Returns category/package-version (without .ebuild). + """ + if (len(argv) < 2): + print "ERROR: insufficient parameters!" + sys.exit(2) + try: + for pack in argv[1:]: + mylist=portage.db[argv[0]]["porttree"].dbapi.match(pack) + print pack+":"+portage.best(mylist) + except KeyError: + sys.exit(1) + + +def all_best_visible(argv): + """ + Returns all best_visible packages (without .ebuild). + """ + if (len(argv) < 1): + print "ERROR: insufficient parameters!" + + #print portage.db[argv[0]]["porttree"].dbapi.cp_all() + for pkg in portage.db[argv[0]]["porttree"].dbapi.cp_all(): + mybest=portage.best(portage.db[argv[0]]["porttree"].dbapi.match(pkg)) + if mybest: + print mybest + +def match(argv): + """ + Returns \n seperated list of category/package-version + """ + if (len(argv) < 2): + print "ERROR: insufficient parameters!" + sys.exit(2) + try: + print string.join(portage.db[argv[0]]["vartree"].dbapi.match(argv[1]),"\n") + except KeyError: + sys.exit(1) + + +def vdb_path(argv): + """ + Returns the path used for the var(installed) package database for the + set environment/configuration options. + """ + print portage.root+portage.VDB_PATH + +def gentoo_mirrors(argv): + """ + Returns the mirrors set to use in the portage configuration. + """ + print portage.settings["GENTOO_MIRRORS"] + + +def portdir(argv): + """ + Returns the PORTDIR path as defined in the portage configuration. + """ + print portage.settings["PORTDIR"] + + +def config_protect(argv): + """ + Returns the CONFIG_PROTECT paths as defined in the portage configuration. + """ + print portage.settings["CONFIG_PROTECT"] + + +def config_protect_mask(argv): + """ + Returns the CONFIG_PROTECT_MASK paths as defined in the portage configuration. + """ + print portage.settings["CONFIG_PROTECT_MASK"] + + +def portdir_overlay(argv): + """ + Returns the PORTDIR_OVERLAY path as defined in the portage configuration. + """ + print portage.settings["PORTDIR_OVERLAY"] + + +def pkgdir(argv): + """ + Returns the PKGDIR path as defined in the portage configuration. + """ + print portage.settings["PKGDIR"] + + +def distdir(argv): + """ + Returns the DISTDIR path as defined in the portage configuration. + """ + print portage.settings["DISTDIR"] + + +def envvar(argv): + """ + Returns a specific environment variable as exists prior to ebuild.sh. + Similar to: emerge --verbose --info | egrep '^=' + """ + print portage.settings[argv[0]] + + +#----------------------------------------------------------------------------- +# +# DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED! +# + +def usage(): + rev="$Revision: 1.13.2.1 $" + ver=string.split(rev, ' ')[1] + print ">>> Portage information query tool -- version "+ver + print ">>> Usage: portageq [