// -*- mode:groovy; coding:utf-8 -*-

//  Gant -- A Groovy way of scripting Ant tasks.
//
//  Copyright © 2008–2014  Russel Winder <russel@winder.org.uk>
//
//  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>

apply plugin: 'eclipse'
apply plugin: 'idea'

import org.apache.tools.ant.filters.ReplaceTokens

ext.artifact = 'gant'
ext.mavenNameExtension = '_groovy'

/*
 *  As discussed on the Groovy developer mail list (thanks to Roshan Dawrani and Paul King), the grammar for
 *  OSGi bundle numbers is fixed and slightly different to the expected grammar for version numbers and Maven
 *  artefacts:
 *
 *   version::= major('.'minor('.'micro('.'qualifier)?)?)?
 *   major::= digit+
 *   minor::= digit+
 *   micro::= digit+
 *   qualifier::= (alpha|digit|'_'|'-')+
 *   digit::= [0..9]
 *   alpha::= [a..zA..Z]
 *
 *  The core difference is that for OSGi bundle numbers the qualifier is separated by a full stop where in
 *  other situations a minus is used.
 */
final gantVersionBase = '1.9.11'
final isPrereleaseSnapshot = false

final createVersionString = {isForOSGi -> gantVersionBase + (isPrereleaseSnapshot ? (isForOSGi ? '.': '-') + 'SNAPSHOT': '')}

final debPackagingNumber = '1'

final gantVersion = createVersionString false
final gantPrefix = artifact + '-' + gantVersion
final gantBundleVersion =  createVersionString true

//  Nominate for each supported series of Groovy, exactly which version to use.

final groovyArtefactName = 'groovy-all'

ext.groovyVersions = [
  '2.0': '2.0.8',
  '2.1': '2.1.9',
  '2.2': '2.2.2',
  '2.3': '2.3.0',
]

//  One series of Groovy needs using for the standalone distribution. This version of Groovy will be packaged with
//  the "standalone" distribution of Gant.  It will generally be the latest widely available released version of Groovy.

final groovyStandaloneSeries = '2.2'

//  Organize the build using subprojects.  There is a subproject gant which is for the build using the
//  locally installed Groovy and there is one for each version of Groovy obtained from the Maven repository
//  that is supported.  These functions ease doing the iteration over all the subprojects.  NB Gradle
//  requires the directories for each of the subprojects to exist.  There is an assumption that each
//  subproject has its own source, etc.  This build slightly perverts the general approach by using exactly
//  the same source for each subproject, the only difference is the version of Groovy used for compilation.

def forEachDistributionVersion(Closure c) {
  groovyVersions.keySet().each{String s -> c(artifact + mavenNameExtension + s) }
}

def forEachProject(Closure c) {
  c artifact
  forEachDistributionVersion c
}

forEachProject{item ->  if (! new File(item).isDirectory()) { mkdir item }}

ext.distributionTasks = []
ext.debTasks = []

//  Using the JackRabbit wagon gets round some problems associated with uploading the distributions that
//  occurs with the standard wagon.  However, it does not solve the problem of not creating missing
//  directories that gives difficulties with new artefact uploads.  Have to cadaver in and create the
//  hierarchy first:-( Using the lightweight HTTP wagon still requires creating the directory structure
//  with cadaver or equivalent:-(

final webdavWagonName = 'org.apache.maven.wagon:wagon-webdav-jackrabbit:2.5'
//final webdavWagonName = 'org.apache.maven.wagon:wagon-http-lightweight:2.5'

//  In creating distributions which include jar files for the source, javadoc, and groovydoc, it is
//  imperative to ensure that they do not get located into the library directory for jars containing
//  compiled code for execution: it is critical to avoid getting the source, javadoc, and groovydoc jars on
//  the classpath.  Rather than build with defaults and sift when creating the distributions, cause the
//  source, javadoc, and groovydoc jars to be located in a different place.  This is the name of that place
//  which will be a peer to the executables jars directory.

final docsJarsDirName = 'docsJars'

// =====================================================================
//
//  Specifications of things for all the (sub)projects.

allprojects{
  group =  'org.codehaus.gant'
  version = gantVersion
}

final signingPropertiesAreSet = {->
  project.hasProperty('signing.keyId') && project.hasProperty('signing.password') && project.hasProperty('signing.secretKeyRingFile')
}

subprojects{
  apply plugin: 'groovy'
  apply plugin: 'osgi'
  if (signingPropertiesAreSet()) { apply plugin: 'signing' }
  sourceCompatibility = 6
  targetCompatibility = 6
  configurations{deployJars}
  sourceSets{
    //  NB All the subprojects are actually using the same source code and this is in a different place so
    //  the location of the source must be specified explicitly.
    main{groovy{srcDir '../src/main/groovy'}}
    test{groovy{srcDir '../src/test/groovy'}}
    integTest{groovy{srcDir '../src/integTest/groovy'}}
  }
  metaInf << fileTree(dir: '..').matching{include 'LICENCE.txt'}
  final theVendor = 'The Codehaus'
  final theTitle = 'Gant: Scripting Ant tasks with Groovy.'
  jar{
    manifest{
      name = 'Gant'
      version = gantBundleVersion
      symbolicName = 'gant'
      instruction 'Bundle-Vendor', theVendor
      instruction 'Bundle-Description', group
      instruction 'Bundle-DocURL', 'http://gant.codehaus.org'
      instruction 'Built-By', System.properties.'user.name'
      instruction 'Extension-Name', artifact
      instruction 'Specification-Title', theTitle
      instruction 'Specification-Version', gantBundleVersion
      instruction 'Specification-Vendor', theVendor
      instruction 'Implementation-Title', theTitle
      instruction 'Implementation-Version', gantBundleVersion
      instruction 'Implementation-Vendor', theVendor
      instruction 'provider', theVendor
      instruction 'Export-Package', "*;version=${gantVersion}"
      instruction 'Import-Package', '*;resolution:=optional'
    }
  }
  repositories{
    if (project.hasProperty('gant_useMavenLocal') && gant_useMavenLocal) { mavenLocal() }
    mavenCentral()
    maven{url 'http://repository.codehaus.org/'}
  }
  dependencies{
    compile(
      'commons-cli:commons-cli:1.2',
      'org.apache.ant:ant:1.9.2'
    )
    testCompile 'junit:junit:4.11'
    testRuntime 'org.apache.ivy:ivy:2.3.0'
    deployJars webdavWagonName
  }
  compileGroovy.options.compilerArgs = ['-Xlint']
  [compileGroovy, compileTestGroovy]*.options*.encoding = 'UTF-8'
  test{
    //  The Gant Ant task integration test (which is still a unit test:-( has to know the absolute
    //  locations of certain files.  Because Gradle uses a multi-project build there is an extra level
    //  complexity in paths compared to Eclipse, IntelliJ IDEA or Gant builds because the multi-project
    //  builds happen in subdirectories.  org.codehaus.gant.ant.tests.Gant_Test has a decision to make, it
    //  needs to know whether this is a Gradle build or not.  Use a property.
    systemProperties['buildFrameworkIdentifier'] = 'Gradle'
  }
  clean.doLast{
    delete 'texput.log', 'target_forMavenTest'
  }
  task integTest(type: Test, dependsOn: /* 'assemble' */ 'classes') {
    include file('src/integTest/groovy').absolutePath + '/org/codehaus/gant/ant/tests/*_Test.*'
  }
  if (signingPropertiesAreSet()) {
    signing{sign configurations.archives}
  }
  final packageTitle = 'Gant ' + gantVersion
  final copyrightString = 'Copyright &#169; 2006&#8211;2013  The Codehaus.  All Rights Reserved.'
  javadoc{
    options{
      overview 'overview.html'
      showAll()
      encoding 'UTF-8'
      setUse true
      author true
      version true
      windowTitle packageTitle
      docTitle packageTitle
      footer copyrightString
    }
  }
  javadoc.doFirst{
    javadoc.title = packageTitle
    javadoc.options.docTitle = javadoc.title
  }
  groovydoc{
    overview = 'overview.html'
    includePrivate = false
    use = true
    windowTitle = packageTitle
    docTitle = packageTitle
    header = packageTitle
    footer = copyrightString
  }
  task documentation(dependsOn: ['javadoc', 'groovydoc'], description: 'Create the API documentation.')
  final docsJarsDir = new File(buildDir, docsJarsDirName)
  task javadocArtifact(type: Jar, dependsOn: 'javadoc') {
    classifier = 'javadoc'
    from docsDir
  }
  javadocArtifact.destinationDir = docsJarsDir
  task groovydocArtifact(type: Jar, dependsOn: 'groovydoc') {
    classifier = 'groovydoc'
    from docsDir
  }
  groovydocArtifact.destinationDir = docsJarsDir
  task sourceArtifact(type: Jar) {
    classifier = 'sources'
    from sourceSets.main.allSource
  }
  sourceArtifact.destinationDir = docsJarsDir
  task allArtifacts(dependsOn: [jar, javadocArtifact, groovydocArtifact, sourceArtifact])
  artifacts {
    archives javadocArtifact
    archives groovydocArtifact
    archives sourceArtifact
  }
  defaultTasks 'build'
}

// =====================================================================
//
//  Use the locally installed Groovy or the standalone version from the Maven repository.  This subproject
//  is used for local installation and also for generating the documentation.

project(':gant'){
  //  If the user has GROOVY_HOME set then use that Groovy rather than the one specified in the properties
  //  files.  However we have to fiddle to find the version number.
  final groovyHome = System.getenv().'GROOVY_HOME'
  final groovyLib = null
  def groovyVersion
  def versionMessage
  if (groovyHome) {
    groovyLib = new File(groovyHome, 'lib')
    final groovyVersionPatternString = /^groovy-(all-)?([0-9].*)\.jar/
    final items = groovyLib.listFiles({File dir, String name -> return (name =~ groovyVersionPatternString).find()} as FilenameFilter)
    assert items
    groovyVersion = (items[0].name =~ groovyVersionPatternString)[0][2]
    assert groovyVersion
    repositories{flatDir(name: 'groovyInstallation', dirs: [new File(groovyHome, 'embeddable'), groovyLib])}
    versionMessage = 'Using Groovy version ' + groovyVersion + ' from ' + groovyHome
  }
  else {
    groovyVersion = groovyVersions[groovyStandaloneSeries]
    versionMessage = 'Using Groovy version ' + groovyVersion
  }
  dependencies{compile(group: 'org.codehaus.groovy', name: groovyArtefactName, version: groovyVersion)}
  compileGroovy.doFirst{println('\n\t' + versionMessage +'\n')}
  final buildPath = [System.properties.'user.dir', 'gant', 'build', 'classes']
  final classPath = []
  classPath << (buildPath + ['main']).join(File.separator)
  classPath << (buildPath + ['test']).join(File.separator)
  configurations.testRuntime.files.each { file -> classPath <<  file.parent }
  test.environment([
                       GROOVY_ANT_TASK_TEST_VERSION:  groovyVersion,
                       gradleClasspathString: classPath.join(System.properties.'path.separator')
                     ])
  final installDirectory = '/usr/share/gant'
  try { installDirectory = evaluate('"' + gant_installPath + '"') }
  catch (MissingPropertyException mpe) { /* Intentionally left blank. */ }
  task install(dependsOn: 'assemble', description: "Install Gant (compiled against Groovy ${groovyVersion}) to ${installDirectory}.") << {
    delete installDirectory
    final installBinDirectory = installDirectory + '/bin'
    final scriptsDirectory = '../scripts'
    copy{
      into installBinDirectory
      from([scriptsDirectory + '/bin', scriptsDirectory + '/bin_requiresGroovy'])
      filter ReplaceTokens, tokens: [
                 GROOVYPATH: 'embeddable',
                 GROOVYJAR: groovyArtefactName + '-' + groovyVersion + '.jar'
               ]
    }
    ant.chmod(perm: 'a+x'){fileset(dir: installBinDirectory, includes: 'gant*')}
    copy{
      into installDirectory + '/conf'
      from scriptsDirectory + '/conf/gant-starter.conf'
    }
    copy{
      into installDirectory + '/lib'
      from new File(buildDir, 'libs')
    }
  }
  task uninstall(type: Delete, description: "Delete ${installDirectory} so as to remove the Gant installation.") { delete installDirectory }
}

