mirror of
https://git.launchpad.net/~ubuntu-release/britney/+git/britney2-ubuntu
synced 2025-05-17 13:31:29 +00:00
Removed two unused methods, check_installable and check_conflicts
This commit is contained in:
parent
9f12113822
commit
7ef794fa21
265
britney.py
265
britney.py
@ -1767,271 +1767,6 @@ class Britney:
|
|||||||
diff = diff + (len(new[arch]) - len(old[arch]))
|
diff = diff + (len(new[arch]) - len(old[arch]))
|
||||||
return diff <= 0
|
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, pkg, hint_undo=[]):
|
def doop_source(self, pkg, hint_undo=[]):
|
||||||
"""Apply a change to the testing distribution as requested by `pkg`
|
"""Apply a change to the testing distribution as requested by `pkg`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user