Snap for 7803083 from a181fe59a34803a1ba7300bd1a32532b6dc3e9fb to mainline-tzdata2-release

Change-Id: Ie7e00b8d8633434cbcd2b463c414ee95b7e57b83
diff --git a/Dockerfile b/Dockerfile
index 2185c83..aba9898 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -12,4 +12,4 @@
 
 WORKDIR /src
 ENTRYPOINT ["./gradlew"]
-CMD ["-PndkPath=/ndk", "run"]
+CMD ["-PndkPath=/ndk", "release"]
diff --git a/README.md b/README.md
index 7d47a9b..6a70957 100644
--- a/README.md
+++ b/README.md
@@ -20,44 +20,13 @@
 Projects define the name and version of the port, the URL to fetch source from,
 a list of modules (libraries) to build, and the build steps.
 
-```kotlin
-abstract class Port {
-    abstract val name: String
-    abstract val version: String
-    abstract val url: String
-
-    open val dependencies: List<String> = emptyList()
-    abstract val modules: List<Module>
-
-    open fun fetchSource(
-        sourceDirectory: File,
-        workingDirectory: File
-    ): Result<Unit, String>
-
-    open fun configure(
-        toolchain: Toolchain,
-        sourceDirectory: File,
-        buildDirectory: File,
-        installDirectory: File,
-        workingDirectory: File
-    ): Result<Unit, String>
-
-    open fun build(
-        toolchain: Toolchain,
-        buildDirectory: File
-    ): Result<Unit, String>
-
-    open fun install(
-        toolchain: Toolchain,
-        buildDirectory: File,
-        installDirectory: File
-    ): Result<Unit, String>
-}
-```
+See the [Port class] for documentation on the port API.
 
 Individual port files are kept in `ports/$name/port.kts`. For example, the cURL
 port is [ports/curl/port.kts](ports/curl/port.kts).
 
+[Port class]: src/main/kotlin/com/android/ndkports/Port.kt
+
 ## Building a Port
 
 ndkports requires an NDK to be used for building to be specified on the command
diff --git a/build.gradle.kts b/build.gradle.kts
index b9a4d11..a00d626 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,7 +1,7 @@
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
 plugins {
-    kotlin("jvm") version "1.3.50"
+    kotlin("jvm") version "1.3.72"
     application
 }
 
@@ -16,13 +16,12 @@
 }
 
 dependencies {
-    implementation(kotlin("stdlib", "1.3.50"))
-    implementation(kotlin("reflect", "1.3.50"))
+    implementation(kotlin("stdlib", "1.3.72"))
+    implementation(kotlin("reflect", "1.3.72"))
 
-    implementation("com.google.prefab:api:1.0.0-alpha2")
+    implementation("com.google.prefab:api:1.0.0")
 
     implementation("com.github.ajalt:clikt:2.2.0")
-    implementation("com.squareup.okhttp3:okhttp:4.2.2")
     implementation("de.swirtz:ktsRunner:0.0.7")
     implementation("org.apache.maven:maven-core:3.6.2")
     implementation("org.redundent:kotlin-xml-builder:1.5.3")
@@ -46,6 +45,10 @@
     )
 }
 
+val portsBuildDir = buildDir.resolve("ports")
+
+val allPorts = listOf("openssl", "curl", "jsoncpp")
+
 // Can be specified in ~/.gradle/gradle.properties:
 //
 //     ndkPath=/path/to/ndk
