Exemplo n.º 1
0
    def load_graph(self, reference, create_reference, graph_info, build_mode,
                   check_updates, update, remote_name, recorder, workspace):
        def _inject_require(conanfile, reference):
            """ test_package functionality requires injecting the tested package as requirement
            before running the install
            """
            require = conanfile.requires.get(reference.name)
            if require:
                require.conan_reference = require.range_reference = reference
            else:
                conanfile.requires(str(reference))
            conanfile._conan_user = reference.user
            conanfile._conan_channel = reference.channel

        # Computing the full dependency graph
        profile = graph_info.profile
        cache_settings = profile.processed_settings
        processed_profile = ProcessedProfile(profile, create_reference)
        if isinstance(reference,
                      list):  # Install workspace with multiple root nodes
            conanfile = self._loader.load_virtual(reference, processed_profile)
        elif isinstance(reference, ConanFileReference):
            # create without test_package and install <ref>
            conanfile = self._loader.load_virtual([reference],
                                                  processed_profile)
        else:
            output = ScopedOutput("PROJECT", self._output)
            if reference.endswith(".py"):
                conanfile = self._loader.load_conanfile(reference,
                                                        output,
                                                        processed_profile,
                                                        consumer=True)
                if create_reference:  # create with test_package
                    _inject_require(conanfile, create_reference)
            else:
                conanfile = self._loader.load_conanfile_txt(
                    reference, output, processed_profile)

        build_mode = BuildMode(build_mode, self._output)
        root_node = Node(None, conanfile)
        deps_graph = self._load_graph(
            root_node,
            check_updates,
            update,
            build_mode=build_mode,
            remote_name=remote_name,
            profile_build_requires=profile.build_requires,
            recorder=recorder,
            workspace=workspace,
            processed_profile=processed_profile)

        # THIS IS NECESSARY to store dependencies options in profile, for consumer
        # FIXME: This is a hack. Might dissapear if the graph for local commands is always recomputed
        graph_info.options = root_node.conanfile.options.values

        version_ranges_output = self._resolver.output
        if version_ranges_output:
            self._output.success("Version ranges solved")
            for msg in version_ranges_output:
                self._output.info("    %s" % msg)
            self._output.writeln("")

        build_mode.report_matches()
        return deps_graph, conanfile, cache_settings
Exemplo n.º 2
0
    def load_graph(self, reference, create_reference, graph_info, build_mode,
                   check_updates, update, remote_name, recorder, workspace):
        def _inject_require(conanfile, ref):
            """ test_package functionality requires injecting the tested package as requirement
            before running the install
            """
            require = conanfile.requires.get(ref.name)
            if require:
                require.ref = require.range_ref = ref
            else:
                conanfile.requires(str(ref))
            conanfile._conan_user = ref.user
            conanfile._conan_channel = ref.channel

        # Computing the full dependency graph
        profile = graph_info.profile
        processed_profile = ProcessedProfile(profile, create_reference)
        ref = None
        if isinstance(reference,
                      list):  # Install workspace with multiple root nodes
            conanfile = self._loader.load_virtual(reference, processed_profile)
            root_node = Node(ref, conanfile, recipe=RECIPE_VIRTUAL)
        elif isinstance(reference, ConanFileReference):
            # create without test_package and install <ref>
            conanfile = self._loader.load_virtual([reference],
                                                  processed_profile)
            root_node = Node(ref, conanfile, recipe=RECIPE_VIRTUAL)
        else:
            path = reference
            if path.endswith(".py"):
                test = str(create_reference) if create_reference else None
                conanfile = self._loader.load_consumer(
                    path,
                    processed_profile,
                    test=test,
                    name=graph_info.root.name,
                    version=graph_info.root.version,
                    user=graph_info.root.user,
                    channel=graph_info.root.channel)
                if create_reference:  # create with test_package
                    _inject_require(conanfile, create_reference)

                ref = ConanFileReference(conanfile.name,
                                         conanfile.version,
                                         conanfile._conan_user,
                                         conanfile._conan_channel,
                                         validate=False)
            else:
                conanfile = self._loader.load_conanfile_txt(
                    path, processed_profile, ref=graph_info.root)

            root_node = Node(ref, conanfile, recipe=RECIPE_CONSUMER)

        build_mode = BuildMode(build_mode, self._output)
        deps_graph = self._load_graph(
            root_node,
            check_updates,
            update,
            build_mode=build_mode,
            remote_name=remote_name,
            profile_build_requires=profile.build_requires,
            recorder=recorder,
            workspace=workspace,
            processed_profile=processed_profile)

        # THIS IS NECESSARY to store dependencies options in profile, for consumer
        # FIXME: This is a hack. Might dissapear if the graph for local commands is always recomputed
        graph_info.options = root_node.conanfile.options.values

        version_ranges_output = self._resolver.output
        if version_ranges_output:
            self._output.success("Version ranges solved")
            for msg in version_ranges_output:
                self._output.info("    %s" % msg)
            self._output.writeln("")

        build_mode.report_matches()
        return deps_graph, conanfile
