Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translate Scala-style version numbers for OSGi #15

Open
szeiger opened this issue May 9, 2014 · 3 comments
Open

Translate Scala-style version numbers for OSGi #15

szeiger opened this issue May 9, 2014 · 3 comments

Comments

@szeiger
Copy link
Contributor

szeiger commented May 9, 2014

The current direct translation from Scala-style version numbers (as used for publishing in Maven repositories) to OSGi version numbers makes it difficult to get import version ranges right.

For instance, this is what we now do in slick-extensions:

  OsgiKeys.importPackage := Seq(
    osgiImport("scala.slick*", slickVersion, requireMicro=true),
    osgiImport("scala*", scalaVersion.value),
    "*"
  )

Where osgiImport is defined as:

  /** Create an OSGi version range for standard Scala / Typesafe versioning
    * schemes that describes binary compatible versions. */
  def osgiVersionRange(version: String, requireMicro: Boolean = false): String =
    if(version contains '-') "${@}" // M, RC or SNAPSHOT -> exact version
    else if(requireMicro) "${range;[===,=+)}" // At least the same micro version
    else "${range;[==,=+)}" // Any binary compatible version

  /** Create an OSGi Import-Package version specification. */
  def osgiImport(pattern: String, version: String, requireMicro: Boolean = false): String =
    pattern + ";version=\"" + osgiVersionRange(version, requireMicro) + "\""

This means that slick-extensions 2.0.2 imports slick [2.0.2,2.1) and slick-extensions 2.1.0 imports slick [2.1.0,2.2), which are the defined binary compatible versions. When we look at non-release versions (which have no binary compatibility guarantees), this also works fine: slick-extensions 2.1.0.M1 imports slick 2.1.0.M1.

Combining either multiple release versions, or multiple non-release versions in a container also poses no problems, but things break down when you try to mix release and non-release versions like slick-extensions 2.1.0.M1 and 2.1.0 because 2.1.0.M1 is matched by [2.1.0,2.2) even though it is incompatible and older than 2.1.0.

I think sbt-osgi would be a good place to solve this for all Scala libraries. It could translate the version from the sbt build to an OSGi version for the bundle and the exported packages, and do the same to dependency versions (or is that fully handled by bnd?).

I have some ideas how a suitable version number scheme could look but I'm sure this problem has already been solved by the OSGi community, so I'll leave it to others to suggest something.

As far as I can tell, the challenges are:

  • How to translate Maven version numbers (including milestones, RCs and possibly snapshots) into OSGi version numbers so that binary compatibility can be specified correctly
  • What are the implications of having different version numbers for the bundle + packages and the JARs in a Maven repo? Will this negatively affect discovery of packages?
  • Bonus: Define the translation scheme such that the standard version range [==,+) can be used.
@reggert
Copy link
Contributor

reggert commented May 30, 2014

Unfortunately, OSGi and Maven have very different views as to how version qualifiers should be handled. Maven primarily uses qualifiers for pre-release builds, whereas OSGi treats versions with qualifiers as being newer than versions without qualifiers. IIRC, there was an attempt to add some sort of pre-release qualifier support to the OSGi spec, but to the best of my knowledge, that attempt was aborted.

@reggert
Copy link
Contributor

reggert commented May 30, 2014

Also note that it is not guaranteed that the package-level version numbers will match the bundle-level or POM-level version numbers for a given dependency, though sbt-osgi (and maven-bundle-plugin) will make them match by default when creating bundles.

E.g., it may be possible that the foo:bar:1.0.0:jar artifact will contain packages a.b.c;version="1.0.1" and d.e.f;version="2.0.0".

@reggert
Copy link
Contributor

reggert commented May 30, 2014

I'm not sure that it's possible to solve this generically in a way that will work for all projects, since different projects are likely to have different policies regarding dependency versions. That said, it may feasible to provide a way to at least generate the appropriate package import for the Scala standard library in a uniform way, since that's likely to be the same across all Scala projects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants