Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unzipping an artifact with SBT

Tags:

sbt

As part of my project build, I'd like to unzip a zip artifact of a managed dependency into a specific directory of the project. Before starting to use SBT I was doing this via an ANT script that would fetch the zip artifact from a maven dependency and unzip it.

My question(s) are:

  • how to specify that I want to depend on the zip dependency? I have defined it like so: "eu.delving" % "sip-creator" % "0.4.6-SNAPSHOT" but this doesn't fetch the zip artifact
  • where / how to hook into the build process to run the unzip (and how to refer to the artifact file in that context)?
like image 325
Manuel Bernhardt Avatar asked Feb 21 '12 14:02

Manuel Bernhardt


1 Answers

If you want to extract a set of managed dependencies, the code below should work. I tested it in sbt 0.12.0, but it should also work with 0.11.x.

import sbt._
import Keys._
import Classpaths.managedJars

object TestBuild extends Build {

    lazy val jarsToExtract = TaskKey[Seq[File]]("jars-to-extract", "JAR files to be extracted")

    lazy val extractJarsTarget = SettingKey[File]("extract-jars-target", "Target directory for extracted JAR files")

    lazy val extractJars = TaskKey[Unit]("extract-jars", "Extracts JAR files")

    lazy val testSettings = Defaults.defaultSettings ++ Seq(
        // define dependencies
        libraryDependencies ++= Seq(
            "com.newrelic" % "newrelic-api" % "2.2.1"
        ),

        // collect jar files to be extracted from managed jar dependencies
        jarsToExtract <<= (classpathTypes, update) map { (ct, up) =>
            managedJars(Compile, ct, up) map { _.data } filter { _.getName.startsWith("newrelic-api") }
        },

        // define the target directory
        extractJarsTarget <<= (baseDirectory)(_ / "extracted"),

        // task to extract jar files
        extractJars <<= (jarsToExtract, extractJarsTarget, streams) map { (jars, target, streams) =>
            jars foreach { jar =>
                streams.log.info("Extracting " + jar.getName + " to " + target)
                IO.unzip(jar, target)
            }
        },

        // make it run before compile
        compile in Compile <<= extractJars map { _ => sbt.inc.Analysis.Empty }
    )

    lazy val test: Project = Project("test", file(".")) settings (testSettings: _*)
}

If you simply have jar files to extract, you can add them as unmanaged dependencies, ie. putting them into the /lib folder. See: https://github.com/harrah/xsbt/wiki/Getting-Started-Library-Dependencies

If you really have zip files (or want to extract the unmanaged dependencies), you can change the above code to list them:

// list jar files to be extracted
jarsToExtract <<= (baseDirectory) map { dir => Seq(dir / "lib" / "newrelic-api-2.2.1.zip") },

You should now be able to manually extract them from sbt and they should automatically be extracted before compile:

> clean
[success] Total time: 0 s, completed Oct 12, 2012 5:39:16 PM
> extract-jars
[info] Extracting newrelic-api-2.2.1.zip to /Users/balagez/Sites/test/extracted
[success] Total time: 0 s, completed Oct 12, 2012 5:39:22 PM
> compile
[info] Extracting newrelic-api-2.2.1.zip to /Users/balagez/Sites/test/extracted
[success] Total time: 0 s, completed Oct 12, 2012 5:39:24 PM

Now you can add a new task or extend the existing one which extracts the zip file from the extracted dependency. If you don't need the contents of the dependency, you can use the task-temporary-directory setting which gives you a temporary directory writable by sbt:

// define the target directory
extractJarsTarget <<= taskTemporaryDirectory,
like image 128
Zoltán Balázs Avatar answered Oct 22 '22 22:10

Zoltán Balázs