built.sbt without .repositories file with m2compatible set to true - sbt

i am in a scenario that the artifacts are published to a local maven repository with both both pom file and ivy file. I am trying to access this repository by treating it as an ivy repo, as a result, I had to set m2compatible=true so that the resolvers can correctly identify the path pattern.
sbt allows one to override the default list of resolvers through the following properties:
-Dsbt.override.build.repos=true -Dsbt.repository.config=<path to sbt repository file>
The foramt of the repository file is something like the following,
[repositories]
local
my-artifacts: http://my.artifact.proxyserver.com/artifacts/,[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]
maven : http://my.artifact.proxyserver.com/artifactory/maven-central
My question is how am I able to specify m2compatible=true for the resolver "my-artifacts" in the above file? Because without that setting, if I depend on
com.google.common % guava % 23.1
the resolver will look for the path:
com.google.common/guava/23.1
instead of
com/google/common/guava/23.1

sbt allows to add mavenCompatible towards the end of an ivy resolver.

Related

Need to provide addtional jars to for xsbt-web-plugin container

I am trying to run my war file using xsbt-web-plugin. My war itself does not contain tomcat-jdbc-pool jar and javax-servlet-api. I tried using container configuration. But sbt complains configuration does not exist.
If I use provided configuration, webapp-runner fails.
I am sure I am missing something. But unable to figure it out.
WARNING: Failed to register in JMX: [javax.naming.NamingException: Could not load resource factory class [Root exception is java.lang.ClassNotFoundException: org.apache.tomcat.jdbc.pool.DataSourceFactory]]
What version of xsbt-web-plugin are you using? Can you post the contents of your sbt build configuration?
The Tomcat plugin in xsbt-web-plugin relies on webapp-runner, which does not appear to bundle the tomcat-jdbc library. You can add it via containerLibs in Tomcat:
enablePlugins(TomcatPlugin)
containerLibs in Tomcat += "org.apache.tomcat" % "tomcat-jdbc" % "8.5.15"

Releasing and publishing from sbt-bintray

I'm trying to publish to bintray a relase for my library. I already released several versions till now.
java.lang.RuntimeException: error uploading to https://api.bintray.com/maven/raisercostin/maven/maven/org/raisercostin/jedi-io_2.10/0.22/jedi-io_2.10-0.22.pom:
{"message":"Unable to upload files: Maven group, artifact or version defined in the pom file do not match the file path 'org/raisercostin/jedi-io_2.10/0.22/jedi-io_2.10-0.22.pom'"}
at bintray.BintrayMavenRepository.put(Resolver.scala:27)
at org.apache.ivy.plugins.resolver.RepositoryResolver.put(RepositoryResolver.java:234)
I'm using bintray-sbt via project/plugins.sbt
addSbtPlugin("me.lessis" % "bintray-sbt" % "0.3.0")
The project with full details is hosted on github/jedi-io.
I noticed a double maven/maven in the api url and tried to "fix" it using a custom bintray-sbt and it didn't work with either: https://api.bintray.com/maven/raisercostin/maven/org/raisercostin/jedi-io_2.10/0.22/jedi-io_2.10-0.22.pom
As a workaround I enabled publishing ivy style with publishMavenStyle := false and defined an additional ivy resolver in the using app resolvers += Resolver.url("raisercostin ivy resolver", url("http://dl.bintray.com/raisercostin/maven"))(Resolver.ivyStylePatterns)

How do I add a Nexus resolver after local repository, but before the default repositories?

