bundler-maglev- 1.0.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +32 -0
  3. data/CHANGELOG.md +805 -0
  4. data/ISSUES.md +62 -0
  5. data/LICENSE +23 -0
  6. data/README.md +29 -0
  7. data/Rakefile +212 -0
  8. data/UPGRADING.md +103 -0
  9. data/bin/bundle +22 -0
  10. data/bundler.gemspec +30 -0
  11. data/lib/bundler.rb +286 -0
  12. data/lib/bundler/capistrano.rb +11 -0
  13. data/lib/bundler/cli.rb +520 -0
  14. data/lib/bundler/definition.rb +438 -0
  15. data/lib/bundler/dependency.rb +134 -0
  16. data/lib/bundler/deployment.rb +58 -0
  17. data/lib/bundler/dsl.rb +257 -0
  18. data/lib/bundler/environment.rb +47 -0
  19. data/lib/bundler/gem_helper.rb +151 -0
  20. data/lib/bundler/gem_installer.rb +9 -0
  21. data/lib/bundler/gem_tasks.rb +2 -0
  22. data/lib/bundler/graph.rb +130 -0
  23. data/lib/bundler/index.rb +138 -0
  24. data/lib/bundler/installer.rb +97 -0
  25. data/lib/bundler/lazy_specification.rb +74 -0
  26. data/lib/bundler/lockfile_parser.rb +108 -0
  27. data/lib/bundler/remote_specification.rb +59 -0
  28. data/lib/bundler/resolver.rb +464 -0
  29. data/lib/bundler/rubygems_ext.rb +237 -0
  30. data/lib/bundler/rubygems_integration.rb +349 -0
  31. data/lib/bundler/runtime.rb +152 -0
  32. data/lib/bundler/settings.rb +115 -0
  33. data/lib/bundler/setup.rb +23 -0
  34. data/lib/bundler/shared_helpers.rb +71 -0
  35. data/lib/bundler/source.rb +708 -0
  36. data/lib/bundler/spec_set.rb +135 -0
  37. data/lib/bundler/templates/Executable +16 -0
  38. data/lib/bundler/templates/Gemfile +4 -0
  39. data/lib/bundler/templates/newgem/Gemfile.tt +4 -0
  40. data/lib/bundler/templates/newgem/Rakefile.tt +1 -0
  41. data/lib/bundler/templates/newgem/bin/newgem.tt +3 -0
  42. data/lib/bundler/templates/newgem/gitignore.tt +4 -0
  43. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +9 -0
  44. data/lib/bundler/templates/newgem/lib/newgem/version.rb.tt +7 -0
  45. data/lib/bundler/templates/newgem/newgem.gemspec.tt +24 -0
  46. data/lib/bundler/ui.rb +73 -0
  47. data/lib/bundler/vendor/thor.rb +358 -0
  48. data/lib/bundler/vendor/thor/actions.rb +314 -0
  49. data/lib/bundler/vendor/thor/actions/create_file.rb +105 -0
  50. data/lib/bundler/vendor/thor/actions/create_link.rb +57 -0
  51. data/lib/bundler/vendor/thor/actions/directory.rb +93 -0
  52. data/lib/bundler/vendor/thor/actions/empty_directory.rb +134 -0
  53. data/lib/bundler/vendor/thor/actions/file_manipulation.rb +270 -0
  54. data/lib/bundler/vendor/thor/actions/inject_into_file.rb +109 -0
  55. data/lib/bundler/vendor/thor/base.rb +576 -0
  56. data/lib/bundler/vendor/thor/core_ext/file_binary_read.rb +9 -0
  57. data/lib/bundler/vendor/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  58. data/lib/bundler/vendor/thor/core_ext/ordered_hash.rb +100 -0
  59. data/lib/bundler/vendor/thor/error.rb +30 -0
  60. data/lib/bundler/vendor/thor/group.rb +273 -0
  61. data/lib/bundler/vendor/thor/invocation.rb +168 -0
  62. data/lib/bundler/vendor/thor/parser.rb +4 -0
  63. data/lib/bundler/vendor/thor/parser/argument.rb +67 -0
  64. data/lib/bundler/vendor/thor/parser/arguments.rb +161 -0
  65. data/lib/bundler/vendor/thor/parser/option.rb +120 -0
  66. data/lib/bundler/vendor/thor/parser/options.rb +175 -0
  67. data/lib/bundler/vendor/thor/rake_compat.rb +66 -0
  68. data/lib/bundler/vendor/thor/runner.rb +309 -0
  69. data/lib/bundler/vendor/thor/shell.rb +88 -0
  70. data/lib/bundler/vendor/thor/shell/basic.rb +302 -0
  71. data/lib/bundler/vendor/thor/shell/color.rb +108 -0
  72. data/lib/bundler/vendor/thor/shell/html.rb +121 -0
  73. data/lib/bundler/vendor/thor/task.rb +113 -0
  74. data/lib/bundler/vendor/thor/util.rb +229 -0
  75. data/lib/bundler/vendor/thor/version.rb +3 -0
  76. data/lib/bundler/vendored_thor.rb +7 -0
  77. data/lib/bundler/version.rb +6 -0
  78. data/lib/bundler/vlad.rb +11 -0
  79. data/man/bundle-config.ronn +90 -0
  80. data/man/bundle-exec.ronn +111 -0
  81. data/man/bundle-install.ronn +317 -0
  82. data/man/bundle-package.ronn +59 -0
  83. data/man/bundle-update.ronn +176 -0
  84. data/man/bundle.ronn +80 -0
  85. data/man/gemfile.5.ronn +284 -0
  86. data/man/index.txt +6 -0
  87. data/spec/bundler/gem_helper_spec.rb +143 -0
  88. data/spec/cache/gems_spec.rb +230 -0
  89. data/spec/cache/git_spec.rb +12 -0
  90. data/spec/cache/path_spec.rb +27 -0
  91. data/spec/cache/platform_spec.rb +57 -0
  92. data/spec/install/deploy_spec.rb +197 -0
  93. data/spec/install/deprecated_spec.rb +37 -0
  94. data/spec/install/gems/c_ext_spec.rb +48 -0
  95. data/spec/install/gems/env_spec.rb +107 -0
  96. data/spec/install/gems/flex_spec.rb +313 -0
  97. data/spec/install/gems/groups_spec.rb +259 -0
  98. data/spec/install/gems/packed_spec.rb +84 -0
  99. data/spec/install/gems/platform_spec.rb +192 -0
  100. data/spec/install/gems/resolving_spec.rb +72 -0
  101. data/spec/install/gems/simple_case_spec.rb +770 -0
  102. data/spec/install/gems/sudo_spec.rb +74 -0
  103. data/spec/install/gems/win32_spec.rb +26 -0
  104. data/spec/install/gemspec_spec.rb +125 -0
  105. data/spec/install/git_spec.rb +570 -0
  106. data/spec/install/invalid_spec.rb +35 -0
  107. data/spec/install/path_spec.rb +405 -0
  108. data/spec/install/upgrade_spec.rb +26 -0
  109. data/spec/lock/git_spec.rb +35 -0
  110. data/spec/lock/lockfile_spec.rb +739 -0
  111. data/spec/other/check_spec.rb +221 -0
  112. data/spec/other/config_spec.rb +40 -0
  113. data/spec/other/console_spec.rb +54 -0
  114. data/spec/other/exec_spec.rb +248 -0
  115. data/spec/other/ext_spec.rb +37 -0
  116. data/spec/other/help_spec.rb +39 -0
  117. data/spec/other/init_spec.rb +40 -0
  118. data/spec/other/newgem_spec.rb +46 -0
  119. data/spec/other/open_spec.rb +35 -0
  120. data/spec/other/show_spec.rb +82 -0
  121. data/spec/quality_spec.rb +62 -0
  122. data/spec/resolver/basic_spec.rb +20 -0
  123. data/spec/resolver/platform_spec.rb +82 -0
  124. data/spec/runtime/executable_spec.rb +110 -0
  125. data/spec/runtime/load_spec.rb +107 -0
  126. data/spec/runtime/platform_spec.rb +90 -0
  127. data/spec/runtime/require_spec.rb +231 -0
  128. data/spec/runtime/setup_spec.rb +730 -0
  129. data/spec/runtime/with_clean_env_spec.rb +15 -0
  130. data/spec/spec_helper.rb +92 -0
  131. data/spec/support/builders.rb +597 -0
  132. data/spec/support/helpers.rb +239 -0
  133. data/spec/support/indexes.rb +112 -0
  134. data/spec/support/matchers.rb +77 -0
  135. data/spec/support/path.rb +71 -0
  136. data/spec/support/platforms.rb +53 -0
  137. data/spec/support/ruby_ext.rb +20 -0
  138. data/spec/support/rubygems_ext.rb +37 -0
  139. data/spec/support/rubygems_hax/platform.rb +11 -0
  140. data/spec/support/sudo.rb +21 -0
  141. data/spec/update/gems_spec.rb +122 -0
  142. data/spec/update/git_spec.rb +196 -0
  143. data/spec/update/source_spec.rb +51 -0
  144. metadata +296 -0
