shopify-bundler 1.10.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (196) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +96 -0
  5. data/.rubocop_todo.yml +177 -0
  6. data/.travis.yml +104 -0
  7. data/CHANGELOG.md +2131 -0
  8. data/CODE_OF_CONDUCT.md +42 -0
  9. data/CONTRIBUTING.md +32 -0
  10. data/DEVELOPMENT.md +118 -0
  11. data/ISSUES.md +96 -0
  12. data/LICENSE.md +23 -0
  13. data/README.md +40 -0
  14. data/Rakefile +309 -0
  15. data/bin/rake +14 -0
  16. data/bin/rspec +10 -0
  17. data/bin/rubocop +11 -0
  18. data/bundler.gemspec +34 -0
  19. data/exe/bundle +21 -0
  20. data/exe/bundle_ruby +60 -0
  21. data/exe/bundler +21 -0
  22. data/lib/bundler.rb +499 -0
  23. data/lib/bundler/capistrano.rb +16 -0
  24. data/lib/bundler/cli.rb +435 -0
  25. data/lib/bundler/cli/binstubs.rb +37 -0
  26. data/lib/bundler/cli/cache.rb +34 -0
  27. data/lib/bundler/cli/check.rb +37 -0
  28. data/lib/bundler/cli/clean.rb +25 -0
  29. data/lib/bundler/cli/common.rb +56 -0
  30. data/lib/bundler/cli/config.rb +88 -0
  31. data/lib/bundler/cli/console.rb +37 -0
  32. data/lib/bundler/cli/exec.rb +51 -0
  33. data/lib/bundler/cli/gem.rb +208 -0
  34. data/lib/bundler/cli/init.rb +32 -0
  35. data/lib/bundler/cli/inject.rb +32 -0
  36. data/lib/bundler/cli/install.rb +188 -0
  37. data/lib/bundler/cli/lock.rb +35 -0
  38. data/lib/bundler/cli/open.rb +22 -0
  39. data/lib/bundler/cli/outdated.rb +86 -0
  40. data/lib/bundler/cli/package.rb +45 -0
  41. data/lib/bundler/cli/platform.rb +42 -0
  42. data/lib/bundler/cli/show.rb +74 -0
  43. data/lib/bundler/cli/update.rb +72 -0
  44. data/lib/bundler/cli/viz.rb +26 -0
  45. data/lib/bundler/constants.rb +5 -0
  46. data/lib/bundler/current_ruby.rb +218 -0
  47. data/lib/bundler/definition.rb +675 -0
  48. data/lib/bundler/dep_proxy.rb +45 -0
  49. data/lib/bundler/dependency.rb +119 -0
  50. data/lib/bundler/deployment.rb +62 -0
  51. data/lib/bundler/deprecate.rb +17 -0
  52. data/lib/bundler/dsl.rb +478 -0
  53. data/lib/bundler/endpoint_specification.rb +100 -0
  54. data/lib/bundler/env.rb +82 -0
  55. data/lib/bundler/environment.rb +41 -0
  56. data/lib/bundler/fetcher.rb +288 -0
  57. data/lib/bundler/fetcher/base.rb +26 -0
  58. data/lib/bundler/fetcher/dependency.rb +88 -0
  59. data/lib/bundler/fetcher/downloader.rb +60 -0
  60. data/lib/bundler/fetcher/index.rb +32 -0
  61. data/lib/bundler/friendly_errors.rb +92 -0
  62. data/lib/bundler/gem_helper.rb +191 -0
  63. data/lib/bundler/gem_helpers.rb +26 -0
  64. data/lib/bundler/gem_installer.rb +9 -0
  65. data/lib/bundler/gem_path_manipulation.rb +8 -0
  66. data/lib/bundler/gem_tasks.rb +5 -0
  67. data/lib/bundler/graph.rb +173 -0
  68. data/lib/bundler/index.rb +199 -0
  69. data/lib/bundler/injector.rb +62 -0
  70. data/lib/bundler/inline.rb +58 -0
  71. data/lib/bundler/installer.rb +242 -0
  72. data/lib/bundler/installer/parallel_installer.rb +122 -0
  73. data/lib/bundler/installer/standalone.rb +48 -0
  74. data/lib/bundler/lazy_specification.rb +82 -0
  75. data/lib/bundler/lockfile_parser.rb +199 -0
  76. data/lib/bundler/match_platform.rb +13 -0
  77. data/lib/bundler/psyched_yaml.rb +26 -0
  78. data/lib/bundler/remote_specification.rb +82 -0
  79. data/lib/bundler/resolver.rb +350 -0
  80. data/lib/bundler/retry.rb +60 -0
  81. data/lib/bundler/ruby_dsl.rb +11 -0
  82. data/lib/bundler/ruby_version.rb +116 -0
  83. data/lib/bundler/rubygems_ext.rb +175 -0
  84. data/lib/bundler/rubygems_integration.rb +674 -0
  85. data/lib/bundler/runtime.rb +285 -0
  86. data/lib/bundler/settings.rb +263 -0
  87. data/lib/bundler/setup.rb +26 -0
  88. data/lib/bundler/shared_helpers.rb +176 -0
  89. data/lib/bundler/similarity_detector.rb +61 -0
  90. data/lib/bundler/source.rb +35 -0
  91. data/lib/bundler/source/git.rb +286 -0
  92. data/lib/bundler/source/git/git_proxy.rb +190 -0
  93. data/lib/bundler/source/path.rb +224 -0
  94. data/lib/bundler/source/path/installer.rb +43 -0
  95. data/lib/bundler/source/rubygems.rb +436 -0
  96. data/lib/bundler/source/rubygems/remote.rb +38 -0
  97. data/lib/bundler/source_list.rb +101 -0
  98. data/lib/bundler/spec_set.rb +156 -0
  99. data/lib/bundler/ssl_certs/.document +1 -0
  100. data/lib/bundler/ssl_certs/AddTrustExternalCARoot-2048.pem +25 -0
  101. data/lib/bundler/ssl_certs/AddTrustExternalCARoot.pem +32 -0
  102. data/lib/bundler/ssl_certs/Class3PublicPrimaryCertificationAuthority.pem +14 -0
  103. data/lib/bundler/ssl_certs/DigiCertHighAssuranceEVRootCA.pem +23 -0
  104. data/lib/bundler/ssl_certs/EntrustnetSecureServerCertificationAuthority.pem +28 -0
  105. data/lib/bundler/ssl_certs/GeoTrustGlobalCA.pem +20 -0
  106. data/lib/bundler/ssl_certs/certificate_manager.rb +64 -0
  107. data/lib/bundler/stub_specification.rb +23 -0
  108. data/lib/bundler/templates/Executable +16 -0
  109. data/lib/bundler/templates/Executable.standalone +12 -0
  110. data/lib/bundler/templates/Gemfile +4 -0
  111. data/lib/bundler/templates/newgem/.travis.yml.tt +4 -0
  112. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +22 -0
  113. data/lib/bundler/templates/newgem/Gemfile.tt +4 -0
  114. data/lib/bundler/templates/newgem/LICENSE.txt.tt +21 -0
  115. data/lib/bundler/templates/newgem/README.md.tt +41 -0
  116. data/lib/bundler/templates/newgem/Rakefile.tt +29 -0
  117. data/lib/bundler/templates/newgem/bin/console.tt +14 -0
  118. data/lib/bundler/templates/newgem/bin/setup.tt +8 -0
  119. data/lib/bundler/templates/newgem/exe/newgem.tt +3 -0
  120. data/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt +3 -0
  121. data/lib/bundler/templates/newgem/ext/newgem/newgem.c.tt +9 -0
  122. data/lib/bundler/templates/newgem/ext/newgem/newgem.h.tt +6 -0
  123. data/lib/bundler/templates/newgem/gitignore.tt +16 -0
  124. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +12 -0
  125. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +7 -0
  126. data/lib/bundler/templates/newgem/newgem.gemspec.tt +43 -0
  127. data/lib/bundler/templates/newgem/rspec.tt +2 -0
  128. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +11 -0
  129. data/lib/bundler/templates/newgem/spec/spec_helper.rb.tt +2 -0
  130. data/lib/bundler/templates/newgem/test/newgem_test.rb.tt +11 -0
  131. data/lib/bundler/templates/newgem/test/test_helper.rb.tt +4 -0
  132. data/lib/bundler/ui.rb +7 -0
  133. data/lib/bundler/ui/rg_proxy.rb +17 -0
  134. data/lib/bundler/ui/shell.rb +108 -0
  135. data/lib/bundler/ui/silent.rb +44 -0
  136. data/lib/bundler/vendor/molinillo/lib/molinillo.rb +5 -0
  137. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +277 -0
  138. data/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb +69 -0
  139. data/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb +3 -0
  140. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb +99 -0
  141. data/lib/bundler/vendor/molinillo/lib/molinillo/modules/ui.rb +63 -0
  142. data/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb +434 -0
  143. data/lib/bundler/vendor/molinillo/lib/molinillo/resolver.rb +43 -0
  144. data/lib/bundler/vendor/molinillo/lib/molinillo/state.rb +51 -0
  145. data/lib/bundler/vendor/net/http/faster.rb +26 -0
  146. data/lib/bundler/vendor/net/http/persistent.rb +1230 -0
  147. data/lib/bundler/vendor/net/http/persistent/ssl_reuse.rb +128 -0
  148. data/lib/bundler/vendor/thor/lib/thor.rb +484 -0
  149. data/lib/bundler/vendor/thor/lib/thor/actions.rb +319 -0
  150. data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +103 -0
  151. data/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb +59 -0
  152. data/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +118 -0
  153. data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +135 -0
  154. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +316 -0
  155. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +107 -0
  156. data/lib/bundler/vendor/thor/lib/thor/base.rb +656 -0
  157. data/lib/bundler/vendor/thor/lib/thor/command.rb +133 -0
  158. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +77 -0
  159. data/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb +10 -0
  160. data/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb +98 -0
  161. data/lib/bundler/vendor/thor/lib/thor/error.rb +32 -0
  162. data/lib/bundler/vendor/thor/lib/thor/group.rb +281 -0
  163. data/lib/bundler/vendor/thor/lib/thor/invocation.rb +178 -0
  164. data/lib/bundler/vendor/thor/lib/thor/line_editor.rb +17 -0
  165. data/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb +35 -0
  166. data/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb +88 -0
  167. data/lib/bundler/vendor/thor/lib/thor/parser.rb +4 -0
  168. data/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +73 -0
  169. data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +175 -0
  170. data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +125 -0
  171. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +218 -0
  172. data/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +71 -0
  173. data/lib/bundler/vendor/thor/lib/thor/runner.rb +322 -0
  174. data/lib/bundler/vendor/thor/lib/thor/shell.rb +81 -0
  175. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +421 -0
  176. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +149 -0
  177. data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +126 -0
  178. data/lib/bundler/vendor/thor/lib/thor/util.rb +267 -0
  179. data/lib/bundler/vendor/thor/lib/thor/version.rb +3 -0
  180. data/lib/bundler/vendored_molinillo.rb +2 -0
  181. data/lib/bundler/vendored_persistent.rb +11 -0
  182. data/lib/bundler/vendored_thor.rb +3 -0
  183. data/lib/bundler/version.rb +6 -0
  184. data/lib/bundler/vlad.rb +11 -0
  185. data/lib/bundler/worker.rb +72 -0
  186. data/man/bundle-config.ronn +187 -0
  187. data/man/bundle-exec.ronn +136 -0
  188. data/man/bundle-gem.ronn +77 -0
  189. data/man/bundle-install.ronn +398 -0
  190. data/man/bundle-package.ronn +66 -0
  191. data/man/bundle-platform.ronn +42 -0
  192. data/man/bundle-update.ronn +188 -0
  193. data/man/bundle.ronn +98 -0
  194. data/man/gemfile.5.ronn +495 -0
  195. data/man/index.txt +8 -0
  196. metadata +346 -0