// =====================================================================
//
//  The subprojects compiling the source against specific Groovy version from the Maven repository.

final ciBuildTasks = []

final pomSpecification = {
  project{
    name 'Gant'
    url 'http://gant.codehaus.org.uk'
    description 'A framework for programming dependencies.'
    packaging 'bundle'
    licenses{
      license{
        name 'The Apache Software License, Version 2.0'
        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
        distribution 'repo'
      }
    }
    scm{
      url 'scm:git@github.com:Gant/Gant.git'
      connection 'scm:git@github.com:Gant/Gant.git'
      developerConnection 'scm:git@github.com:Gant/Gant.git'
    }
    developers{
      developer{name 'Russel Winder'}
    }
  }
}

forEachDistributionVersion{projectName->
  final groovyVersion = groovyVersions[projectName.replace(artifact + mavenNameExtension, '')]
  project(projectName){
    apply plugin: 'maven'
    dependencies{compile(group: 'org.codehaus.groovy', name: groovyArtefactName, version: groovyVersion)}
    compileGroovy.doFirst{println('\n\tUsing Groovy version ' + groovyVersion + '\n')}
    final buildPath = [System.properties.'user.dir', projectName, 'build', 'classes']
    final classPath = []
    classPath << (buildPath + ['main']).join(File.separator)
    classPath << (buildPath + ['test']).join(File.separator)
    configurations.testRuntime.files.each{file -> classPath <<  file.parent}
    test.environment([
                         GROOVY_ANT_TASK_TEST_VERSION:  groovyVersion,
                         gradleClasspathString: classPath.join(System.properties.'path.separator')
                       ])
    install.repositories.mavenInstaller{pom pomSpecification}
    gradle.taskGraph.whenReady{taskGraph ->
      if (taskGraph.hasTask(uploadArchives)) {
        if (! project.hasProperty('gant_experimentalMavenRepository') && !(project.hasProperty('codehausUsername') && project.hasProperty('codehausPassword'))) {
          throw new RuntimeException('Must define both codehausUsername and codehausPassword to upload archives.')
        }
        if (! signingPropertiesAreSet()) {
          throw new RuntimeException('Must define signing.keyId, signing.password, and signing.secretKeyRingFile')
        }
        uploadArchives.repositories.mavenDeployer{
          uniqueVersion = false
          configuration = configurations.deployJars
          beforeDeployment{MavenDeployment deployment -> signing.signPom(deployment)}
          if (project.hasProperty('gant_experimentalMavenRepository')) {
            if (! gant_experimentalMavenRepository) { throw new RuntimeException('gant_experimentalMavenRepository value not reasonable.') }
            repository url: "file://${rootProject.buildDir}/${gant_experimentalMavenRepository}"
          }
          else {
            //repository(url: 'dav:https://dav.codehaus.org/repository/gant/'){
            repository(url: 'https://dav.codehaus.org/repository/gant/'){
              authentication userName: codehausUsername, password: codehausPassword
            }
            //snapshotRepository(url: 'dav:https://dav.codehaus.org/snapshots.repository/gant/'){
            snapshotRepository(url: 'https://dav.codehaus.org/snapshots.repository/gant/'){
              authentication userName: codehausUsername, password: codehausPassword
            }
          }
          pom pomSpecification
        }
      }
    }
    final binCopySpec = copySpec{
      final scriptsDirectory = '../scripts'
      from('..'){include 'README*'}
      into('conf'){from(scriptsDirectory + '/conf'){include '*.conf'}}
      into('lib'){
        from libsDir
        rename projectName + '-' + version, artifact + '-' + version + mavenNameExtension + '-' + groovyVersion
      }
      into('bin'){
        fileMode = 0755
        from([scriptsDirectory + '/bin', scriptsDirectory + '/bin_requiresGroovy'])
        filter ReplaceTokens, tokens: [
                   GROOVYPATH: 'embeddable',
                   GROOVYJAR: groovyArtefactName + '-' + groovyVersion + '.jar'
                 ]
      }
    }
    task binTgz(type: Tar, dependsOn: 'jar', description: 'Build the distribution tarball.') {
      baseName = artifact
      classifier = mavenNameExtension + '-' + groovyVersion
      compression = Compression.GZIP
      into(gantPrefix){with binCopySpec}
    }
    task binZip(type: Zip, dependsOn: 'jar', description: 'Build the distribution zip file.') {
      baseName = artifact
      classifier = mavenNameExtension + '-' + groovyVersion
      into(gantPrefix){with binCopySpec}
    }
    distributionTasks += [binTgz, binZip]
  }
  //  Due to weird effective scoping of projects -- caused by cloning of bindings for projects? -- need to
  //  do the following to get the above tasks into the list defined by the main script.
  distributionTasks += project(projectName).distributionTasks
  ciBuildTasks << projectName + ':build'
}

