jbundler 0.0.1
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.
- data/MIT-LICENSE +20 -0
- data/lib/jbundler/aether.rb +108 -0
- data/lib/jbundler/classpath_file.rb +41 -0
- data/lib/jbundler/gemfile_lock.rb +40 -0
- data/lib/jbundler/maven_util.rb +56 -0
- data/lib/jbundler/mavenfile.rb +77 -0
- data/lib/jbundler/pom.rb +97 -0
- data/lib/jbundler.jar +0 -0
- data/lib/jbundler.rb +34 -0
- data/spec/classpath_file_spec.rb +81 -0
- data/spec/maven_util_spec.rb +44 -0
- data/spec/mavenfile_spec.rb +103 -0
- data/spec/pom_spec.rb +23 -0
- metadata +91 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Kristian Meier
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'java'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module JBundler
|
5
|
+
|
6
|
+
# allow yaml config in $HOME/.jbundlerrc and $PWD/.jbundlerrc
|
7
|
+
class AetherConfig
|
8
|
+
|
9
|
+
attr_accessor :verbose, :local_repository, :mavenfile, :gemfile
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
file = '.jbundlerrc'
|
13
|
+
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 || {})
|
17
|
+
end
|
18
|
+
|
19
|
+
def verbose
|
20
|
+
verbose = ENV['JBUNDLE_VERBOSE'] || @config['verbose']
|
21
|
+
# defaults to false
|
22
|
+
@verbose ||= verbose && verbose != 'false'
|
23
|
+
end
|
24
|
+
|
25
|
+
def mavenfile
|
26
|
+
@mavenfile ||= ENV['JBUNDLE_MAVENFILE'] || @config['mavenfile'] || 'Mvnfile'
|
27
|
+
end
|
28
|
+
|
29
|
+
def gemfile
|
30
|
+
@gemfile ||= ENV['BUNDLE_GEMFILE'] || 'Gemfile'
|
31
|
+
end
|
32
|
+
|
33
|
+
def local_repository
|
34
|
+
# use maven default local repo as default
|
35
|
+
@local_maven_repository ||= (ENV['JBUNDLE_LOCAL_REPOSITORY'] ||
|
36
|
+
@config['local_repository']||
|
37
|
+
File.join( ENV['HOME'], ".m2", "repository"))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class AetherRuby
|
42
|
+
|
43
|
+
def self.setup_classloader
|
44
|
+
maven_home = File.dirname(File.dirname(Gem.bin_path('ruby-maven',
|
45
|
+
'rmvn')))
|
46
|
+
# TODO reduce to the libs which are really needed
|
47
|
+
Dir.glob(File.join(maven_home, 'lib', "*jar")).each {|path| require path }
|
48
|
+
begin
|
49
|
+
require 'jbundler.jar'
|
50
|
+
rescue LoadError
|
51
|
+
# allow the classes already be added to the classloader
|
52
|
+
begin
|
53
|
+
java_import 'jbundler.Aether'
|
54
|
+
rescue NameError
|
55
|
+
# assume this happens only when working on the git clone
|
56
|
+
raise "jbundler.jar is missing - maybe you need to build it first ?"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
java_import 'jbundler.Aether'
|
60
|
+
end
|
61
|
+
|
62
|
+
def initialize(config = AetherConfig.new)
|
63
|
+
unless defined? Aether
|
64
|
+
self.class.setup_classloader
|
65
|
+
end
|
66
|
+
@aether = Aether.new(config.local_repository, config.verbose)
|
67
|
+
end
|
68
|
+
|
69
|
+
def add_artifact(coordinate, extension = nil)
|
70
|
+
if extension
|
71
|
+
coord = coordinate.split(/:/)
|
72
|
+
coord.insert(2, extension)
|
73
|
+
@aether.add_artifact(coord.join(":"))
|
74
|
+
else
|
75
|
+
@aether.add_artifact(coordinate)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def add_repository(name, url)
|
80
|
+
@aether.add_repository(name, url)
|
81
|
+
end
|
82
|
+
|
83
|
+
def resolve
|
84
|
+
@aether.resolve
|
85
|
+
end
|
86
|
+
|
87
|
+
def classpath
|
88
|
+
@aether.classpath
|
89
|
+
end
|
90
|
+
|
91
|
+
def repositories
|
92
|
+
@aether.repositories
|
93
|
+
end
|
94
|
+
|
95
|
+
def artifacts
|
96
|
+
@aether.artifacts
|
97
|
+
end
|
98
|
+
|
99
|
+
def resolved_coordinates
|
100
|
+
@aether.resolved_coordinates
|
101
|
+
end
|
102
|
+
|
103
|
+
def install(coordinate, file)
|
104
|
+
@aether.install(coordinate, file)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module JBundler
|
2
|
+
|
3
|
+
class ClasspathFile
|
4
|
+
|
5
|
+
def initialize(classpathfile = '.jbundler/classpath.rb')
|
6
|
+
@classpathfile = classpathfile
|
7
|
+
end
|
8
|
+
|
9
|
+
def require_classpath
|
10
|
+
p File.exists? @classpathfile
|
11
|
+
p @classpathfile
|
12
|
+
load File.expand_path @classpathfile
|
13
|
+
end
|
14
|
+
|
15
|
+
def mtime
|
16
|
+
File.mtime(@classpathfile)
|
17
|
+
end
|
18
|
+
|
19
|
+
def exists?
|
20
|
+
File.exists?(@classpathfile)
|
21
|
+
end
|
22
|
+
|
23
|
+
def needs_update?(mavenfile, gemfile_lock)
|
24
|
+
!mavenfile.exists? || !exists? || !mavenfile.exists_lock? || (mavenfile.mtime > mtime) || (mavenfile.mtime_lock > mtime) || (gemfile_lock.mtime > mtime)
|
25
|
+
end
|
26
|
+
|
27
|
+
def generate(classpath)
|
28
|
+
FileUtils.mkdir_p(File.dirname(@classpathfile))
|
29
|
+
File.open(@classpathfile, 'w') do |f|
|
30
|
+
f.puts "JBUNDLER_CLASSPATH = []"
|
31
|
+
classpath.split(/#{File::PATH_SEPARATOR}/).each do |path|
|
32
|
+
f.puts "JBUNDLER_CLASSPATH << '#{path}'" unless path =~ /pom$/
|
33
|
+
end
|
34
|
+
f.puts "JBUNDLER_CLASSPATH.freeze"
|
35
|
+
f.puts "JBUNDLER_CLASSPATH.each { |c| require c }"
|
36
|
+
f.close
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'jbundler/pom'
|
3
|
+
|
4
|
+
module JBundler
|
5
|
+
|
6
|
+
class GemfileLock
|
7
|
+
|
8
|
+
def initialize(mavenfile, lockfile = 'Gemfile.lock')
|
9
|
+
@mavenfile = mavenfile
|
10
|
+
@lockfile = lockfile if File.exists?(lockfile)
|
11
|
+
end
|
12
|
+
|
13
|
+
def mtime
|
14
|
+
File.mtime(@lockfile) if @lockfile
|
15
|
+
end
|
16
|
+
|
17
|
+
def populate_depedencies(aether)
|
18
|
+
if @lockfile
|
19
|
+
# assuming we run in Bundler context here
|
20
|
+
# at we have a Gemfile.lock :)
|
21
|
+
Bundler.load.specs.each do |spec|
|
22
|
+
jars = []
|
23
|
+
spec.requirements.each do |rr|
|
24
|
+
rr.split(/\n/).each do |r|
|
25
|
+
jars << r if r =~ /^jar\s/
|
26
|
+
end
|
27
|
+
end
|
28
|
+
unless jars.empty?
|
29
|
+
pom = Pom.new(spec.name, spec.version, jars, "pom")
|
30
|
+
aether.install(pom.coordinate, pom.file)
|
31
|
+
unless @mavenfile.locked?(pom.coordinate)
|
32
|
+
aether.add_artifact(pom.coordinate)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module JBundler
|
2
|
+
module MavenUtil
|
3
|
+
|
4
|
+
def to_coordinate(line)
|
5
|
+
if line =~ /^\s*(jar|pom)\s/
|
6
|
+
|
7
|
+
group_id, artifact_id, version, second_version = line.sub(/\s*[a-z]+\s+/, '').sub(/#.*/,'').gsub(/\s+/,'').gsub(/['"],/, ':').gsub(/['"]/, '').split(/:/)
|
8
|
+
mversion = second_version ? to_version(version, second_version) : to_version(version)
|
9
|
+
extension = line.strip.sub(/\s+.*/, '')
|
10
|
+
"#{group_id}:#{artifact_id}:#{extension}:#{mversion}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_version(*args)
|
15
|
+
if args.size == 0 || (args.size == 1 && args[0].nil?)
|
16
|
+
"[0,)"
|
17
|
+
else
|
18
|
+
low, high = convert(args[0])
|
19
|
+
low, high = convert(args[1], low, high) if args[1] =~ /[=~><]/
|
20
|
+
if low == high
|
21
|
+
low
|
22
|
+
else
|
23
|
+
"#{low || '[0'},#{high || ')'}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def convert(arg, low = nil, high = nil)
|
31
|
+
if arg =~ /~>/
|
32
|
+
val = arg.sub(/~>\s*/, '')
|
33
|
+
last = val.sub(/\.[^.]+$/, '.99999')
|
34
|
+
["[#{val}", "#{last}]"]
|
35
|
+
elsif arg =~ />=/
|
36
|
+
val = arg.sub(/>=\s*/, '')
|
37
|
+
["[#{val}", (nil || high)]
|
38
|
+
elsif arg =~ /<=/
|
39
|
+
val = arg.sub(/<=\s*/, '')
|
40
|
+
[(nil || low), "#{val}]"]
|
41
|
+
# treat '!' the same way as '>' since maven can not describe such range
|
42
|
+
elsif arg =~ /[!>]/
|
43
|
+
val = arg.sub(/[!>]\s*/, '')
|
44
|
+
["(#{val}", (nil || high)]
|
45
|
+
elsif arg =~ /</
|
46
|
+
val = arg.sub(/<\s*/, '')
|
47
|
+
[(nil || low), "#{val})"]
|
48
|
+
elsif arg =~ /\=/
|
49
|
+
val = arg.sub(/=\s*/, '')
|
50
|
+
["[" + val, val + '.0.0.0.0.1)']
|
51
|
+
else
|
52
|
+
[arg, arg]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'jbundler/maven_util'
|
2
|
+
module JBundler
|
3
|
+
|
4
|
+
class Mavenfile
|
5
|
+
include MavenUtil
|
6
|
+
|
7
|
+
def initialize(file = 'Mvnfile')
|
8
|
+
@file = file
|
9
|
+
@lockfile = file + ".lock"
|
10
|
+
end
|
11
|
+
|
12
|
+
def mtime
|
13
|
+
File.mtime(@file)
|
14
|
+
end
|
15
|
+
|
16
|
+
def exists?
|
17
|
+
File.exists?(@file)
|
18
|
+
end
|
19
|
+
|
20
|
+
def mtime_lock
|
21
|
+
File.mtime(@lockfile)
|
22
|
+
end
|
23
|
+
|
24
|
+
def exists_lock?
|
25
|
+
File.exists?(@lockfile)
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_lockfile
|
29
|
+
_locked = []
|
30
|
+
if exists_lock?
|
31
|
+
File.read(@lockfile).each_line do |line|
|
32
|
+
line.strip!
|
33
|
+
if line.size > 0 && !(line =~ /^\s*#/)
|
34
|
+
_locked << line
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
_locked
|
39
|
+
end
|
40
|
+
|
41
|
+
def locked
|
42
|
+
@locked ||= load_lockfile
|
43
|
+
end
|
44
|
+
|
45
|
+
def locked?(coordinate)
|
46
|
+
coord = coordinate.sub(/^([^:]+:[^:]+):.+/) { $1 }
|
47
|
+
locked.detect { |l| l.sub(/^([^:]+:[^:]+):.+/) { $1 } == coord } != nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def populate_unlocked(aether)
|
51
|
+
File.read(@file).each_line do |line|
|
52
|
+
if coord = to_coordinate(line)
|
53
|
+
unless locked?(coord)
|
54
|
+
aether.add_artifact(coord)
|
55
|
+
end
|
56
|
+
elsif line =~ /^\s*(repository|source)\s/
|
57
|
+
name, url = line.sub(/.*(repository|source)\s+/, '').gsub(/['":]/,'').split(/,/)
|
58
|
+
url = name unless url
|
59
|
+
aether.add_repository(name, url)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def populate_locked(aether)
|
65
|
+
locked.each { |l| aether.add_artifact(l) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def generate_lockfile(dependency_coordinates)
|
69
|
+
File.open(@lockfile, 'w') do |f|
|
70
|
+
dependency_coordinates.each do |d|
|
71
|
+
f.puts d.to_s
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
data/lib/jbundler/pom.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'jbundler/maven_util'
|
4
|
+
require 'java'
|
5
|
+
|
6
|
+
module JBundler
|
7
|
+
|
8
|
+
class Pom
|
9
|
+
|
10
|
+
include MavenUtil
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def temp_dir
|
15
|
+
@temp_dir ||=
|
16
|
+
begin
|
17
|
+
d = Dir.mktmpdir
|
18
|
+
at_exit { FileUtils.rm_rf(d.dup) }
|
19
|
+
d
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def writeElement(xmlWriter,element_name, text)
|
24
|
+
xmlWriter.writeStartElement(element_name.to_java)
|
25
|
+
xmlWriter.writeCharacters(text.to_java)
|
26
|
+
xmlWriter.writeEndElement
|
27
|
+
end
|
28
|
+
|
29
|
+
def java_imports
|
30
|
+
%w(
|
31
|
+
javax.xml.stream.XMLStreamWriter
|
32
|
+
javax.xml.stream.XMLOutputFactory
|
33
|
+
javax.xml.stream.XMLStreamException
|
34
|
+
).each {|i| java_import i }
|
35
|
+
end
|
36
|
+
|
37
|
+
GROUP_ID = 'ruby.bundler'
|
38
|
+
|
39
|
+
public
|
40
|
+
|
41
|
+
def coordinate
|
42
|
+
@coord ||= "#{GROUP_ID}:#{@name}:#{@packaging}:#{@version}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def file
|
46
|
+
@file
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize(name, version, deps, packaging = nil)
|
50
|
+
unless defined? XMLOutputFactory
|
51
|
+
java_imports
|
52
|
+
end
|
53
|
+
|
54
|
+
@name = name
|
55
|
+
@packaging = packaging || 'jar'
|
56
|
+
@version = version
|
57
|
+
|
58
|
+
@file = File.join(temp_dir, 'pom.xml')
|
59
|
+
|
60
|
+
out = java.io.BufferedOutputStream.new(java.io.FileOutputStream.new(@file.to_java))
|
61
|
+
outputFactory = XMLOutputFactory.newFactory()
|
62
|
+
xmlStreamWriter = outputFactory.createXMLStreamWriter(out)
|
63
|
+
xmlStreamWriter.writeStartDocument
|
64
|
+
xmlStreamWriter.writeStartElement("project")
|
65
|
+
|
66
|
+
writeElement(xmlStreamWriter,"modelVersion","4.0.0")
|
67
|
+
writeElement(xmlStreamWriter,"groupId", GROUP_ID)
|
68
|
+
writeElement(xmlStreamWriter,"artifactId", name)
|
69
|
+
writeElement(xmlStreamWriter,"version", version.to_s.to_java)
|
70
|
+
writeElement(xmlStreamWriter,"packaging", packaging) if packaging
|
71
|
+
|
72
|
+
xmlStreamWriter.writeStartElement("dependencies".to_java)
|
73
|
+
|
74
|
+
deps.each do |line|
|
75
|
+
if coord = to_coordinate(line)
|
76
|
+
group_id, artifact_id, extension, version = coord.split(/:/)
|
77
|
+
|
78
|
+
xmlStreamWriter.writeStartElement("dependency".to_java)
|
79
|
+
writeElement(xmlStreamWriter,"groupId", group_id)
|
80
|
+
writeElement(xmlStreamWriter,"artifactId", artifact_id)
|
81
|
+
writeElement(xmlStreamWriter,"version", version)
|
82
|
+
|
83
|
+
writeElement(xmlStreamWriter,"type", extension) if extension != 'jar'
|
84
|
+
xmlStreamWriter.writeEndElement #dependency
|
85
|
+
end
|
86
|
+
end
|
87
|
+
xmlStreamWriter.writeEndElement #dependencies
|
88
|
+
|
89
|
+
xmlStreamWriter.writeEndElement #project
|
90
|
+
|
91
|
+
xmlStreamWriter.writeEndDocument
|
92
|
+
xmlStreamWriter.close
|
93
|
+
out.close
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
data/lib/jbundler.jar
ADDED
Binary file
|
data/lib/jbundler.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'jbundler/mavenfile'
|
2
|
+
require 'jbundler/classpath_file'
|
3
|
+
require 'jbundler/gemfile_lock'
|
4
|
+
require 'jbundler/aether'
|
5
|
+
|
6
|
+
config = JBundler::AetherConfig.new
|
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')
|
11
|
+
|
12
|
+
if classpath_file.needs_update?(mavenfile, gemfile_lock)
|
13
|
+
aether = JBundler::AetherRuby.new(config)
|
14
|
+
|
15
|
+
mavenfile.populate_unlocked(aether)
|
16
|
+
gemfile_lock.populate_depedencies(aether)
|
17
|
+
mavenfile.populate_locked(aether)
|
18
|
+
|
19
|
+
aether.resolve
|
20
|
+
|
21
|
+
classpath_file.generate(aether.classpath)
|
22
|
+
mavenfile.generate_lockfile(aether.resolved_coordinates)
|
23
|
+
end
|
24
|
+
|
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}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'jbundler/classpath_file'
|
2
|
+
require 'jbundler/mavenfile'
|
3
|
+
require 'jbundler/gemfile_lock'
|
4
|
+
|
5
|
+
describe JBundler::ClasspathFile do
|
6
|
+
|
7
|
+
let(:workdir) { 'target' }
|
8
|
+
let(:mfile) { File.join(workdir, 'tmp-mvnfile') }
|
9
|
+
let(:gfile_lock) { File.join(workdir, 'tmp-gemfile.lock') }
|
10
|
+
let(:mfile_lock) { mfile + ".lock"}
|
11
|
+
let(:cpfile) { File.join(workdir, 'tmp-cp.rb') }
|
12
|
+
let(:mavenfile) { JBundler::Mavenfile.new(mfile) }
|
13
|
+
let(:gemfile_lock) { JBundler::GemfileLock.new(mavenfile, gfile_lock) }
|
14
|
+
subject { JBundler::ClasspathFile.new(cpfile) }
|
15
|
+
|
16
|
+
before do
|
17
|
+
Dir[File.join(workdir, "tmp*")].each { |f| FileUtils.rm_f f }
|
18
|
+
FileUtils.touch gfile_lock #assume there is always a Gemfile.lock
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'needs update when all files are missing' do
|
22
|
+
subject.needs_update?(mavenfile,gemfile_lock).must_equal true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'needs update when only mavenfile' do
|
26
|
+
FileUtils.touch mfile
|
27
|
+
subject.needs_update?(mavenfile,gemfile_lock).must_equal true
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'needs update when mavenfilelock is missing' do
|
31
|
+
FileUtils.touch mfile
|
32
|
+
FileUtils.touch cpfile
|
33
|
+
subject.needs_update?(mavenfile,gemfile_lock).must_equal true
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'needs no update when classpath file is the youngest' do
|
37
|
+
FileUtils.touch mfile
|
38
|
+
FileUtils.touch mfile_lock
|
39
|
+
FileUtils.touch cpfile
|
40
|
+
subject.needs_update?(mavenfile,gemfile_lock).must_equal false
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'needs update when maven file is the youngest' do
|
44
|
+
FileUtils.touch mfile_lock
|
45
|
+
FileUtils.touch cpfile
|
46
|
+
sleep 1
|
47
|
+
FileUtils.touch mfile
|
48
|
+
subject.needs_update?(mavenfile,gemfile_lock).must_equal true
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'needs update when maven lockfile is the youngest' do
|
52
|
+
FileUtils.touch mfile
|
53
|
+
FileUtils.touch cpfile
|
54
|
+
sleep 1
|
55
|
+
FileUtils.touch mfile_lock
|
56
|
+
subject.needs_update?(mavenfile,gemfile_lock).must_equal true
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'needs update when gem lockfile is the youngest' do
|
60
|
+
FileUtils.touch mfile
|
61
|
+
FileUtils.touch cpfile
|
62
|
+
FileUtils.touch mfile_lock
|
63
|
+
sleep 1
|
64
|
+
FileUtils.touch gfile_lock
|
65
|
+
subject.needs_update?(mavenfile,gemfile_lock).must_equal true
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'generates a classpath ruby file' do
|
69
|
+
subject.generate("a:b:c:d:f:".gsub(/:/, File::PATH_SEPARATOR))
|
70
|
+
File.read(cpfile).must_equal <<-EOF
|
71
|
+
JBUNDLER_CLASSPATH = []
|
72
|
+
JBUNDLER_CLASSPATH << 'a'
|
73
|
+
JBUNDLER_CLASSPATH << 'b'
|
74
|
+
JBUNDLER_CLASSPATH << 'c'
|
75
|
+
JBUNDLER_CLASSPATH << 'd'
|
76
|
+
JBUNDLER_CLASSPATH << 'f'
|
77
|
+
JBUNDLER_CLASSPATH.freeze
|
78
|
+
JBUNDLER_CLASSPATH.each { |c| require c }
|
79
|
+
EOF
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'jbundler/maven_util'
|
2
|
+
class A
|
3
|
+
include JBundler::MavenUtil
|
4
|
+
end
|
5
|
+
|
6
|
+
describe JBundler::MavenUtil do
|
7
|
+
|
8
|
+
subject { A.new }
|
9
|
+
|
10
|
+
it 'should convert ruby version to maven version ranges' do
|
11
|
+
subject.to_version.must_equal "[0,)"
|
12
|
+
subject.to_version('!2.3.4').must_equal "(2.3.4,)"
|
13
|
+
subject.to_version('=2.3.4').must_equal "[2.3.4,2.3.4.0.0.0.0.1)"
|
14
|
+
subject.to_version('~>1.8.2').must_equal "[1.8.2,1.8.99999]"
|
15
|
+
subject.to_version('~>1.8').must_equal "[1.8,1.99999]"
|
16
|
+
subject.to_version('>1.2').must_equal "(1.2,)"
|
17
|
+
subject.to_version('<1.2').must_equal "[0,1.2)"
|
18
|
+
subject.to_version('>=1.2').must_equal "[1.2,)"
|
19
|
+
subject.to_version('<=1.2').must_equal "[0,1.2]"
|
20
|
+
subject.to_version('>=1.2', '<2.0').must_equal "[1.2,2.0)"
|
21
|
+
subject.to_version('>=1.2', '<=2.0').must_equal "[1.2,2.0]"
|
22
|
+
subject.to_version('>1.2', '<2.0').must_equal "(1.2,2.0)"
|
23
|
+
subject.to_version('>1.2', '<=2.0').must_equal "(1.2,2.0]"
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should keep maven version and ranges as they are' do
|
27
|
+
subject.to_version('1.2.3').must_equal "1.2.3"
|
28
|
+
subject.to_version('(1,2)').must_equal "(1,2)"
|
29
|
+
subject.to_version('[1,2)').must_equal "[1,2)"
|
30
|
+
subject.to_version('(1,2]').must_equal "(1,2]"
|
31
|
+
subject.to_version('[1,2]').must_equal "[1,2]"
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should convert pom of jar deps to maven coordinate' do
|
35
|
+
subject.to_coordinate('something "a:b"').must_be_nil
|
36
|
+
subject.to_coordinate('#jar "a:b"').must_be_nil
|
37
|
+
subject.to_coordinate('jar "a:b" # bla').must_equal "a:b:jar:[0,)"
|
38
|
+
subject.to_coordinate("pom 'b:c', '!2.3.4'").must_equal "b:c:pom:(2.3.4,)"
|
39
|
+
subject.to_coordinate('jar "c:d", "2.3.4"').must_equal "c:d:jar:2.3.4"
|
40
|
+
subject.to_coordinate("jar 'd:e', '~>1.8.2'").must_equal "d:e:jar:[1.8.2,1.8.99999]"
|
41
|
+
subject.to_coordinate('pom "e:f", "[1.8,1.9.9)"').must_equal "e:f:pom:[1.8,1.9.9)"
|
42
|
+
subject.to_coordinate('pom "f:g", ">1.2", "<=2.0"').must_equal "f:g:pom:(1.2,2.0]"
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'jbundler/classpath_file'
|
2
|
+
require 'jbundler/mavenfile'
|
3
|
+
require 'jbundler/gemfile_lock'
|
4
|
+
require 'jbundler/aether'
|
5
|
+
|
6
|
+
describe JBundler::Mavenfile do
|
7
|
+
|
8
|
+
let(:workdir) { 'target' }
|
9
|
+
let(:mfile) { File.join(workdir, 'tmp-mvnfile') }
|
10
|
+
let(:mfile_lock) { mfile + ".lock"}
|
11
|
+
let(:aether) { JBundler::AetherRuby.new }
|
12
|
+
subject { JBundler::Mavenfile.new(mfile) }
|
13
|
+
|
14
|
+
before do
|
15
|
+
Dir[File.join(workdir, "tmp*")].each { |f| FileUtils.rm_f f }
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'generates lockfile' do
|
19
|
+
subject.generate_lockfile(%w( a b c d e f))
|
20
|
+
File.read(mfile_lock).must_equal <<-EOF
|
21
|
+
a
|
22
|
+
b
|
23
|
+
c
|
24
|
+
d
|
25
|
+
e
|
26
|
+
f
|
27
|
+
EOF
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'check locked coordinate' do
|
31
|
+
File.open(mfile_lock, 'w') do |f|
|
32
|
+
f.write <<-EOF
|
33
|
+
a:b:pom:3
|
34
|
+
a:c:jar:1
|
35
|
+
EOF
|
36
|
+
end
|
37
|
+
subject.locked.must_equal ["a:b:pom:3", "a:c:jar:1"]
|
38
|
+
subject.locked?("a:b:pom:321").must_equal true
|
39
|
+
subject.locked?("a:b:jar:321").must_equal true
|
40
|
+
subject.locked?("a:d:jar:432").must_equal false
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'populate repositories' do
|
44
|
+
File.open(mfile, 'w') do |f|
|
45
|
+
f.write <<-EOF
|
46
|
+
repository :first, "http://example.com/repo"
|
47
|
+
source 'second', "http://example.org/repo"
|
48
|
+
EOF
|
49
|
+
end
|
50
|
+
subject.populate_unlocked aether
|
51
|
+
aether.repositories.size.must_equal 3
|
52
|
+
aether.artifacts.size.must_equal 0
|
53
|
+
aether.repositories[0].id.must_equal "central"
|
54
|
+
aether.repositories[1].id.must_equal "first"
|
55
|
+
aether.repositories[2].id.must_equal "second"
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'populate artifacts without locked' do
|
59
|
+
File.open(mfile, 'w') do |f|
|
60
|
+
f.write <<-EOF
|
61
|
+
jar 'a:b', '123'
|
62
|
+
pom 'x:y', '987'
|
63
|
+
EOF
|
64
|
+
end
|
65
|
+
subject.populate_unlocked aether
|
66
|
+
aether.repositories.size.must_equal 1 # central
|
67
|
+
aether.artifacts.size.must_equal 2
|
68
|
+
aether.artifacts[0].to_s.must_equal "a:b:jar:123"
|
69
|
+
aether.artifacts[1].to_s.must_equal "x:y:pom:987"
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'populate artifacts with locked' do
|
73
|
+
File.open(mfile, 'w') do |f|
|
74
|
+
f.write <<-EOF
|
75
|
+
jar 'a:b', '123'
|
76
|
+
pom 'x:y', '987'
|
77
|
+
EOF
|
78
|
+
end
|
79
|
+
File.open(mfile_lock, 'w') do |f|
|
80
|
+
f.write <<-EOF
|
81
|
+
a:b:jar:432
|
82
|
+
EOF
|
83
|
+
end
|
84
|
+
|
85
|
+
subject.populate_unlocked aether
|
86
|
+
aether.repositories.size.must_equal 1 # central
|
87
|
+
aether.artifacts.size.must_equal 1
|
88
|
+
aether.artifacts[0].to_s.must_equal "x:y:pom:987"
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'populate locked artifacts' do
|
92
|
+
File.open(mfile_lock, 'w') do |f|
|
93
|
+
f.write <<-EOF
|
94
|
+
a:b:jar:432
|
95
|
+
EOF
|
96
|
+
end
|
97
|
+
|
98
|
+
subject.populate_locked aether
|
99
|
+
aether.repositories.size.must_equal 1 # central
|
100
|
+
aether.artifacts.size.must_equal 1
|
101
|
+
aether.artifacts[0].to_s.must_equal "a:b:jar:432"
|
102
|
+
end
|
103
|
+
end
|
data/spec/pom_spec.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'jbundler/pom'
|
2
|
+
|
3
|
+
describe JBundler::Pom do
|
4
|
+
|
5
|
+
it 'should create jar pom without deps' do
|
6
|
+
pom = JBundler::Pom.new("first", "1", [])
|
7
|
+
File.read(pom.file).must_equal "<?xml version=\"1.0\" ?><project><modelVersion>4.0.0</modelVersion><groupId>ruby.bundler</groupId><artifactId>first</artifactId><version>1</version><dependencies></dependencies></project>"
|
8
|
+
pom.coordinate.must_equal "ruby.bundler:first:jar:1"
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should create pom-pom without deps' do
|
12
|
+
pom = JBundler::Pom.new("first", "1", [], 'pom')
|
13
|
+
File.read(pom.file).must_equal "<?xml version=\"1.0\" ?><project><modelVersion>4.0.0</modelVersion><groupId>ruby.bundler</groupId><artifactId>first</artifactId><version>1</version><packaging>pom</packaging><dependencies></dependencies></project>"
|
14
|
+
pom.coordinate.must_equal "ruby.bundler:first:pom:1"
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should create jar pom without deps' do
|
18
|
+
pom = JBundler::Pom.new("second", "1", ["jar \"org.jruby:jruby-core\", '~>1.7.0'"])
|
19
|
+
File.read(pom.file).must_equal "<?xml version=\"1.0\" ?><project><modelVersion>4.0.0</modelVersion><groupId>ruby.bundler</groupId><artifactId>second</artifactId><version>1</version><dependencies><dependency><groupId>org.jruby</groupId><artifactId>jruby-core</artifactId><version>[1.7.0,1.7.99999]</version></dependency></dependencies></project>"
|
20
|
+
pom.coordinate.must_equal "ruby.bundler:second:jar:1"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jbundler
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kristian Meier
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2012-04-17 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: ruby-maven
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - "="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 3.0.3.0.29.0.pre
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: thor
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - "="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.14.6
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
description: using embedded maven to add jar support to bundler and add bundler like handling of version ranges to maven
|
38
|
+
email:
|
39
|
+
- m.kristian@web.de
|
40
|
+
executables: []
|
41
|
+
|
42
|
+
extensions: []
|
43
|
+
|
44
|
+
extra_rdoc_files: []
|
45
|
+
|
46
|
+
files:
|
47
|
+
- MIT-LICENSE
|
48
|
+
- lib/jbundler.rb
|
49
|
+
- lib/jbundler.jar
|
50
|
+
- lib/jbundler/mavenfile.rb
|
51
|
+
- lib/jbundler/pom.rb
|
52
|
+
- lib/jbundler/maven_util.rb
|
53
|
+
- lib/jbundler/classpath_file.rb
|
54
|
+
- lib/jbundler/aether.rb
|
55
|
+
- lib/jbundler/gemfile_lock.rb
|
56
|
+
- spec/classpath_file_spec.rb
|
57
|
+
- spec/mavenfile_spec.rb
|
58
|
+
- spec/pom_spec.rb
|
59
|
+
- spec/maven_util_spec.rb
|
60
|
+
homepage:
|
61
|
+
licenses:
|
62
|
+
- MIT-LICENSE
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: "0"
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.8.9
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: bundler support for maven or/and maven support for bundler
|
87
|
+
test_files:
|
88
|
+
- spec/classpath_file_spec.rb
|
89
|
+
- spec/mavenfile_spec.rb
|
90
|
+
- spec/pom_spec.rb
|
91
|
+
- spec/maven_util_spec.rb
|