Switch to sbt-datatype, sjson-new & Vectors

This commit is contained in:
Dale Wijnand 2016-11-02 15:22:55 +00:00
parent 52c1826366
commit f2efa10af1
No known key found for this signature in database
GPG Key ID: 4F256E3D151DF5EF
45 changed files with 1372 additions and 1065 deletions

View File

@ -17,7 +17,6 @@ def commonSettings: Seq[Setting[_]] = Seq(
crossScalaVersions := Seq(scala211), crossScalaVersions := Seq(scala211),
resolvers += Resolver.sonatypeRepo("public"), resolvers += Resolver.sonatypeRepo("public"),
scalacOptions += "-Ywarn-unused", scalacOptions += "-Ywarn-unused",
scalacOptions += "-Ywarn-unused-import",
previousArtifact := None, // Some(organization.value %% moduleName.value % "1.0.0"), previousArtifact := None, // Some(organization.value %% moduleName.value % "1.0.0"),
publishArtifact in Compile := true, publishArtifact in Compile := true,
publishArtifact in Test := false publishArtifact in Test := false
@ -47,11 +46,14 @@ lazy val lm = (project in file("librarymanagement")).
commonSettings, commonSettings,
name := "librarymanagement", name := "librarymanagement",
libraryDependencies ++= Seq( libraryDependencies ++= Seq(
ivy, jsch, sbtSerialization, scalaReflect.value, launcherInterface), ivy, jsch, scalaReflect.value, launcherInterface, sjsonnewScalaJson % Optional),
resourceGenerators in Compile <+= (version, resourceManaged, streams, compile in Compile) map Util.generateVersionFile, libraryDependencies ++= scalaXml.value,
binaryIssueFilters ++= Seq() resourceGenerators in Compile += Def.task(Util.generateVersionFile(version.value, resourceManaged.value, streams.value, (compile in Compile).value)).taskValue,
binaryIssueFilters ++= Seq(),
datatypeFormatsForType in generateDatatypes in Compile := DatatypeConfig.getFormats
). ).
configure(addSbtIO, addSbtUtilLogging, addSbtUtilTesting, addSbtUtilCollection, addSbtUtilCompletion) configure(addSbtIO, addSbtUtilLogging, addSbtUtilTesting, addSbtUtilCollection, addSbtUtilCompletion, addSbtUtilCache).
enablePlugins(DatatypePlugin, JsonCodecPlugin)
def customCommands: Seq[Setting[_]] = Seq( def customCommands: Seq[Setting[_]] = Seq(
commands += Command.command("release") { state => commands += Command.command("release") { state =>

View File

@ -0,0 +1,780 @@
{
"codecNamespace": "sbt.librarymanagement",
"fullCodec": "LibraryManagementCodec",
"types": [
{
"name": "Caller",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "caller", "type": "sbt.librarymanagement.ModuleID" },
{ "name": "callerConfigurations", "type": "String*" },
{ "name": "callerExtraAttributes", "type": "Map[String, String]" },
{ "name": "isForceDependency", "type": "boolean" },
{ "name": "isChangingDependency", "type": "boolean" },
{ "name": "isTransitiveDependency", "type": "boolean" },
{ "name": "isDirectlyForceDependency", "type": "boolean" }
],
"toString": "s\"$caller\""
},
{
"name": "ModuleReport",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": [
"Provides information about the resolution of a module.",
"This information is in the context of a specific configuration."
],
"parents": "sbt.librarymanagement.ModuleReportParent",
"fields": [
{ "name": "module", "type": "sbt.librarymanagement.ModuleID" },
{ "name": "artifacts", "type": "scala.Tuple2[sbt.librarymanagement.Artifact, java.io.File]*" },
{ "name": "missingArtifacts", "type": "sbt.librarymanagement.Artifact*" },
{ "name": "status", "type": "String?", "default": "None", "since": "0.0.1" },
{ "name": "publicationDate", "type": "java.util.Date?", "default": "None", "since": "0.0.1" },
{ "name": "resolver", "type": "String?", "default": "None", "since": "0.0.1" },
{ "name": "artifactResolver", "type": "String?", "default": "None", "since": "0.0.1" },
{ "name": "evicted", "type": "boolean", "default": "false", "since": "0.0.1" },
{ "name": "evictedData", "type": "String?", "default": "None", "since": "0.0.1" },
{ "name": "evictedReason", "type": "String?", "default": "None", "since": "0.0.1" },
{ "name": "problem", "type": "String?", "default": "None", "since": "0.0.1" },
{ "name": "homepage", "type": "String?", "default": "None", "since": "0.0.1" },
{ "name": "extraAttributes", "type": "Map[String, String]", "default": "Map.empty", "since": "0.0.1" },
{ "name": "isDefault", "type": "boolean?", "default": "None", "since": "0.0.1" },
{ "name": "branch", "type": "String?", "default": "None", "since": "0.0.1" },
{ "name": "configurations", "type": "String*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "licenses", "type": "scala.Tuple2[String, Option[String]]*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "callers", "type": "sbt.librarymanagement.Caller*", "default": "Vector.empty", "since": "0.0.1" }
],
"toString": [
"s\"\\t\\t$module: \" +",
"(if (arts.size <= 1) \"\" else \"\\n\\t\\t\\t\") + arts.mkString(\"\\n\\t\\t\\t\") + \"\\n\""
]
},
{
"name": "OrganizationArtifactReport",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": [
"OrganizationArtifactReport represents an organization+name entry in Ivy resolution report.",
"In sbt's terminology, \"module\" consists of organization, name, and version.",
"In Ivy's, \"module\" means just organization and name, and the one including version numbers",
"are called revisions.",
"",
"A sequence of OrganizationArtifactReport called details is newly added to ConfigurationReport, replacing evicted.",
"(Note old evicted was just a seq of ModuleIDs).",
"OrganizationArtifactReport groups the ModuleReport of both winners and evicted reports by their organization and name,",
"which can be used to calculate detailed eviction warning etc."
],
"fields": [
{ "name": "organization", "type": "String" },
{ "name": "name", "type": "String" },
{ "name": "modules", "type": "sbt.librarymanagement.ModuleReport*" }
]
},
{
"name": "UpdateStats",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "resolveTime", "type": "long" },
{ "name": "downloadTime", "type": "long" },
{ "name": "downloadSize", "type": "long" },
{ "name": "cached", "type": "boolean" }
],
"toString": "Seq(\"Resolve time: \" + resolveTime + \" ms\", \"Download time: \" + downloadTime + \" ms\", \"Download size: \" + downloadSize + \" bytes\").mkString(\", \")"
},
{
"name": "UpdateLogging",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "enumeration",
"doc": [
"Configures logging during an 'update'. `level` determines the amount of other information logged.",
"`Full` is the default and logs the most.",
"`DownloadOnly` only logs what is downloaded.",
"`Quiet` only displays errors.",
"`Default` uses the current log level of `update` task."
],
"symbols": [ "Full", "DownloadOnly", "Quiet", "Default" ]
},
{
"name": "RetrieveConfiguration",
"namespace": "sbt.internal.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "retrieveDirectory", "type": "java.io.File" },
{ "name": "outputPattern", "type": "String" },
{ "name": "sync", "type": "boolean", "default": "false", "since": "0.0.1" },
{ "name": "configurationsToRetrieve", "type": "Set[sbt.librarymanagement.Configuration]?", "default": "None", "since": "0.0.1" }
]
},
{
"name": "UpdateConfiguration",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "retrieve", "type": "sbt.internal.librarymanagement.RetrieveConfiguration?" },
{ "name": "missingOk", "type": "boolean" },
{ "name": "logging", "type": "sbt.librarymanagement.UpdateLogging" },
{ "name": "artifactFilter", "type": "sbt.librarymanagement.ArtifactTypeFilter" }
]
},
{
"name": "ScmInfo",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": "Basic SCM information for a project module",
"fields": [
{ "name": "browseUrl", "type": "java.net.URL" },
{ "name": "connection", "type": "String" },
{ "name": "devConnection", "type": "String?" }
]
},
{
"name": "Developer",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "id", "type": "String" },
{ "name": "name", "type": "String" },
{ "name": "email", "type": "String" },
{ "name": "url", "type": "java.net.URL" }
]
},
{
"name": "SbtExclusionRule",
"namespace": "sbt.internal.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "organization", "type": "String" },
{ "name": "name", "type": "String" },
{ "name": "artifact", "type": "String" },
{ "name": "configurations", "type": "String*" },
{ "name": "crossVersion", "type": "sbt.librarymanagement.CrossVersion" }
]
},
{
"name": "ModuleInfo",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": "Additional information about a project module",
"fields": [
{ "name": "nameFormal", "type": "String" },
{ "name": "description", "type": "String", "default": "\"\"", "since": "0.0.1" },
{ "name": "homepage", "type": "java.net.URL?", "default": "None", "since": "0.0.1" },
{ "name": "startYear", "type": "int?", "default": "None", "since": "0.0.1" },
{ "name": "licenses", "type": "scala.Tuple2[String, java.net.URL]*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "organizationName", "type": "String", "default": "\"\"", "since": "0.0.1" },
{ "name": "organizationHomepage", "type": "java.net.URL?", "default": "None", "since": "0.0.1" },
{ "name": "scmInfo", "type": "sbt.librarymanagement.ScmInfo?", "default": "None", "since": "0.0.1" },
{ "name": "developers", "type": "sbt.librarymanagement.Developer*", "default": "Vector.empty", "since": "0.0.1" }
]
},
{
"name": "ConflictManager",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": "See http://ant.apache.org/ivy/history/latest-milestone/settings/conflict-managers.html for details of the different conflict managers.",
"fields": [
{ "name": "name", "type": "String" },
{ "name": "organization", "type": "String", "default": "\"*\"", "since": "0.0.1" },
{ "name": "module", "type": "String", "default": "\"*\"", "since": "0.0.1" }
],
"parentsCompanion": "sbt.librarymanagement.ConflictManagerCompanion"
},
{
"name": "IvyScala",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "scalaFullVersion", "type": "String" },
{ "name": "scalaBinaryVersion", "type": "String" },
{ "name": "configurations", "type": "sbt.librarymanagement.Configuration*" },
{ "name": "checkExplicit", "type": "boolean" },
{ "name": "filterImplicit", "type": "boolean" },
{ "name": "overrideScalaVersion", "type": "boolean" },
{ "name": "scalaOrganization", "type": "String", "default": "sbt.librarymanagement.ScalaArtifacts.Organization", "since": "0.0.1" },
{ "name": "scalaArtifacts", "type": "String*", "default": "sbt.librarymanagement.ScalaArtifacts.Artifacts", "since": "0.0.1" }
],
"parentsCompanion": "sbt.librarymanagement.IvyScalaCompanion"
},
{
"name": "ModuleSettings",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "interface",
"fields": [
{ "name": "validate", "type": "boolean" },
{ "name": "ivyScala", "type": "sbt.librarymanagement.IvyScala?" }
],
"types": [
{
"name": "IvyFileConfiguration",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "file", "type": "java.io.File" },
{ "name": "autoScalaTools", "type": "boolean" }
]
},
{
"name": "PomConfiguration",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "file", "type": "java.io.File" },
{ "name": "autoScalaTools", "type": "boolean" }
]
},
{
"name": "InlineConfiguration",
"namespace": "sbt.internal.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "module", "type": "sbt.librarymanagement.ModuleID" },
{ "name": "moduleInfo", "type": "sbt.librarymanagement.ModuleInfo" },
{ "name": "dependencies", "type": "sbt.librarymanagement.ModuleID*" },
{ "name": "overrides", "type": "Set[sbt.librarymanagement.ModuleID]", "default": "Set.empty", "since": "0.0.1" },
{ "name": "excludes", "type": "sbt.internal.librarymanagement.SbtExclusionRule*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "ivyXML", "type": "scala.xml.NodeSeq", "default": "scala.xml.NodeSeq.Empty", "since": "0.0.1" },
{ "name": "configurations", "type": "sbt.librarymanagement.Configuration*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "defaultConfiguration", "type": "sbt.librarymanagement.Configuration?", "default": "None", "since": "0.0.1" },
{ "name": "conflictManager", "type": "sbt.librarymanagement.ConflictManager", "default": "sbt.librarymanagement.ConflictManager.default", "since": "0.0.1" }
],
"parentsCompanion": "sbt.internal.librarymanagement.InlineConfigurationCompanion"
}
]
},
{
"name": "IvyPaths",
"namespace": "sbt.internal.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "baseDirectory", "type": "java.io.File" },
{ "name": "ivyHome", "type": "java.io.File?" }
]
},
{
"name": "InclExclRule",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": [
"Rule to either:",
"<ul>",
"<li> exclude unwanted dependencies pulled in transitively by a module, or to</li>",
"<li> include and merge artifacts coming from the ModuleDescriptor if \"dependencyArtifacts\" are also provided.</li>",
"</ul>",
"Which one depends on the parameter name which it is passed to, but the filter has the same fields in both cases."
],
"fields": [
{ "name": "organization", "type": "String", "default": "\"*\"", "since": "0.0.1" },
{ "name": "name", "type": "String", "default": "\"*\"", "since": "0.0.1" },
{ "name": "artifact", "type": "String", "default": "\"*\"", "since": "0.0.1" },
{ "name": "configurations", "type": "String*", "default": "Vector.empty", "since": "0.0.1" }
],
"parentsCompanion": "sbt.librarymanagement.InclExclRuleCompanion"
},
{
"name": "CrossVersion",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "interface",
"doc": "Configures how a module will be cross-versioned.",
"types": [
{
"name": "Disabled",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"doc": "Disables cross versioning for a module.",
"type": "record"
},
{
"name": "Binary",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"doc": [
"Cross-versions a module using the result of applying `remapVersion` to the binary version.",
"For example, if `remapVersion = v => \"2.10\"` and the binary version is \"2.9.2\" or \"2.10\",",
"the module is cross-versioned with \"2.10\"."
],
"type": "record",
"fields": [
{ "name": "remapVersion", "type": "Function1[String, String]" }
]
},
{
"name": "Full",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": [
"Cross-versions a module with the result of applying `remapVersion` to the full version.",
"For example, if `remapVersion = v => \"2.10\"` and the full version is \"2.9.2\" or \"2.10.3\",",
"the module is cross-versioned with \"2.10\"."
],
"fields": [
{ "name": "remapVersion", "type": "Function1[String, String]" }
]
}
],
"parentsCompanion": "sbt.librarymanagement.CrossVersionCompanion"
},
{
"name": "Configuration",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": "Represents an Ivy configuration.",
"parents": "sbt.librarymanagement.ConfigurationParent",
"fields": [
{ "name": "name", "type": "String" },
{ "name": "description", "type": "String", "default": "\"\"", "since": "0.0.1" },
{ "name": "isPublic", "type": "boolean", "default": "true", "since": "0.0.1" },
{ "name": "extendsConfigs", "type": "sbt.librarymanagement.Configuration*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "transitive", "type": "boolean", "default": "true", "since": "0.0.1" }
],
"toString": "name"
},
{
"name": "Artifact",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"parents": "sbt.librarymanagement.ArtifactParent",
"fields": [
{ "name": "name", "type": "String" },
{ "name": "type", "type": "String", "default": "Artifact.DefaultType", "since": "0.0.1" },
{ "name": "extension", "type": "String", "default": "Artifact.DefaultExtension", "since": "0.0.1" },
{ "name": "classifier", "type": "String?", "default": "None", "since": "0.0.1" },
{ "name": "configurations", "type": "sbt.librarymanagement.Configuration*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "url", "type": "java.net.URL?", "default": "None", "since": "0.0.1" },
{ "name": "extraAttributes", "type": "Map[String, String]", "default": "Map.empty", "since": "0.0.1" }
],
"parentsCompanion": "sbt.librarymanagement.ArtifactCompanion"
},
{
"name": "SshAuthentication",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "interface",
"types": [
{
"name": "PasswordAuthentication",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "user", "type": "String" },
{ "name": "password", "type": "String?" }
]
},
{
"name": "KeyFileAuthentication",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "user", "type": "String" },
{ "name": "keyfile", "type": "java.io.File" },
{ "name": "password", "type": "String?" }
]
}
]
},
{
"name": "SshConnection",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "authentication", "type": "sbt.librarymanagement.SshAuthentication?" },
{ "name": "hostname", "type": "String?" },
{ "name": "port", "type": "int?" }
]
},
{
"name": "FileConfiguration",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": "Configuration specific to an Ivy filesystem resolver.",
"fields": [
{ "name": "isLocal", "type": "boolean" },
{ "name": "isTransactional", "type": "boolean?" }
]
},
{
"name": "Patterns",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "ivyPatterns", "type": "String*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "artifactPatterns", "type": "String*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "isMavenCompatible", "type": "boolean", "default": "true", "since": "0.0.1" },
{ "name": "descriptorOptional", "type": "boolean", "default": "false", "since": "0.0.1" },
{ "name": "skipConsistencyCheck", "type": "boolean", "default": "false", "since": "0.0.1" }
],
"toString": [
"\"Patterns(ivyPatterns=%s, artifactPatterns=%s, isMavenCompatible=%s, descriptorOptional=%s, skipConsistencyCheck=%s)\".format(",
" ivyPatterns, artifactPatterns, isMavenCompatible, descriptorOptional, skipConsistencyCheck)"
],
"parentsCompanion": "sbt.librarymanagement.PatternsCompanion"
},
{
"name": "Resolver",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "interface",
"fields": [
{ "name": "name", "type": "String" }
],
"types": [
{
"name": "ChainedResolver",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "resolvers", "type": "sbt.librarymanagement.Resolver*" }
]
},
{
"name": "IMavenRepository",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "interface",
"doc": "An instance of a remote maven repository. Note: This will use Aether/Maven to resolve artifacts.",
"fields": [
{ "name": "root", "type": "String" },
{ "name": "localIfFile", "type": "boolean", "default": "true", "since": "0.0.1" }
],
"types": [
{
"name": "MavenRepository",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"toString": "s\"$name: $root\""
},
{
"name": "MavenCache",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": [
"An instance of maven CACHE directory. You cannot treat a cache directory the same as a a remote repository because",
"the metadata is different (see Aether ML discussion)."
],
"fields": [
{ "name": "rootFile", "type": "java.io.File" }
],
"extra": "def this(name: String, rootFile: java.io.File) = this(name, rootFile.toURI.toURL.toString, true, rootFile)",
"toString": "s\"cache:$name: ${rootFile.getAbsolutePath}\"",
"extraCompanion": "def apply(name: String, rootFile: java.io.File): MavenCache = new MavenCache(name, rootFile)"
}
]
},
{
"name": "PatternsBasedRepository",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "interface",
"fields": [
{ "name": "patterns", "type": "sbt.librarymanagement.Patterns" }
],
"doc": "sbt interface to an Ivy repository based on patterns, which is most Ivy repositories.",
"types": [
{
"name": "FileRepository",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": "sbt interface for an Ivy filesystem repository. More convenient construction is done using Resolver.file.",
"fields": [
{ "name": "configuration", "type": "sbt.librarymanagement.FileConfiguration" }
],
"extra": [
"def this(name: String, configuration: sbt.librarymanagement.FileConfiguration, patterns: sbt.librarymanagement.Patterns) = ",
" this(name, patterns, configuration)"
],
"extraCompanion": [
"def apply(name: String, configuration: sbt.librarymanagement.FileConfiguration, patterns: sbt.librarymanagement.Patterns) = ",
" new FileRepository(name, patterns, configuration)"
]
},
{
"name": "URLRepository",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record"
},
{
"name": "SshBasedRepository",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "interface",
"doc": "sbt interface for an Ivy ssh-based repository (ssh and sftp). Requires the Jsch library..",
"fields": [
{ "name": "connection", "type": "sbt.librarymanagement.SshConnection" }
],
"types": [
{
"name": "SshRepository",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": "sbt interface for an Ivy repository over ssh. More convenient construction is done using Resolver.ssh.",
"fields": [
{ "name": "publishPermissions", "type": "String?" }
],
"extra": [
"def this(name: String, connection: sbt.librarymanagement.SshConnection, patterns: sbt.librarymanagement.Patterns, publishPermissions: Option[String]) = ",
" this(name, patterns, connection, publishPermissions)"
],
"extraCompanion": [
"def apply(name: String, connection: sbt.librarymanagement.SshConnection, patterns: sbt.librarymanagement.Patterns, publishPermissions: Option[String]) = ",
" new SshRepository(name, patterns, connection, publishPermissions)"
]
},
{
"name": "SftpRepository",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": "sbt interface for an Ivy repository over sftp. More convenient construction is done using Resolver.sftp.",
"extra": [
"def this(name: String, connection: sbt.librarymanagement.SshConnection, patterns: sbt.librarymanagement.Patterns) = ",
" this(name, patterns, connection)"
],
"extraCompanion": [
"def apply(name: String, connection: sbt.librarymanagement.SshConnection, patterns: sbt.librarymanagement.Patterns) = ",
" new SftpRepository(name, patterns, connection)"
]
}
]
}
]
}
],
"parentsCompanion": "sbt.librarymanagement.ResolverCompanion"
},
{
"name": "ModuleConfiguration",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "organization", "type": "String" },
{ "name": "name", "type": "String" },
{ "name": "revision", "type": "String" },
{ "name": "resolver", "type": "sbt.librarymanagement.Resolver" }
],
"extraCompanion": [
"def apply(org: String, resolver: sbt.librarymanagement.Resolver): ModuleConfiguration = apply(org, \"*\", \"*\", resolver)",
"def apply(org: String, name: String, resolver: sbt.librarymanagement.Resolver): ModuleConfiguration = ModuleConfiguration(org, name, \"*\", resolver)"
]
},
{
"name": "IvyConfiguration",
"namespace": "sbt.internal.librarymanagement",
"target": "Scala",
"type": "interface",
"fields": [
{ "name": "lock", "type": "xsbti.GlobalLock?" },
{ "name": "baseDirectory", "type": "java.io.File" },
{ "name": "log", "type": "xsbti.Logger" },
{ "name": "updateOptions", "type": "sbt.librarymanagement.UpdateOptions" }
],
"types": [
{
"name": "InlineIvyConfiguration",
"namespace": "sbt.internal.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "paths", "type": "sbt.internal.librarymanagement.IvyPaths" },
{ "name": "resolvers", "type": "sbt.librarymanagement.Resolver*" },
{ "name": "otherResolvers", "type": "sbt.librarymanagement.Resolver*" },
{ "name": "moduleConfigurations", "type": "sbt.librarymanagement.ModuleConfiguration*" },
{ "name": "localOnly", "type": "boolean" },
{ "name": "checksums", "type": "String*" },
{ "name": "resolutionCacheDir", "type": "java.io.File?" }
],
"extra": [
"def this(",
" paths: sbt.internal.librarymanagement.IvyPaths,",
" resolvers: Vector[sbt.librarymanagement.Resolver],",
" otherResolvers: Vector[sbt.librarymanagement.Resolver],",
" moduleConfigurations: Vector[sbt.librarymanagement.ModuleConfiguration],",
" localOnly: Boolean,",
" lock: Option[xsbti.GlobalLock],",
" checksums: Vector[String],",
" resolutionCacheDir: Option[java.io.File],",
" updateOptions: sbt.librarymanagement.UpdateOptions,",
" log: xsbti.Logger",
") =",
" this(lock, paths.baseDirectory, log, updateOptions, paths, resolvers, otherResolvers,",
" moduleConfigurations, localOnly, checksums, resolutionCacheDir)"
]
},
{
"name": "ExternalIvyConfiguration",
"namespace": "sbt.internal.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "uri", "type": "java.net.URI" },
{ "name": "extraResolvers", "type": "sbt.librarymanagement.Resolver*" }
]
}
]
},
{
"name": "UpdateReportLite",
"namespace": "sbt.internal.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "configurations", "type": "sbt.internal.librarymanagement.ConfigurationReportLite*" }
]
},
{
"name": "ConfigurationReportLite",
"namespace": "sbt.internal.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "configuration", "type": "String" },
{ "name": "details", "type": "sbt.librarymanagement.OrganizationArtifactReport*" }
]
},
{
"name": "ModuleID",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"parents": "sbt.librarymanagement.ModuleIDParent",
"fields": [
{ "name": "organization", "type": "String" },
{ "name": "name", "type": "String" },
{ "name": "revision", "type": "String" },
{ "name": "configurations", "type": "String?", "default": "None", "since": "0.0.1" },
{ "name": "isChanging", "type": "boolean", "default": "false", "since": "0.0.1" },
{ "name": "isTransitive", "type": "boolean", "default": "true", "since": "0.0.1" },
{ "name": "isForce", "type": "boolean", "default": "false", "since": "0.0.1" },
{ "name": "explicitArtifacts", "type": "sbt.librarymanagement.Artifact*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "inclusions", "type": "sbt.librarymanagement.InclExclRule*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "exclusions", "type": "sbt.librarymanagement.InclExclRule*", "default": "Vector.empty", "since": "0.0.1" },
{ "name": "extraAttributes", "type": "Map[String, String]", "default": "Map.empty", "since": "0.0.1" },
{ "name": "crossVersion", "type": "sbt.librarymanagement.CrossVersion", "default": "sbt.librarymanagement.Disabled()", "since": "0.0.1" },
{ "name": "branchName", "type": "String?", "default": "None", "since": "0.0.1" }
],
"toString": [
"organization + \":\" + name + \":\" + revision +",
" (configurations match { case Some(s) => \":\" + s; case None => \"\" }) +",
" (if (extraAttributes.isEmpty) \"\" else \" \" + extraString)"
],
"parentsCompanion": "sbt.librarymanagement.ModuleIDCompanion"
},
{
"name": "ArtifactTypeFilter",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": "Work around the inadequacy of Ivy's ArtifactTypeFilter (that it cannot reverse a filter)",
"parents": "sbt.librarymanagement.ArtifactTypeFilterParent",
"fields": [
{
"name": "types",
"doc": [
"Represents the artifact types that we should try to resolve for (as in the allowed values of",
"`artifact[type]` from a dependency `<publications>` section). One can use this to filter",
"source / doc artifacts."
],
"type": "Set[String]"
},
{
"name": "inverted",
"doc": [ "Whether to invert the types filter (i.e. allow only types NOT in the set)" ],
"type": "boolean"
}
],
"parentsCompanion": "sbt.librarymanagement.ArtifactTypeFilterCompanion"
},
{
"name": "UpdateReport",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": [
"Provides information about dependency resolution.",
"It does not include information about evicted modules, only about the modules ultimately selected by the conflict manager.",
"This means that for a given configuration, there should only be one revision for a given organization and module name."
],
"parents": "sbt.librarymanagement.UpdateReportParent",
"fields": [
{
"name": "cachedDescriptor",
"type": "java.io.File",
"doc": [ "the location of the resolved module descriptor in the cache" ]
},
{
"name": "configurations",
"type": "sbt.librarymanagement.ConfigurationReport*",
"doc": [ "a sequence containing one report for each configuration resolved." ]
},
{
"name": "stats",
"type": "sbt.librarymanagement.UpdateStats",
"doc": [ "stats information about the update that produced this report" ]
},
{ "name": "stamps", "type": "Map[java.io.File, Long]" }
],
"toString": "\"Update report:\\n\\t\" + stats + \"\\n\" + configurations.mkString"
},
{
"name": "ConfigurationReport",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": [
"Provides information about resolution of a single configuration."
],
"parents": "sbt.librarymanagement.ConfigurationReportParent",
"fields": [
{ "name": "configuration", "type": "String", "doc": [ "the configuration this report is for." ] },
{
"name": "modules",
"type": "sbt.librarymanagement.ModuleReport*",
"doc": [
"a sequence containing one report for each module resolved for this configuration."
]
},
{
"name": "details",
"type": "sbt.librarymanagement.OrganizationArtifactReport*",
"doc": [ "a sequence containing one report for each org/name, which may or may not be part of the final resolution." ]
}
]
}
]
}