@@ -55,6 +58,56 @@
 //     ./gradlew -PndkPath=/path/to/ndk run
 val ndkPath: String by project
 tasks.named<JavaExec>("run") {
-    val allPorts = File("ports").listFiles()!!.map { it.name }
-    args = listOf("--ndk", ndkPath, "-o", "out") + allPorts
-}
\ No newline at end of file
+    // Order matters since we don't do any dependency sorting, so we can't just
+    // use the directory list.
+    args = listOf("--ndk", ndkPath, "-o", portsBuildDir.toString()) + allPorts
+}
+
+for (port in allPorts) {
+    distributions {
+        create(port) {
+            contents {
+                includeEmptyDirs = false
+                from(portsBuildDir.resolve(port)) {
+                    include("**/*.aar")
+                    include("**/*.pom")
+                }
+            }
+        }
+    }
+
+    tasks.named("${port}DistTar") {
+        dependsOn(":run")
+    }
+
+    tasks.named("${port}DistZip") {
+        dependsOn(":run")
+    }
+}
+
+distributions {
+    create("all") {
+        contents {
+            includeEmptyDirs = false
+            from(portsBuildDir) {
+                include("**/*.aar")
+                include("**/*.pom")
+            }
+        }
+    }
+}
+
+tasks.named("allDistTar") {
+    dependsOn(":run")
+}
+
+tasks.named("allDistZip") {
+    dependsOn(":run")
+}
+
+tasks.register("release") {
+    dependsOn(":allDistZip")
+    for (port in allPorts) {
+        dependsOn(":${port}DistZip")
+    }
+}
diff --git a/ports/curl/port.kts b/ports/curl/port.kts
index 734fa27..a870a86 100644
--- a/ports/curl/port.kts
+++ b/ports/curl/port.kts
@@ -20,8 +20,8 @@
 
 object : AutoconfPort() {
     override val name = "curl"
-    override val version = "7.66.0"
-    override val url = "https://curl.haxx.se/download/curl-$version.tar.gz"
+    override val version = "7.69.1"
+    override val mavenVersion = "$version-alpha-1"
     override val licensePath = "COPYING"
 
     override val license = License(
@@ -67,4 +67,4 @@
         // TODO: Switch to lld once we're using r21.
         "LDFLAGS" to "-fuse-ld=gold"
     )
-}
\ No newline at end of file
+}
diff --git a/ports/curl/src.tar.gz b/ports/curl/src.tar.gz
new file mode 100644
index 0000000..b0da690
--- /dev/null
+++ b/ports/curl/src.tar.gz
Binary files differ
diff --git a/ports/jsoncpp/port.kts b/ports/jsoncpp/port.kts
index f951e23..8a3e1ba 100644
--- a/ports/jsoncpp/port.kts
+++ b/ports/jsoncpp/port.kts
@@ -20,9 +20,8 @@
 
 object : MesonPort() {
     override val name = "jsoncpp"
-    override val version = "1.9.1"
-    override val url =
-        "https://github.com/open-source-parsers/jsoncpp/archive/$version.tar.gz"
+    override val version = "1.8.4"
+    override val mavenVersion = "$version-alpha-1"
 
     override val license = License(
         "The JsonCpp License",
@@ -33,14 +32,17 @@
         Module("jsoncpp")
     )
 
-    override fun fetchSource(
+    override fun extractSource(
+        sourceTarball: File,
         sourceDirectory: File,
         workingDirectory: File
     ): Result<Unit, String> =
-        super.fetchSource(sourceDirectory, workingDirectory).onSuccess {
-            // jsoncpp has a "version" file on the include path that conflicts
-            // with https://en.cppreference.com/w/cpp/header/version. Remove it
-            // so we can build.
-            sourceDirectory.resolve("version").delete()
-        }
-}
\ No newline at end of file
+        super.extractSource(sourceTarball, sourceDirectory, workingDirectory)
+            .onSuccess {
+                // jsoncpp has a "version" file on the include path that
+                // conflicts with
+                // https://en.cppreference.com/w/cpp/header/version. Remove it
+                // so we can build.
+                sourceDirectory.resolve("version").delete()
+            }
+}
diff --git a/ports/jsoncpp/src.tar.gz b/ports/jsoncpp/src.tar.gz
new file mode 100644
index 0000000..7f3cd4b
--- /dev/null
+++ b/ports/jsoncpp/src.tar.gz
Binary files differ
diff --git a/ports/openssl/port.kts b/ports/openssl/port.kts
index 00345bc..45b5206 100644
--- a/ports/openssl/port.kts
+++ b/ports/openssl/port.kts
@@ -20,9 +20,9 @@
 
 object : Port() {
     override val name = "openssl"
-    override val version = "1.1.1d"
-    override val prefabVersion = CMakeCompatibleVersion(1, 1, 1, 4)
-    override val url = "https://www.openssl.org/source/openssl-$version.tar.gz"
+    override val version = "1.1.1g"
+    override val mavenVersion = "$version-alpha-1"
+    override val prefabVersion = CMakeCompatibleVersion(1, 1, 1, 7)
 
     override val license = License(
         "Dual OpenSSL and SSLeay License",
@@ -87,4 +87,4 @@
                 "PATH" to "${toolchain.binDir}:${System.getenv("PATH")}"
             )
         )
-}
\ No newline at end of file
+}
diff --git a/ports/openssl/src.tar.gz b/ports/openssl/src.tar.gz
new file mode 100644
index 0000000..e768f9e
--- /dev/null
+++ b/ports/openssl/src.tar.gz
Binary files differ
diff --git a/src/main/kotlin/com/android/ndkports/Cli.kt b/src/main/kotlin/com/android/ndkports/Cli.kt
index 25d48ed..e2a5879 100644
--- a/src/main/kotlin/com/android/ndkports/Cli.kt
+++ b/src/main/kotlin/com/android/ndkports/Cli.kt
@@ -51,8 +51,11 @@
 
     private val ndk: Ndk by option().convert { Ndk(File(it)) }.required()
 
