Removed two unused methods, check_installable and check_conflicts

master
Niels Thykier 13 years ago committed by Adam D. Barratt
parent 504a7c2d61
commit 91baa5a4d6

@ -1772,271 +1772,6 @@ class Britney:
diff = diff + (len(new[arch]) - len(old[arch]))
return diff <= 0
def check_installable(self, pkg, arch, suite, excluded=[], conflicts=False):
"""Check if a package is installable
This method analyzes the dependencies of the binary package specified
by the parameter `pkg' for the architecture `arch' within the suite
`suite'. If the dependency can be satisfied in the given `suite` and
`conflicts` parameter is True, then the co-installability with
conflicts handling is checked.
The dependency fields checked are Pre-Depends and Depends.
The method returns a boolean which is True if the given package is
installable.
NOTE: this method has been deprecated, actually we use is_installable
from the britney c extension called within a testing system. See
self.build_systems for more information.
"""
self.__log("WARNING: method check_installable is deprecated: use is_installable instead!", type="E")
# retrieve the binary package from the specified suite and arch
binary_u = self.binaries[suite][arch][0][pkg]
# local copies for better performances
parse_depends = apt_pkg.ParseDepends
get_dependency_solvers = self.get_dependency_solvers
# analyze the dependency fields (if present)
for type in (PREDEPENDS, DEPENDS):
if not binary_u[type]:
continue
# for every block of dependency (which is formed as conjunction of disconjunction)
for block in parse_depends(binary_u[type]):
# if the block is not satisfied, return False
solved, packages = get_dependency_solvers(block, arch, 'testing', excluded, strict=True)
if not solved:
return False
# otherwise, the package is installable (not considering conflicts)
# if the conflicts handling is enabled, then check conflicts before
# saying that the package is really installable
if conflicts:
return self.check_conflicts(pkg, arch, excluded, {}, {})
return True
def check_conflicts(self, pkg, arch, broken, system, conflicts):
"""Check if a package can be installed satisfying the conflicts
This method checks if the `pkg` package from the `arch` architecture
can be installed (excluding `broken` packages) within the system
`system` along with all its dependencies. This means that all the
conflicts relationships are checked in order to achieve the test
co-installability of the package.
The method returns a boolean which is True if the given package is
co-installable in the given system.
"""
# local copies for better performances
binaries = self.binaries['testing'][arch]
parse_depends = apt_pkg.ParseDepends
check_depends = apt_pkg.CheckDep
# unregister conflicts, local method to remove conflicts
# registered from a given package.
def unregister_conflicts(pkg, conflicts):
for c in conflicts.keys():
i = 0
while i < len(conflicts[c]):
if conflicts[c][i][3] == pkg:
del conflicts[c][i]
else: i = i + 1
if len(conflicts[c]) == 0:
del conflicts[c]
def remove_package(pkg, system, conflicts):
for k in system:
if pkg in system[k][1]:
system[k][1].remove(pkg)
unregister_conflicts(pkg, conflicts)
# handle a conflict, local method to solve a conflict which happened
# in the system; the behaviour of the conflict-solver is:
# 1. If there are alternatives for the package which must be removed,
# try them, and if one of them resolves the system return True;
# 2. If none of the alternatives can solve the conflict, then call
# itself for the package which depends on the conflicting package.
# 3. If the top of the dependency tree is reached, then the conflict
# can't be solved, so return False.
def handle_conflict(pkg, source, system, conflicts):
# skip packages which don't have reverse dependencies
if source not in system or system[source][1] == []:
remove_package(source, system, conflicts)
return (system, conflicts)
# reached the top of the tree
if not system[source][1][0]:
return False
# remove its conflicts
unregister_conflicts(source, conflicts)
# if there are alternatives, try them
alternatives = system[source][0]
for alt in alternatives:
if satisfy(alt, [x for x in alternatives if x != alt], pkg_from=system[source][1],
system=system, conflicts=conflicts, excluded=[source]):
remove_package(source, system, conflicts)
return (system, conflicts)
# there are no good alternatives, so remove the package which depends on it
for p in system[source][1]:
# the package does not exist, we reached the top of the tree
if not p: return False
# we are providing the package we conflict on (eg. exim4 and mail-transfer-agent), skip it
if p == pkg: continue
output = handle_conflict(pkg, p, system, conflicts)
if output:
system, conflicts = output
else: return False
remove_package(source, system, conflicts)
return (system, conflicts)
# dependency tree satisfier, local method which tries to satisfy the dependency
# tree for a given package. It calls itself recursively in order to check the
# co-installability of the full tree of dependency of the starting package.
# If a conflict is detected, it tries to handle it calling the handle_conflict
# method; if it can't be resolved, then it returns False.
def satisfy(pkg, pkg_alt=None, pkg_from=None, system=system, conflicts=conflicts, excluded=[]):
# if it is a real package and it is already installed, skip it and return True
if pkg in binaries[0]:
if pkg in system:
if type(pkg_from) == list:
system[pkg][1].extend(pkg_from)
else:
system[pkg][1].append(pkg_from)
system[pkg] = (system[pkg][1], filter(lambda x: x in pkg_alt, system[pkg][0]))
return True
binary_u = binaries[0][pkg]
else: binary_u = None
# if it is a virtual package
providers = []
if pkg_from and pkg in binaries[1]:
providers = binaries[1][pkg]
# it is both real and virtual, so the providers are alternatives
if binary_u:
providers = filter(lambda x: (not pkg_alt or x not in pkg_alt) and x != pkg, providers)
if not pkg_alt:
pkg_alt = []
pkg_alt.extend(providers)
# try all the alternatives and if none of them suits, give up and return False
else:
# if we already have a provider in the system, everything is ok and return True
if len(filter(lambda x: x in providers and x not in excluded, system)) > 0:
return True
for p in providers:
# try to install the providers skipping excluded packages,
# which we already tried but do not work
if p in excluded: continue
elif satisfy(p, [a for a in providers if a != p], pkg_from):
return True
# if none of them suits, return False
return False
# if the package doesn't exist, return False
if not binary_u: return False
# it is broken, but we have providers
if pkg in broken and pkg_from:
for p in providers:
# try to install the providers skipping excluded packages,
# which we already tried but do not work
if p in excluded: continue
elif satisfy(p, [a for a in providers if a != p], pkg_from):
return True
return False
# install the package into the system, recording which package required it
if type(pkg_from) != list:
pkg_from = [pkg_from]
system[pkg] = (pkg_alt or [], pkg_from)
# register provided packages
if binary_u[PROVIDES]:
for p in binary_u[PROVIDES]:
if p in system:
# do not consider packages providing the one which we are checking
if len(system[p][1]) == 1 and system[p][1][0] == None: continue
system[p][1].append(pkg)
else:
system[p] = ([], [pkg])
# check the conflicts
if pkg in conflicts:
for name, version, op, conflicting in conflicts[pkg]:
if conflicting in binary_u[PROVIDES] and system[conflicting][1] == [pkg]: continue
if op == '' and version == '' or check_depends(binary_u[VERSION], op, version):
# if conflict is found, check if it can be solved removing
# already-installed packages without breaking the system; if
# this is not possible, give up and return False
output = handle_conflict(pkg, conflicting, system.copy(), conflicts.copy())
if output:
system, conflicts = output
else:
del system[pkg]
return False
# register conflicts from the just-installed package
if binary_u[CONFLICTS]:
for block in map(operator.itemgetter(0), parse_depends(binary_u[CONFLICTS] or [])):
name, version, op = block
# skip conflicts for packages provided by itself
# if the conflicting package is in the system (and it is not a self-conflict)
if not (name in binary_u[PROVIDES] and system[name][1] == [pkg]) and \
block[0] != pkg and block[0] in system:
if block[0] in binaries[0]:
binary_c = binaries[0][block[0]]
else: binary_c = None
if op == '' and version == '' or binary_c and check_depends(binary_c[VERSION], op, version):
# if conflict is found, check if it can be solved removing
# already-installed packages without breaking the system; if
# this is not possible, give up and return False
output = handle_conflict(pkg, name, system.copy(), conflicts.copy())
if output:
system, conflicts = output
else:
del system[pkg]
unregister_conflicts(pkg, conflicts)
return False
# register the conflict
if block[0] not in conflicts:
conflicts[block[0]] = []
conflicts[block[0]].append((name, version, op, pkg))
# list all its dependencies ...
dependencies = []
for key in (PREDEPENDS, DEPENDS):
if not binary_u[key]: continue
dependencies.extend(parse_depends(binary_u[key]))
# ... and go through them
for block in dependencies:
# list the possible alternatives, in case of a conflict
alternatives = map(operator.itemgetter(0), block)
valid = False
for name, version, op in block:
# otherwise, if it is already installed or it is installable, the block is satisfied
if name in system or satisfy(name, [a for a in alternatives if a != name], pkg):
valid = True
break
# if the block can't be satisfied, the package is not installable so
# we need to remove it, its conflicts and its provided packages and
# return False
if not valid:
del system[pkg]
unregister_conflicts(pkg, conflicts)
for p in providers:
if satisfy(p, [a for a in providers if a != p], pkg_from):
return True
return False
# if all the blocks have been satisfied, the package is installable
return True
# check the package at the top of the tree
return satisfy(pkg)
def doop_source(self, item, hint_undo=[]):
"""Apply a change to the testing distribution as requested by `pkg`

Loading…
Cancel
Save