Add present-and-installable constraints support

Solves first half of GH#5.

Signed-off-by: Niels Thykier <niels@thykier.net>
debian
Niels Thykier 9 years ago
parent e92bbf386f
commit f3e37faf7e

@ -13,6 +13,10 @@ EXCUSES_YAML_OUTPUT = /srv/release.debian.org/britney/var/data-b2/output/excuses
UPGRADE_OUTPUT = /srv/release.debian.org/britney/var/data-b2/output/output.txt
HEIDI_OUTPUT = /srv/release.debian.org/britney/var/data-b2/output/HeidiResult
# External policy/constraints/faux-packages information that
# (presumably) rarely changes. Examples include "constraints".
STATIC_INPUT_DIR = /srv/release.debian.org/britney/input
# Directory for input files that Britney will update herself
# (e.g. aging information) or will need regular updates
# (e.g. urgency information).

@ -317,6 +317,21 @@ class Britney(object):
# unstable
self.binaries['testing'][arch] = self.read_binaries(self.options.testing, "testing", arch)
try:
constraints_file = os.path.join(self.options.static_input_dir, 'constraints')
except AttributeError:
self.log("The static_input_dir option is not set", type='I')
constraints_file = None
if constraints_file is not None and os.path.exists(constraints_file):
self.log("Loading constraints from %s" % constraints_file, type='I')
self.constraints = self._load_constraints(constraints_file)
else:
if constraints_file is not None:
self.log("No constraints as %s does not exist" % constraints_file, type='I')
self.constraints = {
'keep-installable': [],
}
self.log("Compiling Installability tester", type="I")
self._build_installability_tester(self.options.architectures)
@ -476,6 +491,88 @@ class Britney(object):
if self.options.verbose or type in ("E", "W"):
print("%s: [%s] - %s" % (type, time.asctime(), msg))
def _load_constraints(self, constraints_file):
"""Loads configurable constraints
The constraints file can contain extra rules that Britney should attempt
to satisfy. Examples can be "keep package X in testing and ensure it is
installable".
:param constraints_file: Path to the file containing the constraints
"""
tag_file = apt_pkg.TagFile(constraints_file)
get_field = tag_file.section.get
step = tag_file.step
no = 0
faux_version = sys.intern('1')
faux_section = sys.intern('faux')
while step():
no += 1
pkg_name = get_field('Fake-Package-Name', None)
if pkg_name is None:
raise ValueError("Missing Fake-Package-Name field in paragraph %d (file %s)" % (no, constraints_file))
pkg_name = sys.intern(pkg_name)
def mandatory_field(x):
v = get_field(x, None)
if v is None:
raise ValueError("Missing %s field for %s (file %s)" % (x, pkg_name, constraints_file))
return v
constraint = mandatory_field('Constraint')
if constraint not in {'present-and-installable'}:
raise ValueError("Unsupported constraint %s for %s (file %s)" % (constraint, pkg_name, constraints_file))
self.log(" - constraint %s" % pkg_name, type='I')
pkg_list = [x.strip() for x in mandatory_field('Package-List').split("\n") if x.strip() != '']
src_data = [faux_version,
faux_section,
[],
None,
True,
]
self.sources['testing'][pkg_name] = src_data
self.sources['unstable'][pkg_name] = src_data
for arch in self.options.architectures:
deps = []
for pkg_spec in pkg_list:
s = pkg_spec.split(None, 2)
if len(s) == 1:
deps.append(s[0])
else:
pkg, arch_res = s
if not (arch_res.startswith('[') and arch_res.endswith(']')):
raise ValueError("Invalid arch-restriction on %s - should be [arch1 arch2] (for %s file %s)"
% (pkg, pkg_name, constraints_file))
arch_res = arch_res[1:-1].split()
if not arch_res:
msg = "Empty arch-restriction for %s: Uses comma or negation (for %s file %s)"
raise ValueError(msg % (pkg, pkg_name, constraints_file))
for a in arch_res:
if a == arch:
deps.append(pkg)
elif ',' in a or '!' in a:
msg = "Invalid arch-restriction for %s: Uses comma or negation (for %s file %s)"
raise ValueError(msg % (pkg, pkg_name, constraints_file))
pkg_id = (pkg_name, faux_version, arch)
bin_data = BinaryPackage(faux_version,
faux_section,
pkg_name,
faux_version,
arch,
'no',
', '.join(deps),
None,
[],
False,
)
src_data[BINARIES].append(pkg_id)
self.binaries['testing'][arch][0][pkg_name] = bin_data
self.binaries['unstable'][arch][0][pkg_name] = bin_data
self.all_binaries[pkg_id] = bin_data
def _build_installability_tester(self, archs):
"""Create the installability tester"""

Loading…
Cancel
Save