Skip to content

Commit 4413cfb

Browse files
rvowlesgraemerocher
authored andcommitted
GRAILS-3577 - adds honoring the pluginexcludes for resources
1 parent 46cdc5c commit 4413cfb

File tree

2 files changed

+99
-1
lines changed

2 files changed

+99
-1
lines changed

grails-core/src/main/groovy/org/codehaus/groovy/grails/plugins/publishing/PluginDescriptorGenerator.groovy

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import org.apache.ivy.core.module.descriptor.DependencyDescriptor
2727
import org.apache.ivy.plugins.resolver.URLResolver
2828
import org.apache.ivy.plugins.resolver.IBiblioResolver
2929
import org.codehaus.groovy.grails.resolve.GrailsRepoResolver
30+
import org.springframework.util.AntPathMatcher
3031

3132
/**
3233
* Generates the plugin.xml descriptor.
@@ -42,6 +43,7 @@ class PluginDescriptorGenerator {
4243
Resource[] resourceList
4344
List excludes = ["UrlMappings", "DataSource", "BuildConfig", "Config"]
4445
BuildSettings buildSettings
46+
AntPathMatcher antPathMatcher = new AntPathMatcher()
4547

4648
PluginDescriptorGenerator(BuildSettings buildSettings, pluginName, List<Resource> resourceList) {
4749
this.buildSettings = buildSettings
@@ -80,6 +82,53 @@ class PluginDescriptorGenerator {
8082
generatePluginXml(pluginProps, xml)
8183
}
8284

85+
/* the pluginExcludes are Ant matched from the base of the application, but since the
86+
pluginProps is not necessarily a class and we don't actually know where it is, we need
87+
to go through the resources figuring out what the common resource base is. We are going to assume
88+
a common Grails application layout to fudge this.
89+
*/
90+
private String resourceBaseMatchDirs = ['grails-app', 'web-app', 'scripts', 'test', 'src']
91+
private File findCommonResourceBase() {
92+
if (!resourceList) return null // no resources, won't loop
93+
94+
for (Resource r in resourceList) {
95+
File f = r.file
96+
97+
while (f != null && !resourceBaseMatchDirs.contains(f.name)) {
98+
f = f.parentFile
99+
}
100+
101+
if (f) {
102+
if (f.parentFile == null) { // wonderful, thanks Resource
103+
return new File(f.absolutePath.substring(0, f.absolutePath.lastIndexOf(File.separator)))
104+
} else {
105+
return f.parentFile
106+
}
107+
}
108+
}
109+
110+
GrailsUtil.warn("Unable to determine common resource base when generating plugin.xml")
111+
112+
return null
113+
}
114+
115+
private boolean matchesPluginExcludes(List<String> pluginExcludes, File commonResourceBase, Resource r) {
116+
117+
// if we have no excludes or no common resource base, we don't match
118+
if (!pluginExcludes) return false
119+
if (!commonResourceBase) return false
120+
121+
if (r.file.absolutePath.indexOf(commonResourceBase.absolutePath) == 0) {
122+
String path = r.file.absolutePath.substring(commonResourceBase.absolutePath.length()+1)
123+
for(String pattern : pluginExcludes) {
124+
if (antPathMatcher.match(pattern, path)) return true
125+
}
126+
127+
}
128+
129+
return false
130+
}
131+
83132
protected void generatePluginXml(pluginProps, MarkupBuilder xml) {
84133
// Write the content!
85134
def props = ['author', 'authorEmail', 'title', 'description', 'documentation', 'type', 'packaging']
@@ -89,6 +138,13 @@ class PluginDescriptorGenerator {
89138

90139
def pluginGrailsVersion = "${GrailsUtil.grailsVersion} > *"
91140

141+
// check to see if we have the property, grab it if so
142+
def pluginExcludes
143+
if (pluginProps['pluginExcludes'])
144+
pluginExcludes = pluginProps.pluginExcludes
145+
else
146+
pluginExcludes = []
147+
92148
if (pluginProps != null) {
93149
if (pluginProps["grailsVersion"]) {
94150
pluginGrailsVersion = pluginProps["grailsVersion"]
@@ -99,10 +155,12 @@ class PluginDescriptorGenerator {
99155
if (pluginProps[p]) "${p}"(pluginProps[p])
100156
}
101157
xml.resources {
158+
File commonResourceBase = findCommonResourceBase()
159+
102160
for (r in resourceList) {
103161
def matcher = r.URL.toString() =~ ARTEFACT_PATTERN
104162
def name = matcher[0][1].replaceAll('/', /\./)
105-
if (!excludes.contains(name)) {
163+
if (!excludes.contains(name) && !matchesPluginExcludes(pluginExcludes, commonResourceBase, r)) {
106164
xml.resource(name)
107165
}
108166
}

grails-core/src/test/groovy/org/codehaus/groovy/grails/plugins/publishing/PluginDescriptorGeneratorSpec.groovy

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,46 @@ class PluginDescriptorGeneratorSpec extends Specification {
2727
xml.resources.resource[1].text() == 'bar.BarController'
2828
}
2929

30+
def "Test plugin excludes causes no problems when no resources"() {
31+
given:
32+
def generator = new PluginDescriptorGenerator(new BuildSettings(),"foo", [])
33+
when:
34+
def sw = new StringWriter()
35+
generator.generatePluginXml([version:1.0, dependsOn:[core:1.0], author:"Bob", pluginExcludes: ["**/test/**"]], sw)
36+
def xml = new XmlSlurper().parseText(sw.toString())
37+
then:
38+
xml.@name == 'foo'
39+
xml.@version == '1.0'
40+
xml.author.text() == 'Bob'
41+
xml.runtimePluginRequirements.plugin[0].@name == 'core'
42+
xml.runtimePluginRequirements.plugin[0].@version == '1.0'
43+
xml.resources.resource.size() == 0
44+
}
45+
46+
def "Test plugin/excludes is honoured for resources"() {
47+
given:
48+
def generator = new PluginDescriptorGenerator(new BuildSettings(),"foo", [
49+
new FileSystemResource(new File("grails-app/controllers/FooController.groovy")),
50+
new FileSystemResource(new File("grails-app/controllers/test/BarController.groovy")),
51+
new FileSystemResource(new File("grails-app/services/test/MyService.groovy")),
52+
new FileSystemResource(new File("grails-app/services/MyService2.groovy"))
53+
])
54+
when:
55+
def sw = new StringWriter()
56+
generator.generatePluginXml([version:1.0, dependsOn:[core:1.0], author:"Bob", pluginExcludes: ["**/test/**"]], sw)
57+
def xml = new XmlSlurper().parseText(sw.toString())
58+
then:
59+
xml.@name == 'foo'
60+
xml.@version == '1.0'
61+
xml.author.text() == 'Bob'
62+
xml.runtimePluginRequirements.plugin[0].@name == 'core'
63+
xml.runtimePluginRequirements.plugin[0].@version == '1.0'
64+
xml.resources.resource.size() == 2
65+
xml.resources.resource[0].text() == 'FooController'
66+
xml.resources.resource[1].text() == 'MyService2'
67+
68+
}
69+
3070
void "Test that dependencies and repositories are correctly populated from BuildSettings"() {
3171
given:"A plugin descriptor generator with a BuildSettings instance that defines repositories and dependencies"
3272
PluginDescriptorGenerator generator = systemUnderTest()

0 commit comments

Comments
 (0)