From 132c81b142314b5deb33613db33ff0a2b1656f71 Mon Sep 17 00:00:00 2001 From: Alan Evans Date: Fri, 24 May 2019 14:29:01 -0300 Subject: [PATCH] Bring Gradle Witness into repo. - Api/Implementation compatible. - Regex configuration name. --- build.gradle | 2 +- .../witness/WitnessPlugin.groovy | 92 ++++++++++++++++++ .../gradle-plugins/witness.properties | 1 + libs/gradle-witness.jar | Bin 16689 -> 0 bytes 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 buildSrc/src/main/groovy/org/whispersystems/witness/WitnessPlugin.groovy create mode 100644 buildSrc/src/main/resources/META-INF/gradle-plugins/witness.properties delete mode 100644 libs/gradle-witness.jar diff --git a/build.gradle b/build.gradle index f90241631..f28f44e2a 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,6 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:3.3.2' - classpath files('libs/gradle-witness.jar') } } @@ -162,6 +161,7 @@ dependencies { } dependencyVerification { + configuration = '(play|website)(Debug|Release)RuntimeClasspath' verify = [ 'com.android.support:design:7874ad1904eedc74aa41cffffb7f759d8990056f3bbbc9264911651c67c42f5f', 'com.android.support:preference-v14:8133c6e19233fa51e036a341e6d3f4adeead3375cebf777efced0fe154c3267e', diff --git a/buildSrc/src/main/groovy/org/whispersystems/witness/WitnessPlugin.groovy b/buildSrc/src/main/groovy/org/whispersystems/witness/WitnessPlugin.groovy new file mode 100644 index 000000000..31dae7e99 --- /dev/null +++ b/buildSrc/src/main/groovy/org/whispersystems/witness/WitnessPlugin.groovy @@ -0,0 +1,92 @@ +package org.whispersystems.witness + +import org.gradle.api.InvalidUserDataException +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.ResolvedArtifact + +import java.security.MessageDigest + +class WitnessPluginExtension { + List verify + String configuration +} + +class WitnessPlugin implements Plugin { + + static String calculateSha256(file) { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + file.eachByte 4096, {bytes, size -> + md.update(bytes, 0, size); + } + return md.digest().collect {String.format "%02x", it}.join(); + } + + void apply(Project project) { + project.extensions.create("dependencyVerification", WitnessPluginExtension) + project.afterEvaluate { + project.dependencyVerification.verify.each { + assertion -> + List parts = assertion.tokenize(":") + String group = parts.get(0) + String name = parts.get(1) + String hash = parts.get(2) + + def artifacts = allArtifacts(project).findAll { + return it.name.equals(name) && it.moduleVersion.id.group.equals(group) + } + + if (artifacts.size() > 1) { + throw new InvalidUserDataException("Multiple artifacts found for $group:$name, ${artifacts.size()} found") + } + + ResolvedArtifact dependency = artifacts.find() + + println "Verifying " + group + ":" + name + + if (dependency == null) { + throw new InvalidUserDataException("No dependency for integrity assertion found: " + group + ":" + name) + } + + if (!hash.equals(calculateSha256(dependency.file))) { + throw new InvalidUserDataException("Checksum failed for " + assertion) + } + } + } + + project.task('calculateChecksums').doLast { + println "dependencyVerification {" + + def configurationName = project.dependencyVerification.configuration + if (configurationName != null) { + println " configuration = '$configurationName'" + } + + println " verify = [" + + allArtifacts(project).each { + dep -> + println " '" + dep.moduleVersion.id.group+ ":" + dep.name + ":" + calculateSha256(dep.file) + "'," + } + + println " ]" + println "}" + } + } + + private static Set allArtifacts(Project project) { + def configurationName = project.dependencyVerification.configuration + project.configurations + .findAll { config -> config.name =~ configurationName } + .collectMany { tryGetArtifacts(it) } + } + + private static Set tryGetArtifacts(Configuration configuration) { + try { + configuration.resolvedConfiguration.resolvedArtifacts + } catch (Exception ignored) { + [] as Set + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/witness.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/witness.properties new file mode 100644 index 000000000..dae767f67 --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/witness.properties @@ -0,0 +1 @@ +implementation-class=org.whispersystems.witness.WitnessPlugin diff --git a/libs/gradle-witness.jar b/libs/gradle-witness.jar deleted file mode 100644 index 53abf2bb398b04bfaefed23dc52b864b5731b0d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16689 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 E2f&!n0{{R3