17
17
18
18
import groovy.xml.NamespaceBuilder
19
19
20
+ // Configure rat dependencies for use in the custom task.
20
21
configure(rootProject) {
21
22
configurations {
22
23
ratDeps
@@ -27,111 +28,164 @@ configure(rootProject) {
27
28
}
28
29
}
29
30
31
+ // Configure the rat validation task and all scanned directories.
30
32
allprojects {
31
33
task(" rat" , type : RatTask ) {
32
34
group = ' Verification'
33
35
description = ' Runs Apache Rat checks.'
34
- }
35
- }
36
36
37
- configure(rootProject) {
38
- rat {
39
- includes + = [
40
- " buildSrc/**/*.java" ,
41
- " gradle/**/*.gradle" ,
42
- " lucene/tools/forbiddenApis/**" ,
43
- " lucene/tools/prettify/**" ,
44
- ]
45
- excludes + = [
46
- // Unclear if this needs ASF header, depends on how much was copied from ElasticSearch
47
- " **/ErrorReportingTestListener.java"
48
- ]
49
- }
50
- }
37
+ def defaultScanFileTree = project. fileTree(projectDir, {
38
+ // Don't check under the project's build folder.
39
+ exclude project. buildDir. name
51
40
52
- configure(project(" :solr:core" )) {
53
- rat {
54
- srcExcludes + = [
55
- " **/htmlStripReaderTest.html"
56
- ]
57
- }
58
- }
41
+ // Exclude any generated stuff.
42
+ exclude " src/generated"
43
+
44
+ // Don't check any of the subprojects - they have their own rat tasks.
45
+ exclude subprojects. collect { it. projectDir. name }
46
+
47
+ // At the module scope we only check selected file patterns as folks have various .gitignore-d resources
48
+ // generated by IDEs, etc.
49
+ include " **/*.gradle"
50
+ include " **/*.xml"
51
+ include " **/*.md"
52
+ include " **/*.py"
53
+ include " **/*.sh"
54
+ include " **/*.bat"
55
+
56
+ // Include selected patterns from any source folders. We could make this
57
+ // relative to source sets but it seems to be of little value - all our source sets
58
+ // live under 'src' anyway.
59
+ include " src/**"
60
+ exclude " src/**/*.png"
61
+ exclude " src/**/*.txt"
62
+ exclude " src/**/*.zip"
63
+ exclude " src/**/*.properties"
64
+ exclude " src/**/*.utf8"
65
+ exclude " src/**/*.svg"
66
+ exclude " src/**/*.csv"
67
+
68
+ // TODO: SOLR-15601: Some of these should carry the license, perhaps?
69
+ exclude " **/README.md"
70
+ exclude " **/*.html"
71
+ exclude " **/*.xml"
72
+ exclude " **/*.json"
73
+ exclude " **/*.js"
74
+ exclude " **/*.py"
75
+
76
+ // Conditionally apply module-specific patterns. We do it here instead
77
+ // of reconfiguring each project because the provider can be made lazy
78
+ // and it's easier to manage this way.
79
+ switch (project. path) {
80
+ case " :" :
81
+ include " gradlew"
82
+ include " gradlew.bat"
83
+ exclude " .gradle"
84
+ exclude " .idea"
85
+ exclude " .muse"
86
+ exclude " .git"
87
+
88
+ // Exclude github stuff (templates, workflows).
89
+ exclude " .github"
90
+
91
+ exclude " dev-tools/scripts/cloud.sh"
92
+ exclude " dev-tools/scripts/README.md"
93
+ exclude " dev-tools/scripts/create_line_file_docs.py"
59
94
60
- configure(project(" :solr:webapp" )) {
61
- rat {
62
- includes = [" **" ]
63
- excludes + = [
64
- " web/img/**" ,
65
- " *.iml" ,
66
- " build.gradle" ,
67
- " build/**" ,
68
- ]
95
+ // The root project also includes patterns for the boostrap (buildSrc) and composite
96
+ // projects. Include their sources in the scan.
97
+ include " buildSrc/src/**"
98
+ include " dev-tools/missing-doclet/src/**"
99
+ break
100
+
101
+ case " :solr:contrib:clustering" :
102
+ exclude " src/test-files/META-INF/services/*"
103
+ break
104
+
105
+ case " :solr:contrib:langid" :
106
+ exclude " **/langdetect-profiles/*"
107
+ break
108
+
109
+ case " :solr:documentation" :
110
+ exclude " src/markdown/*.md"
111
+ break
112
+
113
+ case " :solr:core" :
114
+ exclude " **/htmlStripReaderTest.html"
115
+ exclude " src/resources/*.json"
116
+ exclude " src/resources/*.xml"
117
+ exclude " src/test-files/**/*.csv"
118
+ exclude " src/test-files/**/*.json"
119
+ exclude " src/test-files/**/*.aff"
120
+ exclude " src/test-files/**/*.dic"
121
+ exclude " src/test-files/**/*.conf"
122
+ exclude " src/test-files/**/external_eff"
123
+ exclude " src/test-files/**/*.incl"
124
+ break
125
+
126
+ case " :solr:server" :
127
+ exclude " **/*.xml"
128
+ exclude " **/*.sh"
129
+ exclude " **/*.bat"
130
+ break
131
+
132
+ case " :solr:webapp" :
133
+ exclude " web/img/**"
134
+ break
135
+
136
+ case " :solr:solr-ref-guide" :
137
+ exclude " src/**"
138
+ break
139
+
140
+ case " :solr:docker" :
141
+ exclude " tests/**/*.xml"
142
+ break
143
+
144
+ case " :solr:example" :
145
+ exclude " **/*.xml"
146
+ exclude " films/README.md"
147
+ break
148
+
149
+ case " :solr:solrj" :
150
+ exclude " src/**/*.json"
151
+ exclude " src/test-files/**/*.cfg"
152
+ exclude " src/test-files/**/*.xml"
153
+ break
154
+ }
155
+ })
156
+ inputFileTrees. add(defaultScanFileTree)
69
157
}
70
158
}
71
159
72
- // Structure inspired by existing task from Apache Kafka, heavily modified since then.
160
+ /**
161
+ * An Apache RAT adapter that validates whether files contain acceptable licenses.
162
+ */
73
163
class RatTask extends DefaultTask {
74
- @Input
75
- List<String > includes = [
76
- " *.gradle" ,
77
- " *.xml" ,
78
- " src/tools/**"
79
- ]
80
-
81
- @Input
82
- List<String > excludes = []
83
-
84
- @Input
85
- List<String > srcExcludes = [
86
- " **/TODO" ,
87
- " **/*.txt" ,
88
- " **/*.md" ,
89
- " **/*.iml" ,
90
- " build/**"
91
- ]
164
+ @InputFiles
165
+ final ListProperty<ConfigurableFileTree > inputFileTrees = project. objects. listProperty(ConfigurableFileTree )
92
166
93
167
@OutputFile
94
- def xmlReport = new File (new File (project. buildDir, ' rat' ), ' rat-report.xml' )
168
+ final RegularFileProperty xmlReport = project. objects. fileProperty(). convention(
169
+ project. layout. buildDirectory. file(" rat/rat-report.xml" ))
95
170
96
- def generateXmlReport ( ) {
97
- def uri = ' antlib:org.apache. rat.anttasks '
171
+ def generateReport ( File reportFile ) {
172
+ // Set up ant rat task.
98
173
def ratClasspath = project. rootProject. configurations. ratDeps. asPath
99
- ant. taskdef(resource : ' org/apache/rat/anttasks/antlib.xml' , uri : uri, classpath : ratClasspath)
174
+ ant. taskdef(resource : ' org/apache/rat/anttasks/antlib.xml' , classpath : ratClasspath)
100
175
101
- def rat = NamespaceBuilder . newInstance(ant, uri)
102
- rat. report(format : ' xml' , reportFile : xmlReport, addDefaultLicenseMatchers : true ) {
103
- ant. fileset(dir : " ${ project.projectDir} " ) {
104
- includes. each { pattern -> ant. include(name : pattern) }
105
- excludes. each { pattern -> ant. exclude(name : pattern) }
106
- }
176
+ // Collect all output files for debugging.
177
+ String inputFileList = inputFileTrees. get(). collectMany { fileTree ->
178
+ fileTree. asList()
179
+ }. sort(). join(" \n " )
180
+ project. file(reportFile. path. replaceAll(' .xml$' , ' -filelist.txt' )). setText(inputFileList, " UTF-8" )
107
181
108
- if (project. plugins. findPlugin(JavaPlugin )) {
109
- def checkSets = [
110
- project. sourceSets. main. java. srcDirs,
111
- project. sourceSets. test. java. srcDirs,
112
- ]
113
-
114
- project. sourceSets. matching { it. name == ' tools' }. all {
115
- checkSets + = project. sourceSets. tools. java. srcDirs
116
- }
117
-
118
- checkSets. flatten(). each { srcLocation ->
119
- ant. fileset(dir : srcLocation, erroronmissingdir : false ) {
120
- srcExcludes. each { pattern -> ant. exclude(name : pattern) }
121
- }
122
- }
123
-
124
- [
125
- project. sourceSets. main. resources. srcDirs
126
- ]. flatten(). each { srcLocation ->
127
- ant. fileset(dir : srcLocation, erroronmissingdir : false ) {
128
- ant. include(name : " META-INF/**" )
129
- }
130
- }
182
+ // Run rat via ant.
183
+ ant. report(format : ' xml' , reportFile : reportFile, addDefaultLicenseMatchers : true ) {
184
+ // Pass all gradle file trees to the ant task (Gradle's internal adapters are used).
185
+ inputFileTrees. get(). each { fileTree ->
186
+ fileTree. addToAntBuilder(ant, ' resources' , FileCollection.AntType.ResourceCollection )
131
187
}
132
188
133
- // The license rules below were manually copied from lucene/common-build.xml, there is currently no mechanism to sync them
134
-
135
189
// BSD 4-clause stuff (is disallowed below)
136
190
substringMatcher(licenseFamilyCategory : " BSD4 " , licenseFamilyName : " Original BSD License (with advertising clause)" ) {
137
191
pattern(substring : " All advertising materials" )
@@ -160,7 +214,7 @@ class RatTask extends DefaultTask {
160
214
// ICU license
161
215
pattern(substring : " Permission is hereby granted, free of charge, to any person obtaining a copy" )
162
216
// ui-grid
163
- pattern(substring : " ; License: MIT" )
217
+ pattern(substring : " ; License: MIT" )
164
218
}
165
219
166
220
// Apache
@@ -186,8 +240,8 @@ class RatTask extends DefaultTask {
186
240
}
187
241
}
188
242
189
- def printUnknownFiles () {
190
- def ratXml = new XmlParser (). parse(xmlReport )
243
+ def printUnknownFiles (File reportFile ) {
244
+ def ratXml = new XmlParser (). parse(reportFile )
191
245
def errors = []
192
246
ratXml. resource. each { resource ->
193
247
if (resource. ' license-approval' . @name[0 ] == " false" ) {
@@ -201,14 +255,15 @@ class RatTask extends DefaultTask {
201
255
}
202
256
203
257
@TaskAction
204
- def rat () {
258
+ def execute () {
205
259
def origEncoding = System . getProperty(" file.encoding" )
206
260
try {
207
- generateXmlReport()
208
- printUnknownFiles()
261
+ File reportFile = xmlReport. get(). asFile
262
+ generateReport(reportFile)
263
+ printUnknownFiles(reportFile)
209
264
} finally {
210
265
if (System . getProperty(" file.encoding" ) != origEncoding) {
211
- throw new GradleException (" Insane: rat changed file.encoding to ${ System.getProperty('file.encoding')} ?" )
266
+ throw new GradleException (" Something is wrong: Apache RAT changed file.encoding to ${ System.getProperty('file.encoding')} ?" )
212
267
}
213
268
}
214
269
}
0 commit comments