jbundler 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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