Exemplo n.º 3
0
    def _evaluate_node(self, node, build_mode, update, remotes):
        assert node.binary is None, "Node.binary should be None"
        assert node.package_id is not None, "Node.package_id shouldn't be None"
        assert node.package_id != PACKAGE_ID_UNKNOWN, "Node.package_id shouldn't be Unknown"
        assert node.prev is None, "Node.prev should be None"

        # If it has lock
        locked = node.graph_lock_node
        if locked and locked.package_id and locked.package_id != PACKAGE_ID_UNKNOWN:
            pref = PackageReference(locked.ref, locked.package_id,
                                    locked.prev)  # Keep locked PREV
            self._process_node(node, pref, build_mode, update, remotes)
            if node.binary == BINARY_MISSING and build_mode.allowed(
                    node.conanfile):
                node.binary = BINARY_BUILD
            if node.binary == BINARY_BUILD:
                locked.unlock_prev()

            if node.package_id != locked.package_id:  # It was a compatible package
                # https://github.com/conan-io/conan/issues/9002
                # We need to iterate to search the compatible combination
                for compatible_package in node.conanfile.compatible_packages:
                    comp_package_id = compatible_package.package_id()
                    if comp_package_id == locked.package_id:
                        node._package_id = locked.package_id  # FIXME: Ugly definition of private
                        node.conanfile.settings.values = compatible_package.settings
                        node.conanfile.options.values = compatible_package.options
                        break
                else:
                    raise ConanException(
                        "'%s' package-id '%s' doesn't match the locked one '%s'"
                        %
                        (repr(locked.ref), node.package_id, locked.package_id))
        else:
            assert node.prev is None, "Non locked node shouldn't have PREV in evaluate_node"
            assert node.binary is None, "Node.binary should be None if not locked"
            pref = PackageReference(node.ref, node.package_id)
            self._process_node(node, pref, build_mode, update, remotes)
            if node.binary in (BINARY_MISSING, BINARY_INVALID):
                if node.conanfile.compatible_packages:
                    compatible_build_mode = BuildMode(None, self._out)
                    for compatible_package in node.conanfile.compatible_packages:
                        package_id = compatible_package.package_id()
                        if package_id == node.package_id:
                            node.conanfile.output.info(
                                "Compatible package ID %s equal to the "
                                "default package ID" % package_id)
                            continue
                        pref = PackageReference(node.ref, package_id)
                        node.binary = None  # Invalidate it
                        # NO Build mode
                        self._process_node(node, pref, compatible_build_mode,
                                           update, remotes)
                        assert node.binary is not None
                        if node.binary not in (BINARY_MISSING, ):
                            node.conanfile.output.info(
                                "Main binary package '%s' missing. Using "
                                "compatible package '%s'" %
                                (node.package_id, package_id))

                            # Modifying package id under the hood, FIXME
                            node._package_id = package_id
                            # So they are available in package_info() method
                            node.conanfile.settings.values = compatible_package.settings
                            # TODO: Conan 2.0 clean this ugly
                            node.conanfile.options._package_options.values = compatible_package.options._package_values
                            break
                    if node.binary == BINARY_MISSING and node.package_id == PACKAGE_ID_INVALID:
                        node.binary = BINARY_INVALID
                if node.binary == BINARY_MISSING and build_mode.allowed(
                        node.conanfile):
                    node.binary = BINARY_BUILD

            if locked:
                # package_id was not locked, this means a base lockfile that is being completed
                locked.complete_base_node(node.package_id, node.prev)