@@ -0,0 +1,58 @@
1
+ # Allows for declaring a Gemfile inline in a ruby script, optionally installing
2
+ # any gems that aren't already installed on the user's system.
3
+ #
4
+ # @note Every gem that is specified in this 'Gemfile' will be `require`d, as if
5
+ # the user had manually called `Bundler.require`. To avoid a requested gem
6
+ # being automatically required, add the `:require => false` option to the
7
+ # `gem` dependency declaration.
8
+ #
9
+ # @param install [Boolean] whether gems that aren't already installed on the
10
+ # user's system should be installed.
11
+ # Defaults to `false`.
12
+ #
13
+ # @param gemfile [Proc] a block that is evaluated as a `Gemfile`.
14
+ #
15
+ # @example Using an inline Gemfile
16
+ #
17
+ # #!/usr/bin/env ruby
18
+ #
19
+ # require 'bundler/inline'
20
+ #
21
+ # gemfile do
22
+ # source 'https://rubygems.org'
23
+ # gem 'json', require: false
24
+ # gem 'nap', require: 'rest'
25
+ # gem 'cocoapods', '~> 0.34.1'
26
+ # end
27
+ #
28
+ # puts Pod::VERSION # => "0.34.4"
29
+ #
30
+ def gemfile(install = false, &gemfile)
31
+ require "bundler"
32
+ old_root = Bundler.method(:root)
33
+ def Bundler.root
34
+ Bundler::SharedHelpers.pwd.expand_path
35
+ end
36
+ ENV["BUNDLE_GEMFILE"] ||= "Gemfile"
37
+
38
+ builder = Bundler::Dsl.new
39
+ builder.instance_eval(&gemfile)
40
+
41
+ definition = builder.to_definition(nil, true)
42
+ def definition.lock(*); end
43
+ definition.validate_ruby!
44
+
45
+ if install
46
+ Bundler.ui = Bundler::UI::Shell.new
47
+ Bundler::Installer.install(Bundler.root, definition, :system => true)
48
+ Bundler::Installer.post_install_messages.each do |name, message|
49
+ Bundler.ui.info "Post-install message from #{name}:\n#{message}"
50
+ end
51
+ end
52
+
53
+ runtime = Bundler::Runtime.new(nil, definition)
54
+ runtime.setup.require
55
+
56
+ bundler_module = class << Bundler; self; end
57
+ bundler_module.send(:define_method, :root, old_root)
58
+ end
@@ -0,0 +1,242 @@
1
+ require "erb"
2
+ require "rubygems/dependency_installer"
3
+ require "bundler/worker"
4
+ require "bundler/installer/parallel_installer"
5
+ require "bundler/installer/standalone"
6
+
7
+ module Bundler
8
+ class Installer < Environment
9
+ class << self
10
+ attr_accessor :post_install_messages, :ambiguous_gems
11
+
12
+ Installer.post_install_messages = {}
13
+ Installer.ambiguous_gems = []
14
+ end
15
+
16
+ # Begins the installation process for Bundler.
17
+ # For more information see the #run method on this class.
18
+ def self.install(root, definition, options = {})
19
+ installer = new(root, definition)
20
+ installer.run(options)
21
+ installer
22
+ end
23
+
24
+ # Runs the install procedures for a specific Gemfile.
25
+ #
26
+ # Firstly, this method will check to see if Bundler.bundle_path exists
27
+ # and if not then will create it. This is usually the location of gems
28
+ # on the system, be it RVM or at a system path.
29
+ #
30
+ # Secondly, it checks if Bundler has been configured to be "frozen"
31
+ # Frozen ensures that the Gemfile and the Gemfile.lock file are matching.
32
+ # This stops a situation where a developer may update the Gemfile but may not run
33
+ # `bundle install`, which leads to the Gemfile.lock file not being correctly updated.
34
+ # If this file is not correctly updated then any other developer running
35
+ # `bundle install` will potentially not install the correct gems.
36
+ #
37
+ # Thirdly, Bundler checks if there are any dependencies specified in the Gemfile using
38
+ # Bundler::Environment#dependencies. If there are no dependencies specified then
39
+ # Bundler returns a warning message stating so and this method returns.
40
+ #
41
+ # Fourthly, Bundler checks if the default lockfile (Gemfile.lock) exists, and if so
42
+ # then proceeds to set up a defintion based on the default gemfile (Gemfile) and the
43
+ # default lock file (Gemfile.lock). However, this is not the case if the platform is different
44
+ # to that which is specified in Gemfile.lock, or if there are any missing specs for the gems.
45
+ #
46
+ # Fifthly, Bundler resolves the dependencies either through a cache of gems or by remote.
47
+ # This then leads into the gems being installed, along with stubs for their executables,
48
+ # but only if the --binstubs option has been passed or Bundler.options[:bin] has been set
49
+ # earlier.
50
+ #
51
+ # Sixthly, a new Gemfile.lock is created from the installed gems to ensure that the next time
52
+ # that a user runs `bundle install` they will receive any updates from this process.
53
+ #
54
+ # Finally: TODO add documentation for how the standalone process works.
55
+ def run(options)
56
+ create_bundle_path
57
+
58
+ if Bundler.settings[:frozen]
59
+ @definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment])
60
+ end
61
+
62
+ if dependencies.empty?
63
+ Bundler.ui.warn "The Gemfile specifies no dependencies"
64
+ lock
65
+ return
66
+ end
67
+
68
+ resolve_if_need(options)
69
+ install(options)
70
+
71
+ lock unless Bundler.settings[:frozen]
72
+ Standalone.new(options[:standalone], @definition).generate if options[:standalone]
73
+ end
74
+
75
+ def install_gem_from_spec(spec, standalone = false, worker = 0, force = false)
76
+ # Fetch the build settings, if there are any
77
+ settings = Bundler.settings["build.#{spec.name}"]
78
+ install_options = { :force => force, :ensure_builtin_gems_cached => standalone }
79
+
80
+ post_install_message = nil
81
+ if settings
82
+ # Build arguments are global, so this is mutexed
83
+ Bundler.rubygems.with_build_args [settings] do
84
+ post_install_message = spec.source.install(spec, install_options)
85
+ end
86
+ else
87
+ post_install_message = spec.source.install(spec, install_options)
88
+ end
89
+
90
+ Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
91
+
92
+ if Bundler.settings[:bin] && standalone
93
+ generate_standalone_bundler_executable_stubs(spec)
94
+ elsif Bundler.settings[:bin]
95
+ generate_bundler_executable_stubs(spec, :force => true)
96
+ end
97
+
98
+ post_install_message
99
+ rescue Errno::ENOSPC
100
+ raise Bundler::InstallError, "Your disk is out of space. Free some " \
101
+ "space to be able to install your bundle."
102
+ rescue Exception => e
103
+ # if install hook failed or gem signature is bad, just die
104
+ raise e if e.is_a?(Bundler::InstallHookError) || e.is_a?(Bundler::SecurityError)
105
+
106
+ # other failure, likely a native extension build failure
107
+ Bundler.ui.info ""
108
+ Bundler.ui.warn "#{e.class}: #{e.message}"
109
+ msg = "An error occurred while installing #{spec.name} (#{spec.version}),"
110
+ msg << " and Bundler cannot continue."
111
+
112
+ unless spec.source.options["git"]
113
+ msg << "\nMake sure that `gem install"
114
+ msg << " #{spec.name} -v '#{spec.version}'` succeeds before bundling."
115
+ end
116
+ Bundler.ui.debug e.backtrace.join("\n")
117
+ raise Bundler::InstallError, msg
118
+ end
119
+
120
+ def generate_bundler_executable_stubs(spec, options = {})
121
+ if options[:binstubs_cmd] && spec.executables.empty?
122
+ options = {}
123
+ spec.runtime_dependencies.each do |dep|
124
+ bins = @definition.specs[dep].first.executables
125
+ options[dep.name] = bins unless bins.empty?
126
+ end
127
+ if options.any?
128
+ Bundler.ui.warn "#{spec.name} has no executables, but you may want " \
129
+ "one from a gem it depends on."
130
+ options.each {|name, bins| Bundler.ui.warn " #{name} has: #{bins.join(", ")}" }
131
+ else
132
+ Bundler.ui.warn "There are no executables for the gem #{spec.name}."
133
+ end
134
+ return
135
+ end
136
+
137
+ # double-assignment to avoid warnings about variables that will be used by ERB
138
+ bin_path = bin_path = Bundler.bin_path
139
+ template = template = File.read(File.expand_path("../templates/Executable", __FILE__))
140
+ relative_gemfile_path = relative_gemfile_path = Bundler.default_gemfile.relative_path_from(bin_path)
141
+ ruby_command = ruby_command = Thor::Util.ruby_command
142
+
143
+ exists = []
144
+ spec.executables.each do |executable|
145
+ next if executable == "bundle"
146
+
147
+ binstub_path = "#{bin_path}/#{executable}"
148
+ if File.exist?(binstub_path) && !options[:force]
149
+ exists << executable
150
+ next
151
+ end
152
+
153
+ File.open(binstub_path, "w", 0777 & ~File.umask) do |f|
154
+ f.puts ERB.new(template, nil, "-").result(binding)
155
+ end
156
+ end
157
+
158
+ if options[:binstubs_cmd] && exists.any?
159
+ case exists.size
160
+ when 1
161
+ Bundler.ui.warn "Skipped #{exists[0]} since it already exists."
162
+ when 2
163
+ Bundler.ui.warn "Skipped #{exists.join(" and ")} since they already exist."
164
+ else
165
+ items = exists[0...-1].empty? ? nil : exists[0...-1].join(", ")
166
+ skipped = [items, exists[-1]].compact.join(" and ")
167
+ Bundler.ui.warn "Skipped #{skipped} since they already exist."
168
+ end
169
+ Bundler.ui.warn "If you want to overwrite skipped stubs, use --force."
170
+ end
171
+ end
172
+
173
+ private
174
+
175
+ # the order that the resolver provides is significant, since
176
+ # dependencies might actually affect the installation of a gem.
177
+ # that said, it's a rare situation (other than rake), and parallel
178
+ # installation is just SO MUCH FASTER. so we let people opt in.
179
+ def install(options)
180
+ force = options["force"]
181
+ jobs = 1
182
+ jobs = [Bundler.settings[:jobs].to_i - 1, 1].max if can_install_in_parallel?
183
+ install_in_parallel jobs, options[:standalone], force
184
+ end
185
+
186
+ def can_install_in_parallel?
187
+ if Bundler.rubygems.provides?(">= 2.1.0")
188
+ true
189
+ else
190
+ Bundler.ui.warn "Rubygems #{Gem::VERSION} is not threadsafe, so your "\
191
+ "gems will be installed one at a time. Upgrade to Rubygems 2.1.0 " \
192
+ "or higher to enable parallel gem installation."
193
+ false
194
+ end
195
+ end
196
+
197
+ def generate_standalone_bundler_executable_stubs(spec)
198
+ # double-assignment to avoid warnings about variables that will be used by ERB
199
+ bin_path = Bundler.bin_path
200
+ template = File.read(File.expand_path("../templates/Executable.standalone", __FILE__))
201
+ ruby_command = ruby_command = Thor::Util.ruby_command
202
+
203
+ spec.executables.each do |executable|
204
+ next if executable == "bundle"
205
+ standalone_path = standalone_path = Pathname(Bundler.settings[:path]).expand_path.relative_path_from(bin_path)
206
+ executable_path = executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
207
+ File.open "#{bin_path}/#{executable}", "w", 0755 do |f|
208
+ f.puts ERB.new(template, nil, "-").result(binding)
209
+ end
210
+ end
211
+ end
212
+
213
+ def install_in_parallel(size, standalone, force = false)
214
+ ParallelInstaller.call(self, specs, size, standalone, force)
215
+ end
216
+
217
+ def create_bundle_path
218
+ SharedHelpers.filesystem_access(Bundler.bundle_path.to_s) do |p|
219
+ Bundler.mkdir_p(p)
220
+ end unless Bundler.bundle_path.exist?
221
+ rescue Errno::EEXIST
222
+ raise PathError, "Could not install to path `#{Bundler.settings[:path]}` " \
223
+ "because of an invalid symlink. Remove the symlink so the directory can be created."
224
+ end
225
+
226
+ def resolve_if_need(options)
227
+ if Bundler.default_lockfile.exist? && !options["update"]
228
+ local = Bundler.ui.silence do
229
+ begin
230
+ tmpdef = Definition.build(Bundler.default_gemfile, Bundler.default_lockfile, nil)
231
+ true unless tmpdef.new_platform? || tmpdef.missing_specs.any?
232
+ rescue BundlerError
233
+ end
234
+ end
235
+ end
236
+
237
+ unless local
238
+ options["local"] ? @definition.resolve_with_cache! : @definition.resolve_remotely!
239
+ end
240
+ end
241
+ end
242
+ end
@@ -0,0 +1,122 @@
1
+ require "bundler/worker"
2
+
3
+ class ParallelInstaller
4
+ class SpecInstallation
5
+ attr_accessor :spec, :name, :post_install_message, :state
6
+ def initialize(spec)
7
+ @spec = spec
8
+ @name = spec.name
9
+ @state = :none
10
+ @post_install_message = ""
11
+ end
12
+
13
+ def installed?
14
+ state == :installed
15
+ end
16
+
17
+ def enqueued?
18
+ state == :enqueued
19
+ end
20
+
21
+ # Only true when spec in neither installed nor already enqueued
22
+ def ready_to_enqueue?
23
+ !installed? && !enqueued?
24
+ end
25
+
26
+ def has_post_install_message?
27
+ !post_install_message.empty?
28
+ end
29
+
30
+ def ignorable_dependency?(dep)
31
+ dep.type == :development || dep.name == @name
32
+ end
33
+
34
+ # Checks installed dependencies against spec's dependencies to make
35
+ # sure needed dependencies have been installed.
36
+ def dependencies_installed?(all_specs)
37
+ installed_specs = all_specs.select(&:installed?).map(&:name)
38
+ dependencies(all_specs.map(&:name)).all? {|d| installed_specs.include? d.name }
39
+ end
40
+
41
+ # Represents only the non-development dependencies, the ones that are
42
+ # itself and are in the total list.
43
+ def dependencies(all_spec_names)
44
+ @dependencies ||= begin
45
+ deps = all_dependencies.reject {|dep| ignorable_dependency? dep }
46
+ missing = deps.reject {|dep| all_spec_names.include? dep.name }
47
+ if missing.size > 0
48
+ raise Bundler::LockfileError, "Your Gemfile.lock is corrupt. The following #{missing.size > 1 ? "gems are" : "gem is"} missing " \
49
+ "from the DEPENDENCIES section: '#{missing.map(&:name).join('\' \'')}'"
50
+ end
51
+ deps
52
+ end
53
+ end
54
+
55
+ # Represents all dependencies
56
+ def all_dependencies
57
+ @spec.dependencies
58
+ end
59
+ end
60
+
61
+ def self.call(*args)
62
+ new(*args).call
63
+ end
64
+
65
+ # Returns max number of threads machine can handle with a min of 1
66
+ def self.max_threads
67
+ [Bundler.settings[:jobs].to_i - 1, 1].max
68
+ end
69
+
70
+ def initialize(installer, all_specs, size, standalone, force)
71
+ @installer = installer
72
+ @size = size
73
+ @standalone = standalone
74
+ @force = force
75
+ @specs = all_specs.map {|s| SpecInstallation.new(s) }
76
+ end
77
+
78
+ def call
79
+ enqueue_specs
80
+ process_specs until @specs.all?(&:installed?)
81
+ ensure
82
+ worker_pool && worker_pool.stop
83
+ end
84
+
85
+ def worker_pool
86
+ @worker_pool ||= Bundler::Worker.new @size, lambda { |spec_install, worker_num|
87
+ message = @installer.install_gem_from_spec spec_install.spec, @standalone, worker_num, @force
88
+ spec_install.post_install_message = message unless message.nil?
89
+ spec_install
90
+ }
91
+ end
92
+
93
+ # Dequeue a spec and save its post-install message and then enqueue the
94
+ # remaining specs.
95
+ # Some specs might've had to wait til this spec was installed to be
96
+ # processed so the call to `enqueue_specs` is important after every
97
+ # dequeue.
98
+ def process_specs
99
+ spec = worker_pool.deq
100
+ spec.state = :installed
101
+ collect_post_install_message spec if spec.has_post_install_message?
102
+ enqueue_specs
103
+ end
104
+
105
+ def collect_post_install_message(spec)
106
+ Bundler::Installer.post_install_messages[spec.name] = spec.post_install_message
107
+ end
108
+
109
+ # Keys in the remains hash represent uninstalled gems specs.
110
+ # We enqueue all gem specs that do not have any dependencies.
111
+ # Later we call this lambda again to install specs that depended on
112
+ # previously installed specifications. We continue until all specs
113
+ # are installed.
114
+ def enqueue_specs
115
+ @specs.select(&:ready_to_enqueue?).each do |spec|
116
+ if spec.dependencies_installed? @specs
117
+ worker_pool.enq spec
118
+ spec.state = :enqueued
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,48 @@
1
+ module Bundler
2
+ class Standalone
3
+ def initialize(groups, definition)
4
+ @specs = groups.empty? ? definition.requested_specs : definition.specs_for(groups.map(&:to_sym))
5
+ end
6
+
7
+ def generate
8
+ SharedHelpers.filesystem_access(bundler_path) do |p|
9
+ FileUtils.mkdir_p(p)
10
+ end
11
+ File.open File.join(bundler_path, "setup.rb"), "w" do |file|
12
+ file.puts "require 'rbconfig'"
13
+ file.puts "# ruby 1.8.7 doesn't define RUBY_ENGINE"
14
+ file.puts "ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'"
15
+ file.puts "ruby_version = RbConfig::CONFIG[\"ruby_version\"]"
16
+ file.puts "path = File.expand_path('..', __FILE__)"
17
+ paths.each do |path|
18
+ file.puts %{$:.unshift "\#{path}/#{path}"}
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def paths
26
+ @specs.map do |spec|
27
+ next if spec.name == "bundler"
28
+ Array(spec.require_paths).map do |path|
29
+ gem_path(path, spec).sub(version_dir, '#{ruby_engine}/#{ruby_version}')
30
+ # This is a static string intentionally. It's interpolated at a later time.
31
+ end
32
+ end.flatten
33
+ end
34
+
35
+ def version_dir
36
+ "#{Bundler.ruby_version.engine}/#{RbConfig::CONFIG["ruby_version"]}"
37
+ end
38
+
39
+ def bundler_path
40
+ File.join(Bundler.settings[:path], "bundler")
41
+ end
42
+
43
+ def gem_path(path, spec)
44
+ full_path = Pathname.new(path).absolute? ? path : File.join(spec.full_gem_path, path)
45
+ Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)).to_s
46
+ end
47
+ end
48
+ end