Exemple #1
0
    def get_failure_reason(self):
        """Return an exception explaining why the solve failed."""
        assert not self.ready

        if self._failure_reason:
            return model.SafeException(self._failure_reason)

        return model.SafeException(
            _("Can't find all required implementations:") + '\n' + '\n'.join([
                "- %s -> %s" % (iface, self.selections[iface])
                for iface in self.selections
            ]))
Exemple #2
0
	def testInvalidXMLSig(self):
		for error, sig in invalid_xmls_sigs:
			try:
				self.check_bad(bad_xml_main + b'\n' + sig)
			except model.SafeException as ex:
				if error not in str(ex):
					raise model.SafeException(str(ex) + '\nSig:\n' + sig)
Exemple #3
0
    def get_command(self, name):
        """@type name: str
		@rtype: L{Command}"""
        if name not in self.commands:
            raise model.SafeException(
                "Command '{name}' not present in selections for {iface}".
                format(name=name, iface=self.interface))
        return self.commands[name]
Exemple #4
0
	def get_path(self, stores, missing_ok = False):
		"""Return the root directory of this implementation.
		For local implementations, this is L{local_path}.
		For cached implementations, this is the directory in the cache.
		@param stores: stores to search
		@type stores: L{zerostore.Stores}
		@param missing_ok: return None for uncached implementations
		@type missing_ok: bool
		@return: the path of the directory
		@rtype: str | None
		@since: 1.8"""
		if self.local_path is not None:
			return self.local_path
		if not self.digests:
			# (for now, we assume this is always an error, even for missing_ok)
			raise model.SafeException("No digests for {feed} {version}".format(feed = self.feed, version = self.version))
		if missing_ok:
			return stores.lookup_maybe(self.digests)
		else:
			return stores.lookup_any(self.digests)
Exemple #5
0
def run_test_combinations(config, spec):
    r = requirements.Requirements(spec.test_iface)
    r.command = spec.command

    d = driver.Driver(config=config, requirements=r)
    solver = d.solver

    # Explore all combinations...

    tested_iface = config.iface_cache.get_interface(spec.test_iface)
    results = Results(spec)
    for combo in spec.get_combos(spec.test_ifaces):
        key = set()
        restrictions = {}
        selections = {}
        for (uri, version) in combo.iteritems():
            iface = config.iface_cache.get_interface(uri)
            selections[iface] = version

            if version.startswith('%'):
                if version == '%nonlocal':
                    restrictions[iface] = [NonlocalRestriction()]
                else:
                    raise model.SafeException(
                        "Unknown special '{special}'".format(special=version))
            elif ',' in version:
                not_before, before = [
                    model.parse_version(v) if v != "" else None
                    for v in version.split(',')
                ]
                if (not_before and before) and not_before >= before:
                    raise model.SafeException(
                        "Low version >= high version in %s!" % version)
                restrictions[iface] = [
                    model.VersionRangeRestriction(before, not_before)
                ]
            else:
                restrictions[iface] = [
                    model.VersionExpressionRestriction(version)
                ]
            key.add((uri, version))

        solver.extra_restrictions = restrictions
        solve = d.solve_with_downloads()
        tasks.wait_for_blocker(solve)
        if not solver.ready:
            logging.info("Can't select combination %s: %s", combo,
                         solver.get_failure_reason())
            result = 'skipped'
            for uri, impl in solver.selections.iteritems():
                if impl is None:
                    selections[uri] = selections.get(uri, None) or '?'
                else:
                    selections[uri] = impl.get_version()
            if not selections:
                selections = solver.get_failure_reason()
        else:
            selections = {}
            for iface, impl in solver.selections.iteritems():
                if impl:
                    version = impl.get_version()
                else:
                    impl = None
                selections[iface] = version
            download = d.download_uncached_implementations()
            if download:
                config.handler.wait_for_blocker(download)

            print format_combo(selections)

            result = run_tests(config, tested_iface, solver.selections, spec)

        results.by_status[result].append(selections)
        results.by_combo[frozenset(key)] = (result, selections)

    return results
Exemple #6
0
 def install(handler):
     raise model.SafeException(
         _("This program depends on '%s', which is a package that is available through your distribution. "
           "Please install it manually using your distribution's tools and try again. Or, install 'packagekit' and I can "
           "use that to install it.") % package)
