Example #1
0
def findPackages(options,
                 exclude=None,
                 destructive=False,
                 time_limit=0,
                 package_names=False,
                 pkgdir=None,
                 port_dbapi=portage.db[portage.root]["porttree"].dbapi,
                 var_dbapi=portage.db[portage.root]["vartree"].dbapi):
    """Find obsolete binary packages.

	@param options: dict of options determined at runtime
	@type  options: dict
	@param exclude: exclusion dict (as defined in the exclude.parseExcludeFile class)
	@type  exclude: dict, optional
	@param destructive: binpkg is obsolete if not installed (default: `False`)
	@type  destructive: bool, optional
	@param time_limit: exclude binpkg if newer than time value as returned by parseTime()
	@type  time_limit: int, optional
	@param package_names: exclude all binpkg versions if package is installed
						  (used with `destructive=True`) (default: `False`)
	@type  package_names: bool, optional
	@param pkgdir: path to the binpkg cache (PKGDIR)
	@type  pkgdir: str
	@param port_dbapi: defaults to portage.db[portage.root]["porttree"].dbapi
					   Can be overridden for tests.
	@param  var_dbapi: defaults to portage.db[portage.root]["vartree"].dbapi
					   Can be overridden for tests.

	@return binary packages to remove. e.g. {'cat/pkg-ver': [filepath]}
	@rtype: dict
	"""
    if exclude is None:
        exclude = {}

    # Access test, os.walk does not error for "no read permission"
    try:
        test = os.listdir(pkgdir)
        del test
    except EnvironmentError as er:
        if options['ignore-failure']:
            exit(0)
        print(pp.error("Error accessing PKGDIR."), file=sys.stderr)
        print(pp.error("(Check your make.conf file and environment)."),
              file=sys.stderr)
        print(pp.error("Error: %s" % str(er)), file=sys.stderr)
        exit(1)

    # Create a dictionary of all installed packages
    if destructive and package_names:
        installed = dict.fromkeys(var_dbapi.cp_all())
    else:
        installed = {}

    # Dictionary of binary packages to clean. Organized as cpv->[pkgs] in order
    # to support FEATURES=binpkg-multi-instance.
    dead_binpkgs = {}

    bin_dbapi = portage.binarytree(pkgdir=pkgdir,
                                   settings=var_dbapi.settings).dbapi
    for cpv in bin_dbapi.cpv_all():
        cp = portage.cpv_getkey(cpv)

        # Exclude per --exclude-file=...
        if exclDictMatchCP(exclude, cp):
            continue

        # Exclude if binpkg is newer than --time-limit=...
        if time_limit:
            mtime = int(bin_dbapi.aux_get(cpv, ['_mtime_'])[0])
            if mtime >= time_limit:
                continue

        # Exclude if binpkg exists in the porttree and not --deep
        if not destructive and port_dbapi.cpv_exists(cpv):
            if not options['changed-deps']:
                continue

            dep_keys = ('RDEPEND', 'PDEPEND')
            keys = ('EAPI', 'USE') + dep_keys
            binpkg_metadata = dict(zip(keys, bin_dbapi.aux_get(cpv, keys)))
            ebuild_metadata = dict(zip(keys, port_dbapi.aux_get(cpv, keys)))

            if _deps_equal(' '.join(binpkg_metadata[key] for key in dep_keys),
                           binpkg_metadata['EAPI'],
                           ' '.join(ebuild_metadata[key] for key in dep_keys),
                           ebuild_metadata['EAPI'],
                           frozenset(binpkg_metadata['USE'].split())):
                continue

        if destructive and var_dbapi.cpv_exists(cpv):
            # Exclude if an instance of the package is installed due to
            # the --package-names option.
            if cp in installed and port_dbapi.cpv_exists(cpv):
                continue

            # Exclude if BUILD_TIME of binpkg is same as vartree
            buildtime = var_dbapi.aux_get(cpv, ['BUILD_TIME'])[0]
            if buildtime == bin_dbapi.aux_get(cpv, ['BUILD_TIME'])[0]:
                continue

        binpkg_path = bin_dbapi.bintree.getname(cpv)
        dead_binpkgs.setdefault(cpv, []).append(binpkg_path)

    return dead_binpkgs