View File

@ -195,20 +195,20 @@ private[sbt] object ConvertResolver {
initializePatterns(resolver, repo.patterns, settings) initializePatterns(resolver, repo.patterns, settings)
initializeConnection(resolver, repo.connection) initializeConnection(resolver, repo.connection)
} }
private def initializeConnection(resolver: AbstractSshBasedResolver, connection: RepositoryHelpers.SshConnection): Unit = { private def initializeConnection(resolver: AbstractSshBasedResolver, connection: SshConnection): Unit = {
import resolver._ import resolver._
import connection._ import connection._
hostname.foreach(setHost) hostname.foreach(setHost)
port.foreach(setPort) port.foreach(setPort)
authentication foreach authentication foreach
{ {
case RepositoryHelpers.PasswordAuthentication(user, password) => case pa: PasswordAuthentication =>
setUser(user) setUser(pa.user)
password.foreach(setUserPassword) pa.password.foreach(setUserPassword)
case RepositoryHelpers.KeyFileAuthentication(user, file, password) => case kfa: KeyFileAuthentication =>
setKeyFile(file) setKeyFile(kfa.keyfile)
password.foreach(setKeyFilePassword) kfa.password.foreach(setKeyFilePassword)
setUser(user) setUser(kfa.user)
} }
} }
private def initializePatterns(resolver: AbstractPatternsBasedResolver, patterns: Patterns, settings: IvySettings): Unit = { private def initializePatterns(resolver: AbstractPatternsBasedResolver, patterns: Patterns, settings: IvySettings): Unit = {

View File

@ -30,8 +30,9 @@ import sbt.util.Logger
import sbt.librarymanagement._ import sbt.librarymanagement._
import Resolver.PluginPattern import Resolver.PluginPattern
import ivyint.{ CachedResolutionResolveEngine, CachedResolutionResolveCache, SbtDefaultDependencyDescriptor } import ivyint.{ CachedResolutionResolveEngine, CachedResolutionResolveCache, SbtDefaultDependencyDescriptor }
import sbt.internal.util.CacheStore
final class IvySbt(val configuration: IvyConfiguration) { final class IvySbt(val configuration: IvyConfiguration, fileToStore: File => CacheStore) { self =>
import configuration.baseDirectory import configuration.baseDirectory
/* /*
@ -92,7 +93,8 @@ final class IvySbt(val configuration: IvyConfiguration) {
setEventManager(new EventManager()) setEventManager(new EventManager())
if (configuration.updateOptions.cachedResolution) { if (configuration.updateOptions.cachedResolution) {
setResolveEngine(new ResolveEngine(getSettings, getEventManager, getSortEngine) with CachedResolutionResolveEngine { setResolveEngine(new ResolveEngine(getSettings, getEventManager, getSortEngine) with CachedResolutionResolveEngine {
val cachedResolutionResolveCache = IvySbt.cachedResolutionResolveCache override private[sbt] val fileToStore: File => CacheStore = self.fileToStore
val cachedResolutionResolveCache = IvySbt.cachedResolutionResolveCache(fileToStore)
val projectResolver = prOpt val projectResolver = prOpt
def makeInstance = mkIvy def makeInstance = mkIvy
}) })
@ -139,7 +141,7 @@ final class IvySbt(val configuration: IvyConfiguration) {
withIvy(log) { i => withIvy(log) { i =>
val prOpt = Option(i.getSettings.getResolver(ProjectResolver.InterProject)) map { case pr: ProjectResolver => pr } val prOpt = Option(i.getSettings.getResolver(ProjectResolver.InterProject)) map { case pr: ProjectResolver => pr }
if (configuration.updateOptions.cachedResolution) { if (configuration.updateOptions.cachedResolution) {
IvySbt.cachedResolutionResolveCache.clean(md, prOpt) IvySbt.cachedResolutionResolveCache(fileToStore).clean(md, prOpt)
} }
} }
@ -236,8 +238,8 @@ private[sbt] object IvySbt {
val DefaultIvyConfigFilename = "ivysettings.xml" val DefaultIvyConfigFilename = "ivysettings.xml"
val DefaultIvyFilename = "ivy.xml" val DefaultIvyFilename = "ivy.xml"
val DefaultMavenFilename = "pom.xml" val DefaultMavenFilename = "pom.xml"
val DefaultChecksums = Seq("sha1", "md5") val DefaultChecksums = Vector("sha1", "md5")
private[sbt] val cachedResolutionResolveCache: CachedResolutionResolveCache = new CachedResolutionResolveCache() private[sbt] def cachedResolutionResolveCache(fileToStore: File => CacheStore): CachedResolutionResolveCache = new CachedResolutionResolveCache(fileToStore)
def defaultIvyFile(project: File) = new File(project, DefaultIvyFilename) def defaultIvyFile(project: File) = new File(project, DefaultIvyFilename)
def defaultIvyConfiguration(project: File) = new File(project, DefaultIvyConfigFilename) def defaultIvyConfiguration(project: File) = new File(project, DefaultIvyConfigFilename)
@ -305,8 +307,8 @@ private[sbt] object IvySbt {
*/ */
def hasImplicitClassifier(artifact: IArtifact): Boolean = def hasImplicitClassifier(artifact: IArtifact): Boolean =
{ {
import collection.JavaConversions._ import scala.collection.JavaConverters._
artifact.getQualifiedExtraAttributes.keys.exists(_.asInstanceOf[String] startsWith "m:") artifact.getQualifiedExtraAttributes.asScala.keys.exists(_.asInstanceOf[String] startsWith "m:")
} }
private def setModuleConfigurations(settings: IvySettings, moduleConfigurations: Seq[ModuleConfiguration], log: Logger): Unit = { private def setModuleConfigurations(settings: IvySettings, moduleConfigurations: Seq[ModuleConfiguration], log: Logger): Unit = {
val existing = settings.getResolverNames val existing = settings.getResolverNames
@ -426,7 +428,7 @@ private[sbt] object IvySbt {
{ {
val sub = CrossVersion(scalaFullVersion, scalaBinaryVersion) val sub = CrossVersion(scalaFullVersion, scalaBinaryVersion)
m match { m match {
case ic: InlineConfiguration => ic.copy(module = sub(ic.module), dependencies = ic.dependencies map sub, overrides = ic.overrides map sub) case ic: InlineConfiguration => ic.withModule(sub(ic.module)).withDependencies(ic.dependencies map sub).withOverrides(ic.overrides map sub)
case _ => m case _ => m
} }
} }
@ -439,7 +441,7 @@ private[sbt] object IvySbt {
} }
def getExtraAttributes(revID: ExtendableItem): Map[String, String] = def getExtraAttributes(revID: ExtendableItem): Map[String, String] =
{ {
import collection.JavaConverters._ import scala.collection.JavaConverters._
revID.getExtraAttributes.asInstanceOf[java.util.Map[String, String]].asScala.toMap revID.getExtraAttributes.asInstanceOf[java.util.Map[String, String]].asScala.toMap
} }
private[sbt] def extra(artifact: Artifact, unqualify: Boolean = false): java.util.Map[String, String] = private[sbt] def extra(artifact: Artifact, unqualify: Boolean = false): java.util.Map[String, String] =
@ -449,8 +451,9 @@ private[sbt] object IvySbt {
} }
private[sbt] def javaMap(m: Map[String, String], unqualify: Boolean = false) = private[sbt] def javaMap(m: Map[String, String], unqualify: Boolean = false) =
{ {
import scala.collection.JavaConverters._
val map = if (unqualify) m map { case (k, v) => (k.stripPrefix("e:"), v) } else m val map = if (unqualify) m map { case (k, v) => (k.stripPrefix("e:"), v) } else m
if (map.isEmpty) null else scala.collection.JavaConversions.mapAsJavaMap(map) if (map.isEmpty) null else map.asJava
} }
/** Creates a full ivy file for 'module' using the 'dependencies' XML as the part after the &lt;info&gt;...&lt;/info&gt; section. */ /** Creates a full ivy file for 'module' using the 'dependencies' XML as the part after the &lt;info&gt;...&lt;/info&gt; section. */
@ -514,7 +517,7 @@ private[sbt] object IvySbt {
val dds = moduleID.getDependencies val dds = moduleID.getDependencies
val deps = dds flatMap { dd => val deps = dds flatMap { dd =>
val module = toModuleID(dd.getDependencyRevisionId) val module = toModuleID(dd.getDependencyRevisionId)
dd.getModuleConfigurations map (c => module.copy(configurations = Some(c))) dd.getModuleConfigurations map (c => module.withConfigurations(Some(c)))
} }
inconsistentDuplicateWarning(deps) inconsistentDuplicateWarning(deps)
} }
@ -571,7 +574,7 @@ private[sbt] object IvySbt {
deps.put(id, updated) deps.put(id, updated)
} }
import collection.JavaConverters._ import scala.collection.JavaConverters._
deps.values.asScala.toSeq.flatMap { dds => deps.values.asScala.toSeq.flatMap { dds =>
val mergeable = (dds, dds.tail).zipped.forall(ivyint.MergeDescriptors.mergeable _) val mergeable = (dds, dds.tail).zipped.forall(ivyint.MergeDescriptors.mergeable _)
if (mergeable) dds.reverse.reduceLeft(ivyint.MergeDescriptors.apply _) :: Nil else dds if (mergeable) dds.reverse.reduceLeft(ivyint.MergeDescriptors.apply _) :: Nil else dds
@ -652,7 +655,7 @@ private[sbt] object IvySbt {
val overridden = overrides.map(id => (key(id), id.revision)).toMap val overridden = overrides.map(id => (key(id), id.revision)).toMap
dependencies map { dep => dependencies map { dep =>
overridden get key(dep) match { overridden get key(dep) match {
case Some(rev) => dep.copy(revision = rev) case Some(rev) => dep.withRevision(rev)
case None => dep case None => dep
} }
} }

View File

@ -21,36 +21,19 @@ import sbt.util.Logger
import sbt.internal.util.{ ShowLines, SourcePosition, LinePosition, RangePosition, LineRange } import sbt.internal.util.{ ShowLines, SourcePosition, LinePosition, RangePosition, LineRange }
import sbt.librarymanagement._ import sbt.librarymanagement._
import sbt.internal.librarymanagement.syntax._ import sbt.internal.librarymanagement.syntax._
import sbt.internal.librarymanagement._
final class DeliverConfiguration(val deliverIvyPattern: String, val status: String, val configurations: Option[Seq[Configuration]], val logging: UpdateLogging.Value) final class DeliverConfiguration(val deliverIvyPattern: String, val status: String, val configurations: Option[Vector[Configuration]], val logging: UpdateLogging)
final class PublishConfiguration(val ivyFile: Option[File], val resolverName: String, val artifacts: Map[Artifact, File], val checksums: Seq[String], val logging: UpdateLogging.Value, final class PublishConfiguration(val ivyFile: Option[File], val resolverName: String, val artifacts: Map[Artifact, File], val checksums: Vector[String], val logging: UpdateLogging,
val overwrite: Boolean) { val overwrite: Boolean) {
def this(ivyFile: Option[File], resolverName: String, artifacts: Map[Artifact, File], checksums: Seq[String], logging: UpdateLogging.Value) = def this(ivyFile: Option[File], resolverName: String, artifacts: Map[Artifact, File], checksums: Vector[String], logging: UpdateLogging) =
this(ivyFile, resolverName, artifacts, checksums, logging, false) this(ivyFile, resolverName, artifacts, checksums, logging, false)
} }
final class UpdateConfiguration(val retrieve: Option[RetrieveConfiguration], val missingOk: Boolean, val logging: UpdateLogging.Value, val artifactFilter: ArtifactTypeFilter) { final case class MakePomConfiguration(file: File, moduleInfo: ModuleInfo, configurations: Option[Vector[Configuration]] = None, extra: NodeSeq = NodeSeq.Empty, process: XNode => XNode = n => n, filterRepositories: MavenRepository => Boolean = _ => true, allRepositories: Boolean, includeTypes: Set[String] = Set(Artifact.DefaultType, Artifact.PomType))
@deprecated("You should use the constructor that provides an artifactFilter", "1.0.x")
def this(retrieve: Option[RetrieveConfiguration], missingOk: Boolean, logging: UpdateLogging.Value) {
this(retrieve, missingOk, logging, ArtifactTypeFilter.forbid(Set("src", "doc"))) // allow everything but "src", "doc" by default
}
private[sbt] def copy(
retrieve: Option[RetrieveConfiguration] = this.retrieve,
missingOk: Boolean = this.missingOk,
logging: UpdateLogging.Value = this.logging,
artifactFilter: ArtifactTypeFilter = this.artifactFilter
): UpdateConfiguration =
new UpdateConfiguration(retrieve, missingOk, logging, artifactFilter)
}
final class RetrieveConfiguration(val retrieveDirectory: File, val outputPattern: String, val sync: Boolean, val configurationsToRetrieve: Option[Set[Configuration]]) {
def this(retrieveDirectory: File, outputPattern: String) = this(retrieveDirectory, outputPattern, false, None)
def this(retrieveDirectory: File, outputPattern: String, sync: Boolean) = this(retrieveDirectory, outputPattern, sync, None)
}
final case class MakePomConfiguration(file: File, moduleInfo: ModuleInfo, configurations: Option[Seq[Configuration]] = None, extra: NodeSeq = NodeSeq.Empty, process: XNode => XNode = n => n, filterRepositories: MavenRepository => Boolean = _ => true, allRepositories: Boolean, includeTypes: Set[String] = Set(Artifact.DefaultType, Artifact.PomType))
/** @param exclude is a map from ModuleID to classifiers that were previously tried and failed, so should now be excluded */ /** @param exclude is a map from ModuleID to classifiers that were previously tried and failed, so should now be excluded */
final case class GetClassifiersConfiguration(module: GetClassifiersModule, exclude: Map[ModuleID, Set[String]], configuration: UpdateConfiguration, ivyScala: Option[IvyScala], sourceArtifactTypes: Set[String], docArtifactTypes: Set[String]) final case class GetClassifiersConfiguration(module: GetClassifiersModule, exclude: Map[ModuleID, Set[String]], configuration: UpdateConfiguration, ivyScala: Option[IvyScala], sourceArtifactTypes: Set[String], docArtifactTypes: Set[String])
final case class GetClassifiersModule(id: ModuleID, modules: Seq[ModuleID], configurations: Seq[Configuration], classifiers: Seq[String]) final case class GetClassifiersModule(id: ModuleID, modules: Vector[ModuleID], configurations: Vector[Configuration], classifiers: Vector[String])
final class UnresolvedWarningConfiguration private[sbt] ( final class UnresolvedWarningConfiguration private[sbt] (
val modulePositions: Map[ModuleID, SourcePosition] val modulePositions: Map[ModuleID, SourcePosition]
@ -61,17 +44,6 @@ object UnresolvedWarningConfiguration {
new UnresolvedWarningConfiguration(modulePositions) new UnresolvedWarningConfiguration(modulePositions)
} }
/**
* Configures logging during an 'update'. `level` determines the amount of other information logged.
* `Full` is the default and logs the most.
* `DownloadOnly` only logs what is downloaded.
* `Quiet` only displays errors.
* `Default` uses the current log level of `update` task.
*/
object UpdateLogging extends Enumeration {
val Full, DownloadOnly, Quiet, Default = Value
}
object IvyActions { object IvyActions {
/** Installs the dependencies of the given 'module' from the resolver named 'from' to the resolver named 'to'.*/ /** Installs the dependencies of the given 'module' from the resolver named 'from' to the resolver named 'to'.*/
def install(module: IvySbt#Module, from: String, to: String, log: Logger): Unit = { def install(module: IvySbt#Module, from: String, to: String, log: Logger): Unit = {
@ -133,13 +105,13 @@ object IvyActions {
if (resolver eq null) sys.error("Undefined resolver '" + resolverName + "'") if (resolver eq null) sys.error("Undefined resolver '" + resolverName + "'")
val ivyArtifact = ivyFile map { file => (MDArtifact.newIvyArtifact(md), file) } val ivyArtifact = ivyFile map { file => (MDArtifact.newIvyArtifact(md), file) }
val cross = crossVersionMap(module.moduleSettings) val cross = crossVersionMap(module.moduleSettings)
val as = mapArtifacts(md, cross, artifacts) ++ ivyArtifact.toSeq val as = mapArtifacts(md, cross, artifacts) ++ ivyArtifact.toList
withChecksums(resolver, checksums) { publish(md, as, resolver, overwrite = overwrite) } withChecksums(resolver, checksums) { publish(md, as, resolver, overwrite = overwrite) }
} }
} }
private[this] def withChecksums[T](resolver: DependencyResolver, checksums: Seq[String])(act: => T): T = private[this] def withChecksums[T](resolver: DependencyResolver, checksums: Vector[String])(act: => T): T =
resolver match { case br: BasicResolver => withChecksums(br, checksums)(act); case _ => act } resolver match { case br: BasicResolver => withChecksums(br, checksums)(act); case _ => act }
private[this] def withChecksums[T](resolver: BasicResolver, checksums: Seq[String])(act: => T): T = private[this] def withChecksums[T](resolver: BasicResolver, checksums: Vector[String])(act: => T): T =
{ {
val previous = resolver.getChecksumAlgorithms val previous = resolver.getChecksumAlgorithms
resolver.setChecksums(checksums mkString ",") resolver.setChecksums(checksums mkString ",")
@ -151,9 +123,9 @@ object IvyActions {
case i: InlineConfiguration => CrossVersion(i.module, i.ivyScala) case i: InlineConfiguration => CrossVersion(i.module, i.ivyScala)
case _ => None case _ => None
} }
def mapArtifacts(module: ModuleDescriptor, cross: Option[String => String], artifacts: Map[Artifact, File]): Seq[(IArtifact, File)] = def mapArtifacts(module: ModuleDescriptor, cross: Option[String => String], artifacts: Map[Artifact, File]): Vector[(IArtifact, File)] =
{ {
val rawa = artifacts.keys.toSeq val rawa = artifacts.keys.toVector
val seqa = CrossVersion.substituteCross(rawa, cross) val seqa = CrossVersion.substituteCross(rawa, cross)
val zipped = rawa zip IvySbt.mapArtifacts(module, seqa) val zipped = rawa zip IvySbt.mapArtifacts(module, seqa)
zipped map { case (a, ivyA) => (ivyA, artifacts(a)) } zipped map { case (a, ivyA) => (ivyA, artifacts(a)) }
@ -235,8 +207,8 @@ object IvyActions {
{ {
import config.{ configuration => c, ivyScala, module => mod } import config.{ configuration => c, ivyScala, module => mod }
import mod.{ id, modules => deps } import mod.{ id, modules => deps }
val base = restrictedCopy(id, true).copy(name = id.name + "$" + label) val base = restrictedCopy(id, true).withName(id.name + "$" + label)
val module = new ivySbt.Module(InlineConfiguration(base, ModuleInfo(base.name), deps).copy(ivyScala = ivyScala)) val module = new ivySbt.Module(InlineConfiguration(false, ivyScala, base, ModuleInfo(base.name), deps))
val report = updateEither(module, c, uwconfig, logicalClock, depDir, log) match { val report = updateEither(module, c, uwconfig, logicalClock, depDir, log) match {
case Right(r) => r case Right(r) => r
case Left(w) => case Left(w) =>
@ -270,10 +242,10 @@ object IvyActions {
val baseModules = modules map { m => restrictedCopy(m, true) } val baseModules = modules map { m => restrictedCopy(m, true) }
// Adding list of explicit artifacts here. // Adding list of explicit artifacts here.
val deps = baseModules.distinct flatMap classifiedArtifacts(classifiers, exclude, artifacts) val deps = baseModules.distinct flatMap classifiedArtifacts(classifiers, exclude, artifacts)
val base = restrictedCopy(id, true).copy(name = id.name + classifiers.mkString("$", "_", "")) val base = restrictedCopy(id, true).withName(id.name + classifiers.mkString("$", "_", ""))
val module = new ivySbt.Module(InlineConfiguration(base, ModuleInfo(base.name), deps).copy(ivyScala = ivyScala, configurations = confs)) val module = new ivySbt.Module(InlineConfiguration(false, ivyScala, base, ModuleInfo(base.name), deps).withConfigurations(confs))
// c.copy ensures c.types is preserved too // c.copy ensures c.types is preserved too
val upConf = c.copy(missingOk = true) val upConf = c.withMissingOk(true)
updateEither(module, upConf, uwconfig, logicalClock, depDir, log) match { updateEither(module, upConf, uwconfig, logicalClock, depDir, log) match {
case Right(r) => case Right(r) =>
// The artifacts that came from Ivy don't have their classifier set, let's set it according to // The artifacts that came from Ivy don't have their classifier set, let's set it according to
@ -285,7 +257,7 @@ object IvyActions {
artFileSeq map { artFileSeq map {
case (art, f) => case (art, f) =>
// Deduce the classifier from the type if no classifier is present already // Deduce the classifier from the type if no classifier is present already
art.copy(classifier = art.classifier orElse typeClassifierMap.get(art.`type`)) -> f art.withClassifier(art.classifier orElse typeClassifierMap.get(art.`type`)) -> f
} }
} }
case Left(w) => case Left(w) =>
@ -294,7 +266,7 @@ object IvyActions {
} }
// This version adds explicit artifact // This version adds explicit artifact
private[sbt] def classifiedArtifacts( private[sbt] def classifiedArtifacts(
classifiers: Seq[String], classifiers: Vector[String],
exclude: Map[ModuleID, Set[String]], exclude: Map[ModuleID, Set[String]],
artifacts: Vector[(String, ModuleID, Artifact, File)] artifacts: Vector[(String, ModuleID, Artifact, File)]
)(m: ModuleID): Option[ModuleID] = { )(m: ModuleID): Option[ModuleID] = {
@ -308,7 +280,7 @@ object IvyActions {
def hardcodedArtifacts = classifiedArtifacts(classifiers, exclude)(m) def hardcodedArtifacts = classifiedArtifacts(classifiers, exclude)(m)
explicitArtifacts orElse hardcodedArtifacts explicitArtifacts orElse hardcodedArtifacts
} }
private def classifiedArtifacts(classifiers: Seq[String], exclude: Map[ModuleID, Set[String]])(m: ModuleID): Option[ModuleID] = private def classifiedArtifacts(classifiers: Vector[String], exclude: Map[ModuleID, Set[String]])(m: ModuleID): Option[ModuleID] =
{ {
val excluded = exclude getOrElse (restrictedCopy(m, false), Set.empty) val excluded = exclude getOrElse (restrictedCopy(m, false), Set.empty)
val included = classifiers filterNot excluded val included = classifiers filterNot excluded
@ -330,12 +302,12 @@ object IvyActions {
* }}} * }}}
* `usage.getDependencyIncludesSet` returns null if there are no (explicit) include rules. * `usage.getDependencyIncludesSet` returns null if there are no (explicit) include rules.
*/ */
private def intransitiveModuleWithExplicitArts(module: ModuleID, arts: Seq[Artifact]): ModuleID = private def intransitiveModuleWithExplicitArts(module: ModuleID, arts: Vector[Artifact]): ModuleID =
module.copy(isTransitive = false, explicitArtifacts = arts, inclusions = InclExclRule.everything :: Nil) module.withIsTransitive(false).withExplicitArtifacts(arts).withInclusions(Vector(InclExclRule.everything))
def addExcluded(report: UpdateReport, classifiers: Seq[String], exclude: Map[ModuleID, Set[String]]): UpdateReport = def addExcluded(report: UpdateReport, classifiers: Vector[String], exclude: Map[ModuleID, Set[String]]): UpdateReport =
report.addMissing { id => classifiedArtifacts(id.name, classifiers filter getExcluded(id, exclude)) } report.addMissing { id => classifiedArtifacts(id.name, classifiers filter getExcluded(id, exclude)) }
def classifiedArtifacts(name: String, classifiers: Seq[String]): Seq[Artifact] = def classifiedArtifacts(name: String, classifiers: Vector[String]): Vector[Artifact] =
classifiers map { c => Artifact.classified(name, c) } classifiers map { c => Artifact.classified(name, c) }
private[this] def getExcluded(id: ModuleID, exclude: Map[ModuleID, Set[String]]): Set[String] = private[this] def getExcluded(id: ModuleID, exclude: Map[ModuleID, Set[String]]): Set[String] =
exclude.getOrElse(restrictedCopy(id, false), Set.empty[String]) exclude.getOrElse(restrictedCopy(id, false), Set.empty[String])
@ -344,10 +316,10 @@ object IvyActions {
report.allMissing flatMap { case (_, mod, art) => art.classifier.map { c => (restrictedCopy(mod, false), c) } } groupBy (_._1) map { case (mod, pairs) => (mod, pairs.map(_._2).toSet) } report.allMissing flatMap { case (_, mod, art) => art.classifier.map { c => (restrictedCopy(mod, false), c) } } groupBy (_._1) map { case (mod, pairs) => (mod, pairs.map(_._2).toSet) }
private[this] def restrictedCopy(m: ModuleID, confs: Boolean) = private[this] def restrictedCopy(m: ModuleID, confs: Boolean) =
ModuleID(m.organization, m.name, m.revision, crossVersion = m.crossVersion, extraAttributes = m.extraAttributes, configurations = if (confs) m.configurations else None) ModuleID(m.organization, m.name, m.revision).withCrossVersion(m.crossVersion).withExtraAttributes(m.extraAttributes).withConfigurations(if (confs) m.configurations else None)
.branch(m.branchName) .branch(m.branchName)
private[this] def resolve(logging: UpdateLogging.Value)(ivy: Ivy, module: DefaultModuleDescriptor, defaultConf: String, filter: ArtifactTypeFilter): (ResolveReport, Option[ResolveException]) = private[this] def resolve(logging: UpdateLogging)(ivy: Ivy, module: DefaultModuleDescriptor, defaultConf: String, filter: ArtifactTypeFilter): (ResolveReport, Option[ResolveException]) =
{ {
val resolveOptions = new ResolveOptions val resolveOptions = new ResolveOptions
val resolveId = ResolveOptions.getDefaultResolveId(module) val resolveId = ResolveOptions.getDefaultResolveId(module)
@ -420,7 +392,7 @@ object IvyActions {
import UpdateLogging.{ Quiet, Full, DownloadOnly, Default } import UpdateLogging.{ Quiet, Full, DownloadOnly, Default }
import LogOptions.{ LOG_QUIET, LOG_DEFAULT, LOG_DOWNLOAD_ONLY } import LogOptions.{ LOG_QUIET, LOG_DEFAULT, LOG_DOWNLOAD_ONLY }
private def ivyLogLevel(level: UpdateLogging.Value) = private def ivyLogLevel(level: UpdateLogging) =
level match { level match {
case Quiet => LOG_QUIET case Quiet => LOG_QUIET
case DownloadOnly => LOG_DOWNLOAD_ONLY case DownloadOnly => LOG_DOWNLOAD_ONLY

View File

@ -15,6 +15,14 @@ import sbt.io.Path
import sbt.util.Logger import sbt.util.Logger
import sbt.librarymanagement._ import sbt.librarymanagement._
import sbt.internal.util.{ CacheStore, FileBasedStore }
import scala.json.ast.unsafe._
import scala.collection.mutable
import jawn.{ SupportParser, MutableFacade }
import sjsonnew.IsoString
import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter }
class NotInCache(val id: ModuleID, cause: Throwable) class NotInCache(val id: ModuleID, cause: Throwable)
extends RuntimeException(NotInCache(id, cause), cause) { extends RuntimeException(NotInCache(id, cause), cause) {
def this(id: ModuleID) = this(id, null) def this(id: ModuleID) = this(id, null)
@ -27,7 +35,9 @@ private object NotInCache {
} }
} }
/** Provides methods for working at the level of a single jar file with the default Ivy cache.*/ /** Provides methods for working at the level of a single jar file with the default Ivy cache.*/
class IvyCache(val ivyHome: Option[File]) { class IvyCache(val ivyHome: Option[File], fileToStore: File => CacheStore) {
def this(ivyHome: Option[File]) = this(ivyHome, DefaultFileToStore)
def lockFile = new File(ivyHome getOrElse Path.userHome, ".sbt.cache.lock") def lockFile = new File(ivyHome getOrElse Path.userHome, ".sbt.cache.lock")
/** Caches the given 'file' with the given ID. It may be retrieved or cleared using this ID.*/ /** Caches the given 'file' with the given ID. It may be retrieved or cleared using this ID.*/
def cacheJar(moduleID: ModuleID, file: File, lock: Option[xsbti.GlobalLock], log: Logger): Unit = { def cacheJar(moduleID: ModuleID, file: File, lock: Option[xsbti.GlobalLock], log: Logger): Unit = {
@ -81,8 +91,8 @@ class IvyCache(val ivyHome: Option[File]) {
{ {
val local = Resolver.defaultLocal val local = Resolver.defaultLocal
val paths = new IvyPaths(new File("."), ivyHome) val paths = new IvyPaths(new File("."), ivyHome)
val conf = new InlineIvyConfiguration(paths, Seq(local), Nil, Nil, false, lock, IvySbt.DefaultChecksums, None, UpdateOptions(), log) val conf = new InlineIvyConfiguration(paths, Vector(local), Vector.empty, Vector.empty, false, lock, IvySbt.DefaultChecksums, None, UpdateOptions(), log)
(new IvySbt(conf), local) (new IvySbt(conf, fileToStore), local)
} }
/** Creates a default jar artifact based on the given ID.*/ /** Creates a default jar artifact based on the given ID.*/
private def defaultArtifact(moduleID: ModuleID): IvyArtifact = private def defaultArtifact(moduleID: ModuleID): IvyArtifact =
@ -98,3 +108,31 @@ private class FileDownloader extends ResourceDownloader {
sys.error("Could not move temporary file " + part + " to final location " + dest) sys.error("Could not move temporary file " + part + " to final location " + dest)
} }
} }
object FixedParser extends SupportParser[JValue] {
implicit val facade: MutableFacade[JValue] =
new MutableFacade[JValue] {
def jnull() = JNull
def jfalse() = JFalse
def jtrue() = JTrue
def jnum(s: String) = JNumber(s)
def jint(s: String) = JNumber(s)
def jstring(s: String) = JString(s)
def jarray(vs: mutable.ArrayBuffer[JValue]) = JArray(vs.toArray)
def jobject(vs: mutable.Map[String, JValue]) = {
val array = new Array[JField](vs.size)
var i = 0
vs.foreach {
case (key, value) =>
array(i) = JField(key, value)
i += 1
}
JObject(array)
}
}
}
object DefaultFileToStore extends (File => CacheStore) {
private implicit lazy val isoString: IsoString[JValue] = IsoString.iso(CompactPrinter.apply _, FixedParser.parseUnsafe _)
override def apply(f: File): CacheStore = new FileBasedStore(f, Converter)
}

View File

@ -3,206 +3,9 @@
*/ */
package sbt.internal.librarymanagement package sbt.internal.librarymanagement
import java.io.File
import java.net.URI
import scala.xml.NodeSeq
import sbt.util.Logger
import sbt.librarymanagement._ import sbt.librarymanagement._
final class IvyPaths(val baseDirectory: File, val ivyHome: Option[File]) { abstract class InlineConfigurationCompanion {
def withBase(newBaseDirectory: File) = new IvyPaths(newBaseDirectory, ivyHome)
override def toString = s"IvyPaths($baseDirectory, $ivyHome)"
}
sealed trait IvyConfiguration {
type This <: IvyConfiguration
def lock: Option[xsbti.GlobalLock]
def baseDirectory: File
def log: Logger
def withBase(newBaseDirectory: File): This
def updateOptions: UpdateOptions
}
final class InlineIvyConfiguration(val paths: IvyPaths, val resolvers: Seq[Resolver], val otherResolvers: Seq[Resolver],
val moduleConfigurations: Seq[ModuleConfiguration], val localOnly: Boolean, val lock: Option[xsbti.GlobalLock],
val checksums: Seq[String], val resolutionCacheDir: Option[File], val updateOptions: UpdateOptions,
val log: Logger) extends IvyConfiguration {
@deprecated("Use the variant that accepts resolutionCacheDir and updateOptions.", "0.13.0")
def this(paths: IvyPaths, resolvers: Seq[Resolver], otherResolvers: Seq[Resolver],
moduleConfigurations: Seq[ModuleConfiguration], localOnly: Boolean, lock: Option[xsbti.GlobalLock],
checksums: Seq[String], log: Logger) =
this(paths, resolvers, otherResolvers, moduleConfigurations, localOnly, lock, checksums, None, UpdateOptions(), log)
@deprecated("Use the variant that accepts updateOptions.", "0.13.6")
def this(paths: IvyPaths, resolvers: Seq[Resolver], otherResolvers: Seq[Resolver],
moduleConfigurations: Seq[ModuleConfiguration], localOnly: Boolean, lock: Option[xsbti.GlobalLock],
checksums: Seq[String], resolutionCacheDir: Option[File], log: Logger) =
this(paths, resolvers, otherResolvers, moduleConfigurations, localOnly, lock, checksums, resolutionCacheDir, UpdateOptions(), log)
override def toString: String = s"InlineIvyConfiguration($paths, $resolvers, $otherResolvers, " +
s"$moduleConfigurations, $localOnly, $checksums, $resolutionCacheDir, $updateOptions)"
type This = InlineIvyConfiguration
def baseDirectory = paths.baseDirectory
def withBase(newBase: File) = new InlineIvyConfiguration(paths.withBase(newBase), resolvers, otherResolvers, moduleConfigurations, localOnly, lock, checksums,
resolutionCacheDir, updateOptions, log)
def changeResolvers(newResolvers: Seq[Resolver]) = new InlineIvyConfiguration(paths, newResolvers, otherResolvers, moduleConfigurations, localOnly, lock, checksums,
resolutionCacheDir, updateOptions, log)
override def equals(o: Any): Boolean = o match {
case o: InlineIvyConfiguration =>
this.paths == o.paths &&
this.resolvers == o.resolvers &&
this.otherResolvers == o.otherResolvers &&
this.moduleConfigurations == o.moduleConfigurations &&
this.localOnly == o.localOnly &&
this.checksums == o.checksums &&
this.resolutionCacheDir == o.resolutionCacheDir &&
this.updateOptions == o.updateOptions
case _ => false
}
override def hashCode: Int =
{
var hash = 1
hash = hash * 31 + this.paths.##
hash = hash * 31 + this.resolvers.##
hash = hash * 31 + this.otherResolvers.##
hash = hash * 31 + this.moduleConfigurations.##
hash = hash * 31 + this.localOnly.##
hash = hash * 31 + this.checksums.##
hash = hash * 31 + this.resolutionCacheDir.##
hash = hash * 31 + this.updateOptions.##
hash
}
}
final class ExternalIvyConfiguration(val baseDirectory: File, val uri: URI, val lock: Option[xsbti.GlobalLock],
val extraResolvers: Seq[Resolver], val updateOptions: UpdateOptions, val log: Logger) extends IvyConfiguration {
@deprecated("Use the variant that accepts updateOptions.", "0.13.6")
def this(baseDirectory: File, uri: URI, lock: Option[xsbti.GlobalLock], extraResolvers: Seq[Resolver], log: Logger) =
this(baseDirectory, uri, lock, extraResolvers, UpdateOptions(), log)
type This = ExternalIvyConfiguration
def withBase(newBase: File) = new ExternalIvyConfiguration(newBase, uri, lock, extraResolvers, UpdateOptions(), log)
}
object ExternalIvyConfiguration {
def apply(baseDirectory: File, file: File, lock: Option[xsbti.GlobalLock], log: Logger) = new ExternalIvyConfiguration(baseDirectory, file.toURI, lock, Nil, UpdateOptions(), log)
}
object IvyConfiguration {
/**
* Called to configure Ivy when inline resolvers are not specified.
* This will configure Ivy with an 'ivy-settings.xml' file if there is one or else use default resolvers.
*/
@deprecated("Explicitly use either external or inline configuration.", "0.12.0")
def apply(paths: IvyPaths, lock: Option[xsbti.GlobalLock], localOnly: Boolean, checksums: Seq[String], log: Logger): IvyConfiguration =
{
log.debug("Autodetecting configuration.")
val defaultIvyConfigFile = IvySbt.defaultIvyConfiguration(paths.baseDirectory)
if (defaultIvyConfigFile.canRead)
ExternalIvyConfiguration(paths.baseDirectory, defaultIvyConfigFile, lock, log)
else
new InlineIvyConfiguration(paths, Resolver.withDefaultResolvers(Nil), Nil, Nil, localOnly, lock, checksums, None, log)
}
}
sealed trait ModuleSettings {
def validate: Boolean
def ivyScala: Option[IvyScala]
def noScala: ModuleSettings
}
final case class IvyFileConfiguration(file: File, ivyScala: Option[IvyScala], validate: Boolean, autoScalaTools: Boolean = true) extends ModuleSettings {
def noScala = copy(ivyScala = None)
}
final case class PomConfiguration(file: File, ivyScala: Option[IvyScala], validate: Boolean, autoScalaTools: Boolean = true) extends ModuleSettings {
def noScala = copy(ivyScala = None)
}
final class InlineConfiguration private[sbt] (
val module: ModuleID,
val moduleInfo: ModuleInfo,
val dependencies: Seq[ModuleID],
val overrides: Set[ModuleID],
val excludes: Seq[SbtExclusionRule],
val ivyXML: NodeSeq,
val configurations: Seq[Configuration],
val defaultConfiguration: Option[Configuration],
val ivyScala: Option[IvyScala],
val validate: Boolean,
val conflictManager: ConflictManager
) extends ModuleSettings {
def withConfigurations(configurations: Seq[Configuration]) = copy(configurations = configurations)
def noScala = copy(ivyScala = None)
def withOverrides(overrides: Set[ModuleID]): ModuleSettings =
copy(overrides = overrides)
private[sbt] def copy(
module: ModuleID = this.module,
moduleInfo: ModuleInfo = this.moduleInfo,
dependencies: Seq[ModuleID] = this.dependencies,
overrides: Set[ModuleID] = this.overrides,
excludes: Seq[SbtExclusionRule] = this.excludes,
ivyXML: NodeSeq = this.ivyXML,
configurations: Seq[Configuration] = this.configurations,
defaultConfiguration: Option[Configuration] = this.defaultConfiguration,
ivyScala: Option[IvyScala] = this.ivyScala,
validate: Boolean = this.validate,
conflictManager: ConflictManager = this.conflictManager
): InlineConfiguration =
InlineConfiguration(module, moduleInfo, dependencies, overrides, excludes, ivyXML,
configurations, defaultConfiguration, ivyScala, validate, conflictManager)
override def toString: String =
s"InlineConfiguration($module, $moduleInfo, $dependencies, $overrides, $excludes, " +
s"$ivyXML, $configurations, $defaultConfiguration, $ivyScala, $validate, $conflictManager)"
override def equals(o: Any): Boolean = o match {
case o: InlineConfiguration =>
this.module == o.module &&
this.moduleInfo == o.moduleInfo &&
this.dependencies == o.dependencies &&
this.overrides == o.overrides &&
this.excludes == o.excludes &&
this.ivyXML == o.ivyXML &&
this.configurations == o.configurations &&
this.defaultConfiguration == o.defaultConfiguration &&
this.ivyScala == o.ivyScala &&
this.validate == o.validate &&
this.conflictManager == o.conflictManager
case _ => false
}
override def hashCode: Int =
{
var hash = 1
hash = hash * 31 + this.module.##
hash = hash * 31 + this.dependencies.##
hash = hash * 31 + this.overrides.##
hash = hash * 31 + this.excludes.##
hash = hash * 31 + this.ivyXML.##
hash = hash * 31 + this.configurations.##
hash = hash * 31 + this.defaultConfiguration.##
hash = hash * 31 + this.ivyScala.##
hash = hash * 31 + this.validate.##
hash = hash * 31 + this.conflictManager.##
hash
}
}
object InlineConfiguration {
def apply(
module: ModuleID,
moduleInfo: ModuleInfo,
dependencies: Seq[ModuleID],
overrides: Set[ModuleID] = Set.empty,
excludes: Seq[SbtExclusionRule] = Nil,
ivyXML: NodeSeq = NodeSeq.Empty,
configurations: Seq[Configuration] = Nil,
defaultConfiguration: Option[Configuration] = None,
ivyScala: Option[IvyScala] = None,
validate: Boolean = false,
conflictManager: ConflictManager = ConflictManager.default
): InlineConfiguration =
new InlineConfiguration(module, moduleInfo, dependencies, overrides, excludes, ivyXML,
configurations, defaultConfiguration, ivyScala, validate, conflictManager)
def configurations(explicitConfigurations: Iterable[Configuration], defaultConfiguration: Option[Configuration]) = def configurations(explicitConfigurations: Iterable[Configuration], defaultConfiguration: Option[Configuration]) =
if (explicitConfigurations.isEmpty) { if (explicitConfigurations.isEmpty) {
defaultConfiguration match { defaultConfiguration match {

View File

@ -17,10 +17,10 @@ import sbt.librarymanagement._
import sbt.internal.librarymanagement.syntax._ import sbt.internal.librarymanagement.syntax._
object IvyRetrieve { object IvyRetrieve {
def reports(report: ResolveReport): Seq[ConfigurationResolveReport] = def reports(report: ResolveReport): Vector[ConfigurationResolveReport] =
report.getConfigurations map report.getConfigurationReport report.getConfigurations.toVector map report.getConfigurationReport
def moduleReports(confReport: ConfigurationResolveReport): Seq[ModuleReport] = def moduleReports(confReport: ConfigurationResolveReport): Vector[ModuleReport] =
for { for {
revId <- confReport.getModuleRevisionIds.toArray.toVector collect { case revId: ModuleRevisionId => revId } revId <- confReport.getModuleRevisionIds.toArray.toVector collect { case revId: ModuleRevisionId => revId }
} yield moduleRevisionDetail(confReport, confReport.getDependency(revId)) } yield moduleRevisionDetail(confReport, confReport.getDependency(revId))
@ -32,7 +32,7 @@ object IvyRetrieve {
ModuleReport(mid, resolved, missing) ModuleReport(mid, resolved, missing)
} }
private[sbt] def artifacts(mid: ModuleID, artReport: Seq[ArtifactDownloadReport]): (Seq[(Artifact, File)], Seq[Artifact]) = private[sbt] def artifacts(mid: ModuleID, artReport: Seq[ArtifactDownloadReport]): (Vector[(Artifact, File)], Vector[Artifact]) =
{ {
val missing = new mutable.ListBuffer[Artifact] val missing = new mutable.ListBuffer[Artifact]
val resolved = new mutable.ListBuffer[(Artifact, File)] val resolved = new mutable.ListBuffer[(Artifact, File)]
@ -44,13 +44,13 @@ object IvyRetrieve {
case None => missing += art case None => missing += art
} }
} }
(resolved.toSeq, missing.toSeq) (resolved.toVector, missing.toVector)
} }
// We need this because current module report used as part of UpdateReport/ConfigurationReport contains // We need this because current module report used as part of UpdateReport/ConfigurationReport contains
// only the revolved modules. // only the revolved modules.
// Sometimes the entire module can be excluded via rules etc. // Sometimes the entire module can be excluded via rules etc.
private[sbt] def organizationArtifactReports(confReport: ConfigurationResolveReport): Seq[OrganizationArtifactReport] = { private[sbt] def organizationArtifactReports(confReport: ConfigurationResolveReport): Vector[OrganizationArtifactReport] = {
val moduleIds = confReport.getModuleIds.toArray.toVector collect { case mId: IvyModuleId => mId } val moduleIds = confReport.getModuleIds.toArray.toVector collect { case mId: IvyModuleId => mId }
def organizationArtifact(mid: IvyModuleId): OrganizationArtifactReport = { def organizationArtifact(mid: IvyModuleId): OrganizationArtifactReport = {
val deps = confReport.getNodes(mid).toArray.toVector collect { case node: IvyNode => node } val deps = confReport.getNodes(mid).toArray.toVector collect { case node: IvyNode => node }
@ -130,14 +130,14 @@ object IvyRetrieve {
case _ => dep.getResolvedId.getExtraAttributes case _ => dep.getResolvedId.getExtraAttributes
}) })
val isDefault = Option(dep.getDescriptor) map { _.isDefault } val isDefault = Option(dep.getDescriptor) map { _.isDefault }
val configurations = dep.getConfigurations(confReport.getConfiguration).toList val configurations = dep.getConfigurations(confReport.getConfiguration).toVector
val licenses: Seq[(String, Option[String])] = mdOpt match { val licenses: Vector[(String, Option[String])] = mdOpt match {
case Some(md) => md.getLicenses.toVector collect { case Some(md) => md.getLicenses.toVector collect {
case lic: IvyLicense if Option(lic.getName).isDefined => case lic: IvyLicense if Option(lic.getName).isDefined =>
val temporaryURL = "http://localhost" val temporaryURL = "http://localhost"
(lic.getName, nonEmptyString(lic.getUrl) orElse { Some(temporaryURL) }) (lic.getName, nonEmptyString(lic.getUrl) orElse { Some(temporaryURL) })
} }
case _ => Nil case _ => Vector.empty
} }
val callers = dep.getCallers(confReport.getConfiguration).toVector map { toCaller } val callers = dep.getCallers(confReport.getConfiguration).toVector map { toCaller }
val (resolved, missing) = artifacts(moduleId, confReport getDownloadReports revId) val (resolved, missing) = artifacts(moduleId, confReport getDownloadReports revId)
@ -151,13 +151,13 @@ object IvyRetrieve {
confReport.getEvictedNodes.map(node => toModuleID(node.getId)) confReport.getEvictedNodes.map(node => toModuleID(node.getId))
def toModuleID(revID: ModuleRevisionId): ModuleID = def toModuleID(revID: ModuleRevisionId): ModuleID =
ModuleID(revID.getOrganisation, revID.getName, revID.getRevision, extraAttributes = IvySbt.getExtraAttributes(revID)) ModuleID(revID.getOrganisation, revID.getName, revID.getRevision).withExtraAttributes(IvySbt.getExtraAttributes(revID))
.branch(nonEmptyString(revID.getBranch)) .branch(nonEmptyString(revID.getBranch))
def toArtifact(art: IvyArtifact): Artifact = def toArtifact(art: IvyArtifact): Artifact =
{ {
import art._ import art._
Artifact(getName, getType, getExt, Option(getExtraAttribute("classifier")), getConfigurations map Configurations.config, Option(getUrl)) Artifact(getName, getType, getExt, Option(getExtraAttribute("classifier")), getConfigurations.toVector map Configurations.config, Option(getUrl))
} }
def updateReport(report: ResolveReport, cachedDescriptor: File): UpdateReport = def updateReport(report: ResolveReport, cachedDescriptor: File): UpdateReport =

View File

@ -3,18 +3,22 @@ package sbt.internal.librarymanagement
import java.io.File import java.io.File
import org.apache.ivy.core import org.apache.ivy.core
import core.module.descriptor.ModuleDescriptor import core.module.descriptor.ModuleDescriptor
import sbt.serialization._
import sbt.util.Logger import sbt.util.Logger
import sbt.internal.util.CacheStore
import sbt.librarymanagement._ import sbt.librarymanagement._
import sbt.librarymanagement.LibraryManagementCodec._
import JsonUtil._
private[sbt] object JsonUtil { private[sbt] object JsonUtil {
def sbtOrgTemp = "org.scala-sbt.temp" def sbtOrgTemp = "org.scala-sbt.temp"
def fakeCallerOrganization = "org.scala-sbt.temp-callers" def fakeCallerOrganization = "org.scala-sbt.temp-callers"
}
private[sbt] class JsonUtil(fileToStore: File => CacheStore) {
def parseUpdateReport(md: ModuleDescriptor, path: File, cachedDescriptor: File, log: Logger): UpdateReport = def parseUpdateReport(md: ModuleDescriptor, path: File, cachedDescriptor: File, log: Logger): UpdateReport =
{ {
try { try {
val lite = fromJsonFile[UpdateReportLite](path).get val lite = fileToStore(path).read[UpdateReportLite]
fromLite(lite, cachedDescriptor) fromLite(lite, cachedDescriptor)
} catch { } catch {
case e: Throwable => case e: Throwable =>
@ -25,7 +29,7 @@ private[sbt] object JsonUtil {
def writeUpdateReport(ur: UpdateReport, graphPath: File): Unit = def writeUpdateReport(ur: UpdateReport, graphPath: File): Unit =
{ {
sbt.io.IO.createDirectory(graphPath.getParentFile) sbt.io.IO.createDirectory(graphPath.getParentFile)
toJsonFile(toLite(ur), graphPath) fileToStore(graphPath).write(toLite(ur))
} }
def toLite(ur: UpdateReport): UpdateReportLite = def toLite(ur: UpdateReport): UpdateReportLite =
UpdateReportLite(ur.configurations map { cr => UpdateReportLite(ur.configurations map { cr =>
@ -44,7 +48,7 @@ private[sbt] object JsonUtil {
}) })
// #1763/#2030. Caller takes up 97% of space, so we need to shrink it down, // #1763/#2030. Caller takes up 97% of space, so we need to shrink it down,
// but there are semantics associated with some of them. // but there are semantics associated with some of them.
def filterOutArtificialCallers(callers: Seq[Caller]): Seq[Caller] = def filterOutArtificialCallers(callers: Vector[Caller]): Vector[Caller] =
if (callers.isEmpty) callers if (callers.isEmpty) callers
else { else {
val nonArtificial = callers filter { c => val nonArtificial = callers filter { c =>
@ -53,8 +57,8 @@ private[sbt] object JsonUtil {
} }
val interProj = (callers find { c => val interProj = (callers find { c =>
c.caller.organization == sbtOrgTemp c.caller.organization == sbtOrgTemp
}).toList }).toVector
interProj ::: nonArtificial.toList interProj ++ nonArtificial
} }
def fromLite(lite: UpdateReportLite, cachedDescriptor: File): UpdateReport = def fromLite(lite: UpdateReportLite, cachedDescriptor: File): UpdateReport =
@ -72,13 +76,3 @@ private[sbt] object JsonUtil {
new UpdateReport(cachedDescriptor, configReports, stats, Map.empty) new UpdateReport(cachedDescriptor, configReports, stats, Map.empty)
} }
} }
private[sbt] case class UpdateReportLite(configurations: Seq[ConfigurationReportLite])
private[sbt] object UpdateReportLite {
implicit val pickler: Pickler[UpdateReportLite] with Unpickler[UpdateReportLite] = PicklerUnpickler.generate[UpdateReportLite]
}
private[sbt] case class ConfigurationReportLite(configuration: String, details: Seq[OrganizationArtifactReport])
private[sbt] object ConfigurationReportLite {
implicit val pickler: Pickler[ConfigurationReportLite] with Unpickler[ConfigurationReportLite] = PicklerUnpickler.generate[ConfigurationReportLite]
}

View File

@ -35,18 +35,16 @@ final class RichUpdateReport(report: UpdateReport) {
/** Constructs a new report that only contains files matching the specified filter.*/ /** Constructs a new report that only contains files matching the specified filter.*/
private[sbt] def filter(f: DependencyFilter): UpdateReport = private[sbt] def filter(f: DependencyFilter): UpdateReport =
moduleReportMap { (configuration, modReport) => moduleReportMap { (configuration, modReport) =>
modReport.copy( modReport
artifacts = modReport.artifacts filter { case (art, file) => f(configuration, modReport.module, art) }, .withArtifacts(modReport.artifacts filter { case (art, file) => f(configuration, modReport.module, art) })
missingArtifacts = modReport.missingArtifacts filter { art => f(configuration, modReport.module, art) } .withMissingArtifacts(modReport.missingArtifacts filter { art => f(configuration, modReport.module, art) })
)
} }
def substitute(f: (String, ModuleID, Seq[(Artifact, File)]) => Seq[(Artifact, File)]): UpdateReport = def substitute(f: (String, ModuleID, Vector[(Artifact, File)]) => Vector[(Artifact, File)]): UpdateReport =
moduleReportMap { (configuration, modReport) => moduleReportMap { (configuration, modReport) =>
val newArtifacts = f(configuration, modReport.module, modReport.artifacts) val newArtifacts = f(configuration, modReport.module, modReport.artifacts)
modReport.copy( modReport
artifacts = newArtifacts, .withArtifacts(newArtifacts)
missingArtifacts = modReport.missingArtifacts .withMissingArtifacts(modReport.missingArtifacts)
)
} }
def toSeq: Seq[(String, ModuleID, Artifact, File)] = def toSeq: Seq[(String, ModuleID, Artifact, File)] =
@ -57,9 +55,8 @@ final class RichUpdateReport(report: UpdateReport) {
def addMissing(f: ModuleID => Seq[Artifact]): UpdateReport = def addMissing(f: ModuleID => Seq[Artifact]): UpdateReport =
moduleReportMap { (configuration, modReport) => moduleReportMap { (configuration, modReport) =>
modReport.copy( modReport
missingArtifacts = (modReport.missingArtifacts ++ f(modReport.module)).distinct .withMissingArtifacts((modReport.missingArtifacts ++ f(modReport.module)).distinct)
)
} }
def moduleReportMap(f: (String, ModuleReport) => ModuleReport): UpdateReport = def moduleReportMap(f: (String, ModuleReport) => ModuleReport): UpdateReport =

View File

@ -1,52 +0,0 @@
package sbt.internal.librarymanagement
import impl.{ GroupID, GroupArtifactID }
import sbt.librarymanagement._
final class SbtExclusionRule(
val organization: String,
val name: String,
val artifact: String,
val configurations: Seq[String],
val crossVersion: CrossVersion
) {
def copy(
organization: String = this.organization,
name: String = this.name,
artifact: String = this.artifact,
configurations: Seq[String] = this.configurations,
crossVersion: CrossVersion = this.crossVersion
): SbtExclusionRule =
SbtExclusionRule(
organization = organization,
name = name,
artifact = artifact,
configurations = configurations,
crossVersion = crossVersion
)
}
object SbtExclusionRule {
def apply(organization: String): SbtExclusionRule =
new SbtExclusionRule(organization, "*", "*", Nil, CrossVersion.Disabled)
def apply(organization: String, name: String): SbtExclusionRule =
new SbtExclusionRule(organization, name, "*", Nil, CrossVersion.Disabled)
def apply(
organization: String,
name: String,
artifact: String,
configurations: Seq[String],
crossVersion: CrossVersion
): SbtExclusionRule =
new SbtExclusionRule(organization, name, artifact, configurations, crossVersion)
implicit def groupIdToExclusionRule(organization: GroupID): SbtExclusionRule =
SbtExclusionRule(organization.groupID)
implicit def stringToExclusionRule(organization: String): SbtExclusionRule =
SbtExclusionRule(organization)
implicit def groupArtifactIDToExcludsionRule(gaid: GroupArtifactID): SbtExclusionRule =
SbtExclusionRule(gaid.groupID, gaid.artifactID, "*", Nil, gaid.crossVersion)
}

View File

@ -0,0 +1,11 @@
package sbt.internal.librarymanagement.formats
import sjsonnew._
import java.util._
import java.text._
trait DateFormat { self: BasicJsonProtocol =>
private val format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy")
implicit lazy val DateFormat: JsonFormat[Date] = project(_.toString, format.parse _)
}

View File

@ -0,0 +1,12 @@
package sbt.internal.librarymanagement.formats
import sjsonnew._
import org.apache.ivy.plugins.resolver.DependencyResolver
trait DependencyResolverFormat { self: BasicJsonProtocol =>
implicit lazy val DependencyResolverFormat: JsonFormat[DependencyResolver] =
project(
MyCrazyReferences.referenced _,
(ref: String) => MyCrazyReferences(ref, classOf[DependencyResolver])
)
}

View File

@ -0,0 +1,8 @@
package sbt.internal.librarymanagement.formats
import sjsonnew._
trait Function1Format { self: BasicJsonProtocol =>
implicit def Function1Format[T, U]: JsonFormat[T => U] =
project(MyCrazyReferences.referenced _, (ref: String) => MyCrazyReferences(ref, classOf[T => U]))
}

View File

@ -0,0 +1,9 @@
package sbt.internal.librarymanagement.formats
import sjsonnew._
import xsbti._
trait GlobalLockFormat { self: BasicJsonProtocol =>
implicit lazy val GlobalLockFormat: JsonFormat[GlobalLock] =
project(MyCrazyReferences.referenced _, (ref: String) => MyCrazyReferences(ref, classOf[GlobalLock]))
}

View File

@ -0,0 +1,9 @@
package sbt.internal.librarymanagement.formats
import sjsonnew._
import xsbti._
trait LoggerFormat { self: BasicJsonProtocol =>
implicit lazy val LoggerFormat: JsonFormat[Logger] =
project(MyCrazyReferences.referenced _, (ref: String) => MyCrazyReferences(ref, classOf[Logger]))
}

View File

@ -0,0 +1,15 @@
package sbt.internal.librarymanagement.formats
import scala.collection.mutable
object MyCrazyReferences {
private val references: mutable.Map[String, Any] = mutable.Map.empty
def apply[T](key: String, clazz: Class[T]): T = synchronized(clazz.cast(references(key)))
def referenced[T](value: T): String = synchronized {
val key = java.util.UUID.randomUUID.toString
references(key) = value
key
}
}

View File

@ -0,0 +1,9 @@
package sbt.internal.librarymanagement.formats
import sjsonnew._
import scala.xml._
trait NodeSeqFormat { self: BasicJsonProtocol =>
implicit lazy val NodeSeqFormat: JsonFormat[NodeSeq] =
project(MyCrazyReferences.referenced _, (ref: String) => MyCrazyReferences(ref, classOf[NodeSeq]))
}

View File

@ -0,0 +1,27 @@
package sbt.internal.librarymanagement
package formats
import sjsonnew._
import sbt.librarymanagement._
trait UpdateOptionsFormat { self: BasicJsonProtocol =>
implicit lazy val UpdateOptionsFormat: JsonFormat[UpdateOptions] =
project(
(uo: UpdateOptions) => (
uo.circularDependencyLevel.name,
uo.interProjectFirst,
uo.latestSnapshots,
uo.consolidatedResolution,
uo.cachedResolution
),
(xs: (String, Boolean, Boolean, Boolean, Boolean)) =>
new UpdateOptions(levels(xs._1), xs._2, xs._3, xs._4, xs._5, ConvertResolver.defaultConvert)
)
private val levels: Map[String, CircularDependencyLevel] = Map(
"warn" -> CircularDependencyLevel.Warn,
"ignore" -> CircularDependencyLevel.Ignore,
"error" -> CircularDependencyLevel.Error
)
}

View File

@ -26,7 +26,7 @@ trait DependencyBuilders {
} }
final class GroupID private[sbt] (private[sbt] val groupID: String) { final class GroupID private[sbt] (private[sbt] val groupID: String) {
def %(artifactID: String) = groupArtifact(artifactID, CrossVersion.Disabled) def %(artifactID: String) = groupArtifact(artifactID, Disabled())
def %%(artifactID: String): GroupArtifactID = groupArtifact(artifactID, CrossVersion.binary) def %%(artifactID: String): GroupArtifactID = groupArtifact(artifactID, CrossVersion.binary)
private def groupArtifact(artifactID: String, cross: CrossVersion) = private def groupArtifact(artifactID: String, cross: CrossVersion) =
@ -53,7 +53,7 @@ final class ModuleIDConfigurable private[sbt] (moduleID: ModuleID) {
{ {
nonEmpty(configurations, "Configurations") nonEmpty(configurations, "Configurations")
val c = configurations val c = configurations
moduleID.copy(configurations = Some(c)) moduleID.withConfigurations(configurations = Some(c))
} }
} }
final class RepositoryName private[sbt] (name: String) { final class RepositoryName private[sbt] (name: String) {

View File

@ -24,6 +24,7 @@ import sbt.io.{ DirectoryFilter, Hash, IO }
import sbt.util.Logger import sbt.util.Logger
import sbt.librarymanagement._ import sbt.librarymanagement._
import sbt.internal.librarymanagement.syntax._ import sbt.internal.librarymanagement.syntax._
import sbt.internal.util.CacheStore
private[sbt] object CachedResolutionResolveCache { private[sbt] object CachedResolutionResolveCache {
def createID(organization: String, name: String, revision: String) = def createID(organization: String, name: String, revision: String) =
@ -38,8 +39,9 @@ private[sbt] object CachedResolutionResolveCache {
lazy val yyyymmdd: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd") lazy val yyyymmdd: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd")
} }
private[sbt] class CachedResolutionResolveCache() { private[sbt] class CachedResolutionResolveCache(fileToStore: File => CacheStore) {
import CachedResolutionResolveCache._ import CachedResolutionResolveCache._
val jsonUtil = new JsonUtil(fileToStore)
val updateReportCache: concurrent.Map[ModuleRevisionId, Either[ResolveException, UpdateReport]] = concurrent.TrieMap() val updateReportCache: concurrent.Map[ModuleRevisionId, Either[ResolveException, UpdateReport]] = concurrent.TrieMap()
// Used for subproject // Used for subproject
val projectReportCache: concurrent.Map[(ModuleRevisionId, LogicalClock), Either[ResolveException, UpdateReport]] = concurrent.TrieMap() val projectReportCache: concurrent.Map[(ModuleRevisionId, LogicalClock), Either[ResolveException, UpdateReport]] = concurrent.TrieMap()
@ -164,7 +166,7 @@ private[sbt] class CachedResolutionResolveCache() {
else None) match { else None) match {
case Some(path) => case Some(path) =>
log.debug(s"parsing ${path.getAbsolutePath.toString}") log.debug(s"parsing ${path.getAbsolutePath.toString}")
val ur = JsonUtil.parseUpdateReport(md, path, cachedDescriptor, log) val ur = jsonUtil.parseUpdateReport(md, path, cachedDescriptor, log)
if (ur.allFiles forall { _.exists }) { if (ur.allFiles forall { _.exists }) {
updateReportCache(md.getModuleRevisionId) = Right(ur) updateReportCache(md.getModuleRevisionId) = Right(ur)
Some(Right(ur)) Some(Right(ur))
@ -198,7 +200,7 @@ private[sbt] class CachedResolutionResolveCache() {
if (changing) { if (changing) {
cleanDynamicGraph() cleanDynamicGraph()
} }
JsonUtil.writeUpdateReport(ur, gp) jsonUtil.writeUpdateReport(ur, gp)
// limit the update cache size // limit the update cache size
if (updateReportCache.size > maxUpdateReportCacheSize) { if (updateReportCache.size > maxUpdateReportCacheSize) {
updateReportCache.remove(updateReportCache.head._1) updateReportCache.remove(updateReportCache.head._1)
@ -221,7 +223,7 @@ private[sbt] class CachedResolutionResolveCache() {
{ {
def reconstructReports(surviving: Vector[ModuleID], evicted: Vector[ModuleID], mgr: String): (Vector[ModuleReport], Vector[ModuleReport]) = { def reconstructReports(surviving: Vector[ModuleID], evicted: Vector[ModuleID], mgr: String): (Vector[ModuleReport], Vector[ModuleReport]) = {
val moduleIdMap = Map(conflicts map { x => x.module -> x }: _*) val moduleIdMap = Map(conflicts map { x => x.module -> x }: _*)
(surviving map moduleIdMap, evicted map moduleIdMap map { _.copy(evicted = true, evictedReason = Some(mgr.toString)) }) (surviving map moduleIdMap, evicted map moduleIdMap map { _.withEvicted(true).withEvictedReason(Some(mgr.toString)) })
} }
(conflictCache get ((cf0, cf1))) match { (conflictCache get ((cf0, cf1))) match {
case Some((surviving, evicted, mgr)) => reconstructReports(surviving, evicted, mgr) case Some((surviving, evicted, mgr)) => reconstructReports(surviving, evicted, mgr)
@ -257,6 +259,9 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
private[sbt] def makeInstance: Ivy private[sbt] def makeInstance: Ivy
private[sbt] val ignoreTransitiveForce: Boolean = true private[sbt] val ignoreTransitiveForce: Boolean = true
private[sbt] val fileToStore: File => CacheStore
private val jsonUtil = new JsonUtil(fileToStore)
def withIvy[A](log: Logger)(f: Ivy => A): A = def withIvy[A](log: Logger)(f: Ivy => A): A =
withIvy(new IvyLoggerInterface(log))(f) withIvy(new IvyLoggerInterface(log))(f)
def withIvy[A](log: MessageLogger)(f: Ivy => A): A = def withIvy[A](log: MessageLogger)(f: Ivy => A): A =
@ -428,7 +433,7 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
if (mr.evicted || mr.problem.nonEmpty) None if (mr.evicted || mr.problem.nonEmpty) None
else else
// https://github.com/sbt/sbt/issues/1763 // https://github.com/sbt/sbt/issues/1763
Some(mr.copy(callers = JsonUtil.filterOutArtificialCallers(mr.callers))) Some(mr.withCallers(jsonUtil.filterOutArtificialCallers(mr.callers)))
} match { } match {
case Vector() => None case Vector() => None
case ms => Some(OrganizationArtifactReport(report0.organization, report0.name, ms)) case ms => Some(OrganizationArtifactReport(report0.organization, report0.name, ms))
@ -504,7 +509,7 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
if (callers.size == callers0.size) mr if (callers.size == callers0.size) mr
else { else {
log.debug(s":: $rootModuleConf: removing caller $moduleWithMostCallers -> $next for sorting") log.debug(s":: $rootModuleConf: removing caller $moduleWithMostCallers -> $next for sorting")
mr.copy(callers = callers) mr.withCallers(callers)
} }
} }
OrganizationArtifactReport(oar.organization, oar.name, mrs) OrganizationArtifactReport(oar.organization, oar.name, mrs)
@ -591,18 +596,18 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
* Merges ModuleReports, which represents orgnization, name, and version. * Merges ModuleReports, which represents orgnization, name, and version.
* Returns a touple of (surviving modules ++ non-conflicting modules, newly evicted modules). * Returns a touple of (surviving modules ++ non-conflicting modules, newly evicted modules).
*/ */
def mergeModuleReports(rootModuleConf: String, modules: Seq[ModuleReport], os: Vector[IvyOverride], log: Logger): (Vector[ModuleReport], Vector[ModuleReport]) = def mergeModuleReports(rootModuleConf: String, modules: Vector[ModuleReport], os: Vector[IvyOverride], log: Logger): (Vector[ModuleReport], Vector[ModuleReport]) =
{ {
if (modules.nonEmpty) { if (modules.nonEmpty) {
log.debug(s":: merging module reports for $rootModuleConf: ${modules.head.module.organization}:${modules.head.module.name}") log.debug(s":: merging module reports for $rootModuleConf: ${modules.head.module.organization}:${modules.head.module.name}")
} }
def mergeModuleReports(org: String, name: String, version: String, xs: Seq[ModuleReport]): ModuleReport = { def mergeModuleReports(org: String, name: String, version: String, xs: Vector[ModuleReport]): ModuleReport = {
val completelyEvicted = xs forall { _.evicted } val completelyEvicted = xs forall { _.evicted }
val allCallers = xs flatMap { _.callers } val allCallers = xs flatMap { _.callers }
// Caller info is often repeated across the subprojects. We only need ModuleID info for later, so xs.head is ok. // Caller info is often repeated across the subprojects. We only need ModuleID info for later, so xs.head is ok.
val distinctByModuleId = allCallers.groupBy({ _.caller }).toList map { case (k, xs) => xs.head } val distinctByModuleId = allCallers.groupBy({ _.caller }).toVector map { case (k, xs) => xs.head }
val allArtifacts = (xs flatMap { _.artifacts }).distinct val allArtifacts = (xs flatMap { _.artifacts }).distinct
xs.head.copy(artifacts = allArtifacts, evicted = completelyEvicted, callers = distinctByModuleId) xs.head.withArtifacts(allArtifacts).withEvicted(completelyEvicted).withCallers(distinctByModuleId)
} }
val merged = (modules groupBy { m => (m.module.organization, m.module.name, m.module.revision) }).toSeq.toVector flatMap { val merged = (modules groupBy { m => (m.module.organization, m.module.name, m.module.revision) }).toSeq.toVector flatMap {
case ((org, name, version), xs) => case ((org, name, version), xs) =>
@ -637,7 +642,7 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
} }
x x
} }
val newlyEvicted = affected map { _.copy(evicted = true, evictedReason = Some("transitive-evict")) } val newlyEvicted = affected map { _.withEvicted(true).withEvictedReason(Some("transitive-evict")) }
if (affected.isEmpty) oar if (affected.isEmpty) oar
else new OrganizationArtifactReport(organization, name, unaffected ++ newlyEvicted) else new OrganizationArtifactReport(organization, name, unaffected ++ newlyEvicted)
} }
@ -669,7 +674,7 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
}) match { }) match {
case Some(m) => case Some(m) =>
log.debug(s"- directly forced dependency: $m ${m.callers}") log.debug(s"- directly forced dependency: $m ${m.callers}")
(Vector(m), conflicts filterNot { _ == m } map { _.copy(evicted = true, evictedReason = Some("direct-force")) }, "direct-force") (Vector(m), conflicts filterNot { _ == m } map { _.withEvicted(true).withEvictedReason(Some("direct-force")) }, "direct-force")
case None => case None =>
(conflicts find { m => (conflicts find { m =>
m.callers.exists { _.isForceDependency } m.callers.exists { _.isForceDependency }
@ -677,13 +682,13 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
// Ivy translates pom.xml dependencies to forced="true", so transitive force is broken. // Ivy translates pom.xml dependencies to forced="true", so transitive force is broken.
case Some(m) if !ignoreTransitiveForce => case Some(m) if !ignoreTransitiveForce =>
log.debug(s"- transitively forced dependency: $m ${m.callers}") log.debug(s"- transitively forced dependency: $m ${m.callers}")
(Vector(m), conflicts filterNot { _ == m } map { _.copy(evicted = true, evictedReason = Some("transitive-force")) }, "transitive-force") (Vector(m), conflicts filterNot { _ == m } map { _.withEvicted(true).withEvictedReason(Some("transitive-force")) }, "transitive-force")
case _ => case _ =>
val strategy = lcm.getStrategy val strategy = lcm.getStrategy
val infos = conflicts map { ModuleReportArtifactInfo(_) } val infos = conflicts map { ModuleReportArtifactInfo(_) }
Option(strategy.findLatest(infos.toArray, None.orNull)) match { Option(strategy.findLatest(infos.toArray, None.orNull)) match {
case Some(ModuleReportArtifactInfo(m)) => case Some(ModuleReportArtifactInfo(m)) =>
(Vector(m), conflicts filterNot { _ == m } map { _.copy(evicted = true, evictedReason = Some(lcm.toString)) }, lcm.toString) (Vector(m), conflicts filterNot { _ == m } map { _.withEvicted(true).withEvictedReason(Some(lcm.toString)) }, lcm.toString)
case _ => (conflicts, Vector(), lcm.toString) case _ => (conflicts, Vector(), lcm.toString)
} }
} }
@ -696,7 +701,7 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
mr.module.revision == ovrVersion mr.module.revision == ovrVersion
} match { } match {
case Some(m) => case Some(m) =>
(Vector(m), conflicts filterNot { _ == m } map { _.copy(evicted = true, evictedReason = Some("override")) }, "override") (Vector(m), conflicts filterNot { _ == m } map { _.withEvicted(true).withEvictedReason(Some("override")) }, "override")
case None => case None =>
sys.error(s"override dependency specifies $ovrVersion but no candidates were found: " + (conflicts map { _.module }).mkString("(", ", ", ")")) sys.error(s"override dependency specifies $ovrVersion but no candidates were found: " + (conflicts map { _.module }).mkString("(", ", ", ")"))
} }

View File

@ -5,22 +5,39 @@ package sbt.librarymanagement
import java.io.File import java.io.File
import java.net.URL import java.net.URL
import sbt.serialization._
final case class Artifact(name: String, `type`: String, extension: String, classifier: Option[String], configurations: Iterable[Configuration], url: Option[URL], extraAttributes: Map[String, String]) { abstract class ArtifactParent {
def name: String
def `type`: String
def extension: String
def classifier: Option[String]
def configurations: Vector[Configuration]
def url: Option[URL]
def extraAttributes: Map[String, String]
protected[this] def copy(
name: String = name,
`type`: String = `type`,
extension: String = extension,
classifier: Option[String] = classifier,
configurations: Vector[Configuration] = configurations,
url: Option[URL] = url,
extraAttributes: Map[String, String] = extraAttributes
): Artifact
def extra(attributes: (String, String)*) = copy(extraAttributes = extraAttributes ++ ModuleID.checkE(attributes)) def extra(attributes: (String, String)*) = copy(extraAttributes = extraAttributes ++ ModuleID.checkE(attributes))
} }
import Configurations.{ Optional, Pom, Test } import Configurations.{ Optional, Pom, Test }
object Artifact { abstract class ArtifactCompanion {
def apply(name: String): Artifact = Artifact(name, DefaultType, DefaultExtension, None, Nil, None) def apply(name: String, extra: Map[String, String]): Artifact = Artifact(name, DefaultType, DefaultExtension, None, Vector.empty, None, extra)
def apply(name: String, extra: Map[String, String]): Artifact = Artifact(name, DefaultType, DefaultExtension, None, Nil, None, extra) def apply(name: String, classifier: String): Artifact = Artifact(name, DefaultType, DefaultExtension, Some(classifier), Vector.empty, None)
def apply(name: String, classifier: String): Artifact = Artifact(name, DefaultType, DefaultExtension, Some(classifier), Nil, None) def apply(name: String, `type`: String, extension: String): Artifact = Artifact(name, `type`, extension, None, Vector.empty, None)
def apply(name: String, `type`: String, extension: String): Artifact = Artifact(name, `type`, extension, None, Nil, None) def apply(name: String, `type`: String, extension: String, classifier: String): Artifact = Artifact(name, `type`, extension, Some(classifier), Vector.empty, None)
def apply(name: String, `type`: String, extension: String, classifier: String): Artifact = Artifact(name, `type`, extension, Some(classifier), Nil, None) def apply(name: String, url: URL): Artifact = Artifact(name, extract(url, DefaultType), extract(url, DefaultExtension), None, Vector.empty, Some(url))
def apply(name: String, url: URL): Artifact = Artifact(name, extract(url, DefaultType), extract(url, DefaultExtension), None, Nil, Some(url))
def apply(name: String, `type`: String, extension: String, classifier: Option[String], configurations: Iterable[Configuration], url: Option[URL]): Artifact = def apply(name: String, `type`: String, extension: String, classifier: Option[String], configurations: Vector[Configuration], url: Option[URL]): Artifact =
Artifact(name, `type`, extension, classifier, configurations, url, Map.empty) Artifact(name, `type`, extension, classifier, configurations, url, Map.empty)
val DefaultExtension = "jar" val DefaultExtension = "jar"
@ -28,7 +45,7 @@ object Artifact {
def sources(name: String) = classified(name, SourceClassifier) def sources(name: String) = classified(name, SourceClassifier)
def javadoc(name: String) = classified(name, DocClassifier) def javadoc(name: String) = classified(name, DocClassifier)
def pom(name: String) = Artifact(name, PomType, PomType, None, Pom :: Nil, None) def pom(name: String) = Artifact(name, PomType, PomType, None, Vector(Pom), None)
// Possible ivy artifact types such that sbt will treat those artifacts at sources / docs // Possible ivy artifact types such that sbt will treat those artifacts at sources / docs
val DefaultSourceTypes = Set("src", "source", "sources") val DefaultSourceTypes = Set("src", "source", "sources")
@ -62,7 +79,7 @@ object Artifact {
val name = file.getName val name = file.getName
val i = name.lastIndexOf('.') val i = name.lastIndexOf('.')
val base = if (i >= 0) name.substring(0, i) else name 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)) Artifact(base, extract(name, DefaultType), extract(name, DefaultExtension), None, Vector.empty, Some(file.toURI.toURL))
} }
def artifactName(scalaVersion: ScalaVersion, module: ModuleID, artifact: Artifact): String = def artifactName(scalaVersion: ScalaVersion, module: ModuleID, artifact: Artifact): String =
{ {
@ -88,75 +105,5 @@ object Artifact {
* The artifact is created under the default configuration. * The artifact is created under the default configuration.
*/ */
def classified(name: String, classifier: String): Artifact = def classified(name: String, classifier: String): Artifact =
Artifact(name, classifierType(classifier), DefaultExtension, Some(classifier), Nil, None) Artifact(name, classifierType(classifier), DefaultExtension, Some(classifier), Vector.empty, None)
private val optStringPickler = implicitly[Pickler[Option[String]]]
private val optStringUnpickler = implicitly[Unpickler[Option[String]]]
private val vectorConfigurationPickler = implicitly[Pickler[Vector[Configuration]]]
private val vectorConfigurationUnpickler = implicitly[Unpickler[Vector[Configuration]]]
private val stringStringMapPickler = implicitly[Pickler[Map[String, String]]]
private val stringStringMapUnpickler = implicitly[Unpickler[Map[String, String]]]
implicit val pickler: Pickler[Artifact] = new Pickler[Artifact] {
val tag = implicitly[FastTypeTag[Artifact]]
val stringTag = implicitly[FastTypeTag[String]]
val optionStringTag = implicitly[FastTypeTag[Option[String]]]
val vectorConfigurationTag = implicitly[FastTypeTag[Vector[Configuration]]]
val stringStringMapTag = implicitly[FastTypeTag[Map[String, String]]]
def pickle(a: Artifact, builder: PBuilder): Unit = {
builder.pushHints()
builder.hintTag(tag)
builder.beginEntry(a)
builder.putField("name", { b =>
b.hintTag(stringTag)
stringPickler.pickle(a.name, b)
})
builder.putField("type", { b =>
b.hintTag(stringTag)
stringPickler.pickle(a.`type`, b)
})
builder.putField("extension", { b =>
b.hintTag(stringTag)
stringPickler.pickle(a.extension, b)
})
builder.putField("classifier", { b =>
b.hintTag(optionStringTag)
optStringPickler.pickle(a.classifier, b)
})
builder.putField("configurations", { b =>
b.hintTag(vectorConfigurationTag)
vectorConfigurationPickler.pickle(a.configurations.toVector, b)
})
builder.putField("url", { b =>
b.hintTag(optionStringTag)
optStringPickler.pickle(a.url map { _.toString }, b)
})
builder.putField("extraAttributes", { b =>
b.hintTag(stringStringMapTag)
stringStringMapPickler.pickle(a.extraAttributes, b)
})
builder.endEntry()
builder.popHints()
()
}
}
implicit val unpickler: Unpickler[Artifact] = new Unpickler[Artifact] {
val tag = implicitly[FastTypeTag[Artifact]]
def unpickle(tpe: String, reader: PReader): Any = {
reader.pushHints()
// reader.hintTag(tag)
reader.beginEntry()
val name = stringPickler.unpickleEntry(reader.readField("name")).asInstanceOf[String]
val tp = stringPickler.unpickleEntry(reader.readField("type")).asInstanceOf[String]
val extension = stringPickler.unpickleEntry(reader.readField("extension")).asInstanceOf[String]
val classifier = optStringUnpickler.unpickleEntry(reader.readField("classifier")).asInstanceOf[Option[String]]
val configurations = vectorConfigurationUnpickler.unpickleEntry(reader.readField("configurations")).asInstanceOf[Vector[Configuration]]
val u = optStringUnpickler.unpickleEntry(reader.readField("url")).asInstanceOf[Option[String]] map { new URL(_) }
val extraAttributes = stringStringMapUnpickler.unpickleEntry(reader.readField("extraAttributes")).asInstanceOf[Map[String, String]]
val result = Artifact(name, tp, extension, classifier, configurations, u, extraAttributes)
reader.endEntry()
reader.popHints()
result
}
}
} }

View File

@ -3,8 +3,6 @@
*/ */
package sbt.librarymanagement package sbt.librarymanagement
import sbt.serialization._
object Configurations { object Configurations {
def config(name: String) = new Configuration(name) def config(name: String) = new Configuration(name)
def default: Seq[Configuration] = defaultMavenConfigurations def default: Seq[Configuration] = defaultMavenConfigurations
@ -50,18 +48,20 @@ object Configurations {
private[sbt] def defaultConfiguration(mavenStyle: Boolean) = if (mavenStyle) Configurations.Compile else Configurations.Default private[sbt] def defaultConfiguration(mavenStyle: Boolean) = if (mavenStyle) Configurations.Compile else Configurations.Default
private[sbt] def removeDuplicates(configs: Iterable[Configuration]) = Set(scala.collection.mutable.Map(configs.map(config => (config.name, config)).toSeq: _*).values.toList: _*) private[sbt] def removeDuplicates(configs: Iterable[Configuration]) = Set(scala.collection.mutable.Map(configs.map(config => (config.name, config)).toSeq: _*).values.toList: _*)
} }
/** Represents an Ivy configuration. */
final case class Configuration(name: String, description: String, isPublic: Boolean, extendsConfigs: List[Configuration], transitive: Boolean) { abstract class ConfigurationParent {
def name: String
def description: String
def isPublic: Boolean
def extendsConfigs: Vector[Configuration]
def transitive: Boolean
require(name != null && !name.isEmpty) require(name != null && !name.isEmpty)
require(description != null) require(description != null)
def this(name: String) = this(name, "", true, Nil, true)
def describedAs(newDescription: String) = Configuration(name, newDescription, isPublic, extendsConfigs, transitive) def describedAs(newDescription: String) = Configuration(name, newDescription, isPublic, extendsConfigs, transitive)
def extend(configs: Configuration*) = Configuration(name, description, isPublic, configs.toList ::: extendsConfigs, transitive) def extend(configs: Configuration*) = Configuration(name, description, isPublic, configs.toVector ++ extendsConfigs, transitive)
def notTransitive = intransitive def notTransitive = intransitive
def intransitive = Configuration(name, description, isPublic, extendsConfigs, false) def intransitive = Configuration(name, description, isPublic, extendsConfigs, false)
def hide = Configuration(name, description, false, extendsConfigs, transitive) def hide = Configuration(name, description, false, extendsConfigs, transitive)
override def toString = name
}
object Configuration {
implicit val pickler: Pickler[Configuration] with Unpickler[Configuration] = PicklerUnpickler.generate[Configuration]
} }

View File

@ -1,89 +1,17 @@
package sbt.librarymanagement package sbt.librarymanagement
import sbt.serialization._
import sbt.internal.librarymanagement.SbtExclusionRule import sbt.internal.librarymanagement.SbtExclusionRule
import sbt.internal.librarymanagement.cross.CrossVersionUtil import sbt.internal.librarymanagement.cross.CrossVersionUtil
final case class ScalaVersion(full: String, binary: String) final case class ScalaVersion(full: String, binary: String)
/** Configures how a module will be cross-versioned. */ abstract class CrossVersionCompanion {
sealed trait CrossVersion
object CrossVersion {
/** The first `major.minor` Scala version that the Scala binary version should be used for cross-versioning instead of the full version. */ /** The first `major.minor` Scala version that the Scala binary version should be used for cross-versioning instead of the full version. */
val TransitionScalaVersion = CrossVersionUtil.TransitionScalaVersion val TransitionScalaVersion = CrossVersionUtil.TransitionScalaVersion
/** The first `major.minor` sbt version that the sbt binary version should be used for cross-versioning instead of the full version. */ /** The first `major.minor` sbt version that the sbt binary version should be used for cross-versioning instead of the full version. */
val TransitionSbtVersion = CrossVersionUtil.TransitionSbtVersion val TransitionSbtVersion = CrossVersionUtil.TransitionSbtVersion
/** Disables cross versioning for a module.*/
object Disabled extends CrossVersion { override def toString = "disabled" }
/**
* Cross-versions a module using the result of applying `remapVersion` to the binary version.
* For example, if `remapVersion = v => "2.10"` and the binary version is "2.9.2" or "2.10",
* the module is cross-versioned with "2.10".
*/
final class Binary(val remapVersion: String => String) extends CrossVersion {
override def toString = "Binary"
override def hashCode = remapVersion.##
override def equals(that: Any) = that match {
case that: Binary => this.remapVersion == that.remapVersion
case _ => false
}
}
/**
* Cross-versions a module with the result of applying `remapVersion` to the full version.
* For example, if `remapVersion = v => "2.10"` and the full version is "2.9.2" or "2.10.3",
* the module is cross-versioned with "2.10".
*/
final class Full(val remapVersion: String => String) extends CrossVersion {
override def toString = "Full"
override def hashCode = remapVersion.##
override def equals(that: Any) = that match {
case that: Full => this.remapVersion == that.remapVersion
case _ => false
}
}
private val disabledTag = implicitly[FastTypeTag[Disabled.type]]
private val binaryTag = implicitly[FastTypeTag[Binary]]
private val fullTag = implicitly[FastTypeTag[Full]]
implicit val pickler: Pickler[CrossVersion] = new Pickler[CrossVersion] {
val tag = implicitly[FastTypeTag[CrossVersion]]
def pickle(a: CrossVersion, builder: PBuilder): Unit = {
builder.pushHints()
builder.hintTag(a match {
case Disabled => disabledTag
case x: Binary => binaryTag
case x: Full => fullTag
})
builder.beginEntry(a)
builder.endEntry()
builder.popHints()
()
}
}
implicit val unpickler: Unpickler[CrossVersion] = new Unpickler[CrossVersion] {
val tag = implicitly[FastTypeTag[CrossVersion]]
def unpickle(tpe: String, reader: PReader): Any = {
reader.pushHints()
reader.hintTag(tag)
val tpeStr = reader.beginEntry()
val tpe = scala.pickling.FastTypeTag(tpeStr)
// sys.error(tpe.toString)
val result = tpe match {
case t if t == disabledTag => Disabled
case t if t == binaryTag => binary
case t if t == fullTag => full
}
reader.endEntry()
reader.popHints()
result
}
}
/** Cross-versions a module with the full version (typically the full Scala version). */ /** Cross-versions a module with the full version (typically the full Scala version). */
def full: CrossVersion = new Full(idStringFun) def full: CrossVersion = new Full(idStringFun)
@ -114,9 +42,9 @@ object CrossVersion {
*/ */
def apply(cross: CrossVersion, fullVersion: String, binaryVersion: String): Option[String => String] = def apply(cross: CrossVersion, fullVersion: String, binaryVersion: String): Option[String => String] =
cross match { cross match {
case Disabled => None case _: Disabled => None
case b: Binary => append(b.remapVersion(binaryVersion)) case b: Binary => append(b.remapVersion(binaryVersion))
case f: Full => append(f.remapVersion(fullVersion)) case f: Full => append(f.remapVersion(fullVersion))
} }
/** Constructs the cross-version function defined by `module` and `is`, if one is configured. */ /** Constructs the cross-version function defined by `module` and `is`, if one is configured. */
@ -128,7 +56,7 @@ object CrossVersion {
is flatMap { i => apply(module, i) } is flatMap { i => apply(module, i) }
/** Cross-version each `Artifact` in `artifacts` according to cross-version function `cross`. */ /** Cross-version each `Artifact` in `artifacts` according to cross-version function `cross`. */
def substituteCross(artifacts: Seq[Artifact], cross: Option[String => String]): Seq[Artifact] = def substituteCross(artifacts: Vector[Artifact], cross: Option[String => String]): Vector[Artifact] =
cross match { cross match {
case None => artifacts case None => artifacts
case Some(is) => substituteCrossA(artifacts, cross) case Some(is) => substituteCrossA(artifacts, cross)
@ -147,14 +75,14 @@ object CrossVersion {
private[sbt] def substituteCross(exclude: SbtExclusionRule, is: Option[IvyScala]): SbtExclusionRule = { private[sbt] def substituteCross(exclude: SbtExclusionRule, is: Option[IvyScala]): SbtExclusionRule = {
val fopt: Option[String => String] = val fopt: Option[String => String] =
is flatMap { i => CrossVersion(exclude.crossVersion, i.scalaFullVersion, i.scalaBinaryVersion) } is flatMap { i => CrossVersion(exclude.crossVersion, i.scalaFullVersion, i.scalaBinaryVersion) }
exclude.copy(name = applyCross(exclude.name, fopt)) exclude.withName(applyCross(exclude.name, fopt))
} }
/** Cross-versions `a` according to cross-version function `cross`. */ /** Cross-versions `a` according to cross-version function `cross`. */
def substituteCross(a: Artifact, cross: Option[String => String]): Artifact = def substituteCross(a: Artifact, cross: Option[String => String]): Artifact =
a.copy(name = applyCross(a.name, cross)) a.withName(applyCross(a.name, cross))
private[sbt] def substituteCrossA(as: Seq[Artifact], cross: Option[String => String]): Seq[Artifact] = private[sbt] def substituteCrossA(as: Vector[Artifact], cross: Option[String => String]): Vector[Artifact] =
as.map(art => substituteCross(art, cross)) as.map(art => substituteCross(art, cross))
/** /**
@ -166,7 +94,7 @@ object CrossVersion {
{ {
val cross = apply(m.crossVersion, scalaFullVersion, scalaBinaryVersion) val cross = apply(m.crossVersion, scalaFullVersion, scalaBinaryVersion)
if (cross.isDefined) if (cross.isDefined)
m.copy(name = applyCross(m.name, cross), explicitArtifacts = substituteCrossA(m.explicitArtifacts, cross)) m.withName(applyCross(m.name, cross)).withExplicitArtifacts(substituteCrossA(m.explicitArtifacts, cross))
else else
m m
} }

View File

@ -88,7 +88,7 @@ final class EvictionPair private[sbt] (
val organization: String, val organization: String,
val name: String, val name: String,
val winner: Option[ModuleReport], val winner: Option[ModuleReport],
val evicteds: Seq[ModuleReport], val evicteds: Vector[ModuleReport],
val includesDirect: Boolean, val includesDirect: Boolean,
val showCallers: Boolean val showCallers: Boolean
) { ) {
@ -168,7 +168,7 @@ object EvictionWarning {
private[sbt] def processEvictions(module: IvySbt#Module, options: EvictionWarningOptions, reports: Seq[OrganizationArtifactReport]): EvictionWarning = { private[sbt] def processEvictions(module: IvySbt#Module, options: EvictionWarningOptions, reports: Seq[OrganizationArtifactReport]): EvictionWarning = {
val directDependencies = module.moduleSettings match { val directDependencies = module.moduleSettings match {
case x: InlineConfiguration => x.dependencies case x: InlineConfiguration => x.dependencies
case _ => Seq() case _ => Vector.empty
} }
val pairs = reports map { detail => val pairs = reports map { detail =>
val evicteds = detail.modules filter { _.evicted } val evicteds = detail.modules filter { _.evicted }

View File

@ -3,54 +3,24 @@
*/ */
package sbt.librarymanagement package sbt.librarymanagement
import java.net.URL
import org.apache.ivy.core.module.descriptor import org.apache.ivy.core.module.descriptor
import org.apache.ivy.util.filter.{ Filter => IvyFilter } import org.apache.ivy.util.filter.{ Filter => IvyFilter }
import sbt.serialization._
/** Additional information about a project module */ abstract class InclExclRuleCompanion {
final case class ModuleInfo(nameFormal: String, description: String = "", homepage: Option[URL] = None, startYear: Option[Int] = None, licenses: Seq[(String, URL)] = Nil, organizationName: String = "", organizationHomepage: Option[URL] = None, scmInfo: Option[ScmInfo] = None, developers: Seq[Developer] = Seq()) { def everything = new InclExclRule("*", "*", "*", Vector.empty)
def this(nameFormal: String, description: String, homepage: Option[URL], startYear: Option[Int], licenses: Seq[(String, URL)], organizationName: String, organizationHomepage: Option[URL], scmInfo: Option[ScmInfo]) =
this(nameFormal, description, homepage, startYear, licenses, organizationName, organizationHomepage, scmInfo, Seq())
def formally(name: String) = copy(nameFormal = name)
def describing(desc: String, home: Option[URL]) = copy(description = desc, homepage = home)
def licensed(lics: (String, URL)*) = copy(licenses = lics)
def organization(name: String, home: Option[URL]) = copy(organizationName = name, organizationHomepage = home)
} }
/** Basic SCM information for a project module */ abstract class ArtifactTypeFilterParent {
final case class ScmInfo(browseUrl: URL, connection: String, devConnection: Option[String] = None) def types: Set[String]
def inverted: Boolean
final case class Developer(id: String, name: String, email: String, url: URL) protected[this] def copy(types: Set[String] = types, inverted: Boolean = inverted): ArtifactTypeFilter
/**
* Rule to either:
* <ul>
* <li> exclude unwanted dependencies pulled in transitively by a module, or to</li>
* <li> include and merge artifacts coming from the ModuleDescriptor if "dependencyArtifacts" are also provided.</li>
* </ul>
* Which one depends on the parameter name which it is passed to, but the filter has the same fields in both cases.
*/
final case class InclExclRule(organization: String = "*", name: String = "*", artifact: String = "*", configurations: Seq[String] = Nil)
object InclExclRule {
def everything = InclExclRule("*", "*", "*", Nil)
implicit val pickler: Pickler[InclExclRule] with Unpickler[InclExclRule] = PicklerUnpickler.generate[InclExclRule]
}
/**
* Work around the inadequacy of Ivy's ArtifactTypeFilter (that it cannot reverse a filter)
* @param types represents the artifact types that we should try to resolve for (as in the allowed values of
* `artifact[type]` from a dependency `<publications>` section). One can use this to filter
* source / doc artifacts.
* @param inverted whether to invert the types filter (i.e. allow only types NOT in the set)
*/
case class ArtifactTypeFilter(types: Set[String], inverted: Boolean) {
def invert = copy(inverted = !inverted) def invert = copy(inverted = !inverted)
def apply(a: descriptor.Artifact): Boolean = (types contains a.getType) ^ inverted def apply(a: descriptor.Artifact): Boolean = (types contains a.getType) ^ inverted
} }
object ArtifactTypeFilter { abstract class ArtifactTypeFilterCompanion {
def allow(types: Set[String]) = ArtifactTypeFilter(types, false) def allow(types: Set[String]) = ArtifactTypeFilter(types, false)
def forbid(types: Set[String]) = ArtifactTypeFilter(types, true) def forbid(types: Set[String]) = ArtifactTypeFilter(types, true)
@ -59,16 +29,12 @@ object ArtifactTypeFilter {
} }
} }
final case class ModuleConfiguration(organization: String, name: String, revision: String, resolver: Resolver) abstract class ConflictManagerCompanion {
object ModuleConfiguration { // To avoid NPE (or making the val's below lazy)
def apply(org: String, resolver: Resolver): ModuleConfiguration = apply(org, "*", "*", resolver) // For case classes refchecks rewrites apply calls to constructor calls, we have to do it manually
def apply(org: String, name: String, resolver: Resolver): ModuleConfiguration = ModuleConfiguration(org, name, "*", resolver) def apply(name: String, organization: String = "*", module: String = "*"): ConflictManager
} def ConflictManager(name: String) = apply(name)
final case class ConflictManager(name: String, organization: String = "*", module: String = "*")
/** See http://ant.apache.org/ivy/history/latest-milestone/settings/conflict-managers.html for details of the different conflict managers.*/
object ConflictManager {
val all = ConflictManager("all") val all = ConflictManager("all")
val latestTime = ConflictManager("latest-time") val latestTime = ConflictManager("latest-time")
val latestRevision = ConflictManager("latest-revision") val latestRevision = ConflictManager("latest-revision")

View File

@ -19,7 +19,7 @@ object ScalaArtifacts {
val ReflectID = "scala-reflect" val ReflectID = "scala-reflect"
val ActorsID = "scala-actors" val ActorsID = "scala-actors"
val ScalapID = "scalap" val ScalapID = "scalap"
val Artifacts = Seq(LibraryID, CompilerID, ReflectID, ActorsID, ScalapID) val Artifacts = Vector(LibraryID, CompilerID, ReflectID, ActorsID, ScalapID)
val DottyIDPrefix = "dotty" val DottyIDPrefix = "dotty"
def dottyID(binaryVersion: String): String = s"${DottyIDPrefix}_${binaryVersion}" def dottyID(binaryVersion: String): String = s"${DottyIDPrefix}_${binaryVersion}"
@ -28,8 +28,8 @@ object ScalaArtifacts {
private[sbt] def toolDependencies(org: String, version: String, isDotty: Boolean = false): Seq[ModuleID] = private[sbt] def toolDependencies(org: String, version: String, isDotty: Boolean = false): Seq[ModuleID] =
if (isDotty) if (isDotty)
Seq(ModuleID(org, DottyIDPrefix, version, Some(Configurations.ScalaTool.name + "->compile"), Seq(ModuleID(org, DottyIDPrefix, version).withConfigurations(Some(Configurations.ScalaTool.name + "->compile"))
crossVersion = CrossVersion.binary)) .withCrossVersion(CrossVersion.binary))
else else
Seq( Seq(
scalaToolDependency(org, ScalaArtifacts.CompilerID, version), scalaToolDependency(org, ScalaArtifacts.CompilerID, version),
@ -37,7 +37,7 @@ object ScalaArtifacts {
) )
private[this] def scalaToolDependency(org: String, id: String, version: String): ModuleID = private[this] def scalaToolDependency(org: String, id: String, version: String): ModuleID =
ModuleID(org, id, version, Some(Configurations.ScalaTool.name + "->default,optional(default)")) ModuleID(org, id, version).withConfigurations(Some(Configurations.ScalaTool.name + "->default,optional(default)"))
} }
object SbtArtifacts { object SbtArtifacts {
val Organization = "org.scala-sbt" val Organization = "org.scala-sbt"
@ -45,9 +45,7 @@ object SbtArtifacts {
import ScalaArtifacts._ import ScalaArtifacts._
final case class IvyScala(scalaFullVersion: String, scalaBinaryVersion: String, configurations: Iterable[Configuration], checkExplicit: Boolean, filterImplicit: Boolean, overrideScalaVersion: Boolean, scalaOrganization: String = ScalaArtifacts.Organization, scalaArtifacts: Seq[String] = ScalaArtifacts.Artifacts) private[sbt] abstract class IvyScalaCompanion {
private[sbt] object IvyScala {
/** Performs checks/adds filters on Scala dependencies (if enabled in IvyScala). */ /** Performs checks/adds filters on Scala dependencies (if enabled in IvyScala). */
def checkModule(module: DefaultModuleDescriptor, conf: String, log: Logger)(check: IvyScala): Unit = { def checkModule(module: DefaultModuleDescriptor, conf: String, log: Logger)(check: IvyScala): Unit = {
if (check.checkExplicit) if (check.checkExplicit)

View File

@ -6,13 +6,37 @@ package sbt.librarymanagement
import java.net.URL import java.net.URL
import sbt.internal.librarymanagement.mavenint.SbtPomExtraProperties import sbt.internal.librarymanagement.mavenint.SbtPomExtraProperties
import sbt.serialization._
final case class ModuleID(organization: String, name: String, revision: String, configurations: Option[String] = None, isChanging: Boolean = false, isTransitive: Boolean = true, isForce: Boolean = false, explicitArtifacts: Seq[Artifact] = Nil, inclusions: Seq[InclusionRule] = Nil, exclusions: Seq[ExclusionRule] = Nil, extraAttributes: Map[String, String] = Map.empty, crossVersion: CrossVersion = CrossVersion.Disabled, branchName: Option[String] = None) { abstract class ModuleIDParent {
override def toString: String = def organization: String
organization + ":" + name + ":" + revision + def name: String
(configurations match { case Some(s) => ":" + s; case None => "" }) + def revision: String
(if (extraAttributes.isEmpty) "" else " " + extraString) def configurations: Option[String]
def isChanging: Boolean
def isTransitive: Boolean
def isForce: Boolean
def explicitArtifacts: Vector[Artifact]
def inclusions: Vector[InclusionRule]
def exclusions: Vector[ExclusionRule]
def extraAttributes: Map[String, String]
def crossVersion: CrossVersion
def branchName: Option[String]
protected[this] def copy(
organization: String = organization,
name: String = name,
revision: String = revision,
configurations: Option[String] = configurations,
isChanging: Boolean = isChanging,
isTransitive: Boolean = isTransitive,
isForce: Boolean = isForce,
explicitArtifacts: Vector[Artifact] = explicitArtifacts,
inclusions: Vector[InclusionRule] = inclusions,
exclusions: Vector[ExclusionRule] = exclusions,
extraAttributes: Map[String, String] = extraAttributes,
crossVersion: CrossVersion = crossVersion,
branchName: Option[String] = branchName
): ModuleID
/** String representation of the extra attributes, excluding any information only attributes. */ /** String representation of the extra attributes, excluding any information only attributes. */
def extraString: String = extraDependencyAttributes.map { case (k, v) => k + "=" + v } mkString ("(", ", ", ")") def extraString: String = extraDependencyAttributes.map { case (k, v) => k + "=" + v } mkString ("(", ", ", ")")
@ -21,10 +45,10 @@ final case class ModuleID(organization: String, name: String, revision: String,
def extraDependencyAttributes: Map[String, String] = extraAttributes.filterKeys(!_.startsWith(SbtPomExtraProperties.POM_INFO_KEY_PREFIX)) def extraDependencyAttributes: Map[String, String] = extraAttributes.filterKeys(!_.startsWith(SbtPomExtraProperties.POM_INFO_KEY_PREFIX))
@deprecated("Use `cross(CrossVersion)`, the variant accepting a CrossVersion value constructed by a member of the CrossVersion object instead.", "0.12.0") @deprecated("Use `cross(CrossVersion)`, the variant accepting a CrossVersion value constructed by a member of the CrossVersion object instead.", "0.12.0")
def cross(v: Boolean): ModuleID = cross(if (v) CrossVersion.binary else CrossVersion.Disabled) def cross(v: Boolean): ModuleID = cross(if (v) CrossVersion.binary else Disabled())
@deprecated("Use `cross(CrossVersion)`, the variant accepting a CrossVersion value constructed by a member of the CrossVersion object instead.", "0.12.0") @deprecated("Use `cross(CrossVersion)`, the variant accepting a CrossVersion value constructed by a member of the CrossVersion object instead.", "0.12.0")
def cross(v: Boolean, verRemap: String => String): ModuleID = cross(if (v) CrossVersion.binaryMapped(verRemap) else CrossVersion.Disabled) def cross(v: Boolean, verRemap: String => String): ModuleID = cross(if (v) CrossVersion.binaryMapped(verRemap) else Disabled())
/** Specifies the cross-version behavior for this module. See [CrossVersion] for details.*/ /** Specifies the cross-version behavior for this module. See [CrossVersion] for details.*/
def cross(v: CrossVersion): ModuleID = copy(crossVersion = v) def cross(v: CrossVersion): ModuleID = copy(crossVersion = v)
@ -64,7 +88,7 @@ final case class ModuleID(organization: String, name: String, revision: String,
* Declares the explicit artifacts for this module. If this ModuleID represents a dependency, * Declares the explicit artifacts for this module. If this ModuleID represents a dependency,
* these artifact definitions override the information in the dependency's published metadata. * these artifact definitions override the information in the dependency's published metadata.
*/ */
def artifacts(newArtifacts: Artifact*) = copy(explicitArtifacts = newArtifacts ++ this.explicitArtifacts) def artifacts(newArtifacts: Artifact*) = copy(explicitArtifacts = newArtifacts.toVector ++ explicitArtifacts)
/** /**
* Applies the provided exclusions to dependencies of this module. Note that only exclusions that specify * Applies the provided exclusions to dependencies of this module. Note that only exclusions that specify
@ -73,7 +97,7 @@ final case class ModuleID(organization: String, name: String, revision: String,
def excludeAll(rules: InclExclRule*) = copy(exclusions = this.exclusions ++ rules) def excludeAll(rules: InclExclRule*) = copy(exclusions = this.exclusions ++ rules)
/** Excludes the dependency with organization `org` and `name` from being introduced by this dependency during resolution. */ /** Excludes the dependency with organization `org` and `name` from being introduced by this dependency during resolution. */
def exclude(org: String, name: String) = excludeAll(InclExclRule(org, name)) def exclude(org: String, name: String) = excludeAll(InclExclRule().withOrganization(org).withName(name))
/** /**
* Adds extra attributes for this module. All keys are prefixed with `e:` if they are not already so prefixed. * Adds extra attributes for this module. All keys are prefixed with `e:` if they are not already so prefixed.
@ -127,9 +151,7 @@ final case class ModuleID(organization: String, name: String, revision: String,
def branch(branchName: Option[String]) = copy(branchName = branchName) def branch(branchName: Option[String]) = copy(branchName = branchName)
} }
object ModuleID { abstract class ModuleIDCompanion {
implicit val pickler: Pickler[ModuleID] with Unpickler[ModuleID] = PicklerUnpickler.generate[ModuleID]
/** Prefixes all keys with `e:` if they are not already so prefixed. */ /** Prefixes all keys with `e:` if they are not already so prefixed. */
def checkE(attributes: Seq[(String, String)]) = def checkE(attributes: Seq[(String, String)]) =
for ((key, value) <- attributes) yield if (key.startsWith("e:")) (key, value) else ("e:" + key, value) for ((key, value) <- attributes) yield if (key.startsWith("e:")) (key, value) else ("e:" + key, value)

View File

@ -9,11 +9,7 @@ import scala.xml.XML
import org.apache.ivy.plugins.resolver.DependencyResolver import org.apache.ivy.plugins.resolver.DependencyResolver
import org.xml.sax.SAXParseException import org.xml.sax.SAXParseException
sealed trait Resolver { final class RawRepository(val resolver: DependencyResolver) extends Resolver(resolver.getName) {
def name: String
}
final class RawRepository(val resolver: DependencyResolver) extends Resolver {
def name = resolver.getName
override def toString = "Raw(" + resolver.toString + ")" override def toString = "Raw(" + resolver.toString + ")"
override def equals(o: Any): Boolean = o match { override def equals(o: Any): Boolean = o match {
@ -29,148 +25,30 @@ final class RawRepository(val resolver: DependencyResolver) extends Resolver {
hash hash
} }
} }
sealed case class ChainedResolver(name: String, resolvers: Seq[Resolver]) extends Resolver
/** An instance of a remote maven repository. Note: This will use Aether/Maven to resolve artifacts. */ abstract class PatternsCompanion {
sealed case class MavenRepository(name: String, root: String, localIfFile: Boolean = true) extends Resolver {
override def toString = s"$name: $root"
def isCache: Boolean = false
def withLocalIfFile(value: Boolean) = MavenRepository(name, root, value)
}
/**
* An instance of maven CACHE directory. You cannot treat a cache directory the same as a a remote repository because
* the metadata is different (see Aether ML discussion).
*/
final class MavenCache(name: String, val rootFile: File) extends MavenRepository(name, rootFile.toURI.toURL.toString) {
override val toString = s"cache:$name: ${rootFile.getAbsolutePath}"
override def isCache: Boolean = true
}
object MavenCache {
def apply(name: String, rootFile: File): MavenCache = new MavenCache(name, rootFile)
}
final class Patterns(val ivyPatterns: Seq[String], val artifactPatterns: Seq[String], val isMavenCompatible: Boolean, val descriptorOptional: Boolean, val skipConsistencyCheck: Boolean) {
private[sbt] def mavenStyle(): Patterns = Patterns(ivyPatterns, artifactPatterns, true)
private[sbt] def withDescriptorOptional(): Patterns = Patterns(ivyPatterns, artifactPatterns, isMavenCompatible, true, skipConsistencyCheck)
private[sbt] def withoutConsistencyCheck(): Patterns = Patterns(ivyPatterns, artifactPatterns, isMavenCompatible, descriptorOptional, true)
private[sbt] def withIvys(patterns: Seq[String]): Patterns = Patterns(patterns ++ ivyPatterns, artifactPatterns, isMavenCompatible)
private[sbt] def withArtifacts(patterns: Seq[String]): Patterns = Patterns(ivyPatterns, patterns ++ artifactPatterns, isMavenCompatible)
override def toString = "Patterns(ivyPatterns=%s, artifactPatterns=%s, isMavenCompatible=%s, descriptorOptional=%s, skipConsistencyCheck=%s)".format(ivyPatterns, artifactPatterns, isMavenCompatible, descriptorOptional, skipConsistencyCheck)
override def equals(obj: Any): Boolean = {
obj match {
case other: Patterns =>
ivyPatterns == other.ivyPatterns && artifactPatterns == other.artifactPatterns && isMavenCompatible == other.isMavenCompatible && descriptorOptional == other.descriptorOptional && skipConsistencyCheck == other.skipConsistencyCheck
case _ => false
}
}
override def hashCode: Int = (ivyPatterns, artifactPatterns, isMavenCompatible, descriptorOptional, skipConsistencyCheck).hashCode
}
object Patterns {
implicit def defaultPatterns: Patterns = Resolver.defaultPatterns implicit def defaultPatterns: Patterns = Resolver.defaultPatterns
def apply(artifactPatterns: String*): Patterns = Patterns(true, artifactPatterns: _*) def apply(artifactPatterns: String*): Patterns = Patterns(true, artifactPatterns: _*)
def apply(isMavenCompatible: Boolean, artifactPatterns: String*): Patterns = Patterns(artifactPatterns, artifactPatterns, isMavenCompatible) def apply(isMavenCompatible: Boolean, artifactPatterns: String*): Patterns = {
def apply(ivyPatterns: Seq[String], artifactPatterns: Seq[String], isMavenCompatible: Boolean): Patterns = apply(ivyPatterns: Seq[String], artifactPatterns: Seq[String], isMavenCompatible: Boolean, false, false) val patterns = artifactPatterns.toVector
def apply(ivyPatterns: Seq[String], artifactPatterns: Seq[String], isMavenCompatible: Boolean, descriptorOptional: Boolean, skipConsistencyCheck: Boolean): Patterns = new Patterns(ivyPatterns, artifactPatterns, isMavenCompatible, descriptorOptional, skipConsistencyCheck) Patterns().withIvyPatterns(patterns).withArtifactPatterns(patterns).withIsMavenCompatible(isMavenCompatible)
}
object RepositoryHelpers {
final case class SshConnection(authentication: Option[SshAuthentication], hostname: Option[String], port: Option[Int]) {
def copy(authentication: Option[SshAuthentication]) = SshConnection(authentication, hostname, port)
} }
/** Configuration specific to an Ivy filesystem resolver. */
final case class FileConfiguration(isLocal: Boolean, isTransactional: Option[Boolean]) {
def transactional() = FileConfiguration(isLocal, Some(true))
def nontransactional() = FileConfiguration(isLocal, Some(false))
def nonlocal() = FileConfiguration(false, isTransactional)
}
sealed trait SshAuthentication
final case class PasswordAuthentication(user: String, password: Option[String]) extends SshAuthentication
final case class KeyFileAuthentication(user: String, keyfile: File, password: Option[String]) extends SshAuthentication
} }
import RepositoryHelpers.{ SshConnection, FileConfiguration }
import RepositoryHelpers.{ KeyFileAuthentication, PasswordAuthentication, SshAuthentication }
/** sbt interface to an Ivy repository based on patterns, which is most Ivy repositories.*/
sealed abstract class PatternsBasedRepository extends Resolver {
type RepositoryType <: PatternsBasedRepository
/** Should be implemented to create a new copy of this repository but with `patterns` as given.*/
protected def copy(patterns: Patterns): RepositoryType
/** The object representing the configured patterns for this repository. */
def patterns: Patterns
/** Enables maven 2 compatibility for this repository. */
def mavenStyle() = copy(patterns.mavenStyle())
/** Makes descriptor metadata optional for this repository. */
def descriptorOptional() = copy(patterns.withDescriptorOptional())
/** Disables consistency checking for this repository. */
def skipConsistencyCheck() = copy(patterns.withoutConsistencyCheck())
/** Adds the given patterns for resolving/publishing Ivy files.*/
def ivys(ivyPatterns: String*): RepositoryType = copy(patterns.withIvys(ivyPatterns))
/** Adds the given patterns for resolving/publishing artifacts.*/
def artifacts(artifactPatterns: String*): RepositoryType = copy(patterns.withArtifacts(artifactPatterns))
}
/** sbt interface for an Ivy filesystem repository. More convenient construction is done using Resolver.file. */
final case class FileRepository(name: String, configuration: FileConfiguration, patterns: Patterns) extends PatternsBasedRepository {
type RepositoryType = FileRepository
protected def copy(patterns: Patterns): FileRepository = FileRepository(name, configuration, patterns)
private def copy(configuration: FileConfiguration) = FileRepository(name, configuration, patterns)
def transactional() = copy(configuration.transactional())
def nonlocal() = copy(configuration.nonlocal())
}
final case class URLRepository(name: String, patterns: Patterns) extends PatternsBasedRepository {
type RepositoryType = URLRepository
protected def copy(patterns: Patterns): URLRepository = URLRepository(name, patterns)
}
/** sbt interface for an Ivy ssh-based repository (ssh and sftp). Requires the Jsch library.. */
sealed abstract class SshBasedRepository extends PatternsBasedRepository {
type RepositoryType <: SshBasedRepository
protected def copy(connection: SshConnection): RepositoryType
private def copy(authentication: SshAuthentication): RepositoryType = copy(connection.copy(Some(authentication)))
/** The object representing the configured ssh connection for this repository. */
def connection: SshConnection
/** Configures this to use the specified user name and password when connecting to the remote repository. */
def as(user: String, password: String): RepositoryType = as(user, Some(password))
def as(user: String): RepositoryType = as(user, None)
def as(user: String, password: Option[String]) = copy(new PasswordAuthentication(user, password))
/** Configures this to use the specified keyfile and password for the keyfile when connecting to the remote repository. */
def as(user: String, keyfile: File): RepositoryType = as(user, keyfile, None)
def as(user: String, keyfile: File, password: String): RepositoryType = as(user, keyfile, Some(password))
def as(user: String, keyfile: File, password: Option[String]): RepositoryType = copy(new KeyFileAuthentication(user, keyfile, password))
}
/** sbt interface for an Ivy repository over ssh. More convenient construction is done using Resolver.ssh. */
final case class SshRepository(name: String, connection: SshConnection, patterns: Patterns, publishPermissions: Option[String]) extends SshBasedRepository {
type RepositoryType = SshRepository
protected def copy(patterns: Patterns): SshRepository = SshRepository(name, connection, patterns, publishPermissions)
protected def copy(connection: SshConnection): SshRepository = SshRepository(name, connection, patterns, publishPermissions)
/** Defines the permissions to set when publishing to this repository. */
def withPermissions(publishPermissions: String): SshRepository = withPermissions(Some(publishPermissions))
def withPermissions(publishPermissions: Option[String]): SshRepository = SshRepository(name, connection, patterns, publishPermissions)
}
/** sbt interface for an Ivy repository over sftp. More convenient construction is done using Resolver.sftp. */
final case class SftpRepository(name: String, connection: SshConnection, patterns: Patterns) extends SshBasedRepository {
type RepositoryType = SftpRepository
protected def copy(patterns: Patterns): SftpRepository = SftpRepository(name, connection, patterns)
protected def copy(connection: SshConnection): SftpRepository = SftpRepository(name, connection, patterns)
}
/** A repository that conforms to sbt launcher's interface */ /** A repository that conforms to sbt launcher's interface */
private[sbt] class FakeRepository(resolver: DependencyResolver) extends xsbti.Repository { private[sbt] class FakeRepository(resolver: DependencyResolver) extends xsbti.Repository {
def rawRepository = new RawRepository(resolver) def rawRepository = new RawRepository(resolver)
} }
import Resolver._ trait ResolversSyntax {
import Resolver._
val DefaultMavenRepository = new MavenRepository("public", centralRepositoryRoot(useSecureResolvers))
val JavaNet2Repository = new MavenRepository(JavaNet2RepositoryName, JavaNet2RepositoryRoot)
val JCenterRepository = new MavenRepository(JCenterRepositoryName, JCenterRepositoryRoot)
}
object DefaultMavenRepository extends MavenRepository("public", centralRepositoryRoot(useSecureResolvers)) abstract class ResolverCompanion {
object JavaNet2Repository extends MavenRepository(JavaNet2RepositoryName, JavaNet2RepositoryRoot)
object JCenterRepository extends MavenRepository(JCenterRepositoryName, JCenterRepositoryRoot)
object Resolver {
private[sbt] def useSecureResolvers = sys.props.get("sbt.repository.secure") map { _.toLowerCase == "true" } getOrElse true private[sbt] def useSecureResolvers = sys.props.get("sbt.repository.secure") map { _.toLowerCase == "true" } getOrElse true
val TypesafeRepositoryRoot = typesafeRepositoryRoot(useSecureResolvers) val TypesafeRepositoryRoot = typesafeRepositoryRoot(useSecureResolvers)
@ -342,7 +220,7 @@ object Resolver {
/** Resolves the ivy file and artifact patterns in `patterns` against the given base. */ /** Resolves the ivy file and artifact patterns in `patterns` against the given base. */
private def resolvePatterns(base: String, basePatterns: Patterns): Patterns = private def resolvePatterns(base: String, basePatterns: Patterns): Patterns =
{ {
def resolveAll(patterns: Seq[String]) = patterns.map(p => resolvePattern(base, p)) def resolveAll(patterns: Vector[String]) = patterns.map(p => resolvePattern(base, p))
Patterns(resolveAll(basePatterns.ivyPatterns), resolveAll(basePatterns.artifactPatterns), basePatterns.isMavenCompatible, basePatterns.descriptorOptional, basePatterns.skipConsistencyCheck) Patterns(resolveAll(basePatterns.ivyPatterns), resolveAll(basePatterns.artifactPatterns), basePatterns.isMavenCompatible, basePatterns.descriptorOptional, basePatterns.skipConsistencyCheck)
} }
private[sbt] def resolvePattern(base: String, pattern: String): String = private[sbt] def resolvePattern(base: String, pattern: String): String =
@ -351,7 +229,7 @@ object Resolver {
if (normBase.endsWith("/") || pattern.startsWith("/")) normBase + pattern else normBase + "/" + pattern if (normBase.endsWith("/") || pattern.startsWith("/")) normBase + pattern else normBase + "/" + pattern
} }
def defaultFileConfiguration = FileConfiguration(true, None) def defaultFileConfiguration = FileConfiguration(true, None)
def mavenStylePatterns = Patterns(Nil, mavenStyleBasePattern :: Nil, true) def mavenStylePatterns = Patterns().withArtifactPatterns(Vector(mavenStyleBasePattern))
def ivyStylePatterns = defaultIvyPatterns //Patterns(Nil, Nil, false) def ivyStylePatterns = defaultIvyPatterns //Patterns(Nil, Nil, false)
def defaultPatterns = mavenStylePatterns def defaultPatterns = mavenStylePatterns
@ -381,17 +259,17 @@ object Resolver {
} }
// TODO - should this just be the *exact* same as mavenLocal? probably... // TODO - should this just be the *exact* same as mavenLocal? probably...
def publishMavenLocal: MavenCache = new MavenCache("publish-m2-local", mavenLocalDir) def publishMavenLocal: MavenCache = new MavenCache("publish-m2-local", mavenLocalDir)
def mavenLocal: MavenRepository = new MavenCache("Maven2 Local", mavenLocalDir) def mavenLocal: IMavenRepository = new MavenCache("Maven2 Local", mavenLocalDir)
def defaultLocal = defaultUserFileRepository("local") def defaultLocal = defaultUserFileRepository("local")
def defaultShared = defaultUserFileRepository("shared") def defaultShared = defaultUserFileRepository("shared")
def defaultUserFileRepository(id: String) = def defaultUserFileRepository(id: String) =
{ {
val pList = s"$${ivy.home}/$id/$localBasePattern" :: Nil val pList = Vector(s"$${ivy.home}/$id/$localBasePattern")
FileRepository(id, defaultFileConfiguration, Patterns(pList, pList, false)) FileRepository(id, defaultFileConfiguration, Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false))
} }
def defaultIvyPatterns = def defaultIvyPatterns =
{ {
val pList = List(localBasePattern) val pList = Vector(localBasePattern)
Patterns(pList, pList, false) Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false)
} }
} }

View File

@ -5,21 +5,13 @@ package sbt.librarymanagement
import java.io.File import java.io.File
import java.{ util => ju } import java.{ util => ju }
import sbt.serialization._
/** abstract class ConfigurationReportParent {
* Provides information about resolution of a single configuration. def configuration: String
* @param configuration the configuration this report is for. def modules: Vector[ModuleReport]
* @param modules a sequence containing one report for each module resolved for this configuration. def details: Vector[OrganizationArtifactReport]
* @param details a sequence containing one report for each org/name, which may or may not be part of the final resolution.
* @param evicted a sequence of evicted modules
*/
final class ConfigurationReport(
val configuration: String,
val modules: Seq[ModuleReport],
val details: Seq[OrganizationArtifactReport]
) {
/** a sequence of evicted modules */
def evicted: Seq[ModuleID] = def evicted: Seq[ModuleID] =
details flatMap (_.modules) filter (_.evicted) map (_.module) details flatMap (_.modules) filter (_.evicted) map (_.module)
@ -36,78 +28,36 @@ final class ConfigurationReport(
val module = mr.module val module = mr.module
if (module.configurations.isEmpty) { if (module.configurations.isEmpty) {
val conf = mr.configurations map (c => s"$configuration->$c") mkString ";" val conf = mr.configurations map (c => s"$configuration->$c") mkString ";"
module.copy(configurations = Some(conf)) module.withConfigurations(Some(conf))
} else module } else module
} }
def retrieve(f: (String, ModuleID, Artifact, File) => File): ConfigurationReport = def retrieve(f: (String, ModuleID, Artifact, File) => File): ConfigurationReport =
new ConfigurationReport(configuration, modules map { _.retrieve((mid, art, file) => f(configuration, mid, art, file)) }, details) new ConfigurationReport(configuration, modules map { _.retrieve((mid, art, file) => f(configuration, mid, art, file)) }, details)
} }
object ConfigurationReport {
implicit val pickler: Pickler[ConfigurationReport] with Unpickler[ConfigurationReport] = PicklerUnpickler.generate[ConfigurationReport]
}
/** abstract class ModuleReportParent {
* OrganizationArtifactReport represents an organization+name entry in Ivy resolution report. def module: ModuleID
* In sbt's terminology, "module" consists of organization, name, and version. def artifacts: Vector[(Artifact, File)]
* In Ivy's, "module" means just organization and name, and the one including version numbers def missingArtifacts: Vector[Artifact]
* are called revisions. def status: Option[String]
* def publicationDate: Option[ju.Date]
* A sequence of OrganizationArtifactReport called details is newly added to ConfigurationReport, replacing evicted. def resolver: Option[String]
* (Note old evicted was just a seq of ModuleIDs). def artifactResolver: Option[String]
* OrganizationArtifactReport groups the ModuleReport of both winners and evicted reports by their organization and name, def evicted: Boolean
* which can be used to calculate detailed evction warning etc. def evictedData: Option[String]
*/ def evictedReason: Option[String]
final class OrganizationArtifactReport private[sbt] ( def problem: Option[String]
val organization: String, def homepage: Option[String]
val name: String, def extraAttributes: Map[String, String]
val modules: Seq[ModuleReport] def isDefault: Option[Boolean]
) { def branch: Option[String]
override def toString: String = { def configurations: Vector[String]
val details = modules map { _.detailReport } def licenses: Vector[(String, Option[String])]
s"\t$organization:$name\n${details.mkString}\n" def callers: Vector[Caller]
}
}
object OrganizationArtifactReport {
implicit val pickler: Pickler[OrganizationArtifactReport] with Unpickler[OrganizationArtifactReport] = PicklerUnpickler.generate[OrganizationArtifactReport]
def apply(organization: String, name: String, modules: Seq[ModuleReport]): OrganizationArtifactReport = protected[this] def arts: Vector[String] = artifacts.map(_.toString) ++ missingArtifacts.map(art => "(MISSING) " + art)
new OrganizationArtifactReport(organization, name, modules)
}
/**
* Provides information about the resolution of a module.
* This information is in the context of a specific configuration.
* @param module the `ModuleID` this report is for.
* @param artifacts the resolved artifacts for this module, paired with the File the artifact was retrieved to.
* @param missingArtifacts the missing artifacts for this module.
*/
final class ModuleReport(
val module: ModuleID,
val artifacts: Seq[(Artifact, File)],
val missingArtifacts: Seq[Artifact],
val status: Option[String],
val publicationDate: Option[ju.Date],
val resolver: Option[String],
val artifactResolver: Option[String],
val evicted: Boolean,
val evictedData: Option[String],
val evictedReason: Option[String],
val problem: Option[String],
val homepage: Option[String],
val extraAttributes: Map[String, String],
val isDefault: Option[Boolean],
val branch: Option[String],
val configurations: Seq[String],
val licenses: Seq[(String, Option[String])],
val callers: Seq[Caller]
) {
private[this] lazy val arts: Seq[String] = artifacts.map(_.toString) ++ missingArtifacts.map(art => "(MISSING) " + art)
override def toString: String = {
s"\t\t$module: " +
(if (arts.size <= 1) "" else "\n\t\t\t") + arts.mkString("\n\t\t\t") + "\n"
}
def detailReport: String = def detailReport: String =
s"\t\t- ${module.revision}\n" + s"\t\t- ${module.revision}\n" +
(if (arts.size <= 1) "" else arts.mkString("\t\t\t", "\n\t\t\t", "\n")) + (if (arts.size <= 1) "" else arts.mkString("\t\t\t", "\n\t\t\t", "\n")) +
@ -148,10 +98,10 @@ final class ModuleReport(
def retrieve(f: (ModuleID, Artifact, File) => File): ModuleReport = def retrieve(f: (ModuleID, Artifact, File) => File): ModuleReport =
copy(artifacts = artifacts.map { case (art, file) => (art, f(module, art, file)) }) copy(artifacts = artifacts.map { case (art, file) => (art, f(module, art, file)) })
private[sbt] def copy( protected[this] def copy(
module: ModuleID = module, module: ModuleID = module,
artifacts: Seq[(Artifact, File)] = artifacts, artifacts: Vector[(Artifact, File)] = artifacts,
missingArtifacts: Seq[Artifact] = missingArtifacts, missingArtifacts: Vector[Artifact] = missingArtifacts,
status: Option[String] = status, status: Option[String] = status,
publicationDate: Option[ju.Date] = publicationDate, publicationDate: Option[ju.Date] = publicationDate,
resolver: Option[String] = resolver, resolver: Option[String] = resolver,
@ -164,66 +114,31 @@ final class ModuleReport(
extraAttributes: Map[String, String] = extraAttributes, extraAttributes: Map[String, String] = extraAttributes,
isDefault: Option[Boolean] = isDefault, isDefault: Option[Boolean] = isDefault,
branch: Option[String] = branch, branch: Option[String] = branch,
configurations: Seq[String] = configurations, configurations: Vector[String] = configurations,
licenses: Seq[(String, Option[String])] = licenses, licenses: Vector[(String, Option[String])] = licenses,
callers: Seq[Caller] = callers callers: Vector[Caller] = callers
): ModuleReport = ): ModuleReport
new ModuleReport(module, artifacts, missingArtifacts, status, publicationDate, resolver, artifactResolver,
evicted, evictedData, evictedReason, problem, homepage, extraAttributes, isDefault, branch, configurations, licenses, callers)
} }
object ModuleReport { abstract class UpdateReportParent {
def apply(module: ModuleID, artifacts: Seq[(Artifact, File)], missingArtifacts: Seq[Artifact]): ModuleReport = def cachedDescriptor: File
new ModuleReport(module, artifacts, missingArtifacts, None, None, None, None, def configurations: Vector[ConfigurationReport]
false, None, None, None, None, Map(), None, None, Nil, Nil, Nil) def stats: UpdateStats
implicit val pickler: Pickler[ModuleReport] with Unpickler[ModuleReport] = PicklerUnpickler.generate[ModuleReport] private[sbt] def stamps: Map[File, Long]
}
final class Caller(
val caller: ModuleID,
val callerConfigurations: Seq[String],
val callerExtraAttributes: Map[String, String],
val isForceDependency: Boolean,
val isChangingDependency: Boolean,
val isTransitiveDependency: Boolean,
val isDirectlyForceDependency: Boolean
) {
override def toString: String =
s"$caller"
}
object Caller {
implicit val pickler: Pickler[Caller] with Unpickler[Caller] = PicklerUnpickler.generate[Caller]
}
/**
* Provides information about dependency resolution.
* It does not include information about evicted modules, only about the modules ultimately selected by the conflict manager.
* This means that for a given configuration, there should only be one revision for a given organization and module name.
* @param cachedDescriptor the location of the resolved module descriptor in the cache
* @param configurations a sequence containing one report for each configuration resolved.
* @param stats information about the update that produced this report
* @see sbt.RichUpdateReport
*/
final class UpdateReport(val cachedDescriptor: File, val configurations: Seq[ConfigurationReport], val stats: UpdateStats, private[sbt] val stamps: Map[File, Long]) {
@deprecated("Use the variant that provides timestamps of files.", "0.13.0")
def this(cachedDescriptor: File, configurations: Seq[ConfigurationReport], stats: UpdateStats) =
this(cachedDescriptor, configurations, stats, Map.empty)
override def toString = "Update report:\n\t" + stats + "\n" + configurations.mkString
/** All resolved modules in all configurations. */ /** All resolved modules in all configurations. */
def allModules: Seq[ModuleID] = def allModules: Vector[ModuleID] =
{ {
val key = (m: ModuleID) => (m.organization, m.name, m.revision) val key = (m: ModuleID) => (m.organization, m.name, m.revision)
configurations.flatMap(_.allModules).groupBy(key).toSeq map { configurations.flatMap(_.allModules).groupBy(key).toVector map {
case (k, v) => case (k, v) =>
v reduceLeft { (agg, x) => v reduceLeft { (agg, x) =>
agg.copy( agg.withConfigurations(
configurations = (agg.configurations, x.configurations) match { (agg.configurations, x.configurations) match {
case (None, _) => x.configurations case (None, _) => x.configurations
case (Some(ac), None) => Some(ac) case (Some(ac), None) => Some(ac)
case (Some(ac), Some(xc)) => Some(s"$ac;$xc") case (Some(ac), Some(xc)) => Some(s"$ac;$xc")
} }
) )
} }
} }
@ -237,81 +152,4 @@ final class UpdateReport(val cachedDescriptor: File, val configurations: Seq[Con
/** Gets the names of all resolved configurations. This `UpdateReport` contains one `ConfigurationReport` for each configuration in this list. */ /** Gets the names of all resolved configurations. This `UpdateReport` contains one `ConfigurationReport` for each configuration in this list. */
def allConfigurations: Seq[String] = configurations.map(_.configuration) def allConfigurations: Seq[String] = configurations.map(_.configuration)
private[sbt] def withStats(us: UpdateStats): UpdateReport =
new UpdateReport(
this.cachedDescriptor,
this.configurations,
us,
this.stamps
)
}
object UpdateReport {
private val vectorConfigurationReportPickler = implicitly[Pickler[Vector[ConfigurationReport]]]
private val vectorConfigurationReportUnpickler = implicitly[Unpickler[Vector[ConfigurationReport]]]
private val updateStatsPickler = implicitly[Pickler[UpdateStats]]
private val updateStatsUnpickler = implicitly[Unpickler[UpdateStats]]
private val flMapPickler = implicitly[Pickler[Map[File, Long]]]
private val flMapUnpickler = implicitly[Unpickler[Map[File, Long]]]
implicit val pickler: Pickler[UpdateReport] with Unpickler[UpdateReport] = new Pickler[UpdateReport] with Unpickler[UpdateReport] {
val tag = implicitly[FastTypeTag[UpdateReport]]
val fileTag = implicitly[FastTypeTag[File]]
val vectorConfigurationReportTag = implicitly[FastTypeTag[Vector[ConfigurationReport]]]
val updateStatsTag = implicitly[FastTypeTag[UpdateStats]]
val flMapTag = implicitly[FastTypeTag[Map[File, Long]]]
def pickle(a: UpdateReport, builder: PBuilder): Unit = {
builder.pushHints()
builder.hintTag(tag)
builder.beginEntry(a)
builder.putField("cachedDescriptor", { b =>
b.hintTag(fileTag)
filePickler.pickle(a.cachedDescriptor, b)
})
builder.putField("configurations", { b =>
b.hintTag(vectorConfigurationReportTag)
vectorConfigurationReportPickler.pickle(a.configurations.toVector, b)
})
builder.putField("stats", { b =>
b.hintTag(updateStatsTag)
updateStatsPickler.pickle(a.stats, b)
})
builder.putField("stamps", { b =>
b.hintTag(flMapTag)
flMapPickler.pickle(a.stamps, b)
})
builder.endEntry()
builder.popHints()
()
}
def unpickle(tpe: String, reader: PReader): Any = {
reader.pushHints()
reader.hintTag(tag)
reader.beginEntry()
val cachedDescriptor = filePickler.unpickleEntry(reader.readField("cachedDescriptor")).asInstanceOf[File]
val configurations = vectorConfigurationReportUnpickler.unpickleEntry(reader.readField("configurations")).asInstanceOf[Vector[ConfigurationReport]]
val stats = updateStatsUnpickler.unpickleEntry(reader.readField("stats")).asInstanceOf[UpdateStats]
val stamps = flMapUnpickler.unpickleEntry(reader.readField("stamps")).asInstanceOf[Map[File, Long]]
val result = new UpdateReport(cachedDescriptor, configurations, stats, stamps)
reader.endEntry()
reader.popHints()
result
}
}
}
final class UpdateStats(val resolveTime: Long, val downloadTime: Long, val downloadSize: Long, val cached: Boolean) {
override def toString = Seq("Resolve time: " + resolveTime + " ms", "Download time: " + downloadTime + " ms", "Download size: " + downloadSize + " bytes").mkString(", ")
private[sbt] def withCached(c: Boolean): UpdateStats =
new UpdateStats(
resolveTime = this.resolveTime,
downloadTime = this.downloadTime,
downloadSize = this.downloadSize,
cached = c
)
}
object UpdateStats {
implicit val pickler: Pickler[UpdateStats] with Unpickler[UpdateStats] = PicklerUnpickler.generate[UpdateStats]
} }

View File

@ -1,6 +1,6 @@
package sbt package sbt
package object librarymanagement { package object librarymanagement extends ResolversSyntax {
type ExclusionRule = InclExclRule type ExclusionRule = InclExclRule
val ExclusionRule = InclExclRule val ExclusionRule = InclExclRule

View File

@ -10,22 +10,32 @@ import sbt.librarymanagement._
import ivyint.SbtChainResolver import ivyint.SbtChainResolver
import Configurations._ import Configurations._
import sbt.internal.util.FileBasedStore
import sjsonnew.IsoString
import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter }
import scala.json.ast.unsafe.JValue
trait BaseIvySpecification extends UnitSpec { trait BaseIvySpecification extends UnitSpec {
def currentBase: File = new File(".") def currentBase: File = new File(".")
def currentTarget: File = currentBase / "target" / "ivyhome" def currentTarget: File = currentBase / "target" / "ivyhome"
def currentManaged: File = currentBase / "target" / "lib_managed" def currentManaged: File = currentBase / "target" / "lib_managed"
def currentDependency: File = currentBase / "target" / "dependency" def currentDependency: File = currentBase / "target" / "dependency"
def defaultModuleId: ModuleID = ModuleID("com.example", "foo", "0.1.0", Some("compile")) def defaultModuleId: ModuleID = ModuleID("com.example", "foo", "0.1.0").withConfigurations(Some("compile"))
implicit val isoString: IsoString[JValue] = IsoString.iso(CompactPrinter.apply, FixedParser.parseUnsafe)
val fileToStore = (f: File) => new FileBasedStore(f, Converter)
lazy val log = ConsoleLogger() lazy val log = ConsoleLogger()
def configurations = Seq(Compile, Test, Runtime) def configurations = Vector(Compile, Test, Runtime)
def module(moduleId: ModuleID, deps: Seq[ModuleID], scalaFullVersion: Option[String], def module(moduleId: ModuleID, deps: Vector[ModuleID], scalaFullVersion: Option[String],
uo: UpdateOptions = UpdateOptions(), overrideScalaVersion: Boolean = true): IvySbt#Module = { uo: UpdateOptions = UpdateOptions(), overrideScalaVersion: Boolean = true): IvySbt#Module = {
val ivyScala = scalaFullVersion map { fv => val ivyScala = scalaFullVersion map { fv =>
new IvyScala( new IvyScala(
scalaFullVersion = fv, scalaFullVersion = fv,
scalaBinaryVersion = CrossVersionUtil.binaryScalaVersion(fv), scalaBinaryVersion = CrossVersionUtil.binaryScalaVersion(fv),
configurations = Nil, configurations = Vector.empty,
checkExplicit = true, checkExplicit = true,
filterImplicit = false, filterImplicit = false,
overrideScalaVersion = overrideScalaVersion overrideScalaVersion = overrideScalaVersion
@ -33,32 +43,32 @@ trait BaseIvySpecification extends UnitSpec {
} }
val moduleSetting: ModuleSettings = InlineConfiguration( val moduleSetting: ModuleSettings = InlineConfiguration(
false,
ivyScala,
module = moduleId, module = moduleId,
moduleInfo = ModuleInfo("foo"), moduleInfo = ModuleInfo("foo"),
dependencies = deps, dependencies = deps
configurations = configurations, ).withConfigurations(configurations)
ivyScala = ivyScala val ivySbt = new IvySbt(mkIvyConfiguration(uo), fileToStore)
)
val ivySbt = new IvySbt(mkIvyConfiguration(uo))
new ivySbt.Module(moduleSetting) new ivySbt.Module(moduleSetting)
} }
def resolvers: Seq[Resolver] = Seq(DefaultMavenRepository) def resolvers: Vector[Resolver] = Vector(DefaultMavenRepository)
def chainResolver = ChainedResolver("sbt-chain", resolvers) def chainResolver = ChainedResolver("sbt-chain", resolvers)
def mkIvyConfiguration(uo: UpdateOptions): IvyConfiguration = { def mkIvyConfiguration(uo: UpdateOptions): IvyConfiguration = {
val paths = new IvyPaths(currentBase, Some(currentTarget)) val paths = new IvyPaths(currentBase, Some(currentTarget))
val other = Nil val other = Vector.empty
val moduleConfs = Seq(ModuleConfiguration("*", chainResolver)) val moduleConfs = Vector(ModuleConfiguration("*", chainResolver))
val off = false val off = false
val check = Nil val check = Vector.empty
val resCacheDir = currentTarget / "resolution-cache" val resCacheDir = currentTarget / "resolution-cache"
new InlineIvyConfiguration(paths, resolvers, other, moduleConfs, off, None, check, Some(resCacheDir), uo, log) new InlineIvyConfiguration(paths, resolvers, other, moduleConfs, off, None, check, Some(resCacheDir), uo, log)
} }
def makeUpdateConfiguration: UpdateConfiguration = { def makeUpdateConfiguration: UpdateConfiguration = {
val retrieveConfig = new RetrieveConfiguration(currentManaged, Resolver.defaultRetrievePattern, false) val retrieveConfig = new RetrieveConfiguration(currentManaged, Resolver.defaultRetrievePattern).withSync(false)
new UpdateConfiguration(Some(retrieveConfig), false, UpdateLogging.Full, ArtifactTypeFilter.forbid(Set("src", "doc"))) new UpdateConfiguration(Some(retrieveConfig), false, UpdateLogging.Full, ArtifactTypeFilter.forbid(Set("src", "doc")))
} }
@ -84,7 +94,7 @@ trait BaseIvySpecification extends UnitSpec {
ivyFile = None, ivyFile = None,
resolverName = resolver.name, resolverName = resolver.name,
artifacts = artifacts, artifacts = artifacts,
checksums = Seq(), checksums = Vector.empty,
logging = UpdateLogging.Full, logging = UpdateLogging.Full,
overwrite = true overwrite = true
) )

View File

@ -9,8 +9,8 @@ class CachedResolutionSpec extends BaseIvySpecification {
"Resolving the same module twice" should "work" in { "Resolving the same module twice" should "work" in {
cleanIvyCache() cleanIvyCache()
val m = module( val m = module(
ModuleID("com.example", "foo", "0.1.0", Some("compile")), ModuleID("com.example", "foo", "0.1.0").withConfigurations(Some("compile")),
Seq(commonsIo13), Some("2.10.2"), UpdateOptions().withCachedResolution(true) Vector(commonsIo13), Some("2.10.2"), UpdateOptions().withCachedResolution(true)
) )
val report = ivyUpdate(m) val report = ivyUpdate(m)
cleanCachedResolutionCache(m) cleanCachedResolutionCache(m)
@ -25,8 +25,8 @@ class CachedResolutionSpec extends BaseIvySpecification {
"Resolving the unsolvable module should" should "not work" in { "Resolving the unsolvable module should" should "not work" in {
// log.setLevel(Level.Debug) // log.setLevel(Level.Debug)
val m = module( val m = module(
ModuleID("com.example", "foo", "0.2.0", Some("compile")), ModuleID("com.example", "foo", "0.2.0").withConfigurations(Some("compile")),
Seq(mavenCayennePlugin302), Some("2.10.2"), UpdateOptions().withCachedResolution(true) Vector(mavenCayennePlugin302), Some("2.10.2"), UpdateOptions().withCachedResolution(true)
) )
ivyUpdateEither(m) match { ivyUpdateEither(m) match {
case Right(_) => sys.error("this should've failed") case Right(_) => sys.error("this should've failed")
@ -52,8 +52,8 @@ class CachedResolutionSpec extends BaseIvySpecification {
// log.setLevel(Level.Debug) // log.setLevel(Level.Debug)
cleanIvyCache() cleanIvyCache()
val m = module( val m = module(
ModuleID("com.example", "foo", "0.3.0", Some("compile")), ModuleID("com.example", "foo", "0.3.0").withConfigurations(Some("compile")),
Seq(avro177, dataAvro1940, netty320), Vector(avro177, dataAvro1940, netty320),
Some("2.10.2"), UpdateOptions().withCachedResolution(true) Some("2.10.2"), UpdateOptions().withCachedResolution(true)
) )
// first resolution creates the minigraph // first resolution creates the minigraph
@ -66,11 +66,11 @@ class CachedResolutionSpec extends BaseIvySpecification {
assert(!(modules exists { x: String => x contains """org.jboss.netty:netty:3.2.1.Final""" })) assert(!(modules exists { x: String => x contains """org.jboss.netty:netty:3.2.1.Final""" }))
} }
def commonsIo13 = ModuleID("commons-io", "commons-io", "1.3", Some("compile")) def commonsIo13 = ModuleID("commons-io", "commons-io", "1.3").withConfigurations(Some("compile"))
def mavenCayennePlugin302 = ModuleID("org.apache.cayenne.plugins", "maven-cayenne-plugin", "3.0.2", Some("compile")) def mavenCayennePlugin302 = ModuleID("org.apache.cayenne.plugins", "maven-cayenne-plugin", "3.0.2").withConfigurations(Some("compile"))
def avro177 = ModuleID("org.apache.avro", "avro", "1.7.7", Some("compile")) def avro177 = ModuleID("org.apache.avro", "avro", "1.7.7").withConfigurations(Some("compile"))
def dataAvro1940 = ModuleID("com.linkedin.pegasus", "data-avro", "1.9.40", Some("compile")) def dataAvro1940 = ModuleID("com.linkedin.pegasus", "data-avro", "1.9.40").withConfigurations(Some("compile"))
def netty320 = ModuleID("org.jboss.netty", "netty", "3.2.0.Final", Some("compile")) def netty320 = ModuleID("org.jboss.netty", "netty", "3.2.0.Final").withConfigurations(Some("compile"))
def defaultOptions = EvictionWarningOptions.default def defaultOptions = EvictionWarningOptions.default
} }

View File

@ -116,7 +116,7 @@ class CrossVersionTest extends UnitSpec {
CrossVersion.binaryScalaVersion("2.10.1") shouldBe "2.10" CrossVersion.binaryScalaVersion("2.10.1") shouldBe "2.10"
} }
it should "return disabled cross version as equal to a copy" in { it should "return disabled cross version as equal to a copy" in {
CrossVersion.Disabled shouldBe CrossVersion.Disabled Disabled() shouldBe Disabled()
} }
it should "return full cross version as equal to a copy" in { it should "return full cross version as equal to a copy" in {
CrossVersion.full shouldBe CrossVersion.full CrossVersion.full shouldBe CrossVersion.full

View File

@ -16,8 +16,8 @@ class CustomPomParserTest extends UnitSpec {
val repoUrl = getClass.getResource("/test-maven-repo") val repoUrl = getClass.getResource("/test-maven-repo")
val local = MavenRepository("Test Repo", repoUrl.toExternalForm) val local = MavenRepository("Test Repo", repoUrl.toExternalForm)
val paths = new IvyPaths(new File("."), Some(cacheDir)) val paths = new IvyPaths(new File("."), Some(cacheDir))
val conf = new InlineIvyConfiguration(paths, Seq(local), Nil, Nil, false, None, Seq("sha1", "md5"), None, UpdateOptions(), log) val conf = new InlineIvyConfiguration(paths, Vector(local), Vector.empty, Vector.empty, false, None, Vector("sha1", "md5"), None, UpdateOptions(), log)
val ivySbt = new IvySbt(conf) val ivySbt = new IvySbt(conf, DefaultFileToStore)
val resolveOpts = new ResolveOptions().setConfs(Array("default")) val resolveOpts = new ResolveOptions().setConfs(Array("default"))
val mrid = ModuleRevisionId.newInstance("com.test", "test-artifact", "1.0.0-SNAPSHOT") val mrid = ModuleRevisionId.newInstance("com.test", "test-artifact", "1.0.0-SNAPSHOT")

View File

@ -2,8 +2,12 @@ package sbt.librarymanagement
import java.net.URL import java.net.URL
import java.io.File import java.io.File
import sbt.serialization._
import sbt.internal.util.UnitSpec import sbt.internal._, librarymanagement._, util.UnitSpec
import scala.json.ast.unsafe._
import sjsonnew._, support.scalajson.unsafe._
import LibraryManagementCodec._
class DMSerializationSpec extends UnitSpec { class DMSerializationSpec extends UnitSpec {
"CrossVersion.full" should "roundtrip" in { "CrossVersion.full" should "roundtrip" in {
@ -13,7 +17,7 @@ class DMSerializationSpec extends UnitSpec {
roundtripStr(CrossVersion.binary: CrossVersion) roundtripStr(CrossVersion.binary: CrossVersion)
} }
"CrossVersion.Disabled" should "roundtrip" in { "CrossVersion.Disabled" should "roundtrip" in {
roundtrip(CrossVersion.Disabled: CrossVersion) roundtrip(Disabled(): CrossVersion)
} }
"""Artifact("foo")""" should "roundtrip" in { """Artifact("foo")""" should "roundtrip" in {
roundtrip(Artifact("foo")) roundtrip(Artifact("foo"))
@ -34,7 +38,7 @@ class DMSerializationSpec extends UnitSpec {
roundtrip(ModuleID("org", "name", "1.0")) roundtrip(ModuleID("org", "name", "1.0"))
} }
"""ModuleReport(ModuleID("org", "name", "1.0"), Nil, Nil)""" should "roundtrip" in { """ModuleReport(ModuleID("org", "name", "1.0"), Nil, Nil)""" should "roundtrip" in {
roundtripStr(ModuleReport(ModuleID("org", "name", "1.0"), Nil, Nil)) roundtripStr(ModuleReport(ModuleID("org", "name", "1.0"), Vector.empty, Vector.empty))
} }
"Organization artifact report" should "roundtrip" in { "Organization artifact report" should "roundtrip" in {
roundtripStr(organizationArtifactReportExample) roundtripStr(organizationArtifactReportExample)
@ -55,17 +59,19 @@ class DMSerializationSpec extends UnitSpec {
lazy val organizationArtifactReportExample = lazy val organizationArtifactReportExample =
new OrganizationArtifactReport("org", "name", Vector(moduleReportExample)) new OrganizationArtifactReport("org", "name", Vector(moduleReportExample))
lazy val moduleReportExample = lazy val moduleReportExample =
ModuleReport(ModuleID("org", "name", "1.0"), Nil, Nil) ModuleReport(ModuleID("org", "name", "1.0"), Vector.empty, Vector.empty)
def roundtrip[A: Pickler: Unpickler](a: A): Unit = def roundtrip[A: JsonReader: JsonWriter](a: A): Unit =
roundtripBuilder(a) { _ shouldBe _ } roundtripBuilder(a) { _ shouldBe _ }
def roundtripStr[A: Pickler: Unpickler](a: A): Unit = def roundtripStr[A: JsonReader: JsonWriter](a: A): Unit =
roundtripBuilder(a) { _.toString shouldBe _.toString } roundtripBuilder(a) { _.toString shouldBe _.toString }
def roundtripBuilder[A: Pickler: Unpickler](a: A)(f: (A, A) => Unit): Unit = def roundtripBuilder[A: JsonReader: JsonWriter](a: A)(f: (A, A) => Unit): Unit =
{ {
val json = toJsonString(a) val json = isoString to (Converter toJsonUnsafe a)
println(json) println(json)
val obj = fromJsonString[A](json).get val obj = Converter fromJsonUnsafe[A] (isoString from json)
f(a, obj) f(a, obj)
} }
implicit val isoString: IsoString[JValue] = IsoString.iso(CompactPrinter.apply, FixedParser.parseUnsafe)
} }

View File

@ -44,25 +44,25 @@ class EvictionWarningSpec extends BaseIvySpecification {
it should "be detected if it's enabled" in scalaLibTransitiveWarn2() it should "be detected if it's enabled" in scalaLibTransitiveWarn2()
it should "print out message about the eviction if it's enabled" in scalaLibTransitiveWarn3() it should "print out message about the eviction if it's enabled" in scalaLibTransitiveWarn3()
def akkaActor214 = ModuleID("com.typesafe.akka", "akka-actor", "2.1.4", Some("compile")) cross CrossVersion.binary def akkaActor214 = ModuleID("com.typesafe.akka", "akka-actor", "2.1.4").withConfigurations(Some("compile")) cross CrossVersion.binary
def akkaActor230 = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0", Some("compile")) cross CrossVersion.binary def akkaActor230 = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("compile")) cross CrossVersion.binary
def akkaActor234 = ModuleID("com.typesafe.akka", "akka-actor", "2.3.4", Some("compile")) cross CrossVersion.binary def akkaActor234 = ModuleID("com.typesafe.akka", "akka-actor", "2.3.4").withConfigurations(Some("compile")) cross CrossVersion.binary
def scala2102 = ModuleID("org.scala-lang", "scala-library", "2.10.2", Some("compile")) def scala2102 = ModuleID("org.scala-lang", "scala-library", "2.10.2").withConfigurations(Some("compile"))
def scala2103 = ModuleID("org.scala-lang", "scala-library", "2.10.3", Some("compile")) def scala2103 = ModuleID("org.scala-lang", "scala-library", "2.10.3").withConfigurations(Some("compile"))
def scala2104 = ModuleID("org.scala-lang", "scala-library", "2.10.4", Some("compile")) def scala2104 = ModuleID("org.scala-lang", "scala-library", "2.10.4").withConfigurations(Some("compile"))
def commonsIo13 = ModuleID("commons-io", "commons-io", "1.3", Some("compile")) def commonsIo13 = ModuleID("commons-io", "commons-io", "1.3").withConfigurations(Some("compile"))
def commonsIo14 = ModuleID("commons-io", "commons-io", "1.4", Some("compile")) def commonsIo14 = ModuleID("commons-io", "commons-io", "1.4").withConfigurations(Some("compile"))
def commonsIo24 = ModuleID("commons-io", "commons-io", "2.4", Some("compile")) def commonsIo24 = ModuleID("commons-io", "commons-io", "2.4").withConfigurations(Some("compile"))
def bnfparser10 = ModuleID("ca.gobits.bnf", "bnfparser", "1.0", Some("compile")) // uses commons-io 2.4 def bnfparser10 = ModuleID("ca.gobits.bnf", "bnfparser", "1.0").withConfigurations(Some("compile")) // uses commons-io 2.4
def unfilteredUploads080 = ModuleID("net.databinder", "unfiltered-uploads", "0.8.0", Some("compile")) cross CrossVersion.binary // uses commons-io 1.4 def unfilteredUploads080 = ModuleID("net.databinder", "unfiltered-uploads", "0.8.0").withConfigurations(Some("compile")) cross CrossVersion.binary // uses commons-io 1.4
def bananaSesame04 = ModuleID("org.w3", "banana-sesame", "0.4", Some("compile")) cross CrossVersion.binary // uses akka-actor 2.1.4 def bananaSesame04 = ModuleID("org.w3", "banana-sesame", "0.4").withConfigurations(Some("compile")) cross CrossVersion.binary // uses akka-actor 2.1.4
def akkaRemote234 = ModuleID("com.typesafe.akka", "akka-remote", "2.3.4", Some("compile")) cross CrossVersion.binary // uses akka-actor 2.3.4 def akkaRemote234 = ModuleID("com.typesafe.akka", "akka-remote", "2.3.4").withConfigurations(Some("compile")) cross CrossVersion.binary // uses akka-actor 2.3.4
def defaultOptions = EvictionWarningOptions.default def defaultOptions = EvictionWarningOptions.default
import sbt.internal.util.ShowLines._ import sbt.internal.util.ShowLines._
def scalaVersionDeps = Seq(scala2102, akkaActor230) def scalaVersionDeps = Vector(scala2102, akkaActor230)
def scalaVersionWarn1() = { def scalaVersionWarn1() = {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false) val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
@ -113,7 +113,7 @@ class EvictionWarningSpec extends BaseIvySpecification {
EvictionWarning(m, defaultOptions.withWarnScalaVersionEviction(false), report, log).scalaEvictions should have size (0) EvictionWarning(m, defaultOptions.withWarnScalaVersionEviction(false), report, log).scalaEvictions should have size (0)
} }
def javaLibDirectDeps = Seq(commonsIo14, commonsIo24) def javaLibDirectDeps = Vector(commonsIo14, commonsIo24)
def javaLibWarn1() = { def javaLibWarn1() = {
val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3")) val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3"))
@ -151,20 +151,20 @@ class EvictionWarningSpec extends BaseIvySpecification {
} }
def javaLibNoWarn1() = { def javaLibNoWarn1() = {
val deps = Seq(commonsIo14, commonsIo13) val deps = Vector(commonsIo14, commonsIo13)
val m = module(defaultModuleId, deps, Some("2.10.3")) val m = module(defaultModuleId, deps, Some("2.10.3"))
val report = ivyUpdate(m) val report = ivyUpdate(m)
EvictionWarning(m, defaultOptions, report, log).reportedEvictions should have size (0) EvictionWarning(m, defaultOptions, report, log).reportedEvictions should have size (0)
} }
def javaLibNoWarn2() = { def javaLibNoWarn2() = {
val deps = Seq(commonsIo14, commonsIo13) val deps = Vector(commonsIo14, commonsIo13)
val m = module(defaultModuleId, deps, Some("2.10.3")) val m = module(defaultModuleId, deps, Some("2.10.3"))
val report = ivyUpdate(m) val report = ivyUpdate(m)
EvictionWarning(m, defaultOptions, report, log).lines shouldBe Nil EvictionWarning(m, defaultOptions, report, log).lines shouldBe Nil
} }
def javaLibTransitiveDeps = Seq(unfilteredUploads080, bnfparser10) def javaLibTransitiveDeps = Vector(unfilteredUploads080, bnfparser10)
def javaLibTransitiveWarn1() = { def javaLibTransitiveWarn1() = {
val m = module(defaultModuleId, javaLibTransitiveDeps, Some("2.10.3")) val m = module(defaultModuleId, javaLibTransitiveDeps, Some("2.10.3"))
@ -190,14 +190,14 @@ class EvictionWarningSpec extends BaseIvySpecification {
} }
def scalaLibWarn1() = { def scalaLibWarn1() = {
val deps = Seq(scala2104, akkaActor214, akkaActor234) val deps = Vector(scala2104, akkaActor214, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4")) val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m) val report = ivyUpdate(m)
EvictionWarning(m, defaultOptions, report, log).reportedEvictions should have size (1) EvictionWarning(m, defaultOptions, report, log).reportedEvictions should have size (1)
} }
def scalaLibWarn2() = { def scalaLibWarn2() = {
val deps = Seq(scala2104, akkaActor214, akkaActor234) val deps = Vector(scala2104, akkaActor214, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4")) val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m) val report = ivyUpdate(m)
EvictionWarning(m, defaultOptions, report, log).lines shouldBe EvictionWarning(m, defaultOptions, report, log).lines shouldBe
@ -210,20 +210,20 @@ class EvictionWarningSpec extends BaseIvySpecification {
} }
def scalaLibNoWarn1() = { def scalaLibNoWarn1() = {
val deps = Seq(scala2104, akkaActor230, akkaActor234) val deps = Vector(scala2104, akkaActor230, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4")) val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m) val report = ivyUpdate(m)
EvictionWarning(m, defaultOptions, report, log).reportedEvictions should have size (0) EvictionWarning(m, defaultOptions, report, log).reportedEvictions should have size (0)
} }
def scalaLibNoWarn2() = { def scalaLibNoWarn2() = {
val deps = Seq(scala2104, akkaActor230, akkaActor234) val deps = Vector(scala2104, akkaActor230, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4")) val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m) val report = ivyUpdate(m)
EvictionWarning(m, defaultOptions, report, log).lines shouldBe Nil EvictionWarning(m, defaultOptions, report, log).lines shouldBe Nil
} }
def scalaLibTransitiveDeps = Seq(scala2104, bananaSesame04, akkaRemote234) def scalaLibTransitiveDeps = Vector(scala2104, bananaSesame04, akkaRemote234)
def scalaLibTransitiveWarn1() = { def scalaLibTransitiveWarn1() = {
val m = module(defaultModuleId, scalaLibTransitiveDeps, Some("2.10.4")) val m = module(defaultModuleId, scalaLibTransitiveDeps, Some("2.10.4"))

View File

@ -20,7 +20,7 @@ class InconsistentDuplicateSpec extends UnitSpec {
IvySbt.inconsistentDuplicateWarning(Seq(akkaActor230Test, akkaActor230)) shouldBe Nil IvySbt.inconsistentDuplicateWarning(Seq(akkaActor230Test, akkaActor230)) shouldBe Nil
} }
def akkaActor214 = ModuleID("com.typesafe.akka", "akka-actor", "2.1.4", Some("compile")) cross CrossVersion.binary def akkaActor214 = ModuleID("com.typesafe.akka", "akka-actor", "2.1.4").withConfigurations(Some("compile")) cross CrossVersion.binary
def akkaActor230 = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0", Some("compile")) cross CrossVersion.binary def akkaActor230 = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("compile")) cross CrossVersion.binary
def akkaActor230Test = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0", Some("test")) cross CrossVersion.binary def akkaActor230Test = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("test")) cross CrossVersion.binary
} }

View File

@ -8,8 +8,8 @@ import sbt.internal.util.UnitSpec
object ResolverTest extends UnitSpec { object ResolverTest extends UnitSpec {
"Resolver url" should "propagate pattern descriptorOptional and skipConsistencyCheck." in { "Resolver url" should "propagate pattern descriptorOptional and skipConsistencyCheck." in {
val pats = Seq("[orgPath]") val pats = Vector("[orgPath]")
val patsExpected = Seq("http://foo.com/test/[orgPath]") val patsExpected = Vector("http://foo.com/test/[orgPath]")
val patterns = Resolver.url("test", new URL("http://foo.com/test"))(Patterns(pats, pats, isMavenCompatible = false, descriptorOptional = true, skipConsistencyCheck = true)).patterns val patterns = Resolver.url("test", new URL("http://foo.com/test"))(Patterns(pats, pats, isMavenCompatible = false, descriptorOptional = true, skipConsistencyCheck = true)).patterns
patterns.ivyPatterns shouldBe patsExpected patterns.ivyPatterns shouldBe patsExpected

View File

@ -9,10 +9,10 @@ import sbt.librarymanagement.{ ModuleID, RawRepository, Resolver, UpdateReport }
class FakeResolverSpecification extends BaseIvySpecification { class FakeResolverSpecification extends BaseIvySpecification {
import FakeResolver._ import FakeResolver._
val myModule = ModuleID("org.example", "my-module", "0.0.1-SNAPSHOT", Some("compile")) val myModule = ModuleID("org.example", "my-module", "0.0.1-SNAPSHOT").withConfigurations(Some("compile"))
val example = ModuleID("com.example", "example", "1.0.0", Some("compile")) val example = ModuleID("com.example", "example", "1.0.0").withConfigurations(Some("compile"))
val anotherExample = ModuleID("com.example", "another-example", "1.0.0", Some("compile")) val anotherExample = ModuleID("com.example", "another-example", "1.0.0").withConfigurations(Some("compile"))
val nonExisting = ModuleID("com.example", "does-not-exist", "1.2.3", Some("compile")) val nonExisting = ModuleID("com.example", "does-not-exist", "1.2.3").withConfigurations(Some("compile"))
"The FakeResolver" should "find modules with only one artifact" in { "The FakeResolver" should "find modules with only one artifact" in {
val m = getModule(myModule) val m = getModule(myModule)
@ -66,8 +66,8 @@ class FakeResolverSpecification extends BaseIvySpecification {
) )
private def fakeResolver = new FakeResolver("FakeResolver", new File("tmp"), modules) private def fakeResolver = new FakeResolver("FakeResolver", new File("tmp"), modules)
override def resolvers: Seq[Resolver] = Seq(new RawRepository(fakeResolver)) override def resolvers: Vector[Resolver] = Vector(new RawRepository(fakeResolver))
private def getModule(myModule: ModuleID): IvySbt#Module = module(defaultModuleId, Seq(myModule), None) private def getModule(myModule: ModuleID): IvySbt#Module = module(defaultModuleId, Vector(myModule), None)
private def getAllFiles(report: UpdateReport) = private def getAllFiles(report: UpdateReport) =
for { for {
conf <- report.configurations conf <- report.configurations
@ -75,4 +75,4 @@ class FakeResolverSpecification extends BaseIvySpecification {
(_, f) <- m.artifacts (_, f) <- m.artifacts
} yield f } yield f
} }

View File

@ -6,7 +6,7 @@ import sbt.librarymanagement._
class IvyRepoSpec extends BaseIvySpecification with DependencyBuilders { class IvyRepoSpec extends BaseIvySpecification with DependencyBuilders {
val ourModuleID = ModuleID("com.example", "foo", "0.1.0", Some("compile")) val ourModuleID = ModuleID("com.example", "foo", "0.1.0").withConfigurations(Some("compile"))
def makeModuleForDepWithSources = { def makeModuleForDepWithSources = {
// By default a module seems to only have [compile, test, runtime], yet deps automatically map to // By default a module seems to only have [compile, test, runtime], yet deps automatically map to
@ -15,7 +15,7 @@ class IvyRepoSpec extends BaseIvySpecification with DependencyBuilders {
module( module(
ourModuleID, ourModuleID,
Seq(dep), None //, UpdateOptions().withCachedResolution(true) Vector(dep), None //, UpdateOptions().withCachedResolution(true)
) )
} }
@ -50,7 +50,7 @@ class IvyRepoSpec extends BaseIvySpecification with DependencyBuilders {
val docTypes = Set("javadoc") val docTypes = Set("javadoc")
// These will be the default classifiers that SBT should try, in case a dependency is Maven. // These will be the default classifiers that SBT should try, in case a dependency is Maven.
// In this case though, they will be tried and should fail gracefully - only the // In this case though, they will be tried and should fail gracefully - only the
val attemptedClassifiers = Seq("sources", "javadoc") val attemptedClassifiers = Vector("sources", "javadoc")
// The dep that we want to get the "classifiers" (i.e. sources / docs) for. // The dep that we want to get the "classifiers" (i.e. sources / docs) for.
// We know it has only one source artifact in the "compile" configuration. // We know it has only one source artifact in the "compile" configuration.
@ -59,12 +59,12 @@ class IvyRepoSpec extends BaseIvySpecification with DependencyBuilders {
val clMod = { val clMod = {
import language.implicitConversions import language.implicitConversions
implicit val key = (m: ModuleID) => (m.organization, m.name, m.revision) implicit val key = (m: ModuleID) => (m.organization, m.name, m.revision)
val externalModules = Seq(dep) val externalModules = Vector(dep)
// Note: need to extract ourModuleID so we can plug it in here, can't fish it back out of the IvySbt#Module (`m`) // Note: need to extract ourModuleID so we can plug it in here, can't fish it back out of the IvySbt#Module (`m`)
GetClassifiersModule(ourModuleID, externalModules, Seq(Configurations.Compile), attemptedClassifiers) GetClassifiersModule(ourModuleID, externalModules, Vector(Configurations.Compile), attemptedClassifiers)
} }
val gcm = GetClassifiersConfiguration(clMod, Map.empty, c.copy(artifactFilter = c.artifactFilter.invert), ivyScala, srcTypes, docTypes) val gcm = GetClassifiersConfiguration(clMod, Map.empty, c.withArtifactFilter(c.artifactFilter.invert), ivyScala, srcTypes, docTypes)
val report2 = IvyActions.updateClassifiers(m.owner, gcm, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, Vector(), log) val report2 = IvyActions.updateClassifiers(m.owner, gcm, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, Vector(), log)
@ -80,7 +80,7 @@ class IvyRepoSpec extends BaseIvySpecification with DependencyBuilders {
} }
} }
override lazy val resolvers: Seq[Resolver] = Seq(testIvy) override lazy val resolvers: Vector[Resolver] = Vector(testIvy)
lazy val testIvy = { lazy val testIvy = {
val repoUrl = getClass.getResource("/test-ivy-repo") val repoUrl = getClass.getResource("/test-ivy-repo")

View File

@ -0,0 +1,61 @@
import sbt.datatype.{ CodecCodeGen, TpeRef }
object DatatypeConfig {
/** Extract the only type parameter from a TpeRef */
def oneArg(tpe: TpeRef): TpeRef = {
val pat = s"""${CodecCodeGen.removeTypeParameters(tpe.name)}[<\\[](.+?)[>\\]]""".r
val pat(arg0) = tpe.name
TpeRef(arg0, false, false, false)
}
/** Extract the two type parameters from a TpeRef */
def twoArgs(tpe: TpeRef): List[TpeRef] = {
val pat = s"""${CodecCodeGen.removeTypeParameters(tpe.name)}[<\\[](.+?), (.+?)[>\\]]""".r
val pat(arg0, arg1) = tpe.name
TpeRef(arg0, false, false, false) :: TpeRef(arg1, false, false, false) :: Nil
}
/** Codecs that were manually written. */
val myCodecs: PartialFunction[String, TpeRef => List[String]] = {
case "java.util.Date" => { _ => "sbt.internal.librarymanagement.formats.DateFormat" :: Nil }
case "Function1" =>
{ tpe => "sbt.internal.librarymanagement.formats.Function1Format" :: twoArgs(tpe).flatMap(getFormats) }
case "scala.xml.NodeSeq" => { _ => "sbt.internal.librarymanagement.formats.NodeSeqFormat" :: Nil }
case "org.apache.ivy.plugins.resolver.DependencyResolver" =>
{ _ => "sbt.internal.librarymanagement.formats.DependencyResolverFormat" :: Nil }
case "xsbti.GlobalLock" => { _ => "sbt.internal.librarymanagement.formats.GlobalLockFormat" :: Nil }
case "xsbti.Logger" => { _ => "sbt.internal.librarymanagement.formats.LoggerFormat" :: Nil }
case "sbt.librarymanagement.UpdateOptions" =>
{ _ => "sbt.internal.librarymanagement.formats.UpdateOptionsFormat" :: Nil }
// TODO: These are handled by BasicJsonProtocol, and sbt-datatype should handle them by default, imo
case "Option" | "Set" => { tpe => getFormats(oneArg(tpe)) }
case "Map" | "Tuple2" | "scala.Tuple2" => { tpe => twoArgs(tpe).flatMap(getFormats) }
case "Int" | "Long" => { _ => Nil }
}
/** Types for which we don't include the format -- they're just aliases to InclExclRule */
val excluded = Set(
"sbt.librarymanagement.InclusionRule",
"sbt.librarymanagement.ExclusionRule")
/** Returns the list of formats required to encode the given `TpeRef`. */
val getFormats: TpeRef => List[String] =
CodecCodeGen.extensibleFormatsForType {
case TpeRef("sbt.internal.librarymanagement.RetrieveConfiguration", false, false, false) =>
"sbt.librarymanagement.RetrieveConfigurationFormats" :: Nil
case tpe @ TpeRef(name, _, _, _) if myCodecs isDefinedAt CodecCodeGen.removeTypeParameters(name) =>
myCodecs(CodecCodeGen.removeTypeParameters(name))(tpe)
case TpeRef(name, _, _, _) if excluded contains CodecCodeGen.removeTypeParameters(name) =>
Nil
case other =>
CodecCodeGen.formatsForType(other)
}
}

View File

@ -5,7 +5,7 @@ object Dependencies {
lazy val scala211 = "2.11.8" lazy val scala211 = "2.11.8"
val ioVersion = "1.0.0-M6" val ioVersion = "1.0.0-M6"
val utilVersion = "0.1.0-M13" val utilVersion = "0.1.0-M15"
private lazy val sbtIO = "org.scala-sbt" %% "io" % ioVersion private lazy val sbtIO = "org.scala-sbt" %% "io" % ioVersion
@ -43,6 +43,16 @@ object Dependencies {
lazy val launcherInterface = "org.scala-sbt" % "launcher-interface" % "1.0.0" lazy val launcherInterface = "org.scala-sbt" % "launcher-interface" % "1.0.0"
lazy val ivy = "org.scala-sbt.ivy" % "ivy" % "2.3.0-sbt-2cc8d2761242b072cedb0a04cb39435c4fa24f9a" lazy val ivy = "org.scala-sbt.ivy" % "ivy" % "2.3.0-sbt-2cc8d2761242b072cedb0a04cb39435c4fa24f9a"
lazy val jsch = "com.jcraft" % "jsch" % "0.1.46" intransitive () lazy val jsch = "com.jcraft" % "jsch" % "0.1.46" intransitive ()
lazy val sbtSerialization = "org.scala-sbt" %% "serialization" % "0.1.2"
lazy val scalaReflect = Def.setting { "org.scala-lang" % "scala-reflect" % scalaVersion.value } lazy val scalaReflect = Def.setting { "org.scala-lang" % "scala-reflect" % scalaVersion.value }
lazy val scalaXml = scala211Module("scala-xml", "1.0.5")
lazy val sjsonnewVersion = "0.4.1"
lazy val sjsonnewScalaJson = "com.eed3si9n" %% "sjson-new-scalajson" % sjsonnewVersion
private def scala211Module(name: String, moduleVersion: String) =
Def.setting {
scalaVersion.value match {
case sv if (sv startsWith "2.9.") || (sv startsWith "2.10.") => Nil
case _ => ("org.scala-lang.modules" %% name % moduleVersion) :: Nil
}
}
} }

View File

@ -1 +1 @@
sbt.version=0.13.9 sbt.version=0.13.13

1
project/sbt-datatype.sbt Normal file
View File

@ -0,0 +1 @@
addSbtPlugin("org.scala-sbt" % "sbt-datatype" % "0.2.8")