Klangism

Things that were important enough at the time when they were written.

Viktor Klang is a legendary programmer, known from places like the Internet. Consider following him on Twitter.

Posts tagged SBT

Dec 8

Hardcore Pom

A fairly nice technique to speed up update- times in SBT is by using ModuleConfigurations. A ModuleConfiguration can be viewed as a filter on top of a repository, saying: "Only look in the repository if the artifact you’re looking for has the following group id."

Pattern:

class MyProject(info: ProjectInfo) extends DefaultProject(info) {

object Repositories {

  //Add repositories here, they won’t be used for artifact lookup since they’re inside the object

  lazy val ScalaToolsRepo = MavenRepository(“Scala Tools Repository”, “http://nexus.scala-tools.org/content/repositories/hosted”)

  //… add more repos here

}

//Here we add our ModuleConfigurations

lazy val scalaTestModuleConfig  = ModuleConfiguration(“org.scalatest”, ScalaToolsRepo) //equiv of saying: “When you look for something with group id “org.scalatest”, look n this repo, but not otherwise

//Here we add our dependencies

val scalatest = “org.scalatest” % “scalatest” % “1.2” % “test”

}

That’s the entire pattern, this leads to extremely fast “sbt update"s and you are in more control of what gets downloaded from where.

However, I noticed that there is a big caveat.

Unfortunately SBT doesn’t take ModuleConfigurations into consideration when generating poms during publish-local and publish, this leads to poms that are missing a lot if not all of the repositories needed for its dependencies if you use the technique above.

With a big list of dependencies and ModuleConfigurations this is what I got in my pom:

<repositories>
        <repository>
            <id>ScalaToolsReleasesRepo</id>
            <name>Scala Tools Releases Repo</name>
            <url>http://scala-tools.org/repo-releases/</url>
        </repository>

</repositories>

Not what I had expected, there should be quite a few repos in there…

So I hacked together a small chunk of Scala that will post-process the poms and add all repos in your ModuleConfigurations, and I’ve named it McPom (ModuleConfiguration into Pom).

And this is the same artifact after McPom is thrown into the game:

    <repositories>
        <repository>
            <id>ScalaToolsReleasesRepo</id>
            <name>Scala Tools Releases Repo</name>
            <url>http://scala-tools.org/repo-releases/</url>
        </repository>
        <repository>
            <id>javanetRepo</id>
            <name>java.net Repo</name>
            <url>http://download.java.net/maven/2/</url>
        </repository>
        <repository>
            <id>JBossRepo</id>
            <name>JBoss Repo</name>
            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
        </repository>
        <repository>
            <id>public</id>
            <name>public</name>
            <url>http://repo1.maven.org/maven2/</url>
        </repository>
        <repository>
            <id>CodehausRepo</id>
            <name>Codehaus Repo</name>
            <url>http://repository.codehaus.org/</url>
        </repository>
        <repository>
            <id>GuiceyFruitRepo</id>
            <name>GuiceyFruit Repo</name>
            <url>http://guiceyfruit.googlecode.com/svn/repo/releases/</url>
        </repository>
        <repository>
            <id>DatabinderRepo</id>
            <name>Databinder Repo</name>
            <url>http://databinder.net/repo/</url>
        </repository>
        <repository>
            <id>GlassfishRepo</id>
            <name>Glassfish Repo</name>
            <url>http://download.java.net/maven/glassfish/</url>
        </repository>
    </repositories>

Woot! McPom saves the day!

The only thing you need to do is to add the McPom trait to your project file, and mix it into the projects that needs it, and add the following override to them:

override def pomPostProcess(node: Node): Node = mcPom(moduleConfigurations)(super.pomPostProcess(node))
That’s it!
McPom can be found here
Enjoy!

Nov 30

SBT-fu: Publish privately

Have you’ve ever had the problem that you need to publish some Jars where your colleagues need to find them, but they are your secret web-scale sauce Jars and no one on the outside should be able to see them?

And you don’t get any permission to put the jars on a network share, and you’re not worthy of your own build server, says mr Infrastructure Manager?

And you happen to be using SBT?

There’s this wonderful service out there called Dropbox which is a small “cloud” storage solution that gives you a stash where you can put your personal files, and you have an option to have files available to the public, but they ALSO give you the possibility to _share_ folder with your trusted accomplices.

Here’s what you need to do:

1) Download and install dropbox

2) Create a new folder in your Dropbox root folder and name it something like "M2"

3) Add the following to your SBT project file

override def managedStyle = ManagedStyle.Maven

 val publishTo = Resolver.file(“shared-repo”,

             Path.userHome / “Dropbox” / “M2” asFile)

    This tells SBTs “publish” action to place your artifacts in your "M2" folder in your dropbox root

4) Then add your awesome Dropbox M2 repo to the projects that needs to use the published artifacts

 val SharedRepo  = MavenRepository(“shared-repo”,
                                  (Path.userHome / “Dropbox” / “M2”).asURL.toString)

5) Log onto www.dropbox.com and go into the “Sharing”-tab and share the M2 folder with all your awesome ninja buddies

6) Do an SBT publish, this places your freshly baked artifacts in your dropbox, and after Dropbox has synched it’s going to be propagated to your awesome friends.

7) No, seriously, you’re all done.

Enjoy!