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

no user/channel pattern matches #14338

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
7 changes: 1 addition & 6 deletions conans/client/graph/build_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,9 @@ def __init__(self, params):
else:
if param.startswith("missing:"):
clean_pattern = param[len("missing:"):]
clean_pattern = clean_pattern[:-1] if param.endswith("@") else clean_pattern
clean_pattern = clean_pattern.replace("@#", "#")
self.build_missing_patterns.append(clean_pattern)
else:
# Remove the @ at the end, to match for
# "conan install --requires=pkg/0.1@ --build=pkg/0.1@"
clean_pattern = param[:-1] if param.endswith("@") else param
clean_pattern = clean_pattern.replace("@#", "#")
clean_pattern = param
if clean_pattern and clean_pattern[0] in ["!", "~"]:
self._excluded_patterns.append(clean_pattern[1:])
else:
Expand Down
10 changes: 10 additions & 0 deletions conans/model/recipe_ref.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,19 @@ def matches(self, pattern, is_consumer):
pattern = pattern[1:]
negate = True

no_user_channel = False
if pattern.endswith("@"): # it means we want to match only without user/channel
pattern = pattern[:-1]
no_user_channel = True
elif "@#" in pattern:
pattern = pattern.replace("@#", "#")
no_user_channel = True

condition = ((pattern == "&" and is_consumer) or
fnmatch.fnmatchcase(str(self), pattern) or
fnmatch.fnmatchcase(self.repr_notime(), pattern))
if no_user_channel:
condition = condition and not self.user and not self.channel
if negate:
return not condition
return condition
Expand Down
37 changes: 37 additions & 0 deletions conans/test/integration/command/create_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,43 @@ def test_create_build_missing():
assert "ERROR: Missing prebuilt package for 'dep/1.0'" in c.out


def test_create_no_user_channel():
""" test the --build=pattern and --build=missing:pattern syntax to build missing packages
without user/channel
"""
c = TestClient()
c.save({"dep/conanfile.py": GenConanfile(),
"pkg/conanfile.py": GenConanfile("pkg", "1.0").with_requires("dep1/0.1", "dep2/0.1@user",
"dep3/0.1@user/channel")})
c.run("export dep --name=dep1 --version=0.1")
c.run("export dep --name=dep2 --version=0.1 --user=user")
c.run("export dep --name=dep3 --version=0.1 --user=user --channel=channel")

# First test the ``--build=missing:pattern``
c.run("create pkg --build=missing:*@", assert_error=True)
c.assert_listed_binary({"dep1/0.1": (NO_SETTINGS_PACKAGE_ID, "Build"),
"dep2/0.1": (NO_SETTINGS_PACKAGE_ID, "Missing"),
"dep3/0.1": (NO_SETTINGS_PACKAGE_ID, "Missing")})
c.run("create pkg --build=missing:!*@", assert_error=True)
c.assert_listed_binary({"dep1/0.1": (NO_SETTINGS_PACKAGE_ID, "Missing"),
"dep2/0.1": (NO_SETTINGS_PACKAGE_ID, "Build"),
"dep3/0.1": (NO_SETTINGS_PACKAGE_ID, "Build")})

# Now lets make sure they exist
c.run("create pkg --build=missing")

# Now test the --build=pattern
c.run("create pkg --build=*@")
c.assert_listed_binary({"dep1/0.1": (NO_SETTINGS_PACKAGE_ID, "Build"),
"dep2/0.1": (NO_SETTINGS_PACKAGE_ID, "Cache"),
"dep3/0.1": (NO_SETTINGS_PACKAGE_ID, "Cache")})
# The --build=* needs to be said: "build all except those that have user/channel
c.run("create pkg --build=* --build=!*@")
c.assert_listed_binary({"dep1/0.1": (NO_SETTINGS_PACKAGE_ID, "Cache"),
"dep2/0.1": (NO_SETTINGS_PACKAGE_ID, "Build"),
"dep3/0.1": (NO_SETTINGS_PACKAGE_ID, "Build")})


