diff --git a/ivy/ArtifactName.scala b/ivy/ArtifactName.scala deleted file mode 100644 index beb2b5cac..000000000 --- a/ivy/ArtifactName.scala +++ /dev/null @@ -1,17 +0,0 @@ -/* sbt -- Simple Build Tool - * Copyright 2011 Mark Harrah - */ -package sbt - -final case class ArtifactName(base: String, version: String, config: String, tpe: String, ext: String, cross: String) -object ArtifactName -{ - def show(name: ArtifactName) = - { - import name._ - val confStr = if(config.isEmpty || config == "compile") "" else "-" + config - val tpeStr = if(tpe.isEmpty) "" else "-" + tpe - val addCross = if(cross.isEmpty) "" else "_" + cross - base + addCross + "-" + version + confStr + tpeStr + "." + ext - } -} \ No newline at end of file diff --git a/ivy/Ivy.scala b/ivy/Ivy.scala index 22d52a6a6..261706f20 100644 --- a/ivy/Ivy.scala +++ b/ivy/Ivy.scala @@ -12,7 +12,7 @@ import java.util.{Collection, Collections} import org.apache.ivy.{core, plugins, util, Ivy} import core.IvyPatternHelper import core.cache.{CacheMetadataOptions, DefaultRepositoryCacheManager} -import core.module.descriptor.{DefaultArtifact, DefaultDependencyArtifactDescriptor, MDArtifact} +import core.module.descriptor.{Artifact => IArtifact, DefaultArtifact, DefaultDependencyArtifactDescriptor, MDArtifact} import core.module.descriptor.{DefaultDependencyDescriptor, DefaultModuleDescriptor, DependencyDescriptor, ModuleDescriptor} import core.module.id.{ArtifactId,ModuleId, ModuleRevisionId} import core.resolve.IvyNode @@ -290,7 +290,7 @@ private object IvySbt private def toIvyArtifact(moduleID: ModuleDescriptor, a: Artifact, configurations: Iterable[String]): MDArtifact = { - val artifact = new MDArtifact(moduleID, a.name, a.`type`, a.extension, null, extra(a)) + val artifact = new MDArtifact(moduleID, a.name, a.`type`, a.extension, null, extra(a, false)) configurations.foreach(artifact.addConfiguration) artifact } @@ -301,7 +301,7 @@ private object IvySbt } private[sbt] def javaMap(m: Map[String,String], unqualify: Boolean = false) = { - val map = m map { case (k, v) => (k.stripPrefix("e:"), v) } + val map = if(unqualify) m map { case (k, v) => (k.stripPrefix("e:"), v) } else m if(map.isEmpty) null else scala.collection.JavaConversions.asJavaMap(map) } @@ -372,10 +372,14 @@ private object IvySbt } } /** This method is used to add inline artifacts to the provided module. */ - def addArtifacts(moduleID: DefaultModuleDescriptor, artifacts: Iterable[Artifact]) + def addArtifacts(moduleID: DefaultModuleDescriptor, artifacts: Iterable[Artifact]): Unit = + for(art <- mapArtifacts(moduleID, artifacts.toSeq); c <- art.getConfigurations) + moduleID.addArtifact(c, art) + + def mapArtifacts(moduleID: ModuleDescriptor, artifacts: Seq[Artifact]): Seq[IArtifact] = { lazy val allConfigurations = moduleID.getPublicConfigurationsNames - for(artifact <- artifacts) + for(artifact <- artifacts) yield { val configurationStrings: Iterable[String] = { @@ -385,10 +389,10 @@ private object IvySbt else artifactConfigurations.map(_.name) } - val ivyArtifact = toIvyArtifact(moduleID, artifact, configurationStrings) - configurationStrings.foreach(configuration => moduleID.addArtifact(configuration, ivyArtifact)) + toIvyArtifact(moduleID, artifact, configurationStrings) } } + /** This code converts the given ModuleDescriptor to a DefaultModuleDescriptor by casting or generating an error. * Ivy 2.0.0 always produces a DefaultModuleDescriptor. */ private def toDefaultModuleDescriptor(md: ModuleDescriptor) = diff --git a/ivy/IvyActions.scala b/ivy/IvyActions.scala index a8ede1d3c..e3105e254 100644 --- a/ivy/IvyActions.scala +++ b/ivy/IvyActions.scala @@ -11,7 +11,7 @@ import core.cache.DefaultRepositoryCacheManager import core.{IvyPatternHelper,LogOptions} import core.deliver.DeliverOptions import core.install.InstallOptions -import core.module.descriptor.{DefaultArtifact, DefaultDependencyArtifactDescriptor, MDArtifact} +import core.module.descriptor.{Artifact => IArtifact, DefaultArtifact, DefaultDependencyArtifactDescriptor, MDArtifact} import core.module.descriptor.{DefaultDependencyDescriptor, DefaultModuleDescriptor, DependencyDescriptor, ModuleDescriptor} import core.module.id.{ArtifactId,ModuleId, ModuleRevisionId} import core.publish.PublishOptions @@ -19,9 +19,10 @@ import core.report.{ArtifactDownloadReport,ResolveReport} import core.resolve.ResolveOptions import core.retrieve.RetrieveOptions import plugins.parser.m2.{PomModuleDescriptorParser,PomModuleDescriptorWriter} +import plugins.resolver.DependencyResolver -final class PublishPatterns(val deliverIvyPattern: String, val srcArtifactPatterns: Seq[String], val publishIvy: Boolean) -final class PublishConfiguration(val patterns: PublishPatterns, val status: String, val resolverName: String, val configurations: Option[Seq[Configuration]], val logging: UpdateLogging.Value) +final class DeliverConfiguration(val deliverIvyPattern: String, val status: String, val configurations: Option[Seq[Configuration]], val logging: UpdateLogging.Value) +final class PublishConfiguration(val ivyFile: Option[File], val resolverName: String, val artifacts: Map[Artifact, File], val logging: UpdateLogging.Value) final class UpdateConfiguration(val retrieve: Option[RetrieveConfiguration], val missingOk: Boolean, val logging: UpdateLogging.Value) final class RetrieveConfiguration(val retrieveDirectory: File, val outputPattern: String) @@ -69,34 +70,36 @@ object IvyActions } } - def deliver(module: IvySbt#Module, configuration: PublishConfiguration, log: Logger) + def deliver(module: IvySbt#Module, configuration: DeliverConfiguration, log: Logger): File = { import configuration._ - import patterns._ module.withModule(log) { case (ivy, md, default) => - resolve(logging)(ivy, md, default) // todo: set download = false for resolve val revID = md.getModuleRevisionId val options = DeliverOptions.newInstance(ivy.getSettings).setStatus(status) options.setConfs(IvySbt.getConfigurations(md, configurations)) - ivy.deliver(revID, revID.getRevision, patterns.deliverIvyPattern, options) + ivy.deliver(revID, revID.getRevision, deliverIvyPattern, options) + deliveredFile(ivy, deliverIvyPattern, md) } } + def deliveredFile(ivy: Ivy, pattern: String, md: ModuleDescriptor): File = + ivy.getSettings.resolveFile(IvyPatternHelper.substitute(pattern, md.getResolvedModuleRevisionId)) - // todo: map configurations, extra dependencies def publish(module: IvySbt#Module, configuration: PublishConfiguration, log: Logger) { import configuration._ - import patterns._ module.withModule(log) { case (ivy, md, default) => - val revID = md.getModuleRevisionId - val patterns = new java.util.ArrayList[String] - srcArtifactPatterns.foreach(pattern => patterns.add(pattern)) - val options = (new PublishOptions).setOverwrite(true) - if(publishIvy) options.setSrcIvyPattern(deliverIvyPattern) - options.setConfs(IvySbt.getConfigurations(md, configurations)) - ivy.publish(revID, patterns, resolverName, options) + val resolver = ivy.getSettings.getResolver(resolverName) + val ivyArtifact = ivyFile map { file => (MDArtifact.newIvyArtifact(md), file) } + val as = mapArtifacts(md, artifacts) ++ ivyArtifact.toList + publish(md, as, resolver, overwrite = true) } } + def mapArtifacts(module: ModuleDescriptor, artifacts: Map[Artifact, File]): Seq[(IArtifact, File)] = + { + val seqa = artifacts.keys.toSeq + val zipped = seqa zip IvySbt.mapArtifacts(module, seqa) + zipped map { case (a, ivyA) => (ivyA, artifacts(a)) } + } /** Resolves and retrieves dependencies. 'ivyConfig' is used to produce an Ivy file and configuration. * 'updateConfig' configures the actual resolution and retrieval process. */ def update(module: IvySbt#Module, configuration: UpdateConfiguration, log: Logger): UpdateReport = @@ -177,5 +180,18 @@ object IvyActions case DownloadOnly => LOG_DOWNLOAD_ONLY case Full => LOG_DEFAULT } + + def publish(module: ModuleDescriptor, artifacts: Iterable[(IArtifact, File)], resolver: DependencyResolver, overwrite: Boolean): Unit = + try { + resolver.beginPublishTransaction(module.getModuleRevisionId(), overwrite); + for( (artifact, file) <- artifacts) if(file.exists) + resolver.publish(artifact, file, overwrite) + resolver.commitPublishTransaction() + } catch { + case e => + try { resolver.abortPublishTransaction() } + finally { throw e } + } + } final class ResolveException(messages: Seq[String]) extends RuntimeException(messages.mkString("\n")) \ No newline at end of file diff --git a/ivy/IvyInterface.scala b/ivy/IvyInterface.scala index e3383766c..79e1fc4ac 100644 --- a/ivy/IvyInterface.scala +++ b/ivy/IvyInterface.scala @@ -359,6 +359,12 @@ object Artifact val base = if(i >= 0) name.substring(0, i) else name Artifact(base, extract(name, defaultType), extract(name, defaultExtension), None, Nil, Some(file.toURI.toURL)) } + def artifactName(module: ModuleID, artifact: Artifact): String = + { + import artifact._ + val classifierStr = classifier match { case None => ""; case Some(c) => "-" + c } + artifact.name + "-" + module.revision + classifierStr + "." + artifact.extension + } } final case class ModuleConfiguration(organization: String, name: String, revision: String, resolver: Resolver) object ModuleConfiguration diff --git a/main/Defaults.scala b/main/Defaults.scala index 45dc01f4a..d6468d87c 100644 --- a/main/Defaults.scala +++ b/main/Defaults.scala @@ -6,8 +6,8 @@ package sbt import Build.data import Scope.{GlobalScope, ThisScope} import compiler.Discovery - import Project.{inConfig, Initialize, inScope, inTask, ScopedKey, Setting} - import Configurations.{Compile => CompileConf, CompilerPlugin, Test => TestConf} + import Project.{inConfig, Initialize, inScope, inTask, ScopedKey, Setting, SettingsDefinition} + import Configurations.{Compile, CompilerPlugin, Test} import complete._ import std.TaskExtra._ @@ -24,27 +24,6 @@ package sbt object Defaults { - implicit def richFileSetting(s: ScopedSetting[File]): RichFileSetting = new RichFileSetting(s) - implicit def richFilesSetting(s: ScopedSetting[Seq[File]]): RichFilesSetting = new RichFilesSetting(s) - - final class RichFileSetting(s: ScopedSetting[File]) extends RichFileBase - { - def /(c: String): Initialize[File] = s { _ / c } - protected[this] def map0(f: PathFinder => PathFinder) = s(file => finder(f)(file :: Nil)) - } - final class RichFilesSetting(s: ScopedSetting[Seq[File]]) extends RichFileBase - { - def /(s: String): Initialize[Seq[File]] = map0 { _ / s } - protected[this] def map0(f: PathFinder => PathFinder) = s(finder(f)) - } - sealed abstract class RichFileBase - { - def *(filter: FileFilter): Initialize[Seq[File]] = map0 { _ * filter } - def **(filter: FileFilter): Initialize[Seq[File]] = map0 { _ ** filter } - protected[this] def map0(f: PathFinder => PathFinder): Initialize[Seq[File]] - protected[this] def finder(f: PathFinder => PathFinder): Seq[File] => Seq[File] = - in => f(in).getFiles - } def configSrcSub(key: ScopedSetting[File]): Initialize[File] = (key, configuration) { (src, conf) => src / nameForSrc(conf.name) } def nameForSrc(config: String) = if(config == "compile") "main" else config def prefix(config: String) = if(config == "compile") "" else config + "-" @@ -230,17 +209,19 @@ object Defaults ) lazy val packageBase = Seq( - jarNameSetting, + artifact <<= name(n => Artifact(n)), packageOptions in GlobalScope :== Nil, - nameToString in GlobalScope :== (ArtifactName.show _) + artifactName in GlobalScope :== ( Artifact.artifactName _ ) ) lazy val packageConfig = Seq( - jarName <<= (jarName, configuration) { (n,c) => n.copy(config = c.name) }, packageOptions in packageBin <<= (packageOptions, mainClass in packageBin) map { _ ++ _.map(Package.MainClass.apply).toList } ) ++ - packageTasks(packageBin, "", packageBinTask) ++ - packageTasks(packageSrc, "src", packageSrcTask) ++ - packageTasks(packageDoc, "doc", packageDocTask) + packageTasks(packageBin, None, packageBinTask) ++ + packageTasks(packageSrc, Some(SourceClassifier), packageSrcTask) ++ + packageTasks(packageDoc, Some(DocClassifier), packageDocTask) + + final val SourceClassifier = "sources" + final val DocClassifier = "javadoc" private[this] val allSubpaths = (dir: File) => (dir.*** --- dir) x relativeTo(dir) @@ -259,25 +240,32 @@ object Defaults (rs --- rdirs) x relativeTo(rdirs) toSeq } - def jarNameSetting = jarName <<= (moduleID, version, scalaVersion, crossPaths) { (n,v, sv, withCross) => - ArtifactName(base = n, version = v, config = "", tpe = "", ext = "jar", cross = if(withCross) sv else "") - } - def jarPathSetting = jarPath <<= (crossTarget, jarName, nameToString) { (t, n, toString) => t / toString(n) } + def artifactPathSetting = (crossTarget, projectID, artifact, artifactName) { (t, module, n, toString) => t / toString(module, n) asFile } - def packageTasks(key: TaskKey[Package.Configuration], tpeString: String, mappingsTask: Initialize[Task[Seq[(File,String)]]]) = + def pairID[A,B] = (a: A, b: B) => (a,b) + def packageTasks(key: TaskKey[File], classifier: Option[String], mappingsTask: Initialize[Task[Seq[(File,String)]]]) = inTask(key)( Seq( key in ThisScope.copy(task = Global) <<= packageTask, + packageConfiguration <<= packageConfigurationTask, mappings <<= mappingsTask, - jarType :== tpeString, - jarName <<= (jarType,jarName){ (tpe, name) => (name.copy(tpe = tpe)) }, + artifactClassifier :== classifier, + packagedArtifact <<= (artifact, key) map pairID, + artifact <<= (artifact, artifactClassifier, configuration) { (a,classifier,c) => + val cPart = if(c == Compile) Nil else c.name :: Nil + val combined = cPart ++ classifier.toList + a.copy(classifier = if(combined.isEmpty) None else Some(combined mkString "-")) + }, cacheDirectory <<= cacheDirectory / key.key.label, - jarPathSetting + artifactPath <<= artifactPathSetting )) - def packageTask: Initialize[Task[Package.Configuration]] = - (jarPath, mappings, packageOptions, cacheDirectory, streams) map { (jar, srcs, options, cacheDir, s) => - val config = new Package.Configuration(srcs, jar, options) + def packageTask: Initialize[Task[File]] = + (packageConfiguration, cacheDirectory, streams) map { (config, cacheDir, s) => Package(config, cacheDir, s.log) - config + config.jar + } + def packageConfigurationTask: Initialize[Task[Package.Configuration]] = + (mappings, artifactPath, packageOptions) map { (srcs, path, options) => + new Package.Configuration(srcs, path, options) } def selectRunMain(classes: Seq[String]): Option[String] = @@ -433,7 +421,7 @@ object Defaults lazy val testSettings = configSettings ++ testTasks lazy val itSettings = inConfig(Configurations.IntegrationTest)(testSettings) - lazy val defaultConfigs = inConfig(CompileConf)(compileSettings) ++ inConfig(TestConf)(testSettings) + lazy val defaultConfigs = inConfig(Compile)(compileSettings) ++ inConfig(Test)(testSettings) // settings that are not specific to a configuration lazy val projectBaseSettings: Seq[Setting[_]] = projectCore ++ paths ++ baseClasspaths ++ baseTasks ++ compileBase ++ disableAggregation @@ -462,18 +450,34 @@ object Classpaths (base * (filter -- excl) +++ (base / config.name).descendentsExcept(filter, excl)).getFiles } ) - def defaultPackageTasks: Seq[ScopedTask[_]] = - for(task <- Seq(packageBin, `packageSrc`, `packageDoc`); conf <- Seq(CompileConf, TestConf)) yield (task in conf) + def defaultPackageKeys = Seq(packageBin, packageSrc, packageDoc) + lazy val defaultPackages: Seq[ScopedTask[File]] = + for(task <- defaultPackageKeys; conf <- Seq(Compile, Test)) yield (task in conf) + lazy val defaultArtifactTasks: Seq[ScopedTask[File]] = makePom +: defaultPackages + + def packaged(pkgTasks: Seq[ScopedTask[File]]): Initialize[Task[Map[Artifact, File]]] = + enabledOnly(packagedArtifact.task, pkgTasks).map(_.join.map(_.toMap)) + def artifactDefs(pkgTasks: Seq[ScopedTask[File]]): Initialize[Seq[Artifact]] = + enabledOnly(artifact, pkgTasks) + + def enabledOnly[T](key: ScopedSetting[T], pkgTasks: Seq[ScopedTask[File]]): Initialize[Seq[T]] = + ( forallIn(key, pkgTasks) zipWith forallIn(publishArtifact, pkgTasks) ) ( _ zip _ collect { case (a, true) => a } ) + def forallIn[T](key: ScopedSetting[T], pkgTasks: Seq[ScopedTask[_]]): Initialize[Seq[T]] = + pkgTasks.map( pkg => key in pkg.scope in pkg ).join + +/* def addArtifact(a: Artifact, taskDef: ScopedTask[File]): SettingsDefinition = + new Project.SettingsList( Seq( artifacts += a, artifacts2 += (a, taskDef.task) ) )*/ val publishSettings: Seq[Setting[_]] = Seq( publishMavenStyle in GlobalScope :== true, - packageToPublish <<= defaultPackageTasks.dependOn, - deliverDepends <<= (publishMavenStyle, makePom.task, packageToPublish.task) { (mavenStyle, mkpom, ptp) => - if(mavenStyle) mkpom.map(_ => ()) else ptp - }, - makePom <<= (ivyModule, makePomConfiguration, packageToPublish, streams) map { (module, config, _, s) => IvyActions.makePom(module, config, s.log); config.file }, - deliver <<= deliverTask(publishConfiguration), - deliverLocal <<= deliverTask(publishLocalConfiguration), + publishArtifact in GlobalScope in Compile :== true, + publishArtifact in GlobalScope in Test:== false, + artifacts <<= artifactDefs(defaultArtifactTasks), + packagedArtifacts <<= packaged(defaultArtifactTasks), + makePom <<= (ivyModule, makePomConfiguration, streams) map { (module, config, s) => IvyActions.makePom(module, config, s.log); config.file }, + packagedArtifact in makePom <<= (artifact in makePom, makePom) map pairID, + deliver <<= deliverTask(deliverConfiguration), + deliverLocal <<= deliverTask(deliverLocalConfiguration), publish <<= publishTask(publishConfiguration, deliver), publishLocal <<= publishTask(publishLocalConfiguration, deliverLocal) ) @@ -505,13 +509,14 @@ object Classpaths ivyScala in GlobalScope <<= scalaVersion(v => Some(new IvyScala(v, Nil, false, false))), moduleConfigurations in GlobalScope :== Nil, publishTo in GlobalScope :== None, - pomName <<= (moduleID, version, scalaVersion, crossPaths) { (n,v,sv, withCross) => - ArtifactName(base = n, version = v, config = "", tpe = "", ext = "pom", cross = if(withCross) sv else "") + artifactPath in makePom <<= (crossTarget, projectID, artifact in makePom, artifactName) { + (t, module, art, toString) => t / toString(module, art) + }, + publishArtifact in makePom :== publishMavenStyle, + artifact in makePom <<= moduleID( name => Artifact(name, "pom", "pom") ), + projectID <<= (organization,moduleID,version,artifacts){ (org,module,version,as) => + ModuleID(org, module, version).cross(true).artifacts(as : _*) }, - pomFile <<= (crossTarget, pomName, nameToString) { (t, n, toString) => t / toString(n) }, - pomArtifact <<= (publishMavenStyle, moduleID)( (mavenStyle, name) => if(mavenStyle) Artifact(name, "pom", "pom") :: Nil else Nil), - artifacts <<= (pomArtifact,moduleID)( (pom,name) => Artifact(name) +: pom), - projectID <<= (organization,moduleID,version,artifacts){ (org,module,version,as) => ModuleID(org, module, version).cross(true).artifacts(as : _*) }, resolvers in GlobalScope :== Nil, projectDescriptors <<= depMap, retrievePattern in GlobalScope :== "[type]/[organisation]/[module]/[artifact](-[revision])(-[classifier]).[ext]", @@ -524,13 +529,16 @@ object Classpaths ivyConfigurations <<= (autoCompilerPlugins, thisProject) { (auto, project) => project.configurations ++ (if(auto) CompilerPlugin :: Nil else Nil) }, - moduleSettings <<= (projectID, allDependencies, ivyXML, ivyConfigurations, defaultConfiguration, ivyScala, ivyValidate) map { - (pid, deps, ivyXML, confs, defaultConf, ivyS, validate) => new InlineConfiguration(pid, deps, ivyXML, confs, defaultConf, ivyS, validate) + moduleSettings <<= moduleSettings0, + makePomConfiguration <<= (artifactPath in makePom)(file => makePomConfigurationTask(file)), + deliverLocalConfiguration <<= (crossTarget, ivyLoggingLevel) map { (outDir, level) => deliverConfig( outDir, logging = level ) }, + deliverConfiguration :== deliverLocalConfiguration, + publishConfiguration <<= (packagedArtifacts, publishTo, publishMavenStyle, deliver, ivyLoggingLevel) map { (arts, publishTo, mavenStyle, ivyFile, level) => + publishConfig(arts, if(mavenStyle) None else Some(ivyFile), resolverName = getPublishTo(publishTo).name, logging = level) + }, + publishLocalConfiguration <<= (packagedArtifacts, deliverLocal, ivyLoggingLevel) map { + (arts, ivyFile, level) => publishConfig(arts, Some(ivyFile), logging = level ) }, - makePomConfiguration <<= pomFile(file => makePomConfigurationTask(file)), - publishConfiguration <<= (crossTarget, publishTo, ivyLoggingLevel, publishMavenStyle) map { (outputDirectory, publishTo, level, mavenStyle) => - publishConfig( publishPatterns(outputDirectory, !mavenStyle), resolverName = getPublishTo(publishTo).name, logging = level) }, - publishLocalConfiguration <<= (crossTarget, ivyLoggingLevel) map { (outputDirectory, level) => publishConfig( publishPatterns(outputDirectory, true), logging = level ) }, ivySbt <<= (ivyConfiguration, credentials, streams) map { (conf, creds, s) => Credentials.register(creds, s.log) new IvySbt(conf) @@ -553,15 +561,19 @@ object Classpaths } ) - def deliverTask(config: TaskKey[PublishConfiguration]): Initialize[Task[Unit]] = - (ivyModule, config, deliverDepends, streams) map { (module, config, _, s) => IvyActions.deliver(module, config, s.log) } + def moduleSettings0: Initialize[Task[ModuleSettings]] = + (projectID, allDependencies, ivyXML, ivyConfigurations, defaultConfiguration, ivyScala, ivyValidate) map { + (pid, deps, ivyXML, confs, defaultConf, ivyS, validate) => new InlineConfiguration(pid, deps, ivyXML, confs, defaultConf, ivyS, validate) + } + def deliverTask(config: TaskKey[DeliverConfiguration]): Initialize[Task[File]] = + (ivyModule, config, update, streams) map { (module, config, _, s) => IvyActions.deliver(module, config, s.log) } def publishTask(config: TaskKey[PublishConfiguration], deliverKey: TaskKey[_]): Initialize[Task[Unit]] = - (ivyModule, config, deliverKey, streams) map { (module, config, _, s) => + (ivyModule, config, streams) map { (module, config, s) => IvyActions.publish(module, config, s.log) } import Cache._ - import CacheIvy.{classpathFormat, publishIC, updateIC, updateReportF} + import CacheIvy.{classpathFormat, /*publishIC,*/ updateIC, updateReportF} def cachedUpdate(cacheFile: File, module: IvySbt#Module, config: UpdateConfiguration, log: Logger): UpdateReport = { @@ -600,22 +612,12 @@ object Classpaths def getPublishTo(repo: Option[Resolver]): Resolver = repo getOrElse error("Repository for publishing is not specified.") - def publishConfig(patterns: PublishPatterns, resolverName: String = "local", status: String = "release", logging: UpdateLogging.Value = UpdateLogging.DownloadOnly) = - new PublishConfiguration(patterns, status, resolverName, None, logging) + def deliverConfig(outputDirectory: File, status: String = "release", logging: UpdateLogging.Value = UpdateLogging.DownloadOnly) = + new DeliverConfiguration(deliverPattern(outputDirectory), status, None, logging) + def publishConfig(artifacts: Map[Artifact, File], ivyFile: Option[File], resolverName: String = "local", logging: UpdateLogging.Value = UpdateLogging.DownloadOnly) = + new PublishConfiguration(ivyFile, resolverName, artifacts, logging) - def publishPatterns(outputPath: Path, publishIvy: Boolean = false): PublishPatterns = - { - val deliverPattern = (outputPath / "[artifact]-[revision](-[classifier]).[ext]").absolutePath - val srcArtifactPatterns: Seq[String] = - { - val pathPatterns = - (outputPath / "[artifact]-[revision]-[type](-[classifier]).[ext]") :: - (outputPath / "[artifact]-[revision](-[classifier]).[ext]") :: - Nil - pathPatterns.map(_.absolutePath) - } - new PublishPatterns(deliverPattern, srcArtifactPatterns, publishIvy) - } + def deliverPattern(outputPath: Path): String = (outputPath / "[artifact]-[revision](-[classifier]).[ext]").absolutePath def projectDependenciesTask = (thisProject, settings) map { (p, data) => diff --git a/main/Keys.scala b/main/Keys.scala index a2d528635..7f3935108 100644 --- a/main/Keys.scala +++ b/main/Keys.scala @@ -100,14 +100,16 @@ object Keys // package keys - val packageBin = TaskKey[Package.Configuration]("package") - val packageDoc = TaskKey[Package.Configuration]("package-doc") - val packageSrc = TaskKey[Package.Configuration]("package-src") + val packageBin = TaskKey[File]("package") + val packageDoc = TaskKey[File]("package-doc") + val packageSrc = TaskKey[File]("package-src") + val packageOptions = TaskKey[Seq[PackageOption]]("package-options") - val jarPath = SettingKey[File]("jar-path") - val jarName = SettingKey[ArtifactName]("jar-name") - val jarType = SettingKey[String]("jar-type") - val nameToString = SettingKey[ArtifactName => String]("name-to-string") + val packageConfiguration = TaskKey[Package.Configuration]("package-configuration") + val artifactPath = SettingKey[File]("artifact-path") + val artifact = SettingKey[Artifact]("artifact") + val artifactClassifier = SettingKey[Option[String]]("artifact-classifier") + val artifactName = SettingKey[(ModuleID, Artifact) => String]("artifact-name") val mappings = TaskKey[Seq[(File,String)]]("mappings") // Run Keys @@ -167,15 +169,16 @@ object Keys val publishConfiguration = TaskKey[PublishConfiguration]("publish-configuration") val publishLocalConfiguration = TaskKey[PublishConfiguration]("publish-local-configuration") + val deliverConfiguration = TaskKey[DeliverConfiguration]("deliver-configuration") + val deliverLocalConfiguration = TaskKey[DeliverConfiguration]("deliver-local-configuration") val makePomConfiguration = SettingKey[MakePomConfiguration]("make-pom-configuration") - val packageToPublish = TaskKey[Unit]("package-to-publish") - val deliverDepends = TaskKey[Unit]("deliver-depends") + val packagedArtifacts = TaskKey[Map[Artifact,File]]("packaged-artifacts") val publishMavenStyle = SettingKey[Boolean]("publish-maven-style") val credentials = TaskKey[Seq[Credentials]]("credentials") val makePom = TaskKey[File]("make-pom") - val deliver = TaskKey[Unit]("deliver") - val deliverLocal = TaskKey[Unit]("deliver-local") + val deliver = TaskKey[File]("deliver") + val deliverLocal = TaskKey[File]("deliver-local") val publish = TaskKey[Unit]("publish") val publishLocal = TaskKey[Unit]("publish-local") @@ -199,15 +202,14 @@ object Keys val ivyValidate = SettingKey[Boolean]("ivy-validate") val ivyLoggingLevel = SettingKey[UpdateLogging.Value]("ivy-logging-level") val publishTo = SettingKey[Option[Resolver]]("publish-to") - val pomName = SettingKey[ArtifactName]("pom-name") - val pomFile = SettingKey[File]("pom-file") - val pomArtifact = SettingKey[Seq[Artifact]]("pom-artifact") val artifacts = SettingKey[Seq[Artifact]]("artifacts") val projectDescriptors = TaskKey[Map[ModuleRevisionId,ModuleDescriptor]]("project-descriptors") val autoUpdate = SettingKey[Boolean]("auto-update") val retrieveManaged = SettingKey[Boolean]("retrieve-managed") val managedDirectory = SettingKey[File]("managed-directory") val classpathTypes = SettingKey[Set[String]]("classpath-types") + val publishArtifact = SettingKey[Boolean]("publish-artifact") + val packagedArtifact = TaskKey[(Artifact, File)]("packaged-artifact") val sbtResolver = SettingKey[Resolver]("sbt-resolver") val sbtDependency = SettingKey[ModuleID]("sbt-dependency") diff --git a/main/Structure.scala b/main/Structure.scala index 61ddf560f..dd19f0ff0 100644 --- a/main/Structure.scala +++ b/main/Structure.scala @@ -12,6 +12,7 @@ package sbt import complete.Parser import java.io.File import java.net.URI + import Path._ sealed trait InputTask[T] { def mapTask[S](f: Task[T] => Task[S]): InputTask[S] @@ -212,6 +213,28 @@ object Scoped def dependOn: Initialize[Task[Unit]] = Apply.tasks(KList.fromList(keys)) { kl => nop.dependsOn(kl.toList :_*) } } + implicit def richFileSetting(s: ScopedSetting[File]): RichFileSetting = new RichFileSetting(s) + implicit def richFilesSetting(s: ScopedSetting[Seq[File]]): RichFilesSetting = new RichFilesSetting(s) + + final class RichFileSetting(s: ScopedSetting[File]) extends RichFileBase + { + def /(c: String): Initialize[File] = s { _ / c } + protected[this] def map0(f: PathFinder => PathFinder) = s(file => finder(f)(file :: Nil)) + } + final class RichFilesSetting(s: ScopedSetting[Seq[File]]) extends RichFileBase + { + def /(s: String): Initialize[Seq[File]] = map0 { _ / s } + protected[this] def map0(f: PathFinder => PathFinder) = s(finder(f)) + } + sealed abstract class RichFileBase + { + def *(filter: FileFilter): Initialize[Seq[File]] = map0 { _ * filter } + def **(filter: FileFilter): Initialize[Seq[File]] = map0 { _ ** filter } + protected[this] def map0(f: PathFinder => PathFinder): Initialize[Seq[File]] + protected[this] def finder(f: PathFinder => PathFinder): Seq[File] => Seq[File] = + in => f(in).getFiles + } + /* * Reduced and combine provide support for mixed Setting/Task flatMap/map. * The general idea is to take a KList of ScopedTaskables, which are either ScopedSettings or ScopedTasks, diff --git a/main/actions/CacheIvy.scala b/main/actions/CacheIvy.scala index c993bb710..133149913 100644 --- a/main/actions/CacheIvy.scala +++ b/main/actions/CacheIvy.scala @@ -53,7 +53,8 @@ object CacheIvy Cache.wrapIn(f, cache) def updateIC: InputCache[IvyConfiguration :+: ModuleSettings :+: UpdateConfiguration :+: HNil] = implicitly - def publishIC: InputCache[IvyConfiguration :+: ModuleSettings :+: PublishConfiguration :+: HNil] = implicitly +/* def deliverIC: InputCache[IvyConfiguration :+: ModuleSettings :+: DeliverConfiguration :+: HNil] = implicitly + def publishIC: InputCache[IvyConfiguration :+: ModuleSettings :+: PublishConfiguration :+: HNil] = implicitly*/ def updateReportF: Format[UpdateReport] = { @@ -133,7 +134,8 @@ object CacheIvy implicit def artifactToHL = (a: Artifact) => a.name :+: a.`type` :+: a.extension :+: a.classifier :+: names(a.configurations) :+: a.url :+: a.extraAttributes :+: HNil - implicit def publishConfToHL = (p: PublishConfiguration) => p.patterns :+: p.status :+: p.resolverName :+: p.configurations :+: HNil +/* implicit def deliverConfToHL = (p: DeliverConfiguration) => p.deliverIvyPattern :+: p.status :+: p.configurations :+: HNil + implicit def publishConfToHL = (p: PublishConfiguration) => p.ivyFile :+: p.resolverName :+: p.artifacts :+: HNil*/ } import L2._ @@ -142,7 +144,8 @@ object CacheIvy implicit def ivyFileIC: InputCache[IvyFileConfiguration] = wrapIn implicit def connectionIC: InputCache[SshConnection] = wrapIn implicit def artifactIC: InputCache[Artifact] = wrapIn - implicit def publishConfIC: InputCache[PublishConfiguration] = wrapIn +/* implicit def publishConfIC: InputCache[PublishConfiguration] = wrapIn + implicit def deliverConfIC: InputCache[DeliverConfiguration] = wrapIn*/ object L1 { implicit def retrieveToHL = (r: RetrieveConfiguration) => exists(r.retrieveDirectory) :+: r.outputPattern :+: HNil @@ -158,8 +161,6 @@ object CacheIvy implicit def externalIvyConfigurationToHL = (e: ExternalIvyConfiguration) => exists(e.baseDirectory) :+: hash(e.file) :+: HNil - - implicit def publishPatternsToHL = (p: PublishPatterns) => p.deliverIvyPattern :+: p.srcArtifactPatterns :+: HNil } import L1._ @@ -170,7 +171,6 @@ object CacheIvy implicit def fileConfIC: InputCache[FileConfiguration] = wrapIn implicit def extIvyIC: InputCache[ExternalIvyConfiguration] = wrapIn implicit def confIC: InputCache[Configuration] = wrapIn - implicit def publishPatternsIC: InputCache[PublishPatterns] = wrapIn implicit def authIC: InputCache[SshAuthentication] = unionInputCache[SshAuthentication, PasswordAuthentication :+: KeyFileAuthentication :+: HNil]