mirror of
				https://git.launchpad.net/~ubuntu-release/britney/+git/britney2-ubuntu
				synced 2025-11-04 10:34:05 +00:00 
			
		
		
		
	britney.py: Split iter_packages into two
Extract a specialised iter_packages_hint from iter_packages that only deals with applying hints. This simplifies iter_packages AND avoids having to re-compute the uninstallability counters after each single item in the hint. This means that a hint can now avoid triggering expontential runtime provided only that the "post-hint" stage does not trigger expontential runtime. Previously the hint had to be ordered such that none of the items in the hint caused such behaviour (if at all possible). Signed-off-by: Niels Thykier <niels@thykier.net>
This commit is contained in:
		
							parent
							
								
									c25e7f9cd7
								
							
						
					
					
						commit
						a46dd88709
					
				
							
								
								
									
										99
									
								
								britney.py
									
									
									
									
									
								
							
							
						
						
									
										99
									
								
								britney.py
									
									
									
									
									
								
							@ -2103,7 +2103,51 @@ class Britney(object):
 | 
			
		||||
                self._installability_test(p, version, arch, broken, to_check, nuninst_arch)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def iter_packages(self, packages, selected, hint=False, nuninst=None, lundo=None):
 | 
			
		||||
    def iter_packages_hint(self, hinted_packages, lundo=None):
 | 
			
		||||
        """Iter on hinted list of actions and apply them in one go
 | 
			
		||||
 | 
			
		||||
        This method applies the changes from "hinted_packages" to
 | 
			
		||||
        testing and computes the uninstallability counters after te
 | 
			
		||||
        actions are performed.
 | 
			
		||||
 | 
			
		||||
        The method returns the new uninstallability counters.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        removals = set()
 | 
			
		||||
        all_affected = set()
 | 
			
		||||
        nobreakall_arches = self.options.nobreakall_arches.split()
 | 
			
		||||
        binaries_t = self.binaries['testing']
 | 
			
		||||
        check_packages = partial(self._check_packages, binaries_t)
 | 
			
		||||
        # Deep copy nuninst (in case the hint is undone)
 | 
			
		||||
        nuninst = {k:v.copy() for k,v in self.nuninst_orig.iteritems()}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        for item in hinted_packages:
 | 
			
		||||
            _, rms, _ = self._compute_groups(item.package, item.suite,
 | 
			
		||||
                                             item.architecture,
 | 
			
		||||
                                             item.is_removal,
 | 
			
		||||
                                             allow_smooth_updates=False)
 | 
			
		||||
            removals.update(rms)
 | 
			
		||||
 | 
			
		||||
        for item in hinted_packages:
 | 
			
		||||
            _, affected, undo = self.doop_source(item,
 | 
			
		||||
                                                 removals=removals)
 | 
			
		||||
            all_affected.update(affected)
 | 
			
		||||
            if lundo is not None:
 | 
			
		||||
                lundo.append((undo,item))
 | 
			
		||||
 | 
			
		||||
        for arch in self.options.architectures:
 | 
			
		||||
            if arch not in nobreakall_arches:
 | 
			
		||||
                skip_archall = True
 | 
			
		||||
            else:
 | 
			
		||||
                skip_archall = False
 | 
			
		||||
 | 
			
		||||
            check_packages(arch, all_affected, skip_archall, nuninst)
 | 
			
		||||
 | 
			
		||||
        return nuninst
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def iter_packages(self, packages, selected, nuninst=None, lundo=None):
 | 
			
		||||
        """Iter on the list of actions and apply them one-by-one
 | 
			
		||||
 | 
			
		||||
        This method applies the changes from `packages` to testing, checking the uninstallability
 | 
			
		||||
@ -2132,25 +2176,10 @@ class Britney(object):
 | 
			
		||||
        dependencies = self.dependencies
 | 
			
		||||
        check_packages = partial(self._check_packages, binaries)
 | 
			
		||||
 | 
			
		||||
        # pre-process a hint batch
 | 
			
		||||
        pre_process = {}
 | 
			
		||||
        if selected and hint:
 | 
			
		||||
            removals = set()
 | 
			
		||||
            for item in selected:
 | 
			
		||||
                _, rms, _ = self._compute_groups(item.package, item.suite,
 | 
			
		||||
                                                 item.architecture,
 | 
			
		||||
                                                 item.is_removal,
 | 
			
		||||
                                                 allow_smooth_updates=False)
 | 
			
		||||
                removals.update(rms)
 | 
			
		||||
            for package in selected:
 | 
			
		||||
                pkg, affected, undo = self.doop_source(package,
 | 
			
		||||
                                                       removals=removals)
 | 
			
		||||
                pre_process[package] = (pkg, affected, undo)
 | 
			
		||||
 | 
			
		||||
        if lundo is None:
 | 
			
		||||
            lundo = []
 | 
			
		||||
        if not hint:
 | 
			
		||||
            self.output_write("recur: [%s] %s %d/%d\n" % ("", ",".join(x.uvname for x in selected), len(packages), len(extra)))
 | 
			
		||||
 | 
			
		||||
        self.output_write("recur: [%s] %s %d/%d\n" % ("", ",".join(x.uvname for x in selected), len(packages), len(extra)))
 | 
			
		||||
 | 
			
		||||
        # loop on the packages (or better, actions)
 | 
			
		||||
        while packages:
 | 
			
		||||
@ -2174,45 +2203,32 @@ class Britney(object):
 | 
			
		||||
                        break
 | 
			
		||||
                if defer: continue
 | 
			
		||||
 | 
			
		||||
            if not hint:
 | 
			
		||||
                self.output_write("trying: %s\n" % (pkg.uvname))
 | 
			
		||||
            self.output_write("trying: %s\n" % (pkg.uvname))
 | 
			
		||||
 | 
			
		||||
            better = True
 | 
			
		||||
            nuninst = {}
 | 
			
		||||
 | 
			
		||||
            # apply the changes
 | 
			
		||||
            if pkg in pre_process:
 | 
			
		||||
                item, affected, undo = pre_process[pkg]
 | 
			
		||||
            else:
 | 
			
		||||
                item, affected, undo = self.doop_source(pkg, lundo)
 | 
			
		||||
            if hint:
 | 
			
		||||
                lundo.append((undo, item))
 | 
			
		||||
            item, affected, undo = self.doop_source(pkg, lundo)
 | 
			
		||||
 | 
			
		||||
            # check the affected packages on all the architectures
 | 
			
		||||
            for arch in (item.architecture == 'source' and architectures or (item.architecture,)):
 | 
			
		||||
                if arch not in nobreakall_arches:
 | 
			
		||||
                    skip_archall = True
 | 
			
		||||
                else: skip_archall = False
 | 
			
		||||
                else:
 | 
			
		||||
                    skip_archall = False
 | 
			
		||||
 | 
			
		||||
                nuninst[arch] = set(x for x in nuninst_comp[arch] if x in binaries[arch][0])
 | 
			
		||||
                nuninst[arch + "+all"] = set(x for x in nuninst_comp[arch + "+all"] if x in binaries[arch][0])
 | 
			
		||||
 | 
			
		||||
                check_packages(arch, affected, skip_archall, nuninst)
 | 
			
		||||
 | 
			
		||||
                # if we are processing hints, go ahead
 | 
			
		||||
                if hint:
 | 
			
		||||
                    nuninst_comp[arch] = nuninst[arch]
 | 
			
		||||
                    nuninst_comp[arch + "+all"] = nuninst[arch + "+all"]
 | 
			
		||||
                    continue
 | 
			
		||||
 | 
			
		||||
                # if the uninstallability counter is worse than before, break the loop
 | 
			
		||||
                if ((item.architecture != 'source' and arch not in new_arches) or \
 | 
			
		||||
                    (arch not in break_arches)) and len(nuninst[arch]) > len(nuninst_comp[arch]):
 | 
			
		||||
                    better = False
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
            # if we are processing hints or the package is already accepted, go ahead
 | 
			
		||||
            if hint or item in selected: continue
 | 
			
		||||
 | 
			
		||||
            # check if the action improved the uninstallability counters
 | 
			
		||||
            if better:
 | 
			
		||||
@ -2242,9 +2258,6 @@ class Britney(object):
 | 
			
		||||
                # (local-scope) binaries is actually self.binaries["testing"] so we cannot use it here.
 | 
			
		||||
                undo_changes(single_undo, self._inst_tester, sources, self.binaries)
 | 
			
		||||
 | 
			
		||||
        # if we are processing hints, return now
 | 
			
		||||
        if hint:
 | 
			
		||||
            return (nuninst_comp, [])
 | 
			
		||||
 | 
			
		||||
        self.output_write(" finish: [%s]\n" % ",".join( x.uvname for x in selected ))
 | 
			
		||||
        self.output_write("endloop: %s\n" % (self.eval_nuninst(self.nuninst_orig)))
 | 
			
		||||
@ -2255,6 +2268,7 @@ class Britney(object):
 | 
			
		||||
 | 
			
		||||
        return (nuninst_comp, extra)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def do_all(self, hinttype=None, init=None, actions=None):
 | 
			
		||||
        """Testing update runner
 | 
			
		||||
 | 
			
		||||
@ -2274,6 +2288,7 @@ class Britney(object):
 | 
			
		||||
        recurse = True
 | 
			
		||||
        lundo = None
 | 
			
		||||
        nuninst_end = None
 | 
			
		||||
        extra = () # empty tuple
 | 
			
		||||
 | 
			
		||||
        if hinttype == "easy" or hinttype == "force-hint":
 | 
			
		||||
            force = hinttype == "force-hint"
 | 
			
		||||
@ -2298,7 +2313,11 @@ class Britney(object):
 | 
			
		||||
 | 
			
		||||
        if init:
 | 
			
		||||
            # init => a hint (e.g. "easy") - so do the hint run
 | 
			
		||||
            (nuninst_end, extra) = self.iter_packages(init, selected, hint=True, lundo=lundo)
 | 
			
		||||
            nuninst_end = self.iter_packages_hint(selected, lundo=lundo)
 | 
			
		||||
            if recurse:
 | 
			
		||||
                # Ensure upgrade_me and selected do not overlap, if we
 | 
			
		||||
                # follow-up with a recurse ("hint"-hint).
 | 
			
		||||
                upgrade_me = [x for x in upgrade_me if x not in set(selected)]
 | 
			
		||||
 | 
			
		||||
        if recurse:
 | 
			
		||||
            # Either the main run or the recursive run of a "hint"-hint.
 | 
			
		||||
@ -2338,7 +2357,7 @@ class Britney(object):
 | 
			
		||||
                if recurse:
 | 
			
		||||
                    self.upgrade_me = sorted(extra)
 | 
			
		||||
                else:
 | 
			
		||||
                    self.upgrade_me = [x for x in self.upgrade_me if x not in selected]
 | 
			
		||||
                    self.upgrade_me = [x for x in self.upgrade_me if x not in set(selected)]
 | 
			
		||||
                self.sort_actions()
 | 
			
		||||
        else:
 | 
			
		||||
            self.output_write("FAILED\n")
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user