//  Gant -- A Groovy way of scripting Ant tasks.
//
//  Copyright © 2007–2010, 2013  Russel Winder
//
//  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.
//
//  Author: Russel Winder <russel@winder.org.uk>

//  The overal algorithm here is to take a standalone distribution (could use either a tarball or a
//  zipfile, prefer to use a tarball if it exists) expand it and then repackage into a deb file.  Do not
//  include any Windows specific bits.  Furthermore replace the standard launch script with one specifically
//  designed for the installation with its known locations and dependencies.

//  Use the ant-deb-task from Marius Scurtescu <marius.scurtescu@gmail.com> to create a deb file.
//  Assume the ant-deb.jar file is in ~/.groovy/lib.

//  Extract the Gant version number from the Gradle build file.  Scanning the text with the regular
//  expression below should result in a single match resulting in a list of two items, the full match and
//  the capture group.  The capture group should be the version number.

final matcher = new File('../../build.gradle').text =~ "gantVersionBase\\s*=\\s*'(.*)'"
assert matcher != null
assert matcher[0] != null
assert matcher[0].size() == 2

final gantVersion = matcher[0][1]

//  Name of and properties to be embedded in the deb.

final packageName = 'gant-standalone'
final section = 'devel'
final priority = 'optional'
final architecture = 'all'
final homepage = 'http://gant.codehaus.org/'

final installPrefixBase = 'usr/share/gant'

final theSynopsis = 'Gant -- Groovy scripting of Ant tasks.'
final theWords = """
Gant is a tool for scripting Ant tasks using Groovy instead of XML to specify
the logic. A Gant specification is just a Groovy script and so can bring all
the power of Groovy to bear directly, something not possible with Ant scripts.
Whilst it might be seen as a competitor to Ant, Gant relies on all the Ant
tasks for the complex actions, so it is really an alternative way of doing
builds using Ant, but using a programming language rather than XML to specify
the rules.
.
This package provides a self-contained installation of Gant that does not
depend on a separate installation of Groovy -- all the jars needed for Gant to
run are included in the package.
.
Homepage: ${homepage}
"""

//  Where to put the deb when uploading.  We need the slide-webdav jar which we get fromt he Maven
//  repository, so we need to make use of the Maven Ant task to be able to get it.

final antlibXMLns = 'antlib:org.apache.maven.artifact.ant'
final distributionURL = 'https://dav.codehaus.org/' +(gantVersion.contains('SNAPSHOT') ? 'snapshots.': '') + 'dist/gant/'

//  Load up the Ant Deb task.

ant.taskdef(resource: 'ant_deb_task.properties', classpath: [ System.properties.'user.home', '.groovy', 'lib', 'ant-deb.jar' ].join(System.properties.'file.separator'))

//  Local details of where to expand the standalone distribution and where to make the debs.

final debsDirectory = 'debs'
final distDirectory = 'dist'
final expandDirectory = distDirectory + '/gant-' + gantVersion

//  Make sure we can tidy things up.  Also that we can easily run subprocesses.

includeTargets << gant.targets.Clean
cleanPattern << '**/*~'
cleanDirectory << [ debsDirectory, distDirectory ]

includeTool << gant.tools.Execute

//  The targets:  create the debs and upload the debs, set the default to build.

target(debFiles: 'Create the deb file of the distribution.') {
  execute.shell("cd ../.. && gradle standaloneBinTgz")
  mkdir(dir: distDirectory)
  delete { fileset(dir: distDirectory, includes: '**/*') }
  execute.shell("cd ${distDirectory} && tar xvf ../../../build/gant-${gantVersion}.tgz")
  mkdir(dir: debsDirectory)
  ////  Why is the ant. needed here ??????
  ant.deb(todir: debsDirectory, 'package': packageName, section: section, priority: priority, architecture: architecture,
        depends: 'java2-runtime', postinst: 'postinst', prerm: 'prerm') {
    version(upstream: gantVersion)
    maintainer(name: 'Russel Winder', email: 'russel@russel.org.uk')
    //homepage(homepage)
    description(synopsis: theSynopsis, theWords)
    tarfileset(file: 'gant', prefix: installPrefixBase + '/bin', filemode: '755')
    tarfileset(file: expandDirectory + '/bin/startGroovy', prefix: installPrefixBase + '/bin', filemode: '644')
    tarfileset(file: expandDirectory + '/conf/gant-starter.conf', prefix: installPrefixBase + '/conf', filemode: '644')
    tarfileset(dir: expandDirectory + '/lib', includes: '*.jar', prefix: installPrefixBase + '/lib', filemode: '644')
  }
}

target(uploadDistribution: 'Upload the deb files to Codehaus.') {
  depends(debFiles)
  "${antlibXMLns}:dependencies"(pathId:  'slidePathId') {
    dependency(groupId: 'slide', artifactId: 'slide-webdavlib', version: '2.1')
  }
  def loader = getClass().getClassLoader()
  def path = path(refid: 'slidePathId')
 (path.list() as List).each { location -> loader.addURL(new URL('file://' + location)) }
  def settings = (new XmlSlurper()).parse(System.properties.'user.home' + '/.m2/settings.xml').servers.server.find { item -> item.id == 'codehaus.org' }
  def credentials =  loader.loadClass('org.apache.commons.httpclient.UsernamePasswordCredentials').getConstructor(String, String).newInstance(settings.username.toString(), settings.password.toString())
  //  Have to put resource in the binding so that the Closures can access it.
  resource = loader.loadClass('org.apache.webdav.lib.WebdavResource').getConstructor(String,  loader.loadClass('org.apache.commons.httpclient.Credentials'), boolean).newInstance(distributionURL, credentials, true)
  if (resource.statusCode != 200) { println('Failed to open ' + distributionURL) }
  else {
    final serverUploadProducts = [:]
    final serverDistributionsDirectory = 'debs'
    new File(debsDirectory).eachFile { file -> serverUploadProducts[ file.path ] = serverDistributionsDirectory + '/' + file.name
    }
    serverUploadProducts.each { source, destination ->
      def serverPath = resource.path + '/' + destination
      print('Uploading ' + source + ' -> ' + destination + ': ')
      def result = 'Failed.'
      if (resource.putMethod(serverPath, new File(source))) { result = 'OK.' }
      println(result + ' Status: ' + resource.statusMessage)
    }
  }
  if (resource != null) { resource.close() }
}

setDefaultTarget(debFiles)
