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,79 @@
|
|
|
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/command_manager'
|
|
8
|
+
require 'libgems/config_file'
|
|
9
|
+
require 'libgems/doc_manager'
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# Run an instance of the gem program.
|
|
13
|
+
#
|
|
14
|
+
# LibGems::GemRunner is only intended for internal use by SlimGems itself. It
|
|
15
|
+
# does not form any public API and may change at any time for any reason.
|
|
16
|
+
#
|
|
17
|
+
# If you would like to duplicate functionality of `gem` commands, use the
|
|
18
|
+
# classes they call directly.
|
|
19
|
+
|
|
20
|
+
class LibGems::GemRunner
|
|
21
|
+
|
|
22
|
+
def initialize(options={})
|
|
23
|
+
@command_manager_class = options[:command_manager] || LibGems::CommandManager
|
|
24
|
+
@config_file_class = options[:config_file] || LibGems::ConfigFile
|
|
25
|
+
@doc_manager_class = options[:doc_manager] || LibGems::DocManager
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# Run the gem command with the following arguments.
|
|
30
|
+
|
|
31
|
+
def run(args)
|
|
32
|
+
start_time = Time.now
|
|
33
|
+
|
|
34
|
+
if args.include?('--')
|
|
35
|
+
# We need to preserve the original ARGV to use for passing gem options
|
|
36
|
+
# to source gems. If there is a -- in the line, strip all options after
|
|
37
|
+
# it...its for the source building process.
|
|
38
|
+
build_args = args[args.index("--") + 1...args.length]
|
|
39
|
+
args = args[0...args.index("--")]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
LibGems::Command.build_args = build_args if build_args
|
|
43
|
+
|
|
44
|
+
do_configuration args
|
|
45
|
+
cmd = @command_manager_class.instance
|
|
46
|
+
|
|
47
|
+
cmd.command_names.each do |command_name|
|
|
48
|
+
config_args = LibGems.configuration[command_name]
|
|
49
|
+
config_args = case config_args
|
|
50
|
+
when String
|
|
51
|
+
config_args.split ' '
|
|
52
|
+
else
|
|
53
|
+
Array(config_args)
|
|
54
|
+
end
|
|
55
|
+
LibGems::Command.add_specific_extra_args command_name, config_args
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
cmd.run LibGems.configuration.args
|
|
59
|
+
end_time = Time.now
|
|
60
|
+
|
|
61
|
+
if LibGems.configuration.benchmark then
|
|
62
|
+
printf "\nExecution time: %0.2f seconds.\n", end_time - start_time
|
|
63
|
+
puts "Press Enter to finish"
|
|
64
|
+
STDIN.gets
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def do_configuration(args)
|
|
71
|
+
LibGems.configuration = @config_file_class.new(args)
|
|
72
|
+
LibGems.use_paths(LibGems.configuration[:gemhome], LibGems.configuration[:gempath])
|
|
73
|
+
LibGems::Command.extra_args = LibGems.configuration[:gem]
|
|
74
|
+
@doc_manager_class.configured_args = LibGems.configuration[:rdoc]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
LibGems.load_plugins
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'libgems/remote_fetcher'
|
|
2
|
+
|
|
3
|
+
module LibGems::GemcutterUtilities
|
|
4
|
+
|
|
5
|
+
def sign_in
|
|
6
|
+
return if LibGems.configuration.rubygems_api_key
|
|
7
|
+
|
|
8
|
+
say "Enter your rubygems.org credentials."
|
|
9
|
+
say "Don't have an account yet? Create one at http://rubygems.org/sign_up"
|
|
10
|
+
|
|
11
|
+
email = ask " Email: "
|
|
12
|
+
password = ask_for_password "Password: "
|
|
13
|
+
say "\n"
|
|
14
|
+
|
|
15
|
+
response = rubygems_api_request :get, "api/v1/api_key" do |request|
|
|
16
|
+
request.basic_auth email, password
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
with_response response do |resp|
|
|
20
|
+
say "Signed in."
|
|
21
|
+
LibGems.configuration.rubygems_api_key = resp.body
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def rubygems_api_request(method, path, host = LibGems.host, &block)
|
|
26
|
+
require 'net/http'
|
|
27
|
+
host = ENV['RUBYGEMS_HOST'] if ENV['RUBYGEMS_HOST']
|
|
28
|
+
uri = URI.parse "#{host}/#{path}"
|
|
29
|
+
|
|
30
|
+
request_method = Net::HTTP.const_get method.to_s.capitalize
|
|
31
|
+
|
|
32
|
+
LibGems::RemoteFetcher.fetcher.request(uri, request_method, &block)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def with_response(resp)
|
|
36
|
+
case resp
|
|
37
|
+
when Net::HTTPSuccess then
|
|
38
|
+
if block_given? then
|
|
39
|
+
yield resp
|
|
40
|
+
else
|
|
41
|
+
say resp.body
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
say resp.body
|
|
45
|
+
terminate_interaction 1
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
@@ -0,0 +1,720 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'tmpdir'
|
|
3
|
+
require 'zlib'
|
|
4
|
+
|
|
5
|
+
require 'libgems'
|
|
6
|
+
require 'libgems/format'
|
|
7
|
+
|
|
8
|
+
begin
|
|
9
|
+
gem 'builder'
|
|
10
|
+
require 'builder/xchar'
|
|
11
|
+
rescue LoadError
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
# Top level class for building the gem repository index.
|
|
16
|
+
|
|
17
|
+
class LibGems::Indexer
|
|
18
|
+
|
|
19
|
+
include LibGems::UserInteraction
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# Build indexes for SlimGems older than 1.2.0 when true
|
|
23
|
+
|
|
24
|
+
attr_accessor :build_legacy
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# Build indexes for SlimGems 1.2.0 and newer when true
|
|
28
|
+
|
|
29
|
+
attr_accessor :build_modern
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Index install location
|
|
33
|
+
|
|
34
|
+
attr_reader :dest_directory
|
|
35
|
+
|
|
36
|
+
##
|
|
37
|
+
# Specs index install location
|
|
38
|
+
|
|
39
|
+
attr_reader :dest_specs_index
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# Latest specs index install location
|
|
43
|
+
|
|
44
|
+
attr_reader :dest_latest_specs_index
|
|
45
|
+
|
|
46
|
+
##
|
|
47
|
+
# Prerelease specs index install location
|
|
48
|
+
|
|
49
|
+
attr_reader :dest_prerelease_specs_index
|
|
50
|
+
|
|
51
|
+
##
|
|
52
|
+
# Index build directory
|
|
53
|
+
|
|
54
|
+
attr_reader :directory
|
|
55
|
+
|
|
56
|
+
##
|
|
57
|
+
# Create an indexer that will index the gems in +directory+.
|
|
58
|
+
|
|
59
|
+
def initialize(directory, options = {})
|
|
60
|
+
unless defined?(Builder::XChar) then
|
|
61
|
+
raise "LibGems::Indexer requires that the XML Builder library be installed:" \
|
|
62
|
+
"\n\tgem install builder"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
options = { :build_legacy => true, :build_modern => true }.merge options
|
|
66
|
+
|
|
67
|
+
@build_legacy = options[:build_legacy]
|
|
68
|
+
@build_modern = options[:build_modern]
|
|
69
|
+
|
|
70
|
+
@rss_title = options[:rss_title]
|
|
71
|
+
@rss_host = options[:rss_host]
|
|
72
|
+
@rss_gems_host = options[:rss_gems_host]
|
|
73
|
+
|
|
74
|
+
@dest_directory = directory
|
|
75
|
+
@directory = File.join Dir.tmpdir, "gem_generate_index_#{$$}"
|
|
76
|
+
|
|
77
|
+
marshal_name = "Marshal.#{LibGems.marshal_version}"
|
|
78
|
+
|
|
79
|
+
@master_index = File.join @directory, 'yaml'
|
|
80
|
+
@marshal_index = File.join @directory, marshal_name
|
|
81
|
+
|
|
82
|
+
@quick_dir = File.join @directory, 'quick'
|
|
83
|
+
|
|
84
|
+
@quick_marshal_dir = File.join @quick_dir, marshal_name
|
|
85
|
+
|
|
86
|
+
@quick_index = File.join @quick_dir, 'index'
|
|
87
|
+
@latest_index = File.join @quick_dir, 'latest_index'
|
|
88
|
+
|
|
89
|
+
@specs_index = File.join @directory, "specs.#{LibGems.marshal_version}"
|
|
90
|
+
@latest_specs_index = File.join @directory,
|
|
91
|
+
"latest_specs.#{LibGems.marshal_version}"
|
|
92
|
+
@prerelease_specs_index = File.join(@directory,
|
|
93
|
+
"prerelease_specs.#{LibGems.marshal_version}")
|
|
94
|
+
|
|
95
|
+
@dest_specs_index = File.join @dest_directory,
|
|
96
|
+
"specs.#{LibGems.marshal_version}"
|
|
97
|
+
@dest_latest_specs_index = File.join @dest_directory,
|
|
98
|
+
"latest_specs.#{LibGems.marshal_version}"
|
|
99
|
+
@dest_prerelease_specs_index = File.join @dest_directory,
|
|
100
|
+
"prerelease_specs.#{LibGems.marshal_version}"
|
|
101
|
+
|
|
102
|
+
@rss_index = File.join @directory, 'index.rss'
|
|
103
|
+
|
|
104
|
+
@files = []
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
##
|
|
108
|
+
# Abbreviate the spec for downloading. Abbreviated specs are only used for
|
|
109
|
+
# searching, downloading and related activities and do not need deployment
|
|
110
|
+
# specific information (e.g. list of files). So we abbreviate the spec,
|
|
111
|
+
# making it much smaller for quicker downloads.
|
|
112
|
+
|
|
113
|
+
def abbreviate(spec)
|
|
114
|
+
spec.files = []
|
|
115
|
+
spec.test_files = []
|
|
116
|
+
spec.rdoc_options = []
|
|
117
|
+
spec.extra_rdoc_files = []
|
|
118
|
+
spec.cert_chain = []
|
|
119
|
+
spec
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
##
|
|
123
|
+
# Build various indicies
|
|
124
|
+
|
|
125
|
+
def build_indicies(index)
|
|
126
|
+
# Marshal gemspecs are used by both modern and legacy SlimGems
|
|
127
|
+
build_marshal_gemspecs index
|
|
128
|
+
build_legacy_indicies index if @build_legacy
|
|
129
|
+
build_modern_indicies index if @build_modern
|
|
130
|
+
build_rss index
|
|
131
|
+
|
|
132
|
+
compress_indicies
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
##
|
|
136
|
+
# Builds indicies for SlimGems older than 1.2.x
|
|
137
|
+
|
|
138
|
+
def build_legacy_indicies(index)
|
|
139
|
+
progress = ui.progress_reporter index.size,
|
|
140
|
+
"Generating YAML quick index gemspecs for #{index.size} gems",
|
|
141
|
+
"Complete"
|
|
142
|
+
|
|
143
|
+
LibGems.time 'Generated YAML quick index gemspecs' do
|
|
144
|
+
index.released_gems.each do |original_name, spec|
|
|
145
|
+
spec_file_name = "#{original_name}.gemspec.rz"
|
|
146
|
+
yaml_name = File.join @quick_dir, spec_file_name
|
|
147
|
+
|
|
148
|
+
yaml_zipped = LibGems.deflate spec.to_yaml
|
|
149
|
+
open yaml_name, 'wb' do |io| io.write yaml_zipped end
|
|
150
|
+
|
|
151
|
+
progress.updated original_name
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
progress.done
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
say "Generating quick index"
|
|
158
|
+
|
|
159
|
+
LibGems.time 'Generated quick index' do
|
|
160
|
+
open @quick_index, 'wb' do |io|
|
|
161
|
+
io.puts index.sort.map { |_, spec| spec.original_name }
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
say "Generating latest index"
|
|
166
|
+
|
|
167
|
+
LibGems.time 'Generated latest index' do
|
|
168
|
+
open @latest_index, 'wb' do |io|
|
|
169
|
+
io.puts index.latest_specs.sort.map { |spec| spec.original_name }
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Don't need prerelease legacy index
|
|
174
|
+
|
|
175
|
+
say "Generating Marshal master index"
|
|
176
|
+
|
|
177
|
+
LibGems.time 'Generated Marshal master index' do
|
|
178
|
+
open @marshal_index, 'wb' do |io|
|
|
179
|
+
io.write index.dump
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
progress = ui.progress_reporter index.size,
|
|
184
|
+
"Generating YAML master index for #{index.size} gems (this may take a while)",
|
|
185
|
+
"Complete"
|
|
186
|
+
|
|
187
|
+
LibGems.time 'Generated YAML master index' do
|
|
188
|
+
open @master_index, 'wb' do |io|
|
|
189
|
+
io.puts "--- !ruby/object:#{index.class}"
|
|
190
|
+
io.puts "gems:"
|
|
191
|
+
|
|
192
|
+
gems = index.sort_by { |name, gemspec| gemspec.sort_obj }
|
|
193
|
+
gems.each do |original_name, gemspec|
|
|
194
|
+
yaml = gemspec.to_yaml.gsub(/^/, ' ')
|
|
195
|
+
yaml = yaml.sub(/\A ---/, '') # there's a needed extra ' ' here
|
|
196
|
+
io.print " #{original_name}:"
|
|
197
|
+
io.puts yaml
|
|
198
|
+
|
|
199
|
+
progress.updated original_name
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
progress.done
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
@files << @quick_dir
|
|
207
|
+
@files << @master_index
|
|
208
|
+
@files << "#{@master_index}.Z"
|
|
209
|
+
@files << @marshal_index
|
|
210
|
+
@files << "#{@marshal_index}.Z"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
##
|
|
214
|
+
# Builds Marshal quick index gemspecs.
|
|
215
|
+
|
|
216
|
+
def build_marshal_gemspecs(index)
|
|
217
|
+
progress = ui.progress_reporter index.size,
|
|
218
|
+
"Generating Marshal quick index gemspecs for #{index.size} gems",
|
|
219
|
+
"Complete"
|
|
220
|
+
|
|
221
|
+
files = []
|
|
222
|
+
|
|
223
|
+
LibGems.time 'Generated Marshal quick index gemspecs' do
|
|
224
|
+
index.gems.each do |original_name, spec|
|
|
225
|
+
spec_file_name = "#{original_name}.gemspec.rz"
|
|
226
|
+
marshal_name = File.join @quick_marshal_dir, spec_file_name
|
|
227
|
+
|
|
228
|
+
marshal_zipped = LibGems.deflate Marshal.dump(spec)
|
|
229
|
+
open marshal_name, 'wb' do |io| io.write marshal_zipped end
|
|
230
|
+
|
|
231
|
+
files << marshal_name
|
|
232
|
+
|
|
233
|
+
progress.updated original_name
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
progress.done
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
@files << @quick_marshal_dir
|
|
240
|
+
|
|
241
|
+
files
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
##
|
|
245
|
+
# Build a single index for SlimGems 1.2 and newer
|
|
246
|
+
|
|
247
|
+
def build_modern_index(index, file, name)
|
|
248
|
+
say "Generating #{name} index"
|
|
249
|
+
|
|
250
|
+
LibGems.time "Generated #{name} index" do
|
|
251
|
+
open(file, 'wb') do |io|
|
|
252
|
+
specs = index.map do |*spec|
|
|
253
|
+
# We have to splat here because latest_specs is an array,
|
|
254
|
+
# while the others are hashes. See the TODO in source_index.rb
|
|
255
|
+
spec = spec.flatten.last
|
|
256
|
+
platform = spec.original_platform
|
|
257
|
+
|
|
258
|
+
# win32-api-1.0.4-x86-mswin32-60
|
|
259
|
+
unless String === platform then
|
|
260
|
+
alert_warning "Skipping invalid platform in gem: #{spec.full_name}"
|
|
261
|
+
next
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
platform = LibGems::Platform::RUBY if platform.nil? or platform.empty?
|
|
265
|
+
[spec.name, spec.version, platform]
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
specs = compact_specs(specs)
|
|
269
|
+
Marshal.dump(specs, io)
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
##
|
|
275
|
+
# Builds indicies for SlimGems 1.2 and newer. Handles full, latest, prerelease
|
|
276
|
+
|
|
277
|
+
def build_modern_indicies(index)
|
|
278
|
+
build_modern_index(index.released_specs.sort, @specs_index, 'specs')
|
|
279
|
+
build_modern_index(index.latest_specs.sort,
|
|
280
|
+
@latest_specs_index,
|
|
281
|
+
'latest specs')
|
|
282
|
+
build_modern_index(index.prerelease_specs.sort,
|
|
283
|
+
@prerelease_specs_index,
|
|
284
|
+
'prerelease specs')
|
|
285
|
+
|
|
286
|
+
@files += [@specs_index,
|
|
287
|
+
"#{@specs_index}.gz",
|
|
288
|
+
@latest_specs_index,
|
|
289
|
+
"#{@latest_specs_index}.gz",
|
|
290
|
+
@prerelease_specs_index,
|
|
291
|
+
"#{@prerelease_specs_index}.gz"]
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
##
|
|
295
|
+
# Builds an RSS feed for past two days gem releases according to the gem's
|
|
296
|
+
# date.
|
|
297
|
+
|
|
298
|
+
def build_rss(index)
|
|
299
|
+
if @rss_host.nil? or @rss_gems_host.nil? then
|
|
300
|
+
if LibGems.configuration.really_verbose then
|
|
301
|
+
alert_warning "no --rss-host or --rss-gems-host, RSS generation disabled"
|
|
302
|
+
end
|
|
303
|
+
return
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
require 'cgi'
|
|
307
|
+
require 'libgems/text'
|
|
308
|
+
|
|
309
|
+
extend LibGems::Text
|
|
310
|
+
|
|
311
|
+
LibGems.time 'Generated rss' do
|
|
312
|
+
open @rss_index, 'wb' do |io|
|
|
313
|
+
rss_host = CGI.escapeHTML @rss_host
|
|
314
|
+
rss_title = CGI.escapeHTML(@rss_title || 'gems')
|
|
315
|
+
|
|
316
|
+
io.puts <<-HEADER
|
|
317
|
+
<?xml version="1.0"?>
|
|
318
|
+
<rss version="2.0">
|
|
319
|
+
<channel>
|
|
320
|
+
<title>#{rss_title}</title>
|
|
321
|
+
<link>http://#{rss_host}</link>
|
|
322
|
+
<description>Recently released gems from http://#{rss_host}</description>
|
|
323
|
+
<generator>#{LibGems::NAME} v#{LibGems::VERSION} (RubyGems v#{LibGems::GEM_VERSION})</generator>
|
|
324
|
+
<docs>http://cyber.law.harvard.edu/rss/rss.html</docs>
|
|
325
|
+
HEADER
|
|
326
|
+
|
|
327
|
+
today = LibGems::Specification::TODAY
|
|
328
|
+
yesterday = today - 86400
|
|
329
|
+
|
|
330
|
+
index = index.select do |_, spec|
|
|
331
|
+
spec_date = spec.date
|
|
332
|
+
|
|
333
|
+
case spec_date
|
|
334
|
+
when Date
|
|
335
|
+
Time.parse(spec_date.to_s) >= yesterday
|
|
336
|
+
when Time
|
|
337
|
+
spec_date >= yesterday
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
index = index.select do |_, spec|
|
|
342
|
+
spec_date = spec.date
|
|
343
|
+
|
|
344
|
+
case spec_date
|
|
345
|
+
when Date
|
|
346
|
+
Time.parse(spec_date.to_s) <= today
|
|
347
|
+
when Time
|
|
348
|
+
spec_date <= today
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
index.sort_by { |_, spec| [-spec.date.to_i, spec] }.each do |_, spec|
|
|
353
|
+
gem_path = CGI.escapeHTML "http://#{@rss_gems_host}/gems/#{spec.file_name}"
|
|
354
|
+
size = File.stat(spec.loaded_from).size rescue next
|
|
355
|
+
|
|
356
|
+
description = spec.description || spec.summary || ''
|
|
357
|
+
authors = Array spec.authors
|
|
358
|
+
emails = Array spec.email
|
|
359
|
+
authors = emails.zip(authors).map do |email, author|
|
|
360
|
+
email += " (#{author})" if author and not author.empty?
|
|
361
|
+
end.join ', '
|
|
362
|
+
|
|
363
|
+
description = description.split(/\n\n+/).map do |chunk|
|
|
364
|
+
format_text chunk, 78
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
description = description.join "\n\n"
|
|
368
|
+
|
|
369
|
+
item = ''
|
|
370
|
+
|
|
371
|
+
item << <<-ITEM
|
|
372
|
+
<item>
|
|
373
|
+
<title>#{CGI.escapeHTML spec.full_name}</title>
|
|
374
|
+
<description>
|
|
375
|
+
<pre>#{CGI.escapeHTML description.chomp}</pre>
|
|
376
|
+
</description>
|
|
377
|
+
<author>#{CGI.escapeHTML authors}</author>
|
|
378
|
+
<guid>#{CGI.escapeHTML spec.full_name}</guid>
|
|
379
|
+
<enclosure url=\"#{gem_path}\"
|
|
380
|
+
length=\"#{size}\" type=\"application/octet-stream\" />
|
|
381
|
+
<pubDate>#{spec.date.rfc2822}</pubDate>
|
|
382
|
+
ITEM
|
|
383
|
+
|
|
384
|
+
item << <<-ITEM if spec.homepage
|
|
385
|
+
<link>#{CGI.escapeHTML spec.homepage}</link>
|
|
386
|
+
ITEM
|
|
387
|
+
|
|
388
|
+
item << <<-ITEM
|
|
389
|
+
</item>
|
|
390
|
+
ITEM
|
|
391
|
+
|
|
392
|
+
io.puts item
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
io.puts <<-FOOTER
|
|
396
|
+
</channel>
|
|
397
|
+
</rss>
|
|
398
|
+
FOOTER
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
@files << @rss_index
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
##
|
|
406
|
+
# Collect specifications from .gem files from the gem directory.
|
|
407
|
+
|
|
408
|
+
def collect_specs(gems = gem_file_list)
|
|
409
|
+
index = LibGems::SourceIndex.new
|
|
410
|
+
|
|
411
|
+
progress = ui.progress_reporter gems.size,
|
|
412
|
+
"Loading #{gems.size} gems from #{@dest_directory}",
|
|
413
|
+
"Loaded all gems"
|
|
414
|
+
|
|
415
|
+
LibGems.time 'loaded' do
|
|
416
|
+
gems.each do |gemfile|
|
|
417
|
+
if File.size(gemfile.to_s) == 0 then
|
|
418
|
+
alert_warning "Skipping zero-length gem: #{gemfile}"
|
|
419
|
+
next
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
begin
|
|
423
|
+
spec = LibGems::Format.from_file_by_path(gemfile).spec
|
|
424
|
+
spec.loaded_from = gemfile
|
|
425
|
+
|
|
426
|
+
unless gemfile =~ /\/#{Regexp.escape spec.original_name}.*\.gem\z/i then
|
|
427
|
+
expected_name = spec.full_name
|
|
428
|
+
expected_name << " (#{spec.original_name})" if
|
|
429
|
+
spec.original_name != spec.full_name
|
|
430
|
+
alert_warning "Skipping misnamed gem: #{gemfile} should be named #{expected_name}"
|
|
431
|
+
next
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
abbreviate spec
|
|
435
|
+
sanitize spec
|
|
436
|
+
|
|
437
|
+
index.add_spec spec, spec.original_name
|
|
438
|
+
|
|
439
|
+
progress.updated spec.original_name
|
|
440
|
+
|
|
441
|
+
rescue SignalException => e
|
|
442
|
+
alert_error "Received signal, exiting"
|
|
443
|
+
raise
|
|
444
|
+
rescue Exception => e
|
|
445
|
+
alert_error "Unable to process #{gemfile}\n#{e.message} (#{e.class})\n\t#{e.backtrace.join "\n\t"}"
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
progress.done
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
index
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
##
|
|
456
|
+
# Compresses indicies on disk
|
|
457
|
+
#--
|
|
458
|
+
# All future files should be compressed using gzip, not deflate
|
|
459
|
+
|
|
460
|
+
def compress_indicies
|
|
461
|
+
say "Compressing indicies"
|
|
462
|
+
|
|
463
|
+
LibGems.time 'Compressed indicies' do
|
|
464
|
+
if @build_legacy then
|
|
465
|
+
compress @quick_index, 'rz'
|
|
466
|
+
paranoid @quick_index, 'rz'
|
|
467
|
+
|
|
468
|
+
compress @latest_index, 'rz'
|
|
469
|
+
paranoid @latest_index, 'rz'
|
|
470
|
+
|
|
471
|
+
compress @marshal_index, 'Z'
|
|
472
|
+
paranoid @marshal_index, 'Z'
|
|
473
|
+
|
|
474
|
+
compress @master_index, 'Z'
|
|
475
|
+
paranoid @master_index, 'Z'
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
if @build_modern then
|
|
479
|
+
gzip @specs_index
|
|
480
|
+
gzip @latest_specs_index
|
|
481
|
+
gzip @prerelease_specs_index
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
##
|
|
487
|
+
# Compacts Marshal output for the specs index data source by using identical
|
|
488
|
+
# objects as much as possible.
|
|
489
|
+
|
|
490
|
+
def compact_specs(specs)
|
|
491
|
+
names = {}
|
|
492
|
+
versions = {}
|
|
493
|
+
platforms = {}
|
|
494
|
+
|
|
495
|
+
specs.map do |(name, version, platform)|
|
|
496
|
+
names[name] = name unless names.include? name
|
|
497
|
+
versions[version] = version unless versions.include? version
|
|
498
|
+
platforms[platform] = platform unless platforms.include? platform
|
|
499
|
+
|
|
500
|
+
[names[name], versions[version], platforms[platform]]
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
##
|
|
505
|
+
# Compress +filename+ with +extension+.
|
|
506
|
+
|
|
507
|
+
def compress(filename, extension)
|
|
508
|
+
data = LibGems.read_binary filename
|
|
509
|
+
|
|
510
|
+
zipped = LibGems.deflate data
|
|
511
|
+
|
|
512
|
+
open "#{filename}.#{extension}", 'wb' do |io|
|
|
513
|
+
io.write zipped
|
|
514
|
+
end
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
##
|
|
518
|
+
# List of gem file names to index.
|
|
519
|
+
|
|
520
|
+
def gem_file_list
|
|
521
|
+
Dir.glob(File.join(@dest_directory, "gems", "*.gem"))
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
##
|
|
525
|
+
# Builds and installs indicies.
|
|
526
|
+
|
|
527
|
+
def generate_index
|
|
528
|
+
make_temp_directories
|
|
529
|
+
index = collect_specs
|
|
530
|
+
build_indicies index
|
|
531
|
+
install_indicies
|
|
532
|
+
rescue SignalException
|
|
533
|
+
ensure
|
|
534
|
+
FileUtils.rm_rf @directory
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
##
|
|
538
|
+
# Zlib::GzipWriter wrapper that gzips +filename+ on disk.
|
|
539
|
+
|
|
540
|
+
def gzip(filename)
|
|
541
|
+
Zlib::GzipWriter.open "#{filename}.gz" do |io|
|
|
542
|
+
io.write LibGems.read_binary(filename)
|
|
543
|
+
end
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
##
|
|
547
|
+
# Install generated indicies into the destination directory.
|
|
548
|
+
|
|
549
|
+
def install_indicies
|
|
550
|
+
verbose = LibGems.configuration.really_verbose
|
|
551
|
+
|
|
552
|
+
say "Moving index into production dir #{@dest_directory}" if verbose
|
|
553
|
+
|
|
554
|
+
files = @files.dup
|
|
555
|
+
files.delete @quick_marshal_dir if files.include? @quick_dir
|
|
556
|
+
|
|
557
|
+
if files.include? @quick_marshal_dir and
|
|
558
|
+
not files.include? @quick_dir then
|
|
559
|
+
files.delete @quick_marshal_dir
|
|
560
|
+
quick_marshal_dir = @quick_marshal_dir.sub @directory, ''
|
|
561
|
+
|
|
562
|
+
dst_name = File.join @dest_directory, quick_marshal_dir
|
|
563
|
+
|
|
564
|
+
FileUtils.mkdir_p File.dirname(dst_name), :verbose => verbose
|
|
565
|
+
FileUtils.rm_rf dst_name, :verbose => verbose
|
|
566
|
+
FileUtils.mv @quick_marshal_dir, dst_name, :verbose => verbose,
|
|
567
|
+
:force => true
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
files = files.map do |path|
|
|
571
|
+
path.sub @directory, ''
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
files.each do |file|
|
|
575
|
+
src_name = File.join @directory, file
|
|
576
|
+
dst_name = File.join @dest_directory, file
|
|
577
|
+
|
|
578
|
+
FileUtils.rm_rf dst_name, :verbose => verbose
|
|
579
|
+
FileUtils.mv src_name, @dest_directory, :verbose => verbose,
|
|
580
|
+
:force => true
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
##
|
|
585
|
+
# Make directories for index generation
|
|
586
|
+
|
|
587
|
+
def make_temp_directories
|
|
588
|
+
FileUtils.rm_rf @directory
|
|
589
|
+
FileUtils.mkdir_p @directory, :mode => 0700
|
|
590
|
+
FileUtils.mkdir_p @quick_marshal_dir
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
##
|
|
594
|
+
# Ensure +path+ and path with +extension+ are identical.
|
|
595
|
+
|
|
596
|
+
def paranoid(path, extension)
|
|
597
|
+
data = LibGems.read_binary path
|
|
598
|
+
compressed_data = LibGems.read_binary "#{path}.#{extension}"
|
|
599
|
+
|
|
600
|
+
unless data == LibGems.inflate(compressed_data) then
|
|
601
|
+
raise "Compressed file #{compressed_path} does not match uncompressed file #{path}"
|
|
602
|
+
end
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
##
|
|
606
|
+
# Sanitize the descriptive fields in the spec. Sometimes non-ASCII
|
|
607
|
+
# characters will garble the site index. Non-ASCII characters will
|
|
608
|
+
# be replaced by their XML entity equivalent.
|
|
609
|
+
|
|
610
|
+
def sanitize(spec)
|
|
611
|
+
spec.summary = sanitize_string(spec.summary)
|
|
612
|
+
spec.description = sanitize_string(spec.description)
|
|
613
|
+
spec.post_install_message = sanitize_string(spec.post_install_message)
|
|
614
|
+
spec.authors = spec.authors.collect { |a| sanitize_string(a) }
|
|
615
|
+
|
|
616
|
+
spec
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
##
|
|
620
|
+
# Sanitize a single string.
|
|
621
|
+
|
|
622
|
+
def sanitize_string(string)
|
|
623
|
+
return string unless string
|
|
624
|
+
|
|
625
|
+
# HACK the #to_s is in here because RSpec has an Array of Arrays of
|
|
626
|
+
# Strings for authors. Need a way to disallow bad values on gempsec
|
|
627
|
+
# generation. (Probably won't happen.)
|
|
628
|
+
string = string.to_s
|
|
629
|
+
|
|
630
|
+
begin
|
|
631
|
+
Builder::XChar.encode string
|
|
632
|
+
rescue NameError, NoMethodError
|
|
633
|
+
string.to_xs
|
|
634
|
+
end
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
##
|
|
638
|
+
# Perform an in-place update of the repository from newly added gems. Only
|
|
639
|
+
# works for modern indicies, and sets #build_legacy to false when run.
|
|
640
|
+
|
|
641
|
+
def update_index
|
|
642
|
+
@build_legacy = false
|
|
643
|
+
|
|
644
|
+
make_temp_directories
|
|
645
|
+
|
|
646
|
+
specs_mtime = File.stat(@dest_specs_index).mtime
|
|
647
|
+
newest_mtime = Time.at 0
|
|
648
|
+
|
|
649
|
+
updated_gems = gem_file_list.select do |gem|
|
|
650
|
+
gem_mtime = File.stat(gem).mtime
|
|
651
|
+
newest_mtime = gem_mtime if gem_mtime > newest_mtime
|
|
652
|
+
gem_mtime >= specs_mtime
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
if updated_gems.empty? then
|
|
656
|
+
say 'No new gems'
|
|
657
|
+
terminate_interaction 0
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
index = collect_specs updated_gems
|
|
661
|
+
|
|
662
|
+
files = build_marshal_gemspecs index
|
|
663
|
+
|
|
664
|
+
LibGems.time 'Updated indexes' do
|
|
665
|
+
update_specs_index index.released_gems, @dest_specs_index, @specs_index
|
|
666
|
+
update_specs_index index.released_gems, @dest_latest_specs_index, @latest_specs_index
|
|
667
|
+
update_specs_index(index.prerelease_gems, @dest_prerelease_specs_index,
|
|
668
|
+
@prerelease_specs_index)
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
compress_indicies
|
|
672
|
+
|
|
673
|
+
verbose = LibGems.configuration.really_verbose
|
|
674
|
+
|
|
675
|
+
say "Updating production dir #{@dest_directory}" if verbose
|
|
676
|
+
|
|
677
|
+
files << @specs_index
|
|
678
|
+
files << "#{@specs_index}.gz"
|
|
679
|
+
files << @latest_specs_index
|
|
680
|
+
files << "#{@latest_specs_index}.gz"
|
|
681
|
+
files << @prerelease_specs_index
|
|
682
|
+
files << "#{@prerelease_specs_index}.gz"
|
|
683
|
+
|
|
684
|
+
files = files.map do |path|
|
|
685
|
+
path.sub @directory, ''
|
|
686
|
+
end
|
|
687
|
+
|
|
688
|
+
files.each do |file|
|
|
689
|
+
src_name = File.join @directory, file
|
|
690
|
+
dst_name = File.join @dest_directory, File.dirname(file)
|
|
691
|
+
|
|
692
|
+
FileUtils.mv src_name, dst_name, :verbose => verbose,
|
|
693
|
+
:force => true
|
|
694
|
+
|
|
695
|
+
File.utime newest_mtime, newest_mtime, dst_name
|
|
696
|
+
end
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
##
|
|
700
|
+
# Combines specs in +index+ and +source+ then writes out a new copy to
|
|
701
|
+
# +dest+. For a latest index, does not ensure the new file is minimal.
|
|
702
|
+
|
|
703
|
+
def update_specs_index(index, source, dest)
|
|
704
|
+
specs_index = Marshal.load LibGems.read_binary(source)
|
|
705
|
+
|
|
706
|
+
index.each do |_, spec|
|
|
707
|
+
platform = spec.original_platform
|
|
708
|
+
platform = LibGems::Platform::RUBY if platform.nil? or platform.empty?
|
|
709
|
+
specs_index << [spec.name, spec.version, platform]
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
specs_index = compact_specs specs_index.uniq.sort
|
|
713
|
+
|
|
714
|
+
open dest, 'wb' do |io|
|
|
715
|
+
Marshal.dump specs_index, io
|
|
716
|
+
end
|
|
717
|
+
end
|
|
718
|
+
|
|
719
|
+
end
|
|
720
|
+
|