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,597 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
# See LICENSE.txt for permissions.
|
|
5
|
+
#++
|
|
6
|
+
|
|
7
|
+
require 'libgems/user_interaction'
|
|
8
|
+
require 'libgems/specification'
|
|
9
|
+
|
|
10
|
+
# :stopdoc:
|
|
11
|
+
module LibGems
|
|
12
|
+
autoload :SpecFetcher, 'libgems/spec_fetcher'
|
|
13
|
+
end
|
|
14
|
+
# :startdoc:
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# The SourceIndex object indexes all the gems available from a
|
|
18
|
+
# particular source (e.g. a list of gem directories, or a remote
|
|
19
|
+
# source). A SourceIndex maps a gem full name to a gem
|
|
20
|
+
# specification.
|
|
21
|
+
#
|
|
22
|
+
# NOTE:: The class used to be named Cache, but that became
|
|
23
|
+
# confusing when cached source fetchers where introduced. The
|
|
24
|
+
# constant LibGems::Cache is an alias for this class to allow old
|
|
25
|
+
# YAMLized source index objects to load properly.
|
|
26
|
+
|
|
27
|
+
class LibGems::SourceIndex
|
|
28
|
+
|
|
29
|
+
include Enumerable
|
|
30
|
+
|
|
31
|
+
include LibGems::UserInteraction
|
|
32
|
+
|
|
33
|
+
attr_reader :gems # :nodoc:
|
|
34
|
+
|
|
35
|
+
##
|
|
36
|
+
# Directories to use to refresh this SourceIndex when calling refresh!
|
|
37
|
+
|
|
38
|
+
attr_accessor :spec_dirs
|
|
39
|
+
|
|
40
|
+
class << self
|
|
41
|
+
include LibGems::UserInteraction
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# Factory method to construct a source index instance for a given
|
|
45
|
+
# path.
|
|
46
|
+
#
|
|
47
|
+
# deprecated::
|
|
48
|
+
# If supplied, from_installed_gems will act just like
|
|
49
|
+
# +from_gems_in+. This argument is deprecated and is provided
|
|
50
|
+
# just for backwards compatibility, and should not generally
|
|
51
|
+
# be used.
|
|
52
|
+
#
|
|
53
|
+
# return::
|
|
54
|
+
# SourceIndex instance
|
|
55
|
+
|
|
56
|
+
def from_installed_gems(*deprecated)
|
|
57
|
+
if deprecated.empty?
|
|
58
|
+
from_gems_in(*installed_spec_directories)
|
|
59
|
+
else
|
|
60
|
+
from_gems_in(*deprecated) # HACK warn
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
##
|
|
65
|
+
# Returns a list of directories from LibGems.path that contain specifications.
|
|
66
|
+
|
|
67
|
+
def installed_spec_directories
|
|
68
|
+
LibGems.path.collect { |dir| File.join(dir, "specifications") }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
##
|
|
72
|
+
# Creates a new SourceIndex from the ruby format gem specifications in
|
|
73
|
+
# +spec_dirs+.
|
|
74
|
+
|
|
75
|
+
def from_gems_in(*spec_dirs)
|
|
76
|
+
source_index = new
|
|
77
|
+
source_index.spec_dirs = spec_dirs
|
|
78
|
+
source_index.refresh!
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
##
|
|
82
|
+
# Loads a ruby-format specification from +file_name+ and returns the
|
|
83
|
+
# loaded spec.
|
|
84
|
+
|
|
85
|
+
def load_specification(file_name)
|
|
86
|
+
return nil unless file_name and File.exist? file_name
|
|
87
|
+
|
|
88
|
+
spec_code = if defined? Encoding then
|
|
89
|
+
File.read file_name, :encoding => 'UTF-8'
|
|
90
|
+
else
|
|
91
|
+
File.read file_name
|
|
92
|
+
end.untaint
|
|
93
|
+
|
|
94
|
+
begin
|
|
95
|
+
gemspec = LibGems.gemspec_eval(spec_code, binding, file_name)
|
|
96
|
+
|
|
97
|
+
if gemspec.is_a?(LibGems::Specification)
|
|
98
|
+
gemspec.loaded_from = file_name
|
|
99
|
+
return gemspec
|
|
100
|
+
end
|
|
101
|
+
alert_warning "File '#{file_name}' does not evaluate to a gem specification"
|
|
102
|
+
rescue SignalException, SystemExit
|
|
103
|
+
raise
|
|
104
|
+
rescue SyntaxError => e
|
|
105
|
+
alert_warning e
|
|
106
|
+
alert_warning spec_code
|
|
107
|
+
rescue Exception => e
|
|
108
|
+
alert_warning "#{e.inspect}\n#{spec_code}"
|
|
109
|
+
alert_warning "Invalid .gemspec format in '#{file_name}'"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
return nil
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
##
|
|
118
|
+
# Constructs a source index instance from the provided specifications, which
|
|
119
|
+
# is a Hash of gem full names and LibGems::Specifications.
|
|
120
|
+
#--
|
|
121
|
+
# TODO merge @gems and @prerelease_gems and provide a separate method
|
|
122
|
+
# #prerelease_gems
|
|
123
|
+
|
|
124
|
+
def initialize(specifications={})
|
|
125
|
+
@gems = {}
|
|
126
|
+
specifications.each{ |full_name, spec| add_spec spec }
|
|
127
|
+
@spec_dirs = nil
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# TODO: remove method
|
|
131
|
+
def all_gems
|
|
132
|
+
@gems
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def prerelease_gems
|
|
136
|
+
@gems.reject{ |name, gem| !gem.version.prerelease? }
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def released_gems
|
|
140
|
+
@gems.reject{ |name, gem| gem.version.prerelease? }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
##
|
|
144
|
+
# Reconstruct the source index from the specifications in +spec_dirs+.
|
|
145
|
+
|
|
146
|
+
def load_gems_in(*spec_dirs)
|
|
147
|
+
@gems.clear
|
|
148
|
+
|
|
149
|
+
spec_dirs.reverse_each do |spec_dir|
|
|
150
|
+
spec_files = Dir.glob File.join(spec_dir, '*.gemspec')
|
|
151
|
+
|
|
152
|
+
spec_files.each do |spec_file|
|
|
153
|
+
gemspec = self.class.load_specification spec_file.untaint
|
|
154
|
+
add_spec gemspec if gemspec
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
self
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
##
|
|
162
|
+
# Returns an Array specifications for the latest released versions
|
|
163
|
+
# of each gem in this index.
|
|
164
|
+
|
|
165
|
+
def latest_specs
|
|
166
|
+
result = Hash.new { |h,k| h[k] = [] }
|
|
167
|
+
latest = {}
|
|
168
|
+
|
|
169
|
+
sort.each do |_, spec|
|
|
170
|
+
name = spec.name
|
|
171
|
+
curr_ver = spec.version
|
|
172
|
+
prev_ver = latest.key?(name) ? latest[name].version : nil
|
|
173
|
+
|
|
174
|
+
next if curr_ver.prerelease?
|
|
175
|
+
next unless prev_ver.nil? or curr_ver >= prev_ver or
|
|
176
|
+
latest[name].platform != LibGems::Platform::RUBY
|
|
177
|
+
|
|
178
|
+
if prev_ver.nil? or
|
|
179
|
+
(curr_ver > prev_ver and spec.platform == LibGems::Platform::RUBY) then
|
|
180
|
+
result[name].clear
|
|
181
|
+
latest[name] = spec
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
if spec.platform != LibGems::Platform::RUBY then
|
|
185
|
+
result[name].delete_if do |result_spec|
|
|
186
|
+
result_spec.platform == spec.platform
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
result[name] << spec
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# TODO: why is this a hash while @gems is an array? Seems like
|
|
194
|
+
# structural similarity would be good.
|
|
195
|
+
result.values.flatten
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
##
|
|
199
|
+
# An array including only the prerelease gemspecs
|
|
200
|
+
|
|
201
|
+
def prerelease_specs
|
|
202
|
+
prerelease_gems.values
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
##
|
|
206
|
+
# An array including only the released gemspecs
|
|
207
|
+
|
|
208
|
+
def released_specs
|
|
209
|
+
released_gems.values
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
##
|
|
213
|
+
# Add a gem specification to the source index.
|
|
214
|
+
|
|
215
|
+
def add_spec(gem_spec, name = gem_spec.full_name)
|
|
216
|
+
# No idea why, but the Indexer wants to insert them using original_name
|
|
217
|
+
# instead of full_name. So we make it an optional arg.
|
|
218
|
+
@gems[name] = gem_spec
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
##
|
|
222
|
+
# Add gem specifications to the source index.
|
|
223
|
+
|
|
224
|
+
def add_specs(*gem_specs)
|
|
225
|
+
gem_specs.each do |spec|
|
|
226
|
+
add_spec spec
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
##
|
|
231
|
+
# Remove a gem specification named +full_name+.
|
|
232
|
+
|
|
233
|
+
def remove_spec(full_name)
|
|
234
|
+
@gems.delete full_name
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
##
|
|
238
|
+
# Iterate over the specifications in the source index.
|
|
239
|
+
|
|
240
|
+
def each(&block) # :yields: gem.full_name, gem
|
|
241
|
+
@gems.each(&block)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
##
|
|
245
|
+
# The gem specification given a full gem spec name.
|
|
246
|
+
|
|
247
|
+
def specification(full_name)
|
|
248
|
+
@gems[full_name]
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
##
|
|
252
|
+
# The signature for the source index. Changes in the signature indicate a
|
|
253
|
+
# change in the index.
|
|
254
|
+
|
|
255
|
+
def index_signature
|
|
256
|
+
require 'digest'
|
|
257
|
+
|
|
258
|
+
Digest::SHA256.new.hexdigest(@gems.keys.sort.join(',')).to_s
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
##
|
|
262
|
+
# The signature for the given gem specification.
|
|
263
|
+
|
|
264
|
+
def gem_signature(gem_full_name)
|
|
265
|
+
require 'digest'
|
|
266
|
+
|
|
267
|
+
Digest::SHA256.new.hexdigest(@gems[gem_full_name].to_yaml).to_s
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def size
|
|
271
|
+
@gems.size
|
|
272
|
+
end
|
|
273
|
+
alias length size
|
|
274
|
+
|
|
275
|
+
##
|
|
276
|
+
# Find a gem by an exact match on the short name.
|
|
277
|
+
|
|
278
|
+
def find_name(gem_name, version_requirement = LibGems::Requirement.default)
|
|
279
|
+
dep = LibGems::Dependency.new gem_name, version_requirement
|
|
280
|
+
search dep
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
##
|
|
284
|
+
# Search for a gem by LibGems::Dependency +gem_pattern+. If +only_platform+
|
|
285
|
+
# is true, only gems matching LibGems::Platform.local will be returned. An
|
|
286
|
+
# Array of matching LibGems::Specification objects is returned.
|
|
287
|
+
#
|
|
288
|
+
# For backwards compatibility, a String or Regexp pattern may be passed as
|
|
289
|
+
# +gem_pattern+, and a LibGems::Requirement for +platform_only+. This
|
|
290
|
+
# behavior is deprecated and will be removed.
|
|
291
|
+
|
|
292
|
+
def search(gem_pattern, platform_only = false)
|
|
293
|
+
version_requirement = nil
|
|
294
|
+
only_platform = false
|
|
295
|
+
|
|
296
|
+
# TODO - Remove support and warning for legacy arguments after 2008/11
|
|
297
|
+
unless LibGems::Dependency === gem_pattern
|
|
298
|
+
warn "#{LibGems.location_of_caller.join ':'}:Warning: LibGems::SourceIndex#search support for #{gem_pattern.class} patterns is deprecated, use #find_name"
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
case gem_pattern
|
|
302
|
+
when Regexp then
|
|
303
|
+
version_requirement = platform_only || LibGems::Requirement.default
|
|
304
|
+
when LibGems::Dependency then
|
|
305
|
+
only_platform = platform_only
|
|
306
|
+
version_requirement = gem_pattern.requirement
|
|
307
|
+
gem_pattern = if Regexp === gem_pattern.name then
|
|
308
|
+
gem_pattern.name
|
|
309
|
+
elsif gem_pattern.name.empty? then
|
|
310
|
+
//
|
|
311
|
+
else
|
|
312
|
+
/^#{Regexp.escape gem_pattern.name}$/
|
|
313
|
+
end
|
|
314
|
+
else
|
|
315
|
+
version_requirement = platform_only || LibGems::Requirement.default
|
|
316
|
+
gem_pattern = /#{gem_pattern}/i
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
unless LibGems::Requirement === version_requirement then
|
|
320
|
+
version_requirement = LibGems::Requirement.create version_requirement
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
specs = all_gems.values.select do |spec|
|
|
324
|
+
spec.name =~ gem_pattern and
|
|
325
|
+
version_requirement.satisfied_by? spec.version
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
if only_platform then
|
|
329
|
+
specs = specs.select do |spec|
|
|
330
|
+
LibGems::Platform.match spec.platform
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
specs.sort_by { |s| s.sort_obj }
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
##
|
|
338
|
+
# Replaces the gems in the source index from specifications in the
|
|
339
|
+
# directories this source index was created from. Raises an exception if
|
|
340
|
+
# this source index wasn't created from a directory (via from_gems_in or
|
|
341
|
+
# from_installed_gems, or having spec_dirs set).
|
|
342
|
+
|
|
343
|
+
def refresh!
|
|
344
|
+
raise 'source index not created from disk' if @spec_dirs.nil?
|
|
345
|
+
load_gems_in(*@spec_dirs)
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
##
|
|
349
|
+
# Returns an Array of LibGems::Specifications that are not up to date.
|
|
350
|
+
|
|
351
|
+
def outdated
|
|
352
|
+
outdateds = []
|
|
353
|
+
|
|
354
|
+
latest_specs.each do |local|
|
|
355
|
+
dependency = LibGems::Dependency.new local.name, ">= #{local.version}"
|
|
356
|
+
|
|
357
|
+
begin
|
|
358
|
+
fetcher = LibGems::SpecFetcher.fetcher
|
|
359
|
+
remotes = fetcher.find_matching dependency
|
|
360
|
+
remotes = remotes.map { |(name, version,_),_| version }
|
|
361
|
+
rescue LibGems::RemoteFetcher::FetchError => e
|
|
362
|
+
raise unless fetcher.warn_legacy e do
|
|
363
|
+
require 'libgems/source_info_cache'
|
|
364
|
+
|
|
365
|
+
specs = LibGems::SourceInfoCache.search_with_source dependency, true
|
|
366
|
+
|
|
367
|
+
remotes = specs.map { |spec,| spec.version }
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
latest = remotes.sort.last
|
|
372
|
+
|
|
373
|
+
outdateds << local.name if latest and local.version < latest
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
outdateds
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
##
|
|
380
|
+
# Updates this SourceIndex from +source_uri+. If +all+ is false, only the
|
|
381
|
+
# latest gems are fetched.
|
|
382
|
+
|
|
383
|
+
def update(source_uri, all)
|
|
384
|
+
source_uri = URI.parse source_uri unless URI::Generic === source_uri
|
|
385
|
+
source_uri.path += '/' unless source_uri.path =~ /\/$/
|
|
386
|
+
|
|
387
|
+
use_incremental = false
|
|
388
|
+
|
|
389
|
+
begin
|
|
390
|
+
gem_names = fetch_quick_index source_uri, all
|
|
391
|
+
remove_extra gem_names
|
|
392
|
+
missing_gems = find_missing gem_names
|
|
393
|
+
|
|
394
|
+
return false if missing_gems.size.zero?
|
|
395
|
+
|
|
396
|
+
say "Missing metadata for #{missing_gems.size} gems" if
|
|
397
|
+
missing_gems.size > 0 and LibGems.configuration.really_verbose
|
|
398
|
+
|
|
399
|
+
use_incremental = missing_gems.size <= LibGems.configuration.bulk_threshold
|
|
400
|
+
rescue LibGems::OperationNotSupportedError => ex
|
|
401
|
+
alert_error "Falling back to bulk fetch: #{ex.message}" if
|
|
402
|
+
LibGems.configuration.really_verbose
|
|
403
|
+
use_incremental = false
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
if use_incremental then
|
|
407
|
+
update_with_missing(source_uri, missing_gems)
|
|
408
|
+
else
|
|
409
|
+
new_index = fetch_bulk_index(source_uri)
|
|
410
|
+
@gems.replace(new_index.gems)
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
true
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def ==(other) # :nodoc:
|
|
417
|
+
self.class === other and @gems == other.gems
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
def dump
|
|
421
|
+
Marshal.dump(self)
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
private
|
|
425
|
+
|
|
426
|
+
def fetcher
|
|
427
|
+
require 'libgems/remote_fetcher'
|
|
428
|
+
|
|
429
|
+
LibGems::RemoteFetcher.fetcher
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
def fetch_index_from(source_uri)
|
|
433
|
+
@fetch_error = nil
|
|
434
|
+
|
|
435
|
+
indexes = %W[
|
|
436
|
+
Marshal.#{LibGems.marshal_version}.Z
|
|
437
|
+
Marshal.#{LibGems.marshal_version}
|
|
438
|
+
yaml.Z
|
|
439
|
+
yaml
|
|
440
|
+
]
|
|
441
|
+
|
|
442
|
+
indexes.each do |name|
|
|
443
|
+
spec_data = nil
|
|
444
|
+
index = source_uri + name
|
|
445
|
+
begin
|
|
446
|
+
spec_data = fetcher.fetch_path index
|
|
447
|
+
spec_data = unzip(spec_data) if name =~ /\.Z$/
|
|
448
|
+
|
|
449
|
+
if name =~ /Marshal/ then
|
|
450
|
+
return Marshal.load(spec_data)
|
|
451
|
+
else
|
|
452
|
+
return YAML.load(spec_data)
|
|
453
|
+
end
|
|
454
|
+
rescue => e
|
|
455
|
+
if LibGems.configuration.really_verbose then
|
|
456
|
+
alert_error "Unable to fetch #{name}: #{e.message}"
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
@fetch_error = e
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
nil
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
def fetch_bulk_index(source_uri)
|
|
467
|
+
say "Bulk updating LibGems source index for: #{source_uri}" if
|
|
468
|
+
LibGems.configuration.verbose
|
|
469
|
+
|
|
470
|
+
index = fetch_index_from(source_uri)
|
|
471
|
+
if index.nil? then
|
|
472
|
+
raise LibGems::RemoteSourceException,
|
|
473
|
+
"Error fetching remote gem cache: #{@fetch_error}"
|
|
474
|
+
end
|
|
475
|
+
@fetch_error = nil
|
|
476
|
+
index
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
##
|
|
480
|
+
# Get the quick index needed for incremental updates.
|
|
481
|
+
|
|
482
|
+
def fetch_quick_index(source_uri, all)
|
|
483
|
+
index = all ? 'index' : 'latest_index'
|
|
484
|
+
|
|
485
|
+
zipped_index = fetcher.fetch_path source_uri + "quick/#{index}.rz"
|
|
486
|
+
|
|
487
|
+
unzip(zipped_index).split("\n")
|
|
488
|
+
rescue ::Exception => e
|
|
489
|
+
unless all then
|
|
490
|
+
say "Latest index not found, using quick index" if
|
|
491
|
+
LibGems.configuration.really_verbose
|
|
492
|
+
|
|
493
|
+
fetch_quick_index source_uri, true
|
|
494
|
+
else
|
|
495
|
+
raise LibGems::OperationNotSupportedError,
|
|
496
|
+
"No quick index found: #{e.message}"
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
##
|
|
501
|
+
# Make a list of full names for all the missing gemspecs.
|
|
502
|
+
|
|
503
|
+
def find_missing(spec_names)
|
|
504
|
+
unless defined? @originals then
|
|
505
|
+
@originals = {}
|
|
506
|
+
each do |full_name, spec|
|
|
507
|
+
@originals[spec.original_name] = spec
|
|
508
|
+
end
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
spec_names.find_all { |full_name|
|
|
512
|
+
@originals[full_name].nil?
|
|
513
|
+
}
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
def remove_extra(spec_names)
|
|
517
|
+
dictionary = spec_names.inject({}) { |h, k| h[k] = true; h }
|
|
518
|
+
each do |name, spec|
|
|
519
|
+
remove_spec name unless dictionary.include? spec.original_name
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
##
|
|
524
|
+
# Unzip the given string.
|
|
525
|
+
|
|
526
|
+
def unzip(string)
|
|
527
|
+
require 'zlib'
|
|
528
|
+
LibGems.inflate string
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
##
|
|
532
|
+
# Tries to fetch Marshal representation first, then YAML
|
|
533
|
+
|
|
534
|
+
def fetch_single_spec(source_uri, spec_name)
|
|
535
|
+
@fetch_error = nil
|
|
536
|
+
|
|
537
|
+
begin
|
|
538
|
+
marshal_uri = source_uri + "quick/Marshal.#{LibGems.marshal_version}/#{spec_name}.gemspec.rz"
|
|
539
|
+
zipped = fetcher.fetch_path marshal_uri
|
|
540
|
+
return Marshal.load(unzip(zipped))
|
|
541
|
+
rescue => ex
|
|
542
|
+
@fetch_error = ex
|
|
543
|
+
|
|
544
|
+
if LibGems.configuration.really_verbose then
|
|
545
|
+
say "unable to fetch marshal gemspec #{marshal_uri}: #{ex.class} - #{ex}"
|
|
546
|
+
end
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
begin
|
|
550
|
+
yaml_uri = source_uri + "quick/#{spec_name}.gemspec.rz"
|
|
551
|
+
zipped = fetcher.fetch_path yaml_uri
|
|
552
|
+
return YAML.load(unzip(zipped))
|
|
553
|
+
rescue => ex
|
|
554
|
+
@fetch_error = ex
|
|
555
|
+
if LibGems.configuration.really_verbose then
|
|
556
|
+
say "unable to fetch YAML gemspec #{yaml_uri}: #{ex.class} - #{ex}"
|
|
557
|
+
end
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
nil
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
##
|
|
564
|
+
# Update the cached source index with the missing names.
|
|
565
|
+
|
|
566
|
+
def update_with_missing(source_uri, missing_names)
|
|
567
|
+
progress = ui.progress_reporter(missing_names.size,
|
|
568
|
+
"Updating metadata for #{missing_names.size} gems from #{source_uri}")
|
|
569
|
+
missing_names.each do |spec_name|
|
|
570
|
+
gemspec = fetch_single_spec(source_uri, spec_name)
|
|
571
|
+
if gemspec.nil? then
|
|
572
|
+
ui.say "Failed to download spec #{spec_name} from #{source_uri}:\n" \
|
|
573
|
+
"\t#{@fetch_error.message}"
|
|
574
|
+
else
|
|
575
|
+
add_spec gemspec
|
|
576
|
+
progress.updated spec_name
|
|
577
|
+
end
|
|
578
|
+
@fetch_error = nil
|
|
579
|
+
end
|
|
580
|
+
progress.done
|
|
581
|
+
progress.count
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
# :stopdoc:
|
|
587
|
+
module LibGems
|
|
588
|
+
|
|
589
|
+
##
|
|
590
|
+
# Cache is an alias for SourceIndex to allow older YAMLized source index
|
|
591
|
+
# objects to load properly.
|
|
592
|
+
|
|
593
|
+
Cache = SourceIndex
|
|
594
|
+
|
|
595
|
+
end
|
|
596
|
+
# :startdoc:
|
|
597
|
+
|