blob: 17e62d20259187c9997af458139d587350882789 [file]
/*
* Copyright 2004-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.tmatesoft.svn.core.io.SVNRepositoryFactory
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory
import org.tmatesoft.svn.core.io.*
import org.tmatesoft.svn.core.*
import org.tmatesoft.svn.core.auth.*
import org.tmatesoft.svn.core.wc.*
/**
* Gant script that handles releasing plugins to a plugin repository.
*
* @author Graeme Rocher
*/
includeTargets << grailsScript("_GrailsPluginDev")
includeTargets << grailsScript("_GrailsDocs")
authManager = null
commitMessage = null
trunk = null
latestRelease = null
versionedRelease = null
target ('default': "A target 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.") {
releasePlugin()
}
target(processAuth:"Prompts user for login details to create authentication manager") {
if(!authManager) {
ant.input(message:"Please enter your SVN username:", addproperty:"user.svn.username")
ant.input(message:"Please enter your SVN password:", addproperty:"user.svn.password")
def username = ant.antProject.properties."user.svn.username"
def password = ant.antProject.properties."user.svn.password"
authManager = SVNWCUtil.createDefaultAuthenticationManager( username , password )
}
}
target(releasePlugin: "The implementation target") {
depends(parseArguments, packagePlugin, processAuth, docs)
if(argsMap.repository) {
configureRepositoryForName(argsMap.repository, "distribution")
}
remoteLocation = "${pluginSVN}/grails-${pluginName}"
trunk = SVNURL.parseURIDecoded("${remoteLocation}/trunk")
latestRelease = "${remoteLocation}/tags/LATEST_RELEASE"
versionedRelease = "${remoteLocation}/tags/RELEASE_${plugin.version.toString().replaceAll('\\.','_')}"
FSRepositoryFactory.setup()
DAVRepositoryFactory.setup()
try {
if(argsMap.pluginlist) {
commitNewGlobalPluginList()
}
else {
def statusClient = new SVNStatusClient((ISVNAuthenticationManager)authManager,null)
try {
// get status of base directory, if this fails exception will be thrown
statusClient.doStatus(baseFile, true)
updateAndCommitLatest()
}
catch(SVNException ex) {
// error with status, not in repo, attempt import.
if (ex.message.contains("is not a working copy")) {
// Now check whether the plugin is in the repository.
// If not, we ask the user whether they want to import
// it.
SVNRepository repos = SVNRepositoryFactory.create(SVNURL.parseURIDecoded(pluginSVN))
boolean notInRepository = true
try {
notInRepository = !repos.info("grails-$pluginName", -1)
}
catch (e) {
// ignore
}
if (notInRepository) {
importToSVN()
}
else {
def result = confirmInput("""
The current directory is not a working copy and your latest changes won't be committed. You need to checkout
a working copy and make your changes there. Alternatively, do you want to proceed and create a release from what is in SVN now?
""")
if(!result) exit(0)
}
}
else {
event('StatusFinal', ["Failed to stat working directory: ${ex.message}"])
exit(1)
}
}
tagPluginRelease()
commitNewGlobalPluginList()
event('StatusFinal', ["Plug-in release successfully published"])
}
}
catch(Exception e) {
logErrorAndExit("Error occurred with release-plugin", e)
}
}
target(commitNewGlobalPluginList:"updates the plugins.xml descriptor stored in the repo") {
if(!commitMessage) askForMessage()
ant.delete(file:pluginsListFile)
println "Building plugin list for commit..."
updatePluginsListManually()
def pluginMetaDir = new File("${grailsSettings.grailsWorkDir}/${repositoryName}/.plugin-meta")
def updateClient = new SVNUpdateClient((ISVNAuthenticationManager)authManager, null)
def importClient = new SVNCommitClient((ISVNAuthenticationManager)authManager, null)
def addClient = new SVNWCClient((ISVNAuthenticationManager)authManager, null)
String remotePluginMetadata = "${pluginSVN}/.plugin-meta"
if(!pluginMetaDir.exists()) {
println "Checking out locally to '${pluginMetaDir}'."
checkoutOrImportPluginMetadata(pluginMetaDir, remotePluginMetadata, updateClient, importClient)
}
else {
try {
updateClient.doUpdate(pluginMetaDir, SVNRevision.HEAD, true)
commitNewestPluginList(pluginMetaDir, importClient)
} catch (SVNException e) {
println "Plugin meta directory corrupt, checking out again"
checkoutOrImportPluginMetadata(pluginMetaDir, remotePluginMetadata, updateClient, importClient)
}
}
}
private checkoutOrImportPluginMetadata (File pluginMetaDir, String remotePluginMetadata, SVNUpdateClient updateClient, SVNCommitClient importClient) {
def svnURL = SVNURL.parseURIDecoded (remotePluginMetadata)
try {
updateClient.doCheckout(svnURL, pluginMetaDir, SVNRevision.HEAD, SVNRevision.HEAD, true)
try {
addClient.doAdd(new File("$pluginMetaDir/plugins-list.xml"), false, false, false, false)
}
catch (e) {
// ignore
}
commitNewestPluginList(pluginMetaDir, importClient)
} catch (SVNException e) {
println "Importing plugin meta data to ${remotePluginMetadata}. Please wait..."
ant.mkdir(dir: pluginMetaDir)
ant.copy(file: pluginsListFile, tofile: "$pluginMetaDir/plugins-list.xml")
def commit = importClient.doImport(pluginMetaDir, svnURL, commitMessage, true)
println "Committed revision ${commit.newRevision} of plugins-list.xml."
ant.delete(dir: pluginMetaDir)
updateClient.doCheckout(svnURL, pluginMetaDir, SVNRevision.HEAD, SVNRevision.HEAD, true)
}
}
private def commitNewestPluginList(File pluginMetaDir, SVNCommitClient importClient) {
ant.copy(file: pluginsListFile, tofile: "$pluginMetaDir/plugins-list.xml", overwrite: true)
def commit = importClient.doCommit([pluginMetaDir] as File[], false, commitMessage, true, true)
println "Committed revision ${commit.newRevision} of plugins-list.xml."
}
target(checkInPluginZip:"Checks in the plug-in zip if it has not been checked in already") {
def statusClient = new SVNStatusClient((ISVNAuthenticationManager)authManager,null)
def wcClient = new SVNWCClient((ISVNAuthenticationManager)authManager,null)
def pluginFile = new File(pluginZip)
def addPluginFile = false
try {
def status = statusClient.doStatus(pluginFile, true)
if(status.kind == SVNNodeKind.NONE || status.kind == SVNNodeKind.UNKNOWN) addPluginFile = true
}
catch(SVNException) {
// not checked in add and commit
addPluginFile = true
}
if(addPluginFile) wcClient.doAdd(pluginFile,true,false,false,false)
def pluginXml = new File("${basedir}/plugin.xml")
addPluginFile = false
try {
def status = statusClient.doStatus(pluginXml, true)
if(status.kind == SVNNodeKind.NONE || status.kind == SVNNodeKind.UNKNOWN) addPluginFile = true
}
catch(SVNException e) {
addPluginFile = true
}
if(addPluginFile) wcClient.doAdd(pluginXml, true, false,false,false)
}
target(updateAndCommitLatest:"Commits the latest revision of the Plug-in") {
def result = confirmInput("""
This command will perform the following steps to release your plug-in to Grails' SVN repository:
* Update your sources to the HEAD revision
* Commit any changes you've made to SVN
* Tag the release
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.
NOTE: Make sure you have updated the version number in your *GrailsPlugin.groovy descriptor.
Are you sure you wish to proceed?
""")
if(!result) exit(0)
checkInPluginZip()
updateClient = new SVNUpdateClient((ISVNAuthenticationManager)authManager, null)
println "Updating from SVN '${remoteLocation}'"
long r = updateClient.doUpdate(baseFile, SVNRevision.HEAD, true)
println "Updated to revision ${r}. Committing local, please wait..."
commitClient = new SVNCommitClient((ISVNAuthenticationManager)authManager, null)
if(!commitMessage) askForMessage()
println "Committing code. Please wait..."
def commit = commitClient.doCommit([baseFile] as File[],false,commitMessage,true,true)
println "Committed revision ${commit.newRevision}."
}
target(importToSVN:"Imports a plug-in project to Grails' remote SVN repository") {
checkOutDir = new File("${baseFile.parentFile.absolutePath}/checkout/${baseFile.name}")
def result = confirmInput("""
This plug-in project is not currently in the repository, this command will now:
* Perform an SVN import into the repository
* Checkout the imported version of the project from SVN to '${checkOutDir}'
* Tag the plug-in project as the LATEST_RELEASE
Are you sure you wish to proceed?
""")
if(!result) exit(0)
ant.unzip(src:pluginZip, dest:"${basedir}/unzipped")
ant.copy(file:pluginZip, todir:"${basedir}/unzipped")
ant.mkdir(dir:"${basedir}/unzipped/grails-app")
importClient = new SVNCommitClient((ISVNAuthenticationManager)authManager, null)
askForMessage()
println "Importing project to ${remoteLocation}. Please wait..."
def svnURL = SVNURL.parseURIDecoded("${remoteLocation}/trunk")
importClient.doImport(new File("${basedir}/unzipped"),svnURL,commitMessage,true)
println "Plug-in project imported to SVN at location '${remoteLocation}/trunk'"
ant.delete(dir:"${basedir}/unzipped")
checkOutDir.parentFile.mkdirs()
updateClient = new SVNUpdateClient((ISVNAuthenticationManager)authManager, null)
println "Checking out locally to '${checkOutDir}'."
updateClient.doCheckout(svnURL, checkOutDir, SVNRevision.HEAD,SVNRevision.HEAD, true)
event('StatusFinal', ["""
Completed SVN project import. If you are in terminal navigate to imported project with:
cd ${checkOutDir}
Future changes should be made to the SVN controlled sources!"""])
}
target(tagPluginRelease:"Tags a plugin-in with the LATEST_RELEASE tag and version tag within the /tags area of SVN") {
println "Preparing to publish the release..."
def copyClient = new SVNCopyClient((ISVNAuthenticationManager) authManager, null)
def commitClient = new SVNCommitClient((ISVNAuthenticationManager) authManager, null)
if (!commitMessage) askForMessage()
tags = SVNURL.parseURIDecoded("${remoteLocation}/tags")
latest = SVNURL.parseURIDecoded(latestRelease)
release = SVNURL.parseURIDecoded(versionedRelease)
try { commitClient.doMkDir([tags] as SVNURL[], commitMessage) }
catch (SVNException e) {
// ok - already exists
}
try { commitClient.doDelete([latest] as SVNURL[], commitMessage) }
catch (SVNException e) {
// ok - the tag doesn't exist yet
}
try { commitClient.doDelete([release] as SVNURL[], commitMessage) }
catch (SVNException e) {
// ok - the tag doesn't exist yet
}
// Get remote URL for this working copy.
def wcClient = new SVNWCClient((ISVNAuthenticationManager) authManager, null)
def copyFromUrl = trunk
if (new File(grailsSettings.baseDir, ".svn").exists()) {
copyFromUrl = wcClient.doInfo(new File("."), SVNRevision.WORKING).URL
}
// First tag this release with the version number.
try {
println "Tagging version release, please wait..."
def copySource = new SVNCopySource(SVNRevision.HEAD, SVNRevision.HEAD, copyFromUrl)
def commit = copyClient.doCopy([copySource] as SVNCopySource[], release, false, false, true, commitMessage, new SVNProperties())
println "Copied trunk to ${versionedRelease} with revision ${commit.newRevision} on ${commit.date}"
// And now make it the latest release.
println "Tagging latest release, please wait..."
copySource = new SVNCopySource(SVNRevision.HEAD, SVNRevision.HEAD, release)
commit = copyClient.doCopy([copySource] as SVNCopySource[], latest, false, false, true, commitMessage, new SVNProperties())
println "Copied trunk to ${latestRelease} with revision ${commit.newRevision} on ${commit.date}"
}
catch (SVNException e) {
logErrorAndExit("Error tagging release", e)
}
}
target(askForMessage:"Asks for the users commit message") {
ant.input(message:"Enter a SVN commit message:", addproperty:"commit.message")
commitMessage = ant.antProject.properties."commit.message"
}