From eb60573e62398268b358e8563a561324a9338ce4 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Tue, 5 Jun 2007 16:37:29 +0000 Subject: [PATCH] Merged from trunk 6719:6733 +------------------------------------------------------------------------+ | 6720 | Make binarytree.prevent_collision() update the Packages | | zmedico | index since it changes the PATH attribute. | |-----------+------------------------------------------------------------| | 6721 | Add a VERSION attribute to the Packages index header and | | zmedico | reject any index with an unsupported version (current | | | supported version is 0). | |-----------+------------------------------------------------------------| | 6722 | Include SHA1 digests in the Packages index. | | zmedico | | |-----------+------------------------------------------------------------| | 6723 | If PORTAGE_BINHOST is defined then use it as a URI | | zmedico | attribute in the Packages index header. | |-----------+------------------------------------------------------------| | 6724 | copyrights.. id? what? | | WarnerBro | | |-----------+------------------------------------------------------------| | 6725 | Use the PORTAGE_BINHOST_HEADER_URI environment variable to | | zmedico | define the URI header field for the Packages index. If the | | | URI header field is defined then the client will use it as | | | a base URI for fetching packages. | |-----------+------------------------------------------------------------| | 6726 | Remove pym/{cache,elog_modules} directory symlinks since | | zmedico | they lead to upgrade/downgrade issues. These modules | | | probably aren't referenced from outside of portage anyway. | | | There's a hack in config.load_best_module() so that | | | cache.* in /etc/portage/modules will first try cache.* and | | | then try portage.cache.* if there's an ImportError. | |-----------+------------------------------------------------------------| | 6727 | Fix broken usage of lstrip in creating the PROFILE header | | zmedico | field. | |-----------+------------------------------------------------------------| | 6728 | For bug #164655, port quickpkg to python and use the | | zmedico | tarfile module for proper handling of symlinks to | | | directories. Thanks to Martin Parm for | | | the initial port. | |-----------+------------------------------------------------------------| | 6729 | Fix typo. | | zmedico | | |-----------+------------------------------------------------------------| | 6730 | Improve support for slot deps atoms given on the command | | zmedico | line. Thanks to Flameeyes for reporting. | |-----------+------------------------------------------------------------| | 6732 | Document EXTRA_ECONF, thanks to Arfrever FTA in bug | | zmedico | #167057. | |-----------+------------------------------------------------------------| | 6733 | Add ECONF_SOURCE to the econf docs. | | zmedico | | +------------------------------------------------------------------------+ svn path=/main/branches/prefix/; revision=6734 --- bin/quickpkg | 328 ++++++++++++++-------------------- man/ebuild.5 | 2 +- man/make.conf.5 | 23 ++- pym/emerge/__init__.py | 7 +- pym/portage/dbapi/__init__.py | 5 + pym/portage/dbapi/bintree.py | 69 +++++-- pym/portage/dbapi/porttree.py | 4 + pym/portage/dbapi/vartree.py | 55 ++++++ pym/portage/dbapi/virtual.py | 5 + 9 files changed, 284 insertions(+), 214 deletions(-) diff --git a/bin/quickpkg b/bin/quickpkg index a422ef1e7..ba3116941 100755 --- a/bin/quickpkg +++ b/bin/quickpkg @@ -1,199 +1,139 @@ -#!@BASH@ +#!@PYTHON@ # Copyright 1999-2007 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Id$ -# This script tries to quickly create a Gentoo binary package using the -# VDB_PATH/category/pkg/* files -# -# Resulting tbz2 file will be created in ${PKGDIR} ... -# default is /usr/portage/packages/All/ - -# not in prefix -#if [[ ${UID} != "0" ]] ; then -# echo "You must run this as root" -# exit 1 -#fi - -# We need to ensure a sane umask for the packages that will be created. -umask 022 - -# We need this portage cruft to be before --help output because -# we utilize some of these vars in the usage info :/ -eval $(portageq envvar -v NOCOLOR PKGDIR PORTAGE_BIN_PATH PORTAGE_NICENESS \ - PORTAGE_PYM_PATH PORTAGE_TMPDIR ROOT) -export PKGDIR PORTAGE_TMPDIR ROOT - -[[ -n ${PORTAGE_NICENESS} ]] && renice $PORTAGE_NICENESS $$ > /dev/null - -# Make sure the xpak module is in PYTHONPATH -export PYTHONPATH=${PORTAGE_PYM_PATH} -export PORTAGE_DB=$(portageq vdb_path) - -version() { - local svnrev='$Rev$' - svnrev=${svnrev#* } - echo "quickpkg-${svnrev% *}" - exit 0 -} -usage() { - cat <<-EOF - Usage: quickpkg [options] - - Options: - -C, --nocolor Disable color output - -x, --debug Run with shell debug turned on - -V, --version Print version and exit - -h, --help This cruft output - - A pkg can be of the form: - - ${PORTAGE_DB}/// - - single depend-type atom ... - if portage can emerge it, quickpkg can make a package - for exact definitions of depend atoms, see ebuild(5) - - Examples: - quickpkg ${PORTAGE_DB}/net-www/apache-1.3.27-r1 - package up apache, just version 1.3.27-r1 - quickpkg apache - package up apache, all versions of apache installed - quickpkg =apache-1.3.27-r1 - quickpkg =apache-1.3.27-r1 - EOF - if [[ -n $1 ]] ; then - echo "" - echo "Unknown arguments: $*" 1>&2 - exit 1 - else - exit 0 - fi -} - -SET_X="no" -while [[ -n $1 ]] ; do - case $1 in - -C|--nocolor) export NOCOLOR="true";; - -x|--debug) SET_X="yes";; - -V|--version) version;; - -h|--help) usage;; - -*) usage "$1";; - *) break;; - esac - shift -done -[[ ${SET_X} == "yes" ]] && set -x - -source "${PORTAGE_BIN_PATH}/isolated-functions.sh" - -# here we make a package given a little info -# $1 = package-name w/version -# $2 = category -do_pkg() { - mkdir -p "${PORTAGE_TMPDIR}/binpkgs" || exit 1 - chmod 0750 "${PORTAGE_TMPDIR}/binpkgs" - MYDIR="${PORTAGE_TMPDIR}/binpkgs/$1" - SRCDIR="${PORTAGE_DB}/$2/$1" - LOG="${PORTAGE_TMPDIR}/binpkgs/$1-quickpkglog" - - ebegin "Building package for $1" - ( - # clean up temp directory - rm -rf "${MYDIR}" - - # get pkg info files - mkdir -p "${MYDIR}"/temp - cp "${SRCDIR}"/* "${MYDIR}"/temp/ - [ -d "${PKGDIR}"/All ] || mkdir -p "${PKGDIR}"/All - local pkg_dest="${PKGDIR}/All/${1}.tbz2" - local pkg_tmp="${PKGDIR}/All/${1}.tbz2.$$" - - # create filelist and a basic tbz2 - gawk '{ - if ($1 != "dir") { - if ($1 == "obj") - NF=NF-2 - else if ($1 == "sym") - NF=NF-3 - } - print - }' "${SRCDIR}"/CONTENTS | cut -f2- -d" " - | sed -e 's:^/:./:' | \ - while read f; do - [ -d "${ROOT}/${f}" ] && [ -h "${ROOT}/${f}" ] && continue - echo "$f" - done > "${MYDIR}"/filelist - tar vjcf "${pkg_tmp}" -C "${ROOT}" --files-from="${MYDIR}"/filelist --no-recursion - - # join together the basic tbz2 and the pkg info files - python -c "import portage.xpak; t=portage.xpak.tbz2('${pkg_tmp}'); t.recompose('${MYDIR}/temp')" - - # move the final binary package to PKGDIR - mv -f "${pkg_tmp}" "${pkg_dest}" - [ -d "${PKGDIR}/$2" ] || mkdir -p "${PKGDIR}/$2" - ( cd "${PKGDIR}/$2" && ln -s ../All/$1.tbz2 ) - - # cleanup again - rm -rf "${MYDIR}" - ) >& "${LOG}" - - if [ -e "${PKGDIR}/All/$1.tbz2" ] ; then - rm -f "${LOG}" - PKGSTATS="${PKGSTATS}"$'\n'"$(einfo $1: $(du -h "${PKGDIR}/All/$1.tbz2" | gawk '{print $1}'))" - eend 0 - else - cat ${LOG} - PKGSTATS="${PKGSTATS}"$'\n'"$(ewarn $1: not created)" - eend 1 - fi -} - -# here we parse the parameters given to use on the cmdline -export PKGERROR="" -export PKGSTATS="" -for x in "$@" ; do - - # they gave us full path - if [ -e "${x}"/CONTENTS ] ; then - x=$(readlink -f $x) - pkg=$(echo ${x} | cut -d/ -f6) - cat=$(echo ${x} | cut -d/ -f5) - do_pkg "${pkg}" "${cat}" - - # lets figure out what they want - else - DIRLIST=$(portageq match "${ROOT}" "${x}") - if [ -z "${DIRLIST}" ] ; then - eerror "Could not find anything to match '${x}'; skipping" - export PKGERROR="${PKGERROR} ${x}" +import errno, signal, sys, os + +def quickpkg_main(options, args, eout): + from portage import dblink, dep_expand, catsplit, isvalidatom, xpak + from portage.util import ensure_dirs + from portage.exception import InvalidData + from portage.dbapi.vartree import tar_contents + import tarfile + import portage + root = portage.settings["ROOT"] + trees = portage.db[root] + vartree = trees["vartree"] + vardb = vartree.dbapi + bintree = trees["bintree"] + if not os.access(bintree.pkgdir, os.W_OK): + eout.eerror("No write access to '%s'" % bintree.pkgdir) + return errno.EACCES + successes = [] + missing = [] + for arg in args: + try: + atom = dep_expand(arg, mydb=vardb, settings=vartree.settings) + except ValueError, e: + # Multiple matches thrown from cpv_expand + eout.eerror("Please use a more specific atom: %s" % \ + " ".join(e.args[0])) + del e + missing.append(arg) continue - fi - - for d in ${DIRLIST} ; do - pkg=$(echo ${d} | cut -d/ -f2) - cat=$(echo ${d} | cut -d/ -f1) - if [ -f "${PORTAGE_DB}/${cat}/${pkg}/CONTENTS" ] ; then - do_pkg ${pkg} ${cat} - elif [ -d "${PORTAGE_DB}/${cat}/${pkg}" ] ; then - ewarn "Package '${cat}/${pkg}' was injected; skipping" - else - eerror "Unhandled case (${cat}/${pkg}) !" - eerror "Please file a bug at http://bugs.gentoo.org/" - exit 10 - fi - done - fi - -done - -if [ -z "${PKGSTATS}" ] ; then - eerror "No packages found" - exit 1 -else - echo $'\n'"$(einfo Packages now in ${PKGDIR}:)${PKGSTATS}" -fi -if [ ! -z "${PKGERROR}" ] ; then - ewarn "The following packages could not be found:" - ewarn "${PKGERROR}" - exit 2 -fi - -exit 0 + except InvalidData, e: + eout.eerror("Invalid atom: %s" % str(e)) + del e + missing.append(arg) + continue + if not isvalidatom(atom): + eout.eerror("Invalid atom: %s" % atom) + missing.append(arg) + continue + matches = vardb.match(atom) + pkgs_for_arg = 0 + for cpv in matches: + bintree.prevent_collision(cpv) + cat, pkg = catsplit(cpv) + dblnk = dblink(cat, pkg, root, + vartree.settings, treetype="vartree", + vartree=vartree) + dblnk.lockdb() + try: + if not dblnk.exists(): + # unmerged by a concurrent process + continue + eout.ebegin("Building package for %s" % cpv) + pkgs_for_arg += 1 + contents = dblnk.getcontents() + xpdata = xpak.xpak(dblnk.dbdir) + binpkg_tmpfile = os.path.join(bintree.pkgdir, + cpv + ".tbz2." + str(os.getpid())) + ensure_dirs(os.path.dirname(binpkg_tmpfile)) + tar = tarfile.open(binpkg_tmpfile, "w:bz2") + tar_contents(contents, root, tar) + tar.close() + xpak.tbz2(binpkg_tmpfile).recompose_mem(xpdata) + finally: + dblnk.unlockdb() + bintree.inject(cpv, filename=binpkg_tmpfile) + binpkg_path = bintree.getname(cpv) + try: + s = os.stat(binpkg_path) + except OSError, e: + # Sanity check, shouldn't happen normally. + eout.eend(1) + eout.eerror(str(e)) + del e + eout.eerror("Failed to create package: '%s'" % binpkg_path) + else: + eout.eend(0) + successes.append((cpv, s.st_size)) + if not pkgs_for_arg: + eout.eerror("Could not find anything " + \ + "to match '%s'; skipping" % arg) + missing.append(arg) + if not successes: + eout.eerror("No packages found") + return 1 + print + eout.einfo("Packages now in '%s':" % bintree.pkgdir) + import math + units = {10:'K', 20:'M', 30:'G', 40:'T', + 50:'P', 60:'E', 70:'Z', 80:'Y'} + for cpv, size in successes: + if not size: + # avoid OverflowError in math.log() + size_str = "0" + else: + power_of_2 = math.log(size, 2) + power_of_2 = 10*int(power_of_2/10) + unit = units.get(power_of_2) + if unit: + size = float(size)/(2**power_of_2) + size_str = "%.1f" % size + if len(size_str) > 4: + # emulate `du -h`, don't show too many sig figs + size_str = str(int(size)) + size_str += unit + else: + size_str = str(size) + eout.einfo("%s: %s" % (cpv, size_str)) + if missing: + print + eout.ewarn("The following packages could not be found:") + eout.ewarn(" ".join(missing)) + return 2 + return os.EX_OK + +if __name__ == "__main__": + usage = "Usage: quickpkg [options] " + from optparse import OptionParser + parser = OptionParser(usage=usage) + options, args = parser.parse_args(sys.argv[1:]) + if not args: + parser.error("no packages atoms given") + # We need to ensure a sane umask for the packages that will be created. + old_umask = os.umask(022) + from portage.output import get_term_size, EOutput + eout = EOutput() + def sigwinch_handler(signum, frame): + lines, eout.term_columns = get_term_size() + signal.signal(signal.SIGWINCH, sigwinch_handler) + try: + retval = quickpkg_main(options, args, eout) + finally: + os.umask(old_umask) + signal.signal(signal.SIGWINCH, signal.SIG_DFL) + sys.exit(retval) diff --git a/man/ebuild.5 b/man/ebuild.5 index 6eafaf177..134a4deb4 100644 --- a/man/ebuild.5 +++ b/man/ebuild.5 @@ -583,7 +583,7 @@ directory. The function will append \fIsource\fR to the \fBDISTDIR\fR variable. \fBeconf\fR \fI[configure options]\fR This is used as a replacement for configure. Performs: .nf -configure \\ +${\fIECONF_SOURCE\fR:-.}/configure \\ \-\-prefix=/usr \\ \-\-host=${CHOST} \\ \-\-mandir=/usr/share/man \\ diff --git a/man/make.conf.5 b/man/make.conf.5 index 492121d85..64bd7bece 100644 --- a/man/make.conf.5 +++ b/man/make.conf.5 @@ -118,6 +118,10 @@ Defines whether or not to ignore short pauses that occur when displaying important informational messages. This variable is unset by default. If it is set to any value pauses are ignored. .TP +\fBEXTRA_ECONF\fR = \fI[configure options string]\fR +Contains additional options that \fBeconf\fR will append to configure +script arguments (see \fBebuild\fR(5)). +.TP \fBFEATURES\fR = \fI"sandbox ccache"\fR Defines actions portage takes by default. These options should not be changed by anyone but developers and/or maintainers. 'sandbox' is an important @@ -322,13 +326,26 @@ Defaults to /usr/portage/packages. This variable defines the directory in which per\-ebuild logs are kept. Logs are created only when this is set and writable. .TP -\fBPORTAGE_BINHOST\fR = \fI"ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon\-xp"\fR +\fBPORTAGE_BINHOST\fR = \fI"ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon\-xp/"\fR This is the host from which portage will grab prebuilt\-binary packages. The list is a single entry specifying the full address of the directory serving the tbz2's for your system. This is only used when running with the get binary pkg options are given to \fBemerge\fR. Review \fBemerge\fR(1) -for more information. Note that it should point to the 'All' directory on -the host that creates the binary packages and not to the root of the \fBPKGDIR\fR. +for more information. For versions of portage less that 2.2, this variable +should point to the 'All' directory on the host that creates the binary +packages and not to the root of the \fBPKGDIR\fR. Starting with portage 2.2, +it should point to a directory containing a 'Packages' index file. If +${PORTAGE_BINHOST}/Packages does not exist then portage will attempt to use +the older protocol. +.TP +\fBPORTAGE_BINHOST_HEADER_URI\fR = \fI"ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon\-xp/"\fR +This variable only makes sense on a system that will serve as a binhost and +build packages for clients. It defines the URI header field for the package +index file which is located at ${PKGDIR}/Packages. Clients that have +\fBPORTAGE_BINHOST\fR properly configured will be able to fetch the index and +use the URI header field as a base URI for fetching binary packages. If the URI +header field is not defined then the client will use it's ${PORTAGE_BINHOST} +setting as the base URI. .TP \fBPORTAGE_COMPRESS\fR = \fI"bzip2"\fR This variable contains the command used to compress documentation during the diff --git a/pym/emerge/__init__.py b/pym/emerge/__init__.py index 7ce99f303..b61eda860 100644 --- a/pym/emerge/__init__.py +++ b/pym/emerge/__init__.py @@ -1081,8 +1081,7 @@ class depgraph: self.blocker_parents.setdefault( tuple(mybigkey), set()).add(myparent) return 1 - if not arg and myroot == self.target_root: - arg = portage.best_match_to_list(mykey, self.args_keys) + # select the correct /var database that we'll be checking against vardbapi = self.trees[myroot]["vartree"].dbapi portdb = self.trees[myroot]["porttree"].dbapi @@ -1094,6 +1093,10 @@ class depgraph: mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi + if not arg and myroot == self.target_root: + cpv_slot = "%s:%s" % (mykey, mydbapi.aux_get(mykey, ["SLOT"])[0]) + arg = portage.best_match_to_list(cpv_slot, self.args_keys) + if myuse is None: self.pkgsettings[myroot].setcpv(mykey, mydb=portdb) myuse = self.pkgsettings[myroot]["USE"].split() diff --git a/pym/portage/dbapi/__init__.py b/pym/portage/dbapi/__init__.py index ef91d4de1..f76878ebb 100644 --- a/pym/portage/dbapi/__init__.py +++ b/pym/portage/dbapi/__init__.py @@ -1,3 +1,8 @@ +# Copyright 1998-2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + + from portage.dep import dep_getslot, dep_getkey, match_from_list from portage.locks import unlockfile from portage.output import red diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py index 061a8d8d8..31086a5c5 100644 --- a/pym/portage/dbapi/bintree.py +++ b/pym/portage/dbapi/bintree.py @@ -1,3 +1,7 @@ +# Copyright 1998-2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + from portage.dep import isvalidatom, isjustname, dep_getkey, match_from_list from portage.dbapi.virtual import fakedbapi from portage.exception import InvalidPackageName, InvalidAtom @@ -126,6 +130,7 @@ class binarytree(object): self.populated = 0 self.tree = {} self._remote_has_index = False + self._remote_base_uri = None self._remotepkgs = None # remote metadata indexed by cpv self.remotepkgs = {} # indexed by tbz2 name (deprecated) self.invalids = [] @@ -133,6 +138,8 @@ class binarytree(object): self._pkg_paths = {} self._all_directory = os.path.isdir( os.path.join(self.pkgdir, "All")) + self._pkgindex_version = 0 + self._pkgindex_hashes = ["MD5","SHA1"] self._pkgindex_file = os.path.join(self.pkgdir, "Packages") self._pkgindex_keys = set(["CPV", "SLOT", "MTIME", "SIZE"]) self._pkgindex_header_keys = set(["ACCEPT_KEYWORDS", "CBUILD", @@ -266,10 +273,14 @@ class binarytree(object): other_cat = portage.xpak.tbz2(dest_path).getfile("CATEGORY") if other_cat: other_cat = other_cat.strip() - self._move_from_all(other_cat + "/" + mypkg) + other_cpv = other_cat + "/" + mypkg + self._move_from_all(other_cpv) + self.inject(other_cpv) """The file may or may not exist. Move it if necessary and update internal state for future calls to getname().""" self._move_to_all(cpv) + if os.path.exists(full_path): + self.inject(cpv) def _move_to_all(self, cpv): """If the file exists, move it. Whether or not it exists, update state @@ -336,8 +347,6 @@ class binarytree(object): dirs.sort() dirs.insert(0, "All") pkgindex = portage.getbinpkg.PackageIndex() - header = pkgindex.header - metadata = pkgindex.packages pf_index = None try: f = open(self._pkgindex_file) @@ -349,6 +358,10 @@ class binarytree(object): finally: f.close() del f + if not self._pkgindex_version_supported(pkgindex): + pkgindex = portage.getbinpkg.PackageIndex() + header = pkgindex.header + metadata = pkgindex.packages update_pkgindex = False for mydir in dirs: for myfile in listdir(os.path.join(self.pkgdir, mydir)): @@ -534,7 +547,12 @@ class binarytree(object): # no timestamp in the header, something's wrong pkgindex = None else: - if local_timestamp != remote_timestamp: + if not self._pkgindex_version_supported(rmt_idx): + writemsg("\n\n!!! Binhost package index version" + \ + " is not supported: '%s'\n" % \ + rmt_idx.header.get("VERSION"), noiselevel=-1) + pkgindex = None + elif local_timestamp != remote_timestamp: rmt_idx.readBody(f) pkgindex = rmt_idx finally: @@ -557,6 +575,7 @@ class binarytree(object): if pkgindex: self._remotepkgs = pkgindex.packages self._remote_has_index = True + self._remote_base_uri = pkgindex.header.get("URI", base_url) self.remotepkgs = {} for cpv in self._remotepkgs: self.dbapi.cpv_inject(cpv) @@ -643,8 +662,9 @@ class binarytree(object): noiselevel=-1) return slot = slot.strip() - from portage.checksum import perform_md5 - md5 = perform_md5(full_path) + from portage.checksum import perform_multiple_checksums + digests = perform_multiple_checksums( + full_path, hashes=self._pkgindex_hashes) self.dbapi.cpv_inject(cpv) self.dbapi._aux_cache.pop(cpv, None) @@ -671,12 +691,13 @@ class binarytree(object): finally: f.close() del f - d = {} + if not self._pkgindex_version_supported(pkgindex): + pkgindex = portage.getbinpkg.PackageIndex() + d = digests d["CPV"] = cpv d["SLOT"] = slot d["MTIME"] = str(long(s.st_mtime)) d["SIZE"] = str(s.st_size) - d["MD5"] = str(md5) rel_path = self._pkg_paths[cpv] # record location if it's non-default if rel_path != cpv + ".tbz2": @@ -719,10 +740,17 @@ class binarytree(object): def _update_pkgindex_header(self, header): portdir = normalize_path(os.path.realpath(self.settings["PORTDIR"])) - profiles_base = os.path.join(portdir, "profiles") + profiles_base = os.path.join(portdir, "profiles") + os.path.sep profile_path = normalize_path(os.path.realpath(self.settings.profile_path)) - profile_path = profile_path.lstrip(profiles_base) + if profile_path.startswith(profiles_base): + profile_path = profile_path[len(profiles_base):] header["PROFILE"] = profile_path + header["VERSION"] = str(self._pkgindex_version) + base_uri = self.settings.get("PORTAGE_BINHOST_HEADER_URI") + if base_uri: + header["URI"] = base_uri + else: + header.pop("URI", None) for k in self._pkgindex_header_keys: v = self.settings.get(k, None) if v: @@ -730,6 +758,16 @@ class binarytree(object): else: header.pop(k, None) + def _pkgindex_version_supported(self, pkgindex): + version = pkgindex.header.get("VERSION") + if version: + try: + if int(version) <= self._pkgindex_version: + return True + except ValueError: + pass + return False + def exists_specific(self, cpv): if not self.populated: self.populate() @@ -803,7 +841,7 @@ class binarytree(object): except (OSError, IOError): pass from urlparse import urljoin - base_url = self.settings["PORTAGE_BINHOST"] + base_url = self._remote_base_uri fcmd = self.settings["RESUMECOMMAND"] if self._remote_has_index: rel_url = self._remotepkgs[pkgname].get("PATH") @@ -817,8 +855,12 @@ class binarytree(object): if success and "strict" in self.settings.features: metadata = self._remotepkgs[pkgname] digests = {} - if "MD5" in metadata: - digests["MD5"] = self._remotepkgs[pkgname]["MD5"] + from portage.checksum import hashfunc_map, verify_all + for k in hashfunc_map: + v = metadata.get(k) + if not v: + continue + digests[k] = v if "SIZE" in metadata: try: digests["size"] = long(self._remotepkgs[pkgname]["SIZE"]) @@ -826,7 +868,6 @@ class binarytree(object): writemsg("!!! Malformed SIZE attribute in remote " + \ "metadata for '%s'\n" % pkgname) if digests: - from portage.checksum import verify_all ok, reason = verify_all(tbz2_path, digests) if not ok: raise portage.exception.DigestException( diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py index 6130dd49d..9a26e038e 100644 --- a/pym/portage/dbapi/porttree.py +++ b/pym/portage/dbapi/porttree.py @@ -1,3 +1,7 @@ +# Copyright 1998-2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + from portage.cache.cache_errors import CacheError from portage.const import REPO_NAME_LOC from portage.data import portage_gid, secpass diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 41147df4d..0eea439c4 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -1,3 +1,7 @@ +# Copyright 1998-2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + from portage.checksum import perform_md5 from portage.const import CACHE_PATH, CONFIG_MEMORY_FILE, PORTAGE_BIN_PATH, \ PRIVATE_PATH, VDB_PATH, EPREFIX @@ -2056,3 +2060,54 @@ class dblink(object): def isregular(self): "Is this a regular package (does it have a CATEGORY file? A dblink can be virtual *and* regular)" return os.path.exists(os.path.join(self.dbdir, "CATEGORY")) + +def tar_contents(contents, root, tar, onProgress=None): + from portage import normalize_path + root = normalize_path(root).rstrip(os.path.sep) + os.path.sep + id_strings = {} + maxval = len(contents) + curval = 0 + if onProgress: + onProgress(maxval, 0) + paths = contents.keys() + paths.sort() + for path in paths: + curval += 1 + try: + lst = os.lstat(path) + except OSError, e: + if e.errno != errno.ENOENT: + raise + del e + if onProgress: + onProgress(maxval, curval) + continue + contents_type = contents[path][0] + if path.startswith(root): + arcname = path[len(root):] + else: + raise ValueError("invalid root argument: '%s'" % root) + live_path = path + if 'dir' == contents_type and \ + not stat.S_ISDIR(lst.st_mode) and \ + os.path.isdir(live_path): + # Even though this was a directory in the original ${D}, it exists + # as a symlink to a directory in the live filesystem. It must be + # recorded as a real directory in the tar file to ensure that tar + # can properly extract it's children. + live_path = os.path.realpath(live_path) + tarinfo = tar.gettarinfo(live_path, arcname) + # store numbers instead of real names like tar's --numeric-owner + tarinfo.uname = id_strings.setdefault(tarinfo.uid, str(tarinfo.uid)) + tarinfo.gname = id_strings.setdefault(tarinfo.gid, str(tarinfo.gid)) + + if stat.S_ISREG(lst.st_mode): + f = file(path) + try: + tar.addfile(tarinfo, f) + finally: + f.close() + else: + tar.addfile(tarinfo) + if onProgress: + onProgress(maxval, curval) diff --git a/pym/portage/dbapi/virtual.py b/pym/portage/dbapi/virtual.py index 760bf81a0..055503ab8 100644 --- a/pym/portage/dbapi/virtual.py +++ b/pym/portage/dbapi/virtual.py @@ -1,3 +1,8 @@ +# Copyright 1998-2007 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + + from portage.dbapi import dbapi from portage import cpv_getkey -- 2.26.2