Merge pull request #58 from dwijnand/contraband

Switch to sbt-datatype, sjson-new & Vectors
This commit is contained in:
eugene yokota 2016-11-16 10:36:56 -05:00 committed by GitHub
commit e90b167b4e
46 changed files with 1339 additions and 1098 deletions

View File

@ -17,7 +17,6 @@ def commonSettings: Seq[Setting[_]] = Seq(
crossScalaVersions := Seq(scala211),
resolvers += Resolver.sonatypeRepo("public"),
scalacOptions += "-Ywarn-unused",
scalacOptions += "-Ywarn-unused-import",
previousArtifact := None, // Some(organization.value %% moduleName.value % "1.0.0"),
publishArtifact in Compile := true,
publishArtifact in Test := false
@ -47,11 +46,14 @@ lazy val lm = (project in file("librarymanagement")).
commonSettings,
name := "librarymanagement",
libraryDependencies ++= Seq(
ivy, jsch, sbtSerialization, scalaReflect.value, launcherInterface),
resourceGenerators in Compile <+= (version, resourceManaged, streams, compile in Compile) map Util.generateVersionFile,
binaryIssueFilters ++= Seq()
ivy, jsch, scalaReflect.value, launcherInterface, sjsonnewScalaJson % Optional),
libraryDependencies ++= scalaXml.value,
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(
commands += Command.command("release") { state =>

View File

@ -0,0 +1,775 @@
{
"codecNamespace": "sbt.librarymanagement",
"fullCodec": "LibraryManagementCodec",
"types": [
{
"name": "Artifact",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"parents": "sbt.librarymanagement.ArtifactExtra",
"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.ArtifactFunctions"
},
{
"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.ArtifactTypeFilterExtra",
"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.ArtifactTypeFilterFunctions"
},
{
"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": "Configuration",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": "Represents an Ivy configuration.",
"parents": "sbt.librarymanagement.ConfigurationExtra",
"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": "ConfigurationReport",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"doc": [
"Provides information about resolution of a single configuration."
],
"parents": "sbt.librarymanagement.ConfigurationReportExtra",
"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." ]
}
]
},
{
"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.ConflictManagerFunctions"
},
{
"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"
},
{
"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\"."
]
}
],
"parentsCompanion": "sbt.librarymanagement.CrossVersionFunctions"
},
{
"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": "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": "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.InclExclRuleFunctions"
},
{
"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.IvyScalaFunctions"
},
{
"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": "ModuleID",
"namespace": "sbt.librarymanagement",
"target": "Scala",
"type": "record",
"parents": "sbt.librarymanagement.ModuleIDExtra",
"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.ModuleIDFunctions"
},
{
"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": "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.ModuleReportExtra",
"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": "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.InlineConfigurationFunctions"
}
]
},
{
"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": "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.PatternsFunctions"
},
{
"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.ResolverFunctions"
},
{
"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": "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": "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": "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": "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.UpdateReportExtra",
"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": "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": "ConfigurationReportLite",
"namespace": "sbt.internal.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "configuration", "type": "String" },
{ "name": "details", "type": "sbt.librarymanagement.OrganizationArtifactReport*" }
]
},
{
"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": "IvyPaths",
"namespace": "sbt.internal.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "baseDirectory", "type": "java.io.File" },
{ "name": "ivyHome", "type": "java.io.File?" }
]
},
{
"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": "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": "UpdateReportLite",
"namespace": "sbt.internal.librarymanagement",
"target": "Scala",
"type": "record",
"fields": [
{ "name": "configurations", "type": "sbt.internal.librarymanagement.ConfigurationReportLite*" }
]
}
]
}

View File

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

View File

