| #!/usr/bin/env kotlin |
| /* |
| * Copyright 2026 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| import java.io.File |
| import java.io.FileNotFoundException |
| import java.net.URI |
| import kotlin.io.readText |
| |
| // This script updates all package-list files in `docs-public/package-lists`. See the README in that |
| // directory for details on the expected contents of the `package-lists` subdirectories. |
| |
| // Navigate up to frameworks/support |
| val supportDir: File = __FILE__.absoluteFile.parentFile.parentFile.parentFile |
| updatePackageLists(File(supportDir, "docs-public/package-lists")) |
| |
| /** Updates the `package-list` file in each subdirectory of [dir]. */ |
| fun updatePackageLists(dir: File) { |
| for (packageListDir in dir.listFiles()) { |
| if (!packageListDir.isDirectory) continue |
| val packageList = PackageListEntry(packageListDir) |
| packageList.update() |
| } |
| } |
| |
| /** Wrapper for functionality of updating a single `package-list` file located in [dir]. */ |
| class PackageListEntry(private val dir: File) { |
| val name: String = dir.name |
| |
| /** Updates the `package-list` file. */ |
| fun update(): Boolean { |
| // If there is a `download-url` file, use that, otherwise use the base url. |
| val downloadUrlFile = |
| getFileIfExists("download-url") |
| ?: getFileIfExists("url") |
| ?: return run { |
| println("ERROR: No `url` file defined for $name") |
| false |
| } |
| val baseDownloadUrl = downloadUrlFile.readText().trim() |
| |
| // Attempt to download the package-list. |
| val baseNewContents = |
| downloadFile(baseDownloadUrl, "package-list") |
| // Newer javadoc calls it element-list instead of package-list. |
| ?: downloadFile(baseDownloadUrl, "element-list") |
| // Sometimes duplicating the last segment of URL will find the package list. |
| ?: downloadFile(duplicateLastSegment(baseDownloadUrl), "package-list") |
| ?: return run { |
| println( |
| "ERROR: Could not download `package-list` or `element-list` from " + |
| "$baseDownloadUrl for $name" |
| ) |
| false |
| } |
| |
| // Add the format line, if one is specified, and optionally filter the contents. |
| val newContents = formatLine() + filterPackageList(baseNewContents) |
| |
| // Update the package-list file. |
| getFile("package-list").writeText(newContents) |
| println("INFO: Package list updated for $name") |
| return true |
| } |
| |
| /** Returns a [File] with [name] contained in [dir]. */ |
| private fun getFile(name: String): File { |
| return File(dir, name) |
| } |
| |
| /** Returns a [File] with [name] contained in [dir] if it exists, or null otherwise. */ |
| private fun getFileIfExists(name: String): File? { |
| return getFile(name).takeIf { it.exists() } |
| } |
| |
| /** Returns the optional line defined in a `format` file to prepend to the `package-list`. */ |
| private fun formatLine(): String { |
| val formatFile = getFileIfExists("format") ?: return "" |
| return formatFile.readText().trim() + "\n" |
| } |
| |
| /** |
| * Filters the contents of the downloaded [packageList] based on the `filter` file, if it |
| * exists. Returns the new `package-list` contents. |
| */ |
| private fun filterPackageList(packageList: String): String { |
| val filterFile = getFileIfExists("filter") ?: return packageList |
| val pattern = filterFile.readText().trim().toRegex() |
| return packageList.split("\n").filter { pattern.matches(it) }.joinToString("\n") |
| } |
| |
| companion object { |
| /** |
| * Downloads the page at [baseUrl]/[page], returning the page contents or `null` if the page |
| * does not exist. |
| */ |
| private fun downloadFile(baseUrl: String, page: String): String? { |
| // Add a trailing slash if there isn't one already. |
| val optionalSlash = "/".takeIf { !baseUrl.endsWith(it) } ?: "" |
| val url = "$baseUrl$optionalSlash$page" |
| return try { |
| URI(url).toURL().readText() |
| } catch (_: FileNotFoundException) { |
| null |
| } |
| } |
| |
| /** |
| * Returns the [url] with the last path segment duplicated. For instance, turns |
| * `https://square.github.io/kotlinpoet/1.x/kotlinpoet` into |
| * `https://square.github.io/kotlinpoet/1.x/kotlinpoet/kotlinpoet`. |
| */ |
| private fun duplicateLastSegment(url: String): String { |
| val withoutSlash = url.removeSuffix("/") |
| val lastSegment = withoutSlash.substringAfterLast("/") |
| return "$withoutSlash/$lastSegment" |
| } |
| } |
| } |