Repository: conan-io/conan
Pull request #16559 (2024-06-27 13:34:09)

Allow `-fo` in `conan list` to use `&:` scope to refer to all packages being listed
Changelog: Feature: Allow `--filter-options` in `conan list` to use `&:` scope to refer to all packages being listed
Docs: Omit?

Closes https://github.com/conan-io/conan/issues/16545

The issue arose when misunderstanding that conan list would treat the consumer pattern as "every package I'm listing" - This adds that functionality, which is less suprising that it not working


Patch:
diff --git a/conan/api/subapi/list.py b/conan/api/subapi/list.py
index 1e92cf74d..a7452ecfe 100644
--- a/conan/api/subapi/list.py
+++ b/conan/api/subapi/list.py
@@ -104,7 +104,9 @@ class ListAPI:
             options = data.get("options", {})
             for k, v in options.items():
                 for pattern, pattern_options in profile_options.items():
-                    if ref_matches(ref, pattern, None):
+                    # Accept &: as referring to the current package being listed,
+                    # even if it's not technically a "consumer"
+                    if ref_matches(ref, pattern, True):
                         value = pattern_options.get_safe(k)
                         if value is not None and value != v:
                             options_match = False
diff --git a/conan/tools/cmake/cmake.py b/conan/tools/cmake/cmake.py
index ca49da148..2efa8f37a 100644
--- a/conan/tools/cmake/cmake.py
+++ b/conan/tools/cmake/cmake.py
@@ -31,7 +31,7 @@ def _cmake_cmd_line_args(conanfile, generator):
     return args
 
 
-class CMake(object):
+class CMake:
     """ CMake helper to use together with the CMakeToolchain feature """
 
     def __init__(self, conanfile):
@@ -60,8 +60,6 @@ class CMake(object):
         """
 
         Reads the ``CMakePresets.json`` file generated by the
-        :param cli_args: List of arguments ``[arg1, arg2, ...]`` that will be passed as extra CLI
-                         arguments to pass to cmake invocation
         :ref:`CMakeToolchain<conan-cmake-toolchain>` to get:
 
            - The generator, to append ``-G="xxx"``.
@@ -78,6 +76,8 @@ class CMake(object):
                           work in the toolchain approach.
         :param build_script_folder: Path to the CMakeLists.txt in case it is not in the declared
                                     ``self.folders.source`` at the ``layout()`` method.
+        :param cli_args: List of arguments ``[arg1, arg2, ...]`` that will be passed
+                         as extra CLI arguments to pass to cmake invocation
         :param stdout: Use it to redirect stdout to this stream
         :param stderr: Use it to redirect stderr to this stream
         """
@@ -173,7 +173,7 @@ class CMake(object):
         :param target: The name of a single build target as a string, or names of multiple build targets in a
                        list of strings to be passed to the ``--target`` argument.
         :param cli_args: A list of arguments ``[arg1, arg2, ...]`` that will be passed to the
-                        ``cmake --build ... arg1 arg2`` command directly.
+                         ``cmake --build ... arg1 arg2`` command directly.
         :param build_tool_args: A list of arguments ``[barg1, barg2, ...]`` for the underlying
                                 build system that will be passed to the command
                                 line after the ``--`` indicator: ``cmake --build ... -- barg1 barg2``
@@ -192,9 +192,8 @@ class CMake(object):
                            It can fail if the build is single configuration (e.g. Unix Makefiles),
                            as in that case the build type must be specified at configure time,
                            not build type.
-        :param cli_args: A list of arguments ``[arg1, arg2, ...]`` for the underlying
-                         build system that will be passed to the command line:
-                         ``cmake --install ... arg1 arg2``
+        :param cli_args: A list of arguments ``[arg1, arg2, ...]`` for the underlying build system
+                         that will be passed to the command line: ``cmake --install ... arg1 arg2``
         :param stdout: Use it to redirect stdout to this stream
         :param stderr: Use it to redirect stderr to this stream
         """
@@ -234,8 +233,7 @@ class CMake(object):
                            time.
         :param target: Name of the build target to run, by default ``RUN_TESTS`` or ``test``
         :param cli_args: Same as above ``build()``, a list of arguments ``[arg1, arg2, ...]``
-                         to be passed as extra arguments for the underlying
-                         build system
+                         to be passed as extra arguments for the underlying build system
         :param build_tool_args: Same as above ``build()``
         :param stdout: Use it to redirect stdout to this stream
         :param stderr: Use it to redirect stderr to this stream
@@ -257,8 +255,7 @@ class CMake(object):
         """
         Equivalent to running ctest ...
 
-        :param cli_args: List of arguments ``[arg1, arg2, ...]`` to be passed
-                         as extra ctest command line arguments
+        :param cli_args: List of arguments ``[arg1, arg2, ...]`` to be passed as extra ctest command line arguments
         :param env: the environment files to activate, by default conanbuild + conanrun
         :param stdout: Use it to redirect stdout to this stream
         :param stderr: Use it to redirect stderr to this stream


Test patch:
diff --git a/test/integration/command_v2/list_test.py b/test/integration/command_v2/list_test.py
index b73c9742e..0139bb5d5 100644
--- a/test/integration/command_v2/list_test.py
+++ b/test/integration/command_v2/list_test.py
@@ -896,3 +896,13 @@ class TestListBinaryFilter:
         assert len(pkg["packages"]) == 1
         settings = pkg["packages"]["d2e97769569ac0a583d72c10a37d5ca26de7c9fa"]["info"]["settings"]
         assert settings == {"arch": "x86", "os": "Windows"}
+
+        # &: will also match every package being listed, as if it was a consumer
+        c.run(f"list *:* -fo &:shared=False --format=json {r}")
+        result = json.loads(c.stdout)
+        header = result[pkg_key]["header/1.0"]["revisions"]["747cc49983b14bdd00df50a0671bd8b3"]
+        assert header["packages"] == {"da39a3ee5e6b4b0d3255bfef95601890afd80709": {"info": {}}}
+        pkg = result[pkg_key]["pkg/1.0"]["revisions"]["03591c8b22497dd74214e08b3bf2a56f"]
+        assert len(pkg["packages"]) == 2
+        settings = pkg["packages"]["d2e97769569ac0a583d72c10a37d5ca26de7c9fa"]["info"]["settings"]
+        assert settings == {"arch": "x86", "os": "Windows"}
diff --git a/test/unittests/model/version/test_version_range.py b/test/unittests/model/version/test_version_range.py
index 29b83685d..5b0101245 100644
--- a/test/unittests/model/version/test_version_range.py
+++ b/test/unittests/model/version/test_version_range.py
@@ -53,6 +53,7 @@ values = [
     ['>=2.0-pre.0, include_prerelease', [[['>=', '2.0-pre.0']]], ["2.1", "2.0-pre.1"], ["1.5"]],
     # Build metadata
     ['>=1.0.0+2', [[['>=', '1.0.0+2']]], ["1.0.0+2", "1.0.0+3"], ["1.0.0+1"]],
+    ['>=2.2.0+build.en.305 <2.2.0+build.en.306', [], ["2.2.0+build.en.305", "2.2.0+build.en.305.1", "2.2.0+build.en.305.2"], ["2.2.0+build.en.306"]]
 ]