Exemple #7
0
    def _init_from_qdom(self, root):
        """Parse and load a selections document.
		@param root: a saved set of selections.
		@type root: L{Element}"""
        self.interface = root.getAttribute('interface')
        self.command = root.getAttribute('command')
        if self.interface is None:
            raise model.SafeException(
                _("Not a selections document (no 'interface' attribute on root)"
                  ))
        old_commands = []

        for selection in root.childNodes:
            if selection.uri != XMLNS_IFACE:
                continue
            if selection.name != 'selection':
                if selection.name == 'command':
                    old_commands.append(Command(selection, None))
                continue

            requires = []
            bindings = []
            digests = []
            commands = {}
            for elem in selection.childNodes:
                if elem.uri != XMLNS_IFACE:
                    continue
                if elem.name in binding_names:
                    bindings.append(process_binding(elem))
                elif elem.name == 'requires':
                    dep = process_depends(elem, None)
                    requires.append(dep)
                elif elem.name == 'manifest-digest':
                    for aname, avalue in elem.attrs.items():
                        digests.append(
                            zerostore.format_algorithm_digest_pair(
                                aname, avalue))
                elif elem.name == 'command':
                    name = elem.getAttribute('name')
                    assert name, "Missing name attribute on <command>"
                    commands[name] = Command(elem, None)

            # For backwards compatibility, allow getting the digest from the ID
            sel_id = selection.attrs['id']
            local_path = selection.attrs.get("local-path", None)
            if (not local_path) and '=' in sel_id:
                alg = sel_id.split('=', 1)[0]
                if alg in ('sha1', 'sha1new', 'sha256'):
                    if sel_id not in digests:
                        digests.append(sel_id)

            iface_uri = selection.attrs['interface']

            s = XMLSelection(requires, bindings, selection.attrs, digests,
                             commands)
            self.selections[iface_uri] = s

        if self.command is None:
            # Old style selections document
            if old_commands:
                # 0launch 0.52 to 1.1
                self.command = 'run'
                iface = self.interface

                for command in old_commands:
                    command.qdom.attrs['name'] = 'run'
                    self.selections[iface].commands['run'] = command
                    runner = command.get_runner()
                    if runner:
                        iface = runner.interface
                    else:
                        iface = None
            else:
                # 0launch < 0.51
                root_sel = self.selections[self.interface]
                main = root_sel.attrs.get('main', None)
                if main is not None:
                    root_sel.commands['run'] = Command(
                        Element(XMLNS_IFACE, 'command', {
                            'path': main,
                            'name': 'run'
                        }), None)
                    self.command = 'run'

        elif self.command == '':
            # New style, but no command requested
            self.command = None
            assert not old_commands, "<command> list in new-style selections document!"
