Move block handling to BlockPolicy

Note that this now also applies to binNMUs. A source block also blocks
binaries. Binaries on a specific architecture can be unblock with an
architecture-specific unblock hint.

This also means all binaries from non-primary suites
(testing-proposed-updates, etc) need approval.

Closes: #916209
ubuntu/rebased
Ivo De Decker 6 years ago
parent 49d9a38d25
commit 0709f8d96c

@ -202,7 +202,7 @@ from britney2.installability.solver import InstallabilitySolver
from britney2.migration import MigrationManager from britney2.migration import MigrationManager
from britney2.migrationitem import MigrationItem, MigrationItemFactory from britney2.migrationitem import MigrationItem, MigrationItemFactory
from britney2.policies import PolicyVerdict from britney2.policies import PolicyVerdict
from britney2.policies.policy import AgePolicy, RCBugPolicy, PiupartsPolicy, BuildDependsPolicy, PolicyEngine from britney2.policies.policy import AgePolicy, RCBugPolicy, PiupartsPolicy, BuildDependsPolicy, PolicyEngine, BlockPolicy
from britney2.policies.autopkgtest import AutopkgtestPolicy from britney2.policies.autopkgtest import AutopkgtestPolicy
from britney2.utils import (log_and_format_old_libraries, get_dependency_solvers, from britney2.utils import (log_and_format_old_libraries, get_dependency_solvers,
read_nuninst, write_nuninst, write_heidi, read_nuninst, write_nuninst, write_heidi,
@ -494,6 +494,7 @@ class Britney(object):
self._policy_engine.add_policy(AutopkgtestPolicy(self.options, self.suite_info)) self._policy_engine.add_policy(AutopkgtestPolicy(self.options, self.suite_info))
self._policy_engine.add_policy(AgePolicy(self.options, self.suite_info, MINDAYS)) self._policy_engine.add_policy(AgePolicy(self.options, self.suite_info, MINDAYS))
self._policy_engine.add_policy(BuildDependsPolicy(self.options, self.suite_info)) self._policy_engine.add_policy(BuildDependsPolicy(self.options, self.suite_info))
self._policy_engine.add_policy(BlockPolicy(self.options, self.suite_info))
@property @property
def hints(self): def hints(self):
@ -1021,13 +1022,6 @@ class Britney(object):
# we assume that this package will be ok, if not invalidated below # we assume that this package will be ok, if not invalidated below
excuse.policy_verdict = PolicyVerdict.PASS excuse.policy_verdict = PolicyVerdict.PASS
if same_source and not is_primary_source:
# support for binNMUs from *pu is currently broken, so disable it
# for now
# see https://bugs.debian.org/916209 for more info
excuse.addhtml("Ignoring binaries for %s from %s on %s (see https://bugs.debian.org/916209)" % (src, source_suite.name, arch))
excuse.policy_verdict = PolicyVerdict.REJECTED_PERMANENTLY
# if there is something something wrong, reject this package # if there is something something wrong, reject this package
if anywrongver: if anywrongver:
excuse.policy_verdict = PolicyVerdict.REJECTED_PERMANENTLY excuse.policy_verdict = PolicyVerdict.REJECTED_PERMANENTLY
@ -1097,58 +1091,6 @@ class Britney(object):
excuse.policy_verdict = PolicyVerdict.REJECTED_PERMANENTLY excuse.policy_verdict = PolicyVerdict.REJECTED_PERMANENTLY
break break
# check if there is a `block' or `block-udeb' hint for this package, or a `block-all source' hint
blocked = {}
for hint in self.hints.search(package=src):
if hint.type in {'block', 'block-udeb'}:
blocked[hint.type] = hint
excuse.add_hint(hint)
if 'block' not in blocked:
for hint in self.hints.search(type='block-all'):
if hint.package == 'source' or (not source_t and hint.package == 'new-source'):
blocked['block'] = hint
excuse.add_hint(hint)
break
if source_suite.suite_class.is_additional_source:
blocked['block'] = '%s-block' % (suite_name)
excuse.needs_approval = True
# if the source is blocked, then look for an `unblock' hint; the unblock request
# is processed only if the specified version is correct. If a package is blocked
# by `block-udeb', then `unblock-udeb' must be present to cancel it.
for block_cmd in blocked:
unblock_cmd = "un" + block_cmd
unblocks = self.hints.search(unblock_cmd, package=src)
if unblocks and unblocks[0].version is not None and unblocks[0].version == source_u.version:
excuse.add_hint(unblocks[0])
if block_cmd == 'block-udeb' or not excuse.needs_approval:
excuse.addhtml("Ignoring %s request by %s, due to %s request by %s" %
(block_cmd, blocked[block_cmd].user, unblock_cmd, unblocks[0].user))
else:
excuse.addhtml("Approved by %s" % (unblocks[0].user))
else:
if unblocks:
if unblocks[0].version is None:
excuse.addhtml("%s request by %s ignored due to missing version" %
(unblock_cmd.capitalize(), unblocks[0].user))
else:
excuse.addhtml("%s request by %s ignored due to version mismatch: %s" %
(unblock_cmd.capitalize(), unblocks[0].user, unblocks[0].version))
if source_suite.suite_class.is_primary_source or block_cmd == 'block-udeb':
tooltip = "please contact debian-release if update is needed"
# redirect people to d-i RM for udeb things:
if block_cmd == 'block-udeb':
tooltip = "please contact the d-i release manager if an update is needed"
excuse.addhtml("Not touching package due to %s request by %s (%s)" %
(block_cmd, blocked[block_cmd].user, tooltip))
excuse.addreason("block")
else:
excuse.addhtml("NEEDS APPROVAL BY RM")
excuse.addreason("block")
excuse.policy_verdict = PolicyVerdict.REJECTED_NEEDS_APPROVAL
all_binaries = self.all_binaries all_binaries = self.all_binaries
for pkg_id in source_u.binaries: for pkg_id in source_u.binaries:
is_valid = self.excuse_unsat_deps(pkg_id.package_name, src, pkg_id.architecture, source_suite, excuse) is_valid = self.excuse_unsat_deps(pkg_id.package_name, src, pkg_id.architecture, source_suite, excuse)

@ -1,6 +1,7 @@
import json import json
import logging import logging
import os import os
import re
import time import time
from urllib.parse import quote from urllib.parse import quote
@ -838,3 +839,93 @@ class BuildDependsPolicy(BasePolicy):
return verdict return verdict
class BlockPolicy(BasePolicy):
def __init__(self, options, suite_info):
super().__init__('block', options, suite_info,
{SuiteClass.PRIMARY_SOURCE_SUITE, SuiteClass.ADDITIONAL_SOURCE_SUITE})
self._britney = None
self._blockall = {}
def initialise(self, britney):
super().initialise(britney)
self._britney = britney
for hint in self.hints.search(type='block-all'):
self._blockall[hint.package] = hint
def register_hints(self, hint_parser):
# block related hints are currently defined in hint.py
pass
def _check_blocked(self, src, arch, version, suite_name, excuse):
verdict = PolicyVerdict.PASS
blocked = {}
unblocked = {}
source_suite = self.suite_info[suite_name]
is_primary = source_suite.suite_class == SuiteClass.PRIMARY_SOURCE_SUITE
if is_primary:
if 'source' in self._blockall:
blocked['block'] = self._blockall['source'].user
excuse.add_hint(self._blockall['source'])
elif 'new-source' in self._blockall and \
src not in self.suite_info.target_suite.sources:
blocked['block'] = self._blockall['new-source'].user
excuse.add_hint(self._blockall['new-source'])
else:
blocked['block'] = suite_name
excuse.needs_approval = True
shints = self.hints.search(package=src)
mismatches = False
r = re.compile('^(un)?(block-?.*)$')
for hint in shints:
m = r.match(hint.type)
if m:
if m.group(1) == 'un':
if hint.version != version or hint.suite.name != suite_name or \
(hint.architecture != arch and hint.architecture != 'source'):
print('hint mismatch: %s %s %s' % (version, arch, suite_name))
mismatches = True
else:
print('hint match')
unblocked[m.group(2)] = hint.user
excuse.add_hint(hint)
else:
# block(-*) hint: only accepts a source, so this will
# always match
blocked[m.group(2)] = hint.user
excuse.add_hint(hint)
for block_cmd in blocked:
unblock_cmd = 'un'+block_cmd
if block_cmd in unblocked:
if is_primary or block_cmd == 'block-udeb':
excuse.addhtml("Ignoring %s request by %s, due to %s request by %s" %
(block_cmd, blocked[block_cmd], unblock_cmd, unblocked[block_cmd]))
else:
excuse.addhtml("Approved by %s" % (unblocked[block_cmd]))
else:
if is_primary or block_cmd == 'block-udeb':
tooltip = "please contact debian-release if update is needed"
# redirect people to d-i RM for udeb things:
if block_cmd == 'block-udeb':
tooltip = "please contact the d-i release manager if an update is needed"
excuse.addhtml("Not touching package due to %s request by %s (%s)" %
(block_cmd, blocked[block_cmd], tooltip))
else:
excuse.addhtml("NEEDS APPROVAL BY RM")
excuse.addreason("block")
if mismatches:
excuse.addhtml("Some hints for %s do not match this item" % src)
verdict = PolicyVerdict.REJECTED_NEEDS_APPROVAL
return verdict
def apply_src_policy_impl(self, block_info, suite, source_name, source_data_tdist, source_data_srcdist, excuse):
return self._check_blocked(source_name, "source", source_data_srcdist.version, suite, excuse)
def apply_srcarch_policy_impl(self, block_info, suite, source_name, arch, source_data_tdist, source_data_srcdist, excuse):
return self._check_blocked(source_name, arch, source_data_srcdist.version, suite, excuse)

Loading…
Cancel
Save