From: Fabian Groffen Date: Sat, 23 Feb 2008 23:46:25 +0000 (-0000) Subject: Merged from trunk 9351:9372 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=2217d9ed7ba05c28c3d8fd7790abf9144fc872fd;p=portage.git Merged from trunk 9351:9372 | 9352 | Revert back to some known working code from the 2.1.2 | | zmedico | branch. | | 9353 | Use parse_use_local_desc() from the repoman.utilities | | zmedico | module. | | 9354 | Make PreservedLibsRegistry.store() use atomic_ofstream so | | zmedico | that we don't lose the whole registry if an error such as | | | 'out of space' occurs. | | 9355 | Bug #210372 - Fix suidctl.conf parser to look for paths | | zmedico | with a leading slash. | | 9357 | Bug #210449 - Reset exeinto(), docinto(), insinto(), and | | zmedico | into() state variables in case the user is running the | | | install phase multiple times consecutively via the ebuild | | | command. | | 9358 | - outsource logic for boolean options into a central | | genone | function - enable support for greedy behavior in | | | StaticFileSet | | 9359 | For greedy slot behavior, in addition to any installed | | zmedico | slots also try to pull in the latest new slot that may be | | | available. | | 9360 | When showing an unsatisfied dep, never include installed | | zmedico | packages. | | 9361 | Make stack_dicts() treat an empty variable assignment just | | zmedico | like a non-empty assignment. This allows the profile to set | | | and empty variable in make.defaults and have it override a | | | non-empty value as one would expect. | | 9362 | In the circular dependency display, drop PDEPEND (aka | | zmedico | MEDIUM_SOFT) from the graph so there's less noise. | | 9363 | Optimize dblink.isowner() to use fewer stat calls by doing | | zmedico | a basename comparison to try and eliminate the file before | | | resorting to inode comparison. This speeds up the `portageq | | | owners` command as well as the search that is done when | | | collision-protect finds a collision. | | 9364 | Make LibraryPackageMap.update() sort the contents of the | | zmedico | library_consumers cache so that it's nice and orderly. | | 9365 | Bug #211067 - Make the "portdir_overlay" and "mydir" | | zmedico | variables contain paths that are consistent wrt eachother | | | regardless of any path irregularities that can be induced | | | by symlinks. Consistency is achieved by regenerating one of | | | the paths to ensure that both paths have the exact same | | | mapping between inodes and paths. This consistency ensures | | | that the path manipulations used to calculate "repolevel" | | | will work as intended. | | 9367 | Add support for file paths as arguments to emerge. If an | | zmedico | argument starts with / and it's not recognized as a tbz2 or | | | ebuild then we try to find and owner in the vdb and | | | generate a slot atom from it. Thanks to solar for the | | | suggestion. | | 9368 | Revert portdbapi category auto-detection code since it's | | zmedico | not really needed and can cause problems if we need to add | | | new non-category directories in the future. We only really | | | need the category auto-detection for bindbapi and vardbapi | | | anyway. | | 9369 | cleanup main option parsing | | SpankMan | | | 9370 | tighten up output from script | | SpankMan | | | 9371 | add support for lzma/gz snapshots | | SpankMan | | | 9372 | only try to fetch compression schemes which the host | | SpankMan | supports | svn path=/main/branches/prefix/; revision=9375 --- diff --git a/bin/ebuild.sh b/bin/ebuild.sh index 60f5d760b..249855481 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -263,10 +263,6 @@ register_die_hook() { #if no perms are specified, dirs/files will have decent defaults #(not secretive, but not stupid) umask 022 -export DESTTREE=/usr -export INSDESTTREE="" -export _E_EXEDESTTREE_="" -export _E_DOCDESTTREE_="" export INSOPTIONS="-m0644" export EXEOPTIONS="-m0755" export LIBOPTIONS="-m0644" @@ -986,6 +982,15 @@ dyn_install() { #some packages uses an alternative to $S to build in, cause #our libtool to create problematic .la files export PWORKDIR="$WORKDIR" + + # Reset exeinto(), docinto(), insinto(), and into() state variables + # in case the user is running the install phase multiple times + # consecutively via the ebuild command. + export DESTTREE=/usr + export INSDESTTREE="" + export _E_EXEDESTTREE_="" + export _E_DOCDESTTREE_="" + ebuild_phase src_install touch "${PORTAGE_BUILDDIR}/.installed" vecho ">>> Completed installing ${PF} into ${ED}" diff --git a/bin/emerge-webrsync b/bin/emerge-webrsync index 37c727260..0910bd939 100755 --- a/bin/emerge-webrsync +++ b/bin/emerge-webrsync @@ -1,5 +1,5 @@ #!@BASH@ -# Copyright 1999-2006 Gentoo Foundation +# Copyright 1999-2008 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Id$ # Author: Karl Trygve Kalleberg @@ -7,6 +7,10 @@ # Author: Alon Bar-Lev # Major rewrite from Karl's scripts. +# TODO: +# - all output should prob be converted to e* funcs +# - add support for ROOT + # # gpg key import # KEY_ID=0x7DDAD20D @@ -14,7 +18,20 @@ # gpg --homedir /etc/portage/gnupg --edit-key $KEY_ID trust # -type portageq > /dev/null || exit $? +# Only echo if in verbose mode +vvecho() { [[ ${do_verbose} -eq 1 ]] && echo "$@" ; } +# Only echo if not in verbose mode +nvecho() { [[ ${do_verbose} -eq 0 ]] && echo "$@" ; } +# warning echos +wecho() { echo "${argv0}: warning: $*" 1>&2 ; } +# error echos +eecho() { echo "${argv0}: error: $*" 1>&2 ; } + +argv0=$0 +if ! type portageq > /dev/null ; then + eecho "could not find 'portageq'; aborting" + exit 1 +fi eval $(portageq envvar -v FEATURES FETCHCOMMAND GENTOO_MIRRORS \ PORTAGE_BIN_PATH PORTAGE_GPG_DIR PORTAGE_INST_UID PORTAGE_INST_GID \ PORTAGE_NICENESS PORTAGE_RSYNC_EXTRA_OPTS PORTAGE_TMPDIR PORTDIR \ @@ -31,6 +48,7 @@ fi source "${PORTAGE_BIN_PATH}"/isolated-functions.sh || exit 1 do_verbose=0 +do_debug=0 if hasq webrsync-gpg ${FEATURES} ; then WEBSYNC_VERIFY_SIGNATURE=1 @@ -38,10 +56,24 @@ else WEBSYNC_VERIFY_SIGNATURE=0 fi if [ ${WEBSYNC_VERIFY_SIGNATURE} != 0 -a -z "${PORTAGE_GPG_DIR}" ]; then - echo "Error: Please set PORTAGE_GPG_DIR in make.conf" + eecho "please set PORTAGE_GPG_DIR in make.conf" exit 1 fi +do_tar() { + local file=$1; shift + local decompressor + case ${file} in + *.lzma) decompressor="lzcat" ;; + *.bz2) decompressor="bzcat" ;; + *.gz) decompressor="zcat" ;; + *) decompressor="cat" ;; + esac + ${decompressor} "${file}" | tar "$@" + _pipestatus=${PIPESTATUS[*]} + [[ ${_pipestatus// /} -eq 0 ]] +} + get_utc_date_in_seconds() { date -u +"%s" } @@ -78,25 +110,17 @@ fetch_file() { local opts if [ "${FETCHCOMMAND/wget/}" != "${FETCHCOMMAND}" ]; then - opts="--continue" - - [ "${do_verbose}" == 0 ] && opts="$opts -q" + opts="--continue $(nvecho -q)" elif [ "${FETCHCOMMAND/curl/}" != "${FETCHCOMMAND}" ]; then - opts="--continue-at -" - - [ "${do_verbose}" == 0 ] && opts="$opts -s -f" + opts="--continue-at - $(nvecho -s -f)" else rm -f "${FILE}" fi - echo "Fetching file ${FILE}..." - - #already set DISTDIR= - if [ "${do_verbose}" == 0 ] ; then - eval "${FETCHCOMMAND}" ${opts} > /dev/null && [ -s "${FILE}" ] - else - eval "${FETCHCOMMAND}" ${opts} && [ -s "${FILE}" ] - fi + vecho "Fetching file ${FILE} ..." + # already set DISTDIR= + eval "${FETCHCOMMAND}" ${opts} + [ -s "${FILE}" ] } check_file_digest() { @@ -104,15 +128,14 @@ check_file_digest() { local file="$2" local r=1 - echo "Checking digest..." + vecho "Checking digest ..." if type -P md5sum > /dev/null; then md5sum -c $digest && r=0 elif type -P md5 > /dev/null; then [ "$(md5 -q $file)" == "$(cut -d \ -f 1 \"$digest\")" ] && r=0 else - echo "Error: Cannot check digest" - echo "No suitable md5/md5sum binaries found" + eecho "cannot check digest: no suitable md5/md5sum binaries found" fi return "${r}" @@ -125,13 +148,12 @@ check_file_signature() { if [ ${WEBSYNC_VERIFY_SIGNATURE} != 0 ]; then - echo "Checking signature..." + vecho "Checking signature ..." if type -p gpg > /dev/null; then gpg --homedir "${PORTAGE_GPG_DIR}" --verify "$signature" "$file" && r=0 else - echo "Error: Cannot check signature" - echo "gpg binary not found" + eecho "cannot check signature: gpg binary not found" fi else r=0 @@ -143,27 +165,22 @@ check_file_signature() { get_snapshot_timestamp() { local file="$1" - tar --to-stdout -xf "${file}" portage/metadata/timestamp.x | cut -f 1 -d " " + do_tar "${file}" --to-stdout -xf - portage/metadata/timestamp.x | cut -f 1 -d " " } sync_local() { local file="$1" - echo "Syncing local tree..." + vecho "Syncing local tree ..." if type -P tarsync &> /dev/null; then - if [ "${do_verbose}" != 0 ] ; then - tarsync_verbose=-v - fi - if ! tarsync $tarsync_verbose -s 1 -o portage -g portage -e /distfiles -e /packages -e /local "${file}" "${PORTDIR}"; then - echo "Error: tarsync failed; tarball is corrupt? (${file})" + if ! tarsync $(vvecho -v) -s 1 -o portage -g portage -e /distfiles -e /packages -e /local "${file}" "${PORTDIR}"; then + eecho "tarsync failed; tarball is corrupt? (${file})" return 1 fi else - echo "Note: tarsync was not found, you may consider emerge it..." - - if ! tar jxf "${file}"; then - echo "Error: tar failed to extract the image. tarball is corrupt? (${file})" + if ! do_tar "${file}" xf -; then + eecho "tar failed to extract the image. tarball is corrupt? (${file})" rm -fr portage return 1 fi @@ -179,12 +196,12 @@ sync_local() { --exclude='/local' ${PORTAGE_RSYNC_EXTRA_OPTS} . "${PORTDIR%%/}" cd .. - echo "Cleaning up..." + vecho "Cleaning up ..." rm -fr portage fi if hasq metadata-transfer ${FEATURES} ; then - echo "Updating cache..." + vecho "Updating cache ..." emerge --metadata fi [ -x "${EPREFIX}"/etc/portage/bin/post_sync ] && "${EPREFIX}"/etc/portage/bin/post_sync @@ -197,76 +214,92 @@ do_snapshot() { local r=1 - local file="portage-${date}.tar.bz2" - local digest="${file}.md5sum" - local signature="${file}.gpgsig" + local base_file="portage-${date}.tar" local have_files=0 local mirror - echo "Trying to retrieve ${date} snapshot..." + local compressions="" + type lzcat > /dev/null && compressions="${compressions} lzma" + type bzcat > /dev/null && compressions="${compressions} bz2" + type zcat > /dev/null && compressions="${compressions} gz" + if [[ -z ${compressions} ]] ; then + eecho "unable to locate any decompressors (lzcat or bzcat or zcat)" + exit 1 + fi for mirror in ${GENTOO_MIRRORS} ; do - [ -s "${file}" -a -s "${digest}" -a -s "${signature}" ] && \ - check_file_digest "${digest}" "${file}" && \ - check_file_signature "${signature}" "${file}" && \ - have_files=1 - - [ ${have_files} == 0 ] && \ - fetch_file "${mirror}/snapshots/${digest}" "${digest}" && \ - fetch_file "${mirror}/snapshots/${signature}" "${signature}" && \ - fetch_file "${mirror}/snapshots/${file}" "${file}" && \ - check_file_digest "${digest}" "${file}" && \ - check_file_signature "${signature}" "${file}" && \ - have_files=1 - - # - # If timestamp is invalid - # we want to try and retieve - # from a different mirror - # - if [ ${have_files} != 0 ]; then - - echo "Getting snapshot timetasmp..." - local snapshot_timestamp=$(get_snapshot_timestamp "${file}") - - if [ ${ignore_timestamp} == 0 ]; then - if [ ${snapshot_timestamp} -lt $(get_portage_timestamp) ]; then - echo "Warning: Portage is newer than snapshot" - have_files=0 - fi - else - local utc_seconds=$(get_utc_second_from_string "${date}") + vecho "Trying to retrieve ${date} snapshot from ${mirror} ..." - # - # Check that this snapshot - # is what it claims to be... - # - if [ ${snapshot_timestamp} -lt ${utc_seconds} ] || \ - [ ${snapshot_timestamp} -gt $((${utc_seconds}+ 2*86400)) ]; then + for compression in ${compressions} ; do + local file="portage-${date}.tar.${compression}" + local digest="${file}.md5sum" + local signature="${file}.gpgsig" - echo "Warning: Snapshot timestamp is not in acceptable period." - have_files=0 - fi + if [ -s "${file}" -a -s "${digest}" -a -s "${signature}" ] ; then + check_file_digest "${digest}" "${file}" && \ + check_file_signature "${signature}" "${file}" && \ + have_files=1 + fi + + if [ ${have_files} -eq 0 ] ; then + fetch_file "${mirror}/snapshots/${digest}" "${digest}" && \ + fetch_file "${mirror}/snapshots/${signature}" "${signature}" && \ + fetch_file "${mirror}/snapshots/${file}" "${file}" && \ + check_file_digest "${digest}" "${file}" && \ + check_file_signature "${signature}" "${file}" && \ + have_files=1 fi - fi - if [ ${have_files} != 0 ]; then - break; - else # - # Remove files and use - # a diffeernt mirror + # If timestamp is invalid + # we want to try and retrieve + # from a different mirror # - rm -f "${file}" "${digest}" "${signature}" - fi + if [ ${have_files} -eq 1 ]; then + + vecho "Getting snapshot timetasmp ..." + local snapshot_timestamp=$(get_snapshot_timestamp "${file}") + + if [ ${ignore_timestamp} == 0 ]; then + if [ ${snapshot_timestamp} -lt $(get_portage_timestamp) ]; then + wecho "portage is newer than snapshot" + have_files=0 + fi + else + local utc_seconds=$(get_utc_second_from_string "${date}") + + # + # Check that this snapshot + # is what it claims to be ... + # + if [ ${snapshot_timestamp} -lt ${utc_seconds} ] || \ + [ ${snapshot_timestamp} -gt $((${utc_seconds}+ 2*86400)) ]; then + + wecho "snapshot timestamp is not in acceptable period" + have_files=0 + fi + fi + fi + + if [ ${have_files} -eq 1 ]; then + break + else + # + # Remove files and use a different mirror + # + rm -f "${file}" "${digest}" "${signature}" + fi + done + + [ ${have_files} -eq 1 ] && break done - if [ ${have_files} != 0 ]; then + if [ ${have_files} -eq 1 ]; then sync_local "${file}" && r=0 else - echo "Warning: ${date} snapshot was not found." + vecho "${date} snapshot was not found" fi rm -f "${file}" "${digest}" "${signature}" @@ -277,7 +310,7 @@ do_latest_snapshot() { local attempts=-1 local r=1 - echo "Fetching most recent snapshot..." + vecho "Fetching most recent snapshot ..." while (( ${attempts} < 40 )) ; do local day @@ -295,10 +328,9 @@ do_latest_snapshot() { utc_midnight=$(get_date_part $(expr ${utc_attempt} - ${utc_attempt} % 86400) "%s") if [ ${utc_midnight} -lt $(($(get_portage_timestamp)-86400)) ]; then - echo "Note: Portage content is newer than available snapshots" - echo "use --revert option to overide." + wecho "portage content is newer than available snapshots (use --revert option to overide)" r=0 - break; + break fi if do_snapshot 0 "${year}${month}${day}"; then @@ -310,42 +342,50 @@ do_latest_snapshot() { return "${r}" } +usage() { + cat <<-EOF + Usage: $0 [options] + + Options: + --revert=yyyymmdd Revert to snapshot + -q, --quiet Only output errors + -v, --verbose Enable verbose output + -x, --debug Enable debug output + -h, --help This help screen (duh!) + EOF + if [[ -n $* ]] ; then + printf "\nError: %s\n" "$*" 1>&2 + exit 1 + else + exit 0 + fi +} + main() { local arg - local do_revert=0 local revert_date [ ! -d "${DISTDIR}" ] && mkdir -p "${DISTDIR}" cd "${DISTDIR}" - for arg in $*; do + for arg in "$@" ; do local v=${arg#*=} case ${arg} in - --help) - echo "usage: $0 [options]" - echo " --verbose (-v) - verbose" - echo " --revert=yyyymmdd - revert to snapshot" - exit 0 - ;; - --verbose|-v) - do_verbose=1 - ;; - --revert=*) - do_revert=1 - revert_date=${v} - ;; - *) - echo "Error: Invalid arguments" - exit 1 - ;; + -h|--help) usage ;; + -q|--quiet) PORTAGE_QUIET=1 ;; + -v|--verbose) do_verbose=1 ;; + -x|--debug) do_debug=1 ;; + --revert=*) revert_date=${v} ;; + *) usage "Invalid option '${arg}'" ;; esac done + [[ ${do_debug} -eq 1 ]] && set -x - if [ ${do_revert} != 0 ]; then + if [[ -n ${revert_date} ]] ; then do_snapshot 1 "${revert_date}" else do_latest_snapshot fi } -main $* +main "$@" diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh index 197f79be3..891d6ef8c 100644 --- a/bin/misc-functions.sh +++ b/bin/misc-functions.sh @@ -592,7 +592,7 @@ preinst_suid_scan() { #note not space-safe for i in $(find "${ED}" -type f \( -perm -4000 -o -perm -2000 \) ); do if [ -s "${sfconf}" ]; then - suid="$(grep "^${i/${D}}$" "${sfconf}")" + suid="$(grep "^/${i#${D}}$" "${sfconf}")" if [ "${suid}" = "${i/${D}}" ]; then vecho "- ${i/${D}} is an approved suid file" else diff --git a/bin/repoman b/bin/repoman index ae1dc01d3..43b118d4f 100755 --- a/bin/repoman +++ b/bin/repoman @@ -7,6 +7,7 @@ # Then, check to make sure deps are satisfiable (to avoid "can't find match for" problems) # that last one is tricky because multiple profiles need to be checked. +import commands import codecs import errno import formatter @@ -491,6 +492,9 @@ repodir = startdir for x in range(0, repolevel - 1): repodir = os.path.dirname(repodir) +def caterror(mycat): + err(mycat+" is not an official category. Skipping QA checks in this directory.\nPlease ensure that you add "+catdir+" to "+repodir+"/profiles/categories\nif it is a new category.") + # retreive local USE list luselist={} try: @@ -506,7 +510,7 @@ if portdir_overlay != portdir: if os.path.exists(filename): try: f = open(filename) - parse_use_local_desc(f, luselist) + utilities.parse_use_local_desc(f, luselist) f.close() except (IOError, OSError, ParseError), e: logging.exception("Couldn't read from '%s'" % filename, e) @@ -546,8 +550,34 @@ if portdir_overlay != portdir: kwlist.update(portage.grabfile( os.path.join(portdir_overlay, "profiles", "arch.list"))) -scanlist = utilities.FindPackagesToScan(repoman_settings, startdir, reposplit) +scanlist=[] +if repolevel==2: + #we are inside a category directory + catdir=reposplit[-1] + if catdir not in repoman_settings.categories: + caterror(catdir) + mydirlist=os.listdir(startdir) + for x in mydirlist: + if x == "CVS" or x.startswith("."): + continue + if os.path.isdir(startdir+"/"+x): + scanlist.append(catdir+"/"+x) +elif repolevel==1: + for x in repoman_settings.categories: + if not os.path.isdir(startdir+"/"+x): + continue + for y in os.listdir(startdir+"/"+x): + if y == "CVS" or y.startswith("."): + continue + if os.path.isdir(startdir+"/"+x+"/"+y): + scanlist.append(x+"/"+y) +elif repolevel==3: + catdir = reposplit[-2] + if catdir not in repoman_settings.categories: + caterror(catdir) + scanlist.append(catdir+"/"+reposplit[-1]) scanlist.sort() + logging.debug("Found the following packages to scan:\n%s" % '\n'.join(scanlist)) profiles={} diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index f2015dfbf..a87aa4515 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -1456,6 +1456,7 @@ class depgraph(object): self._reinstall_nodes = {} self.mydbapi = {} self.trees = {} + self._trees_orig = trees self.roots = {} # Contains a filtered view of preferred packages that are selected # from available repositories. @@ -2150,6 +2151,35 @@ class depgraph(object): cpv=mykey, metadata=metadata, onlydeps=onlydeps) args.append(PackageArg(arg=x, package=pkg, root_config=root_config)) + elif x.startswith(os.path.sep): + if not x.startswith(myroot): + portage.writemsg(("\n\n!!! '%s' does not start with" + \ + " $ROOT.\n") % x, noiselevel=-1) + return 0, [] + relative_path = x[len(myroot):] + vartree = self._trees_orig[myroot]["vartree"] + owner_cpv = None + for cpv in vardb.cpv_all(): + self.spinner.update() + cat, pf = portage.catsplit(cpv) + if portage.dblink(cat, pf, myroot, + pkgsettings, vartree=vartree).isowner( + relative_path, myroot): + owner_cpv = cpv + break + if owner_cpv is None: + portage.writemsg(("\n\n!!! '%s' is not claimed " + \ + "by any package.\n") % x, noiselevel=-1) + return 0, [] + slot = vardb.aux_get(owner_cpv, ["SLOT"])[0] + if not slot: + # portage now masks packages with missing slot, but it's + # possible that one was installed by an older version + atom = portage.cpv_getkey(owner_cpv) + else: + atom = "%s:%s" % (portage.cpv_getkey(owner_cpv), slot) + args.append(AtomArg(arg=atom, atom=atom, + root_config=root_config)) else: if x in ("system", "world"): x = SETPREFIX + x @@ -2520,6 +2550,8 @@ class depgraph(object): portdb = self.roots[root].trees["porttree"].dbapi dbs = self._filtered_trees[root]["dbs"] for db, pkg_type, built, installed, db_keys in dbs: + if installed: + continue match = db.match if hasattr(db, "xmatch"): cpv_list = db.xmatch("match-all", atom) @@ -3352,7 +3384,7 @@ class depgraph(object): # have no parents and thus can not be part of a cycle. while True: root_nodes = mygraph.root_nodes( - ignore_priority=DepPriority.SOFT) + ignore_priority=DepPriority.MEDIUM_SOFT) if not root_nodes: break for node in root_nodes: diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py index e9fad0956..1937c4e11 100644 --- a/pym/portage/dbapi/porttree.py +++ b/pym/portage/dbapi/porttree.py @@ -27,9 +27,6 @@ from itertools import izip class portdbapi(dbapi): """this tree will scan a portage directory located at root (passed to init)""" portdbapi_instances = [] - _non_category_dirs = ["distfiles", "eclass", "licenses", - "local", "metadata", "packages", "profiles", "scripts"] - _non_category_dirs = re.compile(r'^(%s)$' % "|".join(_non_category_dirs)) def __init__(self, porttree_root, mysettings=None): portdbapi.portdbapi_instances.append(self) @@ -39,6 +36,7 @@ class portdbapi(dbapi): else: from portage import settings self.mysettings = config(clone=settings) + self._categories = set(self.mysettings.categories) # This is strictly for use in aux_get() doebuild calls when metadata # is generated by the depend phase. It's safest to use a clone for # this purpose because doebuild makes many changes to the config @@ -486,11 +484,8 @@ class portdbapi(dbapi): def cp_all(self): "returns a list of all keys in our tree" d = {} - for oroot in self.porttrees: - for x in listdir(oroot, EmptyOnError=1, ignorecvs=1, dirsonly=1): - if not self._category_re.match(x) or \ - self._non_category_dirs.match(x): - continue + for x in self.mysettings.categories: + for oroot in self.porttrees: for y in listdir(oroot+"/"+x, EmptyOnError=1, ignorecvs=1, dirsonly=1): if not self._pkg_dir_name_re.match(y) or \ y == "CVS": @@ -520,7 +515,7 @@ class portdbapi(dbapi): self.xcache["match-all"][mycp] = cachelist return cachelist[:] mysplit = mycp.split("/") - invalid_category = not self._category_re.match(mysplit[0]) + invalid_category = mysplit[0] not in self._categories d={} if mytree: mytrees = [mytree] diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index d3ecacee0..6f5f3c9e0 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -63,8 +63,10 @@ class PreservedLibsRegistry(object): """ Store the registry data to file. No need to call this if autocommit was enabled. """ - cPickle.dump(self._data, open(self._filename, "w")) - + f = atomic_ofstream(self._filename) + cPickle.dump(self._data, f) + f.close() + def register(self, cpv, slot, counter, paths): """ Register new objects in the registry. If there is a record with the same packagename (internally derived from cpv) and slot it is @@ -160,7 +162,8 @@ class LibraryPackageMap(object): else: obj_dict[lib].append(mysplit[0]) mapfile = open(self._filename, "w") - for lib in obj_dict: + for lib in sorted(obj_dict): + obj_dict[lib].sort() mapfile.write(lib+" "+",".join(obj_dict[lib])+"\n") mapfile.close() @@ -909,6 +912,7 @@ class dblink(object): self._installed_instance = None self.contentscache = None self._contents_inodes = None + self._contents_basenames = None def lockdb(self): if self._lock_vdb: @@ -1510,6 +1514,16 @@ class dblink(object): if pkgfiles and destfile in pkgfiles: return True if pkgfiles: + basename = os.path.basename(destfile) + if self._contents_basenames is None: + self._contents_basenames = set( + os.path.basename(x) for x in pkgfiles) + if basename not in self._contents_basenames: + # This is a shortcut that, in most cases, allows us to + # eliminate this package as an owner without the need + # to examine inode numbers of parent directories. + return False + # Use stat rather than lstat since we want to follow # any symlinks to the real parent directory. parent_path = os.path.dirname(destfile) @@ -1545,7 +1559,6 @@ class dblink(object): p_path_list = self._contents_inodes.get( (parent_stat.st_dev, parent_stat.st_ino)) if p_path_list: - basename = os.path.basename(destfile) for p_path in p_path_list: x = os.path.join(p_path, basename) if x in pkgfiles: @@ -2101,6 +2114,7 @@ class dblink(object): for dblnk in others_in_slot: dblnk.contentscache = None dblnk._contents_inodes = None + dblnk._contents_basenames = None # If portage is reinstalling itself, remove the old # version now since we want to use the temporary diff --git a/pym/portage/sets/__init__.py b/pym/portage/sets/__init__.py index 5f82b69b7..39cebdf84 100644 --- a/pym/portage/sets/__init__.py +++ b/pym/portage/sets/__init__.py @@ -9,6 +9,16 @@ from portage.const import USER_CONFIG_PATH, GLOBAL_CONFIG_PATH SETPREFIX = "@" +def get_boolean(options, name, default): + if not name in options: + return default + elif options[name].lower() in ("1", "yes", "on", "true"): + return True + elif options[name].lower() in ("0", "no", "off", "false"): + return False + else: + raise SetConfigError("invalid value '%s' for option '%s'" % (options[name], name)) + class SetConfigError(Exception): pass diff --git a/pym/portage/sets/dbapi.py b/pym/portage/sets/dbapi.py index 220ff2283..c4f974aa9 100644 --- a/pym/portage/sets/dbapi.py +++ b/pym/portage/sets/dbapi.py @@ -4,7 +4,7 @@ from portage.versions import catsplit, catpkgsplit from portage.sets.base import PackageSet -from portage.sets import SetConfigError +from portage.sets import SetConfigError, get_boolean from portage.dbapi.vartree import dblink from portage.util import grabfile @@ -65,10 +65,7 @@ class CategorySet(PackageSet): _builderGetRepository = classmethod(_builderGetRepository) def _builderGetVisible(cls, options): - visible = options.get("only_visible", "true").lower() - if visible not in ["1", "0", "yes", "no", "true", "false", "on", "off"]: - raise SetConfigError("invalid value for only_visible: %s" % visible) - return bool(visible in ["1", "yes", "true", "on"]) + return get_boolean(options, "only_visible", True) _builderGetVisible = classmethod(_builderGetVisible) def singleBuilder(cls, options, settings, trees): @@ -176,9 +173,6 @@ class MissingLibraryConsumerSet(LibraryConsumerSet): self._setAtoms(self.mapPathsToAtoms(consumers)) def singleBuilder(cls, options, settings, trees): - if options.get("debug", "true").lower() in ["true", "on", "1", "yes"]: - debug = True - else: - debug = False + debug = get_boolean(options, "debug", False) return MissingLibraryConsumerSet(trees["vartree"].dbapi, debug=debug) singleBuilder = classmethod(singleBuilder) diff --git a/pym/portage/sets/files.py b/pym/portage/sets/files.py index 655391cc4..e11a36e4f 100644 --- a/pym/portage/sets/files.py +++ b/pym/portage/sets/files.py @@ -10,7 +10,7 @@ from portage.const import PRIVATE_PATH, USER_CONFIG_PATH from portage.locks import lockfile, unlockfile from portage import portage_gid from portage.sets.base import PackageSet, EditablePackageSet -from portage.sets import SetConfigError, SETPREFIX +from portage.sets import SetConfigError, SETPREFIX, get_boolean from portage.env.loaders import ItemFileLoader, KeyListFileLoader from portage.env.validators import ValidAtomValidator from portage import dep_getkey, cpv_getkey @@ -20,12 +20,17 @@ __all__ = ["StaticFileSet", "ConfigFileSet", "WorldSet"] class StaticFileSet(EditablePackageSet): _operations = ["merge", "unmerge"] - def __init__(self, filename): + def __init__(self, filename, greedy=False, dbapi=None): super(StaticFileSet, self).__init__() self._filename = filename self._mtime = None self.description = "Package set loaded from file %s" % self._filename self.loader = ItemFileLoader(self._filename, self._validate) + if greedy and not dbapi: + self.errors.append("%s configured as greedy set, but no dbapi instance passed in constructor" % self._filename) + greedy = False + self.greedy = greedy + self.dbapi = dbapi metadata = grabfile(self._filename + ".metadata") key = None @@ -69,13 +74,26 @@ class StaticFileSet(EditablePackageSet): raise del e data = {} - self._setAtoms(data.keys()) + if self.greedy: + atoms = [] + for a in data.keys(): + matches = self.dbapi.match(a) + for cpv in matches: + atoms.append("%s:%s" % (cpv_getkey(cpv), + self.dbapi.aux_get(cpv, ["SLOT"])[0])) + # In addition to any installed slots, also try to pull + # in the latest new slot that may be available. + atoms.append(a) + else: + atoms = data.keys() + self._setAtoms(atoms) self._mtime = mtime def singleBuilder(self, options, settings, trees): if not "filename" in options: raise SetConfigError("no filename specified") - return ConfigFileSet(options[filename]) + greedy = get_boolean(options, "greedy", True) + return StaticFileSet(options["filename"], greedy=greedy, dbapi=trees["vartree"].dbapi) singleBuilder = classmethod(singleBuilder) def multiBuilder(self, options, settings, trees): @@ -84,13 +102,14 @@ class StaticFileSet(EditablePackageSet): name_pattern = options.get("name_pattern", "sets/$name") if not "$name" in name_pattern and not "${name}" in name_pattern: raise SetConfigError("name_pattern doesn't include $name placeholder") + greedy = get_boolean(options, "greedy", True) if os.path.isdir(directory): for filename in os.listdir(directory): if filename.endswith(".metadata"): continue myname = name_pattern.replace("$name", filename) myname = myname.replace("${name}", filename) - rValue[myname] = StaticFileSet(os.path.join(directory, filename)) + rValue[myname] = StaticFileSet(os.path.join(directory, filename), greedy=greedy, dbapi=trees["vartree"].dbapi) return rValue multiBuilder = classmethod(multiBuilder) @@ -108,7 +127,7 @@ class ConfigFileSet(PackageSet): def singleBuilder(self, options, settings, trees): if not "filename" in options: raise SetConfigError("no filename specified") - return ConfigFileSet(options[filename]) + return ConfigFileSet(options["filename"]) singleBuilder = classmethod(singleBuilder) def multiBuilder(self, options, settings, trees): diff --git a/pym/portage/sets/security.py b/pym/portage/sets/security.py index f93b34ef8..928fecbcf 100644 --- a/pym/portage/sets/security.py +++ b/pym/portage/sets/security.py @@ -7,6 +7,7 @@ import portage.glsa as glsa from portage.util import grabfile, write_atomic from portage.sets.base import PackageSet from portage.versions import catpkgsplit, pkgcmp +from portage.sets import get_boolean __all__ = ["SecuritySet", "NewGlsaSet", "NewAffectedSet", "AffectedSet"] @@ -69,11 +70,7 @@ class SecuritySet(PackageSet): myglsa.inject() def singleBuilder(cls, options, settings, trees): - if "use_emerge_resoler" in options \ - and options.get("use_emerge_resolver").lower() in ["1", "yes", "true", "on"]: - least_change = False - else: - least_change = True + least_change = not get_boolean(options, "use_emerge_resolver", False) return cls(settings, trees["vartree"].dbapi, trees["porttree"].dbapi, least_change=least_change) singleBuilder = classmethod(singleBuilder) diff --git a/pym/portage/util.py b/pym/portage/util.py index ea16c5cff..2cbcfb745 100644 --- a/pym/portage/util.py +++ b/pym/portage/util.py @@ -169,7 +169,7 @@ def stack_dicts(dicts, incremental=0, incrementals=[], ignore_none=0): if final_dict is None: final_dict = {} for y in mydict.keys(): - if mydict[y]: + if True: if final_dict.has_key(y) and (incremental or (y in incrementals)): final_dict[y] += " "+mydict[y][:] else: diff --git a/pym/repoman/utilities.py b/pym/repoman/utilities.py index 4282f2a9a..fc31afc88 100644 --- a/pym/repoman/utilities.py +++ b/pym/repoman/utilities.py @@ -317,12 +317,12 @@ def FindPortdir(settings): location = normalize_path(location) - path_ids = set() + path_ids = {} p = location s = None while True: s = os.stat(p) - path_ids.add((s.st_dev, s.st_ino)) + path_ids[(s.st_dev, s.st_ino)] = p if p == "/": break p = os.path.dirname(p) @@ -335,10 +335,12 @@ def FindPortdir(settings): s = os.stat(overlay) except OSError: continue - overlay_id = (s.st_dev, s.st_ino) + overlay = path_ids.get((s.st_dev, s.st_ino)) + if overlay is None: + continue if overlay[-1] != "/": overlay += "/" - if overlay_id in path_ids: + if True: portdir_overlay = overlay subdir = location[len(overlay):] if subdir and subdir[-1] != "/":