jruby-bundler 0.9.5

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,153 @@
1
+ #
2
+ # Copyright (C) 2013 Christian Meier
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+ require 'fileutils'
22
+ require 'tempfile'
23
+ require 'maven/tools/coordinate'
24
+ require 'securerandom'
25
+
26
+ module JBundler
27
+
28
+ class Pom
29
+
30
+ include Maven::Tools::Coordinate
31
+
32
+ private
33
+
34
+ def temp_dir
35
+ @temp_dir ||=
36
+ begin
37
+ # on travis the mktmpdir failed
38
+ d = Dir.mktmpdir rescue FileUtils.mkdir( ".tmp" + SecureRandom.hex( 12) ).first
39
+ at_exit { FileUtils.rm_rf(d.dup) }
40
+ # for jruby-1.7.4 1.8 mode add expand_path
41
+ File.expand_path( d )
42
+ end
43
+ end
44
+
45
+ def writeElement(xmlWriter,element_name, text)
46
+ xmlWriter.writeStartElement(element_name.to_java)
47
+ xmlWriter.writeCharacters(text.to_java)
48
+ xmlWriter.writeEndElement
49
+ end
50
+
51
+ def java_imports
52
+ %w(
53
+ javax.xml.stream.XMLStreamWriter
54
+ javax.xml.stream.XMLOutputFactory
55
+ javax.xml.stream.XMLStreamException
56
+ ).each {|i| java_import i }
57
+ end
58
+
59
+ GROUP_ID = 'ruby.bundler'
60
+
61
+ def start_write_pom( out, name, version, packaging )
62
+ outputFactory = XMLOutputFactory.newFactory()
63
+ xmlStreamWriter = outputFactory.createXMLStreamWriter( out )
64
+
65
+ xmlStreamWriter.writeStartDocument
66
+ xmlStreamWriter.writeStartElement("project")
67
+
68
+ writeElement(xmlStreamWriter,"modelVersion","4.0.0")
69
+ writeElement(xmlStreamWriter,"groupId", GROUP_ID)
70
+ writeElement(xmlStreamWriter,"artifactId", name)
71
+ writeElement(xmlStreamWriter,"version", version.to_s.to_java)
72
+ writeElement(xmlStreamWriter,"packaging", packaging) if packaging
73
+ xmlStreamWriter
74
+ end
75
+
76
+ def to_classifier_version( coords )
77
+ if coords.size == 4
78
+ [ nil, coords[3] ]
79
+ else
80
+ [ coords[3], coords[4] ]
81
+ end
82
+ end
83
+
84
+ def write_dep( xmlStreamWriter, coord )
85
+ coords = coord.split(/:/)
86
+ group_id = coords[0]
87
+ artifact_id = coords[1]
88
+ extension = coords[2]
89
+ classifier, version = to_classifier_version( coords )
90
+
91
+ xmlStreamWriter.writeStartElement("dependency".to_java)
92
+ writeElement(xmlStreamWriter,"groupId", group_id)
93
+ writeElement(xmlStreamWriter,"artifactId", artifact_id)
94
+ writeElement(xmlStreamWriter,"version", version)
95
+
96
+ writeElement(xmlStreamWriter,"type", extension) if extension != 'jar'
97
+ writeElement(xmlStreamWriter,"classifier", classifier) if classifier
98
+ xmlStreamWriter.writeEndElement #dependency
99
+ end
100
+
101
+ def write_dependencies( xmlStreamWriter, deps )
102
+ xmlStreamWriter.writeStartElement("dependencies".to_java)
103
+
104
+ deps.each do |line|
105
+ coord = to_coordinate(line)
106
+ write_dep( xmlStreamWriter, coord ) if coord
107
+ end
108
+
109
+ xmlStreamWriter.writeEndElement #dependencies
110
+ end
111
+
112
+ def end_write_pom( xmlStreamWriter )
113
+ xmlStreamWriter.writeEndElement #project
114
+
115
+ xmlStreamWriter.writeEndDocument
116
+ xmlStreamWriter.close
117
+ end
118
+
119
+ public
120
+
121
+ def coordinate
122
+ @coord ||= "#{GROUP_ID}:#{@name}:#{@packaging}:#{@version}"
123
+ end
124
+
125
+ def file
126
+ @file
127
+ end
128
+
129
+ def initialize(name, version, deps, packaging = nil)
130
+ unless defined? XMLOutputFactory
131
+ java_imports
132
+ end
133
+
134
+ @name = name
135
+ @packaging = packaging || 'jar'
136
+ @version = version
137
+
138
+ @file = File.join(temp_dir, 'pom.xml')
139
+
140
+ out = java.io.BufferedOutputStream.new( java.io.FileOutputStream.new( @file.to_java ) )
141
+
142
+ xmlStreamWriter = start_write_pom( out, name, version, packaging )
143
+
144
+ write_dependencies( xmlStreamWriter, deps )
145
+
146
+ end_write_pom( xmlStreamWriter )
147
+
148
+ ensure
149
+ out.close
150
+ end
151
+
152
+ end
153
+ end
@@ -0,0 +1,71 @@
1
+ require 'maven/ruby/maven'
2
+ module JBundler
3
+
4
+ class PomRunner
5
+
6
+ def initialize( config )
7
+ @config = config
8
+ end
9
+
10
+ def method_missing( m, *args )
11
+ result = @config[ m ] || @config[ m.to_s ]
12
+ result.nil? ? super : result
13
+ end
14
+
15
+ def maven_new
16
+ m = Maven::Ruby::Maven.new
17
+ m.property( 'base.dir', File.expand_path( basedir ) )
18
+ m.property( 'work.dir', File.expand_path( workdir ) ) if workdir
19
+ m.property( 'verbose', debug || verbose )
20
+ if debug
21
+ m.options[ '-X' ] = nil
22
+ elsif verbose
23
+ m.options[ '-e' ] = nil
24
+ else
25
+ m.options[ '-q' ] = nil
26
+ end
27
+ m.verbose = debug
28
+ m
29
+ end
30
+ private :maven_new
31
+
32
+ def maven
33
+ @m ||= maven_new
34
+ end
35
+
36
+ def basedir
37
+ File.expand_path( '.' )
38
+ end
39
+
40
+ def workdir
41
+ @config[ 'workdir' ]
42
+ end
43
+
44
+ def work_dir
45
+ # needs default here
46
+ workdir || 'pkg'
47
+ end
48
+
49
+ def debug
50
+ @config[ 'debug' ] || false
51
+ end
52
+
53
+ def verbose
54
+ @config[ 'verbose' ] || false
55
+ end
56
+
57
+ def clean?
58
+ @config[ 'clean' ] || false
59
+ end
60
+
61
+ def pom_file
62
+ raise 'overwrite this method'
63
+ end
64
+
65
+ def exec( *args )
66
+ maven.options[ '-f' ] ||= pom_file
67
+ args.unshift :clean if clean?
68
+ maven.exec( *args )
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,53 @@
1
+ require 'jbundler/configurator'
2
+ require 'jbundler/classpath_file'
3
+ require 'jbundler/vendor'
4
+ require 'jbundler/gemfile_lock'
5
+ require 'maven/tools/jarfile'
6
+ require 'maven/ruby/maven'
7
+ require 'fileutils'
8
+ module JBundler
9
+ class Show
10
+
11
+ def initialize( config )
12
+ @config = config
13
+ @classpath_file = JBundler::ClasspathFile.new( @config.classpath_file )
14
+ end
15
+
16
+ def show_classpath
17
+ return if ! @config.verbose
18
+ vendor = JBundler::Vendor.new(@config.vendor_dir)
19
+ if vendor.vendored?
20
+ vendor.require_jars
21
+ warn "complete classpath:"
22
+ $CLASSPATH.each do |path|
23
+ warn "\t#{path}"
24
+ end
25
+ else
26
+ @classpath_file.load_classpath
27
+ warn ''
28
+ warn 'jbundler provided classpath:'
29
+ warn '----------------'
30
+ JBUNDLER_JRUBY_CLASSPATH.each do |path|
31
+ warn "#{path}"
32
+ end
33
+ warn ''
34
+ warn 'jbundler runtime classpath:'
35
+ warn '---------------------------'
36
+ JBUNDLER_CLASSPATH.each do |path|
37
+ warn "#{path}"
38
+ end
39
+ warn ''
40
+ warn 'jbundler test classpath:'
41
+ warn '------------------------'
42
+ if JBUNDLER_TEST_CLASSPATH.empty?
43
+ warn "\t--- empty ---"
44
+ else
45
+ JBUNDLER_TEST_CLASSPATH.each do |path|
46
+ warn "#{path}"
47
+ end
48
+ end
49
+ warn ''
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,31 @@
1
+ require 'jbundler/configurator'
2
+ require 'maven/ruby/maven'
3
+ require 'fileutils'
4
+ module JBundler
5
+ class Tree
6
+
7
+ def initialize( config )
8
+ @config = Configurator.new( config )
9
+ end
10
+
11
+ def show_it( debug = false )
12
+ m = Maven::Ruby::Maven.new
13
+ m.options[ '-f' ] = File.join( File.dirname( __FILE__ ),
14
+ '.polyglot.dependency_pom.rb' )
15
+ m.options[ '-q' ] = nil unless debug
16
+ m.verbose = debug
17
+
18
+ @config.configure( m )
19
+
20
+ puts '...'
21
+
22
+ tree = File.join( File.expand_path( @config.work_dir ),
23
+ 'tree.txt' )
24
+ m.property( 'jbundler.outputFile', tree )
25
+
26
+ m.exec( 'dependency:tree' )
27
+
28
+ puts File.read( tree )
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,75 @@
1
+ require 'jar_installer'
2
+ module JBundler
3
+ class Vendor
4
+
5
+ def initialize( dir )
6
+ @dir = File.expand_path( dir )
7
+ @jars_lock = File.join( @dir, 'Jars.lock' )
8
+ end
9
+
10
+ def vendored?
11
+ File.exists?( @dir ) && Dir[ File.join( @dir, '*' ) ].size > 0
12
+ end
13
+
14
+ def require_jars
15
+ if File.exists?(@jars_lock)
16
+ $LOAD_PATH << @dir unless $LOAD_PATH.include? @dir
17
+ ENV_JAVA['jars.lock'] = @jars_lock
18
+ Jars.require_jars_lock!
19
+ true
20
+ else
21
+ require_jars_legacy
22
+ end
23
+ end
24
+
25
+ def require_jars_legacy
26
+ jars = File.join( @dir, 'jbundler.rb' )
27
+ if File.exists?( jars )
28
+ $LOAD_PATH << @dir unless $LOAD_PATH.include? @dir
29
+ require jars
30
+ else
31
+ Dir[ File.join( @dir, '**', '*' ) ].each do |f|
32
+ require f
33
+ end
34
+ Jars.no_more_warnings
35
+ true
36
+ end
37
+ end
38
+
39
+ def clear
40
+ FileUtils.mkdir_p( @dir )
41
+ Dir[ File.join( @dir, '*' ) ].each do |f|
42
+ FileUtils.rm_rf( f )
43
+ end
44
+ end
45
+
46
+ def vendor_dependencies( deps )
47
+ FileUtils.mkdir_p( @dir )
48
+ File.open(@jars_lock, 'w') do |f|
49
+ deps.each do |dep|
50
+ if dep.scope == :runtime
51
+ target = File.join( @dir, dep.path )
52
+ FileUtils.mkdir_p( File.dirname( target ) )
53
+ FileUtils.cp( dep.file, target )
54
+ line = dep.gav + ':runtime:'
55
+ f.puts line
56
+ end
57
+ end
58
+ end
59
+ ['jbundler.rb', 'jbundle.rb'].each do |filename|
60
+ File.write( File.join( @dir, filename ),
61
+ "ENV['JARS_LOCK'] = File.join( File.dirname( __FILE__ ), 'Jars.lock' )\nrequire 'jars/setup'" )
62
+ end
63
+ end
64
+
65
+ def setup( classpath_file )
66
+ classpath_file.require_classpath
67
+ FileUtils.mkdir_p( @dir )
68
+ JBUNDLER_CLASSPATH.each do |f|
69
+ FileUtils.cp( f, File.join( @dir,
70
+ File.basename( f ) ) )
71
+ end
72
+ end
73
+ end
74
+ end
75
+
data/lib/jbundler.rb ADDED
@@ -0,0 +1,73 @@
1
+ #
2
+ # Copyright (C) 2013 Christian Meier
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ # this software and associated documentation files (the "Software"), to deal in
6
+ # the Software without restriction, including without limitation the rights to
7
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ # the Software, and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ #
21
+
22
+ require 'jbundler/context'
23
+ require 'jbundler/lock_down'
24
+
25
+ module JBundler
26
+
27
+ def self.context
28
+ @context ||= JBundler::Context.new
29
+ end
30
+
31
+ def self.setup_test
32
+ context.classpath.require_test_classpath
33
+ context.config
34
+ end
35
+
36
+ def self.require_jars
37
+ if context.vendor.vendored?
38
+ jars = context.vendor.require_jars
39
+ if context.config.verbose
40
+ warn "jbundler classpath:"
41
+ jars.each do |path|
42
+ warn "\t#{path}"
43
+ end
44
+ end
45
+ elsif context.classpath.exists? && context.jarfile.exists_lock?
46
+ require 'java'
47
+ context.classpath.require_classpath
48
+ if context.config.verbose
49
+ warn "jbundler classpath:"
50
+ JBUNDLER_CLASSPATH.each do |path|
51
+ warn "\t#{path}"
52
+ end
53
+ end
54
+ Jars.no_more_warnings
55
+ end
56
+ end
57
+
58
+ def self.install( debug = false, verbose = false )
59
+ jbundler = JBundler::LockDown.new( context.config )
60
+ msg = jbundler.lock_down( false, debug, verbose )
61
+ puts msg if msg
62
+ end
63
+
64
+ def self.setup
65
+ if context.config.skip
66
+ warn "skip jbundler setup" if context.config.verbose
67
+ else
68
+ require_jars
69
+ end
70
+ end
71
+ end
72
+
73
+ JBundler.setup
@@ -0,0 +1,138 @@
1
+ load File.expand_path(File.join('spec', 'setup.rb'))
2
+ require 'jbundler/classpath_file'
3
+ require 'maven/tools/jarfile'
4
+ require 'jbundler/gemfile_lock'
5
+
6
+ describe JBundler::ClasspathFile do
7
+
8
+ let(:workdir) { File.join('pkg', 'tmp') }
9
+ let(:jfile) { File.join(workdir, 'jarfile') }
10
+ let(:gfile_lock) { File.join(workdir, 'gemfile.lock') }
11
+ let(:jfile_lock) { jfile + ".lock"}
12
+ let(:cpfile) { File.join(workdir, 'cp.rb') }
13
+ let(:jarfile) { Maven::Tools::Jarfile.new(jfile) }
14
+ let(:gemfile_lock) { JBundler::GemfileLock.new(jarfile, gfile_lock) }
15
+ subject { JBundler::ClasspathFile.new(cpfile) }
16
+
17
+ before do
18
+ FileUtils.mkdir_p(workdir)
19
+ Dir[File.join(workdir, '*')].each { |f| FileUtils.rm_f f }
20
+ end
21
+
22
+ it 'needs no update when all files are missing' do
23
+ subject.needs_update?(jarfile, gemfile_lock).must_equal false
24
+ end
25
+
26
+ it 'needs update when only gemfile' do
27
+ FileUtils.touch gfile_lock
28
+ subject.needs_update?(jarfile, gemfile_lock).must_equal true
29
+ end
30
+
31
+ it 'needs update when only jarfile' do
32
+ FileUtils.touch jfile
33
+ subject.needs_update?(jarfile, gemfile_lock).must_equal true
34
+ end
35
+
36
+ it 'needs update when jarfilelock is missing' do
37
+ FileUtils.touch gfile_lock
38
+ FileUtils.touch jfile
39
+ FileUtils.touch cpfile
40
+ subject.needs_update?(jarfile, gemfile_lock).must_equal true
41
+ end
42
+
43
+ it 'needs no update when classpath file is the youngest' do
44
+ FileUtils.touch jfile
45
+ FileUtils.touch jfile_lock
46
+ FileUtils.touch cpfile
47
+ subject.needs_update?(jarfile, gemfile_lock).must_equal false
48
+ end
49
+
50
+ it 'needs update when jar file is the youngest' do
51
+ FileUtils.touch gfile_lock
52
+ FileUtils.touch jfile_lock
53
+ FileUtils.touch cpfile
54
+ sleep 1
55
+ FileUtils.touch jfile
56
+ subject.needs_update?(jarfile, gemfile_lock).must_equal true
57
+ end
58
+
59
+ it 'needs update when jar lockfile is the youngest' do
60
+ FileUtils.touch gfile_lock
61
+ FileUtils.touch jfile
62
+ FileUtils.touch cpfile
63
+ sleep 1
64
+ FileUtils.touch jfile_lock
65
+ subject.needs_update?(jarfile, gemfile_lock).must_equal true
66
+ end
67
+
68
+ it 'needs update when gem lockfile is the youngest' do
69
+ FileUtils.touch jfile
70
+ FileUtils.touch cpfile
71
+ FileUtils.touch jfile_lock
72
+ sleep 1
73
+ FileUtils.touch gfile_lock
74
+ subject.needs_update?(jarfile, gemfile_lock).must_equal true
75
+ end
76
+
77
+ it 'generates a classpath ruby file without localrepo' do
78
+ subject.generate("a:b:c:d:f:".split(File::PATH_SEPARATOR) )
79
+ File.read(cpfile).must_equal <<-EOF
80
+ JBUNDLER_JRUBY_CLASSPATH = []
81
+ JBUNDLER_JRUBY_CLASSPATH.freeze
82
+ JBUNDLER_TEST_CLASSPATH = []
83
+ JBUNDLER_TEST_CLASSPATH.freeze
84
+ JBUNDLER_CLASSPATH = []
85
+ JBUNDLER_CLASSPATH << 'a'
86
+ JBUNDLER_CLASSPATH << 'b'
87
+ JBUNDLER_CLASSPATH << 'c'
88
+ JBUNDLER_CLASSPATH << 'd'
89
+ JBUNDLER_CLASSPATH << 'f'
90
+ JBUNDLER_CLASSPATH.freeze
91
+ EOF
92
+ end
93
+
94
+ it 'generates a classpath ruby file with localrepo' do
95
+ subject.generate("a:b:c:d:f:".split(File::PATH_SEPARATOR), [], [], '/tmp')
96
+ File.read(cpfile).must_equal <<-EOF
97
+ require 'jar_dependencies'
98
+ JBUNDLER_LOCAL_REPO = Jars.home
99
+ JBUNDLER_JRUBY_CLASSPATH = []
100
+ JBUNDLER_JRUBY_CLASSPATH.freeze
101
+ JBUNDLER_TEST_CLASSPATH = []
102
+ JBUNDLER_TEST_CLASSPATH.freeze
103
+ JBUNDLER_CLASSPATH = []
104
+ JBUNDLER_CLASSPATH << (JBUNDLER_LOCAL_REPO + 'a')
105
+ JBUNDLER_CLASSPATH << (JBUNDLER_LOCAL_REPO + 'b')
106
+ JBUNDLER_CLASSPATH << (JBUNDLER_LOCAL_REPO + 'c')
107
+ JBUNDLER_CLASSPATH << (JBUNDLER_LOCAL_REPO + 'd')
108
+ JBUNDLER_CLASSPATH << (JBUNDLER_LOCAL_REPO + 'f')
109
+ JBUNDLER_CLASSPATH.freeze
110
+ EOF
111
+ end
112
+
113
+ it 'require classpath using default with generated localrepo' do
114
+ ENV[ 'JARS_HOME' ] = '/tmp'
115
+ Jars.reset
116
+ subject.generate("/a:/b:/c:/d:/f:".split(File::PATH_SEPARATOR), [], [], '/tmp')
117
+ begin
118
+ subject.require_classpath
119
+ rescue LoadError
120
+ # there are no files to require
121
+ end
122
+ JBUNDLER_CLASSPATH.must_equal ["/tmp/a", "/tmp/b", "/tmp/c", "/tmp/d", "/tmp/f"]
123
+ end
124
+
125
+ it 'require classpath with generated localrepo' do
126
+ ENV[ 'JARS_HOME' ] = '/tmp'
127
+ subject.generate("/a:/b:/c:/d:/f:".split(File::PATH_SEPARATOR), [], [], '/tmp')
128
+
129
+ begin
130
+ Jars.reset
131
+ ENV[ 'JARS_HOME' ] = '/temp'
132
+ subject.require_classpath
133
+ rescue LoadError
134
+ # there are no files to require
135
+ end
136
+ JBUNDLER_CLASSPATH.must_equal ["/temp/a", "/temp/b", "/temp/c", "/temp/d", "/temp/f"]
137
+ end
138
+ end