Exemplo n.º 4
0
def deps_install(app, ref_or_path, install_folder, graph_info, remotes=None, build_modes=None,
                 update=False, manifest_folder=None, manifest_verify=False,
                 manifest_interactive=False, generators=None, no_imports=False,
                 create_reference=None, keep_build=False, recorder=None):
    """ Fetch and build all dependencies for the given reference
    @param app: The ConanApp instance with all collaborators
    @param ref_or_path: ConanFileReference or path to user space conanfile
    @param install_folder: where the output files will be saved
    @param build_modes: List of build_modes specified
    @param update: Check for updated in the upstream remotes (and update)
    @param manifest_folder: Folder to install the manifests
    @param manifest_verify: Verify dependencies manifests against stored ones
    @param manifest_interactive: Install deps manifests in folder for later verify, asking user
    for confirmation
    @param generators: List of generators from command line. If False, no generator will be
    written
    @param no_imports: Install specified packages but avoid running imports

    """
    out, user_io, graph_manager, cache = app.out, app.user_io, app.graph_manager, app.cache
    remote_manager, hook_manager = app.remote_manager, app.hook_manager
    if generators is not False:
        generators = set(generators) if generators else set()
        generators.add("txt")  # Add txt generator by default

    if graph_info.profile_build:
        out.info("Configuration (profile_host):")
        out.writeln(graph_info.profile_host.dumps())
        out.info("Configuration (profile_build):")
        out.writeln(graph_info.profile_build.dumps())
    else:
        out.info("Configuration:")
        out.writeln(graph_info.profile_host.dumps())

    deps_graph = graph_manager.load_graph(ref_or_path, create_reference, graph_info, build_modes,
                                          False, update, remotes, recorder)
    root_node = deps_graph.root
    conanfile = root_node.conanfile
    if root_node.recipe == RECIPE_VIRTUAL:
        out.highlight("Installing package: %s" % str(ref_or_path))
    else:
        conanfile.output.highlight("Installing package")
    print_graph(deps_graph, out)

    try:
        if cross_building(conanfile):
            settings = get_cross_building_settings(conanfile)
            message = "Cross-build from '%s:%s' to '%s:%s'" % settings
            out.writeln(message, Color.BRIGHT_MAGENTA)
    except ConanException:  # Setting os doesn't exist
        pass

    installer = BinaryInstaller(app, recorder=recorder)
    # TODO: Extract this from the GraphManager, reuse same object, check args earlier
    build_modes = BuildMode(build_modes, out)
    installer.install(deps_graph, remotes, build_modes, update, keep_build=keep_build,
                      graph_info=graph_info)

    graph_info.graph_lock.complete_matching_prevs()

    if manifest_folder:
        manifest_manager = ManifestManager(manifest_folder, user_io=user_io, cache=cache)
        for node in deps_graph.nodes:
            if node.recipe in (RECIPE_CONSUMER, RECIPE_VIRTUAL):
                continue
            complete_recipe_sources(remote_manager, cache, node.conanfile, node.ref,
                                    remotes)
        manifest_manager.check_graph(deps_graph, verify=manifest_verify,
                                     interactive=manifest_interactive)
        manifest_manager.print_log()

    if install_folder:
        conanfile.install_folder = install_folder
        # Write generators
        output = conanfile.output if root_node.recipe != RECIPE_VIRTUAL else out
        if generators is not False:
            tmp = list(conanfile.generators)  # Add the command line specified generators
            tmp.extend([g for g in generators if g not in tmp])
            conanfile.generators = tmp
            write_generators(conanfile, install_folder, output)
            write_toolchain(conanfile, install_folder, output)
        if not isinstance(ref_or_path, ConanFileReference):
            # Write conaninfo
            content = normalize(conanfile.info.dumps())
            save(os.path.join(install_folder, CONANINFO), content)
            output.info("Generated %s" % CONANINFO)
            graph_info.save(install_folder)
            output.info("Generated graphinfo")
            graph_lock_file = GraphLockFile(graph_info.profile_host, graph_info.profile_build,
                                            graph_info.graph_lock)
            graph_lock_file.save(os.path.join(install_folder, "conan.lock"))
        if not no_imports:
            run_imports(conanfile, install_folder)
        call_system_requirements(conanfile, conanfile.output)

        if not create_reference and isinstance(ref_or_path, ConanFileReference):
            # The conanfile loaded is a virtual one. The one w deploy is the first level one
            neighbours = deps_graph.root.neighbors()
            deploy_conanfile = neighbours[0].conanfile
            if hasattr(deploy_conanfile, "deploy") and callable(deploy_conanfile.deploy):
                run_deploy(deploy_conanfile, install_folder)
