This page describes how to use sbt's Ivy interface directly. This interface is new in 0.7. The source code can be found in the Ivy project of xsbt. The Ivy interface is published to the databinder.net repository (Ivy metadata only). You can use it in an sbt project like:
val sbtIvy = "org.scala-tools.sbt" %% "ivy" % "0.7.7" val dbRepo = Resolver.url("technically.us", new URL("http://databinder.net/repo/"))(Resolver.ivyStylePatterns)
Note that sbt, including the Ivy interface, is only built and published against Scala 2.7.7.
Ivy is normally configured with two separate XML configuration files: a settings file and a module descriptor file, which is usually just called an "Ivy file". The settings file configures resolvers, such as repositories, and paths used by Ivy. Other aspects of Ivy are configurable in the settings file as well. See Settings Files for details. The Ivy file describes a module and its dependencies. See Ivy File for details.
A user interacts with Ivy either through Ant tasks or by using Ivy as a library. To do work with Ivy, you need to run tasks, such as resolve, retrieve, or publish. Each of these tasks generally requires additional configuration.
sbt's interface to Ivy follows this separation. Configuration involves:
Each of the first two configurations may be done either by specifying an external XML file to use for configuration or by using a direct (inline) Scala data structure.
For general Ivy configuration, create an instance of sbt.IvyConfiguration, either sbt.InlineIvyConfiguration or sbt.ExternalIvyConfiguration. Each requires an IvyLogger, which is a basic interface to provide logging. In sbt, the log member of a project definition implements this interface. Additionally, each requires a GlobalLock, which is a means of synchronizing across processes. It is used to ensure the Ivy cache is only be accessed by one running instance of the Ivy interface on a machine. Specifics to each configuration are described in the next sections.
The constructor signature for inline configuration is:
InlineIvyConfiguration( paths: IvyPaths, resolvers: Seq[Resolver], otherResolvers: Seq[Resolver], moduleConfigurations: Seq[ModuleConfiguration], localOnly: Boolean, lock: Option[xsbti.GlobalLock], log: IvyLogger )
Resolvers are described on the Resolvers page. otherResolvers are resolvers that don't go in the default resolver chain. ModuleConfigurations are not currently documented, but are used to configure resolvers on a per-module basis. Nil is an acceptable argument for this parameter. localOnly should be true to achieve an offline mode. It won't check for newer versions of dynamic revisions. lock and log are as described at the beginning of the section.
An instance of IvyPaths configures two common, important paths for Ivy: the base directory and the cache directory. The base directory is the directory against which all relative paths are resolved. The cache directory is where all cached information, such as downloaded module descriptors and artifacts for dependencies, is placed.
The constructor signature for IvyPaths is:
IvyPaths( baseDirectory: File, cacheDirectory: Option[File] )
The base directory used for sbt projects is the project's path, info.projectPath. To use the default cache directory, which is usually <user.home>/.ivy2/cache, specify None. InlineIvyConfiguration is intended to provide easy configuration of the most common parameters. To access all of Ivy's configuration parameters, use ExternalIvyConfiguration, described next.
For configuration with an external XML settings file, use ExternalIvyConfiguration. The constructor signature is:
ExternalIvyConfiguration( baseDirectory: File, file: File, lock: Option[xsbti.GlobalLock], log: IvyLogger)
The base directory is the directory against which all relative paths are resolved. The file parameter specifies the location of the settings file. lock and log are as described at the beginning of the section.
These examples assume they are written in the context of an sbt project definition.
A very basic inline configuration that reuses information from the project:
val paths = new IvyPaths(info.projectPath.asFile, None) // use the repositories defined in the project val resolvers = repositories val inline = new InlineIvyConfiguration(paths, resolvers, Nil, Nil, false, Some(info.launcher.globalLock), log)
A more advanced inline configuration:
// make all paths relative to the `ivy/` subdirectory and put the cache there as well. val paths = new IvyPaths("ivy".asFile, Some("ivy" / "cache" asFile)) // define a repository and use the usual repositories (the local Ivy, central Maven, and Scala Tools repositories) val resolvers = Resolver.withDefaultResolvers( Seq("technically.us" at "http://technically.us/repo/") ) val inline = new InlineIvyConfiguration(paths, resolvers, Nil, Nil, None, log)
An external configuration:
val external = new ExternalIvyConfiguration(info.projectPath.asFile, "ivysettings.xml".asFile, Some(info.launcher.globalLock), log)
To define a module, create an instance of sbt.ModuleSettings: either sbt.IvyFileConfiguration, sbt.PomConfiguration, or sbt.InlineConfiguration. The first corresponds to configuration by an external Ivy file. The second is for configuration by an external POM. The last type is for direct configuration in Scala. Each shares two common parameters: ivyScala and validate. An instance of IvyScala controls whether Scala dependencies are checked for the correct version. If None, no checking is performed. If validate is true, Ivy validates resolved module descriptors.
The constructor signature is:
IvyFileConfiguration( file: File, ivyScala: Option[IvyScala], validate: Boolean)
The constructor signature is:
PomConfiguration(file: File, ivyScala: Option[IvyScala], validate: Boolean)
The constructor signature is:
InlineConfiguration( module: ModuleID, dependencies: Iterable[ModuleID], ivyXML: NodeSeq, configurations: Iterable[Configuration], defaultConfiguration: Option[Configuration], ivyScala: Option[IvyScala], validate: Boolean)
A ModuleID is what is constructed by the % operators in sbt. For example:
val scalacheck = "org.scalacheck" %% "scalacheck" % "1.6" % "test" val testng = "org.testng" % "testng" % "5.7" classifier "jdk15"
An inline example similar to the default sbt configuration, but with Scala version checking disabled:
val projectID: ModuleID = organization % moduleID % version.toString artifacts(artifacts.toSeq : _*) // dependencies are those defined in the project definition as: // val x = "org" % "name" % "rev" val libraryDependencies = reflectiveLibraryDependencies // Use the default Maven scopes val configurations = Configuration.defaultMavenConfigurations // Make 'compile' the default configuration val defaultConf = Configurations.Compile val inline = new InlineConfiguration(projectID, libraryDependencies, NodeSeq.Empty, configurations, defaultConf, None, true)
This section currently only describes update, which is a combination of the Ivy tasks resolve and retrieve. update is configured by an instance of sbt.UpdateConfiguration. Its constructor signature is:
UpdateConfiguration( retrieveDirectory: File, outputPattern: String, synchronize: Boolean, quiet: Boolean)
The retrieveDirectory path is prepended to outputPattern to form the pattern that determines where Ivy retrieves artifacts to. Some examples are shown in the Ivy retrieve task documentation. The default sbt retrieve pattern is:
See the Ivy documentation on patterns for more information.
When synchronize is true, Ivy will remove old artifacts from the destination directory and not just copy the new ones there. If true, quiet surpresses Ivy logging during update. If it is false, Ivy usually displays progress by a series of dots (.) as artifacts are downloaded.
val upConf = new UpdateConfiguration("lib_managed".asFile, "[conf]/[artifact](-[revision])(-[classifier]).[ext]", true, true)
With all of the configuration above, we can now run Ivy. This is a two step process. First, create instances of IvySbt and IvySbt.Module. Think of these loosely as a connection to Ivy and a configured module, respectively. There is some overhead saved by reusing these instances when the configuration is unchanged, especially when using external XML configuration files.
Finally, call the appropriate method(s) in IvyActions.
val ivyConf: IvyConfiguration = ... // as above val ivySbt = new IvySbt(ivyConf) val moduleSettings: ModuleSettings = ... // as above val ivyModule = new ivySbt.Module(moduleSettings) val upConf: UpdateConfiguration = ... // as above // resolve dependencies defined in `moduleSettings` // and retrieve them according to the configuration in `updateConf` IvyActions.update(ivyModule, updateConf) // Deletes cached metadata and artifacts from the Ivy cache IvyActions.cleanCache(ivySbt) // not currently in this documentation- see the source for IvyActions IvyActions.install(ivyModule, "Scala Tools Releases", "local") IvyActions.makePom(ivyModule, ...) IvyActions.deliver(ivyModule, ...) IvyActions.publish(ivyModule, ...)