Example #2
0
def findPackages(options,
                 exclude=None,
                 destructive=False,
                 time_limit=0,
                 package_names=False,
                 pkgdir=None,
                 port_dbapi=portage.db[portage.root]["porttree"].dbapi,
                 var_dbapi=portage.db[portage.root]["vartree"].dbapi):
    """Find all obsolete binary packages.

	XXX: packages are found only by symlinks.
	Maybe i should also return .tbz2 files from All/ that have
	no corresponding symlinks.

	@param options: dict of options determined at runtime
	@param exclude: an exclusion dict as defined in
			exclude.parseExcludeFile class.
	@param destructive: boolean, defaults to False
	@param time_limit: integer time value as returned by parseTime()
	@param package_names: boolean, defaults to False.
			used only if destructive=True
	@param pkgdir: path to the binary package dir being checked
	@param port_dbapi: defaults to portage.db[portage.root]["porttree"].dbapi
					can be overridden for tests.
	@param var_dbapi: defaults to portage.db[portage.root]["vartree"].dbapi
					can be overridden for tests.

	@rtype: dict
	@return clean_me i.e. {'cat/pkg-ver.tbz2': [filepath],}
	"""
    if exclude is None:
        exclude = {}
    clean_me = {}
    # create a full package dictionary

    # now do an access test, os.walk does not error for "no read permission"
    try:
        test = os.listdir(pkgdir)
        del test
    except EnvironmentError as er:
        if options['ignore-failure']:
            exit(0)
        print(pp.error("Error accessing PKGDIR."), file=sys.stderr)
        print(pp.error("(Check your make.conf file and environment)."),
              file=sys.stderr)
        print(pp.error("Error: %s" % str(er)), file=sys.stderr)
        exit(1)

    # if portage supports FEATURES=binpkg-multi-instance, then
    # cpv_all can return multiple instances per cpv, where
    # instances are distinguishable by some extra attributes
    # provided by portage's _pkg_str class
    bin_dbapi = portage.binarytree(pkgdir=pkgdir,
                                   settings=var_dbapi.settings).dbapi
    for cpv in bin_dbapi.cpv_all():
        mtime = int(bin_dbapi.aux_get(cpv, ['_mtime_'])[0])
        if time_limit and mtime >= time_limit:
            # time-limit exclusion
            continue
        # dict is cpv->[pkgs] (supports binpkg-multi-instance)
        clean_me.setdefault(cpv, []).append(cpv)

    # keep only obsolete ones
    if destructive and package_names:
        cp_all = dict.fromkeys(var_dbapi.cp_all())
    else:
        cp_all = {}
    for cpv in list(clean_me):
        if exclDictMatchCP(exclude, portage.cpv_getkey(cpv)):
            # exclusion because of the exclude file
            del clean_me[cpv]
            continue
        if not destructive and port_dbapi.cpv_exists(cpv):
            # exclusion because pkg still exists (in porttree)
            del clean_me[cpv]
            continue
        if destructive and var_dbapi.cpv_exists(cpv):
            buildtime = var_dbapi.aux_get(cpv, ['BUILD_TIME'])[0]
            clean_me[cpv] = [
                pkg for pkg in clean_me[cpv]
                # only keep path if BUILD_TIME is identical with vartree
                if bin_dbapi.aux_get(pkg, ['BUILD_TIME'])[0] != buildtime
            ]
            if not clean_me[cpv]:
                # nothing we can clean for this package
                del clean_me[cpv]
                continue
        if portage.cpv_getkey(cpv) in cp_all and port_dbapi.cpv_exists(cpv):
            # exlusion because of --package-names
            del clean_me[cpv]

    # the getname method correctly supports FEATURES=binpkg-multi-instance,
    # allowing for multiple paths per cpv (the API used here is also compatible
    # with older portage which does not support binpkg-multi-instance)
    for cpv, pkgs in clean_me.items():
        clean_me[cpv] = [bin_dbapi.bintree.getname(pkg) for pkg in pkgs]

    return clean_me