Exemplo n.º 5
0
    def test_allowed(self):
        build_mode = BuildMode(["outdated", "missing"], self.output)
        self.assertTrue(build_mode.allowed(self.conanfile))

        build_mode = BuildMode([], self.output)
        self.assertFalse(build_mode.allowed(self.conanfile))
Exemplo n.º 6
0
    def test_casing(self):
        reference = ConanFileReference.loads("Boost/1.69.0@user/stable")

        build_mode = BuildMode(["Boost"], self.output)
        self.assertTrue(build_mode.forced(self.conanfile, reference))
        build_mode = BuildMode(["Bo*"], self.output)
        self.assertTrue(build_mode.forced(self.conanfile, reference))
        build_mode.report_matches()
        self.assertEqual("", self.output)

        build_mode = BuildMode(["boost"], self.output)
        self.assertFalse(build_mode.forced(self.conanfile, reference))
        build_mode = BuildMode(["bo*"], self.output)
        self.assertFalse(build_mode.forced(self.conanfile, reference))
        build_mode.report_matches()
        self.assertIn("ERROR: No package matching", self.output)
Exemplo n.º 7
0
 def test_full_reference_build_force(self):
     reference = ConanFileReference.loads("Bar/0.1@user/testing")
     build_mode = BuildMode(["Bar/0.1@user/testing"], self.output)
     self.assertTrue(build_mode.forced(self.conanfile, reference))
     build_mode.report_matches()
     self.assertEqual("", self.output)
Exemplo n.º 8
0
 def test_multiple_builds(self):
     reference = ConanFileReference.loads("Bar/0.1@user/stable")
     build_mode = BuildMode(["Bar", "Foo"], self.output)
     self.assertTrue(build_mode.forced(self.conanfile, reference))
     build_mode.report_matches()
     self.assertIn("ERROR: No package matching", self.output)
Exemplo n.º 9
0
    def test_pattern_matching(self):
        build_mode = BuildMode(["Boost*"], self.output)
        reference = ConanFileReference.loads("Boost/1.69.0@user/stable")
        self.assertTrue(build_mode.forced(self.conanfile, reference))
        reference = ConanFileReference.loads("Boost_Addons/1.0.0@user/stable")
        self.assertTrue(build_mode.forced(self.conanfile, reference))
        reference = ConanFileReference.loads("MyBoost/1.0@user/stable")
        self.assertFalse(build_mode.forced(self.conanfile, reference))
        reference = ConanFileReference.loads("foo/Boost@user/stable")
        self.assertFalse(build_mode.forced(self.conanfile, reference))
        reference = ConanFileReference.loads("foo/1.0@Boost/stable")
        self.assertFalse(build_mode.forced(self.conanfile, reference))
        reference = ConanFileReference.loads("foo/1.0@user/Boost")
        self.assertFalse(build_mode.forced(self.conanfile, reference))

        build_mode = BuildMode(["foo/*@user/stable"], self.output)
        reference = ConanFileReference.loads("foo/1.0.0@user/stable")
        self.assertTrue(build_mode.forced(self.conanfile, reference))
        reference = ConanFileReference.loads("foo/1.0@user/stable")
        self.assertTrue(build_mode.forced(self.conanfile, reference))
        reference = ConanFileReference.loads("foo/1.0.0-abcdefg@user/stable")
        self.assertTrue(build_mode.forced(self.conanfile, reference))

        build_mode = BuildMode(["*@user/stable"], self.output)
        reference = ConanFileReference.loads("foo/1.0.0@user/stable")
        self.assertTrue(build_mode.forced(self.conanfile, reference))
        reference = ConanFileReference.loads("bar/1.0@user/stable")
        self.assertTrue(build_mode.forced(self.conanfile, reference))
        reference = ConanFileReference.loads("foo/1.0.0-abcdefg@user/stable")
        self.assertTrue(build_mode.forced(self.conanfile, reference))
        reference = ConanFileReference.loads("foo/1.0.0@NewUser/stable")
        self.assertFalse(build_mode.forced(self.conanfile, reference))

        build_mode = BuildMode(["*Tool"], self.output)
        reference = ConanFileReference.loads("Tool/0.1@lasote/stable")
        self.assertTrue(build_mode.forced(self.conanfile, reference))
        reference = ConanFileReference.loads("PythonTool/0.1@lasote/stable")
        self.assertTrue(build_mode.forced(self.conanfile, reference))
        reference = ConanFileReference.loads("SomeTool/1.2@user/channel")
        self.assertTrue(build_mode.forced(self.conanfile, reference))

        build_mode.report_matches()
        self.assertEqual("", self.output)
