Skip to content

Instantly share code, notes, and snippets.

@djspiewak
Last active August 29, 2015 14:16
Show Gist options
  • Save djspiewak/5f183b22b90047431194 to your computer and use it in GitHub Desktop.
Save djspiewak/5f183b22b90047431194 to your computer and use it in GitHub Desktop.
Ivy REPL

Ivy REPL

Tired of spinning up SBT just to wire in some dependencies for a quick REPL session? Me too! The following pair of scripts completely resolves this issue. Well, mostly…

list-jars is not actually an Ivy2 resolver. What it does is enumerate all possible JARS within ~/.ivy2/cache (in other words, it excludes locally published artifacts), filters them where relevant for only Scala 2.11 cross-builds, and then orders them (via a very primitive partial ordering) by version, always selecting the latest one. No attempt is made to do any real dependency resolution and JAR hell escaping! So…if something doesn't work, you're on your own.

The fun thing is that you can just launch scala-ivy and use all your fancy third-party libraries without having to do any classpath setup.

Caveats

  • JAR hell is a real thing. Don't get sent there.
  • If you have a truly staggering number of JARs in your Ivy cache, you will eventually overrun the maximum argument length. This number is probably somewhere between 500 and 1000 JARs. Note that running list-jars | wc -l will give you an idea of how likely this overrun is (on my system, this command returns 117 and things work fine).
#!/usr/bin/ruby
IVY = "/Users/daniel/.ivy2/cache"
# the optional trailing schtuff means that snapshots, RCs, and other insanity will compare as equal to numbered versions
NUM_VERSION = /^(\d+)(\.\d+)+?([-\.].*)?/
class Artifact
CROSS_BUILT = /_2\.(9.*|10.*|11.*)$/
attr_reader :group_id, :artifact_id, :version
def initialize(group_id, artifact_id, version, bundle)
@group_id = group_id
@artifact_id = artifact_id
@version = version
@bundle = bundle
end
def bundle?
@bundle
end
def crossbuilt_211?
md = artifact_id.match CROSS_BUILT
md.nil? || (md[1] =~ /^11/)
end
def jar
"#{IVY}/#{group_id}/#{artifact_id}/#{if bundle? then "bundles" else "jars" end}/#{artifact_id}-#{version}.jar"
end
def <=>(that)
return nil if group_id != that.group_id || artifact_id != that.artifact_id
if version =~ NUM_VERSION
version_data = $~.to_a
version_data.shift 1
if that.version =~ NUM_VERSION
that_version_data = $~.to_a
that_version_data.shift 1
version_data.select! { |e| !e.nil? }
that_version_data.select! { |e| !e.nil? }
version_data.map! do |e|
if e =~ /^\.(.*)/
$~[1]
else
e
end
end
that_version_data.map! do |e|
if e =~ /^\.(.*)/
$~[1]
else
e
end
end
# if both versions are non-snapshot, non-annotated, and basically not crazy, compare lexicographically
version_data <=> that_version_data
else
nil
end
else
# can't compare crazy versions (yet)
nil
end
end
def to_s
"#{group_id}:#{artifact_id}:#{version}"
end
end
groups = Dir.entries(IVY).select { |g| g != '.' && g != '..' }
artifacts = groups.map do |group|
artifacts = Dir.entries("#{IVY}/#{group}").select { |g| g != '.' && g != '..' }
artifacts.map do |artifact|
jar_path = "#{IVY}/#{group}/#{artifact}/jars"
bundle_path = "#{IVY}/#{group}/#{artifact}/bundles"
version_pat = /^#{artifact}(-bin|-src)?-(.*).jar$/
# TODO add support for locally-published artifacts
jars = if File.exists? jar_path
Dir.entries(jar_path).select { |g| g != '.' && g != '..' }
else
[]
end
bundles = if File.exists? bundle_path
Dir.entries(bundle_path).select { |g| g != '.' && g != '..' }
else
[]
end
jar_arts = jars.map do |jar|
md = jar.match version_pat
if md
version = if md.size == 2
md[1]
else
md[2]
end
[Artifact.new(group, artifact, version, false)]
else
[]
end
end
bundle_arts = bundles.map do |jar|
md = jar.match version_pat
if md
version = if md.size == 2
md[1]
else
md[2]
end
# TODO be less copy-pastey and fail
[Artifact.new(group, artifact, version, true)]
else
[]
end
end
(jar_arts + bundle_arts).uniq
end
end.flatten
only_modern = artifacts.select { |a| a.crossbuilt_211? }
jars = only_modern.group_by { |a| [a.group_id, a.artifact_id] }.map do |_, versions|
versions.sort!
versions.last.jar
end
jars.each { |j| puts j }
#!/bin/bash
exec scala -cp $(list-jars | tr '\n' :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment