Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

conan-source command shouldn't require default profile #12475

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion conan/api/subapi/profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def get_profile(self, profiles, settings=None, options=None, conf=None, cwd=None
loads the "profiles", composing them in order (last profile has priority), and
finally adding the individual settings, options (priority over the profiles)
"""
assert profiles and isinstance(profiles, list), "Please provide at least 1 profile"
assert isinstance(profiles, list), "Please provide a list of profiles"
loader = ProfileLoader(self._cache)
env = None # TODO: Not handling environment
profile = loader.from_cli_args(profiles, settings, options, env, conf, cwd)
Expand Down
12 changes: 3 additions & 9 deletions conan/cli/commands/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
from conan.cli.commands.install import _get_conanfile_path
from conan.cli.args import add_reference_args
from conan.api.conan_app import ConanApp
from conans.client.conanfile.configure import run_configure_method
from conans.client.graph.graph import CONTEXT_HOST
from conans.client.graph.profile_node_definer import initialize_conanfile_profile
from conans.client.source import run_source_method
from conans.errors import conanfile_exception_formatter
from conans.model.options import Options


@conan_command(group=COMMAND_GROUPS['creator'])
Expand All @@ -30,18 +28,14 @@ def source(conan_api, parser, *args):

# TODO: Decide API to put this
app = ConanApp(conan_api.cache_folder)
profile_host = conan_api.profiles.get_profile([conan_api.profiles.get_default_host()])

profile_host.conf.rebase_conf_definition(app.cache.new_config)
# This profile is empty, but with the conf from global.conf
profile = conan_api.profiles.get_profile([])
conanfile = app.loader.load_consumer(path,
name=args.name, version=args.version,
user=args.user, channel=args.channel,
graph_lock=None)

initialize_conanfile_profile(conanfile, profile_host, profile_host, CONTEXT_HOST, False)
run_configure_method(conanfile, down_options=Options(),
profile_options=profile_host.options, ref=None)

initialize_conanfile_profile(conanfile, profile, profile, CONTEXT_HOST, False)
# This is important, otherwise the ``conan source`` doesn't define layout and fails
if hasattr(conanfile, "layout"):
with conanfile_exception_formatter(conanfile, "layout"):
Expand Down
3 changes: 2 additions & 1 deletion conan/tools/cmake/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

def cmake_layout(conanfile, generator=None, src_folder=".", build_folder="build"):
"""

:param conanfile: The current recipe object. Always use ``self``.
:param generator: Allow defining the CMake generator. In most cases it doesn't need to be passed, as it will get the value from the configuration ``tools.cmake.cmaketoolchain:generator``, or it will automatically deduce the generator from the ``settings``
:param src_folder: Value for ``conanfile.folders.source``, change it if your source code
(and CMakeLists.txt) is in a subfolder.
:param build_folder: Specify the name of the "base" build folder. The default is "build", but
if that folder name is used by the project, a different one can be defined
"""
gen = conanfile.conf.get("tools.cmake.cmaketoolchain:generator", default=generator)
if gen:
Expand Down
29 changes: 17 additions & 12 deletions conan/tools/microsoft/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,29 @@ def vs_layout(conanfile):
:param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.
"""
conanfile.folders.test_output = ""
if not conanfile.settings.get_safe("build_type"):
subproject = conanfile.folders.subproject
conanfile.folders.source = subproject or "."
conanfile.folders.generators = os.path.join(subproject, "conan") if subproject else "conan"
conanfile.folders.build = subproject or "."
conanfile.cpp.source.includedirs = ["include"]

try:
build_type = str(conanfile.settings.build_type)
except ConanException:
raise ConanException("The 'vs_layout' requires the 'build_type' setting")
if not conanfile.settings.get_safe("arch"):
try:
arch = str(conanfile.settings.arch)
except ConanException:
raise ConanException("The 'vs_layout' requires the 'arch' setting")

if conanfile.settings.arch != "x86":
arch = msbuild_arch(conanfile.settings.arch)
if arch != "None" and arch != "x86":
arch = msbuild_arch(arch)
if not arch:
raise ConanException("The 'vs_layout' doesn't "
"work with the arch '{}'".format(conanfile.settings.arch))
bindirs = os.path.join(arch, str(conanfile.settings.build_type))
"work with the arch '{}'".format(arch))
bindirs = os.path.join(arch, build_type)
else:
bindirs = str(conanfile.settings.build_type)
bindirs = build_type

subproject = conanfile.folders.subproject
conanfile.folders.build = subproject or "."
conanfile.folders.generators = os.path.join(subproject, "conan") if subproject else "conan"
conanfile.folders.source = subproject or "."
conanfile.cpp.build.libdirs = [bindirs]
conanfile.cpp.build.bindirs = [bindirs]
conanfile.cpp.source.includedirs = ["include"]
1 change: 0 additions & 1 deletion conans/test/functional/layout/test_local_commands.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
import platform
import re
import textwrap

Expand Down
48 changes: 46 additions & 2 deletions conans/test/integration/command/source_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import unittest
from collections import OrderedDict

import pytest

from conans.paths import CONANFILE
from conans.test.assets.genconanfile import GenConanfile
from conans.test.utils.tools import TestClient, TestServer
from conans.util.files import save


class SourceTest(unittest.TestCase):
Expand Down Expand Up @@ -179,7 +182,6 @@ def test_retrieve_exports_sources(self):
self.assertIn("Sources downloaded from 'server0'", client.out)

def test_source_method_called_once(self):

"""
Test that the source() method will be executed just once, and the source code will
be shared for all the package builds.
Expand Down Expand Up @@ -210,7 +212,6 @@ def source(self):
assert "Running source!" not in client.out

def test_source_method_called_again_if_left_dirty(self):

"""
If we fail in retreiving sources make sure the source() method will be called
next time we create
Expand All @@ -236,3 +237,46 @@ def source(self):
client.run("create . --name=lib --version=1.0", assert_error=True)
assert "Running source!" in client.out
assert "Source folder is corrupted, forcing removal" in client.out


class TestSourceWithoutDefaultProfile:
# https://github.com/conan-io/conan/issues/12371
@pytest.fixture()
def client(self):
c = TestClient()
# The ``source()`` should still receive necessary configuration
save(c.cache.new_config_path, "tools.files.download:download_cache=MYCACHE")
# Make sure we don't have default profile
os.remove(c.cache.default_profile_path)
return c

def test_source_without_default_profile(self, client):
conanfile = textwrap.dedent("""
from conan import ConanFile

class Pkg(ConanFile):
def source(self):
c = self.conf.get("tools.files.download:download_cache")
self.output.info("CACHE:{}!!".format(c))
""")
client.save({"conanfile.py": conanfile})
client.run("source .")
assert "conanfile.py: Calling source()" in client.out
assert "CACHE:MYCACHE!!" in client.out

def test_source_with_layout(self, client):
conanfile = textwrap.dedent("""
from conan import ConanFile
from conan.tools.cmake import cmake_layout
class Pkg(ConanFile):
settings = "os", "compiler", "arch", "build_type"
def layout(self):
cmake_layout(self)
def source(self):
c = self.conf.get("tools.files.download:download_cache")
self.output.info("CACHE:{}!!".format(c))
""")
client.save({"conanfile.py": conanfile})
client.run("source .")
assert "conanfile.py: Calling source()" in client.out
assert "CACHE:MYCACHE!!" in client.out