Exemplo n.º 10
0
 def test_invalid_configuration(self):
     for mode in ["outdated", "missing", "cascade"]:
         with six.assertRaisesRegex(
                 self, ConanException,
                 "--build=never not compatible with other options"):
             BuildMode([mode, "never"], self.output)
Exemplo n.º 11
0
    def install(self, reference, install_folder, profile, remote_name=None, build_modes=None,
                update=False, manifest_folder=None, manifest_verify=False,
                manifest_interactive=False, generators=None, no_imports=False, inject_require=None,
                install_reference=False, keep_build=False):
        """ Fetch and build all dependencies for the given reference
        @param reference: ConanFileReference or path to user space conanfile
        @param install_folder: where the output files will be saved
        @param remote: install only from that remote
        @param profile: Profile object with both the -s introduced options and profile read values
        @param build_modes: List of build_modes specified
        @param update: Check for updated in the upstream remotes (and update)
        @param manifest_folder: Folder to install the manifests
        @param manifest_verify: Verify dependencies manifests against stored ones
        @param manifest_interactive: Install deps manifests in folder for later verify, asking user
        for confirmation
        @param generators: List of generators from command line. If False, no generator will be
        written
        @param no_imports: Install specified packages but avoid running imports
        @param inject_require: Reference to add as a requirement to the conanfile
        """

        if generators is not False:
            generators = set(generators) if generators else set()
            generators.add("txt")  # Add txt generator by default

        remote_proxy = self.get_proxy(remote_name=remote_name)

        loader = self.get_loader(profile)
        if not install_reference:
            if isinstance(reference, ConanFileReference):  # is a create
                loader.dev_reference = reference
            elif inject_require:
                loader.dev_reference = inject_require
        conanfile = self._load_install_conanfile(loader, reference)
        if inject_require:
            self._inject_require(conanfile, inject_require)
        graph_builder = self._get_graph_builder(loader, remote_proxy)
        deps_graph = graph_builder.load_graph(conanfile, False, update)

        if not isinstance(reference, ConanFileReference):
            output = ScopedOutput(("%s (test package)" % str(inject_require)) if inject_require else "PROJECT",
                                  self._user_io.out)
            output.highlight("Installing %s" % reference)
        else:
            output = ScopedOutput(str(reference), self._user_io.out)
            output.highlight("Installing package")
        print_graph(deps_graph, self._user_io.out)

        try:
            if cross_building(loader._settings):
                b_os, b_arch, h_os, h_arch = get_cross_building_settings(loader._settings)
                message = "Cross-build from '%s:%s' to '%s:%s'" % (b_os, b_arch, h_os, h_arch)
                self._user_io.out.writeln(message, Color.BRIGHT_MAGENTA)
        except ConanException:  # Setting os doesn't exist
            pass

        build_mode = BuildMode(build_modes, self._user_io.out)
        build_requires = BuildRequires(loader, graph_builder, self._registry)
        installer = ConanInstaller(self._client_cache, output, remote_proxy, build_mode,
                                   build_requires, recorder=self._recorder)

        # Apply build_requires to consumer conanfile
        if not isinstance(reference, ConanFileReference):
            build_requires.install("", conanfile, installer, profile.build_requires, output, update)

        installer.install(deps_graph, profile.build_requires, keep_build, update=update)
        build_mode.report_matches()

        if manifest_folder:
            manifest_manager = ManifestManager(manifest_folder, user_io=self._user_io,
                                               client_cache=self._client_cache)
            for node in deps_graph.nodes:
                if not node.conan_ref:
                    continue
                conanfile = node.conanfile
                complete_recipe_sources(self._remote_manager, self._client_cache, self._registry,
                                        conanfile, node.conan_ref)
            manifest_manager.check_graph(deps_graph,
                                         verify=manifest_verify,
                                         interactive=manifest_interactive)
            manifest_manager.print_log()

        if install_folder:
            # Write generators
            if generators is not False:
                tmp = list(conanfile.generators)  # Add the command line specified generators
                tmp.extend([g for g in generators if g not in tmp])
                conanfile.generators = tmp
                write_generators(conanfile, install_folder, output)
            if not isinstance(reference, ConanFileReference):
                # Write conaninfo
                content = normalize(conanfile.info.dumps())
                save(os.path.join(install_folder, CONANINFO), content)
                output.info("Generated %s" % CONANINFO)
            if not no_imports:
                run_imports(conanfile, install_folder, output)
            call_system_requirements(conanfile, output)

            if install_reference:
                # The conanfile loaded is really a virtual one. The one with the deploy is the first level one
                deploy_conanfile = deps_graph.inverse_levels()[1][0].conanfile
                if hasattr(deploy_conanfile, "deploy") and callable(deploy_conanfile.deploy):
                    run_deploy(deploy_conanfile, install_folder, output)
Exemplo n.º 12
0
    def load_graph(self, reference, create_reference, graph_info, build_mode, check_updates, update,
                   remotes, recorder, apply_build_requires=True):

        def _inject_require(conanfile, ref):
            """ test_package functionality requires injecting the tested package as requirement
            before running the install
            """
            require = conanfile.requires.get(ref.name)
            if require:
                require.ref = require.range_ref = ref
            else:
                conanfile.requires.add_ref(ref)
            conanfile._conan_user = ref.user
            conanfile._conan_channel = ref.channel

        # Computing the full dependency graph
        profile = graph_info.profile
        processed_profile = profile
        processed_profile.dev_reference = create_reference
        ref = None
        graph_lock = graph_info.graph_lock
        if isinstance(reference, list):  # Install workspace with multiple root nodes
            conanfile = self._loader.load_virtual(reference, processed_profile,
                                                  scope_options=False)
            root_node = Node(ref, conanfile, recipe=RECIPE_VIRTUAL)
        elif isinstance(reference, ConanFileReference):
            if not self._cache.config.revisions_enabled and reference.revision is not None:
                raise ConanException("Revisions not enabled in the client, specify a "
                                     "reference without revision")
            # create without test_package and install <ref>
            conanfile = self._loader.load_virtual([reference], processed_profile)
            root_node = Node(ref, conanfile, recipe=RECIPE_VIRTUAL)
            if graph_lock:  # Find the Node ID in the lock of current root
                graph_lock.find_consumer_node(root_node, reference)
        else:
            path = reference
            if path.endswith(".py"):
                test = str(create_reference) if create_reference else None
                lock_python_requires = None
                # do not try apply lock_python_requires for test_package/conanfile.py consumer
                if graph_lock and not create_reference:
                    if graph_info.root.name is None:
                        # If the graph_info information is not there, better get what we can from
                        # the conanfile
                        conanfile = self._loader.load_class(path)
                        graph_info.root = ConanFileReference(graph_info.root.name or conanfile.name,
                                                             graph_info.root.version or conanfile.version,
                                                             graph_info.root.user,
                                                             graph_info.root.channel, validate=False)
                    node_id = graph_lock.get_node(graph_info.root)
                    lock_python_requires = graph_lock.python_requires(node_id)

                conanfile = self._loader.load_consumer(path, processed_profile, test=test,
                                                       name=graph_info.root.name,
                                                       version=graph_info.root.version,
                                                       user=graph_info.root.user,
                                                       channel=graph_info.root.channel,
                                                       lock_python_requires=lock_python_requires)
                if create_reference:  # create with test_package
                    _inject_require(conanfile, create_reference)

                ref = ConanFileReference(conanfile.name, conanfile.version,
                                         conanfile._conan_user, conanfile._conan_channel,
                                         validate=False)
            else:
                conanfile = self._loader.load_conanfile_txt(path, processed_profile,
                                                            ref=graph_info.root)

            root_node = Node(ref, conanfile, recipe=RECIPE_CONSUMER, path=path)

            if graph_lock:  # Find the Node ID in the lock of current root
                graph_lock.find_consumer_node(root_node, create_reference)

        build_mode = BuildMode(build_mode, self._output)
        deps_graph = self._load_graph(root_node, check_updates, update,
                                      build_mode=build_mode, remotes=remotes,
                                      profile_build_requires=profile.build_requires,
                                      recorder=recorder,
                                      processed_profile=processed_profile,
                                      apply_build_requires=apply_build_requires,
                                      graph_lock=graph_lock)

        # THIS IS NECESSARY to store dependencies options in profile, for consumer
        # FIXME: This is a hack. Might dissapear if graph for local commands is always recomputed
        graph_info.options = root_node.conanfile.options.values
        if ref:
            graph_info.root = ref
        if graph_info.graph_lock is None:
            graph_info.graph_lock = GraphLock(deps_graph)
        else:
            graph_info.graph_lock.update_check_graph(deps_graph, self._output)

        version_ranges_output = self._resolver.output
        if version_ranges_output:
            self._output.success("Version ranges solved")
            for msg in version_ranges_output:
                self._output.info("    %s" % msg)
            self._output.writeln("")

        build_mode.report_matches()
        return deps_graph, conanfile
