Skip to content

Commit 19f6d63

Browse files
committed
Check to verify that "copied files" are mentioned in LICENSE
To ensure that files that are known to be mentioned in `LICENSE` are really mentioned in that file, the Gradle plugin introduced in this change verifies this. The "magic word" `CODE_COPIED_TO_POLARIS` must be present in such files. The presence of the "magic word" triggers a validation that the path of the containing file, relative to the project root directory, must be mentioned in `LICENSE`, prefixed with `* `. The plugin checks all source directories in projects that have any Java plugin applied. For other projects, the plugin's extension provides a mechanism to add directory sets similar to how `SourceDirectorySet` works, which is used for the root project. The plugin must be applied on the root project, it adds itself to all other projects. The introduced `checkForCopiedCode` task is added to the `check` task as a dependency. Files that contain "copied code" need to have the word `CODE_COPIED_TO_POLARIS` anywhere. Related to apache#903
1 parent 23385a0 commit 19f6d63

File tree

5 files changed

+458
-0
lines changed

5 files changed

+458
-0
lines changed

aggregated-license-report/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,5 @@ val aggregatedLicenseReportsZip by
6060
destinationDirectory.set(layout.buildDirectory.dir("distributions"))
6161
archiveExtension.set("zip")
6262
}
63+
64+
tasks.register("check")
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package copiedcode
21+
22+
import org.gradle.api.Project
23+
import org.gradle.api.file.RegularFileProperty
24+
import org.gradle.api.file.SourceDirectorySet
25+
import org.gradle.api.provider.Property
26+
import org.gradle.api.provider.SetProperty
27+
28+
abstract class CopiedCodeCheckerExtension(private val project: Project) {
29+
/**
30+
* Per-project set of additional directories to scan.
31+
*
32+
* This property is _not_ propagated to subprojects.
33+
*/
34+
val scanDirectories =
35+
project.objects.domainObjectContainer(
36+
SourceDirectorySet::class.java,
37+
{ name -> project.objects.sourceDirectorySet(name, name) },
38+
)
39+
40+
/**
41+
* By default, this plugin scans all files. The content types that match the regular expression of
42+
* this property are excluded, unless a content-type matches one of the regular expressions in
43+
* [CopiedCodeCheckerExtension.includedContentTypePatterns].
44+
*
45+
* See [CopiedCodeCheckerExtension.addDefaultContentTypes],
46+
* [CopiedCodeCheckerExtension.includedContentTypePatterns],
47+
* [CopiedCodeCheckerExtension.includeUnrecognizedContentType],
48+
* [CopiedCodeCheckerExtension.includedContentTypePatterns].
49+
*/
50+
abstract val excludedContentTypePatterns: SetProperty<String>
51+
/**
52+
* By default, this plugin scans all files. The content types that match the regular expression of
53+
* the [copiedcode.CopiedCodeCheckerExtension.excludedContentTypePatterns] property are excluded,
54+
* unless a content-type matches one of the regular expressions in this property.
55+
*
56+
* See [CopiedCodeCheckerExtension.addDefaultContentTypes],
57+
* [CopiedCodeCheckerExtension.excludedContentTypePatterns],
58+
* [CopiedCodeCheckerExtension.includeUnrecognizedContentType],
59+
* [CopiedCodeCheckerExtension.includedContentTypePatterns].
60+
*/
61+
abstract val includedContentTypePatterns: SetProperty<String>
62+
63+
/**
64+
* If a content-type could not be detected, this property, which defaults to `true`, is consulted.
65+
*
66+
* See [CopiedCodeCheckerPlugin] for details.
67+
*/
68+
abstract val includeUnrecognizedContentType: Property<Boolean>
69+
70+
/**
71+
* The magic "word", if present in a file, meaning "this file has been copied".
72+
*
73+
* A file is considered as "copied" must contain this magic word. "Word" means that the value must
74+
* be surrounded by regular expression word boundaries (`\b`).
75+
*/
76+
abstract val magicWord: Property<String>
77+
78+
/**
79+
* License file to check, configured on the root project. See [CopiedCodeCheckerPlugin] for
80+
* details.
81+
*/
82+
abstract val licenseFile: RegularFileProperty
83+
84+
/** Recommended to use, adds known and used binary content types. */
85+
fun addDefaultContentTypes(): CopiedCodeCheckerExtension {
86+
// Exclude all images
87+
excludedContentTypePatterns.add("image/.*")
88+
// But include images built in XML (e.g. image/svg+xml)
89+
includedContentTypePatterns.add("\\+xml")
90+
91+
return this
92+
}
93+
94+
init {
95+
includeUnrecognizedContentType.convention(true)
96+
magicWord.convention(DEFAULT_MAGIC_WORD)
97+
}
98+
99+
companion object {
100+
// String manipulation is intentional - otherwise this source file would be considered as
101+
// "copied".
102+
val DEFAULT_MAGIC_WORD = "_CODE_COPIED_TO_POLARIS".substring(1)
103+
}
104+
}

0 commit comments

Comments
 (0)