Merged from trunk 6719:6733
authorFabian Groffen <grobian@gentoo.org>
Tue, 5 Jun 2007 16:37:29 +0000 (16:37 -0000)
committerFabian Groffen <grobian@gentoo.org>
Tue, 5 Jun 2007 16:37:29 +0000 (16:37 -0000)
   +------------------------------------------------------------------------+
   | 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 <parmus@diku.dk> 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
man/ebuild.5
man/make.conf.5
pym/emerge/__init__.py
pym/portage/dbapi/__init__.py
pym/portage/dbapi/bintree.py
pym/portage/dbapi/porttree.py
pym/portage/dbapi/vartree.py
pym/portage/dbapi/virtual.py

index a422ef1e7512a61348cc6e4edbbde8ad4b0c658b..ba311694159e3581c51e8378336d41fdb82370ce 100755 (executable)
-#!@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] <list of pkgs>
-       
-       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}/<CATEGORY>/<PKG-VERSION>/
-         - 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] <list of package atoms>"
+       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)
index 6eafaf177b2d3e221fbf39740b6698637508d28a..134a4deb46882938c784e49e1bf411723b381f3a 100644 (file)
@@ -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 \\
index 492121d85f1b66e9914401df3b0e41f59d5ad342..64bd7bece6134ce7a950841c53f70b70a8158c5e 100644 (file)
@@ -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
index 7ce99f3035802452494c92e95f7b0eb4b52d8c6d..b61eda86016659a39d1fdb9754dafe511bade7f4 100644 (file)
@@ -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()
index ef91d4de1cd553399a2f90b8a99782e4e34fa5d2..f76878ebb026f2c4d2a25cf5b90517dabc0c9151 100644 (file)
@@ -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
index 061a8d8d8eff9f9f7b3d0ee9f355db0cda60d431..31086a5c54e1aa9535e97c13e89b10389f3a4d6c 100644 (file)
@@ -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(
index 6130dd49dfb6853b63c773534ee338a24e66c121..9a26e038e6ff3c0512929f4bedd8710dbaabce10 100644 (file)
@@ -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
index 41147df4d236ce731220e9c23cce5e672899044e..0eea439c40327e934c27e9d8fa787ceeba27a15d 100644 (file)
@@ -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)
index 760bf81a0921a4e0ee1b053d601e5c3080bd5689..055503ab8102a004db6fbc632db052aaafb31b36 100644 (file)
@@ -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