mirror of
https://git.launchpad.net/~ubuntu-release/britney/+git/britney2-ubuntu
synced 2025-02-10 05:57:28 +00:00
Removed two unused methods, check_installable and check_conflicts
This commit is contained in:
parent
22d8167786
commit
79f24cd38f
265
britney.py
265
britney.py
@ -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…
x
Reference in New Issue
Block a user