@ -30,8 +30,9 @@ import sbt.util.Logger
import sbt.librarymanagement._
import Resolver.PluginPattern
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
/*
@ -92,7 +93,8 @@ final class IvySbt(val configuration: IvyConfiguration) {
setEventManager(new EventManager())
if (configuration.updateOptions.cachedResolution) {
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
def makeInstance = mkIvy
})
@ -139,7 +141,7 @@ final class IvySbt(val configuration: IvyConfiguration) {
withIvy(log) { i =>
val prOpt = Option(i.getSettings.getResolver(ProjectResolver.InterProject)) map { case pr: ProjectResolver => pr }
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 DefaultIvyFilename = "ivy.xml"
val DefaultMavenFilename = "pom.xml"
val DefaultChecksums = Seq("sha1", "md5")
private[sbt] val cachedResolutionResolveCache: CachedResolutionResolveCache = new CachedResolutionResolveCache()
val DefaultChecksums = Vector("sha1", "md5")
private[sbt] def cachedResolutionResolveCache(fileToStore: File => CacheStore): CachedResolutionResolveCache = new CachedResolutionResolveCache(fileToStore)
def defaultIvyFile(project: File) = new File(project, DefaultIvyFilename)
def defaultIvyConfiguration(project: File) = new File(project, DefaultIvyConfigFilename)
@ -305,8 +307,8 @@ private[sbt] object IvySbt {
*/
def hasImplicitClassifier(artifact: IArtifact): Boolean =
{
import collection.JavaConversions._
artifact.getQualifiedExtraAttributes.keys.exists(_.asInstanceOf[String] startsWith "m:")
import scala.collection.JavaConverters._
artifact.getQualifiedExtraAttributes.asScala.keys.exists(_.asInstanceOf[String] startsWith "m:")
}
private def setModuleConfigurations(settings: IvySettings, moduleConfigurations: Seq[ModuleConfiguration], log: Logger): Unit = {
val existing = settings.getResolverNames
@ -426,7 +428,7 @@ private[sbt] object IvySbt {
{
val sub = CrossVersion(scalaFullVersion, scalaBinaryVersion)
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
}
}
@ -439,7 +441,7 @@ private[sbt] object IvySbt {
}
def getExtraAttributes(revID: ExtendableItem): Map[String, String] =
{
import collection.JavaConverters._
import scala.collection.JavaConverters._
revID.getExtraAttributes.asInstanceOf[java.util.Map[String, String]].asScala.toMap
}
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) =
{
import scala.collection.JavaConverters._
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. */
@ -514,7 +517,7 @@ private[sbt] object IvySbt {
val dds = moduleID.getDependencies
val deps = dds flatMap { dd =>
val module = toModuleID(dd.getDependencyRevisionId)
dd.getModuleConfigurations map (c => module.copy(configurations = Some(c)))
dd.getModuleConfigurations map (c => module.withConfigurations(Some(c)))
}
inconsistentDuplicateWarning(deps)
}
@ -571,7 +574,7 @@ private[sbt] object IvySbt {
deps.put(id, updated)
}
import collection.JavaConverters._
import scala.collection.JavaConverters._
deps.values.asScala.toSeq.flatMap { dds =>
val mergeable = (dds, dds.tail).zipped.forall(ivyint.MergeDescriptors.mergeable _)
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
dependencies map { dep =>
overridden get key(dep) match {
case Some(rev) => dep.copy(revision = rev)
case Some(rev) => dep.withRevision(rev)
case None => dep
}
}

View File

@ -21,36 +21,19 @@ import sbt.util.Logger
import sbt.internal.util.{ ShowLines, SourcePosition, LinePosition, RangePosition, LineRange }
import sbt.librarymanagement._
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 PublishConfiguration(val ivyFile: Option[File], val resolverName: String, val artifacts: Map[Artifact, File], val checksums: Seq[String], 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: Vector[String], val logging: UpdateLogging,
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)
}
final class UpdateConfiguration(val retrieve: Option[RetrieveConfiguration], val missingOk: Boolean, val logging: UpdateLogging.Value, val artifactFilter: ArtifactTypeFilter) {
@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))
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))
/** @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 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] (
val modulePositions: Map[ModuleID, SourcePosition]
@ -61,17 +44,6 @@ object UnresolvedWarningConfiguration {
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 {
/** 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 = {
@ -133,13 +105,13 @@ object IvyActions {
if (resolver eq null) sys.error("Undefined resolver '" + resolverName + "'")
val ivyArtifact = ivyFile map { file => (MDArtifact.newIvyArtifact(md), file) }
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) }
}
}
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 }
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
resolver.setChecksums(checksums mkString ",")
@ -151,9 +123,9 @@ object IvyActions {
case i: InlineConfiguration => CrossVersion(i.module, i.ivyScala)
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 zipped = rawa zip IvySbt.mapArtifacts(module, seqa)
zipped map { case (a, ivyA) => (ivyA, artifacts(a)) }
@ -235,8 +207,8 @@ object IvyActions {
{
import config.{ configuration => c, ivyScala, module => mod }
import mod.{ id, modules => deps }
val base = restrictedCopy(id, true).copy(name = id.name + "$" + label)
val module = new ivySbt.Module(InlineConfiguration(base, ModuleInfo(base.name), deps).copy(ivyScala = ivyScala))
val base = restrictedCopy(id, true).withName(id.name + "$" + label)
val module = new ivySbt.Module(InlineConfiguration(false, ivyScala, base, ModuleInfo(base.name), deps))
val report = updateEither(module, c, uwconfig, logicalClock, depDir, log) match {
case Right(r) => r
case Left(w) =>
@ -270,10 +242,10 @@ object IvyActions {
val baseModules = modules map { m => restrictedCopy(m, true) }
// Adding list of explicit artifacts here.
val deps = baseModules.distinct flatMap classifiedArtifacts(classifiers, exclude, artifacts)
val base = restrictedCopy(id, true).copy(name = id.name + classifiers.mkString("$", "_", ""))
val module = new ivySbt.Module(InlineConfiguration(base, ModuleInfo(base.name), deps).copy(ivyScala = ivyScala, configurations = confs))
val base = restrictedCopy(id, true).withName(id.name + classifiers.mkString("$", "_", ""))
val module = new ivySbt.Module(InlineConfiguration(false, ivyScala, base, ModuleInfo(base.name), deps).withConfigurations(confs))
// 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 {
case Right(r) =>
// 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 {
case (art, f) =>
// 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) =>
@ -294,7 +266,7 @@ object IvyActions {
}
// This version adds explicit artifact
private[sbt] def classifiedArtifacts(
classifiers: Seq[String],
classifiers: Vector[String],
exclude: Map[ModuleID, Set[String]],
artifacts: Vector[(String, ModuleID, Artifact, File)]
)(m: ModuleID): Option[ModuleID] = {
@ -308,7 +280,7 @@ object IvyActions {
def hardcodedArtifacts = classifiedArtifacts(classifiers, exclude)(m)
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 included = classifiers filterNot excluded
@ -330,12 +302,12 @@ object IvyActions {
* }}}
* `usage.getDependencyIncludesSet` returns null if there are no (explicit) include rules.
*/
private def intransitiveModuleWithExplicitArts(module: ModuleID, arts: Seq[Artifact]): ModuleID =
module.copy(isTransitive = false, explicitArtifacts = arts, inclusions = InclExclRule.everything :: Nil)
private def intransitiveModuleWithExplicitArts(module: ModuleID, arts: Vector[Artifact]): ModuleID =
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)) }
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) }
private[this] def getExcluded(id: ModuleID, exclude: Map[ModuleID, Set[String]]): Set[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) }
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)
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 resolveId = ResolveOptions.getDefaultResolveId(module)
@ -420,7 +392,7 @@ object IvyActions {
import UpdateLogging.{ Quiet, Full, DownloadOnly, Default }
import LogOptions.{ LOG_QUIET, LOG_DEFAULT, LOG_DOWNLOAD_ONLY }
private def ivyLogLevel(level: UpdateLogging.Value) =
private def ivyLogLevel(level: UpdateLogging) =
level match {
case Quiet => LOG_QUIET
case DownloadOnly => LOG_DOWNLOAD_ONLY

View File

@ -15,6 +15,14 @@ import sbt.io.Path
import sbt.util.Logger
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)
extends RuntimeException(NotInCache(id, cause), cause) {
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.*/
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")
/** 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 = {
@ -81,8 +91,8 @@ class IvyCache(val ivyHome: Option[File]) {
{
val local = Resolver.defaultLocal
val paths = new IvyPaths(new File("."), ivyHome)
val conf = new InlineIvyConfiguration(paths, Seq(local), Nil, Nil, false, lock, IvySbt.DefaultChecksums, None, UpdateOptions(), log)
(new IvySbt(conf), local)
val conf = new InlineIvyConfiguration(paths, Vector(local), Vector.empty, Vector.empty, false, lock, IvySbt.DefaultChecksums, None, UpdateOptions(), log)
(new IvySbt(conf, fileToStore), local)
}
/** Creates a default jar artifact based on the given ID.*/
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)
}
}
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
import java.io.File
import java.net.URI
import scala.xml.NodeSeq
import sbt.util.Logger
import sbt.librarymanagement._
final class IvyPaths(val baseDirectory: File, val ivyHome: Option[File]) {
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)
abstract class InlineConfigurationFunctions {
def configurations(explicitConfigurations: Iterable[Configuration], defaultConfiguration: Option[Configuration]) =
if (explicitConfigurations.isEmpty) {
defaultConfiguration match {

View File

@ -17,10 +17,10 @@ import sbt.librarymanagement._
import sbt.internal.librarymanagement.syntax._
object IvyRetrieve {
def reports(report: ResolveReport): Seq[ConfigurationResolveReport] =
report.getConfigurations map report.getConfigurationReport
def reports(report: ResolveReport): Vector[ConfigurationResolveReport] =
report.getConfigurations.toVector map report.getConfigurationReport
def moduleReports(confReport: ConfigurationResolveReport): Seq[ModuleReport] =
def moduleReports(confReport: ConfigurationResolveReport): Vector[ModuleReport] =
for {
revId <- confReport.getModuleRevisionIds.toArray.toVector collect { case revId: ModuleRevisionId => revId }
} yield moduleRevisionDetail(confReport, confReport.getDependency(revId))
@ -32,7 +32,7 @@ object IvyRetrieve {
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 resolved = new mutable.ListBuffer[(Artifact, File)]
@ -44,13 +44,13 @@ object IvyRetrieve {
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
// only the revolved modules.
// 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 }
def organizationArtifact(mid: IvyModuleId): OrganizationArtifactReport = {
val deps = confReport.getNodes(mid).toArray.toVector collect { case node: IvyNode => node }
@ -130,14 +130,14 @@ object IvyRetrieve {
case _ => dep.getResolvedId.getExtraAttributes
})
val isDefault = Option(dep.getDescriptor) map { _.isDefault }
val configurations = dep.getConfigurations(confReport.getConfiguration).toList
val licenses: Seq[(String, Option[String])] = mdOpt match {
val configurations = dep.getConfigurations(confReport.getConfiguration).toVector
val licenses: Vector[(String, Option[String])] = mdOpt match {
case Some(md) => md.getLicenses.toVector collect {
case lic: IvyLicense if Option(lic.getName).isDefined =>
val temporaryURL = "http://localhost"
(lic.getName, nonEmptyString(lic.getUrl) orElse { Some(temporaryURL) })
}
case _ => Nil
case _ => Vector.empty
}
val callers = dep.getCallers(confReport.getConfiguration).toVector map { toCaller }
val (resolved, missing) = artifacts(moduleId, confReport getDownloadReports revId)
@ -151,13 +151,13 @@ object IvyRetrieve {
confReport.getEvictedNodes.map(node => toModuleID(node.getId))
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))
def toArtifact(art: IvyArtifact): Artifact =
{
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 =

View File

@ -3,18 +3,22 @@ package sbt.internal.librarymanagement
import java.io.File
import org.apache.ivy.core
import core.module.descriptor.ModuleDescriptor
import sbt.serialization._
import sbt.util.Logger
import sbt.internal.util.CacheStore
import sbt.librarymanagement._
import sbt.librarymanagement.LibraryManagementCodec._
import JsonUtil._
private[sbt] object JsonUtil {
def sbtOrgTemp = "org.scala-sbt.temp"
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 =
{
try {
val lite = fromJsonFile[UpdateReportLite](path).get
val lite = fileToStore(path).read[UpdateReportLite]
fromLite(lite, cachedDescriptor)
} catch {
case e: Throwable =>
@ -25,7 +29,7 @@ private[sbt] object JsonUtil {
def writeUpdateReport(ur: UpdateReport, graphPath: File): Unit =
{
sbt.io.IO.createDirectory(graphPath.getParentFile)
toJsonFile(toLite(ur), graphPath)
fileToStore(graphPath).write(toLite(ur))
}
def toLite(ur: UpdateReport): UpdateReportLite =
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,
// 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
else {
val nonArtificial = callers filter { c =>
@ -53,8 +57,8 @@ private[sbt] object JsonUtil {
}
val interProj = (callers find { c =>
c.caller.organization == sbtOrgTemp
}).toList
interProj ::: nonArtificial.toList
}).toVector
interProj ++ nonArtificial
}
def fromLite(lite: UpdateReportLite, cachedDescriptor: File): UpdateReport =
@ -72,13 +76,3 @@ private[sbt] object JsonUtil {
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.*/
private[sbt] def filter(f: DependencyFilter): UpdateReport =
moduleReportMap { (configuration, modReport) =>
modReport.copy(
artifacts = modReport.artifacts filter { case (art, file) => f(configuration, modReport.module, art) },
missingArtifacts = modReport.missingArtifacts filter { art => f(configuration, modReport.module, art) }
)
modReport
.withArtifacts(modReport.artifacts filter { case (art, file) => 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) =>
val newArtifacts = f(configuration, modReport.module, modReport.artifacts)
modReport.copy(
artifacts = newArtifacts,
missingArtifacts = modReport.missingArtifacts
)
modReport
.withArtifacts(newArtifacts)
.withMissingArtifacts(modReport.missingArtifacts)
}
def toSeq: Seq[(String, ModuleID, Artifact, File)] =
@ -57,9 +55,8 @@ final class RichUpdateReport(report: UpdateReport) {
def addMissing(f: ModuleID => Seq[Artifact]): UpdateReport =
moduleReportMap { (configuration, modReport) =>
modReport.copy(
missingArtifacts = (modReport.missingArtifacts ++ f(modReport.module)).distinct
)
modReport
.withMissingArtifacts((modReport.missingArtifacts ++ f(modReport.module)).distinct)
}
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,8 @@
package sbt.internal.librarymanagement.formats
import sjsonnew._
import org.apache.ivy.plugins.resolver.DependencyResolver
trait DependencyResolverFormat { self: BasicJsonProtocol =>
implicit lazy val DependencyResolverFormat: JsonFormat[DependencyResolver] = ???
}

View File

@ -0,0 +1,8 @@
package sbt.internal.librarymanagement.formats
import sjsonnew._
import xsbti._
trait GlobalLockFormat { self: BasicJsonProtocol =>
implicit lazy val GlobalLockFormat: JsonFormat[GlobalLock] = ???
}

View File

@ -0,0 +1,8 @@
package sbt.internal.librarymanagement.formats
import sjsonnew._
import xsbti._
trait LoggerFormat { self: BasicJsonProtocol =>
implicit lazy val LoggerFormat: JsonFormat[Logger] = ???
}

View File

@ -0,0 +1,8 @@
package sbt.internal.librarymanagement.formats
import sjsonnew._
import scala.xml._
trait NodeSeqFormat { self: BasicJsonProtocol =>
implicit lazy val NodeSeqFormat: JsonFormat[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) {
def %(artifactID: String) = groupArtifact(artifactID, CrossVersion.Disabled)
def %(artifactID: String) = groupArtifact(artifactID, Disabled())
def %%(artifactID: String): GroupArtifactID = groupArtifact(artifactID, CrossVersion.binary)
private def groupArtifact(artifactID: String, cross: CrossVersion) =
@ -53,7 +53,7 @@ final class ModuleIDConfigurable private[sbt] (moduleID: ModuleID) {
{
nonEmpty(configurations, "Configurations")
val c = configurations
moduleID.copy(configurations = Some(c))
moduleID.withConfigurations(configurations = Some(c))
}
}
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.librarymanagement._
import sbt.internal.librarymanagement.syntax._
import sbt.internal.util.CacheStore
private[sbt] object CachedResolutionResolveCache {
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")
}
private[sbt] class CachedResolutionResolveCache() {
private[sbt] class CachedResolutionResolveCache(fileToStore: File => CacheStore) {
import CachedResolutionResolveCache._
val jsonUtil = new JsonUtil(fileToStore)
val updateReportCache: concurrent.Map[ModuleRevisionId, Either[ResolveException, UpdateReport]] = concurrent.TrieMap()
// Used for subproject
val projectReportCache: concurrent.Map[(ModuleRevisionId, LogicalClock), Either[ResolveException, UpdateReport]] = concurrent.TrieMap()
@ -164,7 +166,7 @@ private[sbt] class CachedResolutionResolveCache() {
else None) match {
case Some(path) =>
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 }) {
updateReportCache(md.getModuleRevisionId) = Right(ur)
Some(Right(ur))
@ -198,7 +200,7 @@ private[sbt] class CachedResolutionResolveCache() {
if (changing) {
cleanDynamicGraph()
}
JsonUtil.writeUpdateReport(ur, gp)
jsonUtil.writeUpdateReport(ur, gp)
// limit the update cache size
if (updateReportCache.size > maxUpdateReportCacheSize) {
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]) = {
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 {
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] 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 =
withIvy(new IvyLoggerInterface(log))(f)
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
else
// https://github.com/sbt/sbt/issues/1763
Some(mr.copy(callers = JsonUtil.filterOutArtificialCallers(mr.callers)))
Some(mr.withCallers(jsonUtil.filterOutArtificialCallers(mr.callers)))
} match {
case Vector() => None
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
else {
log.debug(s":: $rootModuleConf: removing caller $moduleWithMostCallers -> $next for sorting")
mr.copy(callers = callers)
mr.withCallers(callers)
}
}
OrganizationArtifactReport(oar.organization, oar.name, mrs)
@ -591,18 +596,18 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
* Merges ModuleReports, which represents orgnization, name, and version.
* 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) {
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 allCallers = xs flatMap { _.callers }
// 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
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 {
case ((org, name, version), xs) =>
@ -637,7 +642,7 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
}
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
else new OrganizationArtifactReport(organization, name, unaffected ++ newlyEvicted)
}
@ -669,7 +674,7 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
}) match {
case Some(m) =>
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 =>
(conflicts find { m =>
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.
case Some(m) if !ignoreTransitiveForce =>
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 _ =>
val strategy = lcm.getStrategy
val infos = conflicts map { ModuleReportArtifactInfo(_) }
Option(strategy.findLatest(infos.toArray, None.orNull)) match {
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)
}
}
@ -696,7 +701,7 @@ private[sbt] trait CachedResolutionResolveEngine extends ResolveEngine {
mr.module.revision == ovrVersion
} match {
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 =>
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.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 ArtifactExtra {
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))
}
import Configurations.{ Optional, Pom, Test }
object Artifact {
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, Nil, None, extra)
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, Nil, 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, Nil, Some(url))
def apply(name: String, `type`: String, extension: String, classifier: Option[String], configurations: Iterable[Configuration], url: Option[URL]): Artifact =
abstract class ArtifactFunctions {
def apply(name: String, extra: Map[String, String]): Artifact = Artifact(name, DefaultType, DefaultExtension, None, Vector.empty, None, extra)
def apply(name: String, classifier: String): Artifact = Artifact(name, DefaultType, DefaultExtension, Some(classifier), Vector.empty, 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, classifier: String): Artifact = Artifact(name, `type`, extension, Some(classifier), Vector.empty, 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, `type`: String, extension: String, classifier: Option[String], configurations: Vector[Configuration], url: Option[URL]): Artifact =
Artifact(name, `type`, extension, classifier, configurations, url, Map.empty)
val DefaultExtension = "jar"
@ -28,7 +45,7 @@ object Artifact {
def sources(name: String) = classified(name, SourceClassifier)
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
val DefaultSourceTypes = Set("src", "source", "sources")
@ -62,7 +79,7 @@ object Artifact {
val name = file.getName
val i = name.lastIndexOf('.')
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 =
{
@ -88,75 +105,5 @@ object Artifact {
* The artifact is created under the default configuration.
*/
def classified(name: String, classifier: String): Artifact =
Artifact(name, classifierType(classifier), DefaultExtension, Some(classifier), Nil, 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
}
}
Artifact(name, classifierType(classifier), DefaultExtension, Some(classifier), Vector.empty, None)
}

View File

@ -3,8 +3,6 @@
*/
package sbt.librarymanagement
import sbt.serialization._
object Configurations {
def config(name: String) = new Configuration(name)
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 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 ConfigurationExtra {
def name: String
def description: String
def isPublic: Boolean
def extendsConfigs: Vector[Configuration]
def transitive: Boolean
require(name != null && !name.isEmpty)
require(description != null)
def this(name: String) = this(name, "", true, Nil, true)
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 intransitive = Configuration(name, description, isPublic, extendsConfigs, false)
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,109 +1,22 @@
package sbt.librarymanagement
import sbt.serialization._
import sbt.internal.librarymanagement.SbtExclusionRule
import sbt.internal.librarymanagement.cross.CrossVersionUtil
final case class ScalaVersion(full: String, binary: String)
/** Configures how a module will be cross-versioned. */
sealed trait CrossVersion
object CrossVersion {
abstract class CrossVersionFunctions {
/** 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
/** 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
/** 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). */
def full: CrossVersion = new Full(idStringFun)
/**
* Cross-versions a module with the result of applying `remapVersion` to the full version
* (typically the full Scala version). See also [[sbt.librarymanagement.CrossVersion.Full]].
*/
def fullMapped(remapVersion: String => String): CrossVersion = new Full(remapVersion)
def full: CrossVersion = new Full()
/** Cross-versions a module with the binary version (typically the binary Scala version). */
def binary: CrossVersion = new Binary(idStringFun)
/**
* Cross-versions a module with the result of applying `remapVersion` to the binary version
* (typically the binary Scala version). See also [[sbt.librarymanagement.CrossVersion.Binary]].
*/
def binaryMapped(remapVersion: String => String): CrossVersion = new Binary(remapVersion)
private[this] def idFun[T]: T => T = x => x
private[this] val idStringFun = idFun[String]
def binary: CrossVersion = new Binary()
private[sbt] def append(s: String): Option[String => String] = Some(x => crossName(x, s))
@ -114,9 +27,9 @@ object CrossVersion {
*/
def apply(cross: CrossVersion, fullVersion: String, binaryVersion: String): Option[String => String] =
cross match {
case Disabled => None
case b: Binary => append(b.remapVersion(binaryVersion))
case f: Full => append(f.remapVersion(fullVersion))
case _: Disabled => None
case _: Binary => append(binaryVersion)
case _: Full => append(fullVersion)
}
/** Constructs the cross-version function defined by `module` and `is`, if one is configured. */
@ -128,7 +41,7 @@ object CrossVersion {
is flatMap { i => apply(module, i) }
/** 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 {
case None => artifacts
case Some(is) => substituteCrossA(artifacts, cross)
@ -147,14 +60,14 @@ object CrossVersion {
private[sbt] def substituteCross(exclude: SbtExclusionRule, is: Option[IvyScala]): SbtExclusionRule = {
val fopt: Option[String => String] =
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`. */
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))
/**
@ -166,7 +79,7 @@ object CrossVersion {
{
val cross = apply(m.crossVersion, scalaFullVersion, scalaBinaryVersion)
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
m
}

View File

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

View File

@ -3,54 +3,24 @@
*/
package sbt.librarymanagement
import java.net.URL
import org.apache.ivy.core.module.descriptor
import org.apache.ivy.util.filter.{ Filter => IvyFilter }
import sbt.serialization._
/** Additional information about a project module */
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 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)
abstract class InclExclRuleFunctions {
def everything = new InclExclRule("*", "*", "*", Vector.empty)
}
/** Basic SCM information for a project module */
final case class ScmInfo(browseUrl: URL, connection: String, devConnection: Option[String] = None)
abstract class ArtifactTypeFilterExtra {
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 apply(a: descriptor.Artifact): Boolean = (types contains a.getType) ^ inverted
}
object ArtifactTypeFilter {
abstract class ArtifactTypeFilterFunctions {
def allow(types: Set[String]) = ArtifactTypeFilter(types, false)
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)
object ModuleConfiguration {
def apply(org: String, resolver: Resolver): ModuleConfiguration = apply(org, "*", "*", resolver)
def apply(org: String, name: String, resolver: Resolver): ModuleConfiguration = ModuleConfiguration(org, name, "*", resolver)
}
abstract class ConflictManagerFunctions {
// To avoid NPE (or making the val's below lazy)
// For case classes refchecks rewrites apply calls to constructor calls, we have to do it manually
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 latestTime = ConflictManager("latest-time")
val latestRevision = ConflictManager("latest-revision")

View File

@ -19,7 +19,7 @@ object ScalaArtifacts {
val ReflectID = "scala-reflect"
val ActorsID = "scala-actors"
val ScalapID = "scalap"
val Artifacts = Seq(LibraryID, CompilerID, ReflectID, ActorsID, ScalapID)
val Artifacts = Vector(LibraryID, CompilerID, ReflectID, ActorsID, ScalapID)
val DottyIDPrefix = "dotty"
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] =
if (isDotty)
Seq(ModuleID(org, DottyIDPrefix, version, Some(Configurations.ScalaTool.name + "->compile"),
crossVersion = CrossVersion.binary))
Seq(ModuleID(org, DottyIDPrefix, version).withConfigurations(Some(Configurations.ScalaTool.name + "->compile"))
.withCrossVersion(CrossVersion.binary))
else
Seq(
scalaToolDependency(org, ScalaArtifacts.CompilerID, version),
@ -37,7 +37,7 @@ object ScalaArtifacts {
)
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 {
val Organization = "org.scala-sbt"
@ -45,9 +45,7 @@ object SbtArtifacts {
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] object IvyScala {
private[sbt] abstract class IvyScalaFunctions {
/** Performs checks/adds filters on Scala dependencies (if enabled in IvyScala). */
def checkModule(module: DefaultModuleDescriptor, conf: String, log: Logger)(check: IvyScala): Unit = {
if (check.checkExplicit)

View File

@ -6,13 +6,37 @@ package sbt.librarymanagement
import java.net.URL
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) {
override def toString: String =
organization + ":" + name + ":" + revision +
(configurations match { case Some(s) => ":" + s; case None => "" }) +
(if (extraAttributes.isEmpty) "" else " " + extraString)
abstract class ModuleIDExtra {
def organization: String
def name: String
def revision: String
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. */
def extraString: String = extraDependencyAttributes.map { case (k, v) => k + "=" + v } mkString ("(", ", ", ")")
@ -21,10 +45,7 @@ final case class ModuleID(organization: String, name: String, revision: String,
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")
def cross(v: Boolean): ModuleID = cross(if (v) CrossVersion.binary else CrossVersion.Disabled)
@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): ModuleID = cross(if (v) CrossVersion.binary else Disabled())
/** Specifies the cross-version behavior for this module. See [CrossVersion] for details.*/
def cross(v: CrossVersion): ModuleID = copy(crossVersion = v)
@ -64,7 +85,7 @@ final case class ModuleID(organization: String, name: String, revision: String,
* 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.
*/
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
@ -73,7 +94,7 @@ final case class ModuleID(organization: String, name: String, revision: String,
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. */
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.
@ -127,9 +148,7 @@ final case class ModuleID(organization: String, name: String, revision: String,
def branch(branchName: Option[String]) = copy(branchName = branchName)
}
object ModuleID {
implicit val pickler: Pickler[ModuleID] with Unpickler[ModuleID] = PicklerUnpickler.generate[ModuleID]
abstract class ModuleIDFunctions {
/** Prefixes all keys with `e:` if they are not already so prefixed. */
def checkE(attributes: Seq[(String, String)]) =
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.xml.sax.SAXParseException
sealed trait Resolver {
def name: String
}
final class RawRepository(val resolver: DependencyResolver) extends Resolver {
def name = resolver.getName
final class RawRepository(val resolver: DependencyResolver) extends Resolver(resolver.getName) {
override def toString = "Raw(" + resolver.toString + ")"
override def equals(o: Any): Boolean = o match {
@ -29,148 +25,30 @@ final class RawRepository(val resolver: DependencyResolver) extends Resolver {
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. */
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 {
abstract class PatternsFunctions {
implicit def defaultPatterns: Patterns = Resolver.defaultPatterns
def apply(artifactPatterns: String*): Patterns = Patterns(true, artifactPatterns: _*)
def apply(isMavenCompatible: Boolean, artifactPatterns: String*): Patterns = Patterns(artifactPatterns, artifactPatterns, isMavenCompatible)
def apply(ivyPatterns: Seq[String], artifactPatterns: Seq[String], isMavenCompatible: Boolean): Patterns = apply(ivyPatterns: Seq[String], artifactPatterns: Seq[String], isMavenCompatible: Boolean, false, false)
def apply(ivyPatterns: Seq[String], artifactPatterns: Seq[String], isMavenCompatible: Boolean, descriptorOptional: Boolean, skipConsistencyCheck: Boolean): Patterns = new Patterns(ivyPatterns, artifactPatterns, isMavenCompatible, descriptorOptional, skipConsistencyCheck)
}
object RepositoryHelpers {
final case class SshConnection(authentication: Option[SshAuthentication], hostname: Option[String], port: Option[Int]) {
def copy(authentication: Option[SshAuthentication]) = SshConnection(authentication, hostname, port)
def apply(isMavenCompatible: Boolean, artifactPatterns: String*): Patterns = {
val patterns = artifactPatterns.toVector
Patterns().withIvyPatterns(patterns).withArtifactPatterns(patterns).withIsMavenCompatible(isMavenCompatible)
}
/** 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 */
private[sbt] class FakeRepository(resolver: DependencyResolver) extends xsbti.Repository {
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))
object JavaNet2Repository extends MavenRepository(JavaNet2RepositoryName, JavaNet2RepositoryRoot)
object JCenterRepository extends MavenRepository(JCenterRepositoryName, JCenterRepositoryRoot)
object Resolver {
abstract class ResolverFunctions {
private[sbt] def useSecureResolvers = sys.props.get("sbt.repository.secure") map { _.toLowerCase == "true" } getOrElse true
val TypesafeRepositoryRoot = typesafeRepositoryRoot(useSecureResolvers)
@ -342,7 +220,7 @@ object Resolver {
/** Resolves the ivy file and artifact patterns in `patterns` against the given base. */
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)
}
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
}
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 defaultPatterns = mavenStylePatterns
@ -381,17 +259,17 @@ object Resolver {
}
// TODO - should this just be the *exact* same as mavenLocal? probably...
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 defaultShared = defaultUserFileRepository("shared")
def defaultUserFileRepository(id: String) =
{
val pList = s"$${ivy.home}/$id/$localBasePattern" :: Nil
FileRepository(id, defaultFileConfiguration, Patterns(pList, pList, false))
val pList = Vector(s"$${ivy.home}/$id/$localBasePattern")
FileRepository(id, defaultFileConfiguration, Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false))
}
def defaultIvyPatterns =
{
val pList = List(localBasePattern)
Patterns(pList, pList, false)
val pList = Vector(localBasePattern)
Patterns().withIvyPatterns(pList).withArtifactPatterns(pList).withIsMavenCompatible(false)
}
}

View File

@ -5,21 +5,13 @@ package sbt.librarymanagement
import java.io.File
import java.{ util => ju }
import sbt.serialization._
/**
* Provides information about resolution of a single configuration.
* @param configuration the configuration this report is for.
* @param modules a sequence containing one report for each module resolved for this configuration.
* @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]
) {
abstract class ConfigurationReportExtra {
def configuration: String
def modules: Vector[ModuleReport]
def details: Vector[OrganizationArtifactReport]
/** a sequence of evicted modules */
def evicted: Seq[ModuleID] =
details flatMap (_.modules) filter (_.evicted) map (_.module)
@ -36,78 +28,36 @@ final class ConfigurationReport(
val module = mr.module
if (module.configurations.isEmpty) {
val conf = mr.configurations map (c => s"$configuration->$c") mkString ";"
module.copy(configurations = Some(conf))
module.withConfigurations(Some(conf))
} else module
}
def retrieve(f: (String, ModuleID, Artifact, File) => File): ConfigurationReport =
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]
}
/**
* 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 evction warning etc.
*/
final class OrganizationArtifactReport private[sbt] (
val organization: String,
val name: String,
val modules: Seq[ModuleReport]
) {
override def toString: String = {
val details = modules map { _.detailReport }
s"\t$organization:$name\n${details.mkString}\n"
}
}
object OrganizationArtifactReport {
implicit val pickler: Pickler[OrganizationArtifactReport] with Unpickler[OrganizationArtifactReport] = PicklerUnpickler.generate[OrganizationArtifactReport]
abstract class ModuleReportExtra {
def module: ModuleID
def artifacts: Vector[(Artifact, File)]
def missingArtifacts: Vector[Artifact]
def status: Option[String]
def publicationDate: Option[ju.Date]
def resolver: Option[String]
def artifactResolver: Option[String]
def evicted: Boolean
def evictedData: Option[String]
def evictedReason: Option[String]
def problem: Option[String]
def homepage: Option[String]
def extraAttributes: Map[String, String]
def isDefault: Option[Boolean]
def branch: Option[String]
def configurations: Vector[String]
def licenses: Vector[(String, Option[String])]
def callers: Vector[Caller]
def apply(organization: String, name: String, modules: Seq[ModuleReport]): OrganizationArtifactReport =
new OrganizationArtifactReport(organization, name, modules)
}
protected[this] def arts: Vector[String] = artifacts.map(_.toString) ++ missingArtifacts.map(art => "(MISSING) " + art)
/**
* 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 =
s"\t\t- ${module.revision}\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 =
copy(artifacts = artifacts.map { case (art, file) => (art, f(module, art, file)) })
private[sbt] def copy(
protected[this] def copy(
module: ModuleID = module,
artifacts: Seq[(Artifact, File)] = artifacts,
missingArtifacts: Seq[Artifact] = missingArtifacts,
artifacts: Vector[(Artifact, File)] = artifacts,
missingArtifacts: Vector[Artifact] = missingArtifacts,
status: Option[String] = status,
publicationDate: Option[ju.Date] = publicationDate,
resolver: Option[String] = resolver,
@ -164,66 +114,31 @@ final class ModuleReport(
extraAttributes: Map[String, String] = extraAttributes,
isDefault: Option[Boolean] = isDefault,
branch: Option[String] = branch,
configurations: Seq[String] = configurations,
licenses: Seq[(String, Option[String])] = licenses,
callers: Seq[Caller] = callers
): ModuleReport =
new ModuleReport(module, artifacts, missingArtifacts, status, publicationDate, resolver, artifactResolver,
evicted, evictedData, evictedReason, problem, homepage, extraAttributes, isDefault, branch, configurations, licenses, callers)
configurations: Vector[String] = configurations,
licenses: Vector[(String, Option[String])] = licenses,
callers: Vector[Caller] = callers
): ModuleReport
}
object ModuleReport {
def apply(module: ModuleID, artifacts: Seq[(Artifact, File)], missingArtifacts: Seq[Artifact]): ModuleReport =
new ModuleReport(module, artifacts, missingArtifacts, None, None, None, None,
false, None, None, None, None, Map(), None, None, Nil, Nil, Nil)
implicit val pickler: Pickler[ModuleReport] with Unpickler[ModuleReport] = PicklerUnpickler.generate[ModuleReport]
}
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
abstract class UpdateReportExtra {
def cachedDescriptor: File
def configurations: Vector[ConfigurationReport]
def stats: UpdateStats
private[sbt] def stamps: Map[File, Long]
/** All resolved modules in all configurations. */
def allModules: Seq[ModuleID] =
def allModules: Vector[ModuleID] =
{
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) =>
v reduceLeft { (agg, x) =>
agg.copy(
configurations = (agg.configurations, x.configurations) match {
case (None, _) => x.configurations
case (Some(ac), None) => Some(ac)
case (Some(ac), Some(xc)) => Some(s"$ac;$xc")
}
agg.withConfigurations(
(agg.configurations, x.configurations) match {
case (None, _) => x.configurations
case (Some(ac), None) => Some(ac)
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. */
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 object librarymanagement {
package object librarymanagement extends ResolversSyntax {
type ExclusionRule = InclExclRule
val ExclusionRule = InclExclRule

View File

@ -4,28 +4,36 @@ import sbt.io.IO
import sbt.io.syntax._
import java.io.File
import cross.CrossVersionUtil
import sbt.util.Logger
import sbt.internal.util.ConsoleLogger
import sbt.librarymanagement._
import ivyint.SbtChainResolver
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 {
def currentBase: File = new File(".")
def currentTarget: File = currentBase / "target" / "ivyhome"
def currentManaged: File = currentBase / "target" / "lib_managed"
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()
def configurations = Seq(Compile, Test, Runtime)
def module(moduleId: ModuleID, deps: Seq[ModuleID], scalaFullVersion: Option[String],
def configurations = Vector(Compile, Test, Runtime)
def module(moduleId: ModuleID, deps: Vector[ModuleID], scalaFullVersion: Option[String],
uo: UpdateOptions = UpdateOptions(), overrideScalaVersion: Boolean = true): IvySbt#Module = {
val ivyScala = scalaFullVersion map { fv =>
new IvyScala(
scalaFullVersion = fv,
scalaBinaryVersion = CrossVersionUtil.binaryScalaVersion(fv),
configurations = Nil,
configurations = Vector.empty,
checkExplicit = true,
filterImplicit = false,
overrideScalaVersion = overrideScalaVersion
@ -33,32 +41,32 @@ trait BaseIvySpecification extends UnitSpec {
}
val moduleSetting: ModuleSettings = InlineConfiguration(
false,
ivyScala,
module = moduleId,
moduleInfo = ModuleInfo("foo"),
dependencies = deps,
configurations = configurations,
ivyScala = ivyScala
)
val ivySbt = new IvySbt(mkIvyConfiguration(uo))
dependencies = deps
).withConfigurations(configurations)
val ivySbt = new IvySbt(mkIvyConfiguration(uo), fileToStore)
new ivySbt.Module(moduleSetting)
}
def resolvers: Seq[Resolver] = Seq(DefaultMavenRepository)
def resolvers: Vector[Resolver] = Vector(DefaultMavenRepository)
def chainResolver = ChainedResolver("sbt-chain", resolvers)
def mkIvyConfiguration(uo: UpdateOptions): IvyConfiguration = {
val paths = new IvyPaths(currentBase, Some(currentTarget))
val other = Nil
val moduleConfs = Seq(ModuleConfiguration("*", chainResolver))
val other = Vector.empty
val moduleConfs = Vector(ModuleConfiguration("*", chainResolver))
val off = false
val check = Nil
val check = Vector.empty
val resCacheDir = currentTarget / "resolution-cache"
new InlineIvyConfiguration(paths, resolvers, other, moduleConfs, off, None, check, Some(resCacheDir), uo, log)
}
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")))
}
@ -84,7 +92,7 @@ trait BaseIvySpecification extends UnitSpec {
ivyFile = None,
resolverName = resolver.name,
artifacts = artifacts,
checksums = Seq(),
checksums = Vector.empty,
logging = UpdateLogging.Full,
overwrite = true
)

View File

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

View File

@ -2,12 +2,11 @@ package sbt.internal.librarymanagement
import java.io.File
import java.util.concurrent.Callable
import sbt.io.IO.{ createDirectory, delete, touch, withTemporaryDirectory }
import sbt.io.IO.withTemporaryDirectory
import sbt.io.IO
import org.apache.ivy.util.ChecksumHelper
import IfMissing.Fail
import xsbti.ComponentProvider
import sbt.util.Logger
// TODO - We need to re-enable this test. Right now, we dont' have a "stub" launcher for this.
// This is testing something which uses a launcher interface, but was grabbing the underlying class directly

View File

@ -1,6 +1,5 @@
package sbt.librarymanagement
import java.io.File
import sbt.internal.util.UnitSpec
class CrossVersionTest extends UnitSpec {
@ -116,7 +115,7 @@ class CrossVersionTest extends UnitSpec {
CrossVersion.binaryScalaVersion("2.10.1") shouldBe "2.10"
}
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 {
CrossVersion.full shouldBe CrossVersion.full

View File

@ -6,7 +6,6 @@ import org.apache.ivy.core.module.id.ModuleRevisionId
import org.apache.ivy.core.resolve.ResolveOptions
import sbt.librarymanagement._
import sbt.io.IO.withTemporaryDirectory
import sbt.util.Logger
import sbt.internal.util.ConsoleLogger
class CustomPomParserTest extends UnitSpec {
@ -16,8 +15,8 @@ class CustomPomParserTest extends UnitSpec {
val repoUrl = getClass.getResource("/test-maven-repo")
val local = MavenRepository("Test Repo", repoUrl.toExternalForm)
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 ivySbt = new IvySbt(conf)
val conf = new InlineIvyConfiguration(paths, Vector(local), Vector.empty, Vector.empty, false, None, Vector("sha1", "md5"), None, UpdateOptions(), log)
val ivySbt = new IvySbt(conf, DefaultFileToStore)
val resolveOpts = new ResolveOptions().setConfs(Array("default"))
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.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 {
"CrossVersion.full" should "roundtrip" in {
@ -13,7 +17,7 @@ class DMSerializationSpec extends UnitSpec {
roundtripStr(CrossVersion.binary: CrossVersion)
}
"CrossVersion.Disabled" should "roundtrip" in {
roundtrip(CrossVersion.Disabled: CrossVersion)
roundtrip(Disabled(): CrossVersion)
}
"""Artifact("foo")""" should "roundtrip" in {
roundtrip(Artifact("foo"))
@ -34,7 +38,7 @@ class DMSerializationSpec extends UnitSpec {
roundtrip(ModuleID("org", "name", "1.0"))
}
"""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 {
roundtripStr(organizationArtifactReportExample)
@ -55,17 +59,19 @@ class DMSerializationSpec extends UnitSpec {
lazy val organizationArtifactReportExample =
new OrganizationArtifactReport("org", "name", Vector(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 _ }
def roundtripStr[A: Pickler: Unpickler](a: A): Unit =
def roundtripStr[A: JsonReader: JsonWriter](a: A): Unit =
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)
val obj = fromJsonString[A](json).get
val obj = Converter fromJsonUnsafe[A] (isoString from json)
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 "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 akkaActor230 = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0", Some("compile")) cross CrossVersion.binary
def akkaActor234 = ModuleID("com.typesafe.akka", "akka-actor", "2.3.4", Some("compile")) cross CrossVersion.binary
def scala2102 = ModuleID("org.scala-lang", "scala-library", "2.10.2", Some("compile"))
def scala2103 = ModuleID("org.scala-lang", "scala-library", "2.10.3", Some("compile"))
def scala2104 = ModuleID("org.scala-lang", "scala-library", "2.10.4", Some("compile"))
def commonsIo13 = ModuleID("commons-io", "commons-io", "1.3", Some("compile"))
def commonsIo14 = ModuleID("commons-io", "commons-io", "1.4", Some("compile"))
def commonsIo24 = ModuleID("commons-io", "commons-io", "2.4", Some("compile"))
def bnfparser10 = ModuleID("ca.gobits.bnf", "bnfparser", "1.0", 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 bananaSesame04 = ModuleID("org.w3", "banana-sesame", "0.4", 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 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").withConfigurations(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").withConfigurations(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").withConfigurations(Some("compile"))
def commonsIo13 = ModuleID("commons-io", "commons-io", "1.3").withConfigurations(Some("compile"))
def commonsIo14 = ModuleID("commons-io", "commons-io", "1.4").withConfigurations(Some("compile"))
def commonsIo24 = ModuleID("commons-io", "commons-io", "2.4").withConfigurations(Some("compile"))
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").withConfigurations(Some("compile")) cross CrossVersion.binary // uses commons-io 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").withConfigurations(Some("compile")) cross CrossVersion.binary // uses akka-actor 2.3.4
def defaultOptions = EvictionWarningOptions.default
import sbt.internal.util.ShowLines._
def scalaVersionDeps = Seq(scala2102, akkaActor230)
def scalaVersionDeps = Vector(scala2102, akkaActor230)
def scalaVersionWarn1() = {
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)
}
def javaLibDirectDeps = Seq(commonsIo14, commonsIo24)
def javaLibDirectDeps = Vector(commonsIo14, commonsIo24)
def javaLibWarn1() = {
val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3"))
@ -151,20 +151,20 @@ class EvictionWarningSpec extends BaseIvySpecification {
}
def javaLibNoWarn1() = {
val deps = Seq(commonsIo14, commonsIo13)
val deps = Vector(commonsIo14, commonsIo13)
val m = module(defaultModuleId, deps, Some("2.10.3"))
val report = ivyUpdate(m)
EvictionWarning(m, defaultOptions, report, log).reportedEvictions should have size (0)
}
def javaLibNoWarn2() = {
val deps = Seq(commonsIo14, commonsIo13)
val deps = Vector(commonsIo14, commonsIo13)
val m = module(defaultModuleId, deps, Some("2.10.3"))
val report = ivyUpdate(m)
EvictionWarning(m, defaultOptions, report, log).lines shouldBe Nil
}
def javaLibTransitiveDeps = Seq(unfilteredUploads080, bnfparser10)
def javaLibTransitiveDeps = Vector(unfilteredUploads080, bnfparser10)
def javaLibTransitiveWarn1() = {
val m = module(defaultModuleId, javaLibTransitiveDeps, Some("2.10.3"))
@ -190,14 +190,14 @@ class EvictionWarningSpec extends BaseIvySpecification {
}
def scalaLibWarn1() = {
val deps = Seq(scala2104, akkaActor214, akkaActor234)
val deps = Vector(scala2104, akkaActor214, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, defaultOptions, report, log).reportedEvictions should have size (1)
}
def scalaLibWarn2() = {
val deps = Seq(scala2104, akkaActor214, akkaActor234)
val deps = Vector(scala2104, akkaActor214, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, defaultOptions, report, log).lines shouldBe
@ -210,20 +210,20 @@ class EvictionWarningSpec extends BaseIvySpecification {
}
def scalaLibNoWarn1() = {
val deps = Seq(scala2104, akkaActor230, akkaActor234)
val deps = Vector(scala2104, akkaActor230, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, defaultOptions, report, log).reportedEvictions should have size (0)
}
def scalaLibNoWarn2() = {
val deps = Seq(scala2104, akkaActor230, akkaActor234)
val deps = Vector(scala2104, akkaActor230, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, defaultOptions, report, log).lines shouldBe Nil
}
def scalaLibTransitiveDeps = Seq(scala2104, bananaSesame04, akkaRemote234)
def scalaLibTransitiveDeps = Vector(scala2104, bananaSesame04, akkaRemote234)
def scalaLibTransitiveWarn1() = {
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
}
def akkaActor214 = ModuleID("com.typesafe.akka", "akka-actor", "2.1.4", Some("compile")) cross CrossVersion.binary
def akkaActor230 = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0", Some("compile")) cross CrossVersion.binary
def akkaActor230Test = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0", Some("test")) 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").withConfigurations(Some("compile")) cross CrossVersion.binary
def akkaActor230Test = ModuleID("com.typesafe.akka", "akka-actor", "2.3.0").withConfigurations(Some("test")) cross CrossVersion.binary
}

View File

@ -1,7 +1,5 @@
package sbt.internal.librarymanagement
import java.io.File
import sbt.util.Logger
import sbt.internal.util.ConsoleLogger
// http://ant.apache.org/ivy/history/2.3.0/ivyfile/dependency.html

View File

@ -2,14 +2,13 @@ package sbt.librarymanagement
import java.net.URL
import sbt._
import sbt.internal.util.UnitSpec
object ResolverTest extends UnitSpec {
"Resolver url" should "propagate pattern descriptorOptional and skipConsistencyCheck." in {
val pats = Seq("[orgPath]")
val patsExpected = Seq("http://foo.com/test/[orgPath]")
val pats = Vector("[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
patterns.ivyPatterns shouldBe patsExpected

View File

@ -1,6 +1,6 @@
package sbt.librarymanagement
import org.apache.ivy.core.module.id.{ ModuleId, ModuleRevisionId }
import org.apache.ivy.core.module.id.ModuleRevisionId
import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor
import sbt.internal.util.UnitSpec

View File

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

View File

@ -6,7 +6,7 @@ import sbt.librarymanagement._
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 = {
// 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(
ourModuleID,
Seq(dep), None //, UpdateOptions().withCachedResolution(true)
Vector(dep), None //, UpdateOptions().withCachedResolution(true)
)
}
@ -50,21 +50,19 @@ class IvyRepoSpec extends BaseIvySpecification with DependencyBuilders {
val docTypes = Set("javadoc")
// 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
val attemptedClassifiers = Seq("sources", "javadoc")
val attemptedClassifiers = Vector("sources", "javadoc")
// 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.
val dep = "com.test" % "module-with-srcs" % "0.1.00" % "compile"
val clMod = {
import language.implicitConversions
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`)
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)
@ -80,7 +78,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 = {
val repoUrl = getClass.getResource("/test-ivy-repo")

View File

@ -0,0 +1,58 @@
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 "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"
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
@ -43,6 +43,16 @@ object Dependencies {
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 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 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")