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.
Files changed (177) hide show
  1. data/ChangeLog +5811 -0
  2. data/History.txt +887 -0
  3. data/LICENSE.txt +51 -0
  4. data/README.md +87 -0
  5. data/Rakefile +113 -0
  6. data/lib/gauntlet_libgems.rb +50 -0
  7. data/lib/libgems.rb +1246 -0
  8. data/lib/libgems/builder.rb +102 -0
  9. data/lib/libgems/command.rb +534 -0
  10. data/lib/libgems/command_manager.rb +182 -0
  11. data/lib/libgems/commands/build_command.rb +53 -0
  12. data/lib/libgems/commands/cert_command.rb +86 -0
  13. data/lib/libgems/commands/check_command.rb +80 -0
  14. data/lib/libgems/commands/cleanup_command.rb +106 -0
  15. data/lib/libgems/commands/contents_command.rb +98 -0
  16. data/lib/libgems/commands/dependency_command.rb +195 -0
  17. data/lib/libgems/commands/environment_command.rb +133 -0
  18. data/lib/libgems/commands/fetch_command.rb +67 -0
  19. data/lib/libgems/commands/generate_index_command.rb +133 -0
  20. data/lib/libgems/commands/help_command.rb +172 -0
  21. data/lib/libgems/commands/install_command.rb +178 -0
  22. data/lib/libgems/commands/list_command.rb +35 -0
  23. data/lib/libgems/commands/lock_command.rb +110 -0
  24. data/lib/libgems/commands/mirror_command.rb +111 -0
  25. data/lib/libgems/commands/outdated_command.rb +33 -0
  26. data/lib/libgems/commands/owner_command.rb +75 -0
  27. data/lib/libgems/commands/pristine_command.rb +93 -0
  28. data/lib/libgems/commands/push_command.rb +56 -0
  29. data/lib/libgems/commands/query_command.rb +280 -0
  30. data/lib/libgems/commands/rdoc_command.rb +91 -0
  31. data/lib/libgems/commands/search_command.rb +31 -0
  32. data/lib/libgems/commands/server_command.rb +86 -0
  33. data/lib/libgems/commands/sources_command.rb +157 -0
  34. data/lib/libgems/commands/specification_command.rb +125 -0
  35. data/lib/libgems/commands/stale_command.rb +27 -0
  36. data/lib/libgems/commands/uninstall_command.rb +83 -0
  37. data/lib/libgems/commands/unpack_command.rb +121 -0
  38. data/lib/libgems/commands/update_command.rb +160 -0
  39. data/lib/libgems/commands/which_command.rb +86 -0
  40. data/lib/libgems/config_file.rb +345 -0
  41. data/lib/libgems/custom_require.rb +44 -0
  42. data/lib/libgems/defaults.rb +101 -0
  43. data/lib/libgems/dependency.rb +227 -0
  44. data/lib/libgems/dependency_installer.rb +286 -0
  45. data/lib/libgems/dependency_list.rb +208 -0
  46. data/lib/libgems/doc_manager.rb +242 -0
  47. data/lib/libgems/errors.rb +35 -0
  48. data/lib/libgems/exceptions.rb +91 -0
  49. data/lib/libgems/ext.rb +18 -0
  50. data/lib/libgems/ext/builder.rb +56 -0
  51. data/lib/libgems/ext/configure_builder.rb +25 -0
  52. data/lib/libgems/ext/ext_conf_builder.rb +24 -0
  53. data/lib/libgems/ext/rake_builder.rb +39 -0
  54. data/lib/libgems/format.rb +81 -0
  55. data/lib/libgems/gem_openssl.rb +92 -0
  56. data/lib/libgems/gem_path_searcher.rb +100 -0
  57. data/lib/libgems/gem_runner.rb +79 -0
  58. data/lib/libgems/gemcutter_utilities.rb +49 -0
  59. data/lib/libgems/indexer.rb +720 -0
  60. data/lib/libgems/install_update_options.rb +125 -0
  61. data/lib/libgems/installer.rb +604 -0
  62. data/lib/libgems/local_remote_options.rb +135 -0
  63. data/lib/libgems/old_format.rb +153 -0
  64. data/lib/libgems/package.rb +97 -0
  65. data/lib/libgems/package/f_sync_dir.rb +23 -0
  66. data/lib/libgems/package/tar_header.rb +266 -0
  67. data/lib/libgems/package/tar_input.rb +222 -0
  68. data/lib/libgems/package/tar_output.rb +144 -0
  69. data/lib/libgems/package/tar_reader.rb +106 -0
  70. data/lib/libgems/package/tar_reader/entry.rb +141 -0
  71. data/lib/libgems/package/tar_writer.rb +241 -0
  72. data/lib/libgems/package_task.rb +126 -0
  73. data/lib/libgems/platform.rb +183 -0
  74. data/lib/libgems/remote_fetcher.rb +414 -0
  75. data/lib/libgems/require_paths_builder.rb +18 -0
  76. data/lib/libgems/requirement.rb +153 -0
  77. data/lib/libgems/security.rb +814 -0
  78. data/lib/libgems/server.rb +872 -0
  79. data/lib/libgems/source_index.rb +597 -0
  80. data/lib/libgems/source_info_cache.rb +395 -0
  81. data/lib/libgems/source_info_cache_entry.rb +56 -0
  82. data/lib/libgems/spec_fetcher.rb +337 -0
  83. data/lib/libgems/specification.rb +1487 -0
  84. data/lib/libgems/test_utilities.rb +147 -0
  85. data/lib/libgems/text.rb +65 -0
  86. data/lib/libgems/uninstaller.rb +278 -0
  87. data/lib/libgems/user_interaction.rb +527 -0
  88. data/lib/libgems/validator.rb +240 -0
  89. data/lib/libgems/version.rb +316 -0
  90. data/lib/libgems/version_option.rb +65 -0
  91. data/lib/rbconfig/datadir.rb +20 -0
  92. data/test/bogussources.rb +8 -0
  93. data/test/data/gem-private_key.pem +27 -0
  94. data/test/data/gem-public_cert.pem +20 -0
  95. data/test/fake_certlib/openssl.rb +7 -0
  96. data/test/foo/discover.rb +0 -0
  97. data/test/gem_installer_test_case.rb +97 -0
  98. data/test/gem_package_tar_test_case.rb +132 -0
  99. data/test/gemutilities.rb +605 -0
  100. data/test/insure_session.rb +43 -0
  101. data/test/mockgemui.rb +56 -0
  102. data/test/plugin/exception/libgems_plugin.rb +2 -0
  103. data/test/plugin/load/libgems_plugin.rb +1 -0
  104. data/test/plugin/standarderror/libgems_plugin.rb +2 -0
  105. data/test/private_key.pem +27 -0
  106. data/test/public_cert.pem +20 -0
  107. data/test/rubygems_plugin.rb +21 -0
  108. data/test/simple_gem.rb +66 -0
  109. data/test/test_config.rb +12 -0
  110. data/test/test_gem.rb +780 -0
  111. data/test/test_gem_builder.rb +27 -0
  112. data/test/test_gem_command.rb +178 -0
  113. data/test/test_gem_command_manager.rb +207 -0
  114. data/test/test_gem_commands_build_command.rb +74 -0
  115. data/test/test_gem_commands_cert_command.rb +124 -0
  116. data/test/test_gem_commands_check_command.rb +18 -0
  117. data/test/test_gem_commands_contents_command.rb +156 -0
  118. data/test/test_gem_commands_dependency_command.rb +216 -0
  119. data/test/test_gem_commands_environment_command.rb +144 -0
  120. data/test/test_gem_commands_fetch_command.rb +76 -0
  121. data/test/test_gem_commands_generate_index_command.rb +135 -0
  122. data/test/test_gem_commands_install_command.rb +315 -0
  123. data/test/test_gem_commands_list_command.rb +36 -0
  124. data/test/test_gem_commands_lock_command.rb +68 -0
  125. data/test/test_gem_commands_mirror_command.rb +60 -0
  126. data/test/test_gem_commands_outdated_command.rb +40 -0
  127. data/test/test_gem_commands_owner_command.rb +105 -0
  128. data/test/test_gem_commands_pristine_command.rb +108 -0
  129. data/test/test_gem_commands_push_command.rb +81 -0
  130. data/test/test_gem_commands_query_command.rb +426 -0
  131. data/test/test_gem_commands_server_command.rb +59 -0
  132. data/test/test_gem_commands_sources_command.rb +209 -0
  133. data/test/test_gem_commands_specification_command.rb +139 -0
  134. data/test/test_gem_commands_stale_command.rb +38 -0
  135. data/test/test_gem_commands_uninstall_command.rb +83 -0
  136. data/test/test_gem_commands_unpack_command.rb +199 -0
  137. data/test/test_gem_commands_update_command.rb +207 -0
  138. data/test/test_gem_commands_which_command.rb +66 -0
  139. data/test/test_gem_config_file.rb +287 -0
  140. data/test/test_gem_dependency.rb +149 -0
  141. data/test/test_gem_dependency_installer.rb +661 -0
  142. data/test/test_gem_dependency_list.rb +230 -0
  143. data/test/test_gem_doc_manager.rb +31 -0
  144. data/test/test_gem_ext_configure_builder.rb +84 -0
  145. data/test/test_gem_ext_ext_conf_builder.rb +173 -0
  146. data/test/test_gem_ext_rake_builder.rb +81 -0
  147. data/test/test_gem_format.rb +70 -0
  148. data/test/test_gem_gem_path_searcher.rb +78 -0
  149. data/test/test_gem_gem_runner.rb +45 -0
  150. data/test/test_gem_gemcutter_utilities.rb +103 -0
  151. data/test/test_gem_indexer.rb +673 -0
  152. data/test/test_gem_install_update_options.rb +68 -0
  153. data/test/test_gem_installer.rb +857 -0
  154. data/test/test_gem_local_remote_options.rb +97 -0
  155. data/test/test_gem_package_tar_header.rb +130 -0
  156. data/test/test_gem_package_tar_input.rb +112 -0
  157. data/test/test_gem_package_tar_output.rb +97 -0
  158. data/test/test_gem_package_tar_reader.rb +46 -0
  159. data/test/test_gem_package_tar_reader_entry.rb +109 -0
  160. data/test/test_gem_package_tar_writer.rb +144 -0
  161. data/test/test_gem_package_task.rb +59 -0
  162. data/test/test_gem_platform.rb +264 -0
  163. data/test/test_gem_remote_fetcher.rb +740 -0
  164. data/test/test_gem_requirement.rb +292 -0
  165. data/test/test_gem_server.rb +356 -0
  166. data/test/test_gem_silent_ui.rb +113 -0
  167. data/test/test_gem_source_index.rb +461 -0
  168. data/test/test_gem_spec_fetcher.rb +410 -0
  169. data/test/test_gem_specification.rb +1334 -0
  170. data/test/test_gem_stream_ui.rb +218 -0
  171. data/test/test_gem_text.rb +43 -0
  172. data/test/test_gem_uninstaller.rb +146 -0
  173. data/test/test_gem_validator.rb +63 -0
  174. data/test/test_gem_version.rb +181 -0
  175. data/test/test_gem_version_option.rb +89 -0
  176. data/test/test_kernel.rb +59 -0
  177. 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
+