jbundler 0.0.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,32 @@
1
+ # build jbundler #
2
+
3
+ the build uses ruby-maven. **note** ruby-maven uses maven and maven is highly modular, i.e. it comes only with the core and the moment you need a plugin he first time its starts downloading it. with that in mind the first usage of (ruby-)maven involves a lot of downloading - so be prepared :)
4
+
5
+ first get all the development gems in place:
6
+
7
+ ```jruby -S bundle install```
8
+
9
+ to build the (extension) jar for the lib directory (prepare the jar before packaging the gem)
10
+
11
+ ```rmvn prepare-package```
12
+
13
+ this also runs all the test over a couple of jruy version each in 1.8 and 1.9 mode. so these tests take some time. in skip the tests when building the gem use:
14
+
15
+ ```rmvn prepare-package --Dmaven.test.skip```
16
+
17
+ to build the gem in **target/jbundler-0.0.1.gem**
18
+
19
+ ```rmvn package```
20
+
21
+ or once the jar file is in place then
22
+
23
+ ```gem build jbundler.gemspec```
24
+
25
+ will do as well.
26
+
27
+ ## proper maven and IDEs ##
28
+
29
+ once ```rmvn``` generated the **Gemfile.pom** you can use proper maven3 by setting a sybolic link from **pom.xml** to **Gemfile.pom**. in the end rmvn is just ruby wrapper around maven3. the **Gemfile.pom** is generated from the *jbundler.gemspec*, *Gemfile*, *Gemfile.lock* and *Mavenfile*.
30
+
31
+ your IDE might be able to use the pom.xml to manage the project and its java sources.
32
+
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source :rubygems
2
+ gemspec
3
+
4
+ # needed for local setup
5
+ #gem 'maven-tools', :path => '../jruby-maven-plugins/ruby-tools/src/main/gem/maven-tools'
6
+
7
+ group :test do
8
+ gem 'minitest', '~> 2.10.0'
9
+ gem 'cucumber', '~> 1.1.9'
10
+ end
@@ -0,0 +1,35 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ jbundler (0.2.0)
5
+ ruby-maven (= 3.0.4.0.29.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ builder (3.0.0)
11
+ cucumber (1.1.9)
12
+ builder (>= 2.1.2)
13
+ diff-lcs (>= 1.1.2)
14
+ gherkin (~> 2.9.0)
15
+ json (>= 1.4.6)
16
+ term-ansicolor (>= 1.0.6)
17
+ diff-lcs (1.1.3)
18
+ gherkin (2.9.3-java)
19
+ json (>= 1.4.6)
20
+ json (1.7.3-java)
21
+ maven-tools (0.29.0)
22
+ minitest (2.10.1)
23
+ ruby-maven (3.0.4.0.29.0)
24
+ maven-tools (= 0.29.0)
25
+ thor (~> 0.14.6)
26
+ term-ansicolor (1.0.7)
27
+ thor (0.14.6)
28
+
29
+ PLATFORMS
30
+ java
31
+
32
+ DEPENDENCIES
33
+ cucumber (~> 1.1.9)
34
+ jbundler!
35
+ minitest (~> 2.10.0)
@@ -0,0 +1,33 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ jbundler (0.2.0)
5
+ ruby-maven (= 3.0.4.0.29.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ builder (3.0.0)
11
+ cucumber (1.1.9)
12
+ builder (>= 2.1.2)
13
+ diff-lcs (>= 1.1.2)
14
+ gherkin (~> 2.9.0)
15
+ json (>= 1.4.6)
16
+ term-ansicolor (>= 1.0.6)
17
+ diff-lcs (1.1.3)
18
+ gherkin (2.9.3-java)
19
+ json (>= 1.4.6)
20
+ json (1.7.3-java)
21
+ minitest (2.10.1)
22
+ ruby-maven (3.0.4.0.29.0)
23
+ thor (~> 0.14.6)
24
+ term-ansicolor (1.0.7)
25
+ thor (0.14.6)
26
+
27
+ PLATFORMS
28
+ java
29
+
30
+ DEPENDENCIES
31
+ cucumber (~> 1.1.9)
32
+ jbundler!
33
+ minitest (~> 2.10.0)
@@ -0,0 +1,88 @@
1
+ # jbundler #
2
+
3
+ * the DSL mimics the one from bundler
4
+ * you can use maven like version declaration or rubygems/bundler like version ranges
5
+ * it locks down the versions like bundler inside "Mvnfile.lock"
6
+ * you can declare jar dependency within a rubygems using the requirements directive of the gem specification. jbundler will include those jar dependencies into its classpath
7
+ * on the first run everything get resolved, any further run just the setup of classpath is done (without any maven involved)
8
+ * it integrates nicely with bundler when Bundler.require is used
9
+
10
+ ## get started
11
+
12
+ just add it as **first** entry in your *Gemfile* (pending since no gem is released)
13
+
14
+ ```gem 'jbundler'```
15
+
16
+ such bundler config will trigger the classpath resolution on the first call of ```Bundler.require```, any successive runs will reuse the classpath from *.jbundler/classpath.rb* without any more action with maven.
17
+
18
+ if you use only **rubygems** or **isolate** then following require will trigger the classpath setup
19
+
20
+ ```require 'jbundler'```
21
+
22
+ ## example ##
23
+
24
+ **please first build the jar file for the jbundler gem, see [Build.md](Build.md).**
25
+
26
+ *example/my_project* has a Gemfile which uses a gem which depends on jar dependency. see *example/gem_with_jar/gem_with_jar.gemspec* how the jar gets declared.
27
+
28
+ execute *example/my_project/info.rb* to see it in action:
29
+
30
+ cd example/my_project
31
+ jruby -S bundle install
32
+ jruby -S bundle exec info.rb
33
+
34
+ ## limitations ##
35
+
36
+ update of single artifacts is not possible.
37
+
38
+ since the version resolution happens in two steps - first the gems then the jars/poms - it is possible in case of failure of the second one there could be another set of versions for the gems which would then succeed the jars/poms resolution. but there is plenty of possible ways to improve this (maven could resolve the gems as well, etc)
39
+
40
+ **Mvnfile** is **not** a DSL, i.e. it is not ruby though it could use a ruby DSL to read the data (any contribution welcome).
41
+
42
+ ## jar/pom dependencies ##
43
+
44
+ a pom dependency is not associated with a jar file but has dependencies to other poms or jars.
45
+
46
+ dependencies can be declared either in **Mvnfile**
47
+
48
+ jar 'org.slf4j:slf4j-simple', '> 1.6.2', '< 1.7.0'
49
+ jar 'org.sonatype.aether:aether-api', '1.13'
50
+
51
+ or inside the gemspec through the requirements (see also the example directory of this project):
52
+
53
+ Gem::Specification.new do |s|
54
+ s.name = 'gem_with_jar'
55
+ s.version = '0.0.0'
56
+ s.requirements << "jar 'org.slf4j:slf4j-api', '1.5.10'"
57
+ end
58
+
59
+ ### maven like version ###
60
+
61
+ ```jar 'my.group.id:my-artifact-id', '1.2.3'```
62
+
63
+ this will add the jar dependency for the maven artifact **my.group.id:my-artifact-id** with version **1.2.3**. this version will be treated as **maven version**, i.e. in case of a version conflict the one which is closer to project root will be used (see also: TODO link)
64
+
65
+ ### rubygem like version ###
66
+
67
+ some example (see also: TODO link)
68
+
69
+ jar 'my.group.id:my-artifact-id', '1.2.3'
70
+ pom 'my.group:my-artifact-id', '=1.2.3'
71
+ jar 'my.group.id:artifact-id', '>1.2.3'
72
+ jar 'my.group:artifact-id', '>1.2.3', '=<2.0.1'
73
+
74
+ the no version will default to **[0,)** (maven version range) which is **>=0** in the rubygems world.
75
+
76
+ jar 'group:artifact-id'
77
+
78
+ the *not* version **!3.4.5** can not be mapped properly to a maven version ranges. **>3.4.5** is used instead in these (rare) cases.
79
+
80
+ ## update ##
81
+
82
+ update of a single artifact is not possible (yet). but to update the whole set of artifacts just delete the lockfile *Mvnfile.lock*
83
+
84
+ if jbundler sees that **Gemfile.lock** or **Mvnfile** is newer then the **.jbundler/classpath.rb** file then jbundler tries to gracefully upgrade towards the changes. the is a maven-like behaviour and once there are command line tools for jbundler they can behave like bundler.
85
+
86
+ ## meta-fu ##
87
+
88
+ bug-reports and pull request are most welcome.
Binary file
@@ -1,34 +1,39 @@
1
- require 'jbundler/mavenfile'
1
+ require 'maven/tools/jarfile'
2
2
  require 'jbundler/classpath_file'
3
3
  require 'jbundler/gemfile_lock'
4
4
  require 'jbundler/aether'
5
5
 
6
6
  config = JBundler::AetherConfig.new
7
7
 
8
- mavenfile = JBundler::Mavenfile.new(config.mavenfile)
9
- classpath_file = JBundler::ClasspathFile.new('.jbundler/classpath.rb')
10
- gemfile_lock = JBundler::GemfileLock.new(mavenfile, config.gemfile + '.lock')
8
+ jarfile = Maven::Tools::Jarfile.new(config.jarfile)
9
+ if config.skip
10
+ warn "skip jbundler setup"
11
+ else
12
+ classpath_file = JBundler::ClasspathFile.new('.jbundler/classpath.rb')
13
+ gemfile_lock = JBundler::GemfileLock.new(jarfile, config.gemfile + '.lock')
11
14
 
12
- if classpath_file.needs_update?(mavenfile, gemfile_lock)
13
- aether = JBundler::AetherRuby.new(config)
15
+ if classpath_file.needs_update?(jarfile, gemfile_lock)
16
+ aether = JBundler::AetherRuby.new(config)
14
17
 
15
- mavenfile.populate_unlocked(aether)
16
- gemfile_lock.populate_depedencies(aether)
17
- mavenfile.populate_locked(aether)
18
+ jarfile.populate_unlocked(aether)
19
+ gemfile_lock.populate_dependencies(aether)
20
+ jarfile.populate_locked(aether)
18
21
 
19
- aether.resolve
22
+ aether.resolve
20
23
 
21
- classpath_file.generate(aether.classpath)
22
- mavenfile.generate_lockfile(aether.resolved_coordinates)
23
- end
24
+ classpath_file.generate(aether.classpath)
25
+ jarfile.generate_lockfile(aether.resolved_coordinates)
26
+ end
24
27
 
25
- if classpath_file.exists?
26
- require 'java'
27
- classpath_file.require_classpath
28
- if config.verbose
29
- warn "jbundler classpath:"
30
- JBUNDLER_CLASSPATH.each do |path|
31
- warn "\t#{path}"
28
+ if classpath_file.exists?
29
+ require 'java'
30
+ classpath_file.require_classpath
31
+ if config.verbose
32
+ warn "jbundler classpath:"
33
+ JBUNDLER_CLASSPATH.each do |path|
34
+ warn "\t#{path}"
35
+ end
32
36
  end
33
37
  end
38
+
34
39
  end
@@ -0,0 +1,2 @@
1
+ require 'jbundler/maven_gemify3'
2
+
@@ -1,4 +1,3 @@
1
- require 'java'
2
1
  require 'yaml'
3
2
 
4
3
  module JBundler
@@ -6,34 +5,54 @@ module JBundler
6
5
  # allow yaml config in $HOME/.jbundlerrc and $PWD/.jbundlerrc
7
6
  class AetherConfig
8
7
 
9
- attr_accessor :verbose, :local_repository, :mavenfile, :gemfile
8
+ attr_accessor :verbose, :local_repository, :jarfile, :gemfile, :skip
10
9
 
11
10
  def initialize
12
11
  file = '.jbundlerrc'
13
12
  homefile = File.join(ENV['HOME'], file)
14
- home = YAML.load_file() if File.exists? homefile
15
- pwd = YAML.load_file(file) if File.exists? file
16
- @config = (home || {}).merge(pwd || {})
13
+ home_config = YAML.load_file(homefile) if File.exists?(homefile)
14
+ pwd_config = YAML.load_file(file) if File.exists?(file)
15
+ @config = (home_config || {}).merge(pwd_config || {})
16
+ end
17
+
18
+ if defined? JRUBY_VERSION
19
+ def jbundler_env(key)
20
+ ENV[key.upcase.gsub(/./, '_')] || java.lang.System.getProperty(key.downcase.gsub(/_/, '.')) || @config[key.downcase.sub(/^j?bundler/, '').sub(/./, '_')]
21
+ end
22
+ else
23
+ def jbundler_env(key)
24
+ ENV[key.upcase.gsub(/./, '_')] || @config[key.downcase.sub(/^j?bundler/, '').sub(/./, '_')]
25
+ end
26
+ end
27
+ private :jbundler_env
28
+
29
+ def skip
30
+ skip = jbundler_env('JBUNDLE_SKIP')
31
+ # defaults to false
32
+ @skip ||= skip && skip != 'false'
17
33
  end
18
34
 
19
35
  def verbose
20
- verbose = ENV['JBUNDLE_VERBOSE'] || @config['verbose']
36
+ verbose = jbundler_env('JBUNDLE_VERBOSE')
21
37
  # defaults to false
22
38
  @verbose ||= verbose && verbose != 'false'
23
39
  end
24
40
 
25
- def mavenfile
26
- @mavenfile ||= ENV['JBUNDLE_MAVENFILE'] || @config['mavenfile'] || 'Mvnfile'
41
+ def jarfile
42
+ if File.exists?('Mvnfile')
43
+ warn "'Mvnfile' name is deprecated, please use 'Jarfile' instead"
44
+ @jarfile = 'Mvnfile'
45
+ end
46
+ @jarfile ||= jbundler_env('JBUNDLE_JARFILE') || 'Jarfile'
27
47
  end
28
48
 
29
49
  def gemfile
30
- @gemfile ||= ENV['BUNDLE_GEMFILE'] || 'Gemfile'
50
+ @gemfile ||= jbundler_env('BUNDLE_GEMFILE') || 'Gemfile'
31
51
  end
32
52
 
33
53
  def local_repository
34
54
  # use maven default local repo as default
35
- @local_maven_repository ||= (ENV['JBUNDLE_LOCAL_REPOSITORY'] ||
36
- @config['local_repository']||
55
+ @local_maven_repository ||= (jbundler_env('JBUNDLE_LOCAL_REPOSITORY') ||
37
56
  File.join( ENV['HOME'], ".m2", "repository"))
38
57
  end
39
58
  end
@@ -41,6 +60,8 @@ module JBundler
41
60
  class AetherRuby
42
61
 
43
62
  def self.setup_classloader
63
+ require 'java'
64
+
44
65
  maven_home = File.dirname(File.dirname(Gem.bin_path('ruby-maven',
45
66
  'rmvn')))
46
67
  # TODO reduce to the libs which are really needed
@@ -81,11 +102,15 @@ module JBundler
81
102
  end
82
103
 
83
104
  def resolve
84
- @aether.resolve
105
+ @aether.resolve unless artifacts.empty?
85
106
  end
86
107
 
87
- def classpath
88
- @aether.classpath
108
+ def classpath
109
+ if artifacts.empty?
110
+ ''
111
+ else
112
+ @aether.classpath
113
+ end
89
114
  end
90
115
 
91
116
  def repositories
@@ -97,7 +122,11 @@ module JBundler
97
122
  end
98
123
 
99
124
  def resolved_coordinates
100
- @aether.resolved_coordinates
125
+ if artifacts.empty?
126
+ []
127
+ else
128
+ @aether.resolved_coordinates
129
+ end
101
130
  end
102
131
 
103
132
  def install(coordinate, file)
@@ -0,0 +1,68 @@
1
+ require 'java'
2
+ module JBundler
3
+
4
+ class AetherRuby
5
+
6
+ def self.setup_classloader
7
+ unless defined? Aether
8
+ @maven_home = File.dirname(File.dirname(Gem.bin_path('ruby-maven',
9
+ 'rmvn')))
10
+ # TODO reduce to the libs which are really needed
11
+ Dir.glob(File.join(@maven_home, 'lib', "*jar")).each {|path| require path }
12
+ require 'jbundler.jar'
13
+ java_import 'jbundler.Aether'
14
+ end
15
+ end
16
+
17
+ def initialize(local_repo = File.join( ENV['HOME'],
18
+ ".m2",
19
+ "repository"),
20
+ verbose = false)
21
+ self.class.setup_classloader
22
+ @aether = AetherRuby.new(local_repo, verbose)
23
+ end
24
+
25
+ def add_artifact(coordinate, extension = nil)
26
+ if extension
27
+ coord = coordinate.split(/:/)
28
+ coord.insert(2, extension)
29
+ @aether.add_artifact(coordinate.join(":"))
30
+ else
31
+ @aether.add_artifact(coordinate)
32
+ end
33
+ end
34
+
35
+ def add_repository(url, name = "repo_#{repos.size}")
36
+ @aether.add_repository(name, url)
37
+ end
38
+
39
+ def install(coordinate)
40
+ @aether.install(coordinate)
41
+ end
42
+
43
+ def resolve
44
+ @aether.resolve
45
+ end
46
+
47
+ def classpath
48
+ @aether.classpath
49
+ end
50
+
51
+ def dependency_map
52
+ @aether.dependency_map
53
+ end
54
+
55
+ def repositories
56
+ @aether.repositories
57
+ end
58
+
59
+ def dependency_coordinates
60
+ @aether.dependency_coordinates
61
+ end
62
+
63
+ def install(coordinate, file)
64
+ @aether.install(coordinate, file)
65
+ end
66
+
67
+ end
68
+ end