/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

/**
 * Gradle script used to perform DM releases (really similar to Apache ACE build.xml)
 */
import aQute.bnd.build.Workspace

buildscript {
  repositories {
    mavenCentral()
  }

  dependencies {
    classpath bnd_plugin
  }
}

// Our release number, which has to be monotonically incremented each time we make a new release.
ext.dmRelease = "r16"

// Our Apache svn Staging repo
ext.svnStagingPath = "https://dist.apache.org/repos/dist/dev/felix"

// Our Apache svn Release repo
ext.svnReleasePath = "https://dist.apache.org/repos/dist/release/felix"

apply plugin: 'java'
apply from: file("rat.gradle")

// Add bnd as a build dependency
buildscript {
    dependencies {
        classpath files('cnf/gradle/biz.aQute.bnd.gradle.jar')
    }
}

// Configure RAT plugin to ignore some files
rat {
  excludes = [
    'rat-report.xml',
    '**/.git/**',
    '**/.gradle/**',
    '**/.project',
    '**/.settings/**',
    '**/*.iml',
    '**/*.iws',
    '**/*.ipr',
    '**/.classpath',
    'cnf/**',
    'gradle/wrapper/**',
    'release/**',
    'gradlew',
    'README',
    '**/DEPENDENCIES',
    '**/README',
    '**/.gitignore',
    '**/generated/**',
    'doc/**',
    '**/packageinfo',
    '**/*.txt',
    'docs/**',
    '.metadata/**'
  ]
}

// Setup the workspace
Workspace workspace
workspace = Workspace.getWorkspace(".")

task makeStaging {
    doLast {
    description = 'Packages the source and binary distributions.'

    // Package source distributions.
    logger.lifecycle("    Packaging source distributions.")
    def topdir="org.apache.felix.dependencymanager-" + dmRelease
    ant.zip(destfile: "staging/"+topdir+'-src.zip') {
		zipfileset(dir: '../cnf', prefix: topdir+"-src/cnf", includes: ".project,.classpath,src/**,*.bnd,*.mvn,ext/**")
		zipfileset(dir: '..', prefix: topdir+"-src", includes: '*.gradle,*.properties')
		zipfileset(dir: 'resources/src', prefix: topdir+"-src", includes: '*')
		ant.zipfileset(dir: '..', prefix: topdir+"-src", includes: 'gradlew')
		ant.zipfileset(dir: '..', prefix: topdir+"-src", includes: 'changelog.txt')
    		ant.zipfileset(dir: '../.gradle-wrapper', prefix: topdir+"-src/.gradle-wrapper", includes: 'gradle-wrapper.properties')
		new File('.').eachFile { 
	    	    if(new File(it, 'bnd.bnd').exists()) {	    		
    			def bndProject = workspace.getProject(it.name)
    			if (! bndProject.isNoBundles() && ! bndProject.getName().endsWith(".benchmark")) {
    		    	    zipfileset(dir: "../${bndProject.name}", prefix: topdir+"-src/${bndProject.name}",
    			    	       includes: "*.gradle,.project,.classpath,.settings/**,src/**,test/**,*.bnd,*.bndrun,run-*/conf/**,resources/**,README*,changelog.txt")
    			}
	   	    }
		}
    }

    // Package binaries as a simple collection of bundles. We use same license files as for src distrib.
    logger.lifecycle("    Packaging binary distribution.")

    // First, get list of latest released bundles available from our Release repository
    def released = []
    def releaseRepo = workspace.getRepository("Release")
    def bundles=releaseRepo.list(null)
    bundles.each {
	    def sortedVersions = releaseRepo.versions(it)
	    def latestVersion = sortedVersions.last()
	    def latestBundle = releaseRepo.get(it, latestVersion, null)
	    released << latestBundle
    }

    // Before adding all latest released bundles in the binary distribution, check if they contain proper license files.
    logger.lifecycle("    Checking META-INF mandatory files.")
    released.each { jarfile -> 
    	if (jarfile.isFile()) {
       		new ByteArrayOutputStream().withStream { os ->
				def result = exec {
	    			executable = 'jar'
	    			args = ['tf', jarfile, "META-INF"]
	    			standardOutput = os
				}
				def files = os.toString().split("\n")
				def mandatory = ["META-INF/LICENSE", "META-INF/NOTICE", "META-INF/DEPENDENCIES", "META-INF/changelog.txt"]
				mandatory.each { resource ->			
					if (! files.contains(resource)) {
						throw new GradleException("Missing mandatory license files in " + jarfile)
					}
				}
			}
		}
    }

    // Now, add all the latest released bundles in the binary distribution
    ant.zip(destfile: "staging/"+topdir+"-bin.zip") {
        // include workspace changelog
	zipfileset(dir: '..', prefix: topdir+"-bin/", includes: "changelog.txt")

        // simply include all released bundle.
        released.each {
	    file=it
            ant.mappedresources() {
        	ant.filelist(files: file)
                ant.chainedmapper() {
                    ant.flattenmapper()
                    ant.globmapper(from: '*', to: topdir+'-bin/*')
                }
            }
        }
        ant.mappedresources() {
            ant.fileset(dir: 'resources/bin', includes: '*')
            ant.chainedmapper() {
                ant.flattenmapper()
                ant.globmapper(from: '*', to: topdir+'-bin/*')
            }
        }
    }
    }
}


 