Example #3
0
def findPackages(
		options,
		exclude=None,
		destructive=False,
		time_limit=0,
		package_names=False,
		pkgdir=None,
		port_dbapi=portage.db[portage.root]["porttree"].dbapi,
		var_dbapi=portage.db[portage.root]["vartree"].dbapi
	):
	"""Find all obsolete binary packages.

	XXX: packages are found only by symlinks.
	Maybe i should also return .tbz2 files from All/ that have
	no corresponding symlinks.

	@param options: dict of options determined at runtime
	@param exclude: an exclusion dict as defined in
			exclude.parseExcludeFile class.
	@param destructive: boolean, defaults to False
	@param time_limit: integer time value as returned by parseTime()
	@param package_names: boolean, defaults to False.
			used only if destructive=True
	@param pkgdir: path to the binary package dir being checked
	@param port_dbapi: defaults to portage.db[portage.root]["porttree"].dbapi
					can be overridden for tests.
	@param var_dbapi: defaults to portage.db[portage.root]["vartree"].dbapi
					can be overridden for tests.

	@rtype: dict
	@return clean_me i.e. {'cat/pkg-ver.tbz2': [filepath],}
	"""
	if exclude is None:
		exclude = {}
	clean_me = {}
	# create a full package dictionary

	# now do an access test, os.walk does not error for "no read permission"
	try:
		test = os.listdir(pkgdir)
		del test
	except EnvironmentError as er:
		if options['ignore-failure']:
			exit(0)
		print( pp.error("Error accessing PKGDIR." ), file=sys.stderr)
		print( pp.error("(Check your make.conf file and environment)."), file=sys.stderr)
		print( pp.error("Error: %s" %str(er)), file=sys.stderr)
		exit(1)

	# if portage supports FEATURES=binpkg-multi-instance, then
	# cpv_all can return multiple instances per cpv, where
	# instances are distinguishable by some extra attributes
	# provided by portage's _pkg_str class
	bin_dbapi = portage.binarytree(pkgdir=pkgdir, settings=var_dbapi.settings).dbapi
	for cpv in bin_dbapi.cpv_all():
		mtime = int(bin_dbapi.aux_get(cpv, ['_mtime_'])[0])
		if time_limit and mtime >= time_limit:
			# time-limit exclusion
			continue
		# dict is cpv->[pkgs] (supports binpkg-multi-instance)
		clean_me.setdefault(cpv, []).append(cpv)

	# keep only obsolete ones
	if destructive and package_names:
		cp_all = dict.fromkeys(var_dbapi.cp_all())
	else:
		cp_all = {}
	for cpv in list(clean_me):
		if exclDictMatchCP(exclude,portage.cpv_getkey(cpv)):
			# exclusion because of the exclude file
			del clean_me[cpv]
			continue
		if not destructive and port_dbapi.cpv_exists(cpv):
			# exclusion because pkg still exists (in porttree)
			del clean_me[cpv]
			continue
		if destructive and var_dbapi.cpv_exists(cpv):
			buildtime = var_dbapi.aux_get(cpv, ['BUILD_TIME'])[0]
			clean_me[cpv] = [pkg for pkg in clean_me[cpv]
				# only keep path if BUILD_TIME is identical with vartree
				if bin_dbapi.aux_get(pkg, ['BUILD_TIME'])[0] != buildtime]
			if not clean_me[cpv]:
				# nothing we can clean for this package
				del clean_me[cpv]
				continue
		if portage.cpv_getkey(cpv) in cp_all and port_dbapi.cpv_exists(cpv):
			# exlusion because of --package-names
			del clean_me[cpv]

	# the getname method correctly supports FEATURES=binpkg-multi-instance,
	# allowing for multiple paths per cpv (the API used here is also compatible
	# with older portage which does not support binpkg-multi-instance)
	for cpv, pkgs in clean_me.items():
		clean_me[cpv] = [bin_dbapi.bintree.getname(pkg) for pkg in pkgs]

	return clean_me
Example #4
0
def findPackages(
    options,
    exclude=None,
    destructive=False,
    time_limit=0,
    package_names=False,
    pkgdir=None,
    port_dbapi=portage.db[portage.root]["porttree"].dbapi,
    var_dbapi=portage.db[portage.root]["vartree"].dbapi,
):
    """Find all obsolete binary packages.

	XXX: packages are found only by symlinks.
	Maybe i should also return .tbz2 files from All/ that have
	no corresponding symlinks.

	@param options: dict of options determined at runtime
	@param exclude: an exclusion dict as defined in
			exclude.parseExcludeFile class.
	@param destructive: boolean, defaults to False
	@param time_limit: integer time value as returned by parseTime()
	@param package_names: boolean, defaults to False.
			used only if destructive=True
	@param pkgdir: path to the binary package dir being checked
	@param port_dbapi: defaults to portage.db[portage.root]["porttree"].dbapi
					can be overridden for tests.
	@param var_dbapi: defaults to portage.db[portage.root]["vartree"].dbapi
					can be overridden for tests.

	@rtype: dict
	@return clean_me i.e. {'cat/pkg-ver.tbz2': [filepath],}
	"""
    if exclude is None:
        exclude = {}
    clean_me = {}
    # create a full package dictionary

    # now do an access test, os.walk does not error for "no read permission"
    try:
        test = os.listdir(pkgdir)
        del test
    except EnvironmentError as er:
        print(pp.error("Error accessing PKGDIR."), file=sys.stderr)
        print(pp.error("(Check your /etc/make.conf and environment)."), file=sys.stderr)
        print(pp.error("Error: %s" % str(er)), file=sys.stderr)
        exit(1)
    for root, dirs, files in os.walk(pkgdir):
        if root[-3:] == "All":
            continue
        for file in files:
            if not file[-5:] == ".tbz2":
                # ignore non-tbz2 files
                continue
            path = os.path.join(root, file)
            category = os.path.split(root)[-1]
            cpv = category + "/" + file[:-5]
            st = os.lstat(path)
            if time_limit and (st[stat.ST_MTIME] >= time_limit):
                # time-limit exclusion
                continue
                # dict is cpv->[files] (2 files in general, because of symlink)
            clean_me[cpv] = [path]
            # if os.path.islink(path):
            if stat.S_ISLNK(st[stat.ST_MODE]):
                clean_me[cpv].append(os.path.realpath(path))
                # keep only obsolete ones
    if destructive:
        dbapi = var_dbapi
        if package_names:
            cp_all = dict.fromkeys(dbapi.cp_all())
        else:
            cp_all = {}
    else:
        dbapi = port_dbapi
        cp_all = {}
    for cpv in list(clean_me):
        if exclDictMatchCP(exclude, portage.cpv_getkey(cpv)):
            # exclusion because of the exclude file
            del clean_me[cpv]
            continue
        if dbapi.cpv_exists(cpv):
            # exclusion because pkg still exists (in porttree or vartree)
            del clean_me[cpv]
            continue
        if portage.cpv_getkey(cpv) in cp_all:
            # exlusion because of --package-names
            del clean_me[cpv]

    return clean_me
