ji2p 0.0.3-jruby-java-universal-java-9
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.
- checksums.yaml +7 -0
- data/bin/bundle +15 -0
- data/bin/ctxirb +119 -0
- data/bin/simple_http_server +20 -0
- data/bin/simple_outproxy +96 -0
- data/lib/actor_system/actor.rb +10 -0
- data/lib/actor_system/concurrent/processor.rb +21 -0
- data/lib/actor_system/concurrent/worker.rb +13 -0
- data/lib/actor_system/core/minimal.rb +84 -0
- data/lib/actor_system/core/observable_implementation.rb +58 -0
- data/lib/actor_system/core/props.rb +45 -0
- data/lib/actor_system/dispatcher.rb +12 -0
- data/lib/actor_system/mailbox.rb +7 -0
- data/lib/actor_system/message.rb +60 -0
- data/lib/core_ext.rb +41 -0
- data/lib/gen_server.rb +57 -0
- data/lib/ji2p.rb +37 -0
- data/lib/ji2p/bundler.rb +165 -0
- data/lib/ji2p/cluster.rb +6 -0
- data/lib/ji2p/cluster/etcd.rb +5 -0
- data/lib/ji2p/cluster/etcd/version3.rb +6 -0
- data/lib/ji2p/cluster/kubernetes.rb +5 -0
- data/lib/ji2p/cluster/kubernetes/kube_api.rb +6 -0
- data/lib/ji2p/concurrent.rb +24 -0
- data/lib/ji2p/concurrent_executor.rb +56 -0
- data/lib/ji2p/config.rb +15 -0
- data/lib/ji2p/control.rb +15 -0
- data/lib/ji2p/control/client_manager.rb +14 -0
- data/lib/ji2p/control/dest.rb +34 -0
- data/lib/ji2p/control/keypair.rb +176 -0
- data/lib/ji2p/control/server.rb +80 -0
- data/lib/ji2p/control/socket_manager.rb +77 -0
- data/lib/ji2p/control/tunnel_manager.rb +62 -0
- data/lib/ji2p/environment.rb +35 -0
- data/lib/ji2p/package/gem_installer.rb +91 -0
- data/lib/ji2p/package/gemfile.rb +234 -0
- data/lib/ji2p/package/jar_dependencies.rb +23 -0
- data/lib/ji2p/package/proxy_support.rb +50 -0
- data/lib/ji2p/rspec.rb +16 -0
- data/lib/ji2p/server.rb +10 -0
- data/lib/ji2p/server/api.rb +14 -0
- data/lib/ji2p/server/database.rb +66 -0
- data/lib/ji2p/server/http.rb +69 -0
- data/lib/ji2p/server/http_server.rb +37 -0
- data/lib/ji2p/server/initializer.rb +4 -0
- data/lib/ji2p/server/launcher.rb +40 -0
- data/lib/ji2p/server/models.rb +9 -0
- data/lib/ji2p/server/models/base_record.rb +7 -0
- data/lib/ji2p/server/models/keypair.rb +32 -0
- data/lib/ji2p/server/models/tunnel.rb +4 -0
- data/lib/ji2p/startup.rb +12 -0
- data/lib/ji2p/startup/bootstrap.rb +60 -0
- data/lib/ji2p/startup/client_application.rb +20 -0
- data/lib/ji2p/startup/router_manager.rb +21 -0
- data/lib/ji2p/startup/sinatra_app.rb +61 -0
- data/lib/ji2p/startup/worker.rb +63 -0
- data/lib/ji2p/utils/blocking_queue.rb +32 -0
- data/lib/ji2p/utils/byte_value.rb +61 -0
- data/lib/ji2p/version.rb +3 -0
- data/lib/ji2p_jars.rb +16 -0
- data/lib/maybe.rb +148 -0
- data/lib/net/i2p/client/mstreaming/0.9.43/mstreaming-0.9.43.jar +0 -0
- data/lib/net/i2p/client/streaming/0.9.43/streaming-0.9.43.jar +0 -0
- data/lib/net/i2p/i2p/0.9.43/i2p-0.9.43.jar +0 -0
- data/lib/net/i2p/router/0.9.43/router-0.9.43.jar +0 -0
- metadata +392 -0
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'java'
|
2
|
+
require 'thread'
|
3
|
+
require_relative 'server.rb'
|
4
|
+
|
5
|
+
module Ji2p::Control
|
6
|
+
java_import 'net.i2p.I2PAppContext'
|
7
|
+
java_import 'net.i2p.client.I2PClientFactory'
|
8
|
+
java_import 'net.i2p.client.streaming.I2PSocketManager'
|
9
|
+
java_import 'net.i2p.client.streaming.I2PSocketManagerFactory'
|
10
|
+
java_import 'net.i2p.client.streaming.IncomingConnectionFilter'
|
11
|
+
java_import 'java.util.Properties'
|
12
|
+
java_import 'java.lang.Thread'
|
13
|
+
|
14
|
+
class SocketManager
|
15
|
+
|
16
|
+
def self.defineManager! name, kp, opts=Java::JavaUtil::Properties.new, filter=IncomingConnectionFilter::ALLOW
|
17
|
+
ctx = I2PAppContext.getGlobalContext
|
18
|
+
session = kp.createSession opts
|
19
|
+
new get_impl.new(ctx,session,opts,name,filter)
|
20
|
+
end
|
21
|
+
|
22
|
+
def connectTunnel
|
23
|
+
@smgr.getSession.connect
|
24
|
+
end
|
25
|
+
|
26
|
+
def myDestination
|
27
|
+
@smgr.getSession.myDestination
|
28
|
+
end
|
29
|
+
|
30
|
+
def leaseSet
|
31
|
+
@smgr.getSession.leaseSet
|
32
|
+
end
|
33
|
+
|
34
|
+
def sessionId
|
35
|
+
@smgr.getSession.sessionId
|
36
|
+
end
|
37
|
+
|
38
|
+
def supports_ls2?
|
39
|
+
@smgr.getSession.supports_ls2?
|
40
|
+
end
|
41
|
+
|
42
|
+
def is_closed?
|
43
|
+
@smgr.getSession.closed?
|
44
|
+
end
|
45
|
+
|
46
|
+
def session
|
47
|
+
@smgr.session
|
48
|
+
end
|
49
|
+
|
50
|
+
def destroy
|
51
|
+
@smgr.getSession.destroySession
|
52
|
+
end
|
53
|
+
|
54
|
+
def lookupDest dest
|
55
|
+
@smgr.getSession.lookupDest dest
|
56
|
+
end
|
57
|
+
|
58
|
+
def getServerSocket
|
59
|
+
SocketServer.new @smgr.getServerSocket
|
60
|
+
end
|
61
|
+
|
62
|
+
def raw
|
63
|
+
@smgr
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def self.get_impl
|
69
|
+
java_import('net.i2p.client.streaming.impl.I2PSocketManagerFull').first
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialize smgr
|
73
|
+
@smgr = smgr
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'java'
|
2
|
+
|
3
|
+
require 'java'
|
4
|
+
require 'digest/sha1'
|
5
|
+
|
6
|
+
module Ji2p::Control
|
7
|
+
class TunnelManager
|
8
|
+
@@tunnelctrl = nil
|
9
|
+
include_package 'net.i2p'
|
10
|
+
include_package 'net.i2p.i2ptunnel'
|
11
|
+
include_package 'net.i2p.client'
|
12
|
+
|
13
|
+
def self.context
|
14
|
+
I2PAppContext.getGlobalContext
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.startTunnelWithConfig conf, createPrivKey = false
|
18
|
+
unless ['client','httpclient','server','httpserver','sockstunnel'].include? conf['type']
|
19
|
+
raise ArgumentError, 'Invalid i2p tunnel type!', caller
|
20
|
+
end
|
21
|
+
tctrl = TunnelController.new conf, '', createPrivKey
|
22
|
+
TunnelCtrl.new tctrl, conf
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.createNewConfig hash = Hash.new
|
26
|
+
props = java.util.Properties.new
|
27
|
+
dfl = {
|
28
|
+
'option.maxPosts'=>'3',
|
29
|
+
'option.i2cp.destination.sigType'=>'EdDSA_SHA512_Ed25519',
|
30
|
+
'option.i2p.streaming.limitAction'=>'http',
|
31
|
+
'description'=>'jruby-tunnel',
|
32
|
+
'interface'=>'127.0.0.1',
|
33
|
+
'type'=>'httpserver',
|
34
|
+
'option.outbound.quantity'=>'4',
|
35
|
+
'option.inbound.quantity'=>'4',
|
36
|
+
'option.postBanTime'=>'1800',
|
37
|
+
'targetPort'=>'8000',
|
38
|
+
'option.postTotalBanTime'=>'600',
|
39
|
+
'i2cpHost'=>'127.0.0.1',
|
40
|
+
'option.postCheckTime'=>'300',
|
41
|
+
'option.i2p.streaming.maxConnsPerHour'=>'40',
|
42
|
+
'option.shouldBundleReplyInfo'=>'false',
|
43
|
+
'option.outbound.length'=>'1',
|
44
|
+
'targetHost'=>'127.0.0.1',
|
45
|
+
'option.inbound.length'=>'1',
|
46
|
+
'i2cpPort'=>'7654',
|
47
|
+
'persistentClientKey'=>'true',
|
48
|
+
'option.maxTotalPosts'=>'10',
|
49
|
+
'option.i2p.streaming.maxConnsPerDay'=>'100',
|
50
|
+
'option.i2p.streaming.maxTotalConnsPerMinute'=>'25',
|
51
|
+
'option.i2p.streaming.maxConnsPerMinute'=>'15',
|
52
|
+
'name'=>'jruby-tunnel',
|
53
|
+
'option.i2p.streaming.maxConcurrentStreams'=>'20',
|
54
|
+
'privKeyFile'=>'kake.dat',
|
55
|
+
'listenPort'=>'8000'
|
56
|
+
}
|
57
|
+
merged = dfl.merge(hash)
|
58
|
+
merged.keys.each { |k| props[k.to_s] = merged[k].to_s }
|
59
|
+
props
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Ji2p
|
4
|
+
module Environment
|
5
|
+
extend self
|
6
|
+
JI2P_HOME = ::File.expand_path(::File.join('..','..'), __dir__) unless defined? JI2P_HOME
|
7
|
+
|
8
|
+
BUNDLE_DIR = ::File.join(JI2P_HOME, "vendor", "bundle") unless defined? BUNDLE_DIR
|
9
|
+
GEMFILE_PATH = ::File.join(JI2P_HOME, "Gemfile") unless defined? GEMFILE_PATH
|
10
|
+
LOCAL_GEM_PATH = ::File.join(JI2P_HOME, 'vendor', 'local_gems') unless defined? LOCAL_GEM_PATH
|
11
|
+
CACHE_PATH = ::File.join(JI2P_HOME, "vendor", "cache") unless defined? CACHE_PATH
|
12
|
+
LOCKFILE = Pathname.new(::File.join(JI2P_HOME, "Gemfile.lock")) unless defined? LOCKFILE
|
13
|
+
GEMFILE = Pathname.new(::File.join(JI2P_HOME, "Gemfile")) unless defined? GEMFILE
|
14
|
+
|
15
|
+
def gem_ruby_version
|
16
|
+
RbConfig::CONFIG["ruby_version"]
|
17
|
+
end
|
18
|
+
|
19
|
+
def ruby_abi_version
|
20
|
+
RUBY_VERSION[/(\d+\.\d+)(\.\d+)*/, 1]
|
21
|
+
end
|
22
|
+
|
23
|
+
def ruby_engine
|
24
|
+
RUBY_ENGINE
|
25
|
+
end
|
26
|
+
|
27
|
+
def ji2p_gem_home
|
28
|
+
::File.join(BUNDLE_DIR, ruby_engine, gem_ruby_version)
|
29
|
+
end
|
30
|
+
|
31
|
+
def vendor_path(path)
|
32
|
+
return ::File.join(JI2P_HOME, "vendor", path)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
|
2
|
+
require "pathname"
|
3
|
+
require "rubygems/package"
|
4
|
+
require "fileutils"
|
5
|
+
|
6
|
+
require_relative 'environment.rb'
|
7
|
+
|
8
|
+
module Ji2p
|
9
|
+
module Package
|
10
|
+
class GemInstaller
|
11
|
+
GEM_HOME = Pathname.new(::File.join(Ji2p::Environment::BUNDLE_DIR, "jruby", "2.5.0"))
|
12
|
+
SPECIFICATIONS_DIR = "specifications"
|
13
|
+
GEMS_DIR = "gems"
|
14
|
+
CACHE_DIR = "cache"
|
15
|
+
|
16
|
+
attr_reader :gem_home
|
17
|
+
|
18
|
+
def initialize(gem_file, display_post_install_message = false, gem_home = GEM_HOME)
|
19
|
+
@gem_file = gem_file
|
20
|
+
@gem = ::Gem::Package.new(@gem_file)
|
21
|
+
@gem_home = Pathname.new(gem_home)
|
22
|
+
@display_post_install_message = display_post_install_message
|
23
|
+
end
|
24
|
+
|
25
|
+
def install
|
26
|
+
create_destination_folders
|
27
|
+
extract_files
|
28
|
+
write_specification
|
29
|
+
copy_gem_file_to_cache
|
30
|
+
post_install_message
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.install(gem_file, display_post_install_message = false, gem_home = GEM_HOME)
|
34
|
+
self.new(gem_file, display_post_install_message, gem_home).install
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def spec
|
39
|
+
@gem.spec
|
40
|
+
end
|
41
|
+
|
42
|
+
def spec_dir
|
43
|
+
gem_home.join(SPECIFICATIONS_DIR)
|
44
|
+
end
|
45
|
+
|
46
|
+
def cache_dir
|
47
|
+
gem_home.join(CACHE_DIR)
|
48
|
+
end
|
49
|
+
|
50
|
+
def spec_file
|
51
|
+
spec_dir.join("#{spec.full_name}.gemspec")
|
52
|
+
end
|
53
|
+
|
54
|
+
def gem_dir
|
55
|
+
gem_home.join(GEMS_DIR, spec.full_name)
|
56
|
+
end
|
57
|
+
|
58
|
+
def extract_files
|
59
|
+
@gem.extract_files gem_dir
|
60
|
+
end
|
61
|
+
|
62
|
+
def write_specification
|
63
|
+
::File.open(spec_file, 'w') do |file|
|
64
|
+
spec.installed_by_version = ::Gem.rubygems_version
|
65
|
+
file.puts spec.to_ruby_for_cache
|
66
|
+
file.fsync rescue nil # Force writing to disk
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def post_install_message
|
71
|
+
spec.post_install_message if display_post_install_message?
|
72
|
+
end
|
73
|
+
|
74
|
+
def display_post_install_message?
|
75
|
+
@display_post_install_message && !spec.post_install_message.nil?
|
76
|
+
end
|
77
|
+
|
78
|
+
def copy_gem_file_to_cache
|
79
|
+
destination = ::File.join(cache_dir, ::File.basename(@gem_file))
|
80
|
+
FileUtils.cp(@gem_file, destination)
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_destination_folders
|
84
|
+
FileUtils.mkdir_p(gem_home)
|
85
|
+
FileUtils.mkdir_p(gem_dir)
|
86
|
+
FileUtils.mkdir_p(spec_dir)
|
87
|
+
FileUtils.mkdir_p(cache_dir)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,234 @@
|
|
1
|
+
module Ji2p
|
2
|
+
module Package
|
3
|
+
class GemfileError < StandardError; end
|
4
|
+
|
5
|
+
class Gemfile
|
6
|
+
attr_accessor :gemset
|
7
|
+
|
8
|
+
HEADER = \
|
9
|
+
"# This is a Logstash generated Gemfile.\n" + \
|
10
|
+
"# If you modify this file manually all comments and formatting will be lost.\n\n"
|
11
|
+
|
12
|
+
# @params io [IO] any IO object that supports read, write, truncate, rewind
|
13
|
+
def initialize(io)
|
14
|
+
@io = io
|
15
|
+
@gemset = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def load(with_backup = true)
|
19
|
+
# encoding must be set to UTF-8 here to avoid ending up with Windows-1252 encoding on Windows
|
20
|
+
# which will break the DSL instance_eval of that string
|
21
|
+
@io.set_encoding(Encoding::UTF_8)
|
22
|
+
@gemset ||= DSL.parse(@io.read)
|
23
|
+
backup if with_backup
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def save
|
28
|
+
raise(GemfileError, "a Gemfile must first be loaded") unless @gemset
|
29
|
+
@io.truncate(0)
|
30
|
+
@io.rewind
|
31
|
+
@io.write(generate)
|
32
|
+
@io.flush
|
33
|
+
end
|
34
|
+
|
35
|
+
def generate
|
36
|
+
"#{HEADER}#{gemset.to_s}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def find(name)
|
40
|
+
@gemset.find_gem(name)
|
41
|
+
end
|
42
|
+
|
43
|
+
# @param name [String] gem name
|
44
|
+
# @param *requirements params following name use the same notation as the Gemfile gem DSL statement
|
45
|
+
# @raise GemfileError if gem already exists in Gemfile
|
46
|
+
def add(name, *requirements)
|
47
|
+
@gemset.add_gem(Gem.parse(name, *requirements))
|
48
|
+
end
|
49
|
+
|
50
|
+
# update existing or add new and merge passed options with current gem options if it exists
|
51
|
+
# @param name [String] gem name
|
52
|
+
# @param *requirements params following name use the same notation as the Gemfile gem DSL statement
|
53
|
+
def update(name, *requirements)
|
54
|
+
@gemset.update_gem(Gem.parse(name, *requirements))
|
55
|
+
end
|
56
|
+
|
57
|
+
# overwrite existing or add new
|
58
|
+
# @param name [String] gem name
|
59
|
+
# @param *requirements params following name use the same notation as the Gemfile gem DSL statement
|
60
|
+
def overwrite(name, *requirements)
|
61
|
+
@gemset.overwrite_gem(Gem.parse(name, *requirements))
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [Gem] removed gem or nil if not found
|
65
|
+
def remove(name)
|
66
|
+
@gemset.remove_gem(name)
|
67
|
+
end
|
68
|
+
|
69
|
+
def backup
|
70
|
+
@original_backup = @gemset.copy
|
71
|
+
end
|
72
|
+
|
73
|
+
def restore
|
74
|
+
@gemset = @original_backup
|
75
|
+
end
|
76
|
+
|
77
|
+
def defined_in_gemfile?(name)
|
78
|
+
@gemset.find_gem(name)
|
79
|
+
end
|
80
|
+
|
81
|
+
def restore!
|
82
|
+
restore
|
83
|
+
save
|
84
|
+
end
|
85
|
+
|
86
|
+
def locally_installed_gems
|
87
|
+
@gemset.gems.select { |gem| gem.options.include?(:path) }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class Gemset
|
92
|
+
attr_accessor :sources, :gems, :gemspec
|
93
|
+
|
94
|
+
def initialize
|
95
|
+
@sources = [] # list of urls
|
96
|
+
@gems = [] # list of Gem class
|
97
|
+
@gems_by_name = {} # hash of name => Gem
|
98
|
+
@gemspec = {} # gemspec is a options hash
|
99
|
+
end
|
100
|
+
|
101
|
+
def to_s
|
102
|
+
[sources_to_s, gemspec_to_s, gems_to_s].select{|s| !s.empty?}.join("\n") + "\n"
|
103
|
+
end
|
104
|
+
|
105
|
+
# @return [Gem] found gem or nil if not found
|
106
|
+
def find_gem(name)
|
107
|
+
@gems_by_name[name.downcase]
|
108
|
+
end
|
109
|
+
|
110
|
+
# @raise GemfileError if gem already exists
|
111
|
+
def add_gem(_gem)
|
112
|
+
raise(GemfileError, "duplicate gem #{_gem.name}") if find_gem(_gem.name)
|
113
|
+
@gems << _gem
|
114
|
+
@gems_by_name[_gem.name.downcase] = _gem
|
115
|
+
end
|
116
|
+
|
117
|
+
# update existing or add new
|
118
|
+
def update_gem(_gem)
|
119
|
+
if old = find_gem(_gem.name)
|
120
|
+
# always overwrite requirements if specified
|
121
|
+
old.requirements = _gem.requirements unless no_constrains?(_gem.requirements)
|
122
|
+
# but merge options
|
123
|
+
old.options = old.options.merge(_gem.options)
|
124
|
+
else
|
125
|
+
@gems << _gem
|
126
|
+
@gems_by_name[_gem.name.downcase] = _gem
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# update existing or add new
|
131
|
+
def overwrite_gem(_gem)
|
132
|
+
if old = find_gem(_gem.name)
|
133
|
+
@gems[@gems.index(old)] = _gem
|
134
|
+
else
|
135
|
+
@gems << _gem
|
136
|
+
end
|
137
|
+
@gems_by_name[_gem.name.downcase] = _gem
|
138
|
+
end
|
139
|
+
|
140
|
+
# @return [Gem] removed gem or nil if not found
|
141
|
+
def remove_gem(name)
|
142
|
+
if _gem = @gems_by_name.delete(name.downcase)
|
143
|
+
@gems.delete_at(@gems.index(_gem))
|
144
|
+
end
|
145
|
+
_gem
|
146
|
+
end
|
147
|
+
|
148
|
+
# deep clone self
|
149
|
+
def copy
|
150
|
+
Marshal.load(Marshal.dump(self))
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def no_constrains?(requirements)
|
156
|
+
return true if requirements.nil? || requirements.empty?
|
157
|
+
|
158
|
+
# check for the dummy ">= 0" version constrain or any variations thereof
|
159
|
+
# which is in fact a "no constrain" constrain which we should discard
|
160
|
+
return true if requirements.size == 1 && requirements.first.to_s.gsub(/\s+/, "") == ">=0"
|
161
|
+
|
162
|
+
false
|
163
|
+
end
|
164
|
+
|
165
|
+
def sources_to_s
|
166
|
+
return "" if @sources.empty?
|
167
|
+
@sources.map{|source| "source #{source.inspect}"}.join("\n")
|
168
|
+
end
|
169
|
+
|
170
|
+
def gems_to_s
|
171
|
+
return "" if @gems.empty?
|
172
|
+
@gems.map do |gem|
|
173
|
+
requirements = gem.requirements.empty? ? nil : gem.requirements.map{|r| r.inspect}.join(", ")
|
174
|
+
options = gem.options.empty? ? nil : gem.options.map{|k, v| "#{k.inspect} => #{v.inspect}"}.join(", ")
|
175
|
+
"gem " + [gem.name.inspect, requirements, options].compact.join(", ")
|
176
|
+
end.join("\n")
|
177
|
+
end
|
178
|
+
|
179
|
+
def gemspec_to_s
|
180
|
+
return "" if @gemspec.empty?
|
181
|
+
options = @gemspec.map{|k, v| "#{k.inspect} => #{v.inspect}"}.join(", ")
|
182
|
+
"gemspec #{options}"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# DSL is a minimal, incomplete Gemfile DSL subset parser, only what is currently required is implemented.
|
187
|
+
class DSL
|
188
|
+
attr_reader :gemset
|
189
|
+
|
190
|
+
def initialize
|
191
|
+
@gemset = Gemset.new
|
192
|
+
end
|
193
|
+
|
194
|
+
# @param gemfile_content [String] the Gemfile string content
|
195
|
+
# @return [Gemset] parsed Gemfile content as a Gemset
|
196
|
+
def self.parse(gemfile_content)
|
197
|
+
dsl = self.new
|
198
|
+
dsl.instance_eval(gemfile_content)
|
199
|
+
dsl.gemset
|
200
|
+
end
|
201
|
+
|
202
|
+
# DSL methods
|
203
|
+
|
204
|
+
def source(url)
|
205
|
+
@gemset.sources << url
|
206
|
+
end
|
207
|
+
|
208
|
+
def gem(name, *requirements)
|
209
|
+
parsed = Gem.parse(name, *requirements)
|
210
|
+
@gemset.add_gem(parsed)
|
211
|
+
end
|
212
|
+
|
213
|
+
def gemspec(options = {})
|
214
|
+
raise(GemfileError, "cannot declare multiple gemspec directives") unless @gemset.gemspec.empty?
|
215
|
+
@gemset.gemspec = options
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
class Gem
|
220
|
+
attr_accessor :name, :requirements, :options
|
221
|
+
|
222
|
+
def initialize(name, requirements = [], options = {})
|
223
|
+
@name = name
|
224
|
+
@requirements = requirements.map{|r| r.to_s.strip}.select{|r| !r.empty?}
|
225
|
+
@options = options
|
226
|
+
end
|
227
|
+
|
228
|
+
def self.parse(name, *requirements)
|
229
|
+
options = requirements.last.is_a?(Hash) ? requirements.pop : {}
|
230
|
+
self.new(name, requirements, options)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|