data/bundler.gemspec ADDED
@@ -0,0 +1,30 @@
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 = "bundler-maglev-"
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_rubygems_version = ">= 1.3.6"
18
+ s.rubyforge_project = "bundler"
19
+
20
+ s.add_development_dependency "ronn"
21
+ s.add_development_dependency "rspec"
22
+
23
+ # Man files are required because they are ignored by git
24
+ man_files = Dir.glob("lib/bundler/man/**/*")
25
+ git_files = `git ls-files`.split("\n") rescue ''
26
+ s.files = git_files + man_files
27
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
28
+ s.executables = %w(bundle)
29
+ s.require_paths = ["lib"]
30
+ end
data/lib/bundler.rb ADDED
@@ -0,0 +1,286 @@
1
+ require 'rbconfig'
2
+ require 'fileutils'
3
+ require 'pathname'
4
+
5
+ begin
6
+ # Pull in Psych if we can, but not if Syck is already loaded
7
+ require 'psych' unless defined?(Syck)
8
+ rescue LoadError
9
+ end
10
+
11
+ require 'yaml'
12
+ require 'bundler/rubygems_ext'
13
+ require 'bundler/rubygems_integration'
14
+ require 'bundler/version'
15
+
16
+ module Bundler
17
+ ORIGINAL_ENV = ENV.to_hash
18
+
19
+ autoload :Definition, 'bundler/definition'
20
+ autoload :Dependency, 'bundler/dependency'
21
+ autoload :Dsl, 'bundler/dsl'
22
+ autoload :Environment, 'bundler/environment'
23
+ autoload :GemHelper, 'bundler/gem_helper'
24
+ autoload :GemInstaller, 'bundler/gem_installer'
25
+ autoload :Graph, 'bundler/graph'
26
+ autoload :Index, 'bundler/index'
27
+ autoload :Installer, 'bundler/installer'
28
+ autoload :LazySpecification, 'bundler/lazy_specification'
29
+ autoload :LockfileParser, 'bundler/lockfile_parser'
30
+ autoload :RemoteSpecification, 'bundler/remote_specification'
31
+ autoload :Resolver, 'bundler/resolver'
32
+ autoload :Runtime, 'bundler/runtime'
33
+ autoload :Settings, 'bundler/settings'
34
+ autoload :SharedHelpers, 'bundler/shared_helpers'
35
+ autoload :SpecSet, 'bundler/spec_set'
36
+ autoload :Source, 'bundler/source'
37
+ autoload :Specification, 'bundler/shared_helpers'
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 PathError < BundlerError; status_code(13) ; end
51
+ class GitError < BundlerError; status_code(11) ; end
52
+ class DeprecatedError < BundlerError; status_code(12) ; end
53
+ class GemspecError < BundlerError; status_code(14) ; end
54
+ class DslError < BundlerError; status_code(15) ; end
55
+ class ProductionError < BundlerError; status_code(16) ; end
56
+ class InvalidOption < DslError ; end
57
+
58
+
59
+ WINDOWS = RbConfig::CONFIG["host_os"] =~ %r!(msdos|mswin|djgpp|mingw)!
60
+ FREEBSD = RbConfig::CONFIG["host_os"] =~ /bsd/
61
+ NULL = WINDOWS ? "NUL" : "/dev/null"
62
+
63
+ # Internal errors, should be rescued
64
+ class VersionConflict < BundlerError
65
+ attr_reader :conflicts
66
+
67
+ def initialize(conflicts, msg = nil)
68
+ super(msg)
69
+ @conflicts = conflicts
70
+ end
71
+
72
+ status_code(6)
73
+ end
74
+
75
+ class InvalidSpecSet < StandardError; end
76
+
77
+ class << self
78
+ attr_writer :ui, :bundle_path
79
+
80
+ def configure
81
+ @configured ||= begin
82
+ configure_gem_home_and_path
83
+ true
84
+ end
85
+ end
86
+
87
+ def ui
88
+ @ui ||= UI.new
89
+ end
90
+
91
+ def bundle_path
92
+ @bundle_path ||= Pathname.new(settings.path).expand_path(root)
93
+ end
94
+
95
+ def bin_path
96
+ @bin_path ||= begin
97
+ path = settings[:bin] || "bin"
98
+ path = Pathname.new(path).expand_path(root)
99
+ FileUtils.mkdir_p(path)
100
+ Pathname.new(path).expand_path
101
+ end
102
+ end
103
+
104
+ def setup(*groups)
105
+ # Just return if all groups are already loaded
106
+ return @setup if defined?(@setup)
107
+
108
+ if groups.empty?
109
+ # Load all groups, but only once
110
+ @setup = load.setup
111
+ else
112
+ @completed_groups ||= []
113
+ # Figure out which groups haven't been loaded yet
114
+ unloaded = groups - @completed_groups
115
+ # Record groups that are now loaded
116
+ @completed_groups = groups
117
+ unloaded.any? ? load.setup(*groups) : load
118
+ end
119
+ end
120
+
121
+ def require(*groups)
122
+ setup(*groups).require(*groups)
123
+ end
124
+
125
+ def load
126
+ @load ||= Runtime.new(root, definition)
127
+ end
128
+
129
+ def environment
130
+ Bundler::Environment.new(root, definition)
131
+ end
132
+
133
+ def definition(unlock = nil)
134
+ @definition = nil if unlock
135
+ @definition ||= begin
136
+ configure
137
+ upgrade_lockfile
138
+ Definition.build(default_gemfile, default_lockfile, unlock)
139
+ end
140
+ end
141
+
142
+ def ruby_scope
143
+ "#{Bundler.rubygems.ruby_engine}/#{Gem::ConfigMap[:ruby_version]}"
144
+ end
145
+
146
+ def user_bundle_path
147
+ Pathname.new(Bundler.rubygems.user_home).join(".bundler")
148
+ end
149
+
150
+ def home
151
+ bundle_path.join("bundler")
152
+ end
153
+
154
+ def install_path
155
+ home.join("gems")
156
+ end
157
+
158
+ def specs_path
159
+ bundle_path.join("specifications")
160
+ end
161
+
162
+ def cache
163
+ bundle_path.join("cache/bundler")
164
+ end
165
+
166
+ def root
167
+ default_gemfile.dirname.expand_path
168
+ end
169
+
170
+ def app_config_path
171
+ ENV['BUNDLE_APP_CONFIG'] ?
172
+ Pathname.new(ENV['BUNDLE_APP_CONFIG']).expand_path(root) :
173
+ root.join('.bundle')
174
+ end
175
+
176
+ def app_cache
177
+ root.join("vendor/cache")
178
+ end
179
+
180
+ def tmp
181
+ user_bundle_path.join("tmp", Process.pid.to_s)
182
+ end
183
+
184
+ def settings
185
+ @settings ||= Settings.new(app_config_path)
186
+ end
187
+
188
+ def with_clean_env
189
+ bundled_env = ENV.to_hash
190
+ ENV.replace(ORIGINAL_ENV)
191
+ yield
192
+ ensure
193
+ ENV.replace(bundled_env.to_hash)
194
+ end
195
+
196
+ def default_gemfile
197
+ SharedHelpers.default_gemfile
198
+ end
199
+
200
+ def default_lockfile
201
+ SharedHelpers.default_lockfile
202
+ end
203
+
204
+ def requires_sudo?
205
+ return @requires_sudo if defined?(@checked_for_sudo) && @checked_for_sudo
206
+
207
+ path = bundle_path
208
+ path = path.parent until path.exist?
209
+ sudo_present = !(`which sudo` rescue '').empty?
210
+
211
+ @checked_for_sudo = true
212
+ @requires_sudo = settings.allow_sudo? && !File.writable?(path) && sudo_present
213
+ end
214
+
215
+ def mkdir_p(path)
216
+ if requires_sudo?
217
+ sudo "mkdir -p '#{path}'" unless File.exist?(path)
218
+ else
219
+ FileUtils.mkdir_p(path)
220
+ end
221
+ end
222
+
223
+ def sudo(str)
224
+ `sudo -p 'Enter your password to install the bundled RubyGems to your system: ' #{str}`
225
+ end
226
+
227
+ def read_file(file)
228
+ File.open(file, "rb") { |f| f.read }
229
+ end
230
+
231
+ def load_gemspec(file)
232
+ path = Pathname.new(file)
233
+ # Eval the gemspec from its parent directory
234
+ Dir.chdir(path.dirname.to_s) do
235
+ contents = File.read(path.basename.to_s)
236
+ begin
237
+ Gem::Specification.from_yaml(contents)
238
+ # Raises ArgumentError if the file is not valid YAML
239
+ rescue ArgumentError, SyntaxError, Gem::EndOfYAMLException, Gem::Exception
240
+ begin
241
+ eval(contents, TOPLEVEL_BINDING, path.expand_path.to_s)
242
+ rescue LoadError => e
243
+ original_line = e.backtrace.find { |line| line.include?(path.to_s) }
244
+ msg = "There was a LoadError while evaluating #{path.basename}:\n #{e.message}"
245
+ msg << " from\n #{original_line}" if original_line
246
+ msg << "\n"
247
+
248
+ if RUBY_VERSION >= "1.9.0"
249
+ msg << "\nDoes it try to require a relative path? That doesn't work in Ruby 1.9."
250
+ end
251
+
252
+ raise GemspecError, msg
253
+ end
254
+ end
255
+ end
256
+ end
257
+
258
+ private
259
+
260
+ def configure_gem_home_and_path
261
+ if settings[:disable_shared_gems]
262
+ ENV['GEM_PATH'] = ''
263
+ ENV['GEM_HOME'] = File.expand_path(bundle_path, root)
264
+ elsif Bundler.rubygems.gem_dir != bundle_path.to_s
265
+ possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path]
266
+ paths = possibles.flatten.compact.uniq.reject { |p| p.empty? }
267
+ ENV["GEM_PATH"] = paths.join(File::PATH_SEPARATOR)
268
+ ENV["GEM_HOME"] = bundle_path.to_s
269
+ end
270
+
271
+ # TODO: This mkdir_p is only needed for JRuby <= 1.5 and should go away (GH #602)
272
+ FileUtils.mkdir_p bundle_path.to_s rescue nil
273
+
274
+ Bundler.rubygems.clear_paths
275
+ end
276
+
277
+ def upgrade_lockfile
278
+ lockfile = default_lockfile
279
+ if lockfile.exist? && lockfile.read(3) == "---"
280
+ Bundler.ui.warn "Detected Gemfile.lock generated by 0.9, deleting..."
281
+ lockfile.rmtree
282
+ end
283
+ end
284
+
285
+ end
286
+ 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,520 @@
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
+ def check
96
+ ENV['BUNDLE_GEMFILE'] = File.expand_path(options[:gemfile]) if options[:gemfile]
97
+ begin
98
+ not_installed = Bundler.definition.missing_specs
99
+ rescue GemNotFound, VersionConflict
100
+ Bundler.ui.error "Your Gemfile's dependencies could not be satisfied"
101
+ Bundler.ui.warn "Install missing gems with `bundle install`"
102
+ exit 1
103
+ end
104
+
105
+ if not_installed.any?
106
+ Bundler.ui.error "The following gems are missing"
107
+ not_installed.each { |s| Bundler.ui.error " * #{s.name} (#{s.version})" }
108
+ Bundler.ui.warn "Install missing gems with `bundle install`"
109
+ exit 1
110
+ else
111
+ Bundler.load.lock
112
+ Bundler.ui.info "The Gemfile's dependencies are satisfied"
113
+ end
114
+ end
115
+
116
+ desc "install", "Install the current environment to the system"
117
+ long_desc <<-D
118
+ Install will install all of the gems in the current bundle, making them available
119
+ for use. In a freshly checked out repository, this command will give you the same
120
+ gem versions as the last person who updated the Gemfile and ran `bundle update`.
121
+
122
+ Passing [DIR] to install (e.g. vendor) will cause the unpacked gems to be installed
123
+ into the [DIR] directory rather than into system gems.
124
+
125
+ If the bundle has already been installed, bundler will tell you so and then exit.
126
+ D
127
+ method_option "without", :type => :array, :banner =>
128
+ "Exclude gems that are part of the specified named group."
129
+ method_option "disable-shared-gems", :type => :boolean, :banner =>
130
+ "This option is deprecated. Please do not use it."
131
+ method_option "gemfile", :type => :string, :banner =>
132
+ "Use the specified gemfile instead of Gemfile"
133
+ method_option "no-prune", :type => :boolean, :banner =>
134
+ "Don't remove stale gems from the cache."
135
+ method_option "no-cache", :type => :boolean, :banner =>
136
+ "Don't update the existing gem cache."
137
+ method_option "quiet", :type => :boolean, :banner =>
138
+ "Only output warnings and errors."
139
+ method_option "local", :type => :boolean, :banner =>
140
+ "Do not attempt to fetch gems remotely and use the gem cache instead"
141
+ method_option "binstubs", :type => :string, :lazy_default => "bin", :banner =>
142
+ "Generate bin stubs for bundled gems to ./bin"
143
+ method_option "path", :type => :string, :banner =>
144
+ "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME). Bundler will remember this value for future installs on this machine"
145
+ method_option "system", :type => :boolean, :banner =>
146
+ "Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
147
+ method_option "frozen", :type => :boolean, :banner =>
148
+ "Do not allow the Gemfile.lock to be updated after this install"
149
+ method_option "deployment", :type => :boolean, :banner =>
150
+ "Install using defaults tuned for deployment environments"
151
+ def install(path = nil)
152
+ opts = options.dup
153
+ if opts[:without]
154
+ opts[:without].map!{|g| g.split(" ") }
155
+ opts[:without].flatten!
156
+ opts[:without].map!{|g| g.to_sym }
157
+ end
158
+
159
+ # Can't use Bundler.settings for this because settings needs gemfile.dirname
160
+ ENV['BUNDLE_GEMFILE'] = File.expand_path(opts[:gemfile]) if opts[:gemfile]
161
+ ENV['RB_USER_INSTALL'] = '1' if Bundler::FREEBSD
162
+
163
+ # Just disable color in deployment mode
164
+ Bundler.ui.shell = Thor::Shell::Basic.new if opts[:deployment]
165
+
166
+ if (path || opts[:path] || opts[:deployment]) && opts[:system]
167
+ Bundler.ui.error "You have specified both a path to install your gems to, \n" \
168
+ "as well as --system. Please choose."
169
+ exit 1
170
+ end
171
+
172
+ if path && opts[:path]
173
+ Bundler.ui.error "You have specified a path via `bundle install #{path}` as well as\n" \
174
+ "by `bundle install --path #{options[:path]}`. These options are\n" \
175
+ "equivalent, so please use one or the other."
176
+ exit 1
177
+ end
178
+
179
+ if opts["disable-shared-gems"]
180
+ Bundler.ui.error "The disable-shared-gem option is no longer available.\n\n" \
181
+ "Instead, use `bundle install` to install to your system,\n" \
182
+ "or `bundle install --path path/to/gems` to install to an isolated\n" \
183
+ "location. Bundler will resolve relative paths relative to\n" \
184
+ "your `Gemfile`."
185
+ exit 1
186
+ end
187
+
188
+ if opts[:deployment] || opts[:frozen]
189
+ unless Bundler.default_lockfile.exist?
190
+ flag = opts[:deployment] ? '--deployment' : '--frozen'
191
+ raise ProductionError, "The #{flag} flag requires a Gemfile.lock. Please make " \
192
+ "sure you have checked your Gemfile.lock into version control " \
193
+ "before deploying."
194
+ end
195
+
196
+ if Bundler.root.join("vendor/cache").exist?
197
+ opts[:local] = true
198
+ end
199
+
200
+ Bundler.settings[:frozen] = '1'
201
+ end
202
+
203
+ # When install is called with --no-deployment, disable deployment mode
204
+ if opts[:deployment] == false
205
+ Bundler.settings.delete(:frozen)
206
+ opts[:system] = true
207
+ end
208
+
209
+ Bundler.settings[:path] = nil if opts[:system]
210
+ Bundler.settings[:path] = "vendor/bundle" if opts[:deployment]
211
+ Bundler.settings[:path] = path if path
212
+ Bundler.settings[:path] = opts[:path] if opts[:path]
213
+ Bundler.settings[:bin] = opts["binstubs"] if opts[:binstubs]
214
+ Bundler.settings[:no_prune] = true if opts["no-prune"]
215
+ Bundler.settings[:disable_shared_gems] = Bundler.settings[:path] ? '1' : nil
216
+ Bundler.settings.without = opts[:without]
217
+ Bundler.ui.be_quiet! if opts[:quiet]
218
+
219
+ Installer.install(Bundler.root, Bundler.definition, opts)
220
+ Bundler.load.cache if Bundler.root.join("vendor/cache").exist? && !options["no-cache"]
221
+
222
+ if Bundler.settings[:path]
223
+ absolute_path = File.expand_path(Bundler.settings[:path])
224
+ relative_path = absolute_path.sub(File.expand_path('.'), '.')
225
+ Bundler.ui.confirm "Your bundle is complete! " +
226
+ "It was installed into #{relative_path}"
227
+ else
228
+ Bundler.ui.confirm "Your bundle is complete! " +
229
+ "Use `bundle show [gemname]` to see where a bundled gem is installed."
230
+ end
231
+
232
+ if path
233
+ Bundler.ui.warn "The path argument to `bundle install` is deprecated. " +
234
+ "It will be removed in version 1.1. " +
235
+ "Please use `bundle install --path #{path}` instead."
236
+ end
237
+ rescue GemNotFound => e
238
+ if opts[:local] && Bundler.app_cache.exist?
239
+ Bundler.ui.warn "Some gems seem to be missing from your vendor/cache directory."
240
+ end
241
+
242
+ if Bundler.definition.no_sources?
243
+ Bundler.ui.warn "Your Gemfile doesn't have any sources. You can add one with a line like 'source :rubygems'"
244
+ end
245
+ raise e
246
+ end
247
+
248
+ desc "update", "update the current environment"
249
+ long_desc <<-D
250
+ Update will install the newest versions of the gems listed in the Gemfile. Use
251
+ update when you have changed the Gemfile, or if you want to get the newest
252
+ possible versions of the gems in the bundle.
253
+ D
254
+ method_option "source", :type => :array, :banner => "Update a specific source (and all gems associated with it)"
255
+ method_option "local", :type => :boolean, :banner =>
256
+ "Do not attempt to fetch gems remotely and use the gem cache instead"
257
+ def update(*gems)
258
+ sources = Array(options[:source])
259
+
260
+ if gems.empty? && sources.empty?
261
+ # We're doing a full update
262
+ Bundler.definition(true)
263
+ else
264
+ Bundler.definition(:gems => gems, :sources => sources)
265
+ end
266
+
267
+ opts = {"update" => true, "local" => options[:local]}
268
+ Installer.install Bundler.root, Bundler.definition, opts
269
+ Bundler.load.cache if Bundler.root.join("vendor/cache").exist?
270
+ Bundler.ui.confirm "Your bundle is updated! " +
271
+ "Use `bundle show [gemname]` to see where a bundled gem is installed."
272
+ end
273
+
274
+ desc "lock", "Locks the bundle to the current set of dependencies, including all child dependencies."
275
+ def lock
276
+ Bundler.ui.warn "Lock is deprecated. Your bundle is now locked whenever you run `bundle install`."
277
+ end
278
+
279
+ desc "unlock", "Unlock the bundle. This allows gem versions to be changed."
280
+ def unlock
281
+ Bundler.ui.warn "Unlock is deprecated. To update to newer gem versions, use `bundle update`."
282
+ end
283
+
284
+ desc "show [GEM]", "Shows all gems that are part of the bundle, or the path to a given gem"
285
+ long_desc <<-D
286
+ Show lists the names and versions of all gems that are required by your Gemfile.
287
+ Calling show with [GEM] will list the exact location of that gem on your machine.
288
+ D
289
+ def show(gem_name = nil)
290
+ Bundler.load.lock
291
+
292
+ if gem_name
293
+ Bundler.ui.info locate_gem(gem_name)
294
+ else
295
+ Bundler.ui.info "Gems included by the bundle:"
296
+ Bundler.load.specs.sort_by { |s| s.name }.each do |s|
297
+ Bundler.ui.info " * #{s.name} (#{s.version}#{s.git_version})"
298
+ end
299
+ end
300
+ end
301
+ map %w(list) => "show"
302
+
303
+ desc "cache", "Cache all the gems to vendor/cache", :hide => true
304
+ method_option "no-prune", :type => :boolean, :banner => "Don't remove stale gems from the cache."
305
+ def cache
306
+ Bundler.definition.resolve_with_cache!
307
+ Bundler.load.cache
308
+ Bundler.settings[:no_prune] = true if options["no-prune"]
309
+ Bundler.load.lock
310
+ rescue GemNotFound => e
311
+ Bundler.ui.error(e.message)
312
+ Bundler.ui.warn "Run `bundle install` to install missing gems."
313
+ exit 128
314
+ end
315
+
316
+ desc "package", "Locks and then caches all of the gems into vendor/cache"
317
+ method_option "no-prune", :type => :boolean, :banner => "Don't remove stale gems from the cache."
318
+ long_desc <<-D
319
+ The package command will copy the .gem files for every gem in the bundle into the
320
+ directory ./vendor/cache. If you then check that directory into your source
321
+ control repository, others who check out your source will be able to install the
322
+ bundle without having to download any additional gems.
323
+ D
324
+ def package
325
+ install
326
+ # TODO: move cache contents here now that all bundles are locked
327
+ Bundler.load.cache
328
+ end
329
+ map %w(pack) => :package
330
+
331
+ desc "exec", "Run the command in context of the bundle"
332
+ long_desc <<-D
333
+ Exec runs a command, providing it access to the gems in the bundle. While using
334
+ bundle exec you can require and call the bundled gems as if they were installed
335
+ into the systemwide Rubygems repository.
336
+ D
337
+ def exec(*)
338
+ ARGV.shift # remove "exec"
339
+
340
+ Bundler.setup
341
+
342
+ begin
343
+ # Run
344
+ Kernel.exec(*ARGV)
345
+ rescue Errno::EACCES
346
+ Bundler.ui.error "bundler: not executable: #{ARGV.first}"
347
+ exit 126
348
+ rescue Errno::ENOENT
349
+ Bundler.ui.error "bundler: command not found: #{ARGV.first}"
350
+ Bundler.ui.warn "Install missing gem executables with `bundle install`"
351
+ exit 127
352
+ end
353
+ end
354
+
355
+ desc "config NAME [VALUE]", "retrieve or set a configuration value"
356
+ long_desc <<-D
357
+ Retrieves or sets a configuration value. If only parameter is provided, retrieve the value. If two parameters are provided, replace the
358
+ existing value with the newly provided one.
359
+
360
+ By default, setting a configuration value sets it for all projects
361
+ on the machine.
362
+
363
+ If a global setting is superceded by local configuration, this command
364
+ will show the current value, as well as any superceded values and
365
+ where they were specified.
366
+ D
367
+ def config(name = nil, *args)
368
+ values = ARGV.dup
369
+ values.shift # remove config
370
+ values.shift # remove the name
371
+
372
+ unless name
373
+ Bundler.ui.confirm "Settings are listed in order of priority. The top value will be used.\n"
374
+
375
+ Bundler.settings.all.each do |setting|
376
+ Bundler.ui.confirm "#{setting}"
377
+ with_padding do
378
+ Bundler.settings.pretty_values_for(setting).each do |line|
379
+ Bundler.ui.info line
380
+ end
381
+ end
382
+ Bundler.ui.confirm ""
383
+ end
384
+ return
385
+ end
386
+
387
+ if values.empty?
388
+ Bundler.ui.confirm "Settings for `#{name}` in order of priority. The top value will be used"
389
+ with_padding do
390
+ Bundler.settings.pretty_values_for(name).each { |line| Bundler.ui.info line }
391
+ end
392
+ else
393
+ locations = Bundler.settings.locations(name)
394
+
395
+ if local = locations[:local]
396
+ Bundler.ui.info "Your application has set #{name} to #{local.inspect}. This will override the " \
397
+ "system value you are currently setting"
398
+ end
399
+
400
+ if global = locations[:global]
401
+ Bundler.ui.info "You are replacing the current system value of #{name}, which is currently #{global}"
402
+ end
403
+
404
+ if env = locations[:env]
405
+ Bundler.ui.info "You have set a bundler environment variable for #{env}. This will take precedence " \
406
+ "over the system value you are setting"
407
+ end
408
+
409
+ Bundler.settings.set_global(name, values.join(" "))
410
+ end
411
+ end
412
+
413
+ desc "open GEM", "Opens the source directory of the given bundled gem"
414
+ def open(name)
415
+ editor = [ENV['BUNDLER_EDITOR'], ENV['VISUAL'], ENV['EDITOR']].find{|e| !e.nil? && !e.empty? }
416
+ if editor
417
+ gem_path = locate_gem(name)
418
+ Dir.chdir(gem_path) do
419
+ command = "#{editor} #{gem_path}"
420
+ success = system(command)
421
+ Bundler.ui.info "Could not run '#{command}'" unless success
422
+ end
423
+ else
424
+ Bundler.ui.info("To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR")
425
+ end
426
+ end
427
+
428
+ desc "console [GROUP]", "Opens an IRB session with the bundle pre-loaded"
429
+ def console(group = nil)
430
+ group ? Bundler.require(:default, *(group.split.map! {|g| g.to_sym })) : Bundler.require
431
+ ARGV.clear
432
+
433
+ require 'irb'
434
+ IRB.start
435
+ end
436
+
437
+ desc "version", "Prints the bundler's version information"
438
+ def version
439
+ Bundler.ui.info "Bundler version #{Bundler::VERSION}"
440
+ end
441
+ map %w(-v --version) => :version
442
+
443
+ desc 'viz', "Generates a visual dependency graph"
444
+ long_desc <<-D
445
+ Viz generates a PNG file of the current Gemfile as a dependency graph.
446
+ Viz requires the ruby-graphviz gem (and its dependencies).
447
+ The associated gems must also be installed via 'bundle install'.
448
+ D
449
+ method_option :file, :type => :string, :default => 'gem_graph.png', :aliases => '-f', :banner => "The name to use for the generated png file."
450
+ method_option :version, :type => :boolean, :default => false, :aliases => '-v', :banner => "Set to show each gem version."
451
+ method_option :requirements, :type => :boolean, :default => false, :aliases => '-r', :banner => "Set to show the version of each required dependency."
452
+ def viz
453
+ output_file = File.expand_path(options[:file])
454
+ graph = Graph.new( Bundler.load )
455
+
456
+ begin
457
+ graph.viz(output_file, options[:version], options[:requirements])
458
+ Bundler.ui.info output_file
459
+ rescue LoadError => e
460
+ Bundler.ui.error e.inspect
461
+ Bundler.ui.warn "Make sure you have the graphviz ruby gem. You can install it with:"
462
+ Bundler.ui.warn "`gem install ruby-graphviz`"
463
+ rescue StandardError => e
464
+ if e.message =~ /GraphViz not installed or dot not in PATH/
465
+ Bundler.ui.error e.message
466
+ Bundler.ui.warn "The ruby graphviz gem requires GraphViz to be installed"
467
+ else
468
+ raise
469
+ end
470
+ end
471
+ end
472
+
473
+ desc "gem GEM", "Creates a skeleton for creating a rubygem"
474
+ method_option :bin, :type => :boolean, :default => false, :aliases => '-b', :banner => "Generate a binary for your library."
475
+ def gem(name)
476
+ name = name.chomp("/") # remove trailing slash if present
477
+ target = File.join(Dir.pwd, name)
478
+ constant_name = name.split('_').map{|p| p[0..0].upcase + p[1..-1] }.join
479
+ constant_name = constant_name.split('-').map{|q| q[0..0].upcase + q[1..-1] }.join('::') if constant_name =~ /-/
480
+ constant_array = constant_name.split('::')
481
+ git_author_name = `git config user.name`.chomp
482
+ git_author_email = `git config user.email`.chomp
483
+ author_name = git_author_name.empty? ? "TODO: Write your name" : git_author_name
484
+ author_email = git_author_email.empty? ? "TODO: Write your email address" : git_author_email
485
+ FileUtils.mkdir_p(File.join(target, 'lib', name))
486
+ opts = {:name => name, :constant_name => constant_name, :constant_array => constant_array, :author_name => author_name, :author_email => author_email}
487
+ template(File.join("newgem/Gemfile.tt"), File.join(target, "Gemfile"), opts)
488
+ template(File.join("newgem/Rakefile.tt"), File.join(target, "Rakefile"), opts)
489
+ template(File.join("newgem/gitignore.tt"), File.join(target, ".gitignore"), opts)
490
+ template(File.join("newgem/newgem.gemspec.tt"), File.join(target, "#{name}.gemspec"), opts)
491
+ template(File.join("newgem/lib/newgem.rb.tt"), File.join(target, "lib/#{name}.rb"), opts)
492
+ template(File.join("newgem/lib/newgem/version.rb.tt"), File.join(target, "lib/#{name}/version.rb"), opts)
493
+ if options[:bin]
494
+ template(File.join("newgem/bin/newgem.tt"), File.join(target, 'bin', name), opts)
495
+ end
496
+ Bundler.ui.info "Initializating git repo in #{target}"
497
+ Dir.chdir(target) { `git init`; `git add .` }
498
+ end
499
+
500
+ def self.source_root
501
+ File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
502
+ end
503
+
504
+ private
505
+
506
+ def have_groff?
507
+ !(`which groff` rescue '').empty?
508
+ end
509
+
510
+ def locate_gem(name)
511
+ spec = Bundler.load.specs.find{|s| s.name == name }
512
+ raise GemNotFound, "Could not find gem '#{name}' in the current bundle." unless spec
513
+ if spec.name == 'bundler'
514
+ return File.expand_path('../../../', __FILE__)
515
+ end
516
+ spec.full_gem_path
517
+ end
518
+
519
+ end
520
+ end