Permalink
Browse files

Merge branch '2.1.x'

Conflicts:
	grails-core/src/main/groovy/org/codehaus/groovy/grails/plugins/publishing/PluginDescriptorGenerator.groovy
	grails-core/src/main/groovy/org/codehaus/groovy/grails/plugins/publishing/PluginPackager.groovy
  • Loading branch information...
2 parents 9cf942b + 58351ac commit e10b644e56cdeecd380a2920b5ba25be70d764da @graemerocher graemerocher committed Sep 11, 2012
@@ -27,6 +27,7 @@ import org.apache.ivy.plugins.resolver.URLResolver
import org.apache.ivy.plugins.resolver.IBiblioResolver
import org.codehaus.groovy.grails.resolve.GrailsRepoResolver
import org.codehaus.groovy.grails.io.support.Resource
+import org.springframework.util.AntPathMatcher
/**
* Generates the plugin.xml descriptor.
@@ -42,6 +43,7 @@ class PluginDescriptorGenerator {
Resource[] resourceList
List excludes = ["UrlMappings", "DataSource", "BuildConfig", "Config"]
BuildSettings buildSettings
+ AntPathMatcher antPathMatcher = new AntPathMatcher()
PluginDescriptorGenerator(BuildSettings buildSettings, pluginName, List<Resource> resourceList) {
this.buildSettings = buildSettings
@@ -80,6 +82,34 @@ class PluginDescriptorGenerator {
generatePluginXml(pluginProps, xml)
}
+ private boolean matchesPluginExcludes(List<String> pluginExcludes, File commonResourceBase, Resource r) {
+
+ // if we have no excludes or no common resource base, we don't match
+ if (!pluginExcludes) return false
+ if (!commonResourceBase) return false
+
+ if (r.file.absolutePath.indexOf(commonResourceBase.absolutePath) == 0) {
+ String path = r.file.absolutePath.substring(commonResourceBase.absolutePath.length()+1)
+ for(String pattern : pluginExcludes) {
+ if (antPathMatcher.match(pattern, path)) return true
+ }
+
+ }
+
+ return false
+ }
+
+ // this is needed to pass the test as the resources don't really exist
+ private File filterPluginDir(File pluginDir) {
+ if (!pluginDir) return null
+
+ if (pluginDir.absolutePath.endsWith(File.separator + ".")) {
+ return new File(pluginDir.absolutePath.substring(0, pluginDir.absolutePath.lastIndexOf(File.separator)))
+ } else {
+ return pluginDir
+ }
+ }
+
protected void generatePluginXml(pluginProps, MarkupBuilder xml) {
// Write the content!
def props = ['author', 'authorEmail', 'title', 'description', 'documentation', 'type', 'packaging']
@@ -89,6 +119,13 @@ class PluginDescriptorGenerator {
def pluginGrailsVersion = "${GrailsUtil.grailsVersion} > *"
+ // check to see if we have the property, grab it if so
+ def pluginExcludes
+ if (pluginProps['pluginExcludes'])
+ pluginExcludes = pluginProps.pluginExcludes
+ else
+ pluginExcludes = []
+
if (pluginProps != null) {
if (pluginProps["grailsVersion"]) {
pluginGrailsVersion = pluginProps["grailsVersion"]
@@ -99,10 +136,12 @@ class PluginDescriptorGenerator {
if (pluginProps[p]) "${p}"(pluginProps[p])
}
xml.resources {
+ File commonResourceBase = filterPluginDir(pluginProps['pluginDir']?.file)
+
for (r in resourceList) {
def matcher = r.URL.toString() =~ ARTEFACT_PATTERN
def name = matcher[0][1].replaceAll('/', /\./)
- if (!excludes.contains(name)) {
+ if (!excludes.contains(name) && !matchesPluginExcludes(pluginExcludes, commonResourceBase, r)) {
xml.resource(name)
}
}
@@ -23,6 +23,7 @@ import org.codehaus.groovy.grails.plugins.GrailsPluginInfo
import grails.util.BuildSettings
import org.codehaus.groovy.grails.io.support.Resource
import org.codehaus.groovy.grails.io.support.FileSystemResource
+import org.springframework.util.AntPathMatcher
/**
* Packages a plugin in source or binary form.
@@ -68,6 +69,7 @@ class PluginPackager {
private AntBuilder ant
private File resourcesDir
private BuildSettings buildSettings
+ private AntPathMatcher antPathMatcher = new AntPathMatcher()
List<File> jarFiles = []
boolean hasApplicationDependencies
@@ -180,6 +182,59 @@ class PluginPackager {
return pluginZip
}
+ private boolean matchesExcludes(excludes, path) {
+ for(String exclude : excludes) {
+ if (antPathMatcher.match(exclude, path)) {
+ return true
+ }
+ }
+
+ return false
+ }
+
+ private void extraExcludesProcessDirectory(File dir, int stripLength, int fullStripLength, excludes, List<String> ejectedFiles) {
+ dir.listFiles().each { File f ->
+ if (f.isFile()) {
+ if (matchesExcludes(excludes, f.absolutePath.substring(stripLength+1))) {
+ ejectedFiles << f.absolutePath.substring(fullStripLength+1)
+ }
+ } else if (f.isDirectory() && !f.name.startsWith(".")) {
+ extraExcludesProcessDirectory(f, stripLength, fullStripLength, excludes, ejectedFiles)
+ }
+ }
+ }
+
+ /**
+ * We have to go through and build up a list of exclusions because the plugin excludes are based from to "basedir" and all of the excludes
+ * when copying are based from the directory we are copying from (e.g. APP/web-app will not match web-app/** because the exclude doesn't include
+ * web-app when determining that pattern). This makes all plugin excludes worthless when copy files unless we go through and manually match them
+ * ourselves and return a list of specifically excluded files.
+ *
+ * @param basedir - the Grails Applications base directory
+ * @param subdir - the sub directory we are copying from so we can prefix this for our pattern matching
+ * @param excludes - the excludes from pluginExcludes
+ * @param base - the ones that the Ant copy wants to include no matter what (originally included as specific exclude: lines)
+ * @return returns a list of files to exclude relative to basedir/subdir
+ */
+ private List<String> extraExcludes(File basedir, String subdir, excludes, List<String> base = []) {
+ if (!excludes) return base
+
+ List<String> ejectedFiles = []
+
+ File dir = new File(basedir, subdir)
+
+ if (dir.exists()) {
+ int stripLength = basedir.absolutePath.size() // e.g. [/blah/blah/]web-dir/ - preserve web-dir so we can match it
+ int fullStripLength = stripLength + 1 + subdir.size() // e.g. /blah/blah/[web-dir/]
+
+ extraExcludesProcessDirectory(dir, stripLength, fullStripLength, excludes, ejectedFiles)
+ }
+
+ ejectedFiles.addAll(base)
+
+ return ejectedFiles
+ }
+
String packageBinary(String pluginName, File classesDir, File targetDir) {
def pluginProps = pluginInfo
ant.taskdef (name: 'gspc', classname : 'org.codehaus.groovy.grails.web.pages.GroovyPageCompilerTask')
@@ -219,30 +274,45 @@ class PluginPackager {
mkdir(dir:"${metaInf}/grails-app/i18n")
if (new File("${resourcesDir}/grails-app/i18n").exists()) {
copy(todir:"${metaInf}/grails-app/i18n", includeEmptyDirs:false,failonerror:false) {
- fileset(dir:"${resourcesDir}/grails-app/i18n")
+ fileset(dir:"${resourcesDir}/grails-app/i18n") {
+ extraExcludes(basedir, "grails-app/i18n", pluginProps?.pluginExcludes).each {
+ exclude name: it
+ }
+ }
}
}
+
+ // the excludes get more difficult now, as they are from the root of the project and these
+ // excludes would be from the fileset's dir
+
mkdir(dir:"${metaInf}/static")
copy(todir:"${metaInf}/static", includeEmptyDirs:false, failonerror:false) {
fileset(dir:"${basedir}/web-app") {
- exclude name:"plugins/**"
- exclude name:"**/WEB-INF/**"
- exclude name:"**/META-INF/**"
- exclude name:"**/*.gsp"
- exclude name:"**/*.jsp"
+ extraExcludes(basedir, "web-app",
+ pluginProps?.pluginExcludes, ["plugins/**", "**/WEB-INF/**", "**/META-INF/**",
+ "**/*.gsp", "**/*.jsp"]).each {
+ exclude name: it
+ }
+
}
}
mkdir(dir:"${metaInf}/scripts")
copy(todir:"${metaInf}/scripts") {
- fileset(dir:"${basedir}/scripts",
- excludes:"_Install.groovy,_Uninstall.groovy,_Upgrade.groovy")
+ fileset(dir:"${basedir}/scripts") {
+ extraExcludes(basedir, "scripts", pluginProps?.pluginExcludes, ["_Install.groovy","_Uninstall.groovy","_Upgrade.groovy"]).each {
+ exclude name: it
+ }
+ }
}
mkdir(dir:"${classesDir}/src")
copy(todir:"${classesDir}/src") {
- fileset(dir:"${basedir}/src", excludes:"groovy/**,java/**")
+ fileset(dir:"${basedir}/src") {
+ extraExcludes(basedir, "src", pluginProps?.pluginExcludes, ["groovy/**","java/**"]).each {
+ exclude name: it
+ }
+ }
}
-
jar(destfile:destinationFile) {
fileset(dir:classesDir, excludes:excludeList.join(','))
manifest {
@@ -27,6 +27,46 @@ class PluginDescriptorGeneratorSpec extends Specification {
xml.resources.resource[1].text() == 'bar.BarController'
}
+ def "Test plugin excludes causes no problems when no resources"() {
+ given:
+ def generator = new PluginDescriptorGenerator(new BuildSettings(),"foo", [])
+ when:
+ def sw = new StringWriter()
+ generator.generatePluginXml([version:1.0, dependsOn:[core:1.0], author:"Bob", pluginDir: new FileSystemResource(new File(".")), pluginExcludes: ["**/test/**"]], sw)
+ def xml = new XmlSlurper().parseText(sw.toString())
+ then:
+ xml.@name == 'foo'
+ xml.@version == '1.0'
+ xml.author.text() == 'Bob'
+ xml.runtimePluginRequirements.plugin[0].@name == 'core'
+ xml.runtimePluginRequirements.plugin[0].@version == '1.0'
+ xml.resources.resource.size() == 0
+ }
+
+ def "Test plugin/excludes is honoured for resources"() {
+ given:
+ def generator = new PluginDescriptorGenerator(new BuildSettings(),"foo", [
+ new FileSystemResource(new File("grails-app/controllers/FooController.groovy")),
+ new FileSystemResource(new File("grails-app/controllers/test/BarController.groovy")),
+ new FileSystemResource(new File("grails-app/services/test/MyService.groovy")),
+ new FileSystemResource(new File("grails-app/services/MyService2.groovy"))
+ ])
+ when:
+ def sw = new StringWriter()
+ generator.generatePluginXml([version:1.0, dependsOn:[core:1.0], author:"Bob", pluginDir: new FileSystemResource(new File(".")), pluginExcludes: ["**/test/**"]], sw)
+ def xml = new XmlSlurper().parseText(sw.toString())
+ then:
+ xml.@name == 'foo'
+ xml.@version == '1.0'
+ xml.author.text() == 'Bob'
+ xml.runtimePluginRequirements.plugin[0].@name == 'core'
+ xml.runtimePluginRequirements.plugin[0].@version == '1.0'
+ xml.resources.resource.size() == 2
+ xml.resources.resource[0].text() == 'FooController'
+ xml.resources.resource[1].text() == 'MyService2'
+
+ }
+
void "Test that dependencies and repositories are correctly populated from BuildSettings"() {
given:"A plugin descriptor generator with a BuildSettings instance that defines repositories and dependencies"
PluginDescriptorGenerator generator = systemUnderTest()

0 comments on commit e10b644

Please sign in to comment.