Exemple #8
0
    def get_failure_reason(self):
        """Return an exception explaining why the solve failed."""
        assert not self.ready

        sels = self.selections.selections

        iface_cache = self.config.iface_cache

        problem = self._problem
        impls_for_iface = self._impls_for_iface
        assert impls_for_iface

        def show(iface_uri):
            # Find all restrictions that are in play and affect this interface
            sel = sels[iface_uri]
            if sel:
                msg = '{version} ({impl})'.format(version=sel.version,
                                                  impl=sel.id)
            else:
                msg = "(problem)"

            iface = iface_cache.get_interface(iface_uri)

            impls = impls_for_iface[iface_cache.get_interface(iface_uri)]
            impls = [i for i in impls if not isinstance(i, _DummyImpl)]

            def apply_restrictions(impls, restrictions):
                for r in restrictions:
                    impls = [i for i in impls if r.meets_restriction(i)]
                return impls

            # orig_impls is all the implementations passed to the SAT solver (these are the
            # ones with a compatible OS, CPU, etc). They are sorted most desirable first.
            orig_impls = impls

            def get_machine_group(impl):
                machine = impl.machine
                if machine and machine != 'src':
                    return arch.machine_groups.get(machine, 0)
                return None

            example_machine_impl = None  # An example chosen impl with a machine type

            our_feed = iface_cache.get_feed(iface_uri)
            our_replacement = our_feed.get_replaced_by() if our_feed else None

            # For each selected implementation...
            for other_uri, other_sel in sels.items():
                # Check for interface-level conflicts
                other_iface = iface_cache.get_feed(other_uri)
                if other_iface and other_iface.get_replaced_by() == iface_uri:
                    msg += "\n    " + _(
                        "Replaces (and therefore conflicts with) {old}"
                    ).format(old=other_uri)
                    if other_sel:
                        impls = []

                if our_replacement == other_uri:
                    msg += "\n    " + _(
                        "Replaced by (and therefore conflicts with) {old}"
                    ).format(old=other_uri)
                    if other_sel:
                        impls = []

                # Otherwise, if we didn't select an implementation then that can't be causing a problem
                if not other_sel: continue

                if example_machine_impl is None:
                    required_machine_group = get_machine_group(other_sel.impl)
                    if required_machine_group is not None:
                        example_machine_impl = other_sel.impl

                for dep in other_sel.impl.requires:
                    if not isinstance(dep, model.InterfaceRestriction):
                        continue
                    # If it depends on us and has restrictions...
                    if dep.interface == iface_uri and dep.restrictions:
                        # Report the restriction
                        msg += "\n    " + _(
                            "{iface} {version} requires {reqs}").format(
                                iface=other_uri,
                                version=other_sel.version,
                                reqs=', '.join(
                                    str(r) for r in dep.restrictions))

                        # Remove implementations incompatible with the other selections
                        impls = apply_restrictions(impls, dep.restrictions)

            # Check for user-supplied restrictions
            user = self.extra_restrictions.get(iface, [])
            if user:
                msg += "\n    " + _("User requested {reqs}").format(
                    reqs=', '.join(str(r) for r in user))
                impls = apply_restrictions(impls, user)

            if sel is None:
                # Report on available implementations
                all_impls = self.details.get(iface, {})
                if not orig_impls:
                    if not all_impls:
                        msg += "\n    " + _("No known implementations at all")
                    else:
                        # No implementations were passed to the solver.
                        msg += "\n    " + _("No usable implementations:")
                        for i, reason in all_impls[:5]:
                            msg += "\n      {impl}: {reason}".format(
                                impl=i, reason=reason)
                        if len(all_impls) > 5:
                            msg += "\n      ..."
                elif not impls:
                    msg += "\n    " + _(
                        "No usable implementations satisfy the restrictions")
                else:
                    # Might still be unusable e.g. if missing a required command. Show reasons, if any.
                    shown = 0
                    candidate_impls = set(impls)
                    for i, reason in all_impls:
                        if reason is _ForceImpl.reason:
                            # We're doing a justify_decision, and this wasn't the one the user specified
                            continue

                        if i not in candidate_impls:
                            # Skip, as hopefully obvious from above restrictions why not chosen
                            continue

                        if reason is None and example_machine_impl:
                            # Could be an architecture problem
                            this_machine_group = get_machine_group(i)
                            if this_machine_group is not None and this_machine_group != required_machine_group:
                                reason = _(
                                    "Can't use {this_arch} with selection of {other_name} ({other_arch})"
                                ).format(
                                    this_arch=i.machine,
                                    other_name=example_machine_impl.feed.
                                    get_name(),
                                    other_arch=example_machine_impl.machine)
                        if reason is None:
                            var = self._iface_to_vars[iface].get(i, None)
                            if var is None:
                                reason = "BUG: no var for impl!"
                            else:
                                varinfo = problem.get_varinfo_for_lit(var)
                                reason = "Hard to explain. Internal reason: {reason} => {assignment}".format(
                                    reason=varinfo.reason, assignment=varinfo)

                        if reason is not _ForceImpl.reason:
                            if shown >= 5:
                                msg += "\n      ..."
                                break
                            if shown == 0:
                                msg += "\n    " + _("Rejected candidates:")
                            msg += "\n      {impl}: {reason}".format(
                                impl=i, reason=reason)
                            shown += 1

            return msg

        msg = _("Can't find all required implementations:") + '\n' + \
          '\n'.join(["- %s -> %s" % (iface, show(iface)) for iface in sorted(sels)])

        if self.config.network_use == model.network_offline:
            msg += "\nNote: 0install is in off-line mode"

        return model.SafeException(msg)
Exemple #9
0
 def get_download(self, url, force=False, hint=None, factory=None):
     if self.allow_downloads:
         return handler.Handler.get_download(self, url, force, hint,
                                             factory)
     raise model.SafeException("DummyHandler: " + url)