+    private fun portDirectoryFor(name: String): File =
+        File("ports").resolve(name)
+
     private fun loadPort(name: String): Port {
-        val portDir = File("ports").resolve(name).also {
+        val portDir = portDirectoryFor(name).also {
             if (!it.exists()) {
                 throw FileNotFoundException("Could not find ${it.path}")
             }
@@ -73,12 +76,12 @@
         for (port in portsByName.values) {
             val workingDirectory =
                 outDir.resolve(port.name).also { it.mkdirs() }
-            val sourceDirectory = workingDirectory.resolve("src")
 
-            port.fetchSource(sourceDirectory, workingDirectory).onFailure {
-                println(it)
-                exitProcess(1)
-            }
+            val sourceDirectory = workingDirectory.resolve("src")
+            val sourceTarball =
+                portDirectoryFor(port.name).resolve("src.tar.gz")
+
+            port.extractSource(sourceTarball, sourceDirectory, workingDirectory)
 
             val apiForAbi = mapOf(
                 Abi.Arm to 16,
diff --git a/src/main/kotlin/com/android/ndkports/Port.kt b/src/main/kotlin/com/android/ndkports/Port.kt
index 08c8fbf..2e0433f 100644
--- a/src/main/kotlin/com/android/ndkports/Port.kt
+++ b/src/main/kotlin/com/android/ndkports/Port.kt
@@ -16,10 +16,7 @@
 
 package com.android.ndkports
 
-import okhttp3.OkHttpClient
-import okhttp3.Request
 import java.io.File
-import java.io.FileOutputStream
 
 @Suppress("unused")
 fun executeProcessStep(
@@ -52,29 +49,105 @@
     toolchain: Toolchain
 ): File = workingDirectory.parentFile.resolve("$name/install/${toolchain.abi}")
 
+/**
+ * A module exported by the package.
+ *
+ * As currently implemented by ndkports, one module is exactly one library.
+ * Prefab supports header-only libraries, but ndkports does not support these
+ * yet.
+ *
+ * Static libraries are not currently supported by ndkports.
+ *
+ * @property[name] The name of the module. Note that currently the name of the
+ * installed library file must be exactly `lib$name.so`.
+ * @property[includesPerAbi] Set to true if a different set of headers should be
+ * exposed per-ABI. Not currently implemented.
+ * @property[dependencies] A list of other modules required by this module, in
+ * the format described by https://google.github.io/prefab/.
+ */
 data class Module(
     val name: String,
     val includesPerAbi: Boolean = false,
     val dependencies: List<String> = emptyList()
 )
 
+/**
+ * The base class for all ports.
+ */
 abstract class Port {
+    /**
+     * The name of the port. Will be used as the package name in prefab.json.
+     */
     abstract val name: String
+
+    /**
+     * The version of the package.
+     *
+     * Used as the default for [prefabVersion] and [mavenVersion] when
+     * appropriate.
+     */
     abstract val version: String
+
+    /**
+     * The version to encode in the prefab.json.
+     *
+     * This version must be compatible with CMake's `find_package` for
+     * config-style packages. This means that it must be one to four decimal
+     * separated integers. No other format is allowed.
+     *
+     * If not set, the default is [version] as interpreted by
+     * [CMakeCompatibleVersion.parse].
+     *
+     * For example, OpenSSL 1.1.1g will set this value to
+     * `CMakeCompatibleVersion(1, 1, 1, 7)`.
+     */
     open val prefabVersion: CMakeCompatibleVersion
         get() = CMakeCompatibleVersion.parse(version)
+
+    /**
+     * The version to use for the maven package.
+     *
+     * This field allows versioning the maven package differently from the
+     * package itself, which is sometimes necessary given CMake's strict version
+     * format requirements.
+     *
+     * If not set, the default is [version].
+     *
+     * For example, this could be set to `"$name-$version-alpha-1"` to
+     * distribute an alpha of the package.
+     */
     open val mavenVersion: String
         get() = version
 
-    abstract val url: String
-
+    /**
+     * The relative path to the license file of this package.
+     *
+     * This file will be packaged in the AAR in the META-INF directory.
+     */
     open val licensePath: String = "LICENSE"
 
+    /**
+     * A description of the license (name and URL) for use in the pom.xml.
+     */
     abstract val license: License
 
+    /**
+     * A list of dependencies for this package.
+     *
+     * For example, curl depends on `listOf("openssl")`.
+     */
     open val dependencies: List<String> = emptyList()
+
+    /**
+     * A list of modules exported by this package.
+     */
     abstract val modules: List<Module>
 
+    /**
+     * The number of CPUs available for building.
+     *
+     * May be passed to the build system if required.
+     */
     protected val ncpus = Runtime.getRuntime().availableProcessors()
 
     fun run(
@@ -103,40 +176,53 @@
         return Result.Ok(Unit)
     }
 
-    open fun fetchSource(
+    /**
+     * Overridable build step for extracting the source package.
+     *
+     * @param[sourceTarball] The path to the source tarball.
+     * @param[sourceDirectory] The destination directory for the extracted
+     * source.
+     * @param[workingDirectory] The working top-level directory for this
+     * package.
+     * @return A [Result<Unit, String>][Result] describing the result of the
+     * operation. On failure, [Result.Error<String>][Result.Error] containing an
+     * error message is returned.
+     */
+    open fun extractSource(
+        sourceTarball: File,
         sourceDirectory: File,
         workingDirectory: File
     ): Result<Unit, String> {
-        val file = workingDirectory.resolve(File(url).name)
-
-        val client = OkHttpClient()
-        val request = Request.Builder().url(url).build()
-        client.newCall(request).execute().use { response ->
-            if (!response.isSuccessful) {
-                return Result.Error("Failed to download $url")
-            }
-
-            val body = response.body ?: throw RuntimeException(
-                "Expected non-null response body for $url"
-            )
-            FileOutputStream(file).use { output ->
-                body.byteStream().use { input ->
-                    input.copyTo(output)
-                }
-            }
-        }
-
         sourceDirectory.mkdirs()
         return executeProcessStep(
             listOf(
                 "tar",
                 "xf",
-                file.absolutePath,
+                sourceTarball.absolutePath,
                 "--strip-components=1"
             ), sourceDirectory
         )
     }
 
+    /**
+     * Overridable build step for configuring the build.
+     *
+     * Any pre-build steps should be run here.
+     *
+     * In an autoconf build, this runs `configure`.
+     *
+     * @param[toolchain] The toolchain used for this build.
+     * @param[sourceDirectory] The directory containing the extracted package
+     * source.
+     * @param[buildDirectory] The directory to use for building.
+     * @param[installDirectory] The destination directory for this package's
+     * installed headers and libraries.
+     * @param[workingDirectory] The top-level working directory for this
+     * package.
+     * @return A [Result<Unit, String>][Result] describing the result of the
+     * operation. On failure, [Result.Error<String>][Result.Error] containing an
+     * error message is returned.
+     */
     open fun configure(
         toolchain: Toolchain,
         sourceDirectory: File,
@@ -145,11 +231,51 @@
         workingDirectory: File
     ): Result<Unit, String> = Result.Ok(Unit)
 
+    /**
+     * Overridable build step for building the package.
+     *
+     * In an autoconf build, this runs `make`.
+     *
+     * @param[toolchain] The toolchain used for this build.
+     * @param[buildDirectory] The directory to use for building.
+     * @return A [Result<Unit, String>][Result] describing the result of the
+     * operation. On failure, [Result.Error<String>][Result.Error] containing an
+     * error message is returned.
+     */
     open fun build(
         toolchain: Toolchain,
         buildDirectory: File
     ): Result<Unit, String> = Result.Ok(Unit)
 
+    /**
+     * Overridable build step for installing built artifacts for packaging.
+     *
+     * The install step is expected to install headers and libraries to the
+     * [installDirectory] with the following layout:
+     *
+     * [installDirectory]
+     *     include/
+     *         <package headers>
+     *     lib/
+     *         <package libraries>
+     *
+     * A matching `lib${module.name}.so` must be present in the `lib` directory
+     * for every item in [modules].
+     *
+     * Note that it is expected for all modules to use the same headers. This is
+     * currently the case for all ports currently maintained, but could change
+     * in the future.
+     *
+     * In an autoconf build, this runs `make install`.
+     *
+     * @param[toolchain] The toolchain used for this build.
+     * @param[buildDirectory] The directory containing build artifacts.
+     * @param[installDirectory] The destination directory for this package's
+     * installed headers and libraries.
+     * @return A [Result<Unit, String>][Result] describing the result of the
+     * operation. On failure, [Result.Error<String>][Result.Error] containing an
+     * error message is returned.
+     */
     open fun install(
         toolchain: Toolchain,
         buildDirectory: File,
diff --git a/src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt b/src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt
index cac9acd..1a58f5a 100644
--- a/src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt
+++ b/src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt
@@ -212,8 +212,8 @@
     }
 
     private fun createArchive() {
-        val archive = directory.resolve("${port.name}.aar")
-        val pomFile = directory.resolve("${port.name}.pom")
+        val archive = directory.resolve("${port.name}-${port.mavenVersion}.aar")
+        val pomFile = directory.resolve("${port.name}-${port.mavenVersion}.pom")
         createZipFromDirectory(archive, packageDirectory)
         createPom(pomFile)
         if (publishToMavenLocal) {