diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/verification/DependencyVerificationWritingIntegTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/verification/DependencyVerificationWritingIntegTest.groovy index c6b52fa52b57..2444617a0880 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/verification/DependencyVerificationWritingIntegTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/verification/DependencyVerificationWritingIntegTest.groovy @@ -16,12 +16,15 @@ package org.gradle.integtests.resolve.verification +import org.gradle.api.internal.artifacts.ivyservice.CacheLayout import org.gradle.integtests.fixtures.ToBeFixedForInstantExecution +import org.gradle.integtests.fixtures.cache.CachingIntegrationFixture import org.gradle.test.fixtures.maven.MavenFileModule import org.gradle.test.fixtures.maven.MavenFileRepository +import spock.lang.Issue import spock.lang.Unroll -class DependencyVerificationWritingIntegTest extends AbstractDependencyVerificationIntegTest { +class DependencyVerificationWritingIntegTest extends AbstractDependencyVerificationIntegTest implements CachingIntegrationFixture { def "can generate an empty verification file"() { when: @@ -1279,4 +1282,48 @@ class DependencyVerificationWritingIntegTest extends AbstractDependencyVerificat hasModules(["org:foo"]) } + @Issue("https://github.com/gradle/gradle/issues/12260") + @Unroll + def "doesn't fail writing verification file if a #artifact file is missing from local store"() { + javaLibrary() + uncheckedModule("org", "foo") + buildFile << """ + dependencies { + implementation "org:foo:1.0" + } + """ + + when: + run ":compileJava" + + then: + noExceptionThrown() + + when: + def group = new File(CacheLayout.FILE_STORE.getPath(metadataCacheDir), "org") + def module = new File(group, "foo") + def version = new File(module, "1.0") + version.eachFileRecurse { + if (it.name.endsWith(".${artifact}")) { + it.delete() + } + } + + writeVerificationMetadata() + run ":help", "--offline" + + then: + hasModules(["org:foo"]) + + and: + if (artifact == 'pom') { + // there's a technical limitation due to the code path used for regular artifacts + // which makes it that we don't even try to snapshot if the file is missing so we can't + // provide an error message + outputContains("Cannot compute checksum for") + } + where: + artifact << ['jar', 'pom'] + } + } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/verification/writer/WriteDependencyVerificationFile.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/verification/writer/WriteDependencyVerificationFile.java index e0c9ecc2cc58..4bde1df1fa41 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/verification/writer/WriteDependencyVerificationFile.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/verification/writer/WriteDependencyVerificationFile.java @@ -352,6 +352,7 @@ private void computeChecksumsConcurrently(SignatureVerificationService signature } if (!entry.getFile().exists()) { LOGGER.warn("Cannot compute checksum for " + entry.getFile() + " because it doesn't exist. It may indicate a corrupt or tampered cache."); + continue; } if (entry instanceof ChecksumEntry) { queueChecksumVerification(queue, (ChecksumEntry) entry); @@ -447,7 +448,12 @@ private boolean isTrustedArtifact(ModuleComponentArtifactIdentifier id) { } private String createHash(File file, ChecksumKind kind) { - return checksumService.hash(file, kind.getAlgorithm()).toString(); + try { + return checksumService.hash(file, kind.getAlgorithm()).toString(); + } catch (Exception e) { + LOGGER.debug("Error while snapshotting " + file, e); + return null; + } } private static void resolveAllConfigurationsAndForceDownload(Project p) {