refactor(build-logic): move PSL download to task action

This commit is contained in:
Harsh Shandilya 2022-10-07 17:28:37 +05:30
parent 656669b55e
commit fe666e9ecb
No known key found for this signature in database
3 changed files with 85 additions and 93 deletions

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="KotlinJpsPluginSettings"> <component name="KotlinJpsPluginSettings">
<option name="version" value="1.7.10" /> <option name="version" value="1.7.20" />
</component> </component>
</project> </project>

View file

@ -1,29 +1,87 @@
/* /* This Source Code Form is subject to the terms of the Mozilla Public
* Copyright © 2014-2022 The Android Password Store Authors. All Rights Reserved. * License, v. 2.0. If a copy of the MPL was not distributed with this
* SPDX-License-Identifier: GPL-3.0-only * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
package app.passwordstore.gradle.psl package app.passwordstore.gradle.psl
import java.util.TreeSet
import okhttp3.OkHttpClient
import okhttp3.Request
import okio.ByteString
import okio.ByteString.Companion.encodeUtf8
import okio.buffer import okio.buffer
import okio.sink import okio.sink
import org.gradle.api.DefaultTask import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFile import org.gradle.api.file.RegularFile
import org.gradle.api.file.RegularFileProperty import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.CacheableTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.TaskAction
@CacheableTask /**
* Based on PublicSuffixListGenerator from OkHttp:
* https://github.com/square/okhttp/blob/3ad1912f783e108b3d0ad2c4a5b1b89b827e4db9/okhttp/src/jvmTest/java/okhttp3/internal/publicsuffix/PublicSuffixListGenerator.java
*/
abstract class PSLUpdateTask : DefaultTask() { abstract class PSLUpdateTask : DefaultTask() {
@get:Input abstract val pslData: Property<PublicSuffixListData>
@get:OutputFile abstract val outputFile: RegularFileProperty @get:OutputFile abstract val outputFile: RegularFileProperty
@TaskAction @TaskAction
fun updatePSL() { fun updatePSL() {
writeListToDisk(outputFile.get(), pslData.get()) val pslData = fetchPublicSuffixList()
writeListToDisk(outputFile.get(), pslData)
}
private fun fetchPublicSuffixList(): PublicSuffixListData {
val client = OkHttpClient.Builder().build()
val request =
Request.Builder().url("https://publicsuffix.org/list/public_suffix_list.dat").build()
client.newCall(request).execute().use { response ->
val source = requireNotNull(response.body).source()
val data = PublicSuffixListData()
while (!source.exhausted()) {
val line = source.readUtf8LineStrict()
if (line.trim { it <= ' ' }.isEmpty() || line.startsWith("//")) {
continue
}
if (line.contains(WILDCARD_CHAR)) {
assertWildcardRule(line)
}
var rule = line.encodeUtf8()
if (rule.startsWith(EXCEPTION_RULE_MARKER)) {
rule = rule.substring(1)
// We use '\n' for end of value.
data.totalExceptionRuleBytes += rule.size + 1
data.sortedExceptionRules.add(rule)
} else {
data.totalRuleBytes += rule.size + 1 // We use '\n' for end of value.
data.sortedRules.add(rule)
}
}
return data
}
}
@Suppress("TooGenericExceptionThrown", "ThrowsCount")
private fun assertWildcardRule(rule: String) {
if (rule.indexOf(WILDCARD_CHAR) != 0) {
throw RuntimeException("Wildcard is not not in leftmost position")
}
if (rule.indexOf(WILDCARD_CHAR, 1) != -1) {
throw RuntimeException("Rule contains multiple wildcards")
}
if (rule.length == 1) {
throw RuntimeException("Rule wildcards the first level")
}
} }
private fun writeListToDisk(destination: RegularFile, data: PublicSuffixListData) { private fun writeListToDisk(destination: RegularFile, data: PublicSuffixListData) {
@ -43,4 +101,16 @@ abstract class PSLUpdateTask : DefaultTask() {
} }
} }
} }
data class PublicSuffixListData(
var totalRuleBytes: Int = 0,
var totalExceptionRuleBytes: Int = 0,
val sortedRules: TreeSet<ByteString> = TreeSet(),
val sortedExceptionRules: TreeSet<ByteString> = TreeSet()
)
private companion object {
private const val WILDCARD_CHAR = "*"
private val EXCEPTION_RULE_MARKER = "!".encodeUtf8()
}
} }

