Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 98d8f6a
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Sun Dec 17 20:37:54 2023 +0100

    Try to address NMakeDeps quoting issues (conan-io#15140)

    * Better spacing and quotes for defines in NMakeDeps

    * No need to escape parenthesis in defines

    * Fix tests

    * Follow proper syntax definition

    * Add numeric test

    * Ensure functional tests cover the quoting

    * Add test for space in values

    * fix values with whitespace in nmaketoolchain defines

    * fix nmakedeps and test

    * simplify

    * review

    ---------

    Co-authored-by: danimtb <danimanzaneque@gmail.com>

commit 94a3549
Author: memsharded <james@conan.io>
Date:   Sat Dec 16 23:45:06 2023 +0100

    fix broken test after source() VirtualBuildEnv

commit 6958893
Author: James <james@conan.io>
Date:   Fri Dec 15 14:00:05 2023 +0100

    Define toolset and architecture in CMakePresets.json for VS to avoid mismatches (conan-io#15215)

    * checking what breaks

    * fix test

    * testing it really fix something

    * wip

    * wip

commit 7921be1
Author: James <james@conan.io>
Date:   Fri Dec 15 12:45:07 2023 +0100

    adding tools.microsoft:winsdk_version conf (conan-io#15272)

    * adding tools.microsoft:winsdk_version conf

    * fix tests

    * wip

    * fix

    * review

commit 018441d
Author: James <james@conan.io>
Date:   Fri Dec 15 12:38:10 2023 +0100

    new CMake.ctest() method (conan-io#15282)

commit 053f22a
Author: James <james@conan.io>
Date:   Fri Dec 15 12:23:57 2023 +0100

    Feature/cmakedeps legacy adapter (conan-io#15207)

    * reusing fixture, will reduce CI time

    * proposal for legacy cmake-like generator

    * better ux for VS not found error (conan-io#15250)

    * better ux

    * improve

    * Update conan/tools/microsoft/visual.py

    Co-authored-by: Rubén Rincón Blanco <git@rinconblanco.es>

    ---------

    Co-authored-by: Rubén Rincón Blanco <git@rinconblanco.es>

    * fix and remove more xfails (conan-io#15251)

    fix and remove xfails

    * Fix/save restore portable (conan-io#15253)

    * make save-restore portable

    * msg

    * require-replaces proposal (conan-io#15136)

    * wip

    * test passing

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * new approach

    * extra checks

    * more tests

    * review

    * Fix failing tests in macos (conan-io#15255)

    Fix tests in macos

    * Add test to ensure &: syntax works in `--requires` install (conan-io#15258)

    Add test to ensure &: syntax qorks in --requires install

    * add CONAN_LOG_LEVEL env-var (conan-io#15263)

    * add CONAN_LOG_LEVEL env-var

    * Update conan/cli/command.py

    ---------

    Co-authored-by: Francisco Ramírez <franchuti688@gmail.com>

    * review

    * review

    ---------

    Co-authored-by: Rubén Rincón Blanco <git@rinconblanco.es>
    Co-authored-by: Rubén Rincón Blanco <rubenrb@jfrog.com>
    Co-authored-by: Francisco Ramírez <franchuti688@gmail.com>

commit 9afacb4
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Fri Dec 15 11:32:21 2023 +0100

    Add different ref tracking syntax for  `<host_version>` (conan-io#15274)

    * Use light=True where possible in build_requires tests

    * Sketch for allowing tracking of different ref

    * Add remote input to build-map command

    * Update conans/client/graph/graph_builder.py

    Co-authored-by: James <memsharded@gmail.com>

    * Update conans/client/graph/graph_builder.py

    Co-authored-by: James <memsharded@gmail.com>

    * Update conans/client/graph/graph_builder.py

    Co-authored-by: James <memsharded@gmail.com>

    * Fix tests

    ---------

    Co-authored-by: James <memsharded@gmail.com>

commit 92af096
Author: Luis Caro Campos <3535649+jcar87@users.noreply.github.com>
Date:   Fri Dec 15 10:10:45 2023 +0000

    Add pyproject.toml (conan-io#15186)

    * Move to pyproject.toml

    * Exclude conan server

    * Try adding a line

    * Upgrade pip in venv

    * update setuptools too

    * Read version from conans.__init__

    * Restore setup.py for compatibility

    * Minimal pyproject toml

    * Restore setup.py

    * Restore jenkinsfile

commit 0c786c5
Author: Carlos Zoido <mrgalleta@gmail.com>
Date:   Fri Dec 15 01:36:22 2023 +0100

    Add environment information to CMakePresets (conan-io#15192)

    * build to config and run to test preset

    * first draft

    * revert

    * wip

    * fix format

    * test ctest

    * simplify

    * get env in right place

    * move test

    * fix windows

    * hopefully fix tests

    * fix test

    * fix test again

    * simplify test

    * add opt-out

    * wip

    * auto_generate for run env

    * minor changes

commit 5becb2a
Author: Juan <35701596+juansblanco@users.noreply.github.com>
Date:   Thu Dec 14 15:58:32 2023 +0100

    Make paths format in layout consistent on Windows (conan-io#15260)

    Changelog: Omit
    Docs: Omit

commit 9f023c3
Author: James <james@conan.io>
Date:   Thu Dec 14 15:48:28 2023 +0100

    proposal for source() buildenv discussion (conan-io#15153)

    * proposal for source() buildenv discussion

    * wip, failing

    * trying alternative opt-in class attribute

    * fix

    * wip

    * wip

    * add cmake_layout test

    * wip

    * named auto_generate

commit 0843372
Author: James <james@conan.io>
Date:   Thu Dec 14 12:34:54 2023 +0100

    fix migration lru (conan-io#15135)

    * fix migration lru

    * fix back migration

commit c655809
Author: Carlos Zoido <mrgalleta@gmail.com>
Date:   Wed Dec 13 16:32:02 2023 +0100

    Add pkglist formatter for conan export command (conan-io#15266)

    add pkglist formatter and test

commit d0e6a3f
Author: James <james@conan.io>
Date:   Wed Dec 13 13:59:50 2023 +0100

    optimize test (conan-io#15214)

    * optimize test

    * fixes

    * fix

commit 6f3f445
Author: James <james@conan.io>
Date:   Wed Dec 13 12:57:00 2023 +0100

    add CONAN_LOG_LEVEL env-var (conan-io#15263)

    * add CONAN_LOG_LEVEL env-var

    * Update conan/cli/command.py

    ---------

    Co-authored-by: Francisco Ramírez <franchuti688@gmail.com>

commit 032eefc
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Tue Dec 12 19:43:09 2023 +0100

    Add test to ensure &: syntax works in `--requires` install (conan-io#15258)

    Add test to ensure &: syntax qorks in --requires install

commit 694b7d1
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Tue Dec 12 14:57:14 2023 +0100

    Fix failing tests in macos (conan-io#15255)

    Fix tests in macos

commit 286d552
Author: James <james@conan.io>
Date:   Tue Dec 12 14:16:18 2023 +0100

    require-replaces proposal (conan-io#15136)

    * wip

    * test passing

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * new approach

    * extra checks

    * more tests

    * review

commit 7aa0b4b
Author: James <james@conan.io>
Date:   Tue Dec 12 12:21:02 2023 +0100

    Fix/save restore portable (conan-io#15253)

    * make save-restore portable

    * msg

commit 1c43d5f
Author: James <james@conan.io>
Date:   Tue Dec 12 09:43:07 2023 +0100

    fix and remove more xfails (conan-io#15251)

    fix and remove xfails

commit 2717bbe
Author: James <james@conan.io>
Date:   Mon Dec 11 20:06:14 2023 +0100

    better ux for VS not found error (conan-io#15250)

    * better ux

    * improve

    * Update conan/tools/microsoft/visual.py

    Co-authored-by: Rubén Rincón Blanco <git@rinconblanco.es>

    ---------

    Co-authored-by: Rubén Rincón Blanco <git@rinconblanco.es>

commit 5ef6824
Author: James <james@conan.io>
Date:   Mon Dec 11 15:18:06 2023 +0100

    drop --build unused patterns unused functionality (conan-io#15233)

commit 1d058e9
Author: James <james@conan.io>
Date:   Mon Dec 11 13:47:21 2023 +0100

    fix deploy absolute folders (conan-io#15244)

    * fix deploy absolute folders

    * fix tests

commit 63ee9c7
Author: James <james@conan.io>
Date:   Mon Dec 11 07:59:37 2023 +0100

    allow hard set_name() set_version() (conan-io#15211)

commit 37573ee
Author: James <james@conan.io>
Date:   Thu Dec 7 15:09:24 2023 +0100

    Tests maintenance, fix some xfail, remove other xfails (conan-io#15234)

    remove xfail

commit e6aa291
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Thu Dec 7 15:04:23 2023 +0100

    Add `in` operator support for ConanFile's `self.dependencies` (conan-io#15221)

    * Add in operator support for ConanFile self.dependencies

    * Ensure tool_requires also work

commit a6f42bf
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Wed Dec 6 12:57:44 2023 +0100

    Fix range escaping in conflict reports involving ranges (conan-io#15222)

    * Add failing test that should pass after issue is fixed

    * Fix range escaping in conflict reports involving ranges

commit acbaf44
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Mon Dec 4 23:16:38 2023 +0100

    Fix `conan graph explain` binary distance calculation (conan-io#15212)

    * Bugfix binary distance calculation

    * Add proper distance culling test

commit 5493a77
Author: James <james@conan.io>
Date:   Mon Dec 4 08:27:53 2023 +0100

    reusing fixture, will reduce CI time (conan-io#15204)

commit 412a027
Author: James <james@conan.io>
Date:   Fri Dec 1 13:58:04 2023 +0100

    New [platform_requires]  similar to system-tools, but for all requires (conan-io#14871)

    * wip

    * test passing

    * wip

    * wip

    * wip

    * wip

    * wip

    * renaming and review

    * fixes

    * add missing dumps

    * Simplified if-else clauses. Keeping more prio for platform_tool_requires

    * Renamed first naming proposal

    * review test, new check

    * fix test

    * fix

    ---------

    Co-authored-by: Francisco Ramirez de Anton <franchuti688@gmail.com>

commit 1f548d8
Author: Luis Caro Campos <3535649+jcar87@users.noreply.github.com>
Date:   Fri Dec 1 09:57:43 2023 +0000

    Fix pyinstaller script on Windows (conan-io#15194)

commit dc98b6a
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Fri Dec 1 10:25:16 2023 +0100

    Fix `conan graph info --format=html` reporting misleading conflicting nodes (conan-io#15196)

    * Fix graph info --format=html conflict report misleading nodes

    * Add node map test

commit 3f3fd45
Author: memsharded <james@conan.io>
Date:   Thu Nov 30 00:33:54 2023 +0100

    wip

commit 9145028
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Wed Nov 29 22:47:57 2023 +0100

    Add `redirect_stdout` to CMake integration methods (conan-io#15150)

    * Add redirect_stdout to CMake integration methods

    * Fix windows tests

    * Simplify tests

    * Directly pass stdout & stderr streams instead of files

    * Ensure outputs are redirected to the correct streams

    * Fix unittests

    * Update conans/test/functional/toolchains/cmake/test_cmake_toolchain.py

    Co-authored-by: Carlos Zoido <mrgalleta@gmail.com>

    * Remove unused method

    * Add cmake.test stdout test, fix failing test

    * Simpify testing

    * Change testing approach for build

    * Change testing approach for build

    * Finally fix tests (hopefully)

    * Simplify tests

    * Comment wording

    * Check for emptyness in Windows

    ---------

    Co-authored-by: Carlos Zoido <mrgalleta@gmail.com>

commit 71d863a
Author: James <james@conan.io>
Date:   Wed Nov 29 17:17:48 2023 +0100

    poc for filtering lists with profile-like inputs (conan-io#14694)

    * poc for filtering lists with profile-like inputs

    * per-package and options and distance

    * wip

    * wip

    * wip

    * refactor list format compact

    * wip

    * wip

    * ready

    * fix test

    * fix tests

    * converted to graph find-binaries approach

    * wip

    * review

    * Create custom formatters to ensure we can expand the command in the future

    * review

    ---------

    Co-authored-by: Rubén Rincón <rubenrb@jfrog.com>

commit 25070c1
Author: Luis Caro Campos <3535649+jcar87@users.noreply.github.com>
Date:   Wed Nov 29 14:02:38 2023 +0000

    Cleanup pyinstall.py (conan-io#15188)

commit 29e9f95
Author: James <james@conan.io>
Date:   Wed Nov 29 10:58:08 2023 +0100

    proposal for deploy() feature (conan-io#15172)

    * proposal for deploy() feature

    * rename argument --deploy-package

    * rename arg

commit f0a1b35
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Tue Nov 28 15:45:17 2023 +0100

    Fix serialization of tool_requires in `conan profile show --format=json` (conan-io#15185)

    * Fix serialization of tool_requires in profile show --format=json

    * Serialize recipe reference as repr in profile tool_requires

    * Fix test

commit a5605d1
Author: James <james@conan.io>
Date:   Tue Nov 28 14:29:54 2023 +0100

    Refactor ``conan list --format=compact`` format code (conan-io#15177)

    * refactor list format compact

    * wip

    * wip

commit 2e56813
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Mon Nov 27 16:47:23 2023 +0100

    Add test showing that `configure()` can be used to set `deprecated` (conan-io#15180)

    Add test showing that configure can set deprecated option just fin

commit 65ec31c
Author: Juan <35701596+juansblanco@users.noreply.github.com>
Date:   Sat Nov 25 08:01:42 2023 +0100

    Removed conan migration compatibility warning (conan-io#15174)

    removed warning and related test

commit dde76f6
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Fri Nov 24 19:20:32 2023 +0100

    Fix `conan graph info --format=text` being printed to stderr (conan-io#15170)

    Fix graph info --format=text being printed to stderr

commit 0d9f52f
Author: Rubén Rincón Blanco <rubenrb@jfrog.com>
Date:   Fri Nov 24 07:00:27 2023 +0100

    Allow querying the contents of settings.yml (and settings_user!) from ConfigAPI (conan-io#15151)

    * Allow querying the contents of settings.yml (and settings_user!) from the API

    * Add tests

    * Pretty print settings, make ConfigAPI.builtin_confs a @Property

    * Fix tests, ensure null is properly printed

    * Remove conan config settings command until it's asked by someone

    * Remove unneeded test

    * Remove unused import
  • Loading branch information
AbrilRBS committed Dec 18, 2023
1 parent df4d43b commit 5faf53f
Show file tree
Hide file tree
Showing 116 changed files with 2,802 additions and 2,501 deletions.
4 changes: 2 additions & 2 deletions conan/api/model.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fnmatch
import json

from conans.client.graph.graph import RECIPE_EDITABLE, RECIPE_CONSUMER, RECIPE_SYSTEM_TOOL, \
from conans.client.graph.graph import RECIPE_EDITABLE, RECIPE_CONSUMER, RECIPE_PLATFORM, \
RECIPE_VIRTUAL, BINARY_SKIP, BINARY_MISSING, BINARY_INVALID
from conans.errors import ConanException
from conans.model.package_ref import PkgReference
Expand Down Expand Up @@ -99,7 +99,7 @@ def load_graph(graphfile, graph_recipes=None, graph_binaries=None):
remote_list.add_refs([pyref])

recipe = node["recipe"]
if recipe in (RECIPE_EDITABLE, RECIPE_CONSUMER, RECIPE_VIRTUAL, RECIPE_SYSTEM_TOOL):
if recipe in (RECIPE_EDITABLE, RECIPE_CONSUMER, RECIPE_VIRTUAL, RECIPE_PLATFORM):
continue

ref = node["ref"]
Expand Down
6 changes: 5 additions & 1 deletion conan/api/subapi/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,23 @@ def save(self, package_list, tgz_path):
for ref, ref_bundle in package_list.refs().items():
ref_layout = app.cache.recipe_layout(ref)
recipe_folder = os.path.relpath(ref_layout.base_folder, cache_folder)
recipe_folder = recipe_folder.replace("\\", "/") # make win paths portable
ref_bundle["recipe_folder"] = recipe_folder
out.info(f"Saving {ref}: {recipe_folder}")
tgz.add(os.path.join(cache_folder, recipe_folder), recipe_folder, recursive=True)
for pref, pref_bundle in package_list.prefs(ref, ref_bundle).items():
pref_layout = app.cache.pkg_layout(pref)
pkg_folder = pref_layout.package()
folder = os.path.relpath(pkg_folder, cache_folder)
folder = folder.replace("\\", "/") # make win paths portable
pref_bundle["package_folder"] = folder
out.info(f"Saving {pref}: {folder}")
tgz.add(os.path.join(cache_folder, folder), folder, recursive=True)
if os.path.exists(pref_layout.metadata()):
metadata_folder = os.path.relpath(pref_layout.metadata(), cache_folder)
metadata_folder = metadata_folder.replace("\\", "/") # make paths portable
pref_bundle["metadata_folder"] = metadata_folder
out.info(f"Saving {pref} metadata: {folder}")
out.info(f"Saving {pref} metadata: {metadata_folder}")
tgz.add(os.path.join(cache_folder, metadata_folder), metadata_folder,
recursive=True)
serialized = json.dumps(package_list.serialize(), indent=2)
Expand All @@ -159,6 +162,7 @@ def restore(self, path):
recipe_layout = cache.get_or_create_ref_layout(ref)
recipe_folder = ref_bundle["recipe_folder"]
rel_path = os.path.relpath(recipe_layout.base_folder, cache.cache_folder)
rel_path = rel_path.replace("\\", "/")
assert rel_path == recipe_folder, f"{rel_path}!={recipe_folder}"
out.info(f"Restore: {ref} in {recipe_folder}")
for pref, pref_bundle in package_list.prefs(ref, ref_bundle).items():
Expand Down
103 changes: 78 additions & 25 deletions conan/api/subapi/config.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import os
import platform
import textwrap

import yaml
from jinja2 import Environment, FileSystemLoader

from conan import conan_version
from conans.client.conf import default_settings_yml
from conan.internal.api import detect_api
from conan.internal.cache.home_paths import HomePaths
from conan.internal.conan_app import ConanApp
from conans.model.conf import ConfDefinition
from conans.errors import ConanException
from conans.model.conf import ConfDefinition, BUILT_IN_CONFS
from conans.model.settings import Settings
from conans.util.files import load, save


Expand Down Expand Up @@ -43,28 +46,78 @@ def global_conf(self):
to the profile ones and passed to the conanfiles.conf, which can be passed to collaborators
"""
if self._new_config is None:
self._new_config = ConfDefinition()
cache_folder = self.conan_api.cache_folder
home_paths = HomePaths(cache_folder)
global_conf_path = home_paths.global_conf_path
if os.path.exists(global_conf_path):
text = load(global_conf_path)
distro = None
if platform.system() in ["Linux", "FreeBSD"]:
import distro
template = Environment(loader=FileSystemLoader(cache_folder)).from_string(text)
content = template.render({"platform": platform, "os": os, "distro": distro,
"conan_version": conan_version,
"conan_home_folder": cache_folder,
"detect_api": detect_api})
self._new_config.loads(content)
else: # creation of a blank global.conf file for user convenience
default_global_conf = textwrap.dedent("""\
# Core configuration (type 'conan config list' to list possible values)
# e.g, for CI systems, to raise if user input would block
# core:non_interactive = True
# some tools.xxx config also possible, though generally better in profiles
# tools.android:ndk_path = my/path/to/android/ndk
""")
save(global_conf_path, default_global_conf)
self._new_config = self.load_config(cache_folder)
return self._new_config

@staticmethod
def load_config(home_folder):
# Do not document yet, keep it private
home_paths = HomePaths(home_folder)
global_conf_path = home_paths.global_conf_path
new_config = ConfDefinition()
if os.path.exists(global_conf_path):
text = load(global_conf_path)
distro = None
if platform.system() in ["Linux", "FreeBSD"]:
import distro
template = Environment(loader=FileSystemLoader(home_folder)).from_string(text)
content = template.render({"platform": platform, "os": os, "distro": distro,
"conan_version": conan_version,
"conan_home_folder": home_folder,
"detect_api": detect_api})
new_config.loads(content)
else: # creation of a blank global.conf file for user convenience
default_global_conf = textwrap.dedent("""\
# Core configuration (type 'conan config list' to list possible values)
# e.g, for CI systems, to raise if user input would block
# core:non_interactive = True
# some tools.xxx config also possible, though generally better in profiles
# tools.android:ndk_path = my/path/to/android/ndk
""")
save(global_conf_path, default_global_conf)
return new_config

@property
def builtin_confs(self):
return BUILT_IN_CONFS

@property
def settings_yml(self):
"""Returns {setting: [value, ...]} defining all the possible
settings without values"""
_home_paths = HomePaths(self.conan_api.cache_folder)
settings_path = _home_paths.settings_path
if not os.path.exists(settings_path):
save(settings_path, default_settings_yml)
save(settings_path + ".orig", default_settings_yml) # stores a copy, to check migrations

def _load_settings(path):
try:
return yaml.safe_load(load(path)) or {}
except yaml.YAMLError as ye:
raise ConanException("Invalid settings.yml format: {}".format(ye))

settings = _load_settings(settings_path)
user_settings_file = _home_paths.settings_path_user
if os.path.exists(user_settings_file):
settings_user = _load_settings(user_settings_file)

def appending_recursive_dict_update(d, u):
# Not the same behavior as conandata_update, because this append lists
for k, v in u.items():
if isinstance(v, list):
current = d.get(k) or []
d[k] = current + [value for value in v if value not in current]
elif isinstance(v, dict):
current = d.get(k) or {}
if isinstance(current, list): # convert to dict lists
current = {k: None for k in current}
d[k] = appending_recursive_dict_update(current, v)
else:
d[k] = v
return d

appending_recursive_dict_update(settings, settings_user)

return Settings(settings)
6 changes: 3 additions & 3 deletions conan/api/subapi/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def install_sources(self, graph, remotes):

# TODO: Look for a better name
def install_consumer(self, deps_graph, generators=None, source_folder=None, output_folder=None,
deploy=False, deploy_folder=None):
deploy=False, deploy_package=None, deploy_folder=None):
""" Once a dependency graph has been installed, there are things to be done, like invoking
generators for the root consumer.
This is necessary for example for conanfile.txt/py, or for "conan install <ref> -g
Expand All @@ -61,9 +61,9 @@ def install_consumer(self, deps_graph, generators=None, source_folder=None, outp
conanfile.folders.set_base_folders(source_folder, output_folder)

# The previous .set_base_folders has already decided between the source_folder and output
if deploy:
if deploy or deploy_package:
base_folder = deploy_folder or conanfile.folders.base_build
do_deploys(self.conan_api, deps_graph, deploy, base_folder)
do_deploys(self.conan_api, deps_graph, deploy, deploy_package, base_folder)

conanfile.generators = list(set(conanfile.generators).union(generators or []))
app = ConanApp(self.conan_api.cache_folder, self.conan_api.config.global_conf)
Expand Down
114 changes: 114 additions & 0 deletions conan/api/subapi/list.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from typing import Dict

from conan.api.model import PackagesList
from conan.api.output import ConanOutput
from conan.internal.conan_app import ConanApp
from conans.errors import ConanException, NotFoundException
from conans.model.info import load_binary_info
from conans.model.package_ref import PkgReference
from conans.model.recipe_ref import RecipeReference
from conans.search.search import get_cache_packages_binary_info, filter_packages
Expand Down Expand Up @@ -164,3 +166,115 @@ def select(self, pattern, package_query=None, remote=None, lru=None):
select_bundle.add_prefs(rrev, prefs)
select_bundle.add_configurations(packages)
return select_bundle

def explain_missing_binaries(self, ref, conaninfo, remotes):
ConanOutput().info(f"Missing binary: {ref}")
ConanOutput().info(f"With conaninfo.txt (package_id):\n{conaninfo.dumps()}")
conaninfo = load_binary_info(conaninfo.dumps())
# Collect all configurations
candidates = []
ConanOutput().info(f"Finding binaries in the cache")
pkg_configurations = self.packages_configurations(ref)
candidates.extend(_BinaryDistance(pref, data, conaninfo)
for pref, data in pkg_configurations.items())

for remote in remotes:
try:
ConanOutput().info(f"Finding binaries in remote {remote.name}")
pkg_configurations = self.packages_configurations(ref, remote=remote)
except Exception as e:
pass
ConanOutput(f"ERROR IN REMOTE {remote.name}: {e}")
else:
candidates.extend(_BinaryDistance(pref, data, conaninfo, remote)
for pref, data in pkg_configurations.items())

candidates.sort()
pkglist = PackagesList()
pkglist.add_refs([ref])
# If there are exact matches, only return the matches
# else, limit to the number specified
candidate_distance = None
for candidate in candidates:
if candidate_distance and candidate.distance != candidate_distance:
break
candidate_distance = candidate.distance
pref = candidate.pref
pkglist.add_prefs(ref, [pref])
pkglist.add_configurations({pref: candidate.binary_config})
# Add the diff data
rev_dict = pkglist.recipes[str(pref.ref)]["revisions"][pref.ref.revision]
rev_dict["packages"][pref.package_id]["diff"] = candidate.serialize()
remote = candidate.remote.name if candidate.remote else "Local Cache"
rev_dict["packages"][pref.package_id]["remote"] = remote
return pkglist


class _BinaryDistance:
def __init__(self, pref, binary_config, expected_config, remote=None):
self.remote = remote
self.pref = pref
self.binary_config = binary_config

# Settings
self.platform_diff = {}
self.settings_diff = {}
binary_settings = binary_config.get("settings", {})
expected_settings = expected_config.get("settings", {})
for k, v in expected_settings.items():
value = binary_settings.get(k)
if value is not None and value != v:
diff = self.platform_diff if k in ("os", "arch") else self.settings_diff
diff.setdefault("expected", []).append(f"{k}={v}")
diff.setdefault("existing", []).append(f"{k}={value}")

# Options
self.options_diff = {}
binary_options = binary_config.get("options", {})
expected_options = expected_config.get("options", {})
for k, v in expected_options.items():
value = binary_options.get(k)
if value is not None and value != v:
self.options_diff.setdefault("expected", []).append(f"{k}={v}")
self.options_diff.setdefault("existing", []).append(f"{k}={value}")

# Requires
self.deps_diff = {}
binary_requires = binary_config.get("requires", [])
expected_requires = expected_config.get("requires", [])
binary_requires = [RecipeReference.loads(r) for r in binary_requires]
expected_requires = [RecipeReference.loads(r) for r in expected_requires]
binary_requires = {r.name: r for r in binary_requires}
for r in expected_requires:
existing = binary_requires.get(r.name)
if not existing or r != existing:
self.deps_diff.setdefault("expected", []).append(repr(r))
self.deps_diff.setdefault("existing", []).append(repr(existing))

def __lt__(self, other):
return self.distance < other.distance

def explanation(self):
if self.platform_diff:
return "This binary belongs to another OS or Architecture, highly incompatible."
if self.settings_diff:
return "This binary was built with different settings."
if self.options_diff:
return "This binary was built with the same settings, but different options"
if self.deps_diff:
return "This binary has same settings and options, but different dependencies"
return "This binary is an exact match for the defined inputs"

@property
def distance(self):
return (len(self.platform_diff.get("expected", [])),
len(self.settings_diff.get("expected", [])),
len(self.options_diff.get("expected", [])),
len(self.deps_diff.get("expected", [])))

def serialize(self):
return {"platform": self.platform_diff,
"settings": self.settings_diff,
"options": self.options_diff,
"dependencies": self.deps_diff,
"explanation": self.explanation()}
2 changes: 2 additions & 0 deletions conan/api/subapi/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ def source(self, path, name=None, version=None, user=None, channel=None, remotes
conanfile.folders.set_base_source(folder)
conanfile.folders.set_base_export_sources(folder)
conanfile.folders.set_base_recipe_metadata(os.path.join(folder, "metadata"))
# The generators are needed for the "conan source" local case with tool-requires
conanfile.folders.set_base_generators(folder)
conanfile.folders.set_base_build(None)
conanfile.folders.set_base_package(None)

Expand Down
Loading

0 comments on commit 5faf53f

Please sign in to comment.