From 77a3e5bfc1c38edc562ba0dbfe6db8c5216d938a Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Mon, 23 Aug 2021 05:04:01 -0300 Subject: [PATCH] [hotfix] Remove package by its reference (#9459) * #6545 Add local remove test Signed-off-by: Uilian Ries * #6545 Remove package by reference Signed-off-by: Uilian Ries --- conans/client/command.py | 16 +++- .../test/integration/command/remove_test.py | 77 +++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/conans/client/command.py b/conans/client/command.py index ddd77707e56..9ade73113af 100644 --- a/conans/client/command.py +++ b/conans/client/command.py @@ -1182,8 +1182,20 @@ def remove(self, *args): if not args.pattern_or_reference: raise ConanException('Please specify a pattern to be removed ("*" for all)') - return self._conan.remove(pattern=args.pattern_or_reference, query=args.query, - packages=args.packages, builds=args.builds, src=args.src, + try: + pref = PackageReference.loads(args.pattern_or_reference, validate=True) + packages = [pref.id] + pattern_or_reference = repr(pref.ref) + except ConanException: + pref = None + pattern_or_reference = args.pattern_or_reference + packages = args.packages + + if pref and args.packages: + raise ConanException("Use package ID only as -p argument or reference, not both") + + return self._conan.remove(pattern=pattern_or_reference, query=args.query, + packages=packages, builds=args.builds, src=args.src, force=args.force, remote_name=args.remote, outdated=args.outdated) def copy(self, *args): diff --git a/conans/test/integration/command/remove_test.py b/conans/test/integration/command/remove_test.py index 19cdf0d1f8c..21533f32982 100644 --- a/conans/test/integration/command/remove_test.py +++ b/conans/test/integration/command/remove_test.py @@ -519,3 +519,80 @@ def test_remote(self): self.client.run("remove lib/1.0 -f -r default") self.client.run("install lib/1.0@", assert_error=True) self.assertIn("ERROR: Unable to find 'lib/1.0' in remotes", self.client.out) + + +class RemovePackageRevisionsTest(unittest.TestCase): + + NO_SETTINGS_RREF = "f3367e0e7d170aa12abccb175fee5f97" + + def setUp(self): + self.test_server = TestServer(users={"user": "password"}, + write_permissions=[("foobar/0.1@*/*", "user")]) + servers = {"default": self.test_server} + self.client = TestClient(servers=servers, users={"default": [("user", "password")]}) + self.client.run("config set general.revisions_enabled=1") + + def test_remove_local_package_id_argument(self): + """ Remove package ID based on recipe revision. The package must be deleted, but + the recipe must be preserved + Package ID is a separated argument: # -p + """ + self.client.save({"conanfile.py": GenConanfile()}) + self.client.run("create . foobar/0.1@user/testing") + self.client.run("info foobar/0.1@user/testing") + self.assertIn("Binary: Cache", self.client.out) + self.assertIn("Revision: f3367e0e7d170aa12abccb175fee5f97", self.client.out) + self.assertIn("Package revision: 83c38d3b4e5f1b8450434436eec31b00", self.client.out) + + self.client.run("remove -f foobar/0.1@user/testing#{} -p {}" + .format(self.NO_SETTINGS_RREF, NO_SETTINGS_PACKAGE_ID)) + self.client.run("info foobar/0.1@user/testing") + self.assertIn("Binary: Missing", self.client.out) + self.assertIn("Revision: f3367e0e7d170aa12abccb175fee5f97", self.client.out) + self.assertIn("Package revision: None", self.client.out) + + def test_remove_local_package_id_reference(self): + """ Remove package ID based on recipe revision. The package must be deleted, but + the recipe must be preserved. + Package ID is part of package reference: #: + """ + self.client.save({"conanfile.py": GenConanfile()}) + self.client.run("create . foobar/0.1@user/testing") + self.client.run("info foobar/0.1@user/testing") + self.assertIn("Binary: Cache", self.client.out) + self.assertIn("Revision: f3367e0e7d170aa12abccb175fee5f97", self.client.out) + self.assertIn("Package revision: 83c38d3b4e5f1b8450434436eec31b00", self.client.out) + + self.client.run("remove -f foobar/0.1@user/testing#{}:{}" + .format(self.NO_SETTINGS_RREF, NO_SETTINGS_PACKAGE_ID)) + self.client.run("info foobar/0.1@user/testing") + self.assertIn("Binary: Missing", self.client.out) + self.assertIn("Revision: f3367e0e7d170aa12abccb175fee5f97", self.client.out) + self.assertIn("Package revision: None", self.client.out) + + def test_remove_duplicated_package_id(self): + """ The package ID must not be present in both -p argument and package reference + """ + self.client.save({"conanfile.py": GenConanfile()}) + self.client.run("create . foobar/0.1@user/testing") + self.client.run("remove -f foobar/0.1@user/testing#{}:{} -p {}" + .format(self.NO_SETTINGS_RREF, NO_SETTINGS_PACKAGE_ID, + NO_SETTINGS_PACKAGE_ID), assert_error=True) + self.assertIn("Use package ID only as -p argument or reference, not both", self.client.out) + + def test_remove_remote_package_id_reference(self): + """ Remove remote package ID based on recipe revision. The package must be deleted, but + the recipe must be preserved. + Package ID is part of package reference: #: + """ + self.client.save({"conanfile.py": GenConanfile()}) + self.client.run("create . foobar/0.1@user/testing") + self.client.run("upload foobar/0.1@user/testing -r default -c --all") + self.client.run("remove -f foobar/0.1@user/testing#{}:{}" + .format(self.NO_SETTINGS_RREF, NO_SETTINGS_PACKAGE_ID)) + self.client.run("info foobar/0.1@user/testing") + self.assertIn("Binary: Download", self.client.out) + self.client.run("remove -f foobar/0.1@user/testing#{}:{} -r default" + .format(self.NO_SETTINGS_RREF, NO_SETTINGS_PACKAGE_ID)) + self.client.run("info foobar/0.1@user/testing") + self.assertIn("Binary: Missing", self.client.out)