Skip to content

Commit a3bc738

Browse files
author
graeme
committed
Implemented grails release-plugin command that does all the SVN import, commit, tagging magic to make publishing plug-ins easier
git-svn-id: https://svn.codehaus.org/grails/trunk@4533 1cfb16fd-6d17-0410-8ff1-b7e8e1e2867d
1 parent 898acbc commit a3bc738

File tree

4 files changed

+227
-5
lines changed

4 files changed

+227
-5
lines changed

lib/svnkit.jar

1.14 MB
Binary file not shown.

scripts/Init.groovy

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,12 @@ getGrailsJar = { args ->
188188
result
189189
}
190190

191-
args = System.getProperty("grails.cli.args")
191+
args = System.getProperty("grails.cli.args")
192+
193+
confirmInput = { String message ->
194+
Ant.input(message: message, addproperty:"confirm.message",validargs:"y,n")
195+
Ant.antProject.properties."confirm.message"
196+
}
192197

193198
task ( createStructure: "Creates the application directory structure") {
194199
Ant.sequential {

scripts/PackagePlugin.groovy

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,6 @@ task(packagePlugin:"Implementation task") {
7878

7979
def gcl = new GroovyClassLoader(cl,compConfig,true)
8080

81-
Class pluginClass
82-
def plugin
8381
try {
8482
pluginClass = gcl.parseClass(pluginFile)
8583
plugin = pluginClass.newInstance()
@@ -89,7 +87,7 @@ task(packagePlugin:"Implementation task") {
8987
t.printStackTrace(System.out)
9088
Ant.fail("Cannot instantiate plugin file")
9189
}
92-
def pluginName = GCU.getScriptName(GCU.getLogicalName(pluginClass, "GrailsPlugin"))
90+
pluginName = GCU.getScriptName(GCU.getLogicalName(pluginClass, "GrailsPlugin"))
9391

9492
// Generate plugin.xml descriptor from info in *GrailsPlugin.groovy
9593
new File("${basedir}/plugin.xml").delete()
@@ -103,7 +101,7 @@ task(packagePlugin:"Implementation task") {
103101
}
104102

105103
// Package plugin's zip distribution
106-
def pluginZip = "${basedir}/grails-${pluginName}-${plugin.version}.zip"
104+
pluginZip = "${basedir}/grails-${pluginName}-${plugin.version}.zip"
107105
Ant.delete(file:pluginZip)
108106
def includesList = pluginIncludes.join(",")
109107
def excludesList = pluginExcludes.join(",")

scripts/ReleasePlugin.groovy

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
import org.codehaus.groovy.grails.commons.GrailsClassUtils as GCU
2+
import org.tmatesoft.svn.core.io.SVNRepositoryFactory
3+
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory
4+
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;
5+
import org.tmatesoft.svn.core.io.*
6+
import org.tmatesoft.svn.core.*
7+
import org.tmatesoft.svn.core.auth.*
8+
import org.tmatesoft.svn.core.wc.*
9+
import org.tmatesoft.svn.core.io.diff.SVNDeltaGenerator;
10+
11+
grailsHome = Ant.project.properties."environment.GRAILS_HOME"
12+
13+
includeTargets << new File ( "${grailsHome}/scripts/Init.groovy" )
14+
includeTargets << new File ( "${grailsHome}/scripts/PackagePlugin.groovy" )
15+
16+
pluginSVN = "https://svn.codehaus.org/grails-plugins"
17+
//pluginSVN = "file:///Developer/localsvn"
18+
authManager = null
19+
message = null
20+
trunk = null
21+
latestRelease = null
22+
versionedRelease = null
23+
24+
task ('default': "A task for plug-in developers that uploads and commits the current plug-in as the latest revision. The command will prompt for your SVN login details.") {
25+
releasePlugin()
26+
}
27+
28+
task(processAuth:"Prompts user for login details to create authentication manager") {
29+
if(!authManager) {
30+
Ant.input(message:"Please enter your SVN username:", addproperty:"user.svn.username")
31+
Ant.input(message:"Please enter your SVN password:", addproperty:"user.svn.password")
32+
33+
def username = Ant.antProject.properties."user.svn.username"
34+
def password = Ant.antProject.properties."user.svn.password"
35+
36+
authManager = SVNWCUtil.createDefaultAuthenticationManager( username , password )
37+
}
38+
}
39+
task(releasePlugin: "The implementation task") {
40+
depends(packagePlugin, processAuth)
41+
42+
remoteLocation = "${pluginSVN}/grails-${pluginName}"
43+
trunk = SVNURL.parseURIDecoded("${remoteLocation}/trunk")
44+
latestRelease = "${remoteLocation}/tags/LATEST_RELEASE"
45+
versionedRelease = "${remoteLocation}/tags/RELEASE_${plugin.version.toString().replaceAll('\\.','_')}"
46+
47+
48+
FSRepositoryFactory.setup();
49+
DAVRepositoryFactory.setup()
50+
51+
try {
52+
def statusClient = new SVNStatusClient((ISVNAuthenticationManager)authManager,null)
53+
54+
boolean imported = false
55+
try {
56+
// get status of base directory, if this fails exception will be thrown
57+
def status = statusClient.doStatus(baseFile, true)
58+
}
59+
catch(SVNException ex) {
60+
61+
// error with status, not in repo, attempt import..
62+
importToSVN()
63+
imported = true
64+
}
65+
if(!imported) {
66+
updateAndCommitLatest()
67+
tagPluginRelease()
68+
event('StatusFinal', ["Plug-in release successfully published"])
69+
}
70+
}
71+
catch(Exception e) {
72+
event('StatusFinal', ["Error occurred with release-plugin: ${e.message}"])
73+
e.printStackTrace()
74+
}
75+
}
76+
77+
task(checkInPluginZip:"Checks in the plug-in zip if it has not been checked in already") {
78+
def statusClient = new SVNStatusClient((ISVNAuthenticationManager)authManager,null)
79+
try {
80+
statusClient.doStatus(pluginZip, true)
81+
}
82+
catch(SVNException) {
83+
if(!message) askForMessage()
84+
// not checked in add and commit
85+
def wcClient = new SVNWCClient((ISVNAuthenticationManager)authManager,null)
86+
def pluginFile = new File(pluginZip)
87+
wcClient.doAdd(pluginFile,true,false,false,false)
88+
}
89+
}
90+
task(updateAndCommitLatest:"Commits the latest revision of the Plug-in") {
91+
def result = confirmInput("""
92+
This command will perform the following steps to release your plug-in into Grails' SVN repository:
93+
* Update your sources to the HEAD revision
94+
* Commit any changes you've made to SVN
95+
* Tag the release
96+
97+
NOTE: This command will not add new resources for you, if you have additional sources to add please run 'svn add' before running this command.
98+
NOTE: Make sure you have updated the version number if you *GrailsPlugin.groovy descriptor.
99+
100+
Are you sure you wish to proceed?
101+
""")
102+
if(result == 'n') exit(0)
103+
104+
checkInPluginZip()
105+
106+
updateClient = new SVNUpdateClient((ISVNAuthenticationManager)authManager, null)
107+
108+
println "Updating from SVN '${remoteLocation}'"
109+
long r = updateClient.doUpdate(baseFile, SVNRevision.HEAD, true)
110+
println "Updated to revision ${r}. Committing local, please wait..."
111+
112+
commitClient = new SVNCommitClient((ISVNAuthenticationManager)authManager, null)
113+
114+
if(!message) askForMessage()
115+
116+
def commit = commitClient.doCommit([baseFile] as File[],false,message,true,true)
117+
118+
println "Committed revision ${commit.newRevision}."
119+
}
120+
121+
task(importToSVN:"Imports a plug-in project to Grails' remote SVN repository") {
122+
checkOutDir = new File("${baseFile.parentFile.absolutePath}/checkout/${baseFile.name}")
123+
124+
def result = confirmInput("""
125+
This plug-in project is not currently in the repository, this command will now:
126+
* Perform an SVN import into the repository
127+
* Tag the plug-in project as the LATEST_RELEASE
128+
* Checkout the imported version of the project from SVN '${checkOutDir}'
129+
Are you sure you wish to proceed?
130+
""")
131+
if(result == 'n') exit(0)
132+
133+
Ant.unzip(src:pluginZip, dest:"${basedir}/unzipped")
134+
Ant.copy(file:pluginZip, todir:"${basedir}/unzipped")
135+
136+
137+
importClient = new SVNCommitClient((ISVNAuthenticationManager)authManager, null)
138+
askForMessage()
139+
140+
println "Importing project to ${remoteLocation}. Please wait..."
141+
142+
def svnURL = SVNURL.parseURIDecoded("${remoteLocation}/trunk")
143+
importClient.doImport(new File("${basedir}/unzipped"),svnURL,message,true)
144+
println "Plug-in project imported to SVN at location '${remoteLocation}/trunk'"
145+
146+
tagPluginRelease()
147+
148+
Ant.delete(dir:"${basedir}/unzipped")
149+
150+
151+
checkOutDir.parentFile.mkdirs()
152+
153+
updateClient = new SVNUpdateClient((ISVNAuthenticationManager)authManager, null)
154+
println "Checking out locally to '${checkOutDir}'."
155+
updateClient.doCheckout(svnURL, checkOutDir, SVNRevision.HEAD,SVNRevision.HEAD, true)
156+
157+
event('StatusFinal', ["""
158+
Completed SVN project import. If you are in terminal navigate to imported project with:
159+
cd ${checkOutDir}
160+
161+
Future changes should be made to the SVN controlled sources!"""])
162+
}
163+
164+
task(tagPluginRelease:"Tags a plugin-in with the LATEST_RELEASE tag and version tag within the /tags area of SVN") {
165+
166+
167+
copyClient = new SVNCopyClient((ISVNAuthenticationManager)authManager, null)
168+
commitClient = new SVNCommitClient((ISVNAuthenticationManager)authManager, null)
169+
170+
if(!message) askForMessage()
171+
172+
tags = SVNURL.parseURIDecoded("${remoteLocation}/tags")
173+
latest = SVNURL.parseURIDecoded(latestRelease)
174+
release = SVNURL.parseURIDecoded(versionedRelease)
175+
176+
try { commitClient.doMkDir([tags] as SVNURL[], message)}
177+
catch(SVNException e) {
178+
// ok - already exists
179+
}
180+
try { commitClient.doDelete([latest] as SVNURL[], message) }
181+
catch(SVNException e) {
182+
// ok - already exists
183+
}
184+
try { commitClient.doDelete([release] as SVNURL[], message) }
185+
catch(SVNException e) {
186+
// ok - already exists
187+
}
188+
try { commitClient.doMkDir([latest] as SVNURL[], message) }
189+
catch(SVNException e) {
190+
// ok - already exists
191+
}
192+
try { commitClient.doMkDir([release] as SVNURL[], message) }
193+
catch(SVNException e) {
194+
// ok - already exists
195+
}
196+
197+
198+
repository = SVNRepositoryFactory.create( trunk )
199+
//repository.setAuthenticationManager( authManager )
200+
201+
// we need to get a list of SVNURL entries to copy into the tags/LATEST_RELEASE directory
202+
def entries = []
203+
def root = repository.getDir("",-1,false , entries)
204+
def urls = entries.collect { it.URL }
205+
206+
def commit
207+
println "Tagging latest release, please wait..."
208+
urls.each { url -> commit = copyClient.doCopy(url,SVNRevision.HEAD,latest, false, false, message ) }
209+
println "Copied trunk to ${latestRelease} with revision ${commit.newRevision} on ${commit.date}"
210+
211+
println "Tagging version release, please wait..."
212+
urls.each { url -> commit = copyClient.doCopy(url,SVNRevision.HEAD,release, false, false, message ) }
213+
println "Copied trunk to ${versionedRelease} with revision ${commit.newRevision} on ${commit.date}"
214+
}
215+
216+
task(askForMessage:"Asks for the users commit message") {
217+
Ant.input(message:"Enter a SVN commit message:", addproperty:"commit.message")
218+
message = Ant.antProject.properties."commit.message"
219+
}

0 commit comments

Comments
 (0)