jbundler 0.0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Build.md +32 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +35 -0
- data/Gemfile.lock- +33 -0
- data/Readme.md +88 -0
- data/lib/jbundler.jar +0 -0
- data/lib/jbundler.rb +25 -20
- data/lib/jbundler.rb~ +2 -0
- data/lib/jbundler/aether.rb +44 -15
- data/lib/jbundler/aether.rb~ +68 -0
- data/lib/jbundler/classpath_file.rb +2 -4
- data/lib/jbundler/classpath_file.rb~ +207 -0
- data/lib/jbundler/gemfile_lock.rb +4 -4
- data/lib/jbundler/gemfile_lock.rb~ +17 -0
- data/lib/jbundler/maven.rb~ +252 -0
- data/lib/jbundler/maven_gemify3.rb~ +337 -0
- data/lib/jbundler/{maven_util.rb → maven_util.rb~} +4 -14
- data/lib/jbundler/maven_version.rb~ +4 -0
- data/lib/jbundler/mavenfile.rb~ +9 -0
- data/lib/jbundler/pom.rb +2 -2
- data/lib/jbundler/pom.rb~ +251 -0
- data/spec/aether_spec.rb +78 -0
- data/spec/{mavenfile_spec.rb → aether_spec.rb~} +12 -14
- data/spec/classpath_file_spec.rb +26 -24
- data/spec/classpath_file_spec.rb~ +81 -0
- data/spec/{maven_util_spec.rb → maven_util_spec.rb~} +1 -12
- data/spec/mavenfile_spec.rb~ +40 -0
- data/spec/pom_spec.rb +2 -0
- data/spec/pom_spec.rb~ +40 -0
- data/spec/setup.rb +3 -0
- data/spec/setup.rb~ +3 -0
- metadata +82 -54
- data/lib/jbundler/mavenfile.rb +0 -77
data/Build.md
ADDED
@@ -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
data/Gemfile.lock
ADDED
@@ -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)
|
data/Gemfile.lock-
ADDED
@@ -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)
|
data/Readme.md
ADDED
@@ -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.
|
data/lib/jbundler.jar
CHANGED
Binary file
|
data/lib/jbundler.rb
CHANGED
@@ -1,34 +1,39 @@
|
|
1
|
-
require '
|
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
|
-
|
9
|
-
|
10
|
-
|
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?(
|
13
|
-
|
15
|
+
if classpath_file.needs_update?(jarfile, gemfile_lock)
|
16
|
+
aether = JBundler::AetherRuby.new(config)
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
jarfile.populate_unlocked(aether)
|
19
|
+
gemfile_lock.populate_dependencies(aether)
|
20
|
+
jarfile.populate_locked(aether)
|
18
21
|
|
19
|
-
|
22
|
+
aether.resolve
|
20
23
|
|
21
|
-
|
22
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
data/lib/jbundler.rb~
ADDED
data/lib/jbundler/aether.rb
CHANGED
@@ -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, :
|
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
|
-
|
15
|
-
|
16
|
-
@config = (
|
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 =
|
36
|
+
verbose = jbundler_env('JBUNDLE_VERBOSE')
|
21
37
|
# defaults to false
|
22
38
|
@verbose ||= verbose && verbose != 'false'
|
23
39
|
end
|
24
40
|
|
25
|
-
def
|
26
|
-
|
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 ||=
|
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 ||= (
|
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
|
-
|
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
|
-
|
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
|