rkh-bundler 1.2.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +42 -0
  3. data/CHANGELOG.md +1105 -0
  4. data/ISSUES.md +67 -0
  5. data/LICENSE +23 -0
  6. data/README.md +31 -0
  7. data/Rakefile +208 -0
  8. data/UPGRADING.md +103 -0
  9. data/bin/bundle +31 -0
  10. data/bundler.gemspec +31 -0
  11. data/lib/bundler.rb +353 -0
  12. data/lib/bundler/capistrano.rb +11 -0
  13. data/lib/bundler/cli.rb +693 -0
  14. data/lib/bundler/definition.rb +568 -0
  15. data/lib/bundler/dep_proxy.rb +43 -0
  16. data/lib/bundler/dependency.rb +134 -0
  17. data/lib/bundler/deployment.rb +58 -0
  18. data/lib/bundler/dsl.rb +256 -0
  19. data/lib/bundler/endpoint_specification.rb +78 -0
  20. data/lib/bundler/environment.rb +47 -0
  21. data/lib/bundler/fetcher.rb +225 -0
  22. data/lib/bundler/gem_helper.rb +162 -0
  23. data/lib/bundler/gem_helpers.rb +23 -0
  24. data/lib/bundler/gem_installer.rb +9 -0
  25. data/lib/bundler/gem_tasks.rb +2 -0
  26. data/lib/bundler/graph.rb +148 -0
  27. data/lib/bundler/index.rb +187 -0
  28. data/lib/bundler/installer.rb +190 -0
  29. data/lib/bundler/lazy_specification.rb +79 -0
  30. data/lib/bundler/lockfile_parser.rb +127 -0
  31. data/lib/bundler/match_platform.rb +13 -0
  32. data/lib/bundler/psyched_yaml.rb +15 -0
  33. data/lib/bundler/remote_specification.rb +57 -0
  34. data/lib/bundler/resolver.rb +486 -0
  35. data/lib/bundler/ruby_version.rb +94 -0
  36. data/lib/bundler/rubygems_ext.rb +153 -0
  37. data/lib/bundler/rubygems_integration.rb +394 -0
  38. data/lib/bundler/runtime.rb +233 -0
  39. data/lib/bundler/settings.rb +128 -0
  40. data/lib/bundler/setup.rb +23 -0
  41. data/lib/bundler/shared_helpers.rb +71 -0
  42. data/lib/bundler/source.rb +869 -0
  43. data/lib/bundler/spec_set.rb +137 -0
  44. data/lib/bundler/templates/Executable +16 -0
  45. data/lib/bundler/templates/Executable.standalone +12 -0
  46. data/lib/bundler/templates/Gemfile +4 -0
  47. data/lib/bundler/templates/newgem/Gemfile.tt +4 -0
  48. data/lib/bundler/templates/newgem/LICENSE.tt +22 -0
  49. data/lib/bundler/templates/newgem/README.md.tt +29 -0
  50. data/lib/bundler/templates/newgem/Rakefile.tt +2 -0
  51. data/lib/bundler/templates/newgem/bin/newgem.tt +3 -0
  52. data/lib/bundler/templates/newgem/gitignore.tt +17 -0
  53. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +9 -0
  54. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +7 -0
  55. data/lib/bundler/templates/newgem/newgem.gemspec.tt +17 -0
  56. data/lib/bundler/ui.rb +88 -0
  57. data/lib/bundler/vendor/net/http/faster.rb +27 -0
  58. data/lib/bundler/vendor/net/http/persistent.rb +468 -0
  59. data/lib/bundler/vendor/thor.rb +358 -0
  60. data/lib/bundler/vendor/thor/actions.rb +314 -0
  61. data/lib/bundler/vendor/thor/actions/create_file.rb +105 -0
  62. data/lib/bundler/vendor/thor/actions/create_link.rb +57 -0
  63. data/lib/bundler/vendor/thor/actions/directory.rb +93 -0
  64. data/lib/bundler/vendor/thor/actions/empty_directory.rb +134 -0
  65. data/lib/bundler/vendor/thor/actions/file_manipulation.rb +270 -0
  66. data/lib/bundler/vendor/thor/actions/inject_into_file.rb +109 -0
  67. data/lib/bundler/vendor/thor/base.rb +576 -0
  68. data/lib/bundler/vendor/thor/core_ext/file_binary_read.rb +9 -0
  69. data/lib/bundler/vendor/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  70. data/lib/bundler/vendor/thor/core_ext/ordered_hash.rb +100 -0
  71. data/lib/bundler/vendor/thor/error.rb +30 -0
  72. data/lib/bundler/vendor/thor/group.rb +273 -0
  73. data/lib/bundler/vendor/thor/invocation.rb +168 -0
  74. data/lib/bundler/vendor/thor/parser.rb +4 -0
  75. data/lib/bundler/vendor/thor/parser/argument.rb +67 -0
  76. data/lib/bundler/vendor/thor/parser/arguments.rb +161 -0
  77. data/lib/bundler/vendor/thor/parser/option.rb +120 -0
  78. data/lib/bundler/vendor/thor/parser/options.rb +172 -0
  79. data/lib/bundler/vendor/thor/rake_compat.rb +66 -0
  80. data/lib/bundler/vendor/thor/runner.rb +309 -0
  81. data/lib/bundler/vendor/thor/shell.rb +88 -0
  82. data/lib/bundler/vendor/thor/shell/basic.rb +302 -0
  83. data/lib/bundler/vendor/thor/shell/color.rb +108 -0
  84. data/lib/bundler/vendor/thor/shell/html.rb +121 -0
  85. data/lib/bundler/vendor/thor/task.rb +113 -0
  86. data/lib/bundler/vendor/thor/util.rb +229 -0
  87. data/lib/bundler/vendor/thor/version.rb +3 -0
  88. data/lib/bundler/vendored_thor.rb +7 -0
  89. data/lib/bundler/version.rb +6 -0
  90. data/lib/bundler/vlad.rb +11 -0
  91. data/man/bundle-config.ronn +130 -0
  92. data/man/bundle-exec.ronn +111 -0
  93. data/man/bundle-install.ronn +335 -0
  94. data/man/bundle-package.ronn +59 -0
  95. data/man/bundle-update.ronn +176 -0
  96. data/man/bundle.ronn +83 -0
  97. data/man/gemfile.5.ronn +324 -0
  98. data/man/index.txt +6 -0
  99. data/spec/bundler/dsl_spec.rb +48 -0
  100. data/spec/bundler/gem_helper_spec.rb +174 -0
  101. data/spec/bundler/source_spec.rb +25 -0
  102. data/spec/cache/gems_spec.rb +239 -0
  103. data/spec/cache/git_spec.rb +124 -0
  104. data/spec/cache/path_spec.rb +103 -0
  105. data/spec/cache/platform_spec.rb +57 -0
  106. data/spec/install/deploy_spec.rb +211 -0
  107. data/spec/install/gems/c_ext_spec.rb +48 -0
  108. data/spec/install/gems/dependency_api_spec.rb +402 -0
  109. data/spec/install/gems/env_spec.rb +107 -0
  110. data/spec/install/gems/flex_spec.rb +313 -0
  111. data/spec/install/gems/groups_spec.rb +268 -0
  112. data/spec/install/gems/packed_spec.rb +84 -0
  113. data/spec/install/gems/platform_spec.rb +208 -0
  114. data/spec/install/gems/post_install_spec.rb +47 -0
  115. data/spec/install/gems/resolving_spec.rb +72 -0
  116. data/spec/install/gems/simple_case_spec.rb +814 -0
  117. data/spec/install/gems/standalone_spec.rb +260 -0
  118. data/spec/install/gems/sudo_spec.rb +74 -0
  119. data/spec/install/gems/win32_spec.rb +26 -0
  120. data/spec/install/gemspec_spec.rb +170 -0
  121. data/spec/install/git_spec.rb +796 -0
  122. data/spec/install/invalid_spec.rb +35 -0
  123. data/spec/install/path_spec.rb +405 -0
  124. data/spec/install/upgrade_spec.rb +26 -0
  125. data/spec/lock/git_spec.rb +35 -0
  126. data/spec/lock/lockfile_spec.rb +809 -0
  127. data/spec/other/check_spec.rb +265 -0
  128. data/spec/other/clean_spec.rb +492 -0
  129. data/spec/other/config_spec.rb +138 -0
  130. data/spec/other/console_spec.rb +54 -0
  131. data/spec/other/exec_spec.rb +229 -0
  132. data/spec/other/ext_spec.rb +37 -0
  133. data/spec/other/help_spec.rb +39 -0
  134. data/spec/other/init_spec.rb +40 -0
  135. data/spec/other/newgem_spec.rb +87 -0
  136. data/spec/other/open_spec.rb +35 -0
  137. data/spec/other/outdated_spec.rb +93 -0
  138. data/spec/other/platform_spec.rb +881 -0
  139. data/spec/other/show_spec.rb +88 -0
  140. data/spec/quality_spec.rb +62 -0
  141. data/spec/realworld/edgecases_spec.rb +177 -0
  142. data/spec/resolver/basic_spec.rb +20 -0
  143. data/spec/resolver/platform_spec.rb +82 -0
  144. data/spec/runtime/executable_spec.rb +120 -0
  145. data/spec/runtime/load_spec.rb +107 -0
  146. data/spec/runtime/platform_spec.rb +90 -0
  147. data/spec/runtime/require_spec.rb +261 -0
  148. data/spec/runtime/setup_spec.rb +755 -0
  149. data/spec/runtime/with_clean_env_spec.rb +80 -0
  150. data/spec/spec_helper.rb +98 -0
  151. data/spec/support/artifice/endopint_marshal_fail_basic_authentication.rb +13 -0
  152. data/spec/support/artifice/endpoint.rb +54 -0
  153. data/spec/support/artifice/endpoint_500.rb +37 -0
  154. data/spec/support/artifice/endpoint_api_missing.rb +16 -0
  155. data/spec/support/artifice/endpoint_basic_authentication.rb +13 -0
  156. data/spec/support/artifice/endpoint_extra.rb +27 -0
  157. data/spec/support/artifice/endpoint_extra_missing.rb +15 -0
  158. data/spec/support/artifice/endpoint_fallback.rb +18 -0
  159. data/spec/support/artifice/endpoint_marshal_fail.rb +11 -0
  160. data/spec/support/artifice/endpoint_redirect.rb +15 -0
  161. data/spec/support/builders.rb +604 -0
  162. data/spec/support/fakeweb/rack-1.0.0.marshal +2 -0
  163. data/spec/support/fakeweb/windows.rb +23 -0
  164. data/spec/support/helpers.rb +317 -0
  165. data/spec/support/indexes.rb +112 -0
  166. data/spec/support/matchers.rb +77 -0
  167. data/spec/support/path.rb +73 -0
  168. data/spec/support/platforms.rb +86 -0
  169. data/spec/support/ruby_ext.rb +20 -0
  170. data/spec/support/rubygems_ext.rb +37 -0
  171. data/spec/support/rubygems_hax/platform.rb +22 -0
  172. data/spec/support/sudo.rb +21 -0
  173. data/spec/update/gems_spec.rb +134 -0
  174. data/spec/update/git_spec.rb +196 -0
  175. data/spec/update/source_spec.rb +51 -0
  176. metadata +338 -0
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib/', __FILE__)
3
+ $:.unshift lib unless $:.include?(lib)
4
+
5
+ require 'bundler/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "rkh-bundler"
9
+ s.version = Bundler::VERSION
10
+ s.platform = Gem::Platform::RUBY
11
+ s.authors = ["André Arko", "Terence Lee", "Carl Lerche", "Yehuda Katz"]
12
+ s.email = ["andre@arko.net"]
13
+ s.homepage = "http://gembundler.com"
14
+ s.summary = %q{The best way to manage your application's dependencies}
15
+ s.description = %q{Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably}
16
+
17
+ s.required_ruby_version = ">= 1.8.7"
18
+ s.required_rubygems_version = ">= 1.3.6"
19
+ s.rubyforge_project = "bundler"
20
+
21
+ s.add_development_dependency "ronn"
22
+ s.add_development_dependency "rspec", "~> 2.0"
23
+
24
+ # Man files are required because they are ignored by git
25
+ man_files = Dir.glob("lib/bundler/man/**/*")
26
+ git_files = `git ls-files`.split("\n") rescue ''
27
+ s.files = git_files + man_files
28
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
29
+ s.executables = %w(bundle)
30
+ s.require_paths = ["lib"]
31
+ end
@@ -0,0 +1,353 @@
1
+ require 'rbconfig'
2
+ require 'fileutils'
3
+ require 'pathname'
4
+ require 'bundler/psyched_yaml'
5
+ require 'bundler/rubygems_ext'
6
+ require 'bundler/rubygems_integration'
7
+ require 'bundler/version'
8
+
9
+ module Bundler
10
+ ORIGINAL_ENV = ENV.to_hash
11
+
12
+ autoload :Definition, 'bundler/definition'
13
+ autoload :Dependency, 'bundler/dependency'
14
+ autoload :DepProxy, 'bundler/dep_proxy'
15
+ autoload :Dsl, 'bundler/dsl'
16
+ autoload :EndpointSpecification, 'bundler/endpoint_specification'
17
+ autoload :Environment, 'bundler/environment'
18
+ autoload :Fetcher, 'bundler/fetcher'
19
+ autoload :GemHelper, 'bundler/gem_helper'
20
+ autoload :GemHelpers, 'bundler/gem_helpers'
21
+ autoload :GemInstaller, 'bundler/gem_installer'
22
+ autoload :Graph, 'bundler/graph'
23
+ autoload :Index, 'bundler/index'
24
+ autoload :Installer, 'bundler/installer'
25
+ autoload :LazySpecification, 'bundler/lazy_specification'
26
+ autoload :LockfileParser, 'bundler/lockfile_parser'
27
+ autoload :MatchPlatform, 'bundler/match_platform'
28
+ autoload :RemoteSpecification, 'bundler/remote_specification'
29
+ autoload :Resolver, 'bundler/resolver'
30
+ autoload :RubyVersion, 'bundler/ruby_version'
31
+ autoload :Runtime, 'bundler/runtime'
32
+ autoload :Settings, 'bundler/settings'
33
+ autoload :SharedHelpers, 'bundler/shared_helpers'
34
+ autoload :SpecSet, 'bundler/spec_set'
35
+ autoload :Source, 'bundler/source'
36
+ autoload :Specification, 'bundler/shared_helpers'
37
+ autoload :SystemRubyVersion, 'bundler/ruby_version'
38
+ autoload :UI, 'bundler/ui'
39
+
40
+ class BundlerError < StandardError
41
+ def self.status_code(code)
42
+ define_method(:status_code) { code }
43
+ end
44
+ end
45
+
46
+ class GemfileNotFound < BundlerError; status_code(10) ; end
47
+ class GemNotFound < BundlerError; status_code(7) ; end
48
+ class GemfileError < BundlerError; status_code(4) ; end
49
+ class InstallError < BundlerError; status_code(5) ; end
50
+ class InstallHookError < BundlerError; status_code(6) ; end
51
+ class PathError < BundlerError; status_code(13) ; end
52
+ class GitError < BundlerError; status_code(11) ; end
53
+ class DeprecatedError < BundlerError; status_code(12) ; end
54
+ class GemspecError < BundlerError; status_code(14) ; end
55
+ class DslError < BundlerError; status_code(15) ; end
56
+ class ProductionError < BundlerError; status_code(16) ; end
57
+ class InvalidOption < DslError ; end
58
+ class HTTPError < BundlerError; status_code(17) ; end
59
+ class RubyVersionMismatch < BundlerError; status_code(18) ; end
60
+
61
+
62
+ WINDOWS = RbConfig::CONFIG["host_os"] =~ %r!(msdos|mswin|djgpp|mingw)!
63
+ FREEBSD = RbConfig::CONFIG["host_os"] =~ /bsd/
64
+ NULL = WINDOWS ? "NUL" : "/dev/null"
65
+
66
+ # Internal errors, should be rescued
67
+ class VersionConflict < BundlerError
68
+ attr_reader :conflicts
69
+
70
+ def initialize(conflicts, msg = nil)
71
+ super(msg)
72
+ @conflicts = conflicts
73
+ end
74
+
75
+ status_code(6)
76
+ end
77
+
78
+ class InvalidSpecSet < StandardError; end
79
+
80
+ class << self
81
+ attr_writer :ui, :bundle_path
82
+
83
+ def configure
84
+ @configured ||= configure_gem_home_and_path
85
+ end
86
+
87
+ def ui
88
+ @ui ||= UI.new
89
+ end
90
+
91
+ # Returns absolute path of where gems are installed on the filesystem.
92
+ def bundle_path
93
+ @bundle_path ||= Pathname.new(settings.path).expand_path(root)
94
+ end
95
+
96
+ # Returns absolute location of where binstubs are installed to.
97
+ def bin_path
98
+ @bin_path ||= begin
99
+ path = settings[:bin] || "bin"
100
+ path = Pathname.new(path).expand_path(root)
101
+ FileUtils.mkdir_p(path)
102
+ Pathname.new(path).expand_path
103
+ end
104
+ end
105
+
106
+ def setup(*groups)
107
+ # Just return if all groups are already loaded
108
+ return @setup if defined?(@setup)
109
+
110
+ definition.validate_ruby!
111
+
112
+ if groups.empty?
113
+ # Load all groups, but only once
114
+ @setup = load.setup
115
+ else
116
+ @completed_groups ||= []
117
+ # Figure out which groups haven't been loaded yet
118
+ unloaded = groups - @completed_groups
119
+ # Record groups that are now loaded
120
+ @completed_groups = groups
121
+ unloaded.any? ? load.setup(*groups) : load
122
+ end
123
+ end
124
+
125
+ def require(*groups)
126
+ setup(*groups).require(*groups)
127
+ end
128
+
129
+ def load
130
+ @load ||= Runtime.new(root, definition)
131
+ end
132
+
133
+ def environment
134
+ Bundler::Environment.new(root, definition)
135
+ end
136
+
137
+ def definition(unlock = nil)
138
+ @definition = nil if unlock
139
+ @definition ||= begin
140
+ configure
141
+ upgrade_lockfile
142
+ Definition.build(default_gemfile, default_lockfile, unlock)
143
+ end
144
+ end
145
+
146
+ def ruby_scope
147
+ "#{Bundler.rubygems.ruby_engine}/#{Gem::ConfigMap[:ruby_version]}"
148
+ end
149
+
150
+ def user_bundle_path
151
+ Pathname.new(Bundler.rubygems.user_home).join(".bundler")
152
+ end
153
+
154
+ def home
155
+ bundle_path.join("bundler")
156
+ end
157
+
158
+ def install_path
159
+ home.join("gems")
160
+ end
161
+
162
+ def specs_path
163
+ bundle_path.join("specifications")
164
+ end
165
+
166
+ def cache
167
+ bundle_path.join("cache/bundler")
168
+ end
169
+
170
+ def root
171
+ default_gemfile.dirname.expand_path
172
+ end
173
+
174
+ def app_config_path
175
+ ENV['BUNDLE_APP_CONFIG'] ?
176
+ Pathname.new(ENV['BUNDLE_APP_CONFIG']).expand_path(root) :
177
+ root.join('.bundle')
178
+ end
179
+
180
+ def app_cache
181
+ root.join("vendor/cache")
182
+ end
183
+
184
+ def tmp
185
+ user_bundle_path.join("tmp", Process.pid.to_s)
186
+ end
187
+
188
+ def settings
189
+ @settings ||= Settings.new(app_config_path)
190
+ end
191
+
192
+ def with_original_env
193
+ bundled_env = ENV.to_hash
194
+ ENV.replace(ORIGINAL_ENV)
195
+ yield
196
+ ensure
197
+ ENV.replace(bundled_env.to_hash)
198
+ end
199
+
200
+ def with_clean_env
201
+ with_original_env do
202
+ ENV.delete_if { |k,_| k[0,7] == 'BUNDLE_' }
203
+ if ENV.has_key? 'RUBYOPT'
204
+ ENV['RUBYOPT'] = ENV['RUBYOPT'].sub '-rbundler/setup', ''
205
+ ENV['RUBYOPT'] = ENV['RUBYOPT'].sub "-I#{File.expand_path('..', __FILE__)}", ''
206
+ end
207
+ yield
208
+ end
209
+ end
210
+
211
+ def clean_system(*args)
212
+ with_clean_env { Kernel.system(*args) }
213
+ end
214
+
215
+ def clean_exec(*args)
216
+ with_clean_env { Kernel.exec(*args) }
217
+ end
218
+
219
+ def default_gemfile
220
+ SharedHelpers.default_gemfile
221
+ end
222
+
223
+ def default_lockfile
224
+ SharedHelpers.default_lockfile
225
+ end
226
+
227
+ def system_bindir
228
+ # Gem.bindir doesn't always return the location that Rubygems will install
229
+ # system binaries. If you put '-n foo' in your .gemrc, Rubygems will
230
+ # install binstubs there instead. Unfortunately, Rubygems doesn't expose
231
+ # that directory at all, so rather than parse .gemrc ourselves, we allow
232
+ # the directory to be set as well, via `bundle config bindir foo`.
233
+ Bundler.settings[:system_bindir] || Bundler.rubygems.gem_bindir
234
+ end
235
+
236
+ def requires_sudo?
237
+ return @requires_sudo if defined?(@checked_for_sudo)
238
+
239
+ path = bundle_path
240
+ path = path.parent until path.exist?
241
+ sudo_present = which "sudo"
242
+ bin_dir = Pathname.new(Bundler.system_bindir)
243
+ bin_dir = bin_dir.parent until bin_dir.exist?
244
+
245
+ @checked_for_sudo = true
246
+ sudo_gems = !File.writable?(path) || !File.writable?(bin_dir)
247
+ @requires_sudo = settings.allow_sudo? && sudo_gems && sudo_present
248
+ end
249
+
250
+ def mkdir_p(path)
251
+ if requires_sudo?
252
+ sudo "mkdir -p '#{path}'" unless File.exist?(path)
253
+ else
254
+ FileUtils.mkdir_p(path)
255
+ end
256
+ end
257
+
258
+ def which(executable)
259
+ if File.executable?(executable)
260
+ executable
261
+ else
262
+ path = ENV['PATH'].split(File::PATH_SEPARATOR).find do |p|
263
+ File.executable?(File.join(p, executable))
264
+ end
265
+ path && File.expand_path(executable, path)
266
+ end
267
+ end
268
+
269
+ def sudo(str)
270
+ `sudo -p 'Enter your password to install the bundled RubyGems to your system: ' #{str}`
271
+ end
272
+
273
+ def read_file(file)
274
+ File.open(file, "rb") { |f| f.read }
275
+ end
276
+
277
+ def load_gemspec(file)
278
+ @gemspec_cache ||= {}
279
+ key = File.expand_path(file)
280
+ spec = ( @gemspec_cache[key] ||= load_gemspec_uncached(file) )
281
+ # Protect against caching side-effected gemspecs by returning a
282
+ # new instance each time.
283
+ spec.dup if spec
284
+ end
285
+
286
+ def load_gemspec_uncached(file)
287
+ path = Pathname.new(file)
288
+ # Eval the gemspec from its parent directory
289
+ Dir.chdir(path.dirname.to_s) do
290
+ contents = File.read(path.basename.to_s)
291
+ begin
292
+ Gem::Specification.from_yaml(contents)
293
+ # Raises ArgumentError if the file is not valid YAML
294
+ rescue ArgumentError, SyntaxError, Gem::EndOfYAMLException, Gem::Exception
295
+ begin
296
+ eval(contents, TOPLEVEL_BINDING, path.expand_path.to_s)
297
+ rescue LoadError => e
298
+ original_line = e.backtrace.find { |line| line.include?(path.to_s) }
299
+ msg = "There was a LoadError while evaluating #{path.basename}:\n #{e.message}"
300
+ msg << " from\n #{original_line}" if original_line
301
+ msg << "\n"
302
+
303
+ if RUBY_VERSION >= "1.9"
304
+ msg << "\nDoes it try to require a relative path? That doesn't work in Ruby 1.9."
305
+ end
306
+
307
+ raise GemspecError, msg
308
+ end
309
+ end
310
+ end
311
+ end
312
+
313
+ def clear_gemspec_cache
314
+ @gemspec_cache = {}
315
+ end
316
+
317
+ private
318
+
319
+ def configure_gem_home_and_path
320
+ blank_home = ENV['GEM_HOME'].nil? || ENV['GEM_HOME'].empty?
321
+
322
+ if settings[:disable_shared_gems]
323
+ ENV['GEM_PATH'] = ''
324
+ configure_gem_home
325
+ elsif blank_home || Bundler.rubygems.gem_dir != bundle_path.to_s
326
+ possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path]
327
+ paths = possibles.flatten.compact.uniq.reject { |p| p.empty? }
328
+ ENV["GEM_PATH"] = paths.join(File::PATH_SEPARATOR)
329
+ configure_gem_home
330
+ end
331
+
332
+ Bundler.rubygems.refresh
333
+ bundle_path
334
+ end
335
+
336
+ def configure_gem_home
337
+ # TODO: This mkdir_p is only needed for JRuby <= 1.5 and should go away (GH #602)
338
+ FileUtils.mkdir_p bundle_path.to_s rescue nil
339
+
340
+ ENV['GEM_HOME'] = File.expand_path(bundle_path, root)
341
+ Bundler.rubygems.clear_paths
342
+ end
343
+
344
+ def upgrade_lockfile
345
+ lockfile = default_lockfile
346
+ if lockfile.exist? && lockfile.read(3) == "---"
347
+ Bundler.ui.warn "Detected Gemfile.lock generated by 0.9, deleting..."
348
+ lockfile.rmtree
349
+ end
350
+ end
351
+
352
+ end
353
+ end
@@ -0,0 +1,11 @@
1
+ # Capistrano task for Bundler.
2
+ #
3
+ # Just add "require 'bundler/capistrano'" in your Capistrano deploy.rb, and
4
+ # Bundler will be activated after each new deployment.
5
+ require 'bundler/deployment'
6
+
7
+ Capistrano::Configuration.instance(:must_exist).load do
8
+ after "deploy:finalize_update", "bundle:install"
9
+ Bundler::Deployment.define_task(self, :task, :except => { :no_release => true })
10
+ set :rake, lambda { "#{fetch(:bundle_cmd, "bundle")} exec rake" }
11
+ end
@@ -0,0 +1,693 @@
1
+ require 'bundler/vendored_thor'
2
+ require 'rubygems/user_interaction'
3
+ require 'rubygems/config_file'
4
+
5
+ module Bundler
6
+ class CLI < Thor
7
+ include Thor::Actions
8
+
9
+ def initialize(*)
10
+ super
11
+ the_shell = (options["no-color"] ? Thor::Shell::Basic.new : shell)
12
+ Bundler.ui = UI::Shell.new(the_shell)
13
+ Bundler.ui.debug! if options["verbose"]
14
+ Bundler.rubygems.ui = UI::RGProxy.new(Bundler.ui)
15
+ end
16
+
17
+ check_unknown_options!
18
+
19
+ default_task :install
20
+ class_option "no-color", :type => :boolean, :banner => "Disable colorization in output"
21
+ class_option "verbose", :type => :boolean, :banner => "Enable verbose output mode", :aliases => "-V"
22
+
23
+ def help(cli = nil)
24
+ case cli
25
+ when "gemfile" then command = "gemfile.5"
26
+ when nil then command = "bundle"
27
+ else command = "bundle-#{cli}"
28
+ end
29
+
30
+ manpages = %w(
31
+ bundle
32
+ bundle-config
33
+ bundle-exec
34
+ bundle-install
35
+ bundle-package
36
+ bundle-update
37
+ gemfile.5)
38
+
39
+ if manpages.include?(command)
40
+ root = File.expand_path("../man", __FILE__)
41
+
42
+ if have_groff? && root !~ %r{^file:/.+!/META-INF/jruby.home/.+}
43
+ groff = "groff -Wall -mtty-char -mandoc -Tascii"
44
+ pager = ENV['MANPAGER'] || ENV['PAGER'] || 'less -R'
45
+
46
+ Kernel.exec "#{groff} #{root}/#{command} | #{pager}"
47
+ else
48
+ puts File.read("#{root}/#{command}.txt")
49
+ end
50
+ else
51
+ super
52
+ end
53
+ end
54
+
55
+ desc "init", "Generates a Gemfile into the current working directory"
56
+ long_desc <<-D
57
+ Init generates a default Gemfile in the current working directory. When adding a
58
+ Gemfile to a gem with a gemspec, the --gemspec option will automatically add each
59
+ dependency listed in the gemspec file to the newly created Gemfile.
60
+ D
61
+ method_option "gemspec", :type => :string, :banner => "Use the specified .gemspec to create the Gemfile"
62
+ def init
63
+ opts = options.dup
64
+ if File.exist?("Gemfile")
65
+ Bundler.ui.error "Gemfile already exists at #{Dir.pwd}/Gemfile"
66
+ exit 1
67
+ end
68
+
69
+ if opts[:gemspec]
70
+ gemspec = File.expand_path(opts[:gemspec])
71
+ unless File.exist?(gemspec)
72
+ Bundler.ui.error "Gem specification #{gemspec} doesn't exist"
73
+ exit 1
74
+ end
75
+ spec = Gem::Specification.load(gemspec)
76
+ puts "Writing new Gemfile to #{Dir.pwd}/Gemfile"
77
+ File.open('Gemfile', 'wb') do |file|
78
+ file << "# Generated from #{gemspec}\n"
79
+ file << spec.to_gemfile
80
+ end
81
+ else
82
+ puts "Writing new Gemfile to #{Dir.pwd}/Gemfile"
83
+ FileUtils.cp(File.expand_path('../templates/Gemfile', __FILE__), 'Gemfile')
84
+ end
85
+ end
86
+
87
+ desc "check", "Checks if the dependencies listed in Gemfile are satisfied by currently installed gems"
88
+ long_desc <<-D
89
+ Check searches the local machine for each of the gems requested in the Gemfile. If
90
+ all gems are found, Bundler prints a success message and exits with a status of 0.
91
+ If not, the first missing gem is listed and Bundler exits status 1.
92
+ D
93
+ method_option "gemfile", :type => :string, :banner =>
94
+ "Use the specified gemfile instead of Gemfile"
95
+ method_option "path", :type => :string, :banner =>
96
+ "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME). Bundler will remember this value for future installs on this machine"
97
+ def check
98
+ ENV['BUNDLE_GEMFILE'] = File.expand_path(options[:gemfile]) if options[:gemfile]
99
+
100
+ Bundler.settings[:path] = File.expand_path(options[:path]) if options[:path]
101
+ begin
102
+ definition = Bundler.definition
103
+ definition.validate_ruby!
104
+ not_installed = definition.missing_specs
105
+ rescue GemNotFound, VersionConflict
106
+ Bundler.ui.error "Your Gemfile's dependencies could not be satisfied"
107
+ Bundler.ui.warn "Install missing gems with `bundle install`"
108
+ exit 1
109
+ end
110
+
111
+ if not_installed.any?
112
+ Bundler.ui.error "The following gems are missing"
113
+ not_installed.each { |s| Bundler.ui.error " * #{s.name} (#{s.version})" }
114
+ Bundler.ui.warn "Install missing gems with `bundle install`"
115
+ exit 1
116
+ elsif !Bundler.default_lockfile.exist? && Bundler.settings[:frozen]
117
+ Bundler.ui.error "This bundle has been frozen, but there is no Gemfile.lock present"
118
+ exit 1
119
+ else
120
+ Bundler.load.lock
121
+ Bundler.ui.info "The Gemfile's dependencies are satisfied"
122
+ end
123
+ end
124
+
125
+ desc "install", "Install the current environment to the system"
126
+ long_desc <<-D
127
+ Install will install all of the gems in the current bundle, making them available
128
+ for use. In a freshly checked out repository, this command will give you the same
129
+ gem versions as the last person who updated the Gemfile and ran `bundle update`.
130
+
131
+ Passing [DIR] to install (e.g. vendor) will cause the unpacked gems to be installed
132
+ into the [DIR] directory rather than into system gems.
133
+
134
+ If the bundle has already been installed, bundler will tell you so and then exit.
135
+ D
136
+ method_option "without", :type => :array, :banner =>
137
+ "Exclude gems that are part of the specified named group."
138
+ method_option "gemfile", :type => :string, :banner =>
139
+ "Use the specified gemfile instead of Gemfile"
140
+ method_option "no-prune", :type => :boolean, :banner =>
141
+ "Don't remove stale gems from the cache."
142
+ method_option "no-cache", :type => :boolean, :banner =>
143
+ "Don't update the existing gem cache."
144
+ method_option "quiet", :type => :boolean, :banner =>
145
+ "Only output warnings and errors."
146
+ method_option "local", :type => :boolean, :banner =>
147
+ "Do not attempt to fetch gems remotely and use the gem cache instead"
148
+ method_option "binstubs", :type => :string, :lazy_default => "bin", :banner =>
149
+ "Generate bin stubs for bundled gems to ./bin"
150
+ method_option "shebang", :type => :string, :banner =>
151
+ "Specify a different shebang executable name than the default (usually 'ruby')"
152
+ method_option "path", :type => :string, :banner =>
153
+ "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME). Bundler will remember this value for future installs on this machine"
154
+ method_option "system", :type => :boolean, :banner =>
155
+ "Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
156
+ method_option "frozen", :type => :boolean, :banner =>
157
+ "Do not allow the Gemfile.lock to be updated after this install"
158
+ method_option "deployment", :type => :boolean, :banner =>
159
+ "Install using defaults tuned for deployment environments"
160
+ method_option "standalone", :type => :array, :lazy_default => [], :banner =>
161
+ "Make a bundle that can work without the Bundler runtime"
162
+ method_option "full-index", :type => :boolean, :banner =>
163
+ "Use the rubygems modern index instead of the API endpoint"
164
+ method_option "clean", :type => :boolean, :banner =>
165
+ "Run bundle clean automatically after install"
166
+ def install
167
+ opts = options.dup
168
+ if opts[:without]
169
+ opts[:without].map!{|g| g.split(" ") }
170
+ opts[:without].flatten!
171
+ opts[:without].map!{|g| g.to_sym }
172
+ end
173
+
174
+ # Can't use Bundler.settings for this because settings needs gemfile.dirname
175
+ ENV['BUNDLE_GEMFILE'] = File.expand_path(opts[:gemfile]) if opts[:gemfile]
176
+ ENV['RB_USER_INSTALL'] = '1' if Bundler::FREEBSD
177
+
178
+ # Just disable color in deployment mode
179
+ Bundler.ui.shell = Thor::Shell::Basic.new if opts[:deployment]
180
+
181
+ if (opts[:path] || opts[:deployment]) && opts[:system]
182
+ Bundler.ui.error "You have specified both a path to install your gems to, \n" \
183
+ "as well as --system. Please choose."
184
+ exit 1
185
+ end
186
+
187
+ if opts[:deployment] || opts[:frozen]
188
+ unless Bundler.default_lockfile.exist?
189
+ flag = opts[:deployment] ? '--deployment' : '--frozen'
190
+ raise ProductionError, "The #{flag} flag requires a Gemfile.lock. Please make " \
191
+ "sure you have checked your Gemfile.lock into version control " \
192
+ "before deploying."
193
+ end
194
+
195
+ if Bundler.root.join("vendor/cache").exist?
196
+ opts[:local] = true
197
+ end
198
+
199
+ Bundler.settings[:frozen] = '1'
200
+ end
201
+
202
+ # When install is called with --no-deployment, disable deployment mode
203
+ if opts[:deployment] == false
204
+ Bundler.settings.delete(:frozen)
205
+ opts[:system] = true
206
+ end
207
+
208
+ # Can't use Bundler.settings for this because settings needs gemfile.dirname
209
+ Bundler.settings[:path] = nil if opts[:system]
210
+ Bundler.settings[:path] = "vendor/bundle" if opts[:deployment]
211
+ Bundler.settings[:path] = opts[:path] if opts[:path]
212
+ Bundler.settings[:path] ||= "bundle" if opts[:standalone]
213
+ Bundler.settings[:bin] = opts["binstubs"] if opts[:binstubs]
214
+ Bundler.settings[:shebang] = opts["shebang"] if opts[:shebang]
215
+ Bundler.settings[:no_prune] = true if opts["no-prune"]
216
+ Bundler.settings[:disable_shared_gems] = Bundler.settings[:path] ? '1' : nil
217
+ Bundler.settings.without = opts[:without]
218
+ Bundler.ui.be_quiet! if opts[:quiet]
219
+ Bundler.settings[:clean] = opts[:clean] if opts[:clean]
220
+
221
+ Bundler::Fetcher.disable_endpoint = opts["full-index"]
222
+ # rubygems plugins sometimes hook into the gem install process
223
+ Gem.load_env_plugins if Gem.respond_to?(:load_env_plugins)
224
+
225
+ definition = Bundler.definition
226
+ definition.validate_ruby!
227
+ Installer.install(Bundler.root, definition, opts)
228
+ Bundler.load.cache if Bundler.root.join("vendor/cache").exist? && !options["no-cache"]
229
+
230
+ if Bundler.settings[:path]
231
+ absolute_path = File.expand_path(Bundler.settings[:path])
232
+ relative_path = absolute_path.sub(File.expand_path('.'), '.')
233
+ Bundler.ui.confirm "Your bundle is complete! " +
234
+ "It was installed into #{relative_path}"
235
+ else
236
+ Bundler.ui.confirm "Your bundle is complete! " +
237
+ "Use `bundle show [gemname]` to see where a bundled gem is installed."
238
+ end
239
+ Installer.post_install_messages.to_a.each do |name, msg|
240
+ Bundler.ui.confirm "Post-install message from #{name}:\n#{msg}"
241
+ end
242
+
243
+ clean if Bundler.settings[:clean] && Bundler.settings[:path]
244
+ rescue GemNotFound => e
245
+ if opts[:local] && Bundler.app_cache.exist?
246
+ Bundler.ui.warn "Some gems seem to be missing from your vendor/cache directory."
247
+ end
248
+
249
+ if Bundler.definition.no_sources?
250
+ Bundler.ui.warn "Your Gemfile has no remote sources. If you need " \
251
+ "gems that are not already on\nyour machine, add a line like this " \
252
+ "to your Gemfile:\n source 'https://rubygems.org'"
253
+ end
254
+ raise e
255
+ end
256
+
257
+ desc "update", "update the current environment"
258
+ long_desc <<-D
259
+ Update will install the newest versions of the gems listed in the Gemfile. Use
260
+ update when you have changed the Gemfile, or if you want to get the newest
261
+ possible versions of the gems in the bundle.
262
+ D
263
+ method_option "source", :type => :array, :banner => "Update a specific source (and all gems associated with it)"
264
+ method_option "local", :type => :boolean, :banner =>
265
+ "Do not attempt to fetch gems remotely and use the gem cache instead"
266
+ method_option "quiet", :type => :boolean, :banner =>
267
+ "Only output warnings and errors."
268
+ method_option "full-index", :type => :boolean, :banner =>
269
+ "Use the rubygems modern index instead of the API endpoint"
270
+ def update(*gems)
271
+ sources = Array(options[:source])
272
+ Bundler.ui.be_quiet! if options[:quiet]
273
+
274
+ if gems.empty? && sources.empty?
275
+ # We're doing a full update
276
+ Bundler.definition(true)
277
+ else
278
+ Bundler.definition(:gems => gems, :sources => sources)
279
+ end
280
+
281
+ Bundler::Fetcher.disable_endpoint = options["full-index"]
282
+
283
+ opts = {"update" => true, "local" => options[:local]}
284
+ # rubygems plugins sometimes hook into the gem install process
285
+ Gem.load_env_plugins if Gem.respond_to?(:load_env_plugins)
286
+
287
+ Bundler.definition.validate_ruby!
288
+ Installer.install Bundler.root, Bundler.definition, opts
289
+ Bundler.load.cache if Bundler.root.join("vendor/cache").exist?
290
+ clean if Bundler.settings[:clean] && Bundler.settings[:path]
291
+ Bundler.ui.confirm "Your bundle is updated! " +
292
+ "Use `bundle show [gemname]` to see where a bundled gem is installed."
293
+ end
294
+
295
+ desc "show [GEM]", "Shows all gems that are part of the bundle, or the path to a given gem"
296
+ long_desc <<-D
297
+ Show lists the names and versions of all gems that are required by your Gemfile.
298
+ Calling show with [GEM] will list the exact location of that gem on your machine.
299
+ D
300
+ method_option "paths", :type => :boolean,
301
+ :banner => "List the paths of all gems that are required by your Gemfile."
302
+ def show(gem_name = nil)
303
+ Bundler.definition.validate_ruby!
304
+ Bundler.load.lock
305
+
306
+ if gem_name
307
+ Bundler.ui.info locate_gem(gem_name)
308
+ elsif options[:paths]
309
+ Bundler.load.specs.sort_by { |s| s.name }.each do |s|
310
+ Bundler.ui.info locate_gem(s.name)
311
+ end
312
+ else
313
+ Bundler.ui.info "Gems included by the bundle:"
314
+ Bundler.load.specs.sort_by { |s| s.name }.each do |s|
315
+ Bundler.ui.info " * #{s.name} (#{s.version}#{s.git_version})"
316
+ end
317
+ end
318
+ end
319
+ map %w(list) => "show"
320
+
321
+ desc "outdated [GEM]", "list installed gems with newer versions available"
322
+ long_desc <<-D
323
+ Outdated lists the names and versions of gems that have a newer version available
324
+ in the given source. Calling outdated with [GEM [GEM]] will only check for newer
325
+ versions of the given gems. By default, available prerelease gems will be ignored.
326
+ D
327
+ method_option "pre", :type => :boolean, :banner => "Check for newer pre-release gems"
328
+ method_option "source", :type => :array, :banner => "Check against a specific source"
329
+ method_option "local", :type => :boolean, :banner =>
330
+ "Do not attempt to fetch gems remotely and use the gem cache instead"
331
+ def outdated(*gems)
332
+ sources = Array(options[:source])
333
+ Bundler.definition.validate_ruby!
334
+ current_specs = Bundler.load.specs
335
+
336
+ if gems.empty? && sources.empty?
337
+ # We're doing a full update
338
+ definition = Bundler.definition(true)
339
+ else
340
+ definition = Bundler.definition(:gems => gems, :sources => sources)
341
+ end
342
+ options["local"] ? definition.resolve_with_cache! : definition.resolve_remotely!
343
+
344
+ Bundler.ui.info ""
345
+ if options["pre"]
346
+ Bundler.ui.info "Outdated gems included in the bundle (including pre-releases):"
347
+ else
348
+ Bundler.ui.info "Outdated gems included in the bundle:"
349
+ end
350
+
351
+ out_count = 0
352
+ # Loop through the current specs
353
+ current_specs.each do |current_spec|
354
+ next if !gems.empty? && !gems.include?(current_spec.name)
355
+
356
+ active_spec = definition.index[current_spec.name].sort_by { |b| b.version }
357
+
358
+ if !current_spec.version.prerelease? && !options[:pre] && active_spec.size > 1
359
+ active_spec = active_spec.delete_if { |b| b.respond_to?(:version) && b.version.prerelease? }
360
+ end
361
+
362
+ active_spec = active_spec.last
363
+ next if active_spec.nil?
364
+
365
+ gem_outdated = Gem::Version.new(active_spec.version) > Gem::Version.new(current_spec.version)
366
+ git_outdated = current_spec.git_version != active_spec.git_version
367
+ if gem_outdated || git_outdated
368
+ spec_version = "#{active_spec.version}#{active_spec.git_version}"
369
+ current_version = "#{current_spec.version}#{current_spec.git_version}"
370
+ Bundler.ui.info " * #{active_spec.name} (#{spec_version} > #{current_version})"
371
+ out_count += 1
372
+ end
373
+ Bundler.ui.debug "from #{active_spec.loaded_from}"
374
+ end
375
+
376
+ Bundler.ui.info " Your bundle is up to date!" if out_count < 1
377
+ Bundler.ui.info ""
378
+ end
379
+
380
+ desc "cache", "Cache all the gems to vendor/cache", :hide => true
381
+ method_option "no-prune", :type => :boolean, :banner => "Don't remove stale gems from the cache."
382
+ method_option "all", :type => :boolean, :banner => "Include all sources (including path and git)."
383
+ def cache
384
+ Bundler.definition.validate_ruby!
385
+ Bundler.definition.resolve_with_cache!
386
+ setup_cache_all
387
+ Bundler.load.cache
388
+ Bundler.settings[:no_prune] = true if options["no-prune"]
389
+ Bundler.load.lock
390
+ rescue GemNotFound => e
391
+ Bundler.ui.error(e.message)
392
+ Bundler.ui.warn "Run `bundle install` to install missing gems."
393
+ exit 128
394
+ end
395
+
396
+ desc "package", "Locks and then caches all of the gems into vendor/cache"
397
+ method_option "no-prune", :type => :boolean, :banner => "Don't remove stale gems from the cache."
398
+ method_option "all", :type => :boolean, :banner => "Include all sources (including path and git)."
399
+ long_desc <<-D
400
+ The package command will copy the .gem files for every gem in the bundle into the
401
+ directory ./vendor/cache. If you then check that directory into your source
402
+ control repository, others who check out your source will be able to install the
403
+ bundle without having to download any additional gems.
404
+ D
405
+ def package
406
+ setup_cache_all
407
+ install
408
+ # TODO: move cache contents here now that all bundles are locked
409
+ Bundler.load.cache
410
+ end
411
+ map %w(pack) => :package
412
+
413
+ desc "exec", "Run the command in context of the bundle"
414
+ long_desc <<-D
415
+ Exec runs a command, providing it access to the gems in the bundle. While using
416
+ bundle exec you can require and call the bundled gems as if they were installed
417
+ into the systemwide Rubygems repository.
418
+ D
419
+ def exec(*)
420
+ ARGV.shift # remove "exec"
421
+
422
+ Bundler.definition.validate_ruby!
423
+ Bundler.load.setup_environment
424
+
425
+ begin
426
+ # Run
427
+ Kernel.exec(*ARGV)
428
+ rescue Errno::EACCES
429
+ Bundler.ui.error "bundler: not executable: #{ARGV.first}"
430
+ exit 126
431
+ rescue Errno::ENOENT
432
+ Bundler.ui.error "bundler: command not found: #{ARGV.first}"
433
+ Bundler.ui.warn "Install missing gem executables with `bundle install`"
434
+ exit 127
435
+ rescue ArgumentError
436
+ Bundler.ui.error "bundler: exec needs a command to run"
437
+ exit 128
438
+ end
439
+ end
440
+
441
+ desc "config NAME [VALUE]", "retrieve or set a configuration value"
442
+ long_desc <<-D
443
+ Retrieves or sets a configuration value. If only parameter is provided, retrieve the value. If two parameters are provided, replace the
444
+ existing value with the newly provided one.
445
+
446
+ By default, setting a configuration value sets it for all projects
447
+ on the machine.
448
+
449
+ If a global setting is superceded by local configuration, this command
450
+ will show the current value, as well as any superceded values and
451
+ where they were specified.
452
+ D
453
+ def config(*)
454
+ values = ARGV.dup
455
+ values.shift # remove config
456
+
457
+ peek = values.shift
458
+
459
+ if peek && peek =~ /^\-\-/
460
+ name, scope = values.shift, $'
461
+ else
462
+ name, scope = peek, "global"
463
+ end
464
+
465
+ unless name
466
+ Bundler.ui.confirm "Settings are listed in order of priority. The top value will be used.\n"
467
+
468
+ Bundler.settings.all.each do |setting|
469
+ Bundler.ui.confirm "#{setting}"
470
+ with_padding do
471
+ Bundler.settings.pretty_values_for(setting).each do |line|
472
+ Bundler.ui.info line
473
+ end
474
+ end
475
+ Bundler.ui.confirm ""
476
+ end
477
+ return
478
+ end
479
+
480
+ case scope
481
+ when "delete"
482
+ Bundler.settings.set_local(name, nil)
483
+ Bundler.settings.set_global(name, nil)
484
+ when "local", "global"
485
+ if values.empty?
486
+ Bundler.ui.confirm "Settings for `#{name}` in order of priority. The top value will be used"
487
+ with_padding do
488
+ Bundler.settings.pretty_values_for(name).each { |line| Bundler.ui.info line }
489
+ end
490
+ return
491
+ end
492
+
493
+ locations = Bundler.settings.locations(name)
494
+
495
+ if scope == "global"
496
+ if local = locations[:local]
497
+ Bundler.ui.info "Your application has set #{name} to #{local.inspect}. This will override the " \
498
+ "global value you are currently setting"
499
+ end
500
+
501
+ if env = locations[:env]
502
+ Bundler.ui.info "You have a bundler environment variable for #{name} set to #{env.inspect}. " \
503
+ "This will take precedence over the global value you are setting"
504
+ end
505
+
506
+ if global = locations[:global]
507
+ Bundler.ui.info "You are replacing the current global value of #{name}, which is currently #{global.inspect}"
508
+ end
509
+ end
510
+
511
+ if scope == "local" && local = locations[:local]
512
+ Bundler.ui.info "You are replacing the current local value of #{name}, which is currently #{local.inspect}"
513
+ end
514
+
515
+ Bundler.settings.send("set_#{scope}", name, values.join(" "))
516
+ else
517
+ Bundler.ui.error "Invalid scope --#{scope} given. Please use --local or --global."
518
+ exit 1
519
+ end
520
+ end
521
+
522
+ desc "open GEM", "Opens the source directory of the given bundled gem"
523
+ def open(name)
524
+ editor = [ENV['BUNDLER_EDITOR'], ENV['VISUAL'], ENV['EDITOR']].find{|e| !e.nil? && !e.empty? }
525
+ if editor
526
+ gem_path = locate_gem(name)
527
+ Dir.chdir(gem_path) do
528
+ command = "#{editor} #{gem_path}"
529
+ success = system(command)
530
+ Bundler.ui.info "Could not run '#{command}'" unless success
531
+ end
532
+ else
533
+ Bundler.ui.info("To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR")
534
+ end
535
+ end
536
+
537
+ desc "console [GROUP]", "Opens an IRB session with the bundle pre-loaded"
538
+ def console(group = nil)
539
+ group ? Bundler.require(:default, *(group.split.map! {|g| g.to_sym })) : Bundler.require
540
+ ARGV.clear
541
+
542
+ require 'irb'
543
+ IRB.start
544
+ end
545
+
546
+ desc "version", "Prints the bundler's version information"
547
+ def version
548
+ Bundler.ui.info "Bundler version #{Bundler::VERSION}"
549
+ end
550
+ map %w(-v --version) => :version
551
+
552
+ desc 'viz', "Generates a visual dependency graph"
553
+ long_desc <<-D
554
+ Viz generates a PNG file of the current Gemfile as a dependency graph.
555
+ Viz requires the ruby-graphviz gem (and its dependencies).
556
+ The associated gems must also be installed via 'bundle install'.
557
+ D
558
+ method_option :file, :type => :string, :default => 'gem_graph', :aliases => '-f', :banner => "The name to use for the generated file. see format option"
559
+ method_option :version, :type => :boolean, :default => false, :aliases => '-v', :banner => "Set to show each gem version."
560
+ method_option :requirements, :type => :boolean, :default => false, :aliases => '-r', :banner => "Set to show the version of each required dependency."
561
+ method_option :format, :type => :string, :default => "png", :aliases => '-F', :banner => "This is output format option. Supported format is png, jpg, svg, dot ..."
562
+ def viz
563
+ output_file = File.expand_path(options[:file])
564
+ output_format = options[:format]
565
+ graph = Graph.new(Bundler.load, output_file, options[:version], options[:requirements], options[:format])
566
+
567
+ begin
568
+ graph.viz
569
+ rescue LoadError => e
570
+ Bundler.ui.error e.inspect
571
+ Bundler.ui.warn "Make sure you have the graphviz ruby gem. You can install it with:"
572
+ Bundler.ui.warn "`gem install ruby-graphviz`"
573
+ rescue StandardError => e
574
+ if e.message =~ /GraphViz not installed or dot not in PATH/
575
+ Bundler.ui.error e.message
576
+ Bundler.ui.warn "The ruby graphviz gem requires GraphViz to be installed"
577
+ else
578
+ raise
579
+ end
580
+ end
581
+ end
582
+
583
+ desc "gem GEM", "Creates a skeleton for creating a rubygem"
584
+ method_option :bin, :type => :boolean, :default => false, :aliases => '-b', :banner => "Generate a binary for your library."
585
+ def gem(name)
586
+ name = name.chomp("/") # remove trailing slash if present
587
+ target = File.join(Dir.pwd, name)
588
+ constant_name = name.split('_').map{|p| p[0..0].upcase + p[1..-1] }.join
589
+ constant_name = constant_name.split('-').map{|q| q[0..0].upcase + q[1..-1] }.join('::') if constant_name =~ /-/
590
+ constant_array = constant_name.split('::')
591
+ FileUtils.mkdir_p(File.join(target, 'lib', name))
592
+ git_user_name = `git config user.name`.chomp
593
+ git_user_email = `git config user.email`.chomp
594
+ opts = {
595
+ :name => name,
596
+ :constant_name => constant_name,
597
+ :constant_array => constant_array,
598
+ :author => git_user_name.empty? ? "TODO: Write your name" : git_user_name,
599
+ :email => git_user_email.empty? ? "TODO: Write your email address" : git_user_email
600
+ }
601
+ template(File.join("newgem/Gemfile.tt"), File.join(target, "Gemfile"), opts)
602
+ template(File.join("newgem/Rakefile.tt"), File.join(target, "Rakefile"), opts)
603
+ template(File.join("newgem/LICENSE.tt"), File.join(target, "LICENSE"), opts)
604
+ template(File.join("newgem/README.md.tt"), File.join(target, "README.md"), opts)
605
+ template(File.join("newgem/gitignore.tt"), File.join(target, ".gitignore"), opts)
606
+ template(File.join("newgem/newgem.gemspec.tt"), File.join(target, "#{name}.gemspec"), opts)
607
+ template(File.join("newgem/lib/newgem.rb.tt"), File.join(target, "lib/#{name}.rb"), opts)
608
+ template(File.join("newgem/lib/newgem/version.rb.tt"), File.join(target, "lib/#{name}/version.rb"), opts)
609
+ if options[:bin]
610
+ template(File.join("newgem/bin/newgem.tt"), File.join(target, 'bin', name), opts)
611
+ end
612
+ Bundler.ui.info "Initializating git repo in #{target}"
613
+ Dir.chdir(target) { `git init`; `git add .` }
614
+ end
615
+
616
+ def self.source_root
617
+ File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
618
+ end
619
+
620
+ desc "clean", "Cleans up unused gems in your bundler directory"
621
+ method_option "force", :type => :boolean, :default => false, :banner =>
622
+ "forces clean even if --path is set"
623
+ def clean
624
+ if Bundler.settings[:path] || options[:force]
625
+ Bundler.load.clean
626
+ else
627
+ Bundler.ui.error "Can only use bundle clean when --path is set or --force is set"
628
+ exit 1
629
+ end
630
+ end
631
+
632
+ desc "platform", "Displays platform compatibility information"
633
+ method_option "ruby", :type => :boolean, :default => false, :banner =>
634
+ "only display ruby related platform information"
635
+ def platform
636
+ platforms = Bundler.definition.platforms.map {|p| "* #{p}" }
637
+ ruby_version = Bundler.definition.ruby_version
638
+ output = []
639
+
640
+ if options[:ruby]
641
+ if ruby_version
642
+ output << ruby_version
643
+ else
644
+ output << "No ruby version specified"
645
+ end
646
+ else
647
+ output << "Your platform is: #{RUBY_PLATFORM}"
648
+ output << "Your app has gems that work on these platforms:\n#{platforms.join("\n")}"
649
+
650
+ if ruby_version
651
+ output << "Your Gemfile specifies a Ruby version requirement:\n* #{ruby_version}"
652
+
653
+ begin
654
+ Bundler.definition.validate_ruby!
655
+ output << "Your current platform satisfies the Ruby version requirement."
656
+ rescue RubyVersionMismatch => e
657
+ output << e.message
658
+ end
659
+ else
660
+ output << "Your Gemfile does not specify a Ruby version requirement."
661
+ end
662
+ end
663
+
664
+ Bundler.ui.info output.join("\n\n")
665
+ end
666
+
667
+ private
668
+
669
+ def setup_cache_all
670
+ if options.key?("all")
671
+ Bundler.settings[:cache_all] = options[:all] || nil
672
+ elsif Bundler.definition.sources.any? { |s| !s.is_a?(Source::Rubygems) }
673
+ Bundler.ui.warn "Your Gemfile contains path and git dependencies. If you want " \
674
+ "to package them as well, please pass the --all flag. This will be the default " \
675
+ "on Bundler 2.0."
676
+ end
677
+ end
678
+
679
+ def have_groff?
680
+ !(`which groff` rescue '').empty?
681
+ end
682
+
683
+ def locate_gem(name)
684
+ spec = Bundler.load.specs.find{|s| s.name == name }
685
+ raise GemNotFound, "Could not find gem '#{name}' in the current bundle." unless spec
686
+ if spec.name == 'bundler'
687
+ return File.expand_path('../../../', __FILE__)
688
+ end
689
+ spec.full_gem_path
690
+ end
691
+
692
+ end
693
+ end