libgems 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/ChangeLog +5811 -0
- data/History.txt +887 -0
- data/LICENSE.txt +51 -0
- data/README.md +87 -0
- data/Rakefile +113 -0
- data/lib/gauntlet_libgems.rb +50 -0
- data/lib/libgems.rb +1246 -0
- data/lib/libgems/builder.rb +102 -0
- data/lib/libgems/command.rb +534 -0
- data/lib/libgems/command_manager.rb +182 -0
- data/lib/libgems/commands/build_command.rb +53 -0
- data/lib/libgems/commands/cert_command.rb +86 -0
- data/lib/libgems/commands/check_command.rb +80 -0
- data/lib/libgems/commands/cleanup_command.rb +106 -0
- data/lib/libgems/commands/contents_command.rb +98 -0
- data/lib/libgems/commands/dependency_command.rb +195 -0
- data/lib/libgems/commands/environment_command.rb +133 -0
- data/lib/libgems/commands/fetch_command.rb +67 -0
- data/lib/libgems/commands/generate_index_command.rb +133 -0
- data/lib/libgems/commands/help_command.rb +172 -0
- data/lib/libgems/commands/install_command.rb +178 -0
- data/lib/libgems/commands/list_command.rb +35 -0
- data/lib/libgems/commands/lock_command.rb +110 -0
- data/lib/libgems/commands/mirror_command.rb +111 -0
- data/lib/libgems/commands/outdated_command.rb +33 -0
- data/lib/libgems/commands/owner_command.rb +75 -0
- data/lib/libgems/commands/pristine_command.rb +93 -0
- data/lib/libgems/commands/push_command.rb +56 -0
- data/lib/libgems/commands/query_command.rb +280 -0
- data/lib/libgems/commands/rdoc_command.rb +91 -0
- data/lib/libgems/commands/search_command.rb +31 -0
- data/lib/libgems/commands/server_command.rb +86 -0
- data/lib/libgems/commands/sources_command.rb +157 -0
- data/lib/libgems/commands/specification_command.rb +125 -0
- data/lib/libgems/commands/stale_command.rb +27 -0
- data/lib/libgems/commands/uninstall_command.rb +83 -0
- data/lib/libgems/commands/unpack_command.rb +121 -0
- data/lib/libgems/commands/update_command.rb +160 -0
- data/lib/libgems/commands/which_command.rb +86 -0
- data/lib/libgems/config_file.rb +345 -0
- data/lib/libgems/custom_require.rb +44 -0
- data/lib/libgems/defaults.rb +101 -0
- data/lib/libgems/dependency.rb +227 -0
- data/lib/libgems/dependency_installer.rb +286 -0
- data/lib/libgems/dependency_list.rb +208 -0
- data/lib/libgems/doc_manager.rb +242 -0
- data/lib/libgems/errors.rb +35 -0
- data/lib/libgems/exceptions.rb +91 -0
- data/lib/libgems/ext.rb +18 -0
- data/lib/libgems/ext/builder.rb +56 -0
- data/lib/libgems/ext/configure_builder.rb +25 -0
- data/lib/libgems/ext/ext_conf_builder.rb +24 -0
- data/lib/libgems/ext/rake_builder.rb +39 -0
- data/lib/libgems/format.rb +81 -0
- data/lib/libgems/gem_openssl.rb +92 -0
- data/lib/libgems/gem_path_searcher.rb +100 -0
- data/lib/libgems/gem_runner.rb +79 -0
- data/lib/libgems/gemcutter_utilities.rb +49 -0
- data/lib/libgems/indexer.rb +720 -0
- data/lib/libgems/install_update_options.rb +125 -0
- data/lib/libgems/installer.rb +604 -0
- data/lib/libgems/local_remote_options.rb +135 -0
- data/lib/libgems/old_format.rb +153 -0
- data/lib/libgems/package.rb +97 -0
- data/lib/libgems/package/f_sync_dir.rb +23 -0
- data/lib/libgems/package/tar_header.rb +266 -0
- data/lib/libgems/package/tar_input.rb +222 -0
- data/lib/libgems/package/tar_output.rb +144 -0
- data/lib/libgems/package/tar_reader.rb +106 -0
- data/lib/libgems/package/tar_reader/entry.rb +141 -0
- data/lib/libgems/package/tar_writer.rb +241 -0
- data/lib/libgems/package_task.rb +126 -0
- data/lib/libgems/platform.rb +183 -0
- data/lib/libgems/remote_fetcher.rb +414 -0
- data/lib/libgems/require_paths_builder.rb +18 -0
- data/lib/libgems/requirement.rb +153 -0
- data/lib/libgems/security.rb +814 -0
- data/lib/libgems/server.rb +872 -0
- data/lib/libgems/source_index.rb +597 -0
- data/lib/libgems/source_info_cache.rb +395 -0
- data/lib/libgems/source_info_cache_entry.rb +56 -0
- data/lib/libgems/spec_fetcher.rb +337 -0
- data/lib/libgems/specification.rb +1487 -0
- data/lib/libgems/test_utilities.rb +147 -0
- data/lib/libgems/text.rb +65 -0
- data/lib/libgems/uninstaller.rb +278 -0
- data/lib/libgems/user_interaction.rb +527 -0
- data/lib/libgems/validator.rb +240 -0
- data/lib/libgems/version.rb +316 -0
- data/lib/libgems/version_option.rb +65 -0
- data/lib/rbconfig/datadir.rb +20 -0
- data/test/bogussources.rb +8 -0
- data/test/data/gem-private_key.pem +27 -0
- data/test/data/gem-public_cert.pem +20 -0
- data/test/fake_certlib/openssl.rb +7 -0
- data/test/foo/discover.rb +0 -0
- data/test/gem_installer_test_case.rb +97 -0
- data/test/gem_package_tar_test_case.rb +132 -0
- data/test/gemutilities.rb +605 -0
- data/test/insure_session.rb +43 -0
- data/test/mockgemui.rb +56 -0
- data/test/plugin/exception/libgems_plugin.rb +2 -0
- data/test/plugin/load/libgems_plugin.rb +1 -0
- data/test/plugin/standarderror/libgems_plugin.rb +2 -0
- data/test/private_key.pem +27 -0
- data/test/public_cert.pem +20 -0
- data/test/rubygems_plugin.rb +21 -0
- data/test/simple_gem.rb +66 -0
- data/test/test_config.rb +12 -0
- data/test/test_gem.rb +780 -0
- data/test/test_gem_builder.rb +27 -0
- data/test/test_gem_command.rb +178 -0
- data/test/test_gem_command_manager.rb +207 -0
- data/test/test_gem_commands_build_command.rb +74 -0
- data/test/test_gem_commands_cert_command.rb +124 -0
- data/test/test_gem_commands_check_command.rb +18 -0
- data/test/test_gem_commands_contents_command.rb +156 -0
- data/test/test_gem_commands_dependency_command.rb +216 -0
- data/test/test_gem_commands_environment_command.rb +144 -0
- data/test/test_gem_commands_fetch_command.rb +76 -0
- data/test/test_gem_commands_generate_index_command.rb +135 -0
- data/test/test_gem_commands_install_command.rb +315 -0
- data/test/test_gem_commands_list_command.rb +36 -0
- data/test/test_gem_commands_lock_command.rb +68 -0
- data/test/test_gem_commands_mirror_command.rb +60 -0
- data/test/test_gem_commands_outdated_command.rb +40 -0
- data/test/test_gem_commands_owner_command.rb +105 -0
- data/test/test_gem_commands_pristine_command.rb +108 -0
- data/test/test_gem_commands_push_command.rb +81 -0
- data/test/test_gem_commands_query_command.rb +426 -0
- data/test/test_gem_commands_server_command.rb +59 -0
- data/test/test_gem_commands_sources_command.rb +209 -0
- data/test/test_gem_commands_specification_command.rb +139 -0
- data/test/test_gem_commands_stale_command.rb +38 -0
- data/test/test_gem_commands_uninstall_command.rb +83 -0
- data/test/test_gem_commands_unpack_command.rb +199 -0
- data/test/test_gem_commands_update_command.rb +207 -0
- data/test/test_gem_commands_which_command.rb +66 -0
- data/test/test_gem_config_file.rb +287 -0
- data/test/test_gem_dependency.rb +149 -0
- data/test/test_gem_dependency_installer.rb +661 -0
- data/test/test_gem_dependency_list.rb +230 -0
- data/test/test_gem_doc_manager.rb +31 -0
- data/test/test_gem_ext_configure_builder.rb +84 -0
- data/test/test_gem_ext_ext_conf_builder.rb +173 -0
- data/test/test_gem_ext_rake_builder.rb +81 -0
- data/test/test_gem_format.rb +70 -0
- data/test/test_gem_gem_path_searcher.rb +78 -0
- data/test/test_gem_gem_runner.rb +45 -0
- data/test/test_gem_gemcutter_utilities.rb +103 -0
- data/test/test_gem_indexer.rb +673 -0
- data/test/test_gem_install_update_options.rb +68 -0
- data/test/test_gem_installer.rb +857 -0
- data/test/test_gem_local_remote_options.rb +97 -0
- data/test/test_gem_package_tar_header.rb +130 -0
- data/test/test_gem_package_tar_input.rb +112 -0
- data/test/test_gem_package_tar_output.rb +97 -0
- data/test/test_gem_package_tar_reader.rb +46 -0
- data/test/test_gem_package_tar_reader_entry.rb +109 -0
- data/test/test_gem_package_tar_writer.rb +144 -0
- data/test/test_gem_package_task.rb +59 -0
- data/test/test_gem_platform.rb +264 -0
- data/test/test_gem_remote_fetcher.rb +740 -0
- data/test/test_gem_requirement.rb +292 -0
- data/test/test_gem_server.rb +356 -0
- data/test/test_gem_silent_ui.rb +113 -0
- data/test/test_gem_source_index.rb +461 -0
- data/test/test_gem_spec_fetcher.rb +410 -0
- data/test/test_gem_specification.rb +1334 -0
- data/test/test_gem_stream_ui.rb +218 -0
- data/test/test_gem_text.rb +43 -0
- data/test/test_gem_uninstaller.rb +146 -0
- data/test/test_gem_validator.rb +63 -0
- data/test/test_gem_version.rb +181 -0
- data/test/test_gem_version_option.rb +89 -0
- data/test/test_kernel.rb +59 -0
- metadata +402 -0
|
@@ -0,0 +1,740 @@
|
|
|
1
|
+
require File.expand_path('../gemutilities', __FILE__)
|
|
2
|
+
require 'ostruct'
|
|
3
|
+
require 'webrick'
|
|
4
|
+
require 'libgems/remote_fetcher'
|
|
5
|
+
require 'libgems/format'
|
|
6
|
+
|
|
7
|
+
# = Testing Proxy Settings
|
|
8
|
+
#
|
|
9
|
+
# These tests check the proper proxy server settings by running two
|
|
10
|
+
# web servers. The web server at http://localhost:#{SERVER_PORT}
|
|
11
|
+
# represents the normal gem server and returns a gemspec with a rake
|
|
12
|
+
# version of 0.4.11. The web server at http://localhost:#{PROXY_PORT}
|
|
13
|
+
# represents the proxy server and returns a different dataset where
|
|
14
|
+
# rake has version 0.4.2. This allows us to detect which server is
|
|
15
|
+
# returning the data.
|
|
16
|
+
#
|
|
17
|
+
# Note that the proxy server is not a *real* proxy server. But our
|
|
18
|
+
# software doesn't really care, as long as we hit the proxy URL when a
|
|
19
|
+
# proxy is configured.
|
|
20
|
+
|
|
21
|
+
class TestGemRemoteFetcher < RubyGemTestCase
|
|
22
|
+
|
|
23
|
+
include LibGems::DefaultUserInteraction
|
|
24
|
+
|
|
25
|
+
SERVER_DATA = <<-EOY
|
|
26
|
+
--- !ruby/object:LibGems::Cache
|
|
27
|
+
gems:
|
|
28
|
+
rake-0.4.11: !ruby/object:LibGems::Specification
|
|
29
|
+
rubygems_version: "0.7"
|
|
30
|
+
specification_version: 1
|
|
31
|
+
name: rake
|
|
32
|
+
version: !ruby/object:LibGems::Version
|
|
33
|
+
version: 0.4.11
|
|
34
|
+
date: 2004-11-12
|
|
35
|
+
summary: Ruby based make-like utility.
|
|
36
|
+
require_paths:
|
|
37
|
+
- lib
|
|
38
|
+
author: Jim Weirich
|
|
39
|
+
email: jim@weirichhouse.org
|
|
40
|
+
homepage: http://rake.rubyforge.org
|
|
41
|
+
rubyforge_project: rake
|
|
42
|
+
description: Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax.
|
|
43
|
+
autorequire:
|
|
44
|
+
default_executable: rake
|
|
45
|
+
bindir: bin
|
|
46
|
+
has_rdoc: true
|
|
47
|
+
required_ruby_version: !ruby/object:LibGems::Version::Requirement
|
|
48
|
+
requirements:
|
|
49
|
+
-
|
|
50
|
+
- ">"
|
|
51
|
+
- !ruby/object:LibGems::Version
|
|
52
|
+
version: 0.0.0
|
|
53
|
+
version:
|
|
54
|
+
platform: ruby
|
|
55
|
+
files:
|
|
56
|
+
- README
|
|
57
|
+
test_files: []
|
|
58
|
+
library_stubs:
|
|
59
|
+
rdoc_options:
|
|
60
|
+
extra_rdoc_files:
|
|
61
|
+
executables:
|
|
62
|
+
- rake
|
|
63
|
+
extensions: []
|
|
64
|
+
requirements: []
|
|
65
|
+
dependencies: []
|
|
66
|
+
EOY
|
|
67
|
+
|
|
68
|
+
PROXY_DATA = SERVER_DATA.gsub(/0.4.11/, '0.4.2')
|
|
69
|
+
|
|
70
|
+
# don't let 1.8 and 1.9 autotest collide
|
|
71
|
+
RUBY_VERSION =~ /(\d+)\.(\d+)\.(\d+)/
|
|
72
|
+
# don't let parallel runners collide
|
|
73
|
+
PROXY_PORT = process_based_port + 100 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i
|
|
74
|
+
SERVER_PORT = process_based_port + 200 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i
|
|
75
|
+
|
|
76
|
+
def setup
|
|
77
|
+
super
|
|
78
|
+
self.class.start_servers
|
|
79
|
+
self.class.enable_yaml = true
|
|
80
|
+
self.class.enable_zip = false
|
|
81
|
+
ENV.delete 'http_proxy'
|
|
82
|
+
ENV.delete 'HTTP_PROXY'
|
|
83
|
+
ENV.delete 'http_proxy_user'
|
|
84
|
+
ENV.delete 'HTTP_PROXY_USER'
|
|
85
|
+
ENV.delete 'http_proxy_pass'
|
|
86
|
+
ENV.delete 'HTTP_PROXY_PASS'
|
|
87
|
+
|
|
88
|
+
base_server_uri = "http://localhost:#{SERVER_PORT}"
|
|
89
|
+
@proxy_uri = "http://localhost:#{PROXY_PORT}"
|
|
90
|
+
|
|
91
|
+
@server_uri = base_server_uri + "/yaml"
|
|
92
|
+
@server_z_uri = base_server_uri + "/yaml.Z"
|
|
93
|
+
|
|
94
|
+
# REFACTOR: copied from test_gem_dependency_installer.rb
|
|
95
|
+
@gems_dir = File.join @tempdir, 'gems'
|
|
96
|
+
@cache_dir = File.join @gemhome, 'cache'
|
|
97
|
+
FileUtils.mkdir @gems_dir
|
|
98
|
+
|
|
99
|
+
@a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end
|
|
100
|
+
|
|
101
|
+
LibGems::RemoteFetcher.fetcher = nil
|
|
102
|
+
|
|
103
|
+
@fetcher = LibGems::RemoteFetcher.fetcher
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def teardown
|
|
107
|
+
super
|
|
108
|
+
LibGems.configuration[:http_proxy] = nil
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def test_self_fetcher
|
|
112
|
+
fetcher = LibGems::RemoteFetcher.fetcher
|
|
113
|
+
refute_nil fetcher
|
|
114
|
+
assert_kind_of LibGems::RemoteFetcher, fetcher
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def test_self_fetcher_with_proxy
|
|
118
|
+
proxy_uri = 'http://proxy.example.com'
|
|
119
|
+
LibGems.configuration[:http_proxy] = proxy_uri
|
|
120
|
+
LibGems::RemoteFetcher.fetcher = nil
|
|
121
|
+
|
|
122
|
+
fetcher = LibGems::RemoteFetcher.fetcher
|
|
123
|
+
|
|
124
|
+
refute_nil fetcher
|
|
125
|
+
assert_kind_of LibGems::RemoteFetcher, fetcher
|
|
126
|
+
assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy_uri).to_s
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_self_fetcher_with_proxy_URI
|
|
130
|
+
proxy_uri = URI.parse 'http://proxy.example.com'
|
|
131
|
+
LibGems.configuration[:http_proxy] = proxy_uri
|
|
132
|
+
LibGems::RemoteFetcher.fetcher = nil
|
|
133
|
+
|
|
134
|
+
fetcher = LibGems::RemoteFetcher.fetcher
|
|
135
|
+
refute_nil fetcher
|
|
136
|
+
|
|
137
|
+
assert_kind_of LibGems::RemoteFetcher, fetcher
|
|
138
|
+
assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy_uri)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def test_fetch_size_bad_uri
|
|
142
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
143
|
+
|
|
144
|
+
e = assert_raises ArgumentError do
|
|
145
|
+
fetcher.fetch_size 'gems.example.com/yaml'
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
assert_equal 'uri scheme is invalid', e.message
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def test_fetch_size_socket_error
|
|
152
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
153
|
+
def fetcher.connection_for(uri)
|
|
154
|
+
raise SocketError, "tarded"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
uri = 'http://gems.example.com/yaml'
|
|
158
|
+
e = assert_raises LibGems::RemoteFetcher::FetchError do
|
|
159
|
+
fetcher.fetch_size uri
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
assert_equal "SocketError: tarded (#{uri})", e.message
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def test_no_proxy
|
|
166
|
+
use_ui @ui do
|
|
167
|
+
assert_data_from_server @fetcher.fetch_path(@server_uri)
|
|
168
|
+
assert_equal SERVER_DATA.size, @fetcher.fetch_size(@server_uri)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def util_fuck_with_fetcher data, blow = false
|
|
173
|
+
fetcher = LibGems::RemoteFetcher.fetcher
|
|
174
|
+
fetcher.instance_variable_set :@test_data, data
|
|
175
|
+
|
|
176
|
+
unless blow then
|
|
177
|
+
def fetcher.fetch_path arg
|
|
178
|
+
@test_arg = arg
|
|
179
|
+
@test_data
|
|
180
|
+
end
|
|
181
|
+
else
|
|
182
|
+
def fetcher.fetch_path arg
|
|
183
|
+
# OMG I'm such an ass
|
|
184
|
+
class << self; remove_method :fetch_path; end
|
|
185
|
+
def self.fetch_path arg
|
|
186
|
+
@test_arg = arg
|
|
187
|
+
@test_data
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
raise LibGems::RemoteFetcher::FetchError.new("haha!", nil)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
fetcher
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def test_download
|
|
198
|
+
a1_data = nil
|
|
199
|
+
File.open @a1_gem, 'rb' do |fp|
|
|
200
|
+
a1_data = fp.read
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
fetcher = util_fuck_with_fetcher a1_data
|
|
204
|
+
|
|
205
|
+
a1_cache_gem = File.join(@gemhome, 'cache', @a1.file_name)
|
|
206
|
+
assert_equal a1_cache_gem, fetcher.download(@a1, 'http://gems.example.com')
|
|
207
|
+
assert_equal("http://gems.example.com/gems/a-1.gem",
|
|
208
|
+
fetcher.instance_variable_get(:@test_arg).to_s)
|
|
209
|
+
assert File.exist?(a1_cache_gem)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def test_download_cached
|
|
213
|
+
FileUtils.mv @a1_gem, @cache_dir
|
|
214
|
+
|
|
215
|
+
inst = LibGems::RemoteFetcher.fetcher
|
|
216
|
+
|
|
217
|
+
assert_equal File.join(@gemhome, 'cache', @a1.file_name),
|
|
218
|
+
inst.download(@a1, 'http://gems.example.com')
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def test_download_local
|
|
222
|
+
FileUtils.mv @a1_gem, @tempdir
|
|
223
|
+
local_path = File.join @tempdir, @a1.file_name
|
|
224
|
+
inst = nil
|
|
225
|
+
|
|
226
|
+
Dir.chdir @tempdir do
|
|
227
|
+
inst = LibGems::RemoteFetcher.fetcher
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
assert_equal File.join(@gemhome, 'cache', @a1.file_name),
|
|
231
|
+
inst.download(@a1, local_path)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def test_download_local_space
|
|
235
|
+
space_path = File.join @tempdir, 'space path'
|
|
236
|
+
FileUtils.mkdir space_path
|
|
237
|
+
FileUtils.mv @a1_gem, space_path
|
|
238
|
+
local_path = File.join space_path, @a1.file_name
|
|
239
|
+
inst = nil
|
|
240
|
+
|
|
241
|
+
Dir.chdir @tempdir do
|
|
242
|
+
inst = LibGems::RemoteFetcher.fetcher
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
assert_equal File.join(@gemhome, 'cache', @a1.file_name),
|
|
246
|
+
inst.download(@a1, local_path)
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def test_download_install_dir
|
|
250
|
+
a1_data = nil
|
|
251
|
+
File.open @a1_gem, 'rb' do |fp|
|
|
252
|
+
a1_data = fp.read
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
fetcher = util_fuck_with_fetcher a1_data
|
|
256
|
+
|
|
257
|
+
install_dir = File.join @tempdir, 'more_gems'
|
|
258
|
+
|
|
259
|
+
a1_cache_gem = File.join install_dir, 'cache', @a1.file_name
|
|
260
|
+
FileUtils.mkdir_p(File.dirname(a1_cache_gem))
|
|
261
|
+
actual = fetcher.download(@a1, 'http://gems.example.com', install_dir)
|
|
262
|
+
|
|
263
|
+
assert_equal a1_cache_gem, actual
|
|
264
|
+
assert_equal("http://gems.example.com/gems/a-1.gem",
|
|
265
|
+
fetcher.instance_variable_get(:@test_arg).to_s)
|
|
266
|
+
|
|
267
|
+
assert File.exist?(a1_cache_gem)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
unless win_platform? # File.chmod doesn't work
|
|
271
|
+
def test_download_local_read_only
|
|
272
|
+
FileUtils.mv @a1_gem, @tempdir
|
|
273
|
+
local_path = File.join @tempdir, @a1.file_name
|
|
274
|
+
inst = nil
|
|
275
|
+
File.chmod 0555, File.join(@gemhome, 'cache')
|
|
276
|
+
|
|
277
|
+
Dir.chdir @tempdir do
|
|
278
|
+
inst = LibGems::RemoteFetcher.fetcher
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
assert_equal File.join(@tempdir, @a1.file_name),
|
|
282
|
+
inst.download(@a1, local_path)
|
|
283
|
+
ensure
|
|
284
|
+
File.chmod 0755, File.join(@gemhome, 'cache')
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def test_download_read_only
|
|
288
|
+
File.chmod 0555, File.join(@gemhome, 'cache')
|
|
289
|
+
File.chmod 0555, File.join(@gemhome)
|
|
290
|
+
|
|
291
|
+
fetcher = util_fuck_with_fetcher File.read(@a1_gem)
|
|
292
|
+
fetcher.download(@a1, 'http://gems.example.com')
|
|
293
|
+
assert File.exist?(File.join(LibGems.user_dir, 'cache', @a1.file_name))
|
|
294
|
+
ensure
|
|
295
|
+
File.chmod 0755, File.join(@gemhome)
|
|
296
|
+
File.chmod 0755, File.join(@gemhome, 'cache')
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def test_download_platform_legacy
|
|
301
|
+
original_platform = 'old-platform'
|
|
302
|
+
|
|
303
|
+
e1, e1_gem = util_gem 'e', '1' do |s|
|
|
304
|
+
s.platform = LibGems::Platform::CURRENT
|
|
305
|
+
s.instance_variable_set :@original_platform, original_platform
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
e1_data = nil
|
|
309
|
+
File.open e1_gem, 'rb' do |fp|
|
|
310
|
+
e1_data = fp.read
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
fetcher = util_fuck_with_fetcher e1_data, :blow_chunks
|
|
314
|
+
|
|
315
|
+
e1_cache_gem = File.join(@gemhome, 'cache', e1.file_name)
|
|
316
|
+
|
|
317
|
+
assert_equal e1_cache_gem, fetcher.download(e1, 'http://gems.example.com')
|
|
318
|
+
|
|
319
|
+
assert_equal("http://gems.example.com/gems/#{e1.original_name}.gem",
|
|
320
|
+
fetcher.instance_variable_get(:@test_arg).to_s)
|
|
321
|
+
assert File.exist?(e1_cache_gem)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def test_download_same_file
|
|
325
|
+
FileUtils.mv @a1_gem, @tempdir
|
|
326
|
+
local_path = File.join @tempdir, @a1.file_name
|
|
327
|
+
inst = nil
|
|
328
|
+
|
|
329
|
+
Dir.chdir @tempdir do
|
|
330
|
+
inst = LibGems::RemoteFetcher.fetcher
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
cache_path = File.join @gemhome, 'cache', @a1.file_name
|
|
334
|
+
FileUtils.mv local_path, cache_path
|
|
335
|
+
|
|
336
|
+
gem = LibGems::Format.from_file_by_path cache_path
|
|
337
|
+
|
|
338
|
+
assert_equal cache_path, inst.download(gem.spec, cache_path)
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def test_download_unsupported
|
|
342
|
+
inst = LibGems::RemoteFetcher.fetcher
|
|
343
|
+
|
|
344
|
+
e = assert_raises LibGems::InstallError do
|
|
345
|
+
inst.download @a1, 'ftp://gems.rubyforge.org'
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
assert_equal 'unsupported URI scheme ftp', e.message
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def test_explicit_proxy
|
|
352
|
+
use_ui @ui do
|
|
353
|
+
fetcher = LibGems::RemoteFetcher.new @proxy_uri
|
|
354
|
+
assert_equal PROXY_DATA.size, fetcher.fetch_size(@server_uri)
|
|
355
|
+
assert_data_from_proxy fetcher.fetch_path(@server_uri)
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def test_explicit_proxy_with_user_auth
|
|
360
|
+
use_ui @ui do
|
|
361
|
+
uri = URI.parse @proxy_uri
|
|
362
|
+
uri.user, uri.password = 'foo', 'bar'
|
|
363
|
+
fetcher = LibGems::RemoteFetcher.new uri.to_s
|
|
364
|
+
proxy = fetcher.instance_variable_get("@proxy_uri")
|
|
365
|
+
assert_equal 'foo', proxy.user
|
|
366
|
+
assert_equal 'bar', proxy.password
|
|
367
|
+
assert_data_from_proxy fetcher.fetch_path(@server_uri)
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
use_ui @ui do
|
|
371
|
+
uri = URI.parse @proxy_uri
|
|
372
|
+
uri.user, uri.password = 'domain%5Cuser', 'bar'
|
|
373
|
+
fetcher = LibGems::RemoteFetcher.new uri.to_s
|
|
374
|
+
proxy = fetcher.instance_variable_get("@proxy_uri")
|
|
375
|
+
assert_equal 'domain\user', URI.unescape(proxy.user)
|
|
376
|
+
assert_equal 'bar', proxy.password
|
|
377
|
+
assert_data_from_proxy fetcher.fetch_path(@server_uri)
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
use_ui @ui do
|
|
381
|
+
uri = URI.parse @proxy_uri
|
|
382
|
+
uri.user, uri.password = 'user', 'my%20pass'
|
|
383
|
+
fetcher = LibGems::RemoteFetcher.new uri.to_s
|
|
384
|
+
proxy = fetcher.instance_variable_get("@proxy_uri")
|
|
385
|
+
assert_equal 'user', proxy.user
|
|
386
|
+
assert_equal 'my pass', URI.unescape(proxy.password)
|
|
387
|
+
assert_data_from_proxy fetcher.fetch_path(@server_uri)
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def test_explicit_proxy_with_user_auth_in_env
|
|
392
|
+
use_ui @ui do
|
|
393
|
+
ENV['http_proxy'] = @proxy_uri
|
|
394
|
+
ENV['http_proxy_user'] = 'foo'
|
|
395
|
+
ENV['http_proxy_pass'] = 'bar'
|
|
396
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
397
|
+
proxy = fetcher.instance_variable_get("@proxy_uri")
|
|
398
|
+
assert_equal 'foo', proxy.user
|
|
399
|
+
assert_equal 'bar', proxy.password
|
|
400
|
+
assert_data_from_proxy fetcher.fetch_path(@server_uri)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
use_ui @ui do
|
|
404
|
+
ENV['http_proxy'] = @proxy_uri
|
|
405
|
+
ENV['http_proxy_user'] = 'foo\user'
|
|
406
|
+
ENV['http_proxy_pass'] = 'my bar'
|
|
407
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
408
|
+
proxy = fetcher.instance_variable_get("@proxy_uri")
|
|
409
|
+
assert_equal 'foo\user', URI.unescape(proxy.user)
|
|
410
|
+
assert_equal 'my bar', URI.unescape(proxy.password)
|
|
411
|
+
assert_data_from_proxy fetcher.fetch_path(@server_uri)
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
def test_fetch_path_gzip
|
|
416
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
417
|
+
|
|
418
|
+
def fetcher.open_uri_or_path(uri, mtime, head = nil)
|
|
419
|
+
LibGems.gzip 'foo'
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
assert_equal 'foo', fetcher.fetch_path(@uri + 'foo.gz')
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
def test_fetch_path_gzip_unmodified
|
|
426
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
427
|
+
|
|
428
|
+
def fetcher.open_uri_or_path(uri, mtime, head = nil)
|
|
429
|
+
nil
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
assert_equal nil, fetcher.fetch_path(@uri + 'foo.gz', Time.at(0))
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
def test_fetch_path_io_error
|
|
436
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
437
|
+
|
|
438
|
+
def fetcher.open_uri_or_path(uri, mtime, head = nil)
|
|
439
|
+
raise EOFError
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
e = assert_raises LibGems::RemoteFetcher::FetchError do
|
|
443
|
+
fetcher.fetch_path 'uri'
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
assert_equal 'EOFError: EOFError (uri)', e.message
|
|
447
|
+
assert_equal 'uri', e.uri
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
def test_fetch_path_socket_error
|
|
451
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
452
|
+
|
|
453
|
+
def fetcher.open_uri_or_path(uri, mtime, head = nil)
|
|
454
|
+
raise SocketError
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
e = assert_raises LibGems::RemoteFetcher::FetchError do
|
|
458
|
+
fetcher.fetch_path 'uri'
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
assert_equal 'SocketError: SocketError (uri)', e.message
|
|
462
|
+
assert_equal 'uri', e.uri
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def test_fetch_path_system_call_error
|
|
466
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
467
|
+
|
|
468
|
+
def fetcher.open_uri_or_path(uri, mtime = nil, head = nil)
|
|
469
|
+
raise Errno::ECONNREFUSED, 'connect(2)'
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
e = assert_raises LibGems::RemoteFetcher::FetchError do
|
|
473
|
+
fetcher.fetch_path 'uri'
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
assert_match %r|ECONNREFUSED:.*connect\(2\) \(uri\)\z|,
|
|
477
|
+
e.message
|
|
478
|
+
assert_equal 'uri', e.uri
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
def test_fetch_path_unmodified
|
|
482
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
483
|
+
|
|
484
|
+
def fetcher.open_uri_or_path(uri, mtime, head = nil)
|
|
485
|
+
nil
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
assert_equal nil, fetcher.fetch_path(URI.parse(@gem_repo), Time.at(0))
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
def test_get_proxy_from_env_auto_normalizes
|
|
492
|
+
fetcher = LibGems::RemoteFetcher.new(nil)
|
|
493
|
+
ENV['HTTP_PROXY'] = 'fakeurl:12345'
|
|
494
|
+
|
|
495
|
+
assert_equal('http://fakeurl:12345', fetcher.get_proxy_from_env.to_s)
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
def test_get_proxy_from_env_empty
|
|
499
|
+
orig_env_HTTP_PROXY = ENV['HTTP_PROXY']
|
|
500
|
+
orig_env_http_proxy = ENV['http_proxy']
|
|
501
|
+
|
|
502
|
+
ENV['HTTP_PROXY'] = ''
|
|
503
|
+
ENV.delete 'http_proxy'
|
|
504
|
+
|
|
505
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
506
|
+
|
|
507
|
+
assert_equal nil, fetcher.send(:get_proxy_from_env)
|
|
508
|
+
|
|
509
|
+
ensure
|
|
510
|
+
orig_env_HTTP_PROXY.nil? ? ENV.delete('HTTP_PROXY') :
|
|
511
|
+
ENV['HTTP_PROXY'] = orig_env_HTTP_PROXY
|
|
512
|
+
orig_env_http_proxy.nil? ? ENV.delete('http_proxy') :
|
|
513
|
+
ENV['http_proxy'] = orig_env_http_proxy
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
def test_implicit_no_proxy
|
|
517
|
+
use_ui @ui do
|
|
518
|
+
ENV['http_proxy'] = 'http://fakeurl:12345'
|
|
519
|
+
fetcher = LibGems::RemoteFetcher.new :no_proxy
|
|
520
|
+
assert_data_from_server fetcher.fetch_path(@server_uri)
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
def test_implicit_proxy
|
|
525
|
+
use_ui @ui do
|
|
526
|
+
ENV['http_proxy'] = @proxy_uri
|
|
527
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
528
|
+
assert_data_from_proxy fetcher.fetch_path(@server_uri)
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
def test_implicit_upper_case_proxy
|
|
533
|
+
use_ui @ui do
|
|
534
|
+
ENV['HTTP_PROXY'] = @proxy_uri
|
|
535
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
536
|
+
assert_data_from_proxy fetcher.fetch_path(@server_uri)
|
|
537
|
+
end
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def test_implicit_proxy_no_env
|
|
541
|
+
use_ui @ui do
|
|
542
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
543
|
+
assert_data_from_server fetcher.fetch_path(@server_uri)
|
|
544
|
+
end
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
def test_open_uri_or_path
|
|
548
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
549
|
+
|
|
550
|
+
conn = Object.new
|
|
551
|
+
def conn.started?() true end
|
|
552
|
+
def conn.request(req)
|
|
553
|
+
unless defined? @requested then
|
|
554
|
+
@requested = true
|
|
555
|
+
res = Net::HTTPMovedPermanently.new nil, 301, nil
|
|
556
|
+
res.add_field 'Location', 'http://gems.example.com/real_path'
|
|
557
|
+
res
|
|
558
|
+
else
|
|
559
|
+
res = Net::HTTPOK.new nil, 200, nil
|
|
560
|
+
def res.body() 'real_path' end
|
|
561
|
+
res
|
|
562
|
+
end
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
conn = { "#{Thread.current.object_id}:gems.example.com:80" => conn }
|
|
566
|
+
fetcher.instance_variable_set :@connections, conn
|
|
567
|
+
|
|
568
|
+
data = fetcher.open_uri_or_path 'http://gems.example.com/redirect'
|
|
569
|
+
|
|
570
|
+
assert_equal 'real_path', data
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
def test_open_uri_or_path_limited_redirects
|
|
574
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
575
|
+
|
|
576
|
+
conn = Object.new
|
|
577
|
+
def conn.started?() true end
|
|
578
|
+
def conn.request(req)
|
|
579
|
+
res = Net::HTTPMovedPermanently.new nil, 301, nil
|
|
580
|
+
res.add_field 'Location', 'http://gems.example.com/redirect'
|
|
581
|
+
res
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
conn = { "#{Thread.current.object_id}:gems.example.com:80" => conn }
|
|
585
|
+
fetcher.instance_variable_set :@connections, conn
|
|
586
|
+
|
|
587
|
+
e = assert_raises LibGems::RemoteFetcher::FetchError do
|
|
588
|
+
fetcher.open_uri_or_path 'http://gems.example.com/redirect'
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
assert_equal 'too many redirects (http://gems.example.com/redirect)',
|
|
592
|
+
e.message
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
def test_request
|
|
596
|
+
uri = URI.parse "#{@gem_repo}/specs.#{LibGems.marshal_version}"
|
|
597
|
+
util_stub_connection_for :body => :junk, :code => 200
|
|
598
|
+
|
|
599
|
+
response = @fetcher.request uri, Net::HTTP::Get
|
|
600
|
+
|
|
601
|
+
assert_equal 200, response.code
|
|
602
|
+
assert_equal :junk, response.body
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
def test_request_head
|
|
606
|
+
uri = URI.parse "#{@gem_repo}/specs.#{LibGems.marshal_version}"
|
|
607
|
+
util_stub_connection_for :body => '', :code => 200
|
|
608
|
+
response = @fetcher.request uri, Net::HTTP::Head
|
|
609
|
+
|
|
610
|
+
assert_equal 200, response.code
|
|
611
|
+
assert_equal '', response.body
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
def test_request_unmodifed
|
|
615
|
+
uri = URI.parse "#{@gem_repo}/specs.#{LibGems.marshal_version}"
|
|
616
|
+
conn = util_stub_connection_for :body => '', :code => 304
|
|
617
|
+
|
|
618
|
+
t = Time.now
|
|
619
|
+
response = @fetcher.request uri, Net::HTTP::Head, t
|
|
620
|
+
|
|
621
|
+
assert_equal 304, response.code
|
|
622
|
+
assert_equal '', response.body
|
|
623
|
+
|
|
624
|
+
assert_equal t.rfc2822, conn.payload['if-modified-since']
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
def test_yaml_error_on_size
|
|
628
|
+
use_ui @ui do
|
|
629
|
+
self.class.enable_yaml = false
|
|
630
|
+
fetcher = LibGems::RemoteFetcher.new nil
|
|
631
|
+
assert_error { fetcher.size }
|
|
632
|
+
end
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
def util_stub_connection_for hash
|
|
636
|
+
def @fetcher.connection= conn
|
|
637
|
+
@conn = conn
|
|
638
|
+
end
|
|
639
|
+
|
|
640
|
+
def @fetcher.connection_for uri
|
|
641
|
+
@conn
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
@fetcher.connection = Conn.new OpenStruct.new(hash)
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
def assert_error(exception_class=Exception)
|
|
648
|
+
got_exception = false
|
|
649
|
+
begin
|
|
650
|
+
yield
|
|
651
|
+
rescue exception_class => ex
|
|
652
|
+
got_exception = true
|
|
653
|
+
end
|
|
654
|
+
assert got_exception, "Expected exception conforming to #{exception_class}"
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
def assert_data_from_server(data)
|
|
658
|
+
assert_block("Data is not from server") { data =~ /0\.4\.11/ }
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
def assert_data_from_proxy(data)
|
|
662
|
+
assert_block("Data is not from proxy") { data =~ /0\.4\.2/ }
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
class Conn
|
|
666
|
+
attr_accessor :payload
|
|
667
|
+
|
|
668
|
+
def initialize(response)
|
|
669
|
+
@response = response
|
|
670
|
+
self.payload = nil
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
def request(req)
|
|
674
|
+
self.payload = req
|
|
675
|
+
@response
|
|
676
|
+
end
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
class NilLog < WEBrick::Log
|
|
680
|
+
def log(level, data) #Do nothing
|
|
681
|
+
end
|
|
682
|
+
end
|
|
683
|
+
|
|
684
|
+
class << self
|
|
685
|
+
attr_reader :normal_server, :proxy_server
|
|
686
|
+
attr_accessor :enable_zip, :enable_yaml
|
|
687
|
+
|
|
688
|
+
def start_servers
|
|
689
|
+
@normal_server ||= start_server(SERVER_PORT, SERVER_DATA)
|
|
690
|
+
@proxy_server ||= start_server(PROXY_PORT, PROXY_DATA)
|
|
691
|
+
@enable_yaml = true
|
|
692
|
+
@enable_zip = false
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
private
|
|
696
|
+
|
|
697
|
+
def start_server(port, data)
|
|
698
|
+
Thread.new do
|
|
699
|
+
begin
|
|
700
|
+
null_logger = NilLog.new
|
|
701
|
+
s = WEBrick::HTTPServer.new(
|
|
702
|
+
:Port => port,
|
|
703
|
+
:DocumentRoot => nil,
|
|
704
|
+
:Logger => null_logger,
|
|
705
|
+
:AccessLog => null_logger
|
|
706
|
+
)
|
|
707
|
+
s.mount_proc("/kill") { |req, res| s.shutdown }
|
|
708
|
+
s.mount_proc("/yaml") { |req, res|
|
|
709
|
+
if @enable_yaml
|
|
710
|
+
res.body = data
|
|
711
|
+
res['Content-Type'] = 'text/plain'
|
|
712
|
+
res['content-length'] = data.size
|
|
713
|
+
else
|
|
714
|
+
res.status = "404"
|
|
715
|
+
res.body = "<h1>NOT FOUND</h1>"
|
|
716
|
+
res['Content-Type'] = 'text/html'
|
|
717
|
+
end
|
|
718
|
+
}
|
|
719
|
+
s.mount_proc("/yaml.Z") { |req, res|
|
|
720
|
+
if @enable_zip
|
|
721
|
+
res.body = Zlib::Deflate.deflate(data)
|
|
722
|
+
res['Content-Type'] = 'text/plain'
|
|
723
|
+
else
|
|
724
|
+
res.status = "404"
|
|
725
|
+
res.body = "<h1>NOT FOUND</h1>"
|
|
726
|
+
res['Content-Type'] = 'text/html'
|
|
727
|
+
end
|
|
728
|
+
}
|
|
729
|
+
s.start
|
|
730
|
+
rescue Exception => ex
|
|
731
|
+
abort ex.message
|
|
732
|
+
puts "ERROR during server thread: #{ex.message}"
|
|
733
|
+
end
|
|
734
|
+
end
|
|
735
|
+
sleep 0.2 # Give the servers time to startup
|
|
736
|
+
end
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
end
|
|
740
|
+
|