// =====================================================================
//
//  Create the standalone distribution.

final projectNameForStandalone = 'gant_groovy' + groovyStandaloneSeries

final standaloneCopySpec = copySpec{
  final scriptsDirectory = 'scripts'
  final projectBase = project projectNameForStandalone
  from('.'){include 'README*'}
  into('conf'){from(scriptsDirectory + '/conf'){include '*.conf'}}
  into('lib'){
    from projectBase.libsDir
    from projectBase.configurations.runtime
  }
  into('bin'){
    fileMode = 0755
    from([scriptsDirectory + '/bin', scriptsDirectory + '/bin_standalone'])
    filter ReplaceTokens, tokens: [
               GROOVYPATH: 'lib',
               GROOVYJAR: groovyArtefactName + '-' + groovyVersions[groovyStandaloneSeries] + '.jar'
             ]
  }
}

task standaloneBinTgz(type: Tar, dependsOn: projectNameForStandalone + ':jar', description: 'Create a tarball of the standalone distribution.') {
  baseName = artifact
  version = gantVersion
  compression = Compression.GZIP
  destinationDir = buildDir
  into(gantPrefix){with standaloneCopySpec}
}

task standaloneBinZip(type: Zip, dependsOn: projectNameForStandalone + ':jar', description: 'Create a zip file of the standalone distribution.') {
  baseName = artifact
  version = gantVersion
  destinationDir = buildDir
  into(gantPrefix){with standaloneCopySpec}
}

distributionTasks += [standaloneBinTgz, standaloneBinZip]

// =====================================================================
//
//  Create the deb file of the standalone distribution.

final debsDirectory = new File(buildDir, 'debs')
final distDirectory = new File(buildDir, 'dist')

task clean(type: Delete) {
  delete debsDirectory
  delete distDirectory
}

task standaloneDeb(dependsOn: standaloneBinTgz, description: 'Create a deb for use with Debian and Ubuntu.') << {
  final packageName = 'gant-standalone'
  final architecture = 'all'
  final createdDebFileName = packageName + '_' + gantVersion + '-' + debPackagingNumber + '_' + architecture + '.deb'
  final installPrefixBase = 'usr/share/gant'
  final expandDirectory = (new File(distDirectory, 'gant-' + gantVersion)).path
  final packagingDirectory = 'packaging/AntDebTask'
  inputs.file packagingDirectory + '/gant'
  inputs.file expandDirectory + '/bin/startGroovy'
  inputs.file expandDirectory + '/conf/gant-starter.conf'
  inputs.dir expandDirectory + '/lib'
  outputs.file debsDirectory.absolutePath + '/' + createdDebFileName
  // Using doLast here causes a concurrent modification exception.
  //doLast {
    delete distDirectory
    distDirectory.mkdirs()
    ant.taskdef resource: 'ant_deb_task.properties', classpath: [System.properties.'user.home', '.groovy', 'lib', 'ant-deb.jar'].join(System.properties.'file.separator')
    logger.info "==>  Untaring ${buildDir}/gant-${gantVersion}.tgz to ${distDirectory}"
    final process = ['sh', '-x', '-c', "cd ${distDirectory} && tar xvf ${buildDir}/gant-${gantVersion}.tgz"].execute()
    process.consumeProcessOutput()
    process.waitFor()
    debsDirectory.mkdirs()
    final result = ant.deb(todir: debsDirectory, 'package': packageName, section: 'devel', priority: 'optional', architecture: architecture,
                             depends: 'java2-runtime', postinst: packagingDirectory+ '/postinst', prerm: packagingDirectory + '/prerm',
                             conflicts: 'gant'){
      //  Hack required to make Gradle get things right.
      //version upstream: gantVersion, debian: debPackagingNumber
      delegate.version upstream: gantVersion, debian: debPackagingNumber
      maintainer name: 'Russel Winder', email: 'russel@winder.org.uk'
      description synopsis: 'Gant -- Groovy scripting of Ant tasks.', '''
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: http://gant.codehaus.org/
'''
      tarfileset file: packagingDirectory + '/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'
    }
    //  The deb Ant task appears not to record the name of the resultant deb file so we have to construct it
    //  by replicating the algorithm:-((
    assert createdDebFileName == result._package + '_' + result._version + '_' + result._architecture + '.deb'
    //}
}

debTasks << standaloneDeb

// =====================================================================
//
//  Create the documentation distribution.

task docTgz(type: Tar, dependsOn: [':gant:javadoc', ':gant:groovydoc'], description: 'Create a tarball of the documentation') {
  baseName = artifact + '_doc'
  version = gantVersion
  compression = Compression.GZIP
  destinationDir = buildDir
  into(gantPrefix + '/docs'){from project(':gant').docsDir}
}

task docZip(type: Zip, dependsOn: [':gant:javadoc', ':gant:groovydoc'], description: 'Create a zip file of the documentation') {
  baseName = artifact + '_doc'
  version = gantVersion
  destinationDir = buildDir
  into(gantPrefix + '/docs'){from project(':gant').docsDir}
}

distributionTasks += [docTgz, docZip]

// =====================================================================
//
//  Create the source distribution.

final srcContent = [
  'artwork/', 'documentation/', 'examples/', 'packaging', 'scripts/', 'src/',
  'build.gradle', 'settings.gradle', 'gradlew','gradlew.bat', 'wrapper/',
  'ciBuild',
  'Gant.ipr', 'Gant.iws',
  '.classpath', '.project', '.settings/',
  'LICENCE.txt',
  'README_Install.txt',
  'releaseNotes.txt',
  'overview.html',
]

task srcTgz(type: Tar, description: 'Create a tarball of the source.') {
  baseName = artifact + '_src'
  version = gantVersion
  compression = Compression.GZIP
  destinationDir = buildDir
  into(gantPrefix){from(projectDir){srcContent.each{include it}}}
}

task srcZip(type: Zip, description: 'Create a zip file of the source.') {
  baseName = artifact + '_src'
  version = gantVersion
  destinationDir = buildDir
  into(gantPrefix){from(projectDir){srcContent.each{include it}}}
}

distributionTasks += [srcTgz, srcZip]

// =====================================================================
//
//  Tasks for getting all the distribution materials uploaded to Codehaus.

final checkAuthority = {->
  if (! project.hasProperty('gant_experimentalDistributionLocation') && !(project.hasProperty('codehausUsername') && project.hasProperty('codehausPassword'))) {
    throw new RuntimeException('Must define both codehausUsername and codehausPassword to upload distributions.')
  }
}

final undertakeUpload = {copySpec, uploadSpec ->
  if (project.hasProperty('gant_experimentalDistributionLocation')) {
    if (! gant_experimentalDistributionLocation) { throw new RuntimeException('gant_experimentalDistributionLocation value not reasonable.') }
    copy copySpec
  }
  else {
    configurations{upload}
    repositories{
      if (project.hasProperty('gant_useMavenLocal') && gant_useMavenLocal) { mavenLocal() }
      mavenCentral()
    }
    dependencies { upload 'com.googlecode.sardine:sardine:146' }
    assert uploadSpec.size() == 2
    final targetDirectoryUrl = 'https://dav.codehaus.org/' + (gantVersion.contains('SNAPSHOT') ? 'snapshots.' : '') + 'dist/gant/' + uploadSpec[0]
    /*
    com.googlecode.sardine.Sardine sardine = com.googlecode.sardine.SardineFactory.begin(codehausUsername, codehausPassword)
    */
  }
}

task buildDistribution(dependsOn: distributionTasks, description: 'Build all the uploadable distribution archives.')

task uploadDistribution(dependsOn: buildDistribution, description: 'Upload all the distribution archives.') << {
  checkAuthority()
  undertakeUpload(
    {
      distributionTasks.each { task -> from task }
      into rootProject.buildDir.absolutePath + '/' + gant_experimentalDistributionLocation + '/distributions'
    },
    ['distributions', distributionTasks])
}

// =====================================================================
//
//  Tasks for getting all the debs uploaded to Codehaus.

task buildDebs(dependsOn: debTasks, description: 'Build all the uploadable debs.')

task uploadDebs(dependsOn: buildDebs, description: 'Upload all the debs.') << {
  checkAuthority()
  undertakeUpload(
    {
      debTasks.each{task -> from task}
      into rootProject.buildDir.absolutePath + '/' + gant_experimentalDistributionLocation + '/debs'
    },
    ['debs', debTasks])
}


// =====================================================================
//
//  Do a complete release.

final archivesUploadTasks = []
forEachDistributionVersion{archivesUploadTasks << ':' + it + ':uploadArchives'}

task uploadRelease(dependsOn: archivesUploadTasks + [uploadDistribution, uploadDebs], description: 'Upload all elements of a release.')

// =====================================================================
//
//  Odds and sods.

task ciBuild(description: 'Run just the builds that use Groovy from the Maven repository.  Used mainly on CI servers.', dependsOn: ciBuildTasks)

task wrapper(type: Wrapper) {
  gradleVersion = '1.11'
}

task clobber(description: 'Do a really detailed clean.') << {
  forEachProject{item -> delete item}
  delete buildDir, 'texput.log'
}

// Russel uses Java 8 with IntelliJ IDEA and assumes everyone else is.

idea {
    module {
        excludeDirs += file 'gradle/' // Gradle directory including the wrapper subdirectory.
        excludeDirs += file '.gradle/' // Gradle directory
        excludeDirs += file '.settings/' // Eclipse settings directory.
        excludeDirs += file 'bin' // Eclipse compilation directory.
        excludeDirs += file 'out' // IDEA compilation directory.
        excludeDirs += file 'build' // Gradle compilation directory.
    }
    project{
        jdkName = '1.8'
        ipr{
            withXml{provider ->
                provider.asNode().component.find{it.'@name' == 'VcsDirectoryMappings'}.mapping[0].'@vcs' = 'Git'
            }
            whenMerged{project ->
                project.jdk.languageLevel = 'JDK_1_8'
            }
        }
    }
}
