rubygems-update 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubygems-update might be problematic. Click here for more details.
- data.tar.gz.sig +0 -0
- data/ChangeLog +267 -1
- data/Rakefile +13 -7
- data/doc/release_notes/rel_1_2_0.rdoc +105 -0
- data/lib/rubygems.rb +82 -14
- data/lib/rubygems/command.rb +1 -1
- data/lib/rubygems/command_manager.rb +3 -2
- data/lib/rubygems/commands/cert_command.rb +1 -1
- data/lib/rubygems/commands/dependency_command.rb +57 -19
- data/lib/rubygems/commands/environment_command.rb +2 -0
- data/lib/rubygems/commands/fetch_command.rb +3 -1
- data/lib/rubygems/commands/install_command.rb +3 -3
- data/lib/rubygems/commands/list_command.rb +30 -28
- data/lib/rubygems/commands/lock_command.rb +1 -1
- data/lib/rubygems/commands/outdated_command.rb +5 -2
- data/lib/rubygems/commands/pristine_command.rb +3 -44
- data/lib/rubygems/commands/query_command.rb +80 -21
- data/lib/rubygems/commands/sources_command.rb +56 -28
- data/lib/rubygems/commands/specification_command.rb +4 -3
- data/lib/rubygems/commands/stale_command.rb +27 -0
- data/lib/rubygems/commands/update_command.rb +35 -22
- data/lib/rubygems/config_file.rb +29 -12
- data/lib/rubygems/custom_require.rb +1 -1
- data/lib/rubygems/defaults.rb +1 -1
- data/lib/rubygems/dependency.rb +63 -9
- data/lib/rubygems/dependency_installer.rb +60 -23
- data/lib/rubygems/dependency_list.rb +1 -1
- data/lib/rubygems/doc_manager.rb +5 -5
- data/lib/rubygems/gem_openssl.rb +1 -1
- data/lib/rubygems/indexer.rb +269 -84
- data/lib/rubygems/install_update_options.rb +6 -0
- data/lib/rubygems/installer.rb +35 -12
- data/lib/rubygems/local_remote_options.rb +26 -5
- data/lib/rubygems/platform.rb +15 -1
- data/lib/rubygems/remote_fetcher.rb +158 -90
- data/lib/rubygems/requirement.rb +16 -12
- data/lib/rubygems/rubygems_version.rb +1 -1
- data/lib/rubygems/security.rb +2 -2
- data/lib/rubygems/server.rb +239 -110
- data/lib/rubygems/source_index.rb +44 -18
- data/lib/rubygems/source_info_cache.rb +1 -1
- data/lib/rubygems/spec_fetcher.rb +251 -0
- data/lib/rubygems/specification.rb +120 -38
- data/lib/rubygems/test_utilities.rb +120 -0
- data/lib/rubygems/uninstaller.rb +11 -10
- data/lib/rubygems/user_interaction.rb +149 -74
- data/lib/rubygems/validator.rb +3 -3
- data/lib/rubygems/version.rb +23 -21
- data/setup.rb +105 -100
- data/test/gemutilities.rb +63 -86
- data/test/test_config.rb +0 -5
- data/test/test_gem.rb +22 -2
- data/test/test_gem_command_manager.rb +1 -1
- data/test/test_gem_commands_dependency_command.rb +125 -6
- data/test/test_gem_commands_environment_command.rb +1 -0
- data/test/test_gem_commands_fetch_command.rb +24 -4
- data/test/test_gem_commands_install_command.rb +6 -8
- data/test/{test_gem_outdated_command.rb → test_gem_commands_outdated_command.rb} +5 -2
- data/test/test_gem_commands_pristine_command.rb +13 -4
- data/test/test_gem_commands_query_command.rb +113 -37
- data/test/test_gem_commands_sources_command.rb +101 -31
- data/test/test_gem_commands_specification_command.rb +4 -1
- data/test/test_gem_commands_stale_command.rb +39 -0
- data/test/test_gem_commands_update_command.rb +17 -27
- data/test/test_gem_config_file.rb +38 -1
- data/test/test_gem_dependency.rb +51 -0
- data/test/test_gem_dependency_installer.rb +133 -25
- data/test/test_gem_gem_path_searcher.rb +4 -1
- data/test/test_gem_indexer.rb +124 -19
- data/test/test_gem_installer.rb +32 -2
- data/test/test_gem_local_remote_options.rb +6 -5
- data/test/test_gem_remote_fetcher.rb +14 -9
- data/test/test_gem_server.rb +207 -21
- data/test/test_gem_source_index.rb +203 -63
- data/test/test_gem_source_info_cache.rb +8 -6
- data/test/test_gem_source_info_cache_entry.rb +11 -9
- data/test/test_gem_spec_fetcher.rb +303 -0
- data/test/test_gem_specification.rb +91 -7
- data/test/test_gem_uninstaller.rb +21 -0
- data/test/test_gem_version.rb +14 -5
- data/test/test_kernel.rb +1 -1
- metadata +10 -73
- metadata.gz.sig +0 -0
- data/lib/rubygems/indexer/abstract_index_builder.rb +0 -88
- data/lib/rubygems/indexer/latest_index_builder.rb +0 -35
- data/lib/rubygems/indexer/marshal_index_builder.rb +0 -17
- data/lib/rubygems/indexer/master_index_builder.rb +0 -54
- data/lib/rubygems/indexer/quick_index_builder.rb +0 -50
- data/test/gem_installer_test_case.rbc +0 -0
- data/test/gem_package_tar_test_case.rbc +0 -0
- data/test/gemutilities.rbc +0 -0
- data/test/mockgemui.rbc +0 -0
- data/test/simple_gem.rbc +0 -0
- data/test/test_config.rbc +0 -0
- data/test/test_gem.rbc +0 -0
- data/test/test_gem_builder.rbc +0 -0
- data/test/test_gem_command.rbc +0 -0
- data/test/test_gem_command_manager.rbc +0 -0
- data/test/test_gem_commands_build_command.rbc +0 -0
- data/test/test_gem_commands_cert_command.rbc +0 -0
- data/test/test_gem_commands_check_command.rbc +0 -0
- data/test/test_gem_commands_contents_command.rbc +0 -0
- data/test/test_gem_commands_dependency_command.rbc +0 -0
- data/test/test_gem_commands_environment_command.rbc +0 -0
- data/test/test_gem_commands_fetch_command.rbc +0 -0
- data/test/test_gem_commands_generate_index_command.rbc +0 -0
- data/test/test_gem_commands_install_command.rbc +0 -0
- data/test/test_gem_commands_mirror_command.rbc +0 -0
- data/test/test_gem_commands_pristine_command.rbc +0 -0
- data/test/test_gem_commands_query_command.rbc +0 -0
- data/test/test_gem_commands_server_command.rbc +0 -0
- data/test/test_gem_commands_sources_command.rbc +0 -0
- data/test/test_gem_commands_specification_command.rbc +0 -0
- data/test/test_gem_commands_unpack_command.rbc +0 -0
- data/test/test_gem_commands_update_command.rbc +0 -0
- data/test/test_gem_config_file.rbc +0 -0
- data/test/test_gem_dependency.rbc +0 -0
- data/test/test_gem_dependency_installer.rbc +0 -0
- data/test/test_gem_dependency_list.rbc +0 -0
- data/test/test_gem_digest.rbc +0 -0
- data/test/test_gem_doc_manager.rbc +0 -0
- data/test/test_gem_ext_configure_builder.rbc +0 -0
- data/test/test_gem_ext_ext_conf_builder.rbc +0 -0
- data/test/test_gem_ext_rake_builder.rbc +0 -0
- data/test/test_gem_format.rbc +0 -0
- data/test/test_gem_gem_path_searcher.rbc +0 -0
- data/test/test_gem_gem_runner.rbc +0 -0
- data/test/test_gem_indexer.rbc +0 -0
- data/test/test_gem_install_update_options.rbc +0 -0
- data/test/test_gem_installer.rbc +0 -0
- data/test/test_gem_local_remote_options.rbc +0 -0
- data/test/test_gem_outdated_command.rbc +0 -0
- data/test/test_gem_package_tar_header.rbc +0 -0
- data/test/test_gem_package_tar_input.rbc +0 -0
- data/test/test_gem_package_tar_output.rbc +0 -0
- data/test/test_gem_package_tar_reader.rbc +0 -0
- data/test/test_gem_package_tar_reader_entry.rbc +0 -0
- data/test/test_gem_package_tar_writer.rbc +0 -0
- data/test/test_gem_platform.rbc +0 -0
- data/test/test_gem_remote_fetcher.rbc +0 -0
- data/test/test_gem_requirement.rbc +0 -0
- data/test/test_gem_server.rbc +0 -0
- data/test/test_gem_source_index.rbc +0 -0
- data/test/test_gem_source_info_cache.rbc +0 -0
- data/test/test_gem_source_info_cache_entry.rbc +0 -0
- data/test/test_gem_specification.rbc +0 -0
- data/test/test_gem_stream_ui.rbc +0 -0
- data/test/test_gem_uninstaller.rbc +0 -0
- data/test/test_gem_validator.rbc +0 -0
- data/test/test_gem_version.rbc +0 -0
- data/test/test_gem_version_option.rbc +0 -0
- data/test/test_kernel.rbc +0 -0
@@ -1,9 +1,12 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rubygems/dependency_list'
|
3
3
|
require 'rubygems/installer'
|
4
|
-
require 'rubygems/
|
4
|
+
require 'rubygems/spec_fetcher'
|
5
5
|
require 'rubygems/user_interaction'
|
6
6
|
|
7
|
+
##
|
8
|
+
# Installs a gem along with all its dependencies from local and remote gems.
|
9
|
+
|
7
10
|
class Gem::DependencyInstaller
|
8
11
|
|
9
12
|
include Gem::UserInteraction
|
@@ -25,36 +28,50 @@ class Gem::DependencyInstaller
|
|
25
28
|
# Creates a new installer instance.
|
26
29
|
#
|
27
30
|
# Options are:
|
28
|
-
# :
|
31
|
+
# :cache_dir:: Alternate repository path to store .gem files in.
|
29
32
|
# :domain:: :local, :remote, or :both. :local only searches gems in the
|
30
33
|
# current directory. :remote searches only gems in Gem::sources.
|
31
34
|
# :both searches both.
|
35
|
+
# :env_shebang:: See Gem::Installer::new.
|
32
36
|
# :force:: See Gem::Installer#install.
|
33
37
|
# :format_executable:: See Gem::Installer#initialize.
|
34
|
-
# :ignore_dependencies
|
35
|
-
# :install_dir
|
36
|
-
# :security_policy
|
37
|
-
# :wrappers
|
38
|
+
# :ignore_dependencies:: Don't install any dependencies.
|
39
|
+
# :install_dir:: See Gem::Installer#install.
|
40
|
+
# :security_policy:: See Gem::Installer::new and Gem::Security.
|
41
|
+
# :wrappers:: See Gem::Installer::new
|
42
|
+
|
38
43
|
def initialize(options = {})
|
39
44
|
options = DEFAULT_OPTIONS.merge options
|
40
|
-
|
45
|
+
|
46
|
+
@bin_dir = options[:bin_dir]
|
47
|
+
@development = options[:development]
|
41
48
|
@domain = options[:domain]
|
49
|
+
@env_shebang = options[:env_shebang]
|
42
50
|
@force = options[:force]
|
43
51
|
@format_executable = options[:format_executable]
|
44
52
|
@ignore_dependencies = options[:ignore_dependencies]
|
45
|
-
@install_dir = options[:install_dir] || Gem.dir
|
46
53
|
@security_policy = options[:security_policy]
|
47
54
|
@wrappers = options[:wrappers]
|
48
|
-
@bin_dir = options[:bin_dir]
|
49
55
|
|
50
56
|
@installed_gems = []
|
57
|
+
|
58
|
+
@install_dir = options[:install_dir] || Gem.dir
|
59
|
+
@cache_dir = options[:cache_dir] || @install_dir
|
60
|
+
|
61
|
+
if options[:install_dir] then
|
62
|
+
spec_dir = File.join @install_dir, 'specifications'
|
63
|
+
@source_index = Gem::SourceIndex.from_gems_in spec_dir
|
64
|
+
else
|
65
|
+
@source_index = Gem.source_index
|
66
|
+
end
|
51
67
|
end
|
52
68
|
|
53
69
|
##
|
54
70
|
# Returns a list of pairs of gemspecs and source_uris that match
|
55
71
|
# Gem::Dependency +dep+ from both local (Dir.pwd) and remote (Gem.sources)
|
56
72
|
# sources. Gems are sorted with newer gems prefered over older gems, and
|
57
|
-
# local gems
|
73
|
+
# local gems preferred over remote gems.
|
74
|
+
|
58
75
|
def find_gems_with_sources(dep)
|
59
76
|
gems_and_sources = []
|
60
77
|
|
@@ -74,8 +91,7 @@ class Gem::DependencyInstaller
|
|
74
91
|
all = requirements.length > 1 ||
|
75
92
|
(requirements.first != ">=" and requirements.first != ">")
|
76
93
|
|
77
|
-
found = Gem::
|
78
|
-
|
94
|
+
found = Gem::SpecFetcher.fetcher.fetch dep, all
|
79
95
|
gems_and_sources.push(*found)
|
80
96
|
|
81
97
|
rescue Gem::RemoteFetcher::FetchError => e
|
@@ -95,6 +111,7 @@ class Gem::DependencyInstaller
|
|
95
111
|
##
|
96
112
|
# Gathers all dependencies necessary for the installation from local and
|
97
113
|
# remote sources unless the ignore_dependencies was given.
|
114
|
+
|
98
115
|
def gather_dependencies
|
99
116
|
specs = @specs_and_sources.map { |spec,_| spec }
|
100
117
|
|
@@ -110,14 +127,25 @@ class Gem::DependencyInstaller
|
|
110
127
|
next if spec.nil? or seen[spec.name]
|
111
128
|
seen[spec.name] = true
|
112
129
|
|
113
|
-
spec.
|
114
|
-
|
130
|
+
deps = spec.runtime_dependencies
|
131
|
+
deps |= spec.development_dependencies if @development
|
132
|
+
|
133
|
+
deps.each do |dep|
|
134
|
+
results = find_gems_with_sources(dep).reverse
|
135
|
+
|
136
|
+
results.reject! do |dep_spec,|
|
137
|
+
to_do.push dep_spec
|
138
|
+
|
139
|
+
@source_index.any? do |_, installed_spec|
|
140
|
+
dep.name == installed_spec.name and
|
141
|
+
dep.version_requirements.satisfied_by? installed_spec.version
|
142
|
+
end
|
143
|
+
end
|
115
144
|
|
116
145
|
results.each do |dep_spec, source_uri|
|
117
146
|
next if seen[dep_spec.name]
|
118
147
|
@specs_and_sources << [dep_spec, source_uri]
|
119
148
|
dependency_list.add dep_spec
|
120
|
-
to_do.push dep_spec
|
121
149
|
end
|
122
150
|
end
|
123
151
|
end
|
@@ -126,6 +154,11 @@ class Gem::DependencyInstaller
|
|
126
154
|
@gems_to_install = dependency_list.dependency_order.reverse
|
127
155
|
end
|
128
156
|
|
157
|
+
##
|
158
|
+
# Finds a spec and the source_uri it came from for gem +gem_name+ and
|
159
|
+
# +version+. Returns an Array of specs and sources required for
|
160
|
+
# installation of the gem.
|
161
|
+
|
129
162
|
def find_spec_by_name_and_version gem_name, version = Gem::Requirement.default
|
130
163
|
spec_and_source = nil
|
131
164
|
|
@@ -160,14 +193,16 @@ class Gem::DependencyInstaller
|
|
160
193
|
|
161
194
|
if spec_and_source.nil? then
|
162
195
|
raise Gem::GemNotFoundException,
|
163
|
-
"could not find #{gem_name} locally or in a repository"
|
196
|
+
"could not find gem #{gem_name} locally or in a repository"
|
164
197
|
end
|
165
198
|
|
166
199
|
@specs_and_sources = [spec_and_source]
|
167
200
|
end
|
168
201
|
|
169
202
|
##
|
170
|
-
# Installs the gem and all its dependencies.
|
203
|
+
# Installs the gem and all its dependencies. Returns an Array of installed
|
204
|
+
# gems specifications.
|
205
|
+
|
171
206
|
def install dep_or_name, version = Gem::Requirement.default
|
172
207
|
if String === dep_or_name then
|
173
208
|
find_spec_by_name_and_version dep_or_name, version
|
@@ -175,15 +210,14 @@ class Gem::DependencyInstaller
|
|
175
210
|
@specs_and_sources = [find_gems_with_sources(dep_or_name).last]
|
176
211
|
end
|
177
212
|
|
178
|
-
|
213
|
+
@installed_gems = []
|
179
214
|
|
180
|
-
|
181
|
-
source_index = Gem::SourceIndex.from_gems_in spec_dir
|
215
|
+
gather_dependencies
|
182
216
|
|
183
217
|
@gems_to_install.each do |spec|
|
184
218
|
last = spec == @gems_to_install.last
|
185
219
|
# HACK is this test for full_name acceptable?
|
186
|
-
next if source_index.any? { |n,_| n == spec.full_name } and not last
|
220
|
+
next if @source_index.any? { |n,_| n == spec.full_name } and not last
|
187
221
|
|
188
222
|
# TODO: make this sorta_verbose so other users can benefit from it
|
189
223
|
say "Installing gem #{spec.full_name}" if Gem.configuration.really_verbose
|
@@ -191,7 +225,7 @@ class Gem::DependencyInstaller
|
|
191
225
|
_, source_uri = @specs_and_sources.assoc spec
|
192
226
|
begin
|
193
227
|
local_gem_path = Gem::RemoteFetcher.fetcher.download spec, source_uri,
|
194
|
-
@
|
228
|
+
@cache_dir
|
195
229
|
rescue Gem::RemoteFetcher::FetchError
|
196
230
|
next if @force
|
197
231
|
raise
|
@@ -205,12 +239,15 @@ class Gem::DependencyInstaller
|
|
205
239
|
:install_dir => @install_dir,
|
206
240
|
:security_policy => @security_policy,
|
207
241
|
:wrappers => @wrappers,
|
208
|
-
:bin_dir => @bin_dir
|
242
|
+
:bin_dir => @bin_dir,
|
243
|
+
:development => @development
|
209
244
|
|
210
245
|
spec = inst.install
|
211
246
|
|
212
247
|
@installed_gems << spec
|
213
248
|
end
|
249
|
+
|
250
|
+
@installed_gems
|
214
251
|
end
|
215
252
|
|
216
253
|
end
|
data/lib/rubygems/doc_manager.rb
CHANGED
@@ -9,9 +9,9 @@ require 'fileutils'
|
|
9
9
|
module Gem
|
10
10
|
|
11
11
|
class DocManager
|
12
|
-
|
12
|
+
|
13
13
|
include UserInteraction
|
14
|
-
|
14
|
+
|
15
15
|
# Create a document manager for the given gem spec.
|
16
16
|
#
|
17
17
|
# spec:: The Gem::Specification object representing the gem.
|
@@ -22,12 +22,12 @@ module Gem
|
|
22
22
|
@doc_dir = File.join(spec.installation_path, "doc", spec.full_name)
|
23
23
|
@rdoc_args = rdoc_args.nil? ? [] : rdoc_args.split
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Is the RDoc documentation installed?
|
27
27
|
def rdoc_installed?
|
28
28
|
return File.exist?(File.join(@doc_dir, "rdoc"))
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
# Generate the RI documents for this gem spec.
|
32
32
|
#
|
33
33
|
# Note that if both RI and RDoc documents are generated from the
|
@@ -102,7 +102,7 @@ module Gem
|
|
102
102
|
args << '--quiet'
|
103
103
|
args << @spec.require_paths.clone
|
104
104
|
args << @spec.extra_rdoc_files
|
105
|
-
args.flatten
|
105
|
+
args = args.flatten.map do |arg| arg.to_s end
|
106
106
|
|
107
107
|
r = RDoc::RDoc.new
|
108
108
|
|
data/lib/rubygems/gem_openssl.rb
CHANGED
data/lib/rubygems/indexer.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'tmpdir'
|
3
|
+
require 'zlib'
|
3
4
|
|
4
5
|
require 'rubygems'
|
5
6
|
require 'rubygems/format'
|
@@ -40,116 +41,304 @@ class Gem::Indexer
|
|
40
41
|
|
41
42
|
marshal_name = "Marshal.#{Gem.marshal_version}"
|
42
43
|
|
43
|
-
@master_index =
|
44
|
-
@marshal_index =
|
45
|
-
@quick_index = Gem::Indexer::QuickIndexBuilder.new 'index', @directory
|
44
|
+
@master_index = File.join @directory, 'yaml'
|
45
|
+
@marshal_index = File.join @directory, marshal_name
|
46
46
|
|
47
|
-
quick_dir = File.join @directory, 'quick'
|
48
|
-
|
47
|
+
@quick_dir = File.join @directory, 'quick'
|
48
|
+
|
49
|
+
@quick_marshal_dir = File.join @quick_dir, marshal_name
|
50
|
+
|
51
|
+
@quick_index = File.join @quick_dir, 'index'
|
52
|
+
@latest_index = File.join @quick_dir, 'latest_index'
|
53
|
+
|
54
|
+
@specs_index = File.join @directory, "specs.#{Gem.marshal_version}"
|
55
|
+
@latest_specs_index = File.join @directory,
|
56
|
+
"latest_specs.#{Gem.marshal_version}"
|
57
|
+
|
58
|
+
files = [
|
59
|
+
@specs_index,
|
60
|
+
"#{@specs_index}.gz",
|
61
|
+
@latest_specs_index,
|
62
|
+
"#{@latest_specs_index}.gz",
|
63
|
+
@quick_dir,
|
64
|
+
@master_index,
|
65
|
+
"#{@master_index}.Z",
|
66
|
+
@marshal_index,
|
67
|
+
"#{@marshal_index}.Z",
|
68
|
+
]
|
69
|
+
|
70
|
+
@files = files.map do |path|
|
71
|
+
path.sub @directory, ''
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Abbreviate the spec for downloading. Abbreviated specs are only used for
|
77
|
+
# searching, downloading and related activities and do not need deployment
|
78
|
+
# specific information (e.g. list of files). So we abbreviate the spec,
|
79
|
+
# making it much smaller for quicker downloads.
|
80
|
+
|
81
|
+
def abbreviate(spec)
|
82
|
+
spec.files = []
|
83
|
+
spec.test_files = []
|
84
|
+
spec.rdoc_options = []
|
85
|
+
spec.extra_rdoc_files = []
|
86
|
+
spec.cert_chain = []
|
87
|
+
spec
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# Build various indicies
|
92
|
+
|
93
|
+
def build_indicies(index)
|
94
|
+
progress = ui.progress_reporter index.size,
|
95
|
+
"Generating quick index gemspecs for #{index.size} gems",
|
96
|
+
"Complete"
|
97
|
+
|
98
|
+
index.each do |original_name, spec|
|
99
|
+
spec_file_name = "#{original_name}.gemspec.rz"
|
100
|
+
yaml_name = File.join @quick_dir, spec_file_name
|
101
|
+
marshal_name = File.join @quick_marshal_dir, spec_file_name
|
102
|
+
|
103
|
+
yaml_zipped = Gem.deflate spec.to_yaml
|
104
|
+
open yaml_name, 'wb' do |io| io.write yaml_zipped end
|
105
|
+
|
106
|
+
marshal_zipped = Gem.deflate Marshal.dump(spec)
|
107
|
+
open marshal_name, 'wb' do |io| io.write marshal_zipped end
|
108
|
+
|
109
|
+
progress.updated original_name
|
110
|
+
end
|
111
|
+
|
112
|
+
progress.done
|
113
|
+
|
114
|
+
say "Generating specs index"
|
115
|
+
|
116
|
+
open @specs_index, 'wb' do |io|
|
117
|
+
specs = index.sort.map do |_, spec|
|
118
|
+
platform = spec.original_platform
|
119
|
+
platform = Gem::Platform::RUBY if platform.nil?
|
120
|
+
[spec.name, spec.version, platform]
|
121
|
+
end
|
122
|
+
|
123
|
+
specs = compact_specs specs
|
124
|
+
|
125
|
+
Marshal.dump specs, io
|
126
|
+
end
|
127
|
+
|
128
|
+
say "Generating latest specs index"
|
129
|
+
|
130
|
+
open @latest_specs_index, 'wb' do |io|
|
131
|
+
specs = index.latest_specs.sort.map do |spec|
|
132
|
+
[spec.name, spec.version, spec.original_platform]
|
133
|
+
end
|
134
|
+
|
135
|
+
specs = compact_specs specs
|
136
|
+
|
137
|
+
Marshal.dump specs, io
|
138
|
+
end
|
139
|
+
|
140
|
+
say "Generating quick index"
|
141
|
+
|
142
|
+
quick_index = File.join @quick_dir, 'index'
|
143
|
+
open quick_index, 'wb' do |io|
|
144
|
+
io.puts index.sort.map { |_, spec| spec.original_name }
|
145
|
+
end
|
146
|
+
|
147
|
+
say "Generating latest index"
|
148
|
+
|
149
|
+
latest_index = File.join @quick_dir, 'latest_index'
|
150
|
+
open latest_index, 'wb' do |io|
|
151
|
+
io.puts index.latest_specs.sort.map { |spec| spec.original_name }
|
152
|
+
end
|
153
|
+
|
154
|
+
say "Generating Marshal master index"
|
155
|
+
|
156
|
+
open @marshal_index, 'wb' do |io|
|
157
|
+
io.write index.dump
|
158
|
+
end
|
159
|
+
|
160
|
+
progress = ui.progress_reporter index.size,
|
161
|
+
"Generating YAML master index for #{index.size} gems (this may take a while)",
|
162
|
+
"Complete"
|
163
|
+
|
164
|
+
open @master_index, 'wb' do |io|
|
165
|
+
io.puts "--- !ruby/object:#{index.class}"
|
166
|
+
io.puts "gems:"
|
167
|
+
|
168
|
+
gems = index.sort_by { |name, gemspec| gemspec.sort_obj }
|
169
|
+
gems.each do |original_name, gemspec|
|
170
|
+
yaml = gemspec.to_yaml.gsub(/^/, ' ')
|
171
|
+
yaml = yaml.sub(/\A ---/, '') # there's a needed extra ' ' here
|
172
|
+
io.print " #{original_name}:"
|
173
|
+
io.puts yaml
|
174
|
+
|
175
|
+
progress.updated original_name
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
progress.done
|
180
|
+
|
181
|
+
say "Compressing indicies"
|
182
|
+
# use gzip for future files.
|
183
|
+
|
184
|
+
compress quick_index, 'rz'
|
185
|
+
paranoid quick_index, 'rz'
|
186
|
+
|
187
|
+
compress latest_index, 'rz'
|
188
|
+
paranoid latest_index, 'rz'
|
189
|
+
|
190
|
+
compress @marshal_index, 'Z'
|
191
|
+
paranoid @marshal_index, 'Z'
|
192
|
+
|
193
|
+
compress @master_index, 'Z'
|
194
|
+
paranoid @master_index, 'Z'
|
195
|
+
|
196
|
+
gzip @specs_index
|
197
|
+
gzip @latest_specs_index
|
49
198
|
end
|
50
199
|
|
51
200
|
##
|
52
|
-
#
|
53
|
-
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
alert_warning "Skipping misnamed gem: #{gemfile} => #{spec.full_name} (#{spec.original_name})"
|
74
|
-
next
|
75
|
-
end
|
76
|
-
|
77
|
-
abbreviate spec
|
78
|
-
sanitize spec
|
79
|
-
|
80
|
-
@master_index.add spec
|
81
|
-
@quick_index.add spec
|
82
|
-
@marshal_index.add spec
|
83
|
-
@latest_index.add spec
|
84
|
-
|
85
|
-
progress.updated spec.original_name
|
86
|
-
|
87
|
-
rescue SignalException => e
|
88
|
-
alert_error "Received signal, exiting"
|
89
|
-
raise
|
90
|
-
rescue Exception => e
|
91
|
-
alert_error "Unable to process #{gemfile}\n#{e.message} (#{e.class})\n\t#{e.backtrace.join "\n\t"}"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
progress.done
|
96
|
-
|
97
|
-
say "Generating master indexes (this may take a while)"
|
98
|
-
end
|
201
|
+
# Collect specifications from .gem files from the gem directory.
|
202
|
+
|
203
|
+
def collect_specs
|
204
|
+
index = Gem::SourceIndex.new
|
205
|
+
|
206
|
+
progress = ui.progress_reporter gem_file_list.size,
|
207
|
+
"Loading #{gem_file_list.size} gems from #{@dest_directory}",
|
208
|
+
"Loaded all gems"
|
209
|
+
|
210
|
+
gem_file_list.each do |gemfile|
|
211
|
+
if File.size(gemfile.to_s) == 0 then
|
212
|
+
alert_warning "Skipping zero-length gem: #{gemfile}"
|
213
|
+
next
|
214
|
+
end
|
215
|
+
|
216
|
+
begin
|
217
|
+
spec = Gem::Format.from_file_by_path(gemfile).spec
|
218
|
+
|
219
|
+
unless gemfile =~ /\/#{Regexp.escape spec.original_name}.*\.gem\z/i then
|
220
|
+
alert_warning "Skipping misnamed gem: #{gemfile} => #{spec.full_name} (#{spec.original_name})"
|
221
|
+
next
|
99
222
|
end
|
223
|
+
|
224
|
+
abbreviate spec
|
225
|
+
sanitize spec
|
226
|
+
|
227
|
+
index.gems[spec.original_name] = spec
|
228
|
+
|
229
|
+
progress.updated spec.original_name
|
230
|
+
|
231
|
+
rescue SignalException => e
|
232
|
+
alert_error "Received signal, exiting"
|
233
|
+
raise
|
234
|
+
rescue Exception => e
|
235
|
+
alert_error "Unable to process #{gemfile}\n#{e.message} (#{e.class})\n\t#{e.backtrace.join "\n\t"}"
|
100
236
|
end
|
101
237
|
end
|
238
|
+
|
239
|
+
progress.done
|
240
|
+
|
241
|
+
index
|
102
242
|
end
|
103
243
|
|
104
|
-
|
105
|
-
|
244
|
+
##
|
245
|
+
# Compacts Marshal output for the specs index data source by using identical
|
246
|
+
# objects as much as possible.
|
106
247
|
|
107
|
-
|
248
|
+
def compact_specs(specs)
|
249
|
+
names = {}
|
250
|
+
versions = {}
|
251
|
+
platforms = {}
|
108
252
|
|
109
|
-
|
110
|
-
|
253
|
+
specs.map do |(name, version, platform)|
|
254
|
+
names[name] = name unless names.include? name
|
255
|
+
versions[version] = version unless versions.include? version
|
256
|
+
platforms[platform] = platform unless platforms.include? platform
|
111
257
|
|
112
|
-
|
113
|
-
|
114
|
-
|
258
|
+
[names[name], versions[version], platforms[platform]]
|
259
|
+
end
|
260
|
+
end
|
115
261
|
|
116
|
-
|
117
|
-
|
262
|
+
##
|
263
|
+
# Compress +filename+ with +extension+.
|
264
|
+
|
265
|
+
def compress(filename, extension)
|
266
|
+
data = Gem.read_binary filename
|
267
|
+
|
268
|
+
zipped = Gem.deflate data
|
269
|
+
|
270
|
+
open "#{filename}.#{extension}", 'wb' do |io|
|
271
|
+
io.write zipped
|
118
272
|
end
|
119
273
|
end
|
120
274
|
|
275
|
+
##
|
276
|
+
# List of gem file names to index.
|
277
|
+
|
278
|
+
def gem_file_list
|
279
|
+
Dir.glob(File.join(@dest_directory, "gems", "*.gem"))
|
280
|
+
end
|
281
|
+
|
282
|
+
##
|
283
|
+
# Builds and installs indexicies.
|
284
|
+
|
121
285
|
def generate_index
|
122
286
|
FileUtils.rm_rf @directory
|
123
287
|
FileUtils.mkdir_p @directory, :mode => 0700
|
288
|
+
FileUtils.mkdir_p @quick_marshal_dir
|
124
289
|
|
125
|
-
|
126
|
-
|
290
|
+
index = collect_specs
|
291
|
+
build_indicies index
|
292
|
+
install_indicies
|
127
293
|
rescue SignalException
|
128
294
|
ensure
|
129
295
|
FileUtils.rm_rf @directory
|
130
296
|
end
|
131
297
|
|
132
|
-
|
133
|
-
|
134
|
-
|
298
|
+
##
|
299
|
+
# Zlib::GzipWriter wrapper that gzips +filename+ on disk.
|
300
|
+
|
301
|
+
def gzip(filename)
|
302
|
+
Zlib::GzipWriter.open "#{filename}.gz" do |io|
|
303
|
+
io.write Gem.read_binary(filename)
|
304
|
+
end
|
135
305
|
end
|
136
306
|
|
137
|
-
|
138
|
-
#
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
307
|
+
##
|
308
|
+
# Install generated indicies into the destination directory.
|
309
|
+
|
310
|
+
def install_indicies
|
311
|
+
verbose = Gem.configuration.really_verbose
|
312
|
+
|
313
|
+
say "Moving index into production dir #{@dest_directory}" if verbose
|
314
|
+
|
315
|
+
@files.each do |file|
|
316
|
+
src_name = File.join @directory, file
|
317
|
+
dst_name = File.join @dest_directory, file
|
318
|
+
|
319
|
+
FileUtils.rm_rf dst_name, :verbose => verbose
|
320
|
+
FileUtils.mv src_name, @dest_directory, :verbose => verbose,
|
321
|
+
:force => true
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
##
|
326
|
+
# Ensure +path+ and path with +extension+ are identical.
|
327
|
+
|
328
|
+
def paranoid(path, extension)
|
329
|
+
data = Gem.read_binary path
|
330
|
+
compressed_data = Gem.read_binary "#{path}.#{extension}"
|
331
|
+
|
332
|
+
unless data == Gem.inflate(compressed_data) then
|
333
|
+
raise "Compressed file #{compressed_path} does not match uncompressed file #{path}"
|
334
|
+
end
|
148
335
|
end
|
149
336
|
|
337
|
+
##
|
150
338
|
# Sanitize the descriptive fields in the spec. Sometimes non-ASCII
|
151
339
|
# characters will garble the site index. Non-ASCII characters will
|
152
340
|
# be replaced by their XML entity equivalent.
|
341
|
+
|
153
342
|
def sanitize(spec)
|
154
343
|
spec.summary = sanitize_string(spec.summary)
|
155
344
|
spec.description = sanitize_string(spec.description)
|
@@ -158,7 +347,9 @@ class Gem::Indexer
|
|
158
347
|
spec
|
159
348
|
end
|
160
349
|
|
350
|
+
##
|
161
351
|
# Sanitize a single string.
|
352
|
+
|
162
353
|
def sanitize_string(string)
|
163
354
|
# HACK the #to_s is in here because RSpec has an Array of Arrays of
|
164
355
|
# Strings for authors. Need a way to disallow bad values on gempsec
|
@@ -168,9 +359,3 @@ class Gem::Indexer
|
|
168
359
|
|
169
360
|
end
|
170
361
|
|
171
|
-
require 'rubygems/indexer/abstract_index_builder'
|
172
|
-
require 'rubygems/indexer/master_index_builder'
|
173
|
-
require 'rubygems/indexer/quick_index_builder'
|
174
|
-
require 'rubygems/indexer/marshal_index_builder'
|
175
|
-
require 'rubygems/indexer/latest_index_builder'
|
176
|
-
|