Repository: conan-io/conan
Pull request #17628 (2025-01-24 13:29:55)

test for integrity remove
Changelog: Omit
Docs: Omit

Close https://github.com/conan-io/conan/issues/17622


Patch:
diff --git a/conan/api/subapi/list.py b/conan/api/subapi/list.py
index da4f76578..55686c9bb 100644
--- a/conan/api/subapi/list.py
+++ b/conan/api/subapi/list.py
@@ -394,10 +394,12 @@ def _get_cache_packages_binary_info(cache, prefs) -> Dict[PkgReference, dict]:
         # Read conaninfo
         info_path = os.path.join(pkg_layout.package(), CONANINFO)
         if not os.path.exists(info_path):
-            raise ConanException(f"Corrupted package '{pkg_layout.reference}' "
-                                 f"without conaninfo.txt in: {info_path}")
-        conan_info_content = load(info_path)
-        info = load_binary_info(conan_info_content)
+            ConanOutput().error(f"Corrupted package '{pkg_layout.reference}' "
+                                f"without conaninfo.txt in: {info_path}")
+            info = {}
+        else:
+            conan_info_content = load(info_path)
+            info = load_binary_info(conan_info_content)
         pref = pkg_layout.reference
         # The key shoudln't have the latest package revision, we are asking for package configs
         pref.revision = None
diff --git a/conan/internal/cache/integrity_check.py b/conan/internal/cache/integrity_check.py
index 7e48b3a22..58dec88ea 100644
--- a/conan/internal/cache/integrity_check.py
+++ b/conan/internal/cache/integrity_check.py
@@ -32,7 +32,11 @@ class IntegrityChecker:
     def _recipe_corrupted(self, ref: RecipeReference):
         layout = self._cache.recipe_layout(ref)
         output = ConanOutput()
-        read_manifest, expected_manifest = layout.recipe_manifests()
+        try:
+            read_manifest, expected_manifest = layout.recipe_manifests()
+        except FileNotFoundError:
+            output.error(f"{ref.repr_notime()}: Manifest missing", error_type="exception")
+            return True
         # Filter exports_sources from read manifest if there are no exports_sources locally
         # This happens when recipe is downloaded without sources (not built from source)
         export_sources_folder = layout.export_sources()
@@ -52,7 +56,11 @@ class IntegrityChecker:
     def _package_corrupted(self, ref: PkgReference):
         layout = self._cache.pkg_layout(ref)
         output = ConanOutput()
-        read_manifest, expected_manifest = layout.package_manifests()
+        try:
+            read_manifest, expected_manifest = layout.package_manifests()
+        except FileNotFoundError:
+            output.error(f"{ref.repr_notime()}: Manifest missing", error_type="exception")
+            return True
 
         if read_manifest != expected_manifest:
             output.error(f"{ref}: Manifest mismatch", error_type="exception")


Test patch:
diff --git a/test/integration/command_v2/test_cache_integrity.py b/test/integration/command_v2/test_cache_integrity.py
index 324f9050f..b40c74565 100644
--- a/test/integration/command_v2/test_cache_integrity.py
+++ b/test/integration/command_v2/test_cache_integrity.py
@@ -17,12 +17,92 @@ def test_cache_integrity():
     layout = t.created_layout()
     conaninfo = os.path.join(layout.package(), "conaninfo.txt")
     save(conaninfo, "[settings]")
+    t.run("create . --name pkg4 --version=4.0")
+    layout = t.created_layout()
+    conaninfo = os.path.join(layout.package(), "conaninfo.txt")
+    save(conaninfo, "[settings]")
 
     t.run("cache check-integrity *", assert_error=True)
     assert "pkg1/1.0: Integrity checked: ok" in t.out
     assert "pkg1/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Integrity checked: ok" in t.out
     assert "ERROR: pkg2/2.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Manifest mismatch" in t.out
     assert "ERROR: pkg3/3.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Manifest mismatch" in t.out