Example #5
0
def findPackages(options,
                 exclude=None,
                 destructive=False,
                 time_limit=0,
                 package_names=False,
                 pkgdir=None,
                 port_dbapi=portage.db[portage.root]["porttree"].dbapi,
                 var_dbapi=portage.db[portage.root]["vartree"].dbapi):
    """Find all obsolete binary packages.

	XXX: packages are found only by symlinks.
	Maybe i should also return .tbz2 files from All/ that have
	no corresponding symlinks.

	@param options: dict of options determined at runtime
	@param exclude: an exclusion dict as defined in
			exclude.parseExcludeFile class.
	@param destructive: boolean, defaults to False
	@param time_limit: integer time value as returned by parseTime()
	@param package_names: boolean, defaults to False.
			used only if destructive=True
	@param pkgdir: path to the binary package dir being checked
	@param port_dbapi: defaults to portage.db[portage.root]["porttree"].dbapi
					can be overridden for tests.
	@param var_dbapi: defaults to portage.db[portage.root]["vartree"].dbapi
					can be overridden for tests.

	@rtype: dict
	@return clean_me i.e. {'cat/pkg-ver.tbz2': [filepath],}
	"""
    if exclude is None:
        exclude = {}
    clean_me = {}
    # create a full package dictionary

    # now do an access test, os.walk does not error for "no read permission"
    try:
        test = os.listdir(pkgdir)
        del test
    except EnvironmentError as er:
        print(pp.error("Error accessing PKGDIR."), file=sys.stderr)
        print(pp.error("(Check your make.conf file and environment)."),
              file=sys.stderr)
        print(pp.error("Error: %s" % str(er)), file=sys.stderr)
        exit(1)
    for root, dirs, files in os.walk(pkgdir):
        if root[-3:] == 'All':
            continue
        for file in files:
            if not file[-5:] == ".tbz2":
                # ignore non-tbz2 files
                continue
            path = os.path.join(root, file)
            category = os.path.split(root)[-1]
            cpv = category + "/" + file[:-5]
            st = os.lstat(path)
            if time_limit and (st[stat.ST_MTIME] >= time_limit):
                # time-limit exclusion
                continue
            # dict is cpv->[files] (2 files in general, because of symlink)
            clean_me[cpv] = [path]
            #if os.path.islink(path):
            if stat.S_ISLNK(st[stat.ST_MODE]):
                clean_me[cpv].append(os.path.realpath(path))
    # keep only obsolete ones
    if destructive:
        dbapi = var_dbapi
        if package_names:
            cp_all = dict.fromkeys(dbapi.cp_all())
        else:
            cp_all = {}
    else:
        dbapi = port_dbapi
        cp_all = {}
    for cpv in list(clean_me):
        if exclDictMatchCP(exclude, portage.cpv_getkey(cpv)):
            # exclusion because of the exclude file
            del clean_me[cpv]
            continue
        if dbapi.cpv_exists(cpv):
            # exclusion because pkg still exists (in porttree or vartree)
            del clean_me[cpv]
            continue
        if portage.cpv_getkey(cpv) in cp_all:
            # exlusion because of --package-names
            del clean_me[cpv]

    return clean_me