View file

@ -1,98 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public /*
* License, v. 2.0. If a copy of the MPL was not distributed with this * Copyright © 2014-2022 The Android Password Store Authors. All Rights Reserved.
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * SPDX-License-Identifier: GPL-3.0-only
*/
package app.passwordstore.gradle.psl package app.passwordstore.gradle.psl
import java.io.Serializable
import java.util.TreeSet
import okhttp3.OkHttpClient
import okhttp3.Request
import okio.ByteString
import okio.ByteString.Companion.encodeUtf8
import org.gradle.api.Plugin import org.gradle.api.Plugin
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.register
/** /** Gradle plugin to update the public suffix list used by the `autofill-parser` library. */
* Gradle plugin to update the public suffix list used by the `lib-publicsuffixlist` component.
*
* Base on PublicSuffixListGenerator from OkHttp:
* https://github.com/square/okhttp/blob/master/okhttp/src/test/java/okhttp3/internal/publicsuffix/PublicSuffixListGenerator.java
*/
@Suppress("Unused") @Suppress("Unused")
class PublicSuffixListPlugin : Plugin<Project> { class PublicSuffixListPlugin : Plugin<Project> {
override fun apply(project: Project) { override fun apply(project: Project) {
project.tasks.register<PSLUpdateTask>("updatePSL") { project.tasks.register<PSLUpdateTask>("updatePSL") {
val list = fetchPublicSuffixList()
pslData.set(list)
outputFile.set(project.layout.projectDirectory.file("src/main/assets/publicsuffixes")) outputFile.set(project.layout.projectDirectory.file("src/main/assets/publicsuffixes"))
} }
} }
private fun fetchPublicSuffixList(): PublicSuffixListData {
val client = OkHttpClient.Builder().build()
val request =
Request.Builder().url("https://publicsuffix.org/list/public_suffix_list.dat").build()
client.newCall(request).execute().use { response ->
val source = requireNotNull(response.body).source()
val data = PublicSuffixListData()
while (!source.exhausted()) {
val line = source.readUtf8LineStrict()
if (line.trim { it <= ' ' }.isEmpty() || line.startsWith("//")) {
continue
}
if (line.contains(WILDCARD_CHAR)) {
assertWildcardRule(line)
}
var rule = line.encodeUtf8()
if (rule.startsWith(EXCEPTION_RULE_MARKER)) {
rule = rule.substring(1)
// We use '\n' for end of value.
data.totalExceptionRuleBytes += rule.size + 1
data.sortedExceptionRules.add(rule)
} else {
data.totalRuleBytes += rule.size + 1 // We use '\n' for end of value.
data.sortedRules.add(rule)
}
}
return data
}
}
@Suppress("TooGenericExceptionThrown", "ThrowsCount")
private fun assertWildcardRule(rule: String) {
if (rule.indexOf(WILDCARD_CHAR) != 0) {
throw RuntimeException("Wildcard is not not in leftmost position")
}
if (rule.indexOf(WILDCARD_CHAR, 1) != -1) {
throw RuntimeException("Rule contains multiple wildcards")
}
if (rule.length == 1) {
throw RuntimeException("Rule wildcards the first level")
}
}
companion object {
private const val WILDCARD_CHAR = "*"
private val EXCEPTION_RULE_MARKER = "!".encodeUtf8()
}
} }
data class PublicSuffixListData(
var totalRuleBytes: Int = 0,
var totalExceptionRuleBytes: Int = 0,
val sortedRules: TreeSet<ByteString> = TreeSet(),
val sortedExceptionRules: TreeSet<ByteString> = TreeSet()
) : Serializable