+    assert "ERROR: pkg4/4.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Manifest mismatch" in t.out
+
+    t.run("remove pkg2/2.0:da39a3ee5e6b4b0d3255bfef95601890afd80709 -c")
+    t.run("remove pkg3/3.0:da39a3ee5e6b4b0d3255bfef95601890afd80709 -c")
+    t.run("remove pkg4/4.0:da39a3ee5e6b4b0d3255bfef95601890afd80709 -c")
+    t.run("cache check-integrity *")
+    assert "pkg1/1.0: Integrity checked: ok" in t.out
+    assert "pkg2/2.0: Integrity checked: ok" in t.out
+    assert "pkg3/3.0: Integrity checked: ok" in t.out
+    assert "pkg4/4.0: Integrity checked: ok" in t.out
+
+
+def test_cache_integrity_missing_recipe_manifest():
+    t = TestClient()
+    t.save({"conanfile.py": GenConanfile()})
+    t.run("create . --name pkg1 --version 1.0")
+    t.run("create . --name pkg2 --version=2.0")
+    layout = t.exported_layout()
+    manifest = os.path.join(layout.export(), "conanmanifest.txt")
+    os.remove(manifest)
+    t.run("create . --name pkg3 --version=3.0")
+
+    t.run("cache check-integrity *", assert_error=True)
+    assert "pkg1/1.0: Integrity checked: ok" in t.out
+    assert "ERROR: pkg2/2.0#4d670581ccb765839f2239cc8dff8fbd: Manifest missing" in t.out
+    assert "pkg3/3.0: Integrity checked: ok" in t.out
+    assert "ERROR: There are corrupted artifacts, check the error logs" in t.out
+
+    t.run("remove pkg2* -c")
+    t.run("cache check-integrity *")
+    assert "pkg1/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Integrity checked: ok" in t.out
+    assert "pkg3/3.0: Integrity checked: ok" in t.out
+    assert "Integrity check: ok" in t.out
+
+
+def test_cache_integrity_missing_package_manifest():
+    t = TestClient()
+    t.save({"conanfile.py": GenConanfile()})
+    t.run("create . --name pkg1 --version 1.0")
+    t.run("create . --name pkg2 --version=2.0")
+    layout = t.created_layout()
+    manifest = os.path.join(layout.package(), "conanmanifest.txt")
+    os.remove(manifest)
+    t.run("create . --name pkg3 --version=3.0")
+
+    t.run("cache check-integrity *", assert_error=True)
+    assert "pkg1/1.0: Integrity checked: ok" in t.out
+    assert "ERROR: pkg2/2.0#4d670581ccb765839f2239cc8dff8fbd" \
+           ":da39a3ee5e6b4b0d3255bfef95601890afd80709" \
+           "#0ba8627bd47edc3a501e8f0eb9a79e5e: Manifest missing" in t.out
+    assert "pkg3/3.0: Integrity checked: ok" in t.out
+    assert "ERROR: There are corrupted artifacts, check the error logs" in t.out
+
+    t.run("remove pkg2* -c")
+    t.run("cache check-integrity *")
+    assert "pkg1/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Integrity checked: ok" in t.out
+    assert "pkg3/3.0: Integrity checked: ok" in t.out
+    assert "Integrity check: ok" in t.out
+
+
+def test_cache_integrity_missing_package_conaninfo():
+    t = TestClient()
+    t.save({"conanfile.py": GenConanfile()})
+    t.run("create . --name pkg1 --version 1.0")
+    t.run("create . --name pkg2 --version=2.0")
+    layout = t.created_layout()
+    conaninfo = os.path.join(layout.package(), "conaninfo.txt")
+    os.remove(conaninfo)
+
+    t.run("cache check-integrity *", assert_error=True)
+    assert "pkg1/1.0: Integrity checked: ok" in t.out
+    assert "ERROR: pkg2/2.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Manifest mismatch" in t.out
+
+    t.run("remove pkg2* -c")
+    t.run("cache check-integrity *")
+    assert "pkg1/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Integrity checked: ok" in t.out
 
 
 def test_cache_integrity_export_sources():