aboutsummaryrefslogtreecommitdiff
path: root/build-logic/automation-plugins
diff options
context:
space:
mode:
authorHarsh Shandilya <me@msfjarvis.dev>2022-12-02 01:57:02 +0530
committerHarsh Shandilya <me@msfjarvis.dev>2022-12-02 01:57:02 +0530
commitafd0eebdd3287d932c53879fa1ac88f430080ef5 (patch)
tree141b9147325b96f4ab3a49927e4a1d997f3c37be /build-logic/automation-plugins
parent54bb4676a7c16d959769e522ac018f3e3e822797 (diff)
refactor(build-logic): move all code to a single top-level project
Diffstat (limited to 'build-logic/automation-plugins')
-rw-r--r--build-logic/automation-plugins/build.gradle.kts48
-rw-r--r--build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/GitHooksPlugin.kt18
-rw-r--r--build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/crowdin/CrowdinExtension.kt20
-rw-r--r--build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/crowdin/CrowdinPlugin.kt140
-rw-r--r--build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/psl/PSLUpdateTask.kt116
-rw-r--r--build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/psl/PublicSuffixListPlugin.kt20
-rw-r--r--build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/tasks/GitHooks.kt54
7 files changed, 0 insertions, 416 deletions
diff --git a/build-logic/automation-plugins/build.gradle.kts b/build-logic/automation-plugins/build.gradle.kts
deleted file mode 100644
index 0aa6b3ac..00000000
--- a/build-logic/automation-plugins/build.gradle.kts
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-@file:Suppress("DSL_SCOPE_VIOLATION", "UnstableApiUsage")
-
-import org.gradle.api.JavaVersion
-import org.gradle.api.tasks.compile.JavaCompile
-import org.gradle.kotlin.dsl.withType
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
-plugins { `kotlin-dsl` }
-
-afterEvaluate {
- tasks.withType<JavaCompile>().configureEach {
- sourceCompatibility = JavaVersion.VERSION_11.toString()
- targetCompatibility = JavaVersion.VERSION_11.toString()
- }
-
- tasks.withType<KotlinCompile>().configureEach {
- kotlinOptions {
- jvmTarget = JavaVersion.VERSION_11.toString()
- freeCompilerArgs = freeCompilerArgs + "-Xsam-conversions=class"
- }
- }
-}
-
-gradlePlugin {
- plugins {
- register("crowdin") {
- id = "com.github.android-password-store.crowdin-plugin"
- implementationClass = "app.passwordstore.gradle.crowdin.CrowdinDownloadPlugin"
- }
- register("psl") {
- id = "com.github.android-password-store.psl-plugin"
- implementationClass = "app.passwordstore.gradle.psl.PublicSuffixListPlugin"
- }
- register("git-hooks") {
- id = "com.github.android-password-store.git-hooks"
- implementationClass = "app.passwordstore.gradle.GitHooksPlugin"
- }
- }
-}
-
-dependencies {
- implementation(libs.build.download)
- implementation(libs.build.okhttp)
-}
diff --git a/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/GitHooksPlugin.kt b/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/GitHooksPlugin.kt
deleted file mode 100644
index f1b7c39d..00000000
--- a/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/GitHooksPlugin.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package app.passwordstore.gradle
-
-import app.passwordstore.gradle.tasks.GitHooks
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.kotlin.dsl.register
-
-@Suppress("Unused")
-class GitHooksPlugin : Plugin<Project> {
-
- override fun apply(project: Project) {
- project.tasks.register<GitHooks>("installGitHooks") {
- val projectDirectory = project.layout.projectDirectory
- hookSource.set(projectDirectory.file("scripts/pre-push-hook.sh"))
- hookOutput.set(projectDirectory.file(".git/hooks/pre-push"))
- }
- }
-}
diff --git a/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/crowdin/CrowdinExtension.kt b/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/crowdin/CrowdinExtension.kt
deleted file mode 100644
index 3d45aebc..00000000
--- a/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/crowdin/CrowdinExtension.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.gradle.crowdin
-
-/** Extension for configuring [CrowdinDownloadPlugin] */
-interface CrowdinExtension {
-
- /** Configure the project name on Crowdin */
- var projectName: String
-
- /**
- * Don't delete downloaded and extracted translation archives from build directory.
- *
- * Useful for debugging.
- */
- var skipCleanup: Boolean
-}
diff --git a/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/crowdin/CrowdinPlugin.kt b/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/crowdin/CrowdinPlugin.kt
deleted file mode 100644
index 98882af5..00000000
--- a/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/crowdin/CrowdinPlugin.kt
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.gradle.crowdin
-
-import de.undercouch.gradle.tasks.download.Download
-import java.io.File
-import java.util.concurrent.TimeUnit
-import javax.xml.parsers.DocumentBuilderFactory
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import org.gradle.api.GradleException
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.tasks.Copy
-import org.gradle.kotlin.dsl.create
-import org.gradle.kotlin.dsl.register
-import org.w3c.dom.Document
-
-private const val EXCEPTION_MESSAGE =
- """Applying `crowdin-plugin` requires a projectName to be configured via the "crowdin" extension."""
-private const val CROWDIN_BUILD_API_URL =
- "https://api.crowdin.com/api/project/%s/export?login=%s&account-key=%s"
-
-@Suppress("Unused")
-class CrowdinDownloadPlugin : Plugin<Project> {
-
- override fun apply(project: Project) {
- with(project) {
- val buildDirectory = layout.buildDirectory.asFile.get()
- val extension = extensions.create<CrowdinExtension>("crowdin")
- afterEvaluate {
- val projectName = extension.projectName
- if (projectName.isEmpty()) {
- throw GradleException(EXCEPTION_MESSAGE)
- }
- val buildOnApi =
- tasks.register("buildOnApi") {
- doLast {
- val login = providers.environmentVariable("CROWDIN_LOGIN")
- val key = providers.environmentVariable("CROWDIN_PROJECT_KEY")
- if (!login.isPresent) {
- throw GradleException("CROWDIN_LOGIN environment variable must be set")
- }
- if (!key.isPresent) {
- throw GradleException("CROWDIN_PROJECT_KEY environment variable must be set")
- }
- val client =
- OkHttpClient.Builder()
- .connectTimeout(5, TimeUnit.MINUTES)
- .writeTimeout(5, TimeUnit.MINUTES)
- .readTimeout(5, TimeUnit.MINUTES)
- .callTimeout(10, TimeUnit.MINUTES)
- .build()
- val url = CROWDIN_BUILD_API_URL.format(projectName, login.get(), key.get())
- val request = Request.Builder().url(url).get().build()
- client.newCall(request).execute().close()
- }
- }
- val downloadCrowdin =
- tasks.register<Download>("downloadCrowdin") {
- dependsOn(buildOnApi)
- src("https://crowdin.com/backend/download/project/$projectName.zip")
- dest("$buildDirectory/translations.zip")
- overwrite(true)
- }
- val extractCrowdin =
- tasks.register<Copy>("extractCrowdin") {
- dependsOn(downloadCrowdin)
- doFirst { File(buildDir, "translations").deleteRecursively() }
- from(zipTree("$buildDirectory/translations.zip"))
- into("$buildDirectory/translations")
- }
- val extractStrings =
- tasks.register<Copy>("extractStrings") {
- dependsOn(extractCrowdin)
- from("$buildDirectory/translations/")
- into("${projectDir}/src/")
- setFinalizedBy(setOf("removeIncompleteStrings"))
- }
- tasks.register("removeIncompleteStrings") {
- doLast {
- val sourceSets = arrayOf("main", "nonFree")
- for (sourceSet in sourceSets) {
- val fileTreeWalk = projectDir.resolve("src/$sourceSet").walkTopDown()
- val valuesDirectories =
- fileTreeWalk.filter { it.isDirectory }.filter { it.name.startsWith("values") }
- val stringFiles = fileTreeWalk.filter { it.name == "strings.xml" }
- val sourceFile =
- stringFiles.firstOrNull { it.path.endsWith("values/strings.xml") }
- ?: throw GradleException("No root strings.xml found in '$sourceSet' sourceSet")
- val sourceDoc = parseDocument(sourceFile)
- val baselineStringCount = countStrings(sourceDoc)
- val threshold = 0.80 * baselineStringCount
- stringFiles.forEach { file ->
- if (file != sourceFile) {
- val doc = parseDocument(file)
- val stringCount = countStrings(doc)
- if (stringCount < threshold) {
- file.delete()
- }
- }
- }
- valuesDirectories.forEach { dir ->
- if (dir.listFiles().isNullOrEmpty()) {
- dir.delete()
- }
- }
- }
- }
- }
- tasks.register("crowdin") {
- dependsOn(extractStrings)
- if (!extension.skipCleanup) {
- doLast {
- File("$buildDirectory/translations").deleteRecursively()
- File("$buildDirectory/nonFree-translations").deleteRecursively()
- File("$buildDirectory/translations.zip").delete()
- }
- }
- }
- }
- }
- }
-
- private fun parseDocument(file: File): Document {
- val dbFactory = DocumentBuilderFactory.newInstance()
- val documentBuilder = dbFactory.newDocumentBuilder()
- return documentBuilder.parse(file)
- }
-
- private fun countStrings(document: Document): Int {
- // Normalization is beneficial for us
- // https://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
- document.documentElement.normalize()
- return document.getElementsByTagName("string").length
- }
-}
diff --git a/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/psl/PSLUpdateTask.kt b/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/psl/PSLUpdateTask.kt
deleted file mode 100644
index a5de3d49..00000000
--- a/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/psl/PSLUpdateTask.kt
+++ /dev/null
@@ -1,116 +0,0 @@
-/* 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
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-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.sink
-import org.gradle.api.DefaultTask
-import org.gradle.api.file.RegularFile
-import org.gradle.api.file.RegularFileProperty
-import org.gradle.api.tasks.OutputFile
-import org.gradle.api.tasks.TaskAction
-
-/**
- * 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() {
- @get:OutputFile abstract val outputFile: RegularFileProperty
-
- @TaskAction
- fun updatePSL() {
- 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) {
- val fileSink = destination.asFile.sink()
-
- fileSink.buffer().use { sink ->
- sink.writeInt(data.totalRuleBytes)
-
- for (domain in data.sortedRules) {
- sink.write(domain).writeByte('\n'.toInt())
- }
-
- sink.writeInt(data.totalExceptionRuleBytes)
-
- for (domain in data.sortedExceptionRules) {
- sink.write(domain).writeByte('\n'.toInt())
- }
- }
- }
-
- 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()
- }
-}
diff --git a/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/psl/PublicSuffixListPlugin.kt b/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/psl/PublicSuffixListPlugin.kt
deleted file mode 100644
index 2efeb4dd..00000000
--- a/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/psl/PublicSuffixListPlugin.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright © 2014-2022 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.gradle.psl
-
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.kotlin.dsl.register
-
-/** Gradle plugin to update the public suffix list used by the `autofill-parser` library. */
-@Suppress("Unused")
-class PublicSuffixListPlugin : Plugin<Project> {
- override fun apply(project: Project) {
- project.tasks.register<PSLUpdateTask>("updatePSL") {
- outputFile.set(project.layout.projectDirectory.file("src/main/assets/publicsuffixes"))
- }
- }
-}
diff --git a/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/tasks/GitHooks.kt b/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/tasks/GitHooks.kt
deleted file mode 100644
index 3ffb4c71..00000000
--- a/build-logic/automation-plugins/src/main/kotlin/app/passwordstore/gradle/tasks/GitHooks.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.gradle.tasks
-
-import java.nio.file.Files
-import java.nio.file.StandardCopyOption
-import java.nio.file.attribute.PosixFilePermission.GROUP_EXECUTE
-import java.nio.file.attribute.PosixFilePermission.GROUP_READ
-import java.nio.file.attribute.PosixFilePermission.OTHERS_EXECUTE
-import java.nio.file.attribute.PosixFilePermission.OTHERS_READ
-import java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE
-import java.nio.file.attribute.PosixFilePermission.OWNER_READ
-import java.nio.file.attribute.PosixFilePermission.OWNER_WRITE
-import org.gradle.api.DefaultTask
-import org.gradle.api.file.RegularFileProperty
-import org.gradle.api.tasks.CacheableTask
-import org.gradle.api.tasks.InputFile
-import org.gradle.api.tasks.OutputFile
-import org.gradle.api.tasks.PathSensitive
-import org.gradle.api.tasks.PathSensitivity
-import org.gradle.api.tasks.TaskAction
-
-@CacheableTask
-abstract class GitHooks : DefaultTask() {
- @get:InputFile
- @get:PathSensitive(PathSensitivity.NONE)
- abstract val hookSource: RegularFileProperty
-
- @get:OutputFile abstract val hookOutput: RegularFileProperty
-
- @TaskAction
- fun install() {
- Files.copy(
- hookSource.asFile.get().toPath(),
- hookOutput.asFile.get().toPath(),
- StandardCopyOption.REPLACE_EXISTING,
- )
- Files.setPosixFilePermissions(
- hookOutput.asFile.get().toPath(),
- setOf(
- OWNER_READ,
- OWNER_WRITE,
- OWNER_EXECUTE,
- GROUP_READ,
- GROUP_EXECUTE,
- OTHERS_READ,
- OTHERS_EXECUTE,
- )
- )
- }
-}