From de29e6c8c1344a6f8e90c9015a43a6451294ea06 Mon Sep 17 00:00:00 2001 From: Pierce Zaifman Date: Mon, 30 Aug 2021 17:47:20 -0400 Subject: [PATCH 1/5] Added ability to have custom licenses. Also added task to update only the missing licenses. --- plugin/build.gradle | 2 +- .../plugin/license/LicenseToolsPlugin.kt | 6 +- .../android/plugin/license/Templates.kt | 2 +- .../plugin/license/data/LibraryInfo.kt | 6 +- .../extension/LibraryInfoExtensions.kt | 45 +++++++++- .../license/task/UpdateMissingLicenses.kt | 55 ++++++++++++ .../android/plugin/license/util/YamlUtils.kt | 4 +- .../template/licenses/custom_license.html | 9 ++ .../license/task/UpdateMissingLicensesTest.kt | 86 +++++++++++++++++++ plugin/src/test/resources/yaml/licenses.yml | 41 +++++++++ .../test/resources/yaml/missing_licenses.yml | 17 ++++ .../yaml/missing_licenses_update.yml | 23 +++++ .../test/resources/yaml/removed_licenses.yml | 19 ++++ sample/build.gradle | 2 +- sample/licenses.yml | 41 +++++++++ sample/src/main/assets/licenses.html | 43 ++++++++++ 16 files changed, 388 insertions(+), 13 deletions(-) create mode 100644 plugin/src/main/java/com/cookpad/android/plugin/license/task/UpdateMissingLicenses.kt create mode 100644 plugin/src/main/resources/template/licenses/custom_license.html create mode 100644 plugin/src/test/java/com/cookpad/android/plugin/license/task/UpdateMissingLicensesTest.kt create mode 100644 plugin/src/test/resources/yaml/missing_licenses.yml create mode 100644 plugin/src/test/resources/yaml/missing_licenses_update.yml create mode 100644 plugin/src/test/resources/yaml/removed_licenses.yml diff --git a/plugin/build.gradle b/plugin/build.gradle index 497f062..4e0a362 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -28,7 +28,7 @@ apply plugin: 'maven' archivesBaseName = 'license-tools' group = 'com.cookpad.android.plugin' -version = '1.2.8' +version = '1.2.9' dependencies { compileOnly gradleApi() diff --git a/plugin/src/main/java/com/cookpad/android/plugin/license/LicenseToolsPlugin.kt b/plugin/src/main/java/com/cookpad/android/plugin/license/LicenseToolsPlugin.kt index a051c67..8824a8b 100644 --- a/plugin/src/main/java/com/cookpad/android/plugin/license/LicenseToolsPlugin.kt +++ b/plugin/src/main/java/com/cookpad/android/plugin/license/LicenseToolsPlugin.kt @@ -3,10 +3,7 @@ package com.cookpad.android.plugin.license -import com.cookpad.android.plugin.license.task.CheckLicenses -import com.cookpad.android.plugin.license.task.GenerateLicenseJson -import com.cookpad.android.plugin.license.task.GenerateLicensePage -import com.cookpad.android.plugin.license.task.UpdateLicenses +import com.cookpad.android.plugin.license.task.* import org.gradle.api.Plugin import org.gradle.api.Project @@ -18,6 +15,7 @@ class LicenseToolsPlugin : Plugin { ) CheckLicenses.register(project) UpdateLicenses.register(project) + UpdateMissingLicenses.register(project) GenerateLicensePage.register(project) GenerateLicenseJson.register(project) } diff --git a/plugin/src/main/java/com/cookpad/android/plugin/license/Templates.kt b/plugin/src/main/java/com/cookpad/android/plugin/license/Templates.kt index 732956e..baf8edf 100644 --- a/plugin/src/main/java/com/cookpad/android/plugin/license/Templates.kt +++ b/plugin/src/main/java/com/cookpad/android/plugin/license/Templates.kt @@ -47,7 +47,7 @@ object Templates { @Throws(NotEnoughInformationException::class) private fun assertLicenseAndStatement(library: LibraryInfo) { - if (library.license.isNullOrBlank()) { + if (library.license.isNullOrBlank() && library.customLicenseName.isNullOrBlank()) { throw NotEnoughInformationException( library, "Missing info in the \"license\" field" diff --git a/plugin/src/main/java/com/cookpad/android/plugin/license/data/LibraryInfo.kt b/plugin/src/main/java/com/cookpad/android/plugin/license/data/LibraryInfo.kt index d50520c..7fa6e3f 100644 --- a/plugin/src/main/java/com/cookpad/android/plugin/license/data/LibraryInfo.kt +++ b/plugin/src/main/java/com/cookpad/android/plugin/license/data/LibraryInfo.kt @@ -15,7 +15,9 @@ data class LibraryInfo( val notice: String? = null, val licenseUrl: String?, val skip: Boolean? = null, - val forceGenerate: Boolean? = null + val forceGenerate: Boolean? = null, + val customLicenseName: String? = null, + val customLicenseContent: String? = null ) { fun normalizedLicense(): String { @@ -70,6 +72,7 @@ data class LibraryInfo( amazon_software_license.matches(license) -> "amazon_software_license" play_core_software_development_kit_terms_of_service.matches(license) -> "play_core_software_development_kit_terms_of_service" pushwoosh_license.matches(license) -> "pushwoosh_license" + custom_license.matches(license) -> "custom_license" else -> license } } @@ -142,5 +145,6 @@ data class LibraryInfo( val amazon_software_license = """(?i).*\bAmazon.*\bSoftware.*\bLicense\b.*""".toRegex() val play_core_software_development_kit_terms_of_service = """(?i).*\bPlay.*\bCore.*\bSoftware.*\bDevelopment.*\bKit.*\bTerms.*\bof.*\bService\b.*""".toRegex() val pushwoosh_license = """(?i).*\bPushwoosh.*\bLicense\b.*""".toRegex() + val custom_license = """(?i).*\bCustom.*\bLicense\b.*""".toRegex() } } diff --git a/plugin/src/main/java/com/cookpad/android/plugin/license/extension/LibraryInfoExtensions.kt b/plugin/src/main/java/com/cookpad/android/plugin/license/extension/LibraryInfoExtensions.kt index 05e414d..828cb31 100644 --- a/plugin/src/main/java/com/cookpad/android/plugin/license/extension/LibraryInfoExtensions.kt +++ b/plugin/src/main/java/com/cookpad/android/plugin/license/extension/LibraryInfoExtensions.kt @@ -2,17 +2,54 @@ package com.cookpad.android.plugin.license.extension import com.cookpad.android.plugin.license.data.LibraryInfo -internal fun LibraryInfo.generateLibraryInfoText(): String { +internal fun LibraryInfo.generateLibraryInfoText(updatedInfo: LibraryInfo? = null): String { val text = StringBuffer() text.append("- artifact: ${artifactId.withWildcardVersion()}\n") - text.append(" name: ${name ?: "#NAME#"}\n") - text.append(" copyrightHolder: ${copyrightHolder ?: "#COPYRIGHT_HOLDER#"}\n") - text.append(" license: ${license ?: "#LICENSE#"}\n") + + var currentName = name ?: "#NAME#" + currentName = if (updatedInfo?.name != null && currentName == "#NAME#") { + updatedInfo.name + } else currentName + var currentCopyrightHolder = copyrightHolder ?: "#COPYRIGHT_HOLDER#" + currentCopyrightHolder = if (updatedInfo?.copyrightHolder != null && currentCopyrightHolder == "#COPYRIGHT_HOLDER#") { + updatedInfo.copyrightHolder + } else currentCopyrightHolder + var currentLicense = license ?: "#LICENSE#" + currentLicense = if (updatedInfo?.license != null && currentLicense == "#LICENSE#") { + updatedInfo.license + } else currentLicense + + + + if (currentName != "#NAME#" || skip != true) { + text.append(" name: ${currentName}\n") + } + if (currentCopyrightHolder != "#COPYRIGHT_HOLDER#" || skip != true) { + text.append(" copyrightHolder: ${currentCopyrightHolder}\n") + } + if (currentLicense != "#LICENSE#" || skip != true) { + text.append(" license: ${currentLicense}\n") + } if (licenseUrl?.isNotBlank() == true) { text.append(" licenseUrl: ${licenseUrl}\n") + } else if (updatedInfo?.licenseUrl?.isNotBlank() == true) { + text.append(" licenseUrl: ${updatedInfo.licenseUrl}\n") } if (url?.isNotBlank() == true) { text.append(" url: ${url}\n") + } else if (updatedInfo?.url?.isNotBlank() == true) { + text.append(" url: ${updatedInfo.url}\n") + } + + if (customLicenseName?.isNotBlank() == true) { + text.append(" customLicenseName: ${customLicenseName}\n") + } + if (customLicenseContent?.isNotBlank() == true) { + text.append(" customLicenseContent: |\n ${customLicenseContent.replace("\n", "\n ")}\n") + } + + if (skip == true) { + text.append(" skip: true\n") } return text.toString().trim() } diff --git a/plugin/src/main/java/com/cookpad/android/plugin/license/task/UpdateMissingLicenses.kt b/plugin/src/main/java/com/cookpad/android/plugin/license/task/UpdateMissingLicenses.kt new file mode 100644 index 0000000..fe95a83 --- /dev/null +++ b/plugin/src/main/java/com/cookpad/android/plugin/license/task/UpdateMissingLicenses.kt @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2016 Cookpad Inc. + +package com.cookpad.android.plugin.license.task + +import com.cookpad.android.plugin.license.LicenseToolsPluginExtension +import com.cookpad.android.plugin.license.data.LibraryInfo +import com.cookpad.android.plugin.license.extension.generateLibraryInfoText +import com.cookpad.android.plugin.license.extension.notListedIn +import com.cookpad.android.plugin.license.util.YamlUtils +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.internal.impldep.com.google.common.annotations.VisibleForTesting + +object UpdateMissingLicenses { + fun register(project: Project): Task { + return project.task("updateMissingLicenses").doLast { + val ext = project.extensions.getByType(LicenseToolsPluginExtension::class.java) + val resolvedArtifacts = + CheckLicenses.resolveProjectDependencies(project, ext.ignoredProjects) + val dependencyLicenses = + CheckLicenses.loadDependencyLicenses(project, resolvedArtifacts, ext.ignoredGroups) + updateMissingLicensesYaml(project, ext.licensesYaml, dependencyLicenses) + } + } + + @VisibleForTesting + internal fun updateMissingLicensesYaml( + project: Project, + licensesYaml: String, + dependencyLicenses: List + ) { + // Dedup and sort dependencies + val sortedDependencies = dependencyLicenses.associateBy { it.artifactId.withWildcardVersion() } + .toSortedMap { o1, o2 -> + o1.compareTo(o2, ignoreCase = true) + }.values.toList() + val yamlList = YamlUtils.loadToLibraryInfo(project.file(licensesYaml)) + val notInDependencies = sortedDependencies.notListedIn(yamlList) + + + project.file(licensesYaml).apply { + // Clean content + writeText("") + for (libraryInfo in yamlList) { + sortedDependencies.find { it.artifactId.matches(libraryInfo.artifactId) }?.let { + appendText("${libraryInfo.generateLibraryInfoText(it)}\n") + } + } + for (libraryInfo in notInDependencies) { + appendText("${libraryInfo.generateLibraryInfoText()}\n") + } + } + } +} diff --git a/plugin/src/main/java/com/cookpad/android/plugin/license/util/YamlUtils.kt b/plugin/src/main/java/com/cookpad/android/plugin/license/util/YamlUtils.kt index 5bd1b67..135c481 100644 --- a/plugin/src/main/java/com/cookpad/android/plugin/license/util/YamlUtils.kt +++ b/plugin/src/main/java/com/cookpad/android/plugin/license/util/YamlUtils.kt @@ -33,7 +33,9 @@ object YamlUtils { forceGenerate = it.getOrDefault( "forceGenerate", "false" - ).toString().toBoolean() + ).toString().toBoolean(), + customLicenseName = it["customLicenseName"] as String?, + customLicenseContent = it["customLicenseContent"] as String? ) } } diff --git a/plugin/src/main/resources/template/licenses/custom_license.html b/plugin/src/main/resources/template/licenses/custom_license.html new file mode 100644 index 0000000..2b90fac --- /dev/null +++ b/plugin/src/main/resources/template/licenses/custom_license.html @@ -0,0 +1,9 @@ +
+

${library.name}

+

${library.copyrightStatement.replaceAll("\n\n", "
")}

+ <% print library.url == null || library.url.isEmpty() ? "" : """

${library.url}

""" %> +
+

${library.customLicenseName}

+ ${library.customLicenseContent} +
+
diff --git a/plugin/src/test/java/com/cookpad/android/plugin/license/task/UpdateMissingLicensesTest.kt b/plugin/src/test/java/com/cookpad/android/plugin/license/task/UpdateMissingLicensesTest.kt new file mode 100644 index 0000000..d289c26 --- /dev/null +++ b/plugin/src/test/java/com/cookpad/android/plugin/license/task/UpdateMissingLicensesTest.kt @@ -0,0 +1,86 @@ +package com.cookpad.android.plugin.license.task + +import com.cookpad.android.plugin.license.data.ArtifactId +import com.cookpad.android.plugin.license.loadYamlFromResources +import com.cookpad.android.plugin.license.util.YamlUtils +import com.google.common.truth.Truth.assertThat +import com.nhaarman.mockitokotlin2.doReturn +import com.nhaarman.mockitokotlin2.whenever +import org.gradle.api.Project +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.junit.MockitoJUnitRunner +import java.io.File + +@RunWith(MockitoJUnitRunner::class) +class UpdateMissingLicensesTest { + + @get:Rule + val tempFolder = TemporaryFolder() + private lateinit var licensesYamlFile: File + + @Mock + lateinit var project: Project + + @Before + fun setUp() { + licensesYamlFile = tempFolder.newFile() + whenever(project.file(FILENAME_LICENSES_YAML)) doReturn licensesYamlFile + } + + @After + fun tearDown() { + licensesYamlFile.delete() + } + + @Test + fun updateLicensesYaml_addsMissingDependencies() { + val licenses = loadYamlFromResources("yaml/missing_licenses.yml") + assertThat(licenses.size).isEqualTo(3) + UpdateMissingLicenses.updateMissingLicensesYaml(project, FILENAME_LICENSES_YAML, licenses) + + var result = YamlUtils.loadToLibraryInfo(licensesYamlFile) + assertThat(result.size).isEqualTo(3) + + val update = loadYamlFromResources("yaml/missing_licenses_update.yml") + UpdateMissingLicenses.updateMissingLicensesYaml(project, FILENAME_LICENSES_YAML, update) + result = YamlUtils.loadToLibraryInfo(licensesYamlFile) + assertThat(result.size).isEqualTo(4) + + assertThat(result.size).isEqualTo(update.size) + for (info in update) { + val finalInfo = result.find { it.artifactId.matches(info.artifactId) } + assertThat(finalInfo).isNotNull() + if (info.artifactId.matches(ArtifactId("com.android.support", "+", "+"))) { + assertThat(info).isNotEqualTo(finalInfo) + assertThat(finalInfo!!.license).isEqualTo("apache2") + } else { + assertThat(info).isEqualTo(finalInfo) + } + } + } + + @Test + fun updateLicensesYaml_removeMissingDependencies() { + val licenses = loadYamlFromResources("yaml/missing_licenses_update.yml") + assertThat(licenses.size).isEqualTo(4) + UpdateMissingLicenses.updateMissingLicensesYaml(project, FILENAME_LICENSES_YAML, licenses) + + var result = YamlUtils.loadToLibraryInfo(licensesYamlFile) + assertThat(result.size).isEqualTo(4) + + val update = loadYamlFromResources("yaml/removed_licenses.yml") + UpdateMissingLicenses.updateMissingLicensesYaml(project, FILENAME_LICENSES_YAML, update) + result = YamlUtils.loadToLibraryInfo(licensesYamlFile) + assertThat(result.size).isEqualTo(3) + } + + companion object { + private const val FILENAME_LICENSES_YAML = "licenses.yml" + } +} diff --git a/plugin/src/test/resources/yaml/licenses.yml b/plugin/src/test/resources/yaml/licenses.yml index 890bfde..e6359f8 100644 --- a/plugin/src/test/resources/yaml/licenses.yml +++ b/plugin/src/test/resources/yaml/licenses.yml @@ -76,3 +76,44 @@ license: cc-by-4.0 licenseUrl: https://creativecommons.org/licenses/by/4.0/legalcode url: https://creativecommons.org/ +- artifact: org.concentus:Concentus:+ + name: Concentus + copyrightHolder: | + Copyright (c) by various holding parties, including (but not limited to): + Skype Limited, Xiph.Org Foundation, CSIRO, Microsoft Corporation, + Jean-Marc Valin, Gregory Maxwell, Mark Borgerding, Timothy B. Terriberry, + Logan Stromberg. All rights are reserved by their respective holders. + license: Custom License + customLicenseName: Concentus License + customLicenseContent: | + Copyright (c) by various holding parties, including (but not limited to): + Skype Limited, Xiph.Org Foundation, CSIRO, Microsoft Corporation, + Jean-Marc Valin, Gregory Maxwell, Mark Borgerding, Timothy B. Terriberry, + Logan Stromberg. All rights are reserved by their respective holders. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Internet Society, IETF or IETF Trust, nor the + names of specific contributors, may be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + licenseUrl: https://github.com/lostromb/concentus/blob/master/LICENSE diff --git a/plugin/src/test/resources/yaml/missing_licenses.yml b/plugin/src/test/resources/yaml/missing_licenses.yml new file mode 100644 index 0000000..c8f062b --- /dev/null +++ b/plugin/src/test/resources/yaml/missing_licenses.yml @@ -0,0 +1,17 @@ +- artifact: com.android.support:+:+ + name: Android Support Libraries + copyrightHolder: The Android Open Source Project + license: apache2 +- artifact: com.mopub:libAvid-mopub:+ + name: AVID SDK (MoPub Android namespace) + copyrightHolder: MoPub (a division of Twitter, Inc.) + license: MoPub SDK License + licenseUrl: http://www.mopub.com/legal/sdk-license-agreement/ + url: https://github.com/mopub/mopub-android-sdk +# This is example license +- artifact: com.example:example-common:+ + name: example-common + copyrightHolder: Example Author + license: #LICENSE# + licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt + url: https://example.com/example/example-common diff --git a/plugin/src/test/resources/yaml/missing_licenses_update.yml b/plugin/src/test/resources/yaml/missing_licenses_update.yml new file mode 100644 index 0000000..1d39e79 --- /dev/null +++ b/plugin/src/test/resources/yaml/missing_licenses_update.yml @@ -0,0 +1,23 @@ +- artifact: com.android.support:+:+ + name: Android Support Libraries + copyrightHolder: The Android Open Source Project + license: #LICENSE# +- artifact: com.mopub:libAvid-mopub:+ + name: AVID SDK (MoPub Android namespace) + copyrightHolder: MoPub (a division of Twitter, Inc.) + license: MoPub SDK License + licenseUrl: http://www.mopub.com/legal/sdk-license-agreement/ + url: https://github.com/mopub/mopub-android-sdk +- artifact: com.mopub:mopub-sdk-base:+ + name: mopub-sdk-base + copyrightHolder: MoPub (a division of Twitter, Inc.) + license: MoPub SDK License + licenseUrl: http://www.mopub.com/legal/sdk-license-agreement/ + url: https://github.com/mopub/mopub-android-sdk +# This is example license +- artifact: com.example:example-common:+ + name: example-common + copyrightHolder: Example Author + license: The Apache Software License, Version 2.0 + licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt + url: https://example.com/example/example-common diff --git a/plugin/src/test/resources/yaml/removed_licenses.yml b/plugin/src/test/resources/yaml/removed_licenses.yml new file mode 100644 index 0000000..a2142a5 --- /dev/null +++ b/plugin/src/test/resources/yaml/removed_licenses.yml @@ -0,0 +1,19 @@ +- artifact: com.mopub:libAvid-mopub:+ + name: AVID SDK (MoPub Android namespace) + copyrightHolder: MoPub (a division of Twitter, Inc.) + license: MoPub SDK License + licenseUrl: http://www.mopub.com/legal/sdk-license-agreement/ + url: https://github.com/mopub/mopub-android-sdk +- artifact: org.jetbrains.kotlinx:kotlinx-coroutines-android:+ + name: kotlinx-coroutines-android + copyrightHolder: JetBrains s.r.o. + license: The Apache Software License, Version 2.0 + licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt + url: https://github.com/Kotlin/kotlinx.coroutines +# This is example license +- artifact: com.example:example-common:+ + name: example-common + copyrightHolder: Example Author + license: The Apache Software License, Version 2.0 + licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt + url: https://example.com/example/example-common diff --git a/sample/build.gradle b/sample/build.gradle index e2534ce..a2139d4 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -7,7 +7,7 @@ // mavenLocal() // } // dependencies { -// classpath 'com.cookpad.android.plugin:license-tools:$your_version' +// classpath 'com.cookpad.android.plugin:license-tools:1.2.9' // } //} //apply plugin: 'com.cookpad.android.plugin.license-tools' diff --git a/sample/licenses.yml b/sample/licenses.yml index 21022c5..8705415 100644 --- a/sample/licenses.yml +++ b/sample/licenses.yml @@ -190,3 +190,44 @@ license: The Apache Software License, Version 2.0 licenseUrl: http://www.apache.org/licenses/LICENSE-2.0.txt url: http://www.jetbrains.org +- artifact: org.concentus:Concentus:+ + name: Concentus + copyrightHolder: | + Copyright (c) by various holding parties, including (but not limited to): + Skype Limited, Xiph.Org Foundation, CSIRO, Microsoft Corporation, + Jean-Marc Valin, Gregory Maxwell, Mark Borgerding, Timothy B. Terriberry, + Logan Stromberg. All rights are reserved by their respective holders. + license: Custom License + customLicenseName: Concentus License + customLicenseContent: | + Copyright (c) by various holding parties, including (but not limited to): + Skype Limited, Xiph.Org Foundation, CSIRO, Microsoft Corporation, + Jean-Marc Valin, Gregory Maxwell, Mark Borgerding, Timothy B. Terriberry, + Logan Stromberg. All rights are reserved by their respective holders.

+ + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met:

+ + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer.

+ + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution.

+ + * Neither the name of Internet Society, IETF or IETF Trust, nor the + names of specific contributors, may be used to endorse or promote + products derived from this software without specific prior written + permission.

+ + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + licenseUrl: https://github.com/lostromb/concentus/blob/master/LICENSE \ No newline at end of file diff --git a/sample/src/main/assets/licenses.html b/sample/src/main/assets/licenses.html index 58f8a0a..a00b3d8 100644 --- a/sample/src/main/assets/licenses.html +++ b/sample/src/main/assets/licenses.html @@ -7979,6 +7979,49 @@

APPENDIX: How to apply the Apache License to your work.

Copyright [yyyy] [name of copyright owner]

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.
+
+

Concentus

+

Copyright © Copyright (c) by various holding parties, including (but not limited to): + Skype Limited, Xiph.Org Foundation, CSIRO, Microsoft Corporation, + Jean-Marc Valin, Gregory Maxwell, Mark Borgerding, Timothy B. Terriberry, + Logan Stromberg. All rights are reserved by their respective holders. + . All rights reserved.

+ +
+

Concentus License

+ Copyright (c) by various holding parties, including (but not limited to): + Skype Limited, Xiph.Org Foundation, CSIRO, Microsoft Corporation, + Jean-Marc Valin, Gregory Maxwell, Mark Borgerding, Timothy B. Terriberry, + Logan Stromberg. All rights are reserved by their respective holders.

+ + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met:

+ + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer.

+ + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution.

+ + * Neither the name of Internet Society, IETF or IETF Trust, nor the + names of specific contributors, may be used to endorse or promote + products derived from this software without specific prior written + permission.

+ + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +
+
From b923ab58ebee5d2e0cc8dafaf2f4ae9222a1e3cb Mon Sep 17 00:00:00 2001 From: Pierce Zaifman Date: Tue, 31 Aug 2021 11:00:53 -0400 Subject: [PATCH 2/5] Fixed the license generating in the wrong directory. Also fixed copyright notice if its more than one line not updating properly. --- .../plugin/license/extension/LibraryInfoExtensions.kt | 6 +++++- .../android/plugin/license/extension/ProjectExtensions.kt | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/plugin/src/main/java/com/cookpad/android/plugin/license/extension/LibraryInfoExtensions.kt b/plugin/src/main/java/com/cookpad/android/plugin/license/extension/LibraryInfoExtensions.kt index 828cb31..e5d5a32 100644 --- a/plugin/src/main/java/com/cookpad/android/plugin/license/extension/LibraryInfoExtensions.kt +++ b/plugin/src/main/java/com/cookpad/android/plugin/license/extension/LibraryInfoExtensions.kt @@ -25,7 +25,11 @@ internal fun LibraryInfo.generateLibraryInfoText(updatedInfo: LibraryInfo? = nul text.append(" name: ${currentName}\n") } if (currentCopyrightHolder != "#COPYRIGHT_HOLDER#" || skip != true) { - text.append(" copyrightHolder: ${currentCopyrightHolder}\n") + if (currentCopyrightHolder.lines().size > 1) { + text.append(" copyrightHolder: |\n ${currentCopyrightHolder.replace("\n", "\n ")}\n") + } else { + text.append(" copyrightHolder: ${currentCopyrightHolder}\n") + } } if (currentLicense != "#LICENSE#" || skip != true) { text.append(" license: ${currentLicense}\n") diff --git a/plugin/src/main/java/com/cookpad/android/plugin/license/extension/ProjectExtensions.kt b/plugin/src/main/java/com/cookpad/android/plugin/license/extension/ProjectExtensions.kt index 20c6f61..6ce5956 100644 --- a/plugin/src/main/java/com/cookpad/android/plugin/license/extension/ProjectExtensions.kt +++ b/plugin/src/main/java/com/cookpad/android/plugin/license/extension/ProjectExtensions.kt @@ -12,7 +12,7 @@ fun Project.toFormattedText(): String { fun Project.writeLicenseHtml(html: String) { val ext = extensions.getByType(LicenseToolsPluginExtension::class.java) - val assetsDir = file("src/main/assets") + val assetsDir = file("app/src/main/assets") assetsDir.mkdirs() logger.info("render $assetsDir/${ext.outputHtml}") file("$assetsDir/${ext.outputHtml}").writeText(html) @@ -20,7 +20,7 @@ fun Project.writeLicenseHtml(html: String) { fun Project.writeLicenseJson(json: String) { val ext = extensions.getByType(LicenseToolsPluginExtension::class.java) - val assetsDir = file("src/main/assets") + val assetsDir = file("app/src/main/assets") assetsDir.mkdirs() logger.info("render $assetsDir/${ext.outputJson}") file("$assetsDir/${ext.outputJson}").writeText(json) From 800b4c1e487e5e6210c7f7a058de5b2f00d12ee2 Mon Sep 17 00:00:00 2001 From: Pierce Zaifman Date: Tue, 31 Aug 2021 11:17:41 -0400 Subject: [PATCH 3/5] Changed to use notice field instead of copyrightHolder when actually including a notice. --- .../plugin/license/extension/LibraryInfoExtensions.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugin/src/main/java/com/cookpad/android/plugin/license/extension/LibraryInfoExtensions.kt b/plugin/src/main/java/com/cookpad/android/plugin/license/extension/LibraryInfoExtensions.kt index e5d5a32..d6793e7 100644 --- a/plugin/src/main/java/com/cookpad/android/plugin/license/extension/LibraryInfoExtensions.kt +++ b/plugin/src/main/java/com/cookpad/android/plugin/license/extension/LibraryInfoExtensions.kt @@ -24,12 +24,14 @@ internal fun LibraryInfo.generateLibraryInfoText(updatedInfo: LibraryInfo? = nul if (currentName != "#NAME#" || skip != true) { text.append(" name: ${currentName}\n") } - if (currentCopyrightHolder != "#COPYRIGHT_HOLDER#" || skip != true) { - if (currentCopyrightHolder.lines().size > 1) { - text.append(" copyrightHolder: |\n ${currentCopyrightHolder.replace("\n", "\n ")}\n") + if (notice != null) { + if (notice.lines().size > 1) { + text.append(" notice: |\n ${notice.replace("\n", "\n ")}\n") } else { - text.append(" copyrightHolder: ${currentCopyrightHolder}\n") + text.append(" notice: ${notice}\n") } + } else if (currentCopyrightHolder != "#COPYRIGHT_HOLDER#" || skip != true) { + text.append(" copyrightHolder: ${currentCopyrightHolder}\n") } if (currentLicense != "#LICENSE#" || skip != true) { text.append(" license: ${currentLicense}\n") From 93fc0d3cbe7d60f8aa70f30ed16d9e3c027447a4 Mon Sep 17 00:00:00 2001 From: Pierce Zaifman Date: Tue, 31 Aug 2021 16:41:33 -0400 Subject: [PATCH 4/5] Removed unnecessary change to generation path. --- .../android/plugin/license/extension/ProjectExtensions.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/main/java/com/cookpad/android/plugin/license/extension/ProjectExtensions.kt b/plugin/src/main/java/com/cookpad/android/plugin/license/extension/ProjectExtensions.kt index 6ce5956..20c6f61 100644 --- a/plugin/src/main/java/com/cookpad/android/plugin/license/extension/ProjectExtensions.kt +++ b/plugin/src/main/java/com/cookpad/android/plugin/license/extension/ProjectExtensions.kt @@ -12,7 +12,7 @@ fun Project.toFormattedText(): String { fun Project.writeLicenseHtml(html: String) { val ext = extensions.getByType(LicenseToolsPluginExtension::class.java) - val assetsDir = file("app/src/main/assets") + val assetsDir = file("src/main/assets") assetsDir.mkdirs() logger.info("render $assetsDir/${ext.outputHtml}") file("$assetsDir/${ext.outputHtml}").writeText(html) @@ -20,7 +20,7 @@ fun Project.writeLicenseHtml(html: String) { fun Project.writeLicenseJson(json: String) { val ext = extensions.getByType(LicenseToolsPluginExtension::class.java) - val assetsDir = file("app/src/main/assets") + val assetsDir = file("src/main/assets") assetsDir.mkdirs() logger.info("render $assetsDir/${ext.outputJson}") file("$assetsDir/${ext.outputJson}").writeText(json) From 60ecba9ec4feb052e2943cda7e4998efc23cc838 Mon Sep 17 00:00:00 2001 From: Pierce Zaifman Date: Tue, 31 Aug 2021 18:02:22 -0400 Subject: [PATCH 5/5] Modified tasks to allow them to be used as part of the gradle build and be cacheable. --- .../plugin/license/task/GenerateLicensePage.kt | 14 ++++++++++---- .../license/task/UpdateMissingLicenses.kt | 18 ++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/plugin/src/main/java/com/cookpad/android/plugin/license/task/GenerateLicensePage.kt b/plugin/src/main/java/com/cookpad/android/plugin/license/task/GenerateLicensePage.kt index 3ef084e..1f084d5 100644 --- a/plugin/src/main/java/com/cookpad/android/plugin/license/task/GenerateLicensePage.kt +++ b/plugin/src/main/java/com/cookpad/android/plugin/license/task/GenerateLicensePage.kt @@ -9,6 +9,7 @@ import com.cookpad.android.plugin.license.data.LibraryInfo import com.cookpad.android.plugin.license.exception.NotEnoughInformationException import com.cookpad.android.plugin.license.extension.writeLicenseHtml import com.cookpad.android.plugin.license.util.YamlUtils +import org.gradle.api.Action import org.gradle.api.GradleException import org.gradle.api.Project import org.gradle.api.Task @@ -16,10 +17,15 @@ import org.gradle.internal.impldep.com.google.common.annotations.VisibleForTesti object GenerateLicensePage { fun register(project: Project): Task { - return project.task("generateLicensePage").doLast { - val ext = project.extensions.getByType(LicenseToolsPluginExtension::class.java) - val yamlInfoList = YamlUtils.loadToLibraryInfo(project.file(ext.licensesYaml)) - project.writeLicenseHtml(yamlInfoList.toHtml(project)) + return project.task("generateLicensePage").doLast(GenerateLicensePageAction()) + } + + // can't use lambdas to define the action if you want to allow this to be used as a cacheable task + class GenerateLicensePageAction : Action { + override fun execute(task: Task) { + val ext = task.project.extensions.getByType(LicenseToolsPluginExtension::class.java) + val yamlInfoList = YamlUtils.loadToLibraryInfo(task.project.file(ext.licensesYaml)) + task.project.writeLicenseHtml(yamlInfoList.toHtml(task.project)) } } diff --git a/plugin/src/main/java/com/cookpad/android/plugin/license/task/UpdateMissingLicenses.kt b/plugin/src/main/java/com/cookpad/android/plugin/license/task/UpdateMissingLicenses.kt index fe95a83..46254b7 100644 --- a/plugin/src/main/java/com/cookpad/android/plugin/license/task/UpdateMissingLicenses.kt +++ b/plugin/src/main/java/com/cookpad/android/plugin/license/task/UpdateMissingLicenses.kt @@ -8,22 +8,28 @@ import com.cookpad.android.plugin.license.data.LibraryInfo import com.cookpad.android.plugin.license.extension.generateLibraryInfoText import com.cookpad.android.plugin.license.extension.notListedIn import com.cookpad.android.plugin.license.util.YamlUtils +import org.gradle.api.Action import org.gradle.api.Project import org.gradle.api.Task import org.gradle.internal.impldep.com.google.common.annotations.VisibleForTesting object UpdateMissingLicenses { fun register(project: Project): Task { - return project.task("updateMissingLicenses").doLast { - val ext = project.extensions.getByType(LicenseToolsPluginExtension::class.java) + return project.task("updateMissingLicenses").doLast(UpdateMissingLicensesAction()) + } + + // can't use lambdas to define the action if you want to allow this to be used as a cacheable task + class UpdateMissingLicensesAction : Action { + override fun execute(task: Task) { + val ext = task.project.extensions.getByType(LicenseToolsPluginExtension::class.java) val resolvedArtifacts = - CheckLicenses.resolveProjectDependencies(project, ext.ignoredProjects) + CheckLicenses.resolveProjectDependencies(task.project, ext.ignoredProjects) val dependencyLicenses = - CheckLicenses.loadDependencyLicenses(project, resolvedArtifacts, ext.ignoredGroups) - updateMissingLicensesYaml(project, ext.licensesYaml, dependencyLicenses) + CheckLicenses.loadDependencyLicenses(task.project, resolvedArtifacts, ext.ignoredGroups) + updateMissingLicensesYaml(task.project, ext.licensesYaml, dependencyLicenses) + } } - @VisibleForTesting internal fun updateMissingLicensesYaml( project: Project,