def test_create_format_json():
"""
Tests the ``conan create . -f json`` result
Expand Down
40 changes: 40 additions & 0 deletions conans/test/integration/options/options_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,46 @@ def test_transitive_options_conanfile_py_create(self, client):
self.check(client)


def test_options_no_user_channel_patterns():
c = TestClient()
conanfile = textwrap.dedent("""\
from conan import ConanFile
class Pkg(ConanFile):
options = {"myoption": [1, 2, 3]}
def configure(self):
self.output.info(f"MYOPTION: {self.options.myoption}")
""")
c.save({"dep/conanfile.py": conanfile,
"pkg/conanfile.py": GenConanfile("pkg", "1.0").with_requires("dep1/0.1", "dep2/0.1@user",
"dep3/0.1@user/channel")})
c.run("export dep --name=dep1 --version=0.1")
c.run("export dep --name=dep2 --version=0.1 --user=user")
c.run("export dep --name=dep3 --version=0.1 --user=user --channel=channel")

c.run("graph info pkg -o *:myoption=3 -o *@:myoption=1")
assert "dep1/0.1: MYOPTION: 1" in c.out
assert "dep2/0.1@user: MYOPTION: 3" in c.out
assert "dep3/0.1@user/channel: MYOPTION: 3" in c.out

# Recall that order is also important latest matching pattern wins
c.run("graph info pkg -o *@:myoption=1 -o *:myoption=1")
assert "dep1/0.1: MYOPTION: 1" in c.out
assert "dep2/0.1@user: MYOPTION: 1" in c.out
assert "dep3/0.1@user/channel: MYOPTION: 1" in c.out

# This is a bit weird negation approach, but it works = all packages that have user channel
c.run("graph info pkg -o *:myoption=3 -o ~*@:myoption=1")
assert "dep1/0.1: MYOPTION: 3" in c.out
assert "dep2/0.1@user: MYOPTION: 1" in c.out
assert "dep3/0.1@user/channel: MYOPTION: 1" in c.out

# Which is identical to '~*@' == '*@*'
c.run("graph info pkg -o *:myoption=3 -o *@*:myoption=1")
assert "dep1/0.1: MYOPTION: 3" in c.out
assert "dep2/0.1@user: MYOPTION: 1" in c.out
assert "dep3/0.1@user/channel: MYOPTION: 1" in c.out


class TestTransitiveOptionsSharedInvisible:
"""
https://github.com/conan-io/conan/issues/13854
Expand Down
20 changes: 20 additions & 0 deletions conans/test/integration/settings/per_package_settings_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,23 @@ class Pkg(ConanFile):
client.run("create . --name=consumer --version=0.1 --user=user --channel=testing %s -s compiler.libcxx=libstdc++ "
"-s pkg*:compiler.libcxx=libstdc++11" % settings)
self.assertIn("consumer/0.1@user/testing: Created package", client.out)

def test_per_package_setting_all_packages_without_user_channel(self):
client = TestClient()
conanfile = textwrap.dedent("""
from conan import ConanFile
class Pkg(ConanFile):
settings = "os"
def configure(self):
self.output.info(f"I am a {self.settings.os} pkg!!!")
""")
client.save({"conanfile.py": conanfile})
client.run("create . --name=pkg1 --version=0.1 -s os=Windows")
client.run("create . --name=pkg2 --version=0.1 --user=user -s os=Linux")
client.run("create . --name=pkg3 --version=0.1 --user=user --channel=channel -s os=Linux")
client.save({"conanfile.py": GenConanfile().with_requires("pkg1/0.1", "pkg2/0.1@user",
"pkg3/0.1@user/channel")})
client.run("install . -s os=Linux -s *@:os=Windows")
assert "pkg1/0.1: I am a Windows pkg!!!" in client.out
assert "pkg2/0.1@user: I am a Linux pkg!!!" in client.out
assert "pkg3/0.1@user/channel: I am a Linux pkg!!!" in client.out