We have an internal Nexus repository that we use to publish artifacts to and also to cache external dependencies (from Maven Central, Typesafe, etc.)
I want to add the repository as a resolver in my SBT build, under the following restrictions:
The settings need to be part of the build declaration (either .sbt or .scala, but not in the "global" sbt settings
If a dependency exists in the local repository, it should be taken from there. I don't want to have to access the network to get all the dependencies for every build.
If a dependency doesn't exist locally, sbt should first try to get it from the Nexus repository before trying the external repositories.
I saw several similar questions here, but didn't find any solution that does exactly this. Specifically, the code I currently have is:
externalResolvers ~= { rs => nexusResolver +: rs }
But when I show externalResolvers the Nexus repo appears before the local one.
So far, I've come up with the following solution:
externalResolvers ~= { rs =>
val grouped = rs.groupBy(_.isInstanceOf[FileRepository])
val fileRepos = grouped(true)
val remoteRepos = grouped(false)
fileRepos ++ (nexusResolver +: remoteRepos)
}
It works, but is kinda dirty... If anyone has a "cleaner" solution, I'd love to hear it.

SBT support for custom ivy module status?

In my SBT build I have a dependency on an ivy artifact that makes use of a custom module status. This causes the following error in SBT:
[error] (*:update) sbt.ResolveException: unresolved dependency: my-org#myapp-core_2.11;1.0: java.text.ParseException: inconsistent module descriptor file found in 'http://artifacts.myorg.com/libs-snapshots-local/myapp-core_2.11/1.0/myapp-ivy.xml': bad status: 'snapshot';
I can work around this by telling SBT to use an external ivy settings, like so:
externalIvySettings(baseDirectory(_ / "ivySettings.xml"))
And then create an ivySettings.xml containing the following:
<statuses default="release">
<status name="release" integration="false"/>
<status name="snapshot" integration="false"/>
</statuses>
But surely there must be a better way? The problem with this work around is that now all my settings (such as resolvers) have to be in the ivy file too, because (IFAIK) it's all or nothing when you use externalIvySettings.
Is there a way to specify a set of custom statuses within my build.sbt? Or alternatively is there a way to tell sbt to combine external ivy settings with the ones it generates from the build.sbt.
Since specifying custom module statuses is a valid thing to do in ivy, this should really be supported in sbt too.
This is because for some repositories, they use non-standard status which fails the consistency check. We addressed this by constructing the customized resolver which doesn't do consistency check. You can also construct resolver with the custom status using the same approach. The following is the working snippet.
resolvers += {
val resolver = new org.apache.ivy.plugins.resolver.IBiblioResolver
resolver.setName("Custom Ivy Snapshots")
resolver.setRoot("http://Custom/snapshots/")
val settings = new org.apache.ivy.core.settings.IvySettings()
settings.setVariable("ivy.local.default.ivy.pattern", Pattern)
settings.setVariable("ivy.local.default.artifact.pattern", Pattern)
resolver.setSettings(settings)
resolver.setM2compatible(true)
resolver.setCheckconsistency(false)
new RawRepository(resolver)
}

How to configure Typesafe Activator not to use user home?

I'd like to configure Typesafe Activator and it's bundled tooling not to use my user home directory - I mean ~/.activator (configuration?), ~/.sbt (sbt configuration?) and especially ~/.ivy2, which I'd like to share between my two OSes.
Typesafe "documentation" is of little help.
Need help for both Windows and Linux, please.
From Command Line Options in the official documentation of sbt:
sbt.global.base - The directory containing global settings and plugins (default: ~/.sbt/0.13)
sbt.ivy.home - The directory containing the local Ivy repository and artifact cache (default: ~/.ivy2)
It appears that ~/.activator is set and used in the startup scripts and that's where I'd change the value.
It also appears (in sbt/sbt.boot.properties in activator-launch-1.2.1.jar) that the value of ivy-home is ${user.home}/.ivy2:
[ivy]
ivy-home: ${user.home}/.ivy2
checksums: ${sbt.checksums-sha1,md5}
override-build-repos: ${sbt.override.build.repos-false}
repository-config: ${sbt.repository.config-${sbt.global.base-${user.home}/.sbt}/repositories}
It means that without some development it's only possible to change sbt.global.base.
➜ minimal-scala activator -Dsbt.global.base=./sbt -Dsbt.ivy.home=./ivy2 about
[info] Loading project definition from /Users/jacek/sandbox/sbt-launcher/minimal-scala/project
[info] Set current project to minimal-scala (in build file:/Users/jacek/sandbox/sbt-launcher/minimal-scala/)
[info] This is sbt 0.13.5
[info] The current project is {file:/Users/jacek/sandbox/sbt-launcher/minimal-scala/}minimal-scala 1.0
[info] The current project is built against Scala 2.11.1
[info] Available Plugins: sbt.plugins.IvyPlugin, sbt.plugins.JvmPlugin, sbt.plugins.CorePlugin, sbt.plugins.JUnitXmlReportPlugin
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.4
If you want to see under the hood, you could query for the current values of the home directories for sbt and Ivy with consoleProject command (it assumes you started activator with activator -Dsbt.global.base=./sbt -Dsbt.ivy.home=./ivy2):
> consoleProject
[info] Starting scala interpreter...
[info]
import sbt._
import Keys._
import _root_.sbt.plugins.IvyPlugin
import _root_.sbt.plugins.JvmPlugin
import _root_.sbt.plugins.CorePlugin
import _root_.sbt.plugins.JUnitXmlReportPlugin
import currentState._
import extracted._
import cpHelpers._
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_60).
Type in expressions to have them evaluated.
Type :help for more information.
scala> appConfiguration.eval.provider.scalaProvider.launcher.bootDirectory
res0: java.io.File = /Users/jacek/sandbox/sbt-launcher/minimal-scala/sbt/boot
scala> appConfiguration.eval.provider.scalaProvider.launcher.ivyHome
res1: java.io.File = /Users/jacek/.ivy2
Iff you're really into convincing Activator to use sbt.ivy.home, you have to change sbt/sbt.boot.properties in activator-launch-1.2.2.jar. Just follow the steps:
Unpack sbt/sbt.boot.properties out of activator-launch-1.2.2.jar.
jar -xvf activator-launch-1.2.2.jar sbt/sbt.boot.properties
Edit sbt/sbt.boot.properties and replace ivy-home under [ivy].
ivy-home: ${sbt.ivy.home-${user.home}/.ivy2}
Add the changed sbt/sbt.boot.properties to activator-launch-1.2.2.jar.
jar -uvf activator-launch-1.2.2.jar sbt/sbt.boot.properties
With the change, -Dsbt.ivy.home=./ivy2 works fine.
scala> appConfiguration.eval.provider.scalaProvider.launcher.bootDirectory
res0: java.io.File = /Users/jacek/sandbox/sbt-launcher/minimal-scala/sbt/boot
scala> appConfiguration.eval.provider.scalaProvider.launcher.ivyHome
res1: java.io.File = /Users/jacek/sandbox/sbt-launcher/minimal-scala/ivy2
I was experimenting with this today. After a while, it seems to me like this could be the best thing to do:
Windows:
setx _JAVA_OPTIONS "-Duser.home=C:/my/preferred/home/"
Linux:
export _JAVA_OPTIONS='-Duser.home=/local/home/me'
Then you should be good to go for any Java Program that wants to store data in your home directory.
As an addition to Jacek's answer, another way that worked for me to set the .ivy2 directory was to use the sbt ivyConfiguration task. It returns configuration settings related to ivy, including the path to the ivy home (the one which defaults to ~/.ivy2).
Simply add these few lines to the build.sbt file in your project :
ivyConfiguration ~= { originalIvyConfiguration =>
val config = originalIvyConfiguration.asInstanceOf[InlineIvyConfiguration]
val ivyHome = file("./.ivy2")
val ivyPaths = new IvyPaths(config.paths.baseDirectory, Some(ivyHome))
new InlineIvyConfiguration(ivyPaths, config.resolvers, config.otherResolvers,
config.moduleConfigurations, config.localOnly, config.lock,
config.checksums, config.resolutionCacheDir, config.log)
}
It returns a new ivy configuration identical to the original one, but with the right path to the ivy home directory (here ./.ivy2, so it'll be located just next to the build.sbt file). This way, when sbt uses the ivyConfiguration task to get the ivy configuration, the path to the .ivy2 directory will be the one set above.
It worked for me using sbt 0.13.5 and 0.13.8.
Note: for sbt versions 0.13.6 and above, the construction of the InlineIvyConfiguration needs an additional parameter to avoid being flagged as deprecated, so you might want to change the last line into :
new InlineIvyConfiguration(ivyPaths, config.resolvers, config.otherResolvers,
config.moduleConfigurations, config.localOnly, config.lock,
config.checksums, config.resolutionCacheDir, config.updateOptions, config.log)
(note the additional config.updateOptions)
I had that same problem on Mac. I erased the directory in user home directory named .activator and all related folder. After that run activator run command on terminal. Activator download all of the folder which I deleted. Than problem solved.

Resources