bundler 4.0.11 → 4.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/lib/bundler/build_metadata.rb +1 -1
  4. data/lib/bundler/cli/add.rb +3 -0
  5. data/lib/bundler/cli/common.rb +6 -0
  6. data/lib/bundler/cli/config.rb +8 -3
  7. data/lib/bundler/cli/install.rb +3 -0
  8. data/lib/bundler/cli/outdated.rb +42 -2
  9. data/lib/bundler/cli/update.rb +2 -0
  10. data/lib/bundler/cli.rb +16 -12
  11. data/lib/bundler/compact_index_client/parser.rb +4 -1
  12. data/lib/bundler/definition.rb +26 -4
  13. data/lib/bundler/dsl.rb +6 -2
  14. data/lib/bundler/endpoint_specification.rb +11 -1
  15. data/lib/bundler/installer.rb +5 -0
  16. data/lib/bundler/lockfile_parser.rb +15 -0
  17. data/lib/bundler/man/bundle-add.1 +4 -1
  18. data/lib/bundler/man/bundle-add.1.ronn +6 -1
  19. data/lib/bundler/man/bundle-config.1 +120 -156
  20. data/lib/bundler/man/bundle-config.1.ronn +30 -0
  21. data/lib/bundler/man/bundle-install.1 +4 -1
  22. data/lib/bundler/man/bundle-install.1.ronn +9 -1
  23. data/lib/bundler/man/bundle-outdated.1 +16 -13
  24. data/lib/bundler/man/bundle-outdated.1.ronn +19 -12
  25. data/lib/bundler/man/bundle-update.1 +4 -1
  26. data/lib/bundler/man/bundle-update.1.ronn +8 -0
  27. data/lib/bundler/remote_specification.rb +1 -1
  28. data/lib/bundler/resolver.rb +42 -1
  29. data/lib/bundler/rubygems_ext.rb +22 -0
  30. data/lib/bundler/rubygems_gem_installer.rb +1 -1
  31. data/lib/bundler/settings.rb +1 -0
  32. data/lib/bundler/source/git/git_proxy.rb +7 -2
  33. data/lib/bundler/source/path.rb +3 -2
  34. data/lib/bundler/source/rubygems/remote.rb +12 -2
  35. data/lib/bundler/source/rubygems.rb +51 -3
  36. data/lib/bundler/source_list.rb +6 -2
  37. data/lib/bundler/version.rb +1 -1
  38. data/lib/bundler.rb +10 -0
  39. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1eb2d32f3dd6dc576ac4fc1cf263101ae709911da9a91d58d05e51f94a22f94a
4
- data.tar.gz: 0df681b631b0be9801622df725900061a487c8a8855cc932c0bf1c978d1c6fe2
3
+ metadata.gz: 6aecb16228f32866a007c26b7a70fd787bcf81d42ee002004ba3ec2dd2625694
4
+ data.tar.gz: 5bce03c60cbf8034dfc540848298fbe3d8958314dc8513b61c0e8238f180f096
5
5
  SHA512:
