Added the Scala Bazaar archive generation Ant task. Modified the SABBUS build script to use it.
git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@5575 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
977ef82b06
commit
c5f3ec19a4
18
build.xml
18
build.xml
|
@ -63,7 +63,7 @@ PROPERTIES
|
||||||
<!-- Location of structure of the distribution properties -->
|
<!-- Location of structure of the distribution properties -->
|
||||||
<property name="dist.dir" value="${basedir}/dists"/>
|
<property name="dist.dir" value="${basedir}/dists"/>
|
||||||
<property name="dist.latest.dir" value="${dist.dir}/latest"/>
|
<property name="dist.latest.dir" value="${dist.dir}/latest"/>
|
||||||
<property name="dist.name" value="scala"/>
|
<property name="dist.name" value="scala-core"/>
|
||||||
<property name="lib.jar.name" value="${dist.name}-${lib.dir.name}.jar"/>
|
<property name="lib.jar.name" value="${dist.name}-${lib.dir.name}.jar"/>
|
||||||
<property name="comp.jar.name" value="${dist.name}-${comp.dir.name}.jar"/>
|
<property name="comp.jar.name" value="${dist.name}-${comp.dir.name}.jar"/>
|
||||||
<property name="scala.exec.name" value="${dist.name}2"/>
|
<property name="scala.exec.name" value="${dist.name}2"/>
|
||||||
|
@ -237,6 +237,9 @@ INITIALISATION
|
||||||
<taskdef name="quicktool"
|
<taskdef name="quicktool"
|
||||||
classname="scala.tools.ant.ScalaTool"
|
classname="scala.tools.ant.ScalaTool"
|
||||||
classpathref="quick.classpath"/>
|
classpathref="quick.classpath"/>
|
||||||
|
<taskdef name="quicksbaz"
|
||||||
|
classname="scala.tools.ant.ScalaBazaar"
|
||||||
|
classpathref="quick.classpath"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- ===========================================================================
|
<!-- ===========================================================================
|
||||||
|
@ -604,7 +607,7 @@ GENERATES A DISTRIBUTION
|
||||||
<mkdir dir="${dist.current.dir}/bin"/>
|
<mkdir dir="${dist.current.dir}/bin"/>
|
||||||
<!-- Build executable files -->
|
<!-- Build executable files -->
|
||||||
<mkdir dir="${dist.current.dir}/bin"/>
|
<mkdir dir="${dist.current.dir}/bin"/>
|
||||||
<lockertool file="${dist.current.dir}/bin/${scalac.exec.name}"
|
<quicktool file="${dist.current.dir}/bin/${scalac.exec.name}"
|
||||||
genericFile="${dist.current.dir}/bin/${scala.exec.name}"
|
genericFile="${dist.current.dir}/bin/${scala.exec.name}"
|
||||||
name="Scala compiler"
|
name="Scala compiler"
|
||||||
class="scala.tools.nsc.Main"
|
class="scala.tools.nsc.Main"
|
||||||
|
@ -624,7 +627,16 @@ GENERATES A DISTRIBUTION
|
||||||
overwrite="yes"
|
overwrite="yes"
|
||||||
failonerror="no"/>
|
failonerror="no"/>
|
||||||
</then>
|
</then>
|
||||||
</if>
|
</if>
|
||||||
|
<quicksbaz file="${dist.dir}/${dist.name}-${version.number}.sbp"
|
||||||
|
adfile="${dist.dir}/${dist.name}-${version.number}.advert"
|
||||||
|
name="${dist.name}"
|
||||||
|
version="${version.number}"
|
||||||
|
desc="The Scala core library and compiler.">
|
||||||
|
<libset dir="${dist.current.dir}/lib" includes="*.jar"/>
|
||||||
|
<binset dir="${dist.current.dir}/bin" includes="*"/>
|
||||||
|
<manset dir="${docs.dir}/man" includes="**"/>
|
||||||
|
</quicksbaz>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- ===========================================================================
|
<!-- ===========================================================================
|
||||||
|
|
|
@ -0,0 +1,283 @@
|
||||||
|
/* __ ______________ *\
|
||||||
|
** / |/ / ____/ ____/ **
|
||||||
|
** / | | /___ / /___ **
|
||||||
|
** /_/|__/_____/_____/ Copyright 2005-2006 LAMP/EPFL **
|
||||||
|
**
|
||||||
|
** $Id: ScalaTool.scala 5482 2006-01-09 19:22:46 +0100 (Mon, 09 Jan 2006) dubochet $
|
||||||
|
\* */
|
||||||
|
|
||||||
|
package scala.tools.ant {
|
||||||
|
|
||||||
|
import scala.collection.Map
|
||||||
|
import scala.collection.mutable.HashMap
|
||||||
|
import java.io.{File, FileInputStream, FileOutputStream,
|
||||||
|
FileWriter, StringReader}
|
||||||
|
import java.net.{URL, URLClassLoader}
|
||||||
|
import java.util.{ArrayList, Vector}
|
||||||
|
import java.util.zip.{ZipOutputStream, ZipEntry}
|
||||||
|
|
||||||
|
import org.apache.tools.ant.{AntClassLoader, BuildException,
|
||||||
|
DirectoryScanner, Project}
|
||||||
|
import org.apache.tools.ant.taskdefs.MatchingTask
|
||||||
|
import org.apache.tools.ant.types.Path
|
||||||
|
import org.apache.tools.ant.util.{FileUtils, MergingMapper,
|
||||||
|
SourceFileScanner}
|
||||||
|
import org.apache.tools.ant.types.{EnumeratedAttribute, Reference, FileSet}
|
||||||
|
|
||||||
|
/** An Ant task that generates a SH or BAT script to execute a Scala program.
|
||||||
|
* This task can take the following parameters as attributes:<ul>
|
||||||
|
* <li>file (mandatory),</li>
|
||||||
|
* <li>adfile,</li>
|
||||||
|
* <li>name (mandatory),</li>
|
||||||
|
* <li>version (mandatory),</li>
|
||||||
|
* <li>depends,</li>
|
||||||
|
* <li>description.</li></ul>
|
||||||
|
*
|
||||||
|
* @author Gilles Dubochet */
|
||||||
|
class ScalaBazaar extends MatchingTask {
|
||||||
|
|
||||||
|
/** The unique Ant file utilities instance to use in this task. */
|
||||||
|
private val fileUtils = FileUtils.newFileUtils()
|
||||||
|
|
||||||
|
/******************************************************************************\
|
||||||
|
** Ant user-properties **
|
||||||
|
\******************************************************************************/
|
||||||
|
|
||||||
|
/** The path to the archive file. */
|
||||||
|
private var file: Option[File] = None
|
||||||
|
/** The optional path to the advertisement file. */
|
||||||
|
private var adfile: Option[File] = None
|
||||||
|
/** The name of the package. */
|
||||||
|
private var name: Option[String] = None
|
||||||
|
/** The version number of the package. */
|
||||||
|
private var version: Option[String] = None
|
||||||
|
/** An (optional) list of names of the packages it depends of. */
|
||||||
|
private var depends: List[String] = Nil
|
||||||
|
/** An (optional) description of this package. */
|
||||||
|
private var desc: Option[String] = None
|
||||||
|
/** An (optional) description of this package. */
|
||||||
|
private object fileSetsMap extends Map[String, List[FileSet]] {
|
||||||
|
private var content = new HashMap[String, List[FileSet]]()
|
||||||
|
def get(key: String): Option[List[FileSet]] = content.get(key)
|
||||||
|
def size: Int = content.size
|
||||||
|
def update(key: String, value: FileSet) = {
|
||||||
|
if (content.contains(key) && content(key) != Nil)
|
||||||
|
content.update(key, value :: content(key))
|
||||||
|
else content.update(key, List(value))
|
||||||
|
}
|
||||||
|
def fileSets = elements.toList
|
||||||
|
def elements = content.elements
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************\
|
||||||
|
** Properties setters **
|
||||||
|
\******************************************************************************/
|
||||||
|
|
||||||
|
/** Sets the file attribute. Used by Ant.
|
||||||
|
* @param input The value of <code>file</code>. */
|
||||||
|
def setFile(input: File) =
|
||||||
|
file = Some(input)
|
||||||
|
|
||||||
|
/** Sets the advertisement file attribute. Used by Ant.
|
||||||
|
* @param input The value of <code>adfile</code>. */
|
||||||
|
def setAdfile(input: File) =
|
||||||
|
adfile = Some(input)
|
||||||
|
|
||||||
|
/** Sets the name attribute of this package. Used by Ant.
|
||||||
|
* @param input The value of <code>name</code>. */
|
||||||
|
def setName(input: String) =
|
||||||
|
name = Some(input)
|
||||||
|
|
||||||
|
/** Sets the version attribute of this package. Used by Ant.
|
||||||
|
* @param input The value of <code>version</code>. */
|
||||||
|
def setVersion(input: String) =
|
||||||
|
version = Some(input)
|
||||||
|
|
||||||
|
/** Sets the depends attribute. Used by Ant.
|
||||||
|
* @param input The value for <code>depends</code>. */
|
||||||
|
def setDepends(input: String) = {
|
||||||
|
depends = List.fromArray(input.split(",")).flatMap(s: String => {
|
||||||
|
val st = s.trim()
|
||||||
|
(if (st != "") List(st) else Nil)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the description attribute of this package. Used by Ant.
|
||||||
|
* @param input The value of <code>description</code>. */
|
||||||
|
def setDesc(input: String) =
|
||||||
|
desc = Some(input)
|
||||||
|
|
||||||
|
def addConfiguredLibset(input: FileSet) =
|
||||||
|
fileSetsMap.update("lib", input)
|
||||||
|
|
||||||
|
def addConfiguredBinset(input: FileSet) =
|
||||||
|
fileSetsMap.update("bin", input)
|
||||||
|
|
||||||
|
def addConfiguredSrcset(input: FileSet) =
|
||||||
|
fileSetsMap.update("src", input)
|
||||||
|
|
||||||
|
def addConfiguredManset(input: FileSet) =
|
||||||
|
fileSetsMap.update("man", input)
|
||||||
|
|
||||||
|
def addConfiguredDocset(input: FileSet) =
|
||||||
|
fileSetsMap.update("doc/" + getName, input)
|
||||||
|
|
||||||
|
def addConfiguredMiscset(input: FileSet) =
|
||||||
|
fileSetsMap.update("misc/" + getName, input)
|
||||||
|
|
||||||
|
/******************************************************************************\
|
||||||
|
** Properties getters **
|
||||||
|
\******************************************************************************/
|
||||||
|
|
||||||
|
/** Gets the value of the file attribute in a Scala-friendly form.
|
||||||
|
* @returns The file as a file. */
|
||||||
|
private def getName: String =
|
||||||
|
if (name.isEmpty) error("Name attribute must be defined first.")
|
||||||
|
else name.get
|
||||||
|
|
||||||
|
/** Gets the value of the file attribute in a Scala-friendly form.
|
||||||
|
* @returns The file as a file. */
|
||||||
|
private def getFile: File =
|
||||||
|
if (file.isEmpty) error("Member 'file' is empty.")
|
||||||
|
else getProject().resolveFile(file.get.toString())
|
||||||
|
|
||||||
|
/** Gets the value of the adfile attribute in a Scala-friendly form.
|
||||||
|
* @returns The adfile as a file. */
|
||||||
|
private def getAdfile: File =
|
||||||
|
if (adfile.isEmpty) error("Member 'adfile' is empty.")
|
||||||
|
else getProject().resolveFile(adfile.get.toString())
|
||||||
|
|
||||||
|
/******************************************************************************\
|
||||||
|
** Compilation and support methods **
|
||||||
|
\******************************************************************************/
|
||||||
|
/** Transforms a string name into a file relative to the provided base
|
||||||
|
* directory.
|
||||||
|
* @param base A file pointing to the location relative to which the name
|
||||||
|
* will be resolved.
|
||||||
|
* @param name A relative or absolute path to the file as a string.
|
||||||
|
* @return A file created from the name and the base file. */
|
||||||
|
private def nameToFile(base: File)(name: String): File =
|
||||||
|
existing(fileUtils.resolveFile(base, name))
|
||||||
|
|
||||||
|
/** Transforms a string name into a file relative to the build root
|
||||||
|
* directory.
|
||||||
|
* @param name A relative or absolute path to the file as a string.
|
||||||
|
* @return A file created from the name. */
|
||||||
|
private def nameToFile(name: String): File =
|
||||||
|
existing(getProject().resolveFile(name))
|
||||||
|
|
||||||
|
/** Tests if a file exists and prints a warning in case it doesn't. Always
|
||||||
|
* returns the file, even if it doesn't exist.
|
||||||
|
* @param file A file to test for existance.
|
||||||
|
* @return The same file. */
|
||||||
|
private def existing(file: File): File = {
|
||||||
|
if (!file.exists())
|
||||||
|
log("Element '" + file.toString() + "' does not exist.",
|
||||||
|
Project.MSG_WARN)
|
||||||
|
file
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Generates a build error. Error location will be the current task in the
|
||||||
|
* ant file.
|
||||||
|
* @param message A message describing the error.
|
||||||
|
* @throws BuildException A build error exception thrown in every case. */
|
||||||
|
private def error(message: String): All =
|
||||||
|
throw new BuildException(message, getLocation())
|
||||||
|
|
||||||
|
private def writeFile(file: File, content: String) =
|
||||||
|
if (file.exists() && !file.canWrite())
|
||||||
|
error("File " + file + " is not writable")
|
||||||
|
else {
|
||||||
|
val writer = new FileWriter(file, false)
|
||||||
|
writer.write(content)
|
||||||
|
writer.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************\
|
||||||
|
** The big execute method **
|
||||||
|
\******************************************************************************/
|
||||||
|
|
||||||
|
/** Performs the compilation. */
|
||||||
|
override def execute() = {
|
||||||
|
// Tests if all mandatory attributes are set and valid.
|
||||||
|
if (file.isEmpty) error("Attribute 'file' is not set.")
|
||||||
|
if (name.isEmpty) error("Attribute 'name' is not set.")
|
||||||
|
if (version.isEmpty) error("Attribute 'version' is not set.")
|
||||||
|
|
||||||
|
val pack = {
|
||||||
|
<package>
|
||||||
|
<name>{name.get}</name>
|
||||||
|
<version>{version.get}</version>{
|
||||||
|
if (!depends.isEmpty)
|
||||||
|
<depends>{
|
||||||
|
for (val depend <- depends) yield
|
||||||
|
<name>{depend}</name>
|
||||||
|
}</depends>
|
||||||
|
else Nil
|
||||||
|
}{
|
||||||
|
if (!desc.isEmpty)
|
||||||
|
<description>{desc.get}</description>
|
||||||
|
else Nil
|
||||||
|
}
|
||||||
|
</package>
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the advert file
|
||||||
|
val advert = {
|
||||||
|
<availablepackage>
|
||||||
|
{pack}
|
||||||
|
<link></link>
|
||||||
|
</availablepackage>
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!adfile.isEmpty)
|
||||||
|
writeFile(getAdfile, advert.toString())
|
||||||
|
|
||||||
|
// Checks for new files and creates the ZIP
|
||||||
|
|
||||||
|
val mapper = new MergingMapper()
|
||||||
|
mapper.setTo(getFile.getName)
|
||||||
|
val zipContent =
|
||||||
|
for {
|
||||||
|
val Pair(folder, fileSets) <- fileSetsMap.fileSets
|
||||||
|
val fileSet <- fileSets
|
||||||
|
val file <- {
|
||||||
|
List.fromArray(new SourceFileScanner(this).restrict(
|
||||||
|
fileSet.getDirectoryScanner(getProject).getIncludedFiles,
|
||||||
|
fileSet.getDir(getProject),
|
||||||
|
getFile.getParentFile,
|
||||||
|
mapper
|
||||||
|
))
|
||||||
|
}
|
||||||
|
} yield Triple(folder, fileSet.getDir(getProject), file)
|
||||||
|
if (!zipContent.isEmpty) {
|
||||||
|
val zip = new ZipOutputStream(new FileOutputStream(file.get, false))
|
||||||
|
for (val Triple(destFolder, srcFolder, file) <- zipContent) {
|
||||||
|
log(file, Project.MSG_DEBUG)
|
||||||
|
zip.putNextEntry(new ZipEntry(destFolder + "/" + file))
|
||||||
|
val input = new FileInputStream(nameToFile(srcFolder)(file))
|
||||||
|
var byte = input.read()
|
||||||
|
while (byte != -1) {
|
||||||
|
zip.write (byte)
|
||||||
|
byte = input.read()
|
||||||
|
}
|
||||||
|
zip.closeEntry()
|
||||||
|
input.close()
|
||||||
|
}
|
||||||
|
zip.putNextEntry(new ZipEntry("meta/description"))
|
||||||
|
val packInput = new StringReader(pack.toString())
|
||||||
|
var byte = packInput.read()
|
||||||
|
while (byte != -1) {
|
||||||
|
zip.write (byte)
|
||||||
|
byte = packInput.read()
|
||||||
|
}
|
||||||
|
zip.closeEntry()
|
||||||
|
packInput.close()
|
||||||
|
zip.close
|
||||||
|
} else log("No files added to SBaz archive.", Project.MSG_VERBOSE)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue