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,135 @@
|
|
|
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 'uri'
|
|
8
|
+
require 'libgems'
|
|
9
|
+
|
|
10
|
+
##
|
|
11
|
+
# Mixin methods for local and remote LibGems::Command options.
|
|
12
|
+
|
|
13
|
+
module LibGems::LocalRemoteOptions
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# Allows OptionParser to handle HTTP URIs.
|
|
17
|
+
|
|
18
|
+
def accept_uri_http
|
|
19
|
+
OptionParser.accept URI::HTTP do |value|
|
|
20
|
+
begin
|
|
21
|
+
uri = URI.parse value
|
|
22
|
+
rescue URI::InvalidURIError
|
|
23
|
+
raise OptionParser::InvalidArgument, value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
unless ['http', 'https', 'file'].include?(uri.scheme)
|
|
27
|
+
raise OptionParser::InvalidArgument, value
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
value
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
# Add local/remote options to the command line parser.
|
|
36
|
+
|
|
37
|
+
def add_local_remote_options
|
|
38
|
+
add_option(:"Local/Remote", '-l', '--local',
|
|
39
|
+
'Restrict operations to the LOCAL domain') do |value, options|
|
|
40
|
+
options[:domain] = :local
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
add_option(:"Local/Remote", '-r', '--remote',
|
|
44
|
+
'Restrict operations to the REMOTE domain') do |value, options|
|
|
45
|
+
options[:domain] = :remote
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
add_option(:"Local/Remote", '-b', '--both',
|
|
49
|
+
'Allow LOCAL and REMOTE operations') do |value, options|
|
|
50
|
+
options[:domain] = :both
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
add_bulk_threshold_option
|
|
54
|
+
add_source_option
|
|
55
|
+
add_proxy_option
|
|
56
|
+
add_update_sources_option
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
##
|
|
60
|
+
# Add the --bulk-threshold option
|
|
61
|
+
|
|
62
|
+
def add_bulk_threshold_option
|
|
63
|
+
add_option(:"Local/Remote", '-B', '--bulk-threshold COUNT',
|
|
64
|
+
"Threshold for switching to bulk",
|
|
65
|
+
"synchronization (default #{LibGems.configuration.bulk_threshold})") do
|
|
66
|
+
|value, options|
|
|
67
|
+
LibGems.configuration.bulk_threshold = value.to_i
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
##
|
|
72
|
+
# Add the --http-proxy option
|
|
73
|
+
|
|
74
|
+
def add_proxy_option
|
|
75
|
+
accept_uri_http
|
|
76
|
+
|
|
77
|
+
add_option(:"Local/Remote", '-p', '--[no-]http-proxy [URL]', URI::HTTP,
|
|
78
|
+
'Use HTTP proxy for remote operations') do |value, options|
|
|
79
|
+
options[:http_proxy] = (value == false) ? :no_proxy : value
|
|
80
|
+
LibGems.configuration[:http_proxy] = options[:http_proxy]
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
##
|
|
85
|
+
# Add the --source option
|
|
86
|
+
|
|
87
|
+
def add_source_option
|
|
88
|
+
accept_uri_http
|
|
89
|
+
|
|
90
|
+
add_option(:"Local/Remote", '--source URL', URI::HTTP,
|
|
91
|
+
'Use URL as the remote source for gems') do |source, options|
|
|
92
|
+
source << '/' if source !~ /\/\z/
|
|
93
|
+
|
|
94
|
+
if options[:added_source] then
|
|
95
|
+
LibGems.sources << source unless LibGems.sources.include?(source)
|
|
96
|
+
else
|
|
97
|
+
options[:added_source] = true
|
|
98
|
+
LibGems.sources.replace [source]
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
##
|
|
104
|
+
# Add the --update-sources option
|
|
105
|
+
|
|
106
|
+
def add_update_sources_option
|
|
107
|
+
add_option(:"Local/Remote", '-u', '--[no-]update-sources',
|
|
108
|
+
'Update local source cache') do |value, options|
|
|
109
|
+
LibGems.configuration.update_sources = value
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
##
|
|
114
|
+
# Is fetching of local and remote information enabled?
|
|
115
|
+
|
|
116
|
+
def both?
|
|
117
|
+
options[:domain] == :both
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
##
|
|
121
|
+
# Is local fetching enabled?
|
|
122
|
+
|
|
123
|
+
def local?
|
|
124
|
+
options[:domain] == :local || options[:domain] == :both
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
##
|
|
128
|
+
# Is remote fetching enabled?
|
|
129
|
+
|
|
130
|
+
def remote?
|
|
131
|
+
options[:domain] == :remote || options[:domain] == :both
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
end
|
|
135
|
+
|
|
@@ -0,0 +1,153 @@
|
|
|
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'
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
# The format class knows the guts of the RubyGem .gem file format and provides
|
|
11
|
+
# the capability to read gem files
|
|
12
|
+
|
|
13
|
+
class LibGems::OldFormat
|
|
14
|
+
|
|
15
|
+
attr_accessor :spec, :file_entries, :gem_path
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# Constructs an instance of a Format object, representing the gem's data
|
|
19
|
+
# structure.
|
|
20
|
+
#
|
|
21
|
+
# gem:: [String] The file name of the gem
|
|
22
|
+
|
|
23
|
+
def initialize(gem_path)
|
|
24
|
+
require 'fileutils'
|
|
25
|
+
require 'zlib'
|
|
26
|
+
LibGems.load_yaml
|
|
27
|
+
|
|
28
|
+
@gem_path = gem_path
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Reads the named gem file and returns a Format object, representing the
|
|
33
|
+
# data from the gem file
|
|
34
|
+
#
|
|
35
|
+
# file_path:: [String] Path to the gem file
|
|
36
|
+
|
|
37
|
+
def self.from_file_by_path(file_path)
|
|
38
|
+
unless File.exist?(file_path)
|
|
39
|
+
raise LibGems::Exception, "Cannot load gem file [#{file_path}]"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
File.open(file_path, 'rb') do |file|
|
|
43
|
+
from_io(file, file_path)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Reads a gem from an io stream and returns a Format object, representing
|
|
49
|
+
# the data from the gem file
|
|
50
|
+
#
|
|
51
|
+
# io:: [IO] Stream from which to read the gem
|
|
52
|
+
|
|
53
|
+
def self.from_io(io, gem_path="(io)")
|
|
54
|
+
format = self.new(gem_path)
|
|
55
|
+
skip_ruby(io)
|
|
56
|
+
format.spec = read_spec(io)
|
|
57
|
+
format.file_entries = []
|
|
58
|
+
read_files_from_gem(io) do |entry, file_data|
|
|
59
|
+
format.file_entries << [entry, file_data]
|
|
60
|
+
end
|
|
61
|
+
format
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
##
|
|
67
|
+
# Skips the Ruby self-install header. After calling this method, the
|
|
68
|
+
# IO index will be set after the Ruby code.
|
|
69
|
+
#
|
|
70
|
+
# file:: [IO] The IO to process (skip the Ruby code)
|
|
71
|
+
|
|
72
|
+
def self.skip_ruby(file)
|
|
73
|
+
end_seen = false
|
|
74
|
+
loop {
|
|
75
|
+
line = file.gets
|
|
76
|
+
if(line == nil || line.chomp == "__END__") then
|
|
77
|
+
end_seen = true
|
|
78
|
+
break
|
|
79
|
+
end
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if end_seen == false then
|
|
83
|
+
raise LibGems::Exception.new("Failed to find end of ruby script while reading gem")
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
##
|
|
88
|
+
# Reads the specification YAML from the supplied IO and constructs
|
|
89
|
+
# a LibGems::Specification from it. After calling this method, the
|
|
90
|
+
# IO index will be set after the specification header.
|
|
91
|
+
#
|
|
92
|
+
# file:: [IO] The IO to process
|
|
93
|
+
|
|
94
|
+
def self.read_spec(file)
|
|
95
|
+
yaml = ''
|
|
96
|
+
|
|
97
|
+
read_until_dashes file do |line|
|
|
98
|
+
yaml << line
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
LibGems::Specification.from_yaml yaml
|
|
102
|
+
rescue YAML::Error => e
|
|
103
|
+
raise LibGems::Exception, "Failed to parse gem specification out of gem file"
|
|
104
|
+
rescue ArgumentError => e
|
|
105
|
+
raise LibGems::Exception, "Failed to parse gem specification out of gem file"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
##
|
|
109
|
+
# Reads lines from the supplied IO until a end-of-yaml (---) is
|
|
110
|
+
# reached
|
|
111
|
+
#
|
|
112
|
+
# file:: [IO] The IO to process
|
|
113
|
+
# block:: [String] The read line
|
|
114
|
+
|
|
115
|
+
def self.read_until_dashes(file)
|
|
116
|
+
while((line = file.gets) && line.chomp.strip != "---") do
|
|
117
|
+
yield line
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
##
|
|
122
|
+
# Reads the embedded file data from a gem file, yielding an entry
|
|
123
|
+
# containing metadata about the file and the file contents themselves
|
|
124
|
+
# for each file that's archived in the gem.
|
|
125
|
+
# NOTE: Many of these methods should be extracted into some kind of
|
|
126
|
+
# LibGems file read/writer
|
|
127
|
+
#
|
|
128
|
+
# gem_file:: [IO] The IO to process
|
|
129
|
+
|
|
130
|
+
def self.read_files_from_gem(gem_file)
|
|
131
|
+
errstr = "Error reading files from gem"
|
|
132
|
+
header_yaml = ''
|
|
133
|
+
begin
|
|
134
|
+
self.read_until_dashes(gem_file) do |line|
|
|
135
|
+
header_yaml << line
|
|
136
|
+
end
|
|
137
|
+
header = YAML.load(header_yaml)
|
|
138
|
+
raise LibGems::Exception, errstr unless header
|
|
139
|
+
|
|
140
|
+
header.each do |entry|
|
|
141
|
+
file_data = ''
|
|
142
|
+
self.read_until_dashes(gem_file) do |line|
|
|
143
|
+
file_data << line
|
|
144
|
+
end
|
|
145
|
+
yield [entry, Zlib::Inflate.inflate(file_data.strip.unpack("m")[0])]
|
|
146
|
+
end
|
|
147
|
+
rescue Zlib::DataError
|
|
148
|
+
raise LibGems::Exception, errstr
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
end
|
|
153
|
+
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#--
|
|
3
|
+
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
|
|
4
|
+
# See LICENSE.txt for additional licensing information.
|
|
5
|
+
#++
|
|
6
|
+
|
|
7
|
+
require 'fileutils'
|
|
8
|
+
require 'find'
|
|
9
|
+
require 'stringio'
|
|
10
|
+
require 'yaml'
|
|
11
|
+
require 'zlib'
|
|
12
|
+
|
|
13
|
+
require 'libgems/security'
|
|
14
|
+
require 'libgems/specification'
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# Wrapper for FileUtils meant to provide logging and additional operations if
|
|
18
|
+
# needed.
|
|
19
|
+
|
|
20
|
+
class LibGems::FileOperations
|
|
21
|
+
|
|
22
|
+
def initialize(logger = nil)
|
|
23
|
+
@logger = logger
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def method_missing(meth, *args, &block)
|
|
27
|
+
case
|
|
28
|
+
when FileUtils.respond_to?(meth)
|
|
29
|
+
@logger.log "#{meth}: #{args}" if @logger
|
|
30
|
+
FileUtils.send meth, *args, &block
|
|
31
|
+
when LibGems::FileOperations.respond_to?(meth)
|
|
32
|
+
@logger.log "#{meth}: #{args}" if @logger
|
|
33
|
+
LibGems::FileOperations.send meth, *args, &block
|
|
34
|
+
else
|
|
35
|
+
super
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
module LibGems::Package
|
|
42
|
+
|
|
43
|
+
class Error < StandardError; end
|
|
44
|
+
class NonSeekableIO < Error; end
|
|
45
|
+
class ClosedIO < Error; end
|
|
46
|
+
class BadCheckSum < Error; end
|
|
47
|
+
class TooLongFileName < Error; end
|
|
48
|
+
class FormatError < Error; end
|
|
49
|
+
|
|
50
|
+
def self.open(io, mode = "r", signer = nil, &block)
|
|
51
|
+
tar_type = case mode
|
|
52
|
+
when 'r' then TarInput
|
|
53
|
+
when 'w' then TarOutput
|
|
54
|
+
else
|
|
55
|
+
raise "Unknown Package open mode"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
tar_type.open(io, signer, &block)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.pack(src, destname, signer = nil)
|
|
62
|
+
TarOutput.open(destname, signer) do |outp|
|
|
63
|
+
dir_class.chdir(src) do
|
|
64
|
+
outp.metadata = (file_class.read("RPA/metadata") rescue nil)
|
|
65
|
+
find_class.find('.') do |entry|
|
|
66
|
+
case
|
|
67
|
+
when file_class.file?(entry)
|
|
68
|
+
entry.sub!(%r{\./}, "")
|
|
69
|
+
next if entry =~ /\ARPA\//
|
|
70
|
+
stat = File.stat(entry)
|
|
71
|
+
outp.add_file_simple(entry, stat.mode, stat.size) do |os|
|
|
72
|
+
file_class.open(entry, "rb") do |f|
|
|
73
|
+
os.write(f.read(4096)) until f.eof?
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
when file_class.dir?(entry)
|
|
77
|
+
entry.sub!(%r{\./}, "")
|
|
78
|
+
next if entry == "RPA"
|
|
79
|
+
outp.mkdir(entry, file_class.stat(entry).mode)
|
|
80
|
+
else
|
|
81
|
+
raise "Don't know how to pack this yet!"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
require 'libgems/package/f_sync_dir'
|
|
91
|
+
require 'libgems/package/tar_header'
|
|
92
|
+
require 'libgems/package/tar_input'
|
|
93
|
+
require 'libgems/package/tar_output'
|
|
94
|
+
require 'libgems/package/tar_reader'
|
|
95
|
+
require 'libgems/package/tar_reader/entry'
|
|
96
|
+
require 'libgems/package/tar_writer'
|
|
97
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#--
|
|
3
|
+
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
|
|
4
|
+
# See LICENSE.txt for additional licensing information.
|
|
5
|
+
#++
|
|
6
|
+
|
|
7
|
+
module LibGems::Package::FSyncDir
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# make sure this hits the disc
|
|
13
|
+
|
|
14
|
+
def fsync_dir(dirname)
|
|
15
|
+
dir = open dirname, 'r'
|
|
16
|
+
dir.fsync
|
|
17
|
+
rescue # ignore IOError if it's an unpatched (old) Ruby
|
|
18
|
+
ensure
|
|
19
|
+
dir.close if dir rescue nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#--
|
|
3
|
+
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
|
|
4
|
+
# See LICENSE.txt for additional licensing information.
|
|
5
|
+
#++
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
#--
|
|
9
|
+
# struct tarfile_entry_posix {
|
|
10
|
+
# char name[100]; # ASCII + (Z unless filled)
|
|
11
|
+
# char mode[8]; # 0 padded, octal, null
|
|
12
|
+
# char uid[8]; # ditto
|
|
13
|
+
# char gid[8]; # ditto
|
|
14
|
+
# char size[12]; # 0 padded, octal, null
|
|
15
|
+
# char mtime[12]; # 0 padded, octal, null
|
|
16
|
+
# char checksum[8]; # 0 padded, octal, null, space
|
|
17
|
+
# char typeflag[1]; # file: "0" dir: "5"
|
|
18
|
+
# char linkname[100]; # ASCII + (Z unless filled)
|
|
19
|
+
# char magic[6]; # "ustar\0"
|
|
20
|
+
# char version[2]; # "00"
|
|
21
|
+
# char uname[32]; # ASCIIZ
|
|
22
|
+
# char gname[32]; # ASCIIZ
|
|
23
|
+
# char devmajor[8]; # 0 padded, octal, null
|
|
24
|
+
# char devminor[8]; # o padded, octal, null
|
|
25
|
+
# char prefix[155]; # ASCII + (Z unless filled)
|
|
26
|
+
# };
|
|
27
|
+
#++
|
|
28
|
+
# A header for a tar file
|
|
29
|
+
|
|
30
|
+
class LibGems::Package::TarHeader
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
# Fields in the tar header
|
|
34
|
+
|
|
35
|
+
FIELDS = [
|
|
36
|
+
:checksum,
|
|
37
|
+
:devmajor,
|
|
38
|
+
:devminor,
|
|
39
|
+
:gid,
|
|
40
|
+
:gname,
|
|
41
|
+
:linkname,
|
|
42
|
+
:magic,
|
|
43
|
+
:mode,
|
|
44
|
+
:mtime,
|
|
45
|
+
:name,
|
|
46
|
+
:prefix,
|
|
47
|
+
:size,
|
|
48
|
+
:typeflag,
|
|
49
|
+
:uid,
|
|
50
|
+
:uname,
|
|
51
|
+
:version,
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# Pack format for a tar header
|
|
56
|
+
|
|
57
|
+
PACK_FORMAT = 'a100' + # name
|
|
58
|
+
'a8' + # mode
|
|
59
|
+
'a8' + # uid
|
|
60
|
+
'a8' + # gid
|
|
61
|
+
'a12' + # size
|
|
62
|
+
'a12' + # mtime
|
|
63
|
+
'a7a' + # chksum
|
|
64
|
+
'a' + # typeflag
|
|
65
|
+
'a100' + # linkname
|
|
66
|
+
'a6' + # magic
|
|
67
|
+
'a2' + # version
|
|
68
|
+
'a32' + # uname
|
|
69
|
+
'a32' + # gname
|
|
70
|
+
'a8' + # devmajor
|
|
71
|
+
'a8' + # devminor
|
|
72
|
+
'a155' # prefix
|
|
73
|
+
|
|
74
|
+
##
|
|
75
|
+
# Unpack format for a tar header
|
|
76
|
+
|
|
77
|
+
UNPACK_FORMAT = 'A100' + # name
|
|
78
|
+
'A8' + # mode
|
|
79
|
+
'A8' + # uid
|
|
80
|
+
'A8' + # gid
|
|
81
|
+
'A12' + # size
|
|
82
|
+
'A12' + # mtime
|
|
83
|
+
'A8' + # checksum
|
|
84
|
+
'A' + # typeflag
|
|
85
|
+
'A100' + # linkname
|
|
86
|
+
'A6' + # magic
|
|
87
|
+
'A2' + # version
|
|
88
|
+
'A32' + # uname
|
|
89
|
+
'A32' + # gname
|
|
90
|
+
'A8' + # devmajor
|
|
91
|
+
'A8' + # devminor
|
|
92
|
+
'A155' # prefix
|
|
93
|
+
|
|
94
|
+
attr_reader(*FIELDS)
|
|
95
|
+
|
|
96
|
+
##
|
|
97
|
+
# Creates a tar header from IO +stream+
|
|
98
|
+
|
|
99
|
+
def self.from(stream)
|
|
100
|
+
header = stream.read 512
|
|
101
|
+
empty = (header == "\0" * 512)
|
|
102
|
+
|
|
103
|
+
fields = header.unpack UNPACK_FORMAT
|
|
104
|
+
|
|
105
|
+
name = fields.shift
|
|
106
|
+
mode = fields.shift.oct
|
|
107
|
+
uid = fields.shift.oct
|
|
108
|
+
gid = fields.shift.oct
|
|
109
|
+
size = fields.shift.oct
|
|
110
|
+
mtime = fields.shift.oct
|
|
111
|
+
checksum = fields.shift.oct
|
|
112
|
+
typeflag = fields.shift
|
|
113
|
+
linkname = fields.shift
|
|
114
|
+
magic = fields.shift
|
|
115
|
+
version = fields.shift.oct
|
|
116
|
+
uname = fields.shift
|
|
117
|
+
gname = fields.shift
|
|
118
|
+
devmajor = fields.shift.oct
|
|
119
|
+
devminor = fields.shift.oct
|
|
120
|
+
prefix = fields.shift
|
|
121
|
+
|
|
122
|
+
new :name => name,
|
|
123
|
+
:mode => mode,
|
|
124
|
+
:uid => uid,
|
|
125
|
+
:gid => gid,
|
|
126
|
+
:size => size,
|
|
127
|
+
:mtime => mtime,
|
|
128
|
+
:checksum => checksum,
|
|
129
|
+
:typeflag => typeflag,
|
|
130
|
+
:linkname => linkname,
|
|
131
|
+
:magic => magic,
|
|
132
|
+
:version => version,
|
|
133
|
+
:uname => uname,
|
|
134
|
+
:gname => gname,
|
|
135
|
+
:devmajor => devmajor,
|
|
136
|
+
:devminor => devminor,
|
|
137
|
+
:prefix => prefix,
|
|
138
|
+
|
|
139
|
+
:empty => empty
|
|
140
|
+
|
|
141
|
+
# HACK unfactor for Rubinius
|
|
142
|
+
#new :name => fields.shift,
|
|
143
|
+
# :mode => fields.shift.oct,
|
|
144
|
+
# :uid => fields.shift.oct,
|
|
145
|
+
# :gid => fields.shift.oct,
|
|
146
|
+
# :size => fields.shift.oct,
|
|
147
|
+
# :mtime => fields.shift.oct,
|
|
148
|
+
# :checksum => fields.shift.oct,
|
|
149
|
+
# :typeflag => fields.shift,
|
|
150
|
+
# :linkname => fields.shift,
|
|
151
|
+
# :magic => fields.shift,
|
|
152
|
+
# :version => fields.shift.oct,
|
|
153
|
+
# :uname => fields.shift,
|
|
154
|
+
# :gname => fields.shift,
|
|
155
|
+
# :devmajor => fields.shift.oct,
|
|
156
|
+
# :devminor => fields.shift.oct,
|
|
157
|
+
# :prefix => fields.shift,
|
|
158
|
+
|
|
159
|
+
# :empty => empty
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
##
|
|
163
|
+
# Creates a new TarHeader using +vals+
|
|
164
|
+
|
|
165
|
+
def initialize(vals)
|
|
166
|
+
unless vals[:name] && vals[:size] && vals[:prefix] && vals[:mode] then
|
|
167
|
+
raise ArgumentError, ":name, :size, :prefix and :mode required"
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
vals[:uid] ||= 0
|
|
171
|
+
vals[:gid] ||= 0
|
|
172
|
+
vals[:mtime] ||= 0
|
|
173
|
+
vals[:checksum] ||= ""
|
|
174
|
+
vals[:typeflag] ||= "0"
|
|
175
|
+
vals[:magic] ||= "ustar"
|
|
176
|
+
vals[:version] ||= "00"
|
|
177
|
+
vals[:uname] ||= "wheel"
|
|
178
|
+
vals[:gname] ||= "wheel"
|
|
179
|
+
vals[:devmajor] ||= 0
|
|
180
|
+
vals[:devminor] ||= 0
|
|
181
|
+
|
|
182
|
+
FIELDS.each do |name|
|
|
183
|
+
instance_variable_set "@#{name}", vals[name]
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
@empty = vals[:empty]
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
##
|
|
190
|
+
# Is the tar entry empty?
|
|
191
|
+
|
|
192
|
+
def empty?
|
|
193
|
+
@empty
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def ==(other) # :nodoc:
|
|
197
|
+
self.class === other and
|
|
198
|
+
@checksum == other.checksum and
|
|
199
|
+
@devmajor == other.devmajor and
|
|
200
|
+
@devminor == other.devminor and
|
|
201
|
+
@gid == other.gid and
|
|
202
|
+
@gname == other.gname and
|
|
203
|
+
@linkname == other.linkname and
|
|
204
|
+
@magic == other.magic and
|
|
205
|
+
@mode == other.mode and
|
|
206
|
+
@mtime == other.mtime and
|
|
207
|
+
@name == other.name and
|
|
208
|
+
@prefix == other.prefix and
|
|
209
|
+
@size == other.size and
|
|
210
|
+
@typeflag == other.typeflag and
|
|
211
|
+
@uid == other.uid and
|
|
212
|
+
@uname == other.uname and
|
|
213
|
+
@version == other.version
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def to_s # :nodoc:
|
|
217
|
+
update_checksum
|
|
218
|
+
header
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
##
|
|
222
|
+
# Updates the TarHeader's checksum
|
|
223
|
+
|
|
224
|
+
def update_checksum
|
|
225
|
+
header = header " " * 8
|
|
226
|
+
@checksum = oct calculate_checksum(header), 6
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
private
|
|
230
|
+
|
|
231
|
+
def calculate_checksum(header)
|
|
232
|
+
header.unpack("C*").inject { |a, b| a + b }
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def header(checksum = @checksum)
|
|
236
|
+
header = [
|
|
237
|
+
name,
|
|
238
|
+
oct(mode, 7),
|
|
239
|
+
oct(uid, 7),
|
|
240
|
+
oct(gid, 7),
|
|
241
|
+
oct(size, 11),
|
|
242
|
+
oct(mtime, 11),
|
|
243
|
+
checksum,
|
|
244
|
+
" ",
|
|
245
|
+
typeflag,
|
|
246
|
+
linkname,
|
|
247
|
+
magic,
|
|
248
|
+
oct(version, 2),
|
|
249
|
+
uname,
|
|
250
|
+
gname,
|
|
251
|
+
oct(devmajor, 7),
|
|
252
|
+
oct(devminor, 7),
|
|
253
|
+
prefix
|
|
254
|
+
]
|
|
255
|
+
|
|
256
|
+
header = header.pack PACK_FORMAT
|
|
257
|
+
|
|
258
|
+
header << ("\0" * ((512 - header.size) % 512))
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def oct(num, len)
|
|
262
|
+
"%0#{len}o" % num
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
end
|
|
266
|
+
|