mirror of https://github.com/sbt/sbt.git
Merge remote-tracking branch 'upstream/0.13' into 0.13
This commit is contained in:
commit
ef3eccf95f
|
|
@ -84,6 +84,22 @@ Whether implementing a new feature, fixing a bug, or modifying documentation, pl
|
||||||
Binary compatible changes will be backported to a previous series (currently, 0.12.x) at the time of the next stable release.
|
Binary compatible changes will be backported to a previous series (currently, 0.12.x) at the time of the next stable release.
|
||||||
See below for instructions on building sbt from source.
|
See below for instructions on building sbt from source.
|
||||||
|
|
||||||
|
All pull requests are required to include a "Notes" file which documents the change. This file should reside in the
|
||||||
|
directory:
|
||||||
|
|
||||||
|
<sbt root>
|
||||||
|
notes/
|
||||||
|
<target release>/
|
||||||
|
<your-change-name>.md
|
||||||
|
|
||||||
|
Notes files should have the following contents:
|
||||||
|
|
||||||
|
* Bullet item description under one of the following sections:
|
||||||
|
- `### Bug fixes`
|
||||||
|
- `### Improvements`
|
||||||
|
- `### Fixes with compatibility implications`
|
||||||
|
* Complete section describing new features.
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
package org.apache.ivy.plugins.parser.m2
|
||||||
|
|
||||||
|
import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It turns out there was a very subtle, and evil, issue sitting the Ivy/maven configuration, and it
|
||||||
|
* related to dependency mapping. A mapping of `foo->bar(*)` means that the local configuration
|
||||||
|
* `foo` depends on the remote configuration `bar`, if it exists, or *ALL CONFIGURATIONS* if `bar`
|
||||||
|
* does not exist. Since the default Ivy configuration mapping was using the random `master`
|
||||||
|
* configuration, which AFAICT is NEVER specified, just an assumed default, this would cause leaks
|
||||||
|
* between maven + ivy projects.
|
||||||
|
*
|
||||||
|
* i.e. if a maven POM depends on a module denoted by an ivy.xml file, then you'd wind up accidentally
|
||||||
|
* bleeding ALL the ivy module's configurations into the maven module's configurations.
|
||||||
|
*
|
||||||
|
* This fix works around the issue, by assuming that if there is no `master` configuration, than the
|
||||||
|
* maven default of `compile` is intended. As sbt forces generated `ivy.xml` files to abide by
|
||||||
|
* maven conventions, this works in all of our test cases. The only scenario where it wouldn't work
|
||||||
|
* is those who have custom ivy.xml files *and* have pom.xml files which rely on those custom ivy.xml files,
|
||||||
|
* a very unlikely situation where the workaround is: "define a master configuration".
|
||||||
|
*
|
||||||
|
* Also see: http://ant.apache.org/ivy/history/2.3.0/ivyfile/dependency.html
|
||||||
|
* and: http://svn.apache.org/repos/asf/ant/ivy/core/tags/2.3.0/src/java/org/apache/ivy/plugins/parser/m2/PomModuleDescriptorBuilder.java
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
object ReplaceMavenConfigurationMappings {
|
||||||
|
|
||||||
|
val REPLACEMENT_MAVEN_MAPPINGS = {
|
||||||
|
// Here we copy paste from Ivy
|
||||||
|
val REPLACEMENT_MAPPINGS = new java.util.HashMap[String, PomModuleDescriptorBuilder.ConfMapper]
|
||||||
|
|
||||||
|
// NOTE - This code is copied from org.apache.ivy.plugins.parser.m2.PomModuleDescriptorBuilder
|
||||||
|
// except with altered default configurations...
|
||||||
|
REPLACEMENT_MAPPINGS.put("compile", new PomModuleDescriptorBuilder.ConfMapper {
|
||||||
|
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean) {
|
||||||
|
if (isOptional) {
|
||||||
|
dd.addDependencyConfiguration("optional", "compile(*)")
|
||||||
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("optional", "master(compile)")
|
||||||
|
} else {
|
||||||
|
dd.addDependencyConfiguration("compile", "compile(*)")
|
||||||
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("compile", "master(compile)")
|
||||||
|
dd.addDependencyConfiguration("runtime", "runtime(*)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
REPLACEMENT_MAPPINGS.put("provided", new PomModuleDescriptorBuilder.ConfMapper {
|
||||||
|
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean) {
|
||||||
|
if (isOptional) {
|
||||||
|
dd.addDependencyConfiguration("optional", "compile(*)")
|
||||||
|
dd.addDependencyConfiguration("optional", "provided(*)")
|
||||||
|
dd.addDependencyConfiguration("optional", "runtime(*)")
|
||||||
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("optional", "master(compile)")
|
||||||
|
} else {
|
||||||
|
dd.addDependencyConfiguration("provided", "compile(*)")
|
||||||
|
dd.addDependencyConfiguration("provided", "provided(*)")
|
||||||
|
dd.addDependencyConfiguration("provided", "runtime(*)")
|
||||||
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("provided", "master(compile)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
REPLACEMENT_MAPPINGS.put("runtime", new PomModuleDescriptorBuilder.ConfMapper {
|
||||||
|
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean) {
|
||||||
|
if (isOptional) {
|
||||||
|
dd.addDependencyConfiguration("optional", "compile(*)")
|
||||||
|
dd.addDependencyConfiguration("optional", "provided(*)")
|
||||||
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("optional", "master(compile)")
|
||||||
|
} else {
|
||||||
|
dd.addDependencyConfiguration("runtime", "compile(*)")
|
||||||
|
dd.addDependencyConfiguration("runtime", "runtime(*)")
|
||||||
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("runtime", "master(compile)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
REPLACEMENT_MAPPINGS.put("test", new PomModuleDescriptorBuilder.ConfMapper {
|
||||||
|
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean) {
|
||||||
|
dd.addDependencyConfiguration("test", "runtime(*)")
|
||||||
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("test", "master(compile)")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
REPLACEMENT_MAPPINGS.put("system", new PomModuleDescriptorBuilder.ConfMapper {
|
||||||
|
def addMappingConfs(dd: DefaultDependencyDescriptor, isOptional: Boolean) {
|
||||||
|
// FIX - Here we take a mroe conservative approach of depending on the compile configuration if master isn't there.
|
||||||
|
dd.addDependencyConfiguration("system", "master(compile)")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
REPLACEMENT_MAPPINGS
|
||||||
|
}
|
||||||
|
|
||||||
|
def init(): Unit = {
|
||||||
|
// Here we mutate a static final field, because we have to AND because it's evil.
|
||||||
|
try {
|
||||||
|
val map = PomModuleDescriptorBuilder.MAVEN2_CONF_MAPPING.asInstanceOf[java.util.Map[String, PomModuleDescriptorBuilder.ConfMapper]]
|
||||||
|
map.clear()
|
||||||
|
map.putAll(REPLACEMENT_MAVEN_MAPPINGS)
|
||||||
|
} catch {
|
||||||
|
case e: Exception =>
|
||||||
|
// TODO - Log that Ivy may not be configured correctly and you could have maven/ivy issues.
|
||||||
|
throw new RuntimeException("FAILURE to install Ivy maven hooks. Your ivy-maven interaction may suffer resolution errors", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ import org.apache.ivy.core.module.id.ModuleRevisionId
|
||||||
import org.apache.ivy.core.module.descriptor.{ DefaultArtifact, DefaultExtendsDescriptor, DefaultModuleDescriptor, ModuleDescriptor }
|
import org.apache.ivy.core.module.descriptor.{ DefaultArtifact, DefaultExtendsDescriptor, DefaultModuleDescriptor, ModuleDescriptor }
|
||||||
import org.apache.ivy.core.module.descriptor.{ DefaultDependencyDescriptor, DependencyDescriptor }
|
import org.apache.ivy.core.module.descriptor.{ DefaultDependencyDescriptor, DependencyDescriptor }
|
||||||
import org.apache.ivy.plugins.parser.{ ModuleDescriptorParser, ModuleDescriptorParserRegistry, ParserSettings }
|
import org.apache.ivy.plugins.parser.{ ModuleDescriptorParser, ModuleDescriptorParserRegistry, ParserSettings }
|
||||||
import org.apache.ivy.plugins.parser.m2.{ PomModuleDescriptorBuilder, PomModuleDescriptorParser }
|
import org.apache.ivy.plugins.parser.m2.{ ReplaceMavenConfigurationMappings, PomModuleDescriptorBuilder, PomModuleDescriptorParser }
|
||||||
import org.apache.ivy.plugins.repository.Resource
|
import org.apache.ivy.plugins.repository.Resource
|
||||||
import org.apache.ivy.plugins.namespace.NamespaceTransformer
|
import org.apache.ivy.plugins.namespace.NamespaceTransformer
|
||||||
import org.apache.ivy.util.extendable.ExtendableItem
|
import org.apache.ivy.util.extendable.ExtendableItem
|
||||||
|
|
@ -27,6 +27,10 @@ final class CustomPomParser(delegate: ModuleDescriptorParser, transform: (Module
|
||||||
override def getMetadataArtifact(mrid: ModuleRevisionId, res: Resource) = delegate.getMetadataArtifact(mrid, res)
|
override def getMetadataArtifact(mrid: ModuleRevisionId, res: Resource) = delegate.getMetadataArtifact(mrid, res)
|
||||||
}
|
}
|
||||||
object CustomPomParser {
|
object CustomPomParser {
|
||||||
|
|
||||||
|
// Evil hackery to override the default maven pom mappings.
|
||||||
|
ReplaceMavenConfigurationMappings.init()
|
||||||
|
|
||||||
/** The key prefix that indicates that this is used only to store extra information and is not intended for dependency resolution.*/
|
/** The key prefix that indicates that this is used only to store extra information and is not intended for dependency resolution.*/
|
||||||
val InfoKeyPrefix = "info."
|
val InfoKeyPrefix = "info."
|
||||||
val ApiURLKey = "info.apiURL"
|
val ApiURLKey = "info.apiURL"
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ private[sbt] object SettingCompletions {
|
||||||
{
|
{
|
||||||
import extracted._
|
import extracted._
|
||||||
val r = relation(extracted.structure, true)
|
val r = relation(extracted.structure, true)
|
||||||
val allDefs = r._1s.toSeq
|
val allDefs = Def.flattenLocals(Def.compiled(extracted.structure.settings, true)(structure.delegates, structure.scopeLocal, implicitly[Show[ScopedKey[_]]])).map(_._1)
|
||||||
val projectScope = Load.projectScope(currentRef)
|
val projectScope = Load.projectScope(currentRef)
|
||||||
def resolve(s: Setting[_]): Seq[Setting[_]] = Load.transformSettings(projectScope, currentRef.build, rootProject, s :: Nil)
|
def resolve(s: Setting[_]): Seq[Setting[_]] = Load.transformSettings(projectScope, currentRef.build, rootProject, s :: Nil)
|
||||||
def rescope[T](setting: Setting[T]): Seq[Setting[_]] =
|
def rescope[T](setting: Setting[T]): Seq[Setting[_]] =
|
||||||
|
|
@ -353,4 +353,4 @@ private[sbt] object SettingCompletions {
|
||||||
classOf[Long],
|
classOf[Long],
|
||||||
classOf[String]
|
classOf[String]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
[1586]: https://github.com/sbt/sbt/pull/1586
|
||||||
|
[@jsuereth]: https://github.com/jsuereth
|
||||||
|
|
||||||
|
|
||||||
|
### Fixes with compatibility implications
|
||||||
|
|
||||||
|
* Maven artifact dependencies now limit their transitive dependencies to "compile" rather than "every configuration"
|
||||||
|
if no `master` configuration is found. [#1586][1586] by [@jsuereth][@jsuereth]
|
||||||
|
|
@ -17,7 +17,7 @@ object Sbt extends Build {
|
||||||
s"all control/$task collections/$task io/$task completion/$task"
|
s"all control/$task collections/$task io/$task completion/$task"
|
||||||
def buildSettings = Seq(
|
def buildSettings = Seq(
|
||||||
organization := "org.scala-sbt",
|
organization := "org.scala-sbt",
|
||||||
version := "0.13.6-SNAPSHOT",
|
version := "0.13.7-SNAPSHOT",
|
||||||
publishArtifact in packageDoc := false,
|
publishArtifact in packageDoc := false,
|
||||||
scalaVersion := "2.10.4",
|
scalaVersion := "2.10.4",
|
||||||
publishMavenStyle := false,
|
publishMavenStyle := false,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
val repoFile = file("mvn-repo")
|
||||||
|
|
||||||
|
resolvers += "bad-mvn-repo" at repoFile.toURI.toURL.toString
|
||||||
|
|
||||||
|
libraryDependencies += "bad" % "mvn" % "1.0"
|
||||||
|
|
||||||
|
TaskKey[Unit]("check") := {
|
||||||
|
val cp = (fullClasspath in Compile).value
|
||||||
|
def isTestJar(n: String): Boolean =
|
||||||
|
(n contains "scalacheck") ||
|
||||||
|
(n contains "specs2")
|
||||||
|
val testLibs = cp map (_.data.getName) filter isTestJar
|
||||||
|
assert(testLibs.isEmpty, s"Compile Classpath has test libs:\n * ${testLibs.mkString("\n * ")}")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>bad</groupId>
|
||||||
|
<artifactId>mvn</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<version>1.0</version>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.scala-sbt</groupId>
|
||||||
|
<artifactId>completion</artifactId>
|
||||||
|
<version>0.13.5</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
> check
|
||||||
|
|
@ -16,9 +16,14 @@ object TestProject extends Build
|
||||||
private def check(transitive: Boolean) =
|
private def check(transitive: Boolean) =
|
||||||
(dependencyClasspath in Compile) map { downloaded =>
|
(dependencyClasspath in Compile) map { downloaded =>
|
||||||
val jars = downloaded.size
|
val jars = downloaded.size
|
||||||
if(transitive)
|
if(transitive) {
|
||||||
if(jars <= 2) error("Transitive dependencies not downloaded") else ()
|
if (jars <= 2)
|
||||||
else
|
sys.error(s"Transitive dependencies not downloaded, found:\n * ${downloaded.mkString("\n * ")}")
|
||||||
if(jars > 2) error("Transitive dependencies downloaded (" + downloaded.files.mkString(", ") + ")") else ()
|
else ()
|
||||||
|
} else {
|
||||||
|
if (jars > 2)
|
||||||
|
sys.error(s"Transitive dependencies not downloaded, found:\n * ${downloaded.mkString("\n * ")}")
|
||||||
|
else ()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
> debug
|
||||||
# load the project definition with transitive dependencies enabled
|
# load the project definition with transitive dependencies enabled
|
||||||
# and check that they are not downloaded
|
# and check that they are not downloaded
|
||||||
#$ pause
|
#$ pause
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
val a = project.settings(version := "2.8.1")
|
||||||
|
|
||||||
|
val trySetEvery = taskKey[Unit]("Tests \"set every\"")
|
||||||
|
|
||||||
|
trySetEvery := {
|
||||||
|
val s = state.value
|
||||||
|
val extracted = Project.extract(s)
|
||||||
|
import extracted._
|
||||||
|
val allProjs = structure.allProjectRefs
|
||||||
|
val Some(aProj) = allProjs.find(_.project == "a")
|
||||||
|
val aVer = (version in aProj get structure.data).get
|
||||||
|
if (aVer != "1.0") {
|
||||||
|
println("Version of project a: " + aVer + ", expected: 1.0")
|
||||||
|
error("\"set every\" did not change the version of all projects.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
> set every version := '"1.0"'
|
||||||
|
> trySetEvery
|
||||||
|
|
||||||
Loading…
Reference in New Issue