bundler 1.0.0.rc.1 → 1.0.0.rc.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

@@ -1,3 +1,51 @@
1
+ ## 1.0.0.rc.2 (July 29, 2010)
2
+
3
+ - `bundle install path` was causing confusion, so we now print
4
+ a clarifying warning. The preferred way to install to a path
5
+ (which will not print the warning) is
6
+ `bundle install --path path/to/install`.
7
+ - `bundle install --system` installs to the default system
8
+ location ($BUNDLE_PATH or $GEM_HOME) even if you previously
9
+ used `bundle install --path`
10
+ - completely remove `--disable-shared-gems`. If you install to
11
+ system, you will not be isolated, while if you install to
12
+ another path, you will be isolated from gems installed to
13
+ the system. This was mostly an internal option whose naming
14
+ and semantics were extremely confusing.
15
+ - Add a `--production` option to `bundle install`:
16
+ - by default, installs to `vendor/bundle`. This can be
17
+ overridden with the `--path` option
18
+ - uses `--local` if `vendor/cache` is found. This will
19
+ guarantee that Bundler does not attempt to connect to
20
+ Rubygems and will use the gems cached in `vendor/cache`
21
+ instead
22
+ - Raises an exception if a Gemfile.lock is not found
23
+ - Raises an exception if you modify your Gemfile in development
24
+ but do not check in an updated Gemfile.lock
25
+ - Fixes a bug where switching a source from Rubygems to git
26
+ would always say "the git source is not checked out" when
27
+ running `bundle install`
28
+
29
+ NOTE: We received several reports of "the git source has not
30
+ been checked out. Please run bundle install". As far as we
31
+ can tell, these problems have two possible causes:
32
+
33
+ 1. `bundle install ~/.bundle` in one user, but actually running
34
+ the application as another user. Never install gems to a
35
+ directory scoped to a user (`~` or `$HOME`) in deployment.
36
+ 2. A bug that happened when changing a gem to a git source.
37
+
38
+ To mitigate several common causes of `(1)`, please use the
39
+ new `--production` flag. This flag is simply a roll-up of
40
+ the best practices we have been encouraging people to use
41
+ for deployment.
42
+
43
+ If you want to share gems across deployments, and you use
44
+ Capistrano, symlink release_path/current/vendor/bundle to
45
+ release_path/shared/bundled_gems. This will keep deployments
46
+ snappy while maintaining the benefits of clean, deploy-time
47
+ isolation.
48
+
1
49
  ## 1.0.0.rc.1 (July 26, 2010)
2
50
 
3
51
  - Fixed a bug with `bundle install` on multiple machines and git
@@ -28,12 +28,7 @@ module Bundler
28
28
 
29
29
  class BundlerError < StandardError
30
30
  def self.status_code(code = nil)
31
- return @code unless code
32
- @code = code
33
- end
34
-
35
- def status_code
36
- self.class.status_code
31
+ define_method(:status_code) { code }
37
32
  end
38
33
  end
39
34
 
@@ -45,7 +40,9 @@ module Bundler
45
40
  class GemspecError < BundlerError; status_code(14) ; end
46
41
  class DeprecatedError < BundlerError; status_code(12) ; end
47
42
  class GemspecError < BundlerError; status_code(14) ; end
48
- class InvalidOption < BundlerError; status_code(15) ; end
43
+ class DslError < BundlerError; status_code(15) ; end
44
+ class ProductionError < BundlerError; status_code(16) ; end
45
+ class InvalidOption < DslError ; end
49
46
 
50
47
  class VersionConflict < BundlerError
51
48
  attr_reader :conflicts
@@ -71,6 +68,14 @@ module Bundler
71
68
  end
72
69
  end
73
70
 
71
+ def production?
72
+ @production
73
+ end
74
+
75
+ def production=(value)
76
+ @production = value
77
+ end
78
+
74
79
  def ui
75
80
  @ui ||= UI.new
76
81
  end
@@ -86,7 +86,7 @@ module Bundler
86
86
  method_option "without", :type => :array, :banner =>
87
87
  "Exclude gems that are part of the specified named group."
88
88
  method_option "disable-shared-gems", :type => :boolean, :banner =>
89
- "Do not use any shared gems, such as the system gem repository."
89
+ "This option is deprecated. Please do not use it."
90
90
  method_option "gemfile", :type => :string, :banner =>
91
91
  "Use the specified gemfile instead of Gemfile"
92
92
  method_option "no-prune", :type => :boolean, :banner =>
@@ -99,16 +99,61 @@ module Bundler
99
99
  "Do not attempt to fetch gems remotely and use the gem cache instead"
100
100
  method_option "binstubs", :type => :string, :lazy_default => "bin", :banner =>
101
101
  "Generate bin stubs for bundled gems to ./bin"
102
+ method_option "path", :type => :string, :banner =>
103
+ "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME). Bundler will remember this value for future installs on this machine"
104
+ method_option "system", :type => :boolean, :banner =>
105
+ "Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
106
+ method_option "production", :type => :boolean, :banner =>
107
+ "Install using defaults tuned for deployment environments"
102
108
  def install(path = nil)
103
109
  opts = options.dup
104
110
  opts[:without] ||= []
105
111
  opts[:without].map! { |g| g.to_sym }
106
112
 
113
+ if (path || options[:path] || options[:production]) && options[:system]
114
+ Bundler.ui.error "You have specified both a path to install your gems to, \n" \
115
+ "as well as --system. Please choose."
116
+ exit 1
117
+ end
118
+
119
+ if path && options[:path]
120
+ Bundler.ui.error "You have specified a path via `bundle install #{path}` as well as\n" \
121
+ "by `bundle install --path #{options[:path]}`. These options are\n" \
122
+ "equivalent, so please use one or the other."
123
+ exit 1
124
+ end
125
+
126
+ if opts["disable-shared-gems"]
127
+ Bundler.ui.error "The disable-shared-gem option is no longer available.\n\n" \
128
+ "Instead, use `bundle install` to install to your system,\n" \
129
+ "or `bundle install --path path/to/gems` to install to an isolated\n" \
130
+ "location. Bundler will resolve relative paths relative to\n" \
131
+ "your `Gemfile`."
132
+ exit 1
133
+ end
134
+
135
+ if opts[:production]
136
+ Bundler.production = true
137
+
138
+ unless Bundler.root.join("Gemfile.lock").exist?
139
+ raise ProductionError, "The --production flag requires a Gemfile.lock. Please\n" \
140
+ "make sure you have checked your Gemfile.lock into version\n" \
141
+ "control before deploying."
142
+ end
143
+
144
+ if Bundler.root.join("vendor/cache").exist?
145
+ opts["local"] = true
146
+ end
147
+ end
148
+
107
149
  # Can't use Bundler.settings for this because settings needs gemfile.dirname
108
150
  ENV['BUNDLE_GEMFILE'] = opts[:gemfile] if opts[:gemfile]
151
+ Bundler.settings[:path] = nil if options[:system]
152
+ Bundler.settings[:path] = "vendor/bundle" if options[:production]
109
153
  Bundler.settings[:path] = path if path
154
+ Bundler.settings[:path] = options[:path] if options[:path]
110
155
  Bundler.settings[:bin] = opts["binstubs"] if opts[:binstubs]
111
- Bundler.settings[:disable_shared_gems] = '1' if options["disable-shared-gems"] || path
156
+ Bundler.settings[:disable_shared_gems] = '1' if Bundler.settings[:path]
112
157
  Bundler.settings.without = opts[:without]
113
158
  Bundler.ui.be_quiet! if opts[:quiet]
114
159
 
@@ -116,6 +161,13 @@ module Bundler
116
161
  Bundler.load.cache if Bundler.root.join("vendor/cache").exist?
117
162
  Bundler.ui.confirm "Your bundle is complete! " +
118
163
  "Use `bundle show [gemname]` to see where a bundled gem is installed."
164
+
165
+ Bundler.ui.confirm "\nYour bundle was installed to `#{Bundler.settings[:path]}`" if Bundler.settings[:path]
166
+
167
+ if path
168
+ Bundler.ui.warn "\nIf you meant to install it to your system, please remove the\n" \
169
+ "`#{path}` directory and run `bundle install --system`"
170
+ end
119
171
  rescue GemNotFound => e
120
172
  if Bundler.definition.no_sources?
121
173
  Bundler.ui.warn "Your Gemfile doesn't have any sources. You can add one with a line like 'source :gemcutter'"
@@ -231,8 +283,7 @@ module Bundler
231
283
  existing value with the newly provided one.
232
284
 
233
285
  By default, setting a configuration value sets it for all projects
234
- on the machine. If you want to set the configuration for a specific
235
- project, use the --local flag.
286
+ on the machine.
236
287
 
237
288
  If a global setting is superceded by local configuration, this command
238
289
  will show the current value, as well as any superceded values and
@@ -67,7 +67,12 @@ module Bundler
67
67
  current_platform = Gem.platforms.map { |p| generic(p) }.compact.last
68
68
  @platforms |= [current_platform]
69
69
 
70
- converge
70
+ if Bundler.production?
71
+ ensure_equivalent_gemfile_and_lockfile
72
+ end
73
+
74
+ converge_sources
75
+ converge_dependencies
71
76
  end
72
77
 
73
78
  def resolve_with_cache!
@@ -122,6 +127,7 @@ module Bundler
122
127
 
123
128
  def resolve
124
129
  @resolve ||= begin
130
+ converge_locked_specs
125
131
  if @last_resolve.valid_for?(expanded_dependencies)
126
132
  @last_resolve
127
133
  else
@@ -202,17 +208,74 @@ module Bundler
202
208
  end
203
209
 
204
210
  private
211
+ def ensure_equivalent_gemfile_and_lockfile
212
+ changes = false
205
213
 
206
- def converge
207
- converge_sources
208
- converge_dependencies
209
- converge_locked_specs
214
+ msg = "You have modified your Gemfile in development but did not check\n" \
215
+ "the resulting snapshot (Gemfile.lock) into version control"
216
+
217
+ added = []
218
+ deleted = []
219
+ changed = []
220
+
221
+ if @locked_sources != @sources
222
+ new_sources = @sources - @locked_sources
223
+ deleted_sources = @locked_sources - @sources
224
+
225
+ if new_sources.any?
226
+ added.concat new_sources.map { |source| "* source: #{source}" }
227
+ end
228
+
229
+ if deleted_sources.any?
230
+ deleted.concat deleted_sources.map { |source| "* source: #{source}" }
231
+ end
232
+
233
+ changes = true
234
+ end
235
+
236
+ both_sources = Hash.new { |h,k| h[k] = ["no specified source", "no specified source"] }
237
+ @dependencies.each { |d| both_sources[d.name][0] = d.source if d.source }
238
+ @locked_deps.each { |d| both_sources[d.name][1] = d.source if d.source }
239
+ both_sources.delete_if { |k,v| v[0] == v[1] }
240
+
241
+ if @dependencies != @locked_deps
242
+ new_deps = @dependencies - @locked_deps
243
+ deleted_deps = @locked_deps - @dependencies
244
+
245
+ if new_deps.any?
246
+ added.concat new_deps.map { |d| "* #{pretty_dep(d)}" }
247
+ end
248
+
249
+ if deleted_deps.any?
250
+ deleted.concat deleted_deps.map { |d| "* #{pretty_dep(d)}" }
251
+ end
252
+
253
+ both_sources.each do |name, sources|
254
+ changed << "* #{name} from `#{sources[0]}` to `#{sources[1]}`"
255
+ end
256
+
257
+ changes = true
258
+ end
259
+
260
+ msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
261
+ msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
262
+ msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
263
+
264
+ raise ProductionError, msg if added.any? || deleted.any? || changed.any?
265
+ end
266
+
267
+ def pretty_dep(dep, source = false)
268
+ msg = "#{dep.name}"
269
+ msg << " (#{dep.requirement})" unless dep.requirement == Gem::Requirement.default
270
+ msg << " from the `#{dep.source}` source" if source && dep.source
271
+ msg
210
272
  end
211
273
 
212
274
  def converge_sources
213
275
  @sources.map! do |source|
214
276
  @locked_sources.find { |s| s == source } || source
215
277
  end
278
+
216
279
  @sources.each do |source|
217
280
  source.unlock! if source.respond_to?(:unlock!) && @unlock[:sources].include?(source.name)
218
281
  end
@@ -237,8 +300,12 @@ module Bundler
237
300
  # the gem in the Gemfile.lock still satisfies it, this is fine
238
301
  # too.
239
302
  @dependencies.each do |dep|
240
- if in_locked_deps?(dep) || satisfies_locked_spec?(dep)
303
+ locked_dep = @locked_deps.find { |d| dep == d }
304
+
305
+ if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep)
241
306
  deps << dep
307
+ elsif dep.source.is_a?(Source::Path) && (!locked_dep || dep.source != locked_dep.source)
308
+ dep.source.specs.each { |s| @unlock[:gems] << s.name }
242
309
  end
243
310
  end
244
311
 
@@ -271,10 +338,8 @@ module Bundler
271
338
  @last_resolve = resolve
272
339
  end
273
340
 
274
- def in_locked_deps?(dep)
275
- @locked_deps.any? do |d|
276
- dep == d && dep.source == d.source
277
- end
341
+ def in_locked_deps?(dep, d)
342
+ d && dep.source == d.source
278
343
  end
279
344
 
280
345
  def satisfies_locked_spec?(dep)
@@ -1,6 +1,4 @@
1
1
  module Bundler
2
- class DslError < StandardError; end
3
-
4
2
  class Dsl
5
3
  def self.evaluate(gemfile)
6
4
  builder = new
@@ -8,7 +6,7 @@ module Bundler
8
6
  builder.to_definition
9
7
  end
10
8
 
11
- VALID_PLATFORMS = [:ruby, :ruby_18, :ruby_19, :mri, :mri_18, :mri19, :jruby, :mswin]
9
+ VALID_PLATFORMS = [:ruby, :ruby_18, :ruby_19, :mri, :mri_18, :mri_19, :jruby, :mswin]
12
10
 
13
11
  def initialize
14
12
  @rubygems_source = Source::Rubygems.new
@@ -190,7 +188,7 @@ module Bundler
190
188
  def _normalize_options(name, version, opts)
191
189
  _normalize_hash(opts)
192
190
 
193
- invalid_keys = opts.keys - %w(group git path name branch ref tag require submodules)
191
+ invalid_keys = opts.keys - %w(group git path name branch ref tag require submodules platforms)
194
192
  if invalid_keys.any?
195
193
  plural = invalid_keys.size > 1
196
194
  message = "You passed #{invalid_keys.map{|k| ':'+k }.join(", ")} "
@@ -232,9 +232,6 @@ module Bundler
232
232
  # to keep a list of every spot a failure happened.
233
233
  debug { " -> Jumping to: #{parent.name}" }
234
234
  if parent
235
- p [parent, parent.name]
236
- p current
237
- throw parent.name, nil if !existing.respond_to?(:required_by) || !existing.required_by.last
238
235
  throw parent.name, existing.respond_to?(:required_by) && existing.required_by.last.name
239
236
  else
240
237
  # The original set of dependencies conflict with the base set of specs
@@ -15,6 +15,10 @@ module Bundler
15
15
  set_key(key, value, @local_config, local_config_file)
16
16
  end
17
17
 
18
+ def delete(key)
19
+ @local_config
20
+ end
21
+
18
22
  def set_global(key, value)
19
23
  set_key(key, value, @global_config, global_config_file)
20
24
  end
@@ -90,6 +94,7 @@ module Bundler
90
94
 
91
95
  unless hash[key] == value
92
96
  hash[key] = value
97
+ hash.delete(key) if value.nil?
93
98
  FileUtils.mkdir_p(file.dirname)
94
99
  File.open(file, "w") { |f| f.puts hash.to_yaml }
95
100
  end
@@ -58,7 +58,7 @@ class Thor
58
58
  bold, end_bold = bold ? [BOLD, END_BOLD] : ['', '']
59
59
  "#{bold}#{color}#{string}#{CLEAR}#{end_bold}"
60
60
  end
61
-
61
+
62
62
  # Ask something to the user and receives a response.
63
63
  #
64
64
  # ==== Example
@@ -2,5 +2,5 @@ module Bundler
2
2
  # We're doing this because we might write tests that deal
3
3
  # with other versions of bundler and we are unsure how to
4
4
  # handle this better.
5
- VERSION = "1.0.0.rc.1" unless defined?(::Bundler::VERSION)
5
+ VERSION = "1.0.0.rc.2" unless defined?(::Bundler::VERSION)
6
6
  end
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundler
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15424055
5
4
  prerelease: true
6
5
  segments:
7
6
  - 1
8
7
  - 0
9
8
  - 0
10
9
  - rc
11
- - 1
12
- version: 1.0.0.rc.1
10
+ - 2
11
+ version: 1.0.0.rc.2
13
12
  platform: ruby
14
13
  authors:
15
14
  - Carl Lerche
@@ -19,18 +18,16 @@ autorequire:
19
18
  bindir: bin
20
19
  cert_chain: []
21
20
 
22
- date: 2010-07-26 00:00:00 -07:00
21
+ date: 2010-07-29 00:00:00 -07:00
23
22
  default_executable:
24
23
  dependencies:
25
24
  - !ruby/object:Gem::Dependency
26
25
  name: rspec
27
26
  prerelease: false
28
27
  requirement: &id001 !ruby/object:Gem::Requirement
29
- none: false
30
28
  requirements:
31
29
  - - ">="
32
30
  - !ruby/object:Gem::Version
33
- hash: 3
34
31
  segments:
35
32
  - 0
36
33
  version: "0"
@@ -105,20 +102,16 @@ rdoc_options: []
105
102
  require_paths:
106
103
  - lib
107
104
  required_ruby_version: !ruby/object:Gem::Requirement
108
- none: false
109
105
  requirements:
110
106
  - - ">="
111
107
  - !ruby/object:Gem::Version
112
- hash: 3
113
108
  segments:
114
109
  - 0
115
110
  version: "0"
116
111
  required_rubygems_version: !ruby/object:Gem::Requirement
117
- none: false
118
112
  requirements:
119
113
  - - ">="
120
114
  - !ruby/object:Gem::Version
121
- hash: 23
122
115
  segments:
123
116
  - 1
124
117
  - 3
@@ -127,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
120
  requirements: []
128
121
 
129
122
  rubyforge_project: bundler
130
- rubygems_version: 1.3.7
123
+ rubygems_version: 1.3.6
131
124
  signing_key:
132
125
  specification_version: 3
133
126
  summary: The best way to manage your application's dependencies