// Sign staging directory (you must use "--no-daemon" gradle option)
task signStaging {
  doLast {
    	ant.input(message: 'Enter PGP password:', addproperty: 'pass')

        description = 'Signs the local staging distribution.'
	fileTree("staging").visit { FileVisitDetails details -> 
		logger.lifecycle("    Signing " + details.file.path)
		ant.exec(executable: 'gpg', dir: 'staging') {
			ant.arg(line: '--batch')
			ant.arg(line: '--passphrase')
			ant.arg(line: ant.properties.pass)
	    		ant.arg(line: '--armor')
	    		ant.arg(line: '--output')
	    		ant.arg(line: details.file.name + ".asc")
	    		ant.arg(line: "--detach-sig")
	    		ant.arg(line: details.file.name)
		}

		ant.exec(executable: 'gpg', dir: 'staging', output: "staging/" + details.file.name + ".sha1") {
	    		ant.arg(line: '--print-md')
	    		ant.arg(line: 'SHA1')
	    		ant.arg(line: details.file.name)
		}

		ant.exec(executable: 'gpg', dir: 'staging', output: "staging/" + details.file.name + ".sha512") {
	    		ant.arg(line: '--print-md')
	    		ant.arg(line: 'SHA512')
	    		ant.arg(line: details.file.name)
		}
	}
    }
}



// Moves the source and binary distributions to staging.
task commitToStaging {
  doLast {
    description = 'Commits the local staging to the Apache svn staging repository.'
    getProject().exec { 
    	commandLine 'svn', 
		'import', 'staging', svnStagingPath + "/org.apache.felix.dependencymanager-" + dmRelease + "/", 
		'-m', "Staging Apache Felix Dependency Manager release " + dmRelease + ".", "--force-interactive"
    }
  }
}

// Promotes the staged distributions to release
task promoteToRelease {
  doLast {
    description = 'Moves the staging repository to the Apache release repository.'

    // Move all artifacts from the staging repo to the release repo
    new ByteArrayOutputStream().withStream { os ->
		def result = exec {
	    	executable = 'svn'
	    	args = ['list', svnStagingPath+"/org.apache.felix.dependencymanager-" + dmRelease]
	    	standardOutput = os
		}
		def outputAsString = os.toString()

		outputAsString.split("\n").each { artifact -> 
	    	logger.lifecycle("    Moving " + artifact + " to release repository ...")
	    	getProject().exec { 
				commandLine 'svn',
				'move', svnStagingPath+"/org.apache.felix.dependencymanager-" + dmRelease + "/" + artifact , 
				svnReleasePath, '-m', "Releasing Apache Felix Dependency Manager release " + dmRelease + ".", "--force-interactive"
	    	}
		}
    }

    // And remove the toplevel release path from the staging repo
    logger.lifecycle("    Removing org.apache.felix.dependencymanager-" + dmRelease + " from staging ...")    
    getProject().exec { 
    	commandLine 'svn',
		'rm', svnStagingPath+"/org.apache.felix.dependencymanager-" + dmRelease, "-m", 
		"Releasing Apache Felix Dependency Manager release " + dmRelease + "."
    }
  }
}

// Removes the staged distributions from staging
task deleteFromStaging {
  doLast {
    description = 'Cancels the staged distribution from the Apache staging repository.'
    getProject().exec { 
    	commandLine 'svn',
		'delete', svnStagingPath+"/org.apache.felix.dependencymanager-" + dmRelease + "/",
		"-m", "Removing Apache Felix Dependency Manager release " + dmRelease + " from staging."
    }
  }
}

// Clean staging directory

clean.doLast {
    new File("release/staging").deleteDir()
    new File("rat-report.xml").delete()
}

// Only clean the staging directory
task cleanStaging {
  doLast {
    description = 'Clean the local staging directory.'
    new File("release/staging").deleteDir()
    new File("release/staging-copy").deleteDir()
  }
}
