From b16b0adc0f73c751030622cb97815b53b6d56eee Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Tue, 21 Sep 2010 22:10:21 -0400 Subject: [PATCH] add sbt package object for use from project definitions only- it is a top-level project add dependency and repository builders cross-versioning will be a post-construction transformation --- ivy/IvyInterface.scala | 19 ++++------- main/DependencyBuilders.scala | 62 +++++++++++++++++++++++++++++++++++ main/StringUtilities.scala | 14 ++++++++ project/build/XSbt.scala | 4 ++- sbt/package.scala | 7 ++++ 5 files changed, 92 insertions(+), 14 deletions(-) create mode 100644 main/DependencyBuilders.scala create mode 100644 main/StringUtilities.scala create mode 100644 sbt/package.scala diff --git a/ivy/IvyInterface.scala b/ivy/IvyInterface.scala index 2e4038074..5bc230b5f 100644 --- a/ivy/IvyInterface.scala +++ b/ivy/IvyInterface.scala @@ -9,17 +9,18 @@ import scala.xml.NodeSeq import org.apache.ivy.plugins.resolver.{DependencyResolver, IBiblioResolver} import org.apache.ivy.util.url.CredentialsStore -final case class ModuleID(organization: String, name: String, revision: String, configurations: Option[String], isChanging: Boolean, isTransitive: Boolean, explicitArtifacts: Seq[Artifact], extraAttributes: Map[String,String]) extends NotNull +final case class ModuleID(organization: String, name: String, revision: String, configurations: Option[String] = None, isChanging: Boolean = false, isTransitive: Boolean = true, explicitArtifacts: Seq[Artifact] = Nil, extraAttributes: Map[String,String] = Map.empty, crossVersion: Boolean = false) { override def toString = organization + ":" + name + ":" + revision // () required for chaining + def cross(v: Boolean) = copy(crossVersion = v) def notTransitive() = intransitive() - def intransitive() = ModuleID(organization, name, revision, configurations, isChanging, false, explicitArtifacts, extraAttributes) - def changing() = ModuleID(organization, name, revision, configurations, true, isTransitive, explicitArtifacts, extraAttributes) + def intransitive() = copy(isTransitive = false) + def changing() = copy(isChanging = true) def from(url: String) = artifacts(Artifact(name, new URL(url))) def classifier(c: String) = artifacts(Artifact(name, c)) - def artifacts(newArtifacts: Artifact*) = ModuleID(organization, name, revision, configurations, isChanging, isTransitive, newArtifacts ++ explicitArtifacts, extraAttributes) - def extra(attributes: (String,String)*) = ModuleID(organization, name, revision, configurations, isChanging, isTransitive, explicitArtifacts, extraAttributes ++ ModuleID.checkE(attributes)) + def artifacts(newArtifacts: Artifact*) = copy(explicitArtifacts = newArtifacts ++ this.explicitArtifacts) + def extra(attributes: (String,String)*) = copy(extraAttributes = this.extraAttributes ++ ModuleID.checkE(attributes)) def sources() = artifacts(Artifact.sources(name)) def javadoc() = artifacts(Artifact.javadoc(name)) def withSources() = jarIfEmpty.sources() @@ -29,14 +30,6 @@ final case class ModuleID(organization: String, name: String, revision: String, } object ModuleID { - def apply(organization: String, name: String, revision: String): ModuleID = ModuleID(organization, name, revision, None) - def apply(organization: String, name: String, revision: String, configurations: Option[String]): ModuleID = - ModuleID(organization, name, revision, configurations, false, true) - def apply(organization: String, name: String, revision: String, configurations: Option[String], isChanging: Boolean, isTransitive: Boolean): ModuleID = - ModuleID(organization, name, revision, configurations, isChanging, isTransitive, Nil) - def apply(organization: String, name: String, revision: String, configurations: Option[String], isChanging: Boolean, isTransitive: Boolean, explicitArtifacts: Seq[Artifact]): ModuleID = - ModuleID(organization, name, revision, configurations, isChanging, isTransitive, explicitArtifacts, Map.empty) - def checkE(attributes: Seq[(String, String)]) = for ( (key, value) <- attributes) yield if(key.startsWith("e:")) (key, value) else ("e:" + key, value) diff --git a/main/DependencyBuilders.scala b/main/DependencyBuilders.scala new file mode 100644 index 000000000..00168d7c1 --- /dev/null +++ b/main/DependencyBuilders.scala @@ -0,0 +1,62 @@ +/* sbt -- Simple Build Tool + * Copyright 2009,2010 Mark Harrah + */ +package sbt +package impl + + import StringUtilities.{appendable,nonEmpty} + +trait DependencyBuilders +{ + final implicit def toGroupID(groupID: String): GroupID = + { + nonEmpty(groupID, "Group ID") + new GroupID(groupID) + } + final implicit def toRepositoryName(name: String): RepositoryName = + { + nonEmpty(name, "Repository name") + new RepositoryName(name) + } + final implicit def moduleIDConfigurable(m: ModuleID): ModuleIDConfigurable = + { + require(m.configurations.isEmpty, "Configurations already specified for module " + m) + new ModuleIDConfigurable(m) + } +} + +final class GroupID private[sbt] (groupID: String) +{ + def % (artifactID: String) = groupArtifact(artifactID, false) + def %% (artifactID: String) = groupArtifact(artifactID, true) + private def groupArtifact(artifactID: String, cross: Boolean) = + { + nonEmpty(artifactID, "Artifact ID") + new GroupArtifactID(groupID, artifactID, cross) + } +} +final class GroupArtifactID private[sbt] (groupID: String, artifactID: String, crossVersion: Boolean) +{ + def % (revision: String): ModuleID = + { + nonEmpty(revision, "Revision") + ModuleID(groupID, artifactID, revision).cross(crossVersion) + } +} +final class ModuleIDConfigurable private[sbt] (moduleID: ModuleID) +{ + def % (configurations: String): ModuleID = + { + nonEmpty(configurations, "Configurations") + val c = configurations + moduleID.copy(configurations = Some(c)) + } +} +final class RepositoryName private[sbt] (name: String) +{ + def at (location: String) = + { + nonEmpty(location, "Repository location") + new MavenRepository(name, location) + } +} diff --git a/main/StringUtilities.scala b/main/StringUtilities.scala new file mode 100644 index 000000000..3a0075bb4 --- /dev/null +++ b/main/StringUtilities.scala @@ -0,0 +1,14 @@ +/* sbt -- Simple Build Tool + * Copyright 2009 Mark Harrah + */ +package sbt + +object StringUtilities +{ + def normalize(s: String) = s.toLowerCase.replaceAll("""\s+""", "-") + def nonEmpty(s: String, label: String) + { + require(s.trim.length > 0, label + " cannot be empty.") + } + def appendable(s: String) = if(s.isEmpty) "" else "_" + s +} diff --git a/project/build/XSbt.scala b/project/build/XSbt.scala index f1573c13f..cfc55489b 100644 --- a/project/build/XSbt.scala +++ b/project/build/XSbt.scala @@ -46,8 +46,10 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths classfileSub, classpathSub, compilePersistSub, compilerSub, compileIncrementalSub, interfaceSub, ivySub, launchInterfaceSub, logSub, discoverySub, processSub) val stdTaskSub = testedBase(tasksPath / "standard", "Task System", taskSub, collectionSub, logSub, ioSub, processSub) - val altCompilerSub = project("main", "Alternate Compiler Test", (i: ProjectInfo) => new Base(i) { override def normalizedName = "sbt" }, // temporary + val mainSub = baseProject("main", "Main", buildSub, compileIncrementalSub, compilerSub, completeSub, discoverySub, ioSub, logSub, processSub, taskSub, stdTaskSub, runSub, trackingSub) + val sbtSub = project(sbtPath, "Simple Build Tool", (i: ProjectInfo) => new Base(i) { override def normalizedName = "sbt" }, + mainSub) // technically, we need a dependency on all of mainSub's dependencies, but we don't do that since this is strictly an integration project /** following modules are not updated for 2.8 or 0.9 */ /*val testSub = project("scripted", "Test", new TestProject(_), ioSub) diff --git a/sbt/package.scala b/sbt/package.scala new file mode 100644 index 000000000..8c128211a --- /dev/null +++ b/sbt/package.scala @@ -0,0 +1,7 @@ +/* sbt -- Simple Build Tool + * Copyright 2010 Mark Harrah + */ +package object sbt extends sbt.std.TaskExtra with sbt.Types with sbt.ProcessExtra with sbt.impl.DependencyBuilders +{ + type File = java.io.File +}