Ejemplo n.º 1
0
    def _check_conflict(self, p1, p2):
        # Does p1 conflict with p2
        for conflict in p1.conflicts:
            cq = Query(conflict)
            if cq.matches(p2) and not self._does_bridge_after(p1, p2):
                return (p1, p2)

        # Does p2 conflict with p1
        for conflict in p2.conflicts:
            cq = Query(conflict)
            if cq.matches(p1) and not self._does_bridge_after(p2, p1):
                return p2, p1
Ejemplo n.º 2
0
    def _does_bridge(self, local_repo, targets, p1, p2):
        # Do we have a bridge already installed?
        installed_bridges = local_repo.find_bridges(p1, p2)
        if installed_bridges:
            return True

        # Do any of the packages we are about to install offer to bridge this?
        for package in targets:
            for bridge in package.bridges:
                b1 = Query(bridge[0])
                b2 = Query(bridge[1])
                if b1.matches(p1) and b2.matches(p2):
                    return True
                elif b2.matches(p1) and b1.matches(p2):
                    return True
        return False
Ejemplo n.º 3
0
    def _find_conflicts(self, targets, local_repo):
        # Find conflicts inside targets
        conflicts = set()
        for t in targets:
            for conflict in t.conflicts:
                cq = Query(conflict)
                for tc in targets:
                    # Packages don't conflict with themselves
                    if t == tc:
                        continue
                    if (cq.matches(tc) and
                            not self._does_bridge(local_repo, targets, t, tc)):
                        conflicts.add((t, tc))

        local_packages = local_repo.get_all_packages()
        # Find conflicts from targets to local_repo
        for t in targets:
            for conflict in t.conflicts:
                cq = Query(conflict)
                for lp in local_packages:
                    # Packages don't conflict with themselves
                    if t == lp:
                        continue
                    if (cq.matches(lp) and
                            not self._does_bridge(local_repo, targets, t, lp)):
                        conflicts.add((t, lp))

        # Find conflicts from local_repo to targets
        for lp in local_packages:
            for conflict in lp.conflicts:
                cq = Query(conflict)
                for tc in targets:
                    # Packages don't conflict with themselves
                    if lp == tc:
                        continue
                    if (cq.matches(tc) and not self._does_bridge(
                            local_repo, targets, lp, tc)):  # NOQA
                        conflicts.add((lp, tc))
        return conflicts
Ejemplo n.º 4
0
    def expand(self):
        # If theres no targets, expand to all local packages
        if not self.targets:
            self.targets = self.local_repo.get_all_packages()

        upgrades = self._find_upgrade_required(self.targets)
        self.removes = [u[0] for u in upgrades]
        self.installs = [u[1] for u in upgrades]
        self.targets = [
            u[1] for u in upgrades if u[0].reason == InstallReason.REQ
        ]

        # So the dependencies might have changed. I don't think we want to
        # remove unused dependencies, but we do want to pull in new ones. We
        # might also stop providing something, which could invalidate some
        # other part of the local database.
        # Basically we will want to do the following:
        #   - Check if all dependencies are filled
        #   - Fill new ones (maybe asking?)
        #   - Check that all the people depending on us still have their
        #   dependencies filled after the transaction
        # During all of these steps we need to make sure that we aren't
        # matching packages that this transaction is going to remove, but
        # include packages we are about to install.

        # Find all packages touched by something we are removing

        new_missing = set()

        for package in self.removes:
            dependants = self.local_repo.find_dependants(package)
            for dependant in dependants:

                # If the dependant is queued for removal we don't really care
                # if we are going to break dependencies
                if dependant in self.removes:
                    continue

                for dep_str in dependant.dependecies:
                    q = Query(dep_str)
                    # If it didn't match before then we don't care
                    # This is important because we don't want to pop up and
                    # error now if the user purposefully broke some
                    # dependencies at some point, but if we are breaking
                    # something we want to report that
                    if not q.matches(package):
                        continue
                    # Are we going to install something that fixes it?
                    dep_sat = super()._find_satisfier_in_set(self.installs, q)
                    if dep_sat is not None:
                        continue
                    # Do we have something else that fixes it?
                    dep_sat = self.local_repo.find_package(
                        q, exclude=self.removes)
                    if dep_sat is not None:
                        continue
                    # This upgrade is going to be a problem
                    # @COMPLETE We should dump the package here as well.
                    new_missing.add((dependant, q))

        if len(new_missing) > 0:
            raise MissingDependencyError(new_missing)

        # @HACK: Reset removes, since the add transaction finds all packages
        # that are actually upgrades
        self.removes = []

        self.targets = self.installs
        super().expand()