6
- metadata.gz: '0852662046057ee2680a9a0b975f169493da3681b08e2ce4b08cbad86ef1537b7598b87e24109a3b51c3c6b93dbc2863ca7259a18c45126b849a2e1885eefedf'
7
- data.tar.gz: 00f14095e674ce91531777ab01f883de1e3e612fbbb3ee3a59a6eccfa6188be0fcbfadf237a7cf8133d05ed360ad6cc8fa6a7d0da588c3aad73501fb7af36a8b
6
+ metadata.gz: 4500a906181c0c43b1384fd9dda403dcc00ec11466911c156b01b309f2886336e756057af742396786ad2a0111e1a650729ad7bc03d09d04b0984a3770d4ebf4
7
+ data.tar.gz: 11e96f5ebdeca17df80db3506f010fd190b35c12cc8fd82532f6eeea9b51aa7b113a353c1cf88df215846c0226696a672813a79bf06202a3e5ffd7b543b0805a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.0.13 / 2026-06-03
4
+
5
+ ### Enhancements:
6
+
7
+ * Do not hard-code permissions for new gem directories during bundle install. Pull request [#9557](https://github.com/ruby/rubygems/pull/9557) by maxfelsher-cgi
8
+ * Clear gem specification cache after acquiring process lock. Pull request [#9310](https://github.com/ruby/rubygems/pull/9310) by ngan
9
+ * Show release date with bundle outdated. Pull request [#9337](https://github.com/ruby/rubygems/pull/9337) by hsbt
10
+
11
+ ### Bug fixes:
12
+
13
+ * Apply cooldown to locally installed gem versions. Pull request [#9582](https://github.com/ruby/rubygems/pull/9582) by hsbt
14
+
15
+ ### Security:
16
+
17
+ * Add `cooldown` to delay newly published gem. Pull request [#9576](https://github.com/ruby/rubygems/pull/9576) by hsbt
18
+
19
+ ## 4.0.12 / 2026-05-20
20
+
21
+ ### Enhancements:
22
+
23
+ * Make `bundle config get` return status 1 when the value is not set. Pull request [#9505](https://github.com/ruby/rubygems/pull/9505) by willnet
24
+ * Use Pathname#absolute?. Pull request [#9529](https://github.com/ruby/rubygems/pull/9529) by nobu
25
+ * Deprecate parsing non-lockfile content in LockfileParser. Pull request [#9502](https://github.com/ruby/rubygems/pull/9502) by kurotaky
26
+ * Print a warning for a potential confusion from the indirect dependencies. Pull request [#5029](https://github.com/ruby/rubygems/pull/5029) by junaruga
27
+ * Respect Gemfile bundler setting in `Bundler.setup`. Pull request [#4892](https://github.com/ruby/rubygems/pull/4892) by godfat
28
+
29
+ ### Bug fixes:
30
+
31
+ * Gracefully handle missing checksums in Compact Index. Pull request [#9492](https://github.com/ruby/rubygems/pull/9492) by jneen
32
+ * Skip git source exclusion when lockfile cannot backfill. Pull request [#9544](https://github.com/ruby/rubygems/pull/9544) by yahonda
33
+ * Fix bundle config gemfile unset behavior. Pull request [#9514](https://github.com/ruby/rubygems/pull/9514) by afurm
34
+
3
35
  ## 4.0.11 / 2026-04-30
4
36
 
5
37
  ### Enhancements:
@@ -5,7 +5,7 @@ module Bundler
5
5
  module BuildMetadata
6
6
  # begin ivars
7
7
  @built_at = nil
8
- @git_commit_sha = "b7155a3865".freeze
8
+ @git_commit_sha = "003f20f0dc".freeze
9
9
  # end ivars
10
10
 
11
11
  # A hash representation of the build metadata.
@@ -14,6 +14,9 @@ module Bundler
14
14
  def run
15
15
  Bundler.ui.level = "warn" if options[:quiet]
16
16
 
17
+ Bundler::CLI::Common.validate_cooldown!(options[:cooldown])
18
+ Bundler.settings.set_command_option_if_given :cooldown, options[:cooldown]
19
+
17
20
  validate_options!
18
21
  inject_dependencies
19
22
  perform_bundle_install unless options["skip-install"]
@@ -2,6 +2,12 @@
2
2
 
3
3
  module Bundler
4
4
  module CLI::Common
5
+ def self.validate_cooldown!(value)
6
+ return if value.nil?
7
+ return if value.is_a?(Integer) && value >= 0
8
+ raise InvalidOption, "Expected `--cooldown` to be a non-negative integer, got #{value.inspect}"
9
+ end
10
+
5
11
  def self.output_post_install_messages(messages)
6
12
  return if Bundler.settings["ignore_messages"]
7
13
  messages.to_a.each do |name, msg|
@@ -87,16 +87,21 @@ module Bundler
87
87
 
88
88
  if value.nil?
89
89
  warn_unused_scope "Ignoring --#{scope} since no value to set was given"
90
+ current_value = Bundler.settings[name]
90
91
 
91
92
  if options[:parseable]
92
93
  if value = Bundler.settings[name]
93
94
  Bundler.ui.info("#{name}=#{value}")
94
95
  end
95
- return
96
+ else
97
+ confirm(name)
96
98
  end
97
99
 
98
- confirm(name)
99
- return
100
+ if current_value.nil?
101
+ exit 1
102
+ else
103
+ return
104
+ end
100
105
  end
101
106
 
102
107
  Bundler.ui.info(message) if message
@@ -112,6 +112,9 @@ module Bundler
112
112
 
113
113
  Bundler.settings.set_command_option_if_given :jobs, options["jobs"]
114
114
 
115
+ Bundler::CLI::Common.validate_cooldown!(options["cooldown"])
116
+ Bundler.settings.set_command_option_if_given :cooldown, options["cooldown"]
117
+
115
118
  Bundler.settings.set_command_option_if_given :no_prune, options["no-prune"]
116
119
 
117
120
  Bundler.settings.set_command_option_if_given :no_install, options["no-install"]
@@ -26,6 +26,9 @@ module Bundler
26
26
  def run
27
27
  check_for_deployment_mode!
28
28
 
29
+ Bundler::CLI::Common.validate_cooldown!(options[:cooldown])
30
+ Bundler.settings.set_command_option_if_given :cooldown, options[:cooldown]
31
+
29
32
  Bundler.definition.validate_runtime!
30
33
  current_specs = Bundler.ui.silence { Bundler.definition.resolve }
31
34
 
@@ -199,7 +202,15 @@ module Bundler
199
202
  end
200
203
 
201
204
  spec_outdated_info = "#{active_spec.name} (newest #{spec_version}, " \
202
- "installed #{current_version}#{dependency_version})"
205
+ "installed #{current_version}#{dependency_version}"
206
+
207
+ release_date = release_date_for(active_spec)
208
+ spec_outdated_info += ", released #{release_date}" unless release_date.empty?
209
+
210
+ remaining = cooldown_days_remaining(active_spec)
211
+ spec_outdated_info += ", in cooldown for #{remaining} more day#{"s" if remaining > 1}" if remaining
212
+
213
+ spec_outdated_info += ")"
203
214
 
204
215
  output_message = if options[:parseable]
205
216
  spec_outdated_info.to_s
@@ -215,13 +226,25 @@ module Bundler
215
226
  def gem_column_for(current_spec, active_spec, dependency, groups)
216
227
  current_version = "#{current_spec.version}#{current_spec.git_version}"
217
228
  spec_version = "#{active_spec.version}#{active_spec.git_version}"
229
+ remaining = cooldown_days_remaining(active_spec)
230
+ spec_version += " (cooldown #{remaining}d)" if remaining
218
231
  dependency = dependency.requirement if dependency
219
232
 
220
233
  ret_val = [active_spec.name, current_version, spec_version, dependency.to_s, groups.to_s]
234
+ ret_val << release_date_for(active_spec)
221
235
  ret_val << loaded_from_for(active_spec).to_s if Bundler.ui.debug?
222
236
  ret_val
223
237
  end
224
238
 
239
+ def cooldown_days_remaining(spec, now = Time.now)
240
+ return nil unless spec.respond_to?(:created_at) && spec.created_at
241
+ return nil unless spec.respond_to?(:remote) && spec.remote
242
+ days = spec.remote.effective_cooldown
243
+ return nil if days.nil? || days <= 0
244
+ remaining = days - ((now - spec.created_at) / 86_400.0)
245
+ remaining > 0 ? remaining.ceil : nil
246
+ end
247
+
225
248
  def check_for_deployment_mode!
226
249
  return unless Bundler.frozen_bundle?
227
250
  suggested_command = if Bundler.settings.locations("frozen").keys.&([:global, :local]).any?
@@ -283,11 +306,28 @@ module Bundler
283
306
  end
284
307
 
285
308
  def table_header
286
- header = ["Gem", "Current", "Latest", "Requested", "Groups"]
309
+ header = ["Gem", "Current", "Latest", "Requested", "Groups", "Release Date"]
287
310
  header << "Path" if Bundler.ui.debug?
288
311
  header
289
312
  end
290
313
 
314
+ def release_date_for(spec)
315
+ return "" unless spec.respond_to?(:date)
316
+
317
+ date = spec.date
318
+ return "" unless date
319
+
320
+ return "" unless Gem.const_defined?(:DEFAULT_SOURCE_DATE_EPOCH)
321
+ default_date = Time.at(Gem::DEFAULT_SOURCE_DATE_EPOCH).utc
322
+ default_date = Time.utc(default_date.year, default_date.month, default_date.day)
323
+
324
+ date = date.utc if date.respond_to?(:utc)
325
+
326
+ return "" if date == default_date
327
+
328
+ date.strftime("%Y-%m-%d")
329
+ end
330
+
291
331
  def justify(row, sizes)
292
332
  row.each_with_index.map do |element, index|
293
333
  element.ljust(sizes[index])
@@ -66,6 +66,8 @@ module Bundler
66
66
  opts["force"] = options[:redownload] if options[:redownload]
67
67
 
68
68
  Bundler.settings.set_command_option_if_given :jobs, opts["jobs"]
69
+ Bundler::CLI::Common.validate_cooldown!(options[:cooldown])
70
+ Bundler.settings.set_command_option_if_given :cooldown, options[:cooldown]
69
71
 
70
72
  Bundler.definition.validate_runtime!
71
73
 
data/lib/bundler/cli.rb CHANGED
@@ -61,18 +61,18 @@ module Bundler
61
61
 
62
62
  current_cmd = args.last[:current_command].name
63
63
 
64
- custom_gemfile = options[:gemfile] || Bundler.settings[:gemfile]
65
- if custom_gemfile && !custom_gemfile.empty?
66
- Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", File.expand_path(custom_gemfile)
67
- reset_settings = true
68
- end
69
-
70
- # lock --lockfile works differently than install --lockfile
71
- unless current_cmd == "lock"
72
- custom_lockfile = options[:lockfile] || ENV["BUNDLE_LOCKFILE"] || Bundler.settings[:lockfile]
73
- if custom_lockfile && !custom_lockfile.empty?
74
- Bundler::SharedHelpers.set_env "BUNDLE_LOCKFILE", File.expand_path(custom_lockfile)
75
- reset_settings = true
64
+ # `bundle config` manages stored settings, so avoid promoting settings
65
+ # like `gemfile` or `lockfile` to environment variables before it runs.
66
+ unless current_cmd == "config"
67
+ Bundler.configure_custom_gemfile(options[:gemfile])
68
+
69
+ # lock --lockfile works differently than install --lockfile
70
+ unless current_cmd == "lock"
71
+ custom_lockfile = options[:lockfile] || ENV["BUNDLE_LOCKFILE"] || Bundler.settings[:lockfile]
72
+ if custom_lockfile && !custom_lockfile.empty?
73
+ Bundler::SharedHelpers.set_env "BUNDLE_LOCKFILE", File.expand_path(custom_lockfile)
74
+ reset_settings = true
75
+ end
76
76
  end
77
77
  end
78
78
 
@@ -274,6 +274,7 @@ module Bundler
274
274
  method_option "target-rbconfig", type: :string, banner: "Path to rbconfig.rb for the deployment target platform"
275
275
  method_option "without", type: :array, banner: "Exclude gems that are part of the specified named group (removed)."
276
276
  method_option "with", type: :array, banner: "Include gems that are part of the specified named group (removed)."
277
+ method_option "cooldown", type: :numeric, banner: "Only consider gem versions published at least N days ago. Use 0 to disable."
277
278
  def install
278
279
  %w[clean deployment frozen no-prune path shebang without with].each do |option|
279
280
  remembered_flag_deprecation(option)
@@ -324,6 +325,7 @@ module Bundler
324
325
  method_option "strict", type: :boolean, banner: "Do not allow any gem to be updated past latest --patch | --minor | --major"
325
326
  method_option "conservative", type: :boolean, banner: "Use bundle install conservative update behavior and do not allow shared dependencies to be updated."
326
327
  method_option "all", type: :boolean, banner: "Update everything."
328
+ method_option "cooldown", type: :numeric, banner: "Only consider gem versions published at least N days ago. Use 0 to disable."
327
329
  def update(*gems)
328
330
  require_relative "cli/update"
329
331
  Bundler.settings.temporary(no_install: false) do
@@ -405,6 +407,7 @@ module Bundler
405
407
  method_option "skip-install", type: :boolean, banner: "Adds gem to the Gemfile but does not install it"
406
408
  method_option "optimistic", type: :boolean, banner: "Adds optimistic declaration of version to gem"
407
409
  method_option "strict", type: :boolean, banner: "Adds strict declaration of version to gem"
410
+ method_option "cooldown", type: :numeric, banner: "Only consider gem versions published at least N days ago. Use 0 to disable."
408
411
  def add(*gems)
409
412
  require_relative "cli/add"
410
413
  Add.new(options.dup, gems).run
@@ -435,6 +438,7 @@ module Bundler
435
438
  method_option "filter-patch", type: :boolean, banner: "Only list patch newer versions"
436
439
  method_option "parseable", aliases: "--porcelain", type: :boolean, banner: "Use minimal formatting for more parseable output"
437
440
  method_option "only-explicit", type: :boolean, banner: "Only list gems specified in your Gemfile, not their dependencies"
441
+ method_option "cooldown", type: :numeric, banner: "Only consider gem versions published at least N days ago. Use 0 to disable."
438
442
  def outdated(*gems)
439
443
  require_relative "cli/outdated"
440
444
  Outdated.new(options, gems).run
@@ -71,7 +71,10 @@ module Bundler
71
71
  # This method gets called at least once for every gem when parsing versions.
72
72
  def parse_version_checksum(line, checksums)
73
73
  return unless (name_end = line.index(" ")) # Artifactory bug causes blank lines in artifactor index files
74
- return unless (checksum_start = line.index(" ", name_end + 1) + 1)
74
+ checksum_start = line.index(" ", name_end + 1)
75
+ return unless checksum_start
76
+ checksum_start += 1
77
+
75
78
  checksum_end = line.size - checksum_start
76
79
 
77
80
  line.freeze # allows slicing into the string to not allocate a copy of the line
@@ -783,7 +783,25 @@ module Bundler
783
783
  end
784
784
 
785
785
  def precompute_source_requirements_for_indirect_dependencies?
786
- sources.non_global_rubygems_sources.all?(&:dependency_api_available?)
786
+ if sources.non_global_rubygems_sources.all?(&:dependency_api_available?)
787
+ true
788
+ else
789
+ non_dependency_api_warning
790
+ false
791
+ end
792
+ end
793
+
794
+ def non_dependency_api_warning
795
+ non_api_sources = sources.non_global_rubygems_sources.reject(&:dependency_api_available?)
796
+ non_api_source_names = non_api_sources.map {|d| " * #{d}" }.join("\n")
797
+
798
+ msg = String.new
799
+ msg << "Your Gemfile contains scoped sources that don't implement a dependency API, namely:\n\n"
800
+ msg << non_api_source_names
801
+ msg << "\n\nUsing the above gem servers may result in installing unexpected gems. " \
802
+ "To resolve this warning, make sure you use gem servers that implement dependency APIs, " \
803
+ "such as gemstash or geminabox gem servers."
804
+ Bundler.ui.warn msg
787
805
  end
788
806
 
789
807
  def current_platform_locked?
@@ -1159,16 +1177,20 @@ module Bundler
1159
1177
  def find_source_requirements
1160
1178
  preload_git_sources
1161
1179
 
1180
+ # Only safe to exclude when locked_requirements (merged below) backfills the gap.
1181
+ nothing_changed = nothing_changed?
1182
+ excluded = nothing_changed ? excluded_git_sources : []
1183
+
1162
1184
  # Record the specs available in each gem's source, so that those
1163
1185
  # specs will be available later when the resolver knows where to
1164
1186
  # look for that gemspec (or its dependencies)
1165
1187
  source_requirements = if precompute_source_requirements_for_indirect_dependencies?
1166
- all_requirements = source_map.all_requirements(excluded_git_sources)
1188
+ all_requirements = source_map.all_requirements(excluded)
1167
1189
  { default: default_source }.merge(all_requirements)
1168
1190
  else
1169
- { default: Source::RubygemsAggregate.new(sources, source_map, excluded_git_sources) }.merge(source_map.direct_requirements)
1191
+ { default: Source::RubygemsAggregate.new(sources, source_map, excluded) }.merge(source_map.direct_requirements)
1170
1192
  end
1171
- source_requirements.merge!(source_map.locked_requirements) if nothing_changed?
1193
+ source_requirements.merge!(source_map.locked_requirements) if nothing_changed
1172
1194
  metadata_dependencies.each do |dep|
1173
1195
  source_requirements[dep.name] = sources.metadata_source
1174
1196
  end
data/lib/bundler/dsl.rb CHANGED
@@ -116,6 +116,10 @@ module Bundler
116
116
  options = args.last.is_a?(Hash) ? args.pop.dup : {}
117
117
  options = normalize_hash(options)
118
118
  source = normalize_source(source)
119
+ cooldown = options["cooldown"]
120
+ if cooldown && !(cooldown.is_a?(Integer) && cooldown >= 0)
121
+ raise InvalidOption, "Expected `cooldown` to be a non-negative integer, got #{cooldown.inspect}"
122
+ end
119
123
 
120
124
  if options.key?("type")
121
125
  options["type"] = options["type"].to_s
@@ -130,9 +134,9 @@ module Bundler
130
134
  source_opts = options.merge("uri" => source)
131
135
  with_source(@sources.add_plugin_source(options["type"], source_opts), &blk)
132
136
  elsif block_given?
133
- with_source(@sources.add_rubygems_source("remotes" => source), &blk)
137
+ with_source(@sources.add_rubygems_source("remotes" => source, "cooldown" => cooldown), &blk)
134
138
  else
135
- @sources.add_global_rubygems_remote(source)
139
+ @sources.add_global_rubygems_remote(source, cooldown: cooldown)
136
140
  end
137
141
  end
138
142
 
@@ -5,7 +5,7 @@ module Bundler
5
5
  class EndpointSpecification < Gem::Specification
6
6
  include MatchRemoteMetadata
7
7
 
8
- attr_reader :name, :version, :platform, :checksum
8
+ attr_reader :name, :version, :platform, :checksum, :created_at
9
9
  attr_writer :dependencies
10
10
  attr_accessor :remote, :locked_platform
11
11
 
@@ -145,6 +145,7 @@ module Bundler
145
145
  unless data
146
146
  @required_ruby_version = nil
147
147
  @required_rubygems_version = nil
148
+ @created_at = nil
148
149
  return
149
150
  end
150
151
 
@@ -161,6 +162,15 @@ module Bundler
161
162
  @required_rubygems_version = Gem::Requirement.new(v)
162
163
  when "ruby"
163
164
  @required_ruby_version = Gem::Requirement.new(v)
165
+ when "created_at"
166
+ value = v.is_a?(Array) ? v.last : v
167
+ if value.is_a?(String)
168
+ @created_at = begin
169
+ Time.new(value)
170
+ rescue ArgumentError
171
+ nil
172
+ end
173
+ end
164
174
  end
165
175
  end
166
176
  rescue StandardError => e
@@ -63,6 +63,11 @@ module Bundler
63
63
  Bundler.create_bundle_path
64
64
 
65
65
  ProcessLock.lock do
66
+ # Invalidate any stale gem specification cache from before we acquired the lock.
67
+ # Another process may have installed gems while we were waiting.
68
+ Gem::Specification.reset
69
+ @definition.sources.clear_cache
70
+
66
71
  @definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment])
67
72
 
68
73
  if @definition.dependencies.empty?
@@ -115,6 +115,17 @@ module Bundler
115
115
  "Run `git checkout HEAD -- #{@lockfile_path}` first to get a clean lock."
116
116
  end
117
117
 
118
+ @valid = lockfile.strip.empty? ||
119
+ lockfile.split(/(?:\r?\n)+/).any? {|l| KNOWN_SECTIONS.include?(l) }
120
+
121
+ unless @valid
122
+ SharedHelpers.feature_deprecated!(
123
+ "Your #{@lockfile_path} does not appear to be a valid lockfile. " \
124
+ "Run `rm #{@lockfile_path}` and then `bundle install` to generate a new lockfile. " \
125
+ "This will raise a LockfileError in a future version of Bundler."
126
+ )
127
+ end
128
+
118
129
  lockfile.split(/((?:\r?\n)+)/) do |line|
119
130
  # split alternates between the line and the following whitespace
120
131
  next @pos.advance!(line) if line.match?(/^\s*$/)
@@ -164,6 +175,10 @@ module Bundler
164
175
  bundler_version.nil? || bundler_version < Gem::Version.new("1.16.2")
165
176
  end
166
177
 
178
+ def valid?
179
+ @valid
180
+ end
181
+
167
182
  private
168
183
 
169
184
  TYPES = {
@@ -4,7 +4,7 @@
4
4
  .SH "NAME"
5
5
  \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
6
6
  .SH "SYNOPSIS"
7
- \fBbundle add\fR \fIGEM_NAME\fR [\-\-group=GROUP] [\-\-version=VERSION] [\-\-source=SOURCE] [\-\-path=PATH] [\-\-git=GIT|\-\-github=GITHUB] [\-\-branch=BRANCH] [\-\-ref=REF] [\-\-quiet] [\-\-skip\-install] [\-\-strict|\-\-optimistic]
7
+ \fBbundle add\fR \fIGEM_NAME\fR [\-\-group=GROUP] [\-\-version=VERSION] [\-\-source=SOURCE] [\-\-path=PATH] [\-\-git=GIT|\-\-github=GITHUB] [\-\-branch=BRANCH] [\-\-ref=REF] [\-\-cooldown=NUMBER] [\-\-quiet] [\-\-skip\-install] [\-\-strict|\-\-optimistic]
8
8
  .SH "DESCRIPTION"
9
9
  Adds the named gem to the [\fBGemfile(5)\fR][Gemfile(5)] and run \fBbundle install\fR\. \fBbundle install\fR can be avoided by using the flag \fB\-\-skip\-install\fR\.
10
10
  .SH "OPTIONS"
@@ -50,6 +50,9 @@ Adds optimistic declaration of version\.
50
50
  .TP
51
51
  \fB\-\-strict\fR
52
52
  Adds strict declaration of version\.
53
+ .TP
54
+ \fB\-\-cooldown=<number>\fR
55
+ Only consider gem versions published at least \fInumber\fR days ago when resolving\. Pass \fB0\fR to disable cooldown for this run\. See \fBcooldown\fR in bundle\-config(1) for precedence rules\.
53
56
  .SH "EXAMPLES"
54
57
  .IP "1." 4
55
58
  You can add the \fBrails\fR gem to the Gemfile without any version restriction\. The source of the gem will be the global source\.
@@ -5,7 +5,7 @@ bundle-add(1) -- Add gem to the Gemfile and run bundle install
5
5
 
6
6
  `bundle add` <GEM_NAME> [--group=GROUP] [--version=VERSION] [--source=SOURCE]
7
7
  [--path=PATH] [--git=GIT|--github=GITHUB] [--branch=BRANCH] [--ref=REF]
8
- [--quiet] [--skip-install] [--strict|--optimistic]
8
+ [--cooldown=NUMBER] [--quiet] [--skip-install] [--strict|--optimistic]
9
9
 
10
10
  ## DESCRIPTION
11
11
 
@@ -56,6 +56,11 @@ Adds the named gem to the [`Gemfile(5)`][Gemfile(5)] and run `bundle install`.
56
56
  * `--strict`:
57
57
  Adds strict declaration of version.
58
58
 
59
+ * `--cooldown=<number>`:
60
+ Only consider gem versions published at least <number> days ago when
61
+ resolving. Pass `0` to disable cooldown for this run. See `cooldown`
62
+ in bundle-config(1) for precedence rules.
63
+
59
64
  ## EXAMPLES
60
65
 
61
66
  1. You can add the `rails` gem to the Gemfile without any version restriction.