libgems 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+