Exemplo n.º 13
0
    def _evaluate_node(self, node, build_mode, update, remotes):
        assert node.binary is None, "Node.binary should be None"
        assert node.package_id is not None, "Node.package_id shouldn't be None"
        assert node.package_id != PACKAGE_ID_UNKNOWN, "Node.package_id shouldn't be Unknown"
        assert node.prev is None, "Node.prev should be None"

        # If it has lock
        locked = node.graph_lock_node
        if locked and locked.package_id:  # if package_id = None, nothing to lock here
            # First we update the package_id, just in case there are differences or something
            if locked.package_id != node.package_id and locked.package_id != PACKAGE_ID_UNKNOWN:
                raise ConanException(
                    "'%s' package-id '%s' doesn't match the locked one '%s'" %
                    (repr(locked.ref), node.package_id, locked.package_id))
            locked.package_id = node.package_id  # necessary for PACKAGE_ID_UNKNOWN
            pref = PackageReference(locked.ref, locked.package_id,
                                    locked.prev)  # Keep locked PREV
            self._process_node(node, pref, build_mode, update, remotes)
            if node.binary == BINARY_MISSING and build_mode.allowed(
                    node.conanfile):
                node.binary = BINARY_BUILD
            if node.binary == BINARY_BUILD:
                locked.unlock_prev()
        else:
            assert node.prev is None, "Non locked node shouldn't have PREV in evaluate_node"
            assert node.binary is None, "Node.binary should be None if not locked"
            pref = PackageReference(node.ref, node.package_id)
            self._process_node(node, pref, build_mode, update, remotes)
            if node.binary in (BINARY_MISSING, BINARY_INVALID):
                if node.conanfile.compatible_packages:
                    compatible_build_mode = BuildMode(None, self._out)
                    for compatible_package in node.conanfile.compatible_packages:
                        package_id = compatible_package.package_id()
                        if package_id == node.package_id:
                            node.conanfile.output.info(
                                "Compatible package ID %s equal to the "
                                "default package ID" % package_id)
                            continue
                        pref = PackageReference(node.ref, package_id)
                        node.binary = None  # Invalidate it
                        # NO Build mode
                        self._process_node(node, pref, compatible_build_mode,
                                           update, remotes)
                        assert node.binary is not None
                        if node.binary not in (BINARY_MISSING, ):
                            node.conanfile.output.info(
                                "Main binary package '%s' missing. Using "
                                "compatible package '%s'" %
                                (node.package_id, package_id))

                            # Modifying package id under the hood, FIXME
                            node._package_id = package_id
                            # So they are available in package_info() method
                            node.conanfile.settings.values = compatible_package.settings
                            node.conanfile.options.values = compatible_package.options
                            break
                    if node.binary == BINARY_MISSING and node.package_id == PACKAGE_ID_INVALID:
                        node.binary = BINARY_INVALID
                if node.binary == BINARY_MISSING and build_mode.allowed(
                        node.conanfile):
                    node.binary = BINARY_BUILD

            if locked:
                # package_id was not locked, this means a base lockfile that is being completed
                locked.complete_base_node(node.package_id, node.prev)
Exemplo n.º 14
0
 def test_non_matching_full_reference_build_force(self):
     reference = ConanFileReference.loads("Bar/0.1@user/stable")
     build_mode = BuildMode(["Bar/0.1@user/testing"], self.output)
     self.assertFalse(build_mode.forced(self.conanfile, reference))
     build_mode.report_matches()
     self.assertIn("No package matching 'Bar/0.1@user/testing' pattern", self.output)
Exemplo n.º 15
0
 def test_invalid_configuration(self):
     with self.assertRaisesRegexp(ConanException,
                                  "--build=never not compatible with other options"):
         BuildMode(["outdated", "missing", "never"], self.output)