libgems 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,44 @@
|
|
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
|
+
module Kernel
|
8
|
+
|
9
|
+
##
|
10
|
+
# The Kernel#require from before SlimGems was loaded.
|
11
|
+
|
12
|
+
alias libgems_original_require require
|
13
|
+
|
14
|
+
##
|
15
|
+
# When SlimGems is required, Kernel#require is replaced with our own which
|
16
|
+
# is capable of loading gems on demand.
|
17
|
+
#
|
18
|
+
# When you call <tt>require 'x'</tt>, this is what happens:
|
19
|
+
# * If the file can be loaded from the existing Ruby loadpath, it
|
20
|
+
# is.
|
21
|
+
# * Otherwise, installed gems are searched for a file that matches.
|
22
|
+
# If it's found in gem 'y', that gem is activated (added to the
|
23
|
+
# loadpath).
|
24
|
+
#
|
25
|
+
# The normal <tt>require</tt> functionality of returning false if
|
26
|
+
# that file has already been loaded is preserved.
|
27
|
+
|
28
|
+
def require(path) # :doc:
|
29
|
+
libgems_original_require path
|
30
|
+
rescue LoadError => load_error
|
31
|
+
if load_error.message.end_with?(path)
|
32
|
+
if LibGems.try_activate(path)
|
33
|
+
return libgems_original_require(path)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
raise load_error
|
38
|
+
end
|
39
|
+
|
40
|
+
private :require
|
41
|
+
private :libgems_original_require
|
42
|
+
|
43
|
+
end unless Kernel.private_method_defined?(:libgems_original_require)
|
44
|
+
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module LibGems
|
2
|
+
|
3
|
+
@post_install_hooks ||= []
|
4
|
+
@post_uninstall_hooks ||= []
|
5
|
+
@pre_uninstall_hooks ||= []
|
6
|
+
@pre_install_hooks ||= []
|
7
|
+
|
8
|
+
##
|
9
|
+
# An Array of the default sources that come with SlimGems
|
10
|
+
|
11
|
+
def self.default_sources
|
12
|
+
%w[http://rubygems.org/]
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Default home directory path to be used if an alternate value is not
|
17
|
+
# specified in the environment
|
18
|
+
|
19
|
+
def self.default_dir
|
20
|
+
if defined? RUBY_FRAMEWORK_VERSION then
|
21
|
+
File.join File.dirname(ConfigMap[:sitedir]), 'Gems',
|
22
|
+
ConfigMap[:ruby_version]
|
23
|
+
elsif ConfigMap[:rubylibprefix] then
|
24
|
+
File.join(ConfigMap[:rubylibprefix], 'gems',
|
25
|
+
ConfigMap[:ruby_version])
|
26
|
+
else
|
27
|
+
File.join(ConfigMap[:libdir], ruby_engine, 'gems',
|
28
|
+
ConfigMap[:ruby_version])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Path for gems in the user's home directory
|
34
|
+
|
35
|
+
def self.user_dir
|
36
|
+
File.join LibGems.user_home, '.gem', ruby_engine, ConfigMap[:ruby_version]
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Default gem load path
|
41
|
+
|
42
|
+
def self.default_path
|
43
|
+
if File.exist? LibGems.user_home then
|
44
|
+
[user_dir, default_dir]
|
45
|
+
else
|
46
|
+
[default_dir]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Deduce Ruby's --program-prefix and --program-suffix from its install name
|
52
|
+
|
53
|
+
def self.default_exec_format
|
54
|
+
exec_format = ConfigMap[:ruby_install_name].sub('ruby', '%s') rescue '%s'
|
55
|
+
|
56
|
+
unless exec_format =~ /%s/ then
|
57
|
+
raise LibGems::Exception,
|
58
|
+
"[BUG] invalid exec_format #{exec_format.inspect}, no %s"
|
59
|
+
end
|
60
|
+
|
61
|
+
exec_format
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# The default directory for binaries
|
66
|
+
|
67
|
+
def self.default_bindir
|
68
|
+
if defined? RUBY_FRAMEWORK_VERSION then # mac framework support
|
69
|
+
'/usr/bin'
|
70
|
+
else # generic install
|
71
|
+
ConfigMap[:bindir]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# The default system-wide source info cache directory
|
77
|
+
|
78
|
+
def self.default_system_source_cache_dir
|
79
|
+
File.join LibGems.dir, 'source_cache'
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# The default user-specific source info cache directory
|
84
|
+
|
85
|
+
def self.default_user_source_cache_dir
|
86
|
+
File.join LibGems.user_home, '.gem', 'source_cache'
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# A wrapper around RUBY_ENGINE const that may not be defined
|
91
|
+
|
92
|
+
def self.ruby_engine
|
93
|
+
if defined? RUBY_ENGINE then
|
94
|
+
RUBY_ENGINE
|
95
|
+
else
|
96
|
+
'ruby'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
@@ -0,0 +1,227 @@
|
|
1
|
+
require "libgems/requirement"
|
2
|
+
|
3
|
+
##
|
4
|
+
# The Dependency class holds a LibGems name and a LibGems::Requirement.
|
5
|
+
|
6
|
+
class LibGems::Dependency
|
7
|
+
|
8
|
+
# :stopdoc:
|
9
|
+
@warned_version_requirement = false
|
10
|
+
|
11
|
+
def self.warned_version_requirement
|
12
|
+
@warned_version_requirement
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.warned_version_requirement= value
|
16
|
+
@warned_version_requirement = value
|
17
|
+
end
|
18
|
+
# :startdoc:
|
19
|
+
|
20
|
+
##
|
21
|
+
# Valid dependency types.
|
22
|
+
#--
|
23
|
+
# When this list is updated, be sure to change
|
24
|
+
# LibGems::Specification::CURRENT_SPECIFICATION_VERSION as well.
|
25
|
+
|
26
|
+
TYPES = [
|
27
|
+
:development,
|
28
|
+
:runtime,
|
29
|
+
]
|
30
|
+
|
31
|
+
##
|
32
|
+
# Dependency name or regular expression.
|
33
|
+
|
34
|
+
attr_accessor :name
|
35
|
+
|
36
|
+
##
|
37
|
+
# Allows you to force this dependency to be a prerelease.
|
38
|
+
|
39
|
+
attr_writer :prerelease
|
40
|
+
|
41
|
+
##
|
42
|
+
# Dependency type.
|
43
|
+
|
44
|
+
attr_reader :type
|
45
|
+
|
46
|
+
##
|
47
|
+
# Constructs a dependency with +name+ and +requirements+. The last
|
48
|
+
# argument can optionally be the dependency type, which defaults to
|
49
|
+
# <tt>:runtime</tt>.
|
50
|
+
|
51
|
+
def initialize name, *requirements
|
52
|
+
type = Symbol === requirements.last ? requirements.pop : :runtime
|
53
|
+
requirements = requirements.first if 1 == requirements.length # unpack
|
54
|
+
|
55
|
+
unless TYPES.include? type
|
56
|
+
raise ArgumentError, "Valid types are #{TYPES.inspect}, "
|
57
|
+
+ "not #{type.inspect}"
|
58
|
+
end
|
59
|
+
|
60
|
+
@name = name
|
61
|
+
@requirement = LibGems::Requirement.create requirements
|
62
|
+
@type = type
|
63
|
+
@prerelease = false
|
64
|
+
|
65
|
+
# This is for Marshal backwards compatability. See the comments in
|
66
|
+
# +requirement+ for the dirty details.
|
67
|
+
|
68
|
+
@version_requirements = @requirement
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# A dependency's hash is the XOR of the hashes of +name+, +type+,
|
73
|
+
# and +requirement+.
|
74
|
+
|
75
|
+
def hash # :nodoc:
|
76
|
+
name.hash ^ type.hash ^ requirement.hash
|
77
|
+
end
|
78
|
+
|
79
|
+
def inspect # :nodoc:
|
80
|
+
"<%s type=%p name=%p requirements=%p>" %
|
81
|
+
[self.class, @type, @name, requirement.to_s]
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Does this dependency require a prerelease?
|
86
|
+
|
87
|
+
def prerelease?
|
88
|
+
@prerelease || requirement.prerelease?
|
89
|
+
end
|
90
|
+
|
91
|
+
def pretty_print(q) # :nodoc:
|
92
|
+
q.group 1, 'LibGems::Dependency.new(', ')' do
|
93
|
+
q.pp name
|
94
|
+
q.text ','
|
95
|
+
q.breakable
|
96
|
+
|
97
|
+
q.pp requirement
|
98
|
+
|
99
|
+
q.text ','
|
100
|
+
q.breakable
|
101
|
+
|
102
|
+
q.pp type
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# What does this dependency require?
|
108
|
+
|
109
|
+
def requirement
|
110
|
+
return @requirement if defined?(@requirement) and @requirement
|
111
|
+
|
112
|
+
# @version_requirements and @version_requirement are legacy ivar
|
113
|
+
# names, and supported here because older gems need to keep
|
114
|
+
# working and Dependency doesn't implement marshal_dump and
|
115
|
+
# marshal_load. In a happier world, this would be an
|
116
|
+
# attr_accessor. The horrifying instance_variable_get you see
|
117
|
+
# below is also the legacy of some old restructurings.
|
118
|
+
#
|
119
|
+
# Note also that because of backwards compatibility (loading new
|
120
|
+
# gems in an old SlimGems installation), we can't add explicit
|
121
|
+
# marshaling to this class until we want to make a big
|
122
|
+
# break. Maybe 2.0.
|
123
|
+
#
|
124
|
+
# Children, define explicit marshal and unmarshal behavior for
|
125
|
+
# public classes. Marshal formats are part of your public API.
|
126
|
+
|
127
|
+
if defined?(@version_requirement) && @version_requirement
|
128
|
+
version = @version_requirement.instance_variable_get :@version
|
129
|
+
@version_requirement = nil
|
130
|
+
@version_requirements = LibGems::Requirement.new version
|
131
|
+
end
|
132
|
+
|
133
|
+
@requirement = @version_requirements if defined?(@version_requirements)
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Rails subclasses LibGems::Dependency and uses this method, so we'll hack
|
138
|
+
# around it.
|
139
|
+
|
140
|
+
alias __requirement requirement # :nodoc:
|
141
|
+
|
142
|
+
def requirements_list
|
143
|
+
requirement.as_list
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_s # :nodoc:
|
147
|
+
"#{name} (#{requirement}, #{type})"
|
148
|
+
end
|
149
|
+
|
150
|
+
def version_requirements # :nodoc:
|
151
|
+
unless LibGems::Dependency.warned_version_requirement then
|
152
|
+
warn "#{LibGems.location_of_caller.join ':'}:Warning: " \
|
153
|
+
"LibGems::Dependency#version_requirements is deprecated " \
|
154
|
+
"and will be removed on or after August 2010. " \
|
155
|
+
"Use #requirement"
|
156
|
+
|
157
|
+
LibGems::Dependency.warned_version_requirement = true
|
158
|
+
end
|
159
|
+
|
160
|
+
__requirement
|
161
|
+
end
|
162
|
+
|
163
|
+
alias version_requirement version_requirements # :nodoc:
|
164
|
+
|
165
|
+
def version_requirements= requirements # :nodoc:
|
166
|
+
warn "#{LibGems.location_of_caller.join ':'}:Warning: " \
|
167
|
+
"LibGems::Dependency#version_requirements= is deprecated " \
|
168
|
+
"and will be removed on or after August 2010. " \
|
169
|
+
"Use LibGems::Dependency.new."
|
170
|
+
|
171
|
+
@requirement = LibGems::Requirement.create requirements
|
172
|
+
end
|
173
|
+
|
174
|
+
def == other # :nodoc:
|
175
|
+
LibGems::Dependency === other &&
|
176
|
+
self.name == other.name &&
|
177
|
+
self.type == other.type &&
|
178
|
+
self.requirement == other.requirement
|
179
|
+
end
|
180
|
+
|
181
|
+
##
|
182
|
+
# Dependencies are ordered by name.
|
183
|
+
|
184
|
+
def <=> other
|
185
|
+
@name <=> other.name
|
186
|
+
end
|
187
|
+
|
188
|
+
##
|
189
|
+
# Uses this dependency as a pattern to compare to +other+. This
|
190
|
+
# dependency will match if the name matches the other's name, and
|
191
|
+
# other has only an equal version requirement that satisfies this
|
192
|
+
# dependency.
|
193
|
+
|
194
|
+
def =~ other
|
195
|
+
unless LibGems::Dependency === other
|
196
|
+
return unless other.respond_to?(:name) && other.respond_to?(:version)
|
197
|
+
other = LibGems::Dependency.new other.name, other.version
|
198
|
+
end
|
199
|
+
|
200
|
+
return false unless name === other.name
|
201
|
+
|
202
|
+
reqs = other.requirement.requirements
|
203
|
+
|
204
|
+
return false unless reqs.length == 1
|
205
|
+
return false unless reqs.first.first == '='
|
206
|
+
|
207
|
+
version = reqs.first.last
|
208
|
+
|
209
|
+
requirement.satisfied_by? version
|
210
|
+
end
|
211
|
+
|
212
|
+
def match?(spec_name, spec_version)
|
213
|
+
return false unless name === spec_name
|
214
|
+
return true if requirement.none?
|
215
|
+
|
216
|
+
requirement.satisfied_by? LibGems::Version.new(spec_version)
|
217
|
+
end
|
218
|
+
|
219
|
+
def matches_spec?(spec)
|
220
|
+
return false unless name === spec.name # name can be a Regexp, so use ===
|
221
|
+
return true if requirement.none?
|
222
|
+
|
223
|
+
requirement.satisfied_by?(spec.version)
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
@@ -0,0 +1,286 @@
|
|
1
|
+
require 'libgems'
|
2
|
+
require 'libgems/dependency_list'
|
3
|
+
require 'libgems/installer'
|
4
|
+
require 'libgems/spec_fetcher'
|
5
|
+
require 'libgems/user_interaction'
|
6
|
+
|
7
|
+
##
|
8
|
+
# Installs a gem along with all its dependencies from local and remote gems.
|
9
|
+
|
10
|
+
class LibGems::DependencyInstaller
|
11
|
+
|
12
|
+
include LibGems::UserInteraction
|
13
|
+
|
14
|
+
attr_reader :gems_to_install
|
15
|
+
attr_reader :installed_gems
|
16
|
+
|
17
|
+
DEFAULT_OPTIONS = {
|
18
|
+
:env_shebang => false,
|
19
|
+
:domain => :both, # HACK dup
|
20
|
+
:force => false,
|
21
|
+
:format_executable => false, # HACK dup
|
22
|
+
:ignore_dependencies => false,
|
23
|
+
:prerelease => false,
|
24
|
+
:security_policy => nil, # HACK NoSecurity requires OpenSSL. AlmostNo? Low?
|
25
|
+
:wrappers => true,
|
26
|
+
}
|
27
|
+
|
28
|
+
##
|
29
|
+
# Creates a new installer instance.
|
30
|
+
#
|
31
|
+
# Options are:
|
32
|
+
# :cache_dir:: Alternate repository path to store .gem files in.
|
33
|
+
# :domain:: :local, :remote, or :both. :local only searches gems in the
|
34
|
+
# current directory. :remote searches only gems in LibGems::sources.
|
35
|
+
# :both searches both.
|
36
|
+
# :env_shebang:: See LibGems::Installer::new.
|
37
|
+
# :force:: See LibGems::Installer#install.
|
38
|
+
# :format_executable:: See LibGems::Installer#initialize.
|
39
|
+
# :ignore_dependencies:: Don't install any dependencies.
|
40
|
+
# :install_dir:: See LibGems::Installer#install.
|
41
|
+
# :prerelease:: Allow prerelease versions. See #install.
|
42
|
+
# :security_policy:: See LibGems::Installer::new and LibGems::Security.
|
43
|
+
# :user_install:: See LibGems::Installer.new
|
44
|
+
# :wrappers:: See LibGems::Installer::new
|
45
|
+
|
46
|
+
def initialize(options = {})
|
47
|
+
if options[:install_dir] then
|
48
|
+
spec_dir = options[:install_dir], 'specifications'
|
49
|
+
@source_index = LibGems::SourceIndex.from_gems_in spec_dir
|
50
|
+
else
|
51
|
+
@source_index = LibGems.source_index
|
52
|
+
end
|
53
|
+
|
54
|
+
options = DEFAULT_OPTIONS.merge options
|
55
|
+
|
56
|
+
@bin_dir = options[:bin_dir]
|
57
|
+
@development = options[:development]
|
58
|
+
@domain = options[:domain]
|
59
|
+
@env_shebang = options[:env_shebang]
|
60
|
+
@force = options[:force]
|
61
|
+
@format_executable = options[:format_executable]
|
62
|
+
@ignore_dependencies = options[:ignore_dependencies]
|
63
|
+
@prerelease = options[:prerelease]
|
64
|
+
@security_policy = options[:security_policy]
|
65
|
+
@user_install = options[:user_install]
|
66
|
+
@wrappers = options[:wrappers]
|
67
|
+
|
68
|
+
@installed_gems = []
|
69
|
+
|
70
|
+
@install_dir = options[:install_dir] || LibGems.dir
|
71
|
+
@cache_dir = options[:cache_dir] || @install_dir
|
72
|
+
|
73
|
+
# Set with any errors that SpecFetcher finds while search through
|
74
|
+
# gemspecs for a dep
|
75
|
+
@errors = nil
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Returns a list of pairs of gemspecs and source_uris that match
|
80
|
+
# LibGems::Dependency +dep+ from both local (Dir.pwd) and remote (LibGems.sources)
|
81
|
+
# sources. Gems are sorted with newer gems prefered over older gems, and
|
82
|
+
# local gems preferred over remote gems.
|
83
|
+
|
84
|
+
def find_gems_with_sources(dep)
|
85
|
+
# Reset the errors
|
86
|
+
@errors = nil
|
87
|
+
gems_and_sources = []
|
88
|
+
|
89
|
+
if @domain == :both or @domain == :local then
|
90
|
+
Dir[File.join(Dir.pwd, "#{dep.name}-[0-9]*.gem")].each do |gem_file|
|
91
|
+
spec = LibGems::Format.from_file_by_path(gem_file).spec
|
92
|
+
gems_and_sources << [spec, gem_file] if spec.name == dep.name
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
if @domain == :both or @domain == :remote then
|
97
|
+
begin
|
98
|
+
requirements = dep.requirement.requirements.map do |req, ver|
|
99
|
+
req
|
100
|
+
end
|
101
|
+
|
102
|
+
all = !dep.prerelease? &&
|
103
|
+
# we only need latest if there's one requirement and it is
|
104
|
+
# guaranteed to match the newest specs
|
105
|
+
(requirements.length > 1 or
|
106
|
+
(requirements.first != ">=" and requirements.first != ">"))
|
107
|
+
|
108
|
+
found, @errors = LibGems::SpecFetcher.fetcher.fetch_with_errors dep, all, true, dep.prerelease?
|
109
|
+
|
110
|
+
gems_and_sources.push(*found)
|
111
|
+
|
112
|
+
rescue LibGems::RemoteFetcher::FetchError => e
|
113
|
+
if LibGems.configuration.really_verbose then
|
114
|
+
say "Error fetching remote data:\t\t#{e.message}"
|
115
|
+
say "Falling back to local-only install"
|
116
|
+
end
|
117
|
+
@domain = :local
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
gems_and_sources.sort_by do |gem, source|
|
122
|
+
[gem, source =~ /^http:\/\// ? 0 : 1] # local gems win
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
##
|
127
|
+
# Gathers all dependencies necessary for the installation from local and
|
128
|
+
# remote sources unless the ignore_dependencies was given.
|
129
|
+
|
130
|
+
def gather_dependencies
|
131
|
+
specs = @specs_and_sources.map { |spec,_| spec }
|
132
|
+
|
133
|
+
dependency_list = LibGems::DependencyList.new @development
|
134
|
+
dependency_list.add(*specs)
|
135
|
+
|
136
|
+
unless @ignore_dependencies then
|
137
|
+
to_do = specs.dup
|
138
|
+
seen = {}
|
139
|
+
|
140
|
+
until to_do.empty? do
|
141
|
+
spec = to_do.shift
|
142
|
+
next if spec.nil? or seen[spec.name]
|
143
|
+
seen[spec.name] = true
|
144
|
+
|
145
|
+
deps = spec.runtime_dependencies
|
146
|
+
deps |= spec.development_dependencies if @development
|
147
|
+
|
148
|
+
deps.each do |dep|
|
149
|
+
results = find_gems_with_sources(dep).reverse
|
150
|
+
|
151
|
+
results.reject! do |dep_spec,|
|
152
|
+
to_do.push dep_spec
|
153
|
+
|
154
|
+
@source_index.any? do |_, installed_spec|
|
155
|
+
dep.name == installed_spec.name and
|
156
|
+
dep.requirement.satisfied_by? installed_spec.version
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
results.each do |dep_spec, source_uri|
|
161
|
+
next if seen[dep_spec.name]
|
162
|
+
@specs_and_sources << [dep_spec, source_uri]
|
163
|
+
dependency_list.add dep_spec
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
@gems_to_install = dependency_list.dependency_order.reverse
|
170
|
+
end
|
171
|
+
|
172
|
+
##
|
173
|
+
# Finds a spec and the source_uri it came from for gem +gem_name+ and
|
174
|
+
# +version+. Returns an Array of specs and sources required for
|
175
|
+
# installation of the gem.
|
176
|
+
|
177
|
+
def find_spec_by_name_and_version(gem_name,
|
178
|
+
version = LibGems::Requirement.default,
|
179
|
+
prerelease = false)
|
180
|
+
spec_and_source = nil
|
181
|
+
|
182
|
+
glob = if File::ALT_SEPARATOR then
|
183
|
+
gem_name.gsub File::ALT_SEPARATOR, File::SEPARATOR
|
184
|
+
else
|
185
|
+
gem_name
|
186
|
+
end
|
187
|
+
|
188
|
+
local_gems = Dir["#{glob}*"].sort.reverse
|
189
|
+
|
190
|
+
unless local_gems.empty? then
|
191
|
+
local_gems.each do |gem_file|
|
192
|
+
next unless gem_file =~ /gem$/
|
193
|
+
begin
|
194
|
+
spec = LibGems::Format.from_file_by_path(gem_file).spec
|
195
|
+
spec_and_source = [spec, gem_file]
|
196
|
+
break
|
197
|
+
rescue SystemCallError, LibGems::Package::FormatError
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
if spec_and_source.nil? then
|
203
|
+
dep = LibGems::Dependency.new gem_name, version
|
204
|
+
dep.prerelease = true if prerelease
|
205
|
+
spec_and_sources = find_gems_with_sources(dep).reverse
|
206
|
+
|
207
|
+
spec_and_source = spec_and_sources.find { |spec, source|
|
208
|
+
LibGems::Platform.match spec.platform
|
209
|
+
}
|
210
|
+
end
|
211
|
+
|
212
|
+
if spec_and_source.nil? then
|
213
|
+
raise LibGems::GemNotFoundException.new(
|
214
|
+
"Could not find a valid gem '#{gem_name}' (#{version}) locally or in a repository",
|
215
|
+
gem_name, version, @errors)
|
216
|
+
end
|
217
|
+
|
218
|
+
@specs_and_sources = [spec_and_source]
|
219
|
+
end
|
220
|
+
|
221
|
+
##
|
222
|
+
# Installs the gem +dep_or_name+ and all its dependencies. Returns an Array
|
223
|
+
# of installed gem specifications.
|
224
|
+
#
|
225
|
+
# If the +:prerelease+ option is set and there is a prerelease for
|
226
|
+
# +dep_or_name+ the prerelease version will be installed.
|
227
|
+
#
|
228
|
+
# Unless explicitly specified as a prerelease dependency, prerelease gems
|
229
|
+
# that +dep_or_name+ depend on will not be installed.
|
230
|
+
#
|
231
|
+
# If c-1.a depends on b-1 and a-1.a and there is a gem b-1.a available then
|
232
|
+
# c-1.a, b-1 and a-1.a will be installed. b-1.a will need to be installed
|
233
|
+
# separately.
|
234
|
+
|
235
|
+
def install dep_or_name, version = LibGems::Requirement.default
|
236
|
+
if String === dep_or_name then
|
237
|
+
find_spec_by_name_and_version dep_or_name, version, @prerelease
|
238
|
+
else
|
239
|
+
dep_or_name.prerelease = @prerelease
|
240
|
+
@specs_and_sources = [find_gems_with_sources(dep_or_name).last]
|
241
|
+
end
|
242
|
+
|
243
|
+
@installed_gems = []
|
244
|
+
|
245
|
+
gather_dependencies
|
246
|
+
|
247
|
+
@gems_to_install.each do |spec|
|
248
|
+
last = spec == @gems_to_install.last
|
249
|
+
# HACK is this test for full_name acceptable?
|
250
|
+
next if @source_index.any? { |n,_| n == spec.full_name } and not last
|
251
|
+
|
252
|
+
# TODO: make this sorta_verbose so other users can benefit from it
|
253
|
+
say "Installing gem #{spec.full_name}" if LibGems.configuration.really_verbose
|
254
|
+
|
255
|
+
_, source_uri = @specs_and_sources.assoc spec
|
256
|
+
begin
|
257
|
+
local_gem_path = LibGems::RemoteFetcher.fetcher.download spec, source_uri,
|
258
|
+
@cache_dir
|
259
|
+
rescue LibGems::RemoteFetcher::FetchError
|
260
|
+
next if @force
|
261
|
+
raise
|
262
|
+
end
|
263
|
+
|
264
|
+
inst = LibGems::Installer.new local_gem_path,
|
265
|
+
:bin_dir => @bin_dir,
|
266
|
+
:development => @development,
|
267
|
+
:env_shebang => @env_shebang,
|
268
|
+
:force => @force,
|
269
|
+
:format_executable => @format_executable,
|
270
|
+
:ignore_dependencies => @ignore_dependencies,
|
271
|
+
:install_dir => @install_dir,
|
272
|
+
:security_policy => @security_policy,
|
273
|
+
:source_index => @source_index,
|
274
|
+
:user_install => @user_install,
|
275
|
+
:wrappers => @wrappers
|
276
|
+
|
277
|
+
spec = inst.install
|
278
|
+
|
279
|
+
@installed_gems << spec
|
280
|
+
end
|
281
|
+
|
282
|
+
@installed_gems
|
283
|
+
end
|
284
|
+
|
285
|
+
end
|
286
|
+
|