sbt/launch/ProjectProperties.scala

147 lines
5.5 KiB
Scala

/* sbt -- Simple Build Tool
* Copyright 2009 Mark Harrah
*/
package xsbt.boot
/*
Project does not exist, create new project? [y/N/s] y
Name:
Organization []:
Version [1.0]:
Scala version [2.7.5]:
sbt version [0.7]:
*/
import java.io.File
/** Constants related to reading/writing the build.properties file in a project.
* See BootConfiguration for general constants used by the loader. */
private object ProjectProperties
{
/** The properties key for storing the name of the project.*/
val NameKey = "project.name"
/** The properties key for storing the organization of the project.*/
val OrganizationKey = "project.organization"
/** The properties key for storing the version of the project.*/
val VersionKey = "project.version"
/** The properties key for storing the version of Scala used with the project.*/
val ScalaVersionKey = "scala.version"
/** The properties key for storing the version of sbt used to build the project.*/
val SbtVersionKey = "sbt.version"
/** The properties key to communicate to the main component of sbt that the project
* should be initialized after being loaded, typically by creating a default directory structure.*/
val InitializeProjectKey = "project.initialize"
/** The properties key that configures the project to be flattened a bit for use by quick throwaway projects.*/
val ScratchKey = "project.scratch"
/** The label used when prompting for the name of the user's project.*/
val NameLabel = "Name"
/** The label used when prompting for the organization of the user's project.*/
val OrganizationLabel = "Organization"
/** The label used when prompting for the version of the user's project.*/
val VersionLabel = "Version"
/** The label used when prompting for the version of Scala to use for the user's project.*/
val ScalaVersionLabel = "Scala version"
/** The label used when prompting for the version of sbt to use for the user's project.*/
val SbtVersionLabel = "sbt version"
/** The default organization of the new user project when the user doesn't explicitly specify one when prompted.*/
val DefaultOrganization = ""
/** The default version of the new user project when the user doesn't explicitly specify a version when prompted.*/
val DefaultVersion = "1.0"
/** The default version of sbt when the user doesn't explicitly specify a version when prompted.*/
val DefaultSbtVersion = "0.7"
/** The default version of Scala when the user doesn't explicitly specify a version when prompted.*/
val DefaultScalaVersion = "2.7.5"
// sets up the project properties for a throwaway project (flattens src and lib to the root project directory)
def scratch(file: File)
{
withProperties(file) { properties =>
for( (key, _, default, _) <- propertyDefinitions(false))
properties(key) = default.getOrElse("scratch")
properties(ScratchKey) = true.toString
}
}
// returns (scala version, sbt version)
def apply(file: File, setInitializeProject: Boolean): (String, String) = applyImpl(file, setInitializeProject, Nil)
def forcePrompt(file: File, propertyKeys: String*) = applyImpl(file, false, propertyKeys)
private def applyImpl(file: File, setInitializeProject: Boolean, propertyKeys: Iterable[String]): (String, String) =
{
val organizationOptional = file.exists
withProperties(file) { properties =>
properties -= propertyKeys
prompt(properties, organizationOptional)
if(setInitializeProject)
properties(InitializeProjectKey) = true.toString
}
}
// (key, label, defaultValue, promptRequired)
private def propertyDefinitions(organizationOptional: Boolean) =
(NameKey, NameLabel, None, true) ::
(OrganizationKey, OrganizationLabel, Some(DefaultOrganization), !organizationOptional) ::
(VersionKey, VersionLabel, Some(DefaultVersion), true) ::
(ScalaVersionKey, ScalaVersionLabel, Some(DefaultScalaVersion), true) ::
(SbtVersionKey, SbtVersionLabel, Some(DefaultSbtVersion), true) ::
Nil
private def prompt(fill: ProjectProperties, organizationOptional: Boolean)
{
for( (key, label, default, promptRequired) <- propertyDefinitions(organizationOptional))
{
val value = fill(key)
if(value == null && promptRequired)
fill(key) = readLine(label, default)
}
}
private def withProperties(file: File)(f: ProjectProperties => Unit) =
{
val properties = new ProjectProperties(file)
f(properties)
properties.save
(properties(ScalaVersionKey), properties(SbtVersionKey))
}
private def readLine(label: String, default: Option[String]): String =
{
val prompt =
default match
{
case Some(d) => "%s [%s]: ".format(label, d)
case None => "%s: ".format(label)
}
SimpleReader.readLine(prompt) orElse default match
{
case Some(line) => line
case None => throw new BootException("Project not loaded: " + label + " not specified.")
}
}
}
import java.io.{FileInputStream, FileOutputStream}
import java.util.Properties
private class ProjectProperties(file: File) extends NotNull
{
private[this] var modified = false
private[this] val properties = new Properties
if(file.exists)
{
val in = new FileInputStream(file)
try { properties.load(in) } finally { in.close() }
}
def update(key: String, value: String)
{
modified = true
properties.setProperty(key, value)
}
def apply(key: String) = properties.getProperty(key)
def save()
{
if(modified)
{
file.getParentFile.mkdirs()
val out = new FileOutputStream(file)
try { properties.store(out, "Project Properties") } finally { out.close() }
modified = false
}
}
def -= (keys: Iterable[String]) { for(key <- keys) properties.remove(key) }
}