bundler 4.0.12 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94fc49b469e2eb2c15c70f7bb43e4503f0de0962380b5b6eea5909bff3a08d1e
4
- data.tar.gz: 301b0eb9cb089ba4fda55fcbcd1ad1e65c608c35107906a415546245d58d1368
3
+ metadata.gz: 6aecb16228f32866a007c26b7a70fd787bcf81d42ee002004ba3ec2dd2625694
4
+ data.tar.gz: 5bce03c60cbf8034dfc540848298fbe3d8958314dc8513b61c0e8238f180f096
5
5
  SHA512:
6
- metadata.gz: ca630b85c261a32145258e2264627f9beca9c45c72cc21ad195a72774d28808fbe57a9b6242af937ac2ee85d636f0f7f73278c97aeae7cf8a7b1de58f7480f50
7
- data.tar.gz: 40329f0aa226b3e314c740e765ae8d22e298666fcf05454bb9b1788639e4ef1b8bea18cb74f2da33245b0faefcd2dac70175169067f375841decc36bd01523d7
6
+ metadata.gz: 4500a906181c0c43b1384fd9dda403dcc00ec11466911c156b01b309f2886336e756057af742396786ad2a0111e1a650729ad7bc03d09d04b0984a3770d4ebf4
7
+ data.tar.gz: 11e96f5ebdeca17df80db3506f010fd190b35c12cc8fd82532f6eeea9b51aa7b113a353c1cf88df215846c0226696a672813a79bf06202a3e5ffd7b543b0805a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
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
+
3
19
  ## 4.0.12 / 2026-05-20
4
20
 
5
21
  ### Enhancements:
@@ -5,7 +5,7 @@ module Bundler
5
5
  module BuildMetadata
6
6
  # begin ivars
7
7
  @built_at = nil
8
- @git_commit_sha = "665f998196".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|
@@ -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
@@ -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
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?
@@ -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.
@@ -69,162 +69,126 @@ The canonical form of this configuration is \fB"without"\fR\. To convert the can
69
69
  Any periods in the configuration keys must be replaced with two underscores when setting it via environment variables\. The configuration key \fBlocal\.rack\fR becomes the environment variable \fBBUNDLE_LOCAL__RACK\fR\.
70
70
  .SH "LIST OF AVAILABLE KEYS"
71
71
  The following is a list of all configuration keys and their purpose\. You can learn more about their operation in bundle install(1) \fIbundle\-install\.1\.html\fR\.
72
- .TP
73
- \fBapi_request_size\fR (\fBBUNDLE_API_REQUEST_SIZE\fR)
74
- Configure how many dependencies to fetch when resolving the specifications\. This configuration is only used when fetchig specifications from RubyGems servers that didn't implement the Compact Index API\. Defaults to 100\.
75
- .TP
76
- \fBauto_install\fR (\fBBUNDLE_AUTO_INSTALL\fR)
77
- Automatically run \fBbundle install\fR when gems are missing\.
78
- .TP
79
- \fBbin\fR (\fBBUNDLE_BIN\fR)
80
- If configured, \fBbundle binstubs\fR will install executables from gems in the bundle to the specified directory\. Otherwise it will create them in a \fBbin\fR directory relative to the Gemfile directory\. These executables run in Bundler's context\. If used, you might add this directory to your environment's \fBPATH\fR variable\. For instance, if the \fBrails\fR gem comes with a \fBrails\fR executable, \fBbundle binstubs\fR will create a \fBbin/rails\fR executable that ensures that all referred dependencies will be resolved using the bundled gems\.
81
- .TP
82
- \fBcache_all\fR (\fBBUNDLE_CACHE_ALL\fR)
83
- Cache all gems, including path and git gems\. This needs to be explicitly before bundler 4, but will be the default on bundler 4\.
84
- .TP
85
- \fBcache_all_platforms\fR (\fBBUNDLE_CACHE_ALL_PLATFORMS\fR)
86
- Cache gems for all platforms\.
87
- .TP
88
- \fBcache_path\fR (\fBBUNDLE_CACHE_PATH\fR)
89
- The directory that bundler will place cached gems in when running \fBbundle package\fR, and that bundler will look in when installing gems\. Defaults to \fBvendor/cache\fR\.
90
- .TP
91
- \fBclean\fR (\fBBUNDLE_CLEAN\fR)
92
- Whether Bundler should run \fBbundle clean\fR automatically after \fBbundle install\fR\. Defaults to \fBtrue\fR in Bundler 4, as long as \fBpath\fR is not explicitly configured\.
93
- .TP
94
- \fBconsole\fR (\fBBUNDLE_CONSOLE\fR)
95
- The console that \fBbundle console\fR starts\. Defaults to \fBirb\fR\.
96
- .TP
97
- \fBdefault_cli_command\fR (\fBBUNDLE_DEFAULT_CLI_COMMAND\fR)
98
- The command that running \fBbundle\fR without arguments should run\. Defaults to \fBcli_help\fR since Bundler 4, but can also be \fBinstall\fR which was the previous default\.
99
- .TP
100
- \fBdeployment\fR (\fBBUNDLE_DEPLOYMENT\fR)
101
- Equivalent to setting \fBfrozen\fR to \fBtrue\fR and \fBpath\fR to \fBvendor/bundle\fR\.
102
- .TP
103
- \fBdisable_checksum_validation\fR (\fBBUNDLE_DISABLE_CHECKSUM_VALIDATION\fR)
104
- Allow installing gems even if they do not match the checksum provided by RubyGems\.
105
- .TP
106
- \fBdisable_exec_load\fR (\fBBUNDLE_DISABLE_EXEC_LOAD\fR)
107
- Stop Bundler from using \fBload\fR to launch an executable in\-process in \fBbundle exec\fR\.
108
- .TP
109
- \fBdisable_local_branch_check\fR (\fBBUNDLE_DISABLE_LOCAL_BRANCH_CHECK\fR)
110
- Allow Bundler to use a local git override without a branch specified in the Gemfile\.
111
- .TP
112
- \fBdisable_local_revision_check\fR (\fBBUNDLE_DISABLE_LOCAL_REVISION_CHECK\fR)
113
- Allow Bundler to use a local git override without checking if the revision present in the lockfile is present in the repository\.
114
- .TP
115
- \fBdisable_shared_gems\fR (\fBBUNDLE_DISABLE_SHARED_GEMS\fR)
116
- Stop Bundler from accessing gems installed to RubyGems' normal location\.
117
- .TP
118
- \fBdisable_version_check\fR (\fBBUNDLE_DISABLE_VERSION_CHECK\fR)
119
- Stop Bundler from checking if a newer Bundler version is available on rubygems\.org\.
120
- .TP
121
- \fBforce_ruby_platform\fR (\fBBUNDLE_FORCE_RUBY_PLATFORM\fR)
122
- Ignore the current machine's platform and install only \fBruby\fR platform gems\. As a result, gems with native extensions will be compiled from source\.
123
- .TP
124
- \fBfrozen\fR (\fBBUNDLE_FROZEN\fR)
125
- Disallow any automatic changes to \fBGemfile\.lock\fR\. Bundler commands will be blocked unless the lockfile can be installed exactly as written\. Usually this will happen when changing the \fBGemfile\fR manually and forgetting to update the lockfile through \fBbundle lock\fR or \fBbundle install\fR\.
126
- .TP
127
- \fBgem\.github_username\fR (\fBBUNDLE_GEM__GITHUB_USERNAME\fR)
128
- Sets a GitHub username or organization to be used in the \fBREADME\fR and \fB\.gemspec\fR files when you create a new gem via \fBbundle gem\fR command\. It can be overridden by passing an explicit \fB\-\-github\-username\fR flag to \fBbundle gem\fR\.
129
- .TP
130
- \fBgem\.push_key\fR (\fBBUNDLE_GEM__PUSH_KEY\fR)
131
- Sets the \fB\-\-key\fR parameter for \fBgem push\fR when using the \fBrake release\fR command with a private gemstash server\.
132
- .TP
133
- \fBgemfile\fR (\fBBUNDLE_GEMFILE\fR)
134
- The name of the file that bundler should use as the \fBGemfile\fR\. This location of this file also sets the root of the project, which is used to resolve relative paths in the \fBGemfile\fR, among other things\. By default, bundler will search up from the current working directory until it finds a \fBGemfile\fR\.
135
- .TP
136
- \fBglobal_gem_cache\fR (\fBBUNDLE_GLOBAL_GEM_CACHE\fR)
137
- Whether Bundler should cache all gems and compiled extensions globally, rather than locally to the configured installation path\.
138
- .TP
139
- \fBignore_funding_requests\fR (\fBBUNDLE_IGNORE_FUNDING_REQUESTS\fR)
140
- When set, no funding requests will be printed\.
141
- .TP
142
- \fBignore_messages\fR (\fBBUNDLE_IGNORE_MESSAGES\fR)
143
- When set, no post install messages will be printed\. To silence a single gem, use dot notation like \fBignore_messages\.httparty true\fR\.
144
- .TP
145
- \fBinit_gems_rb\fR (\fBBUNDLE_INIT_GEMS_RB\fR)
146
- Generate a \fBgems\.rb\fR instead of a \fBGemfile\fR when running \fBbundle init\fR\.
147
- .TP
148
- \fBjobs\fR (\fBBUNDLE_JOBS\fR)
149
- The number of gems Bundler can download and install in parallel\. Defaults to the number of available processors\.
150
- .TP
151
- \fBlockfile\fR (\fBBUNDLE_LOCKFILE\fR)
152
- The path to the lockfile that bundler should use\. By default, Bundler adds \fB\.lock\fR to the end of the \fBgemfile\fR entry\. Can be set to \fBfalse\fR in the Gemfile to disable lockfile creation entirely (see gemfile(5))\.
153
- .TP
154
- \fBlockfile_checksums\fR (\fBBUNDLE_LOCKFILE_CHECKSUMS\fR)
155
- Whether Bundler should include a checksums section in new lockfiles, to protect from compromised gem sources\. Defaults to true\.
156
- .TP
157
- \fBno_install\fR (\fBBUNDLE_NO_INSTALL\fR)
158
- Whether \fBbundle package\fR should skip installing gems\.
159
- .TP
160
- \fBno_prune\fR (\fBBUNDLE_NO_PRUNE\fR)
161
- Whether Bundler should leave outdated gems unpruned when caching\.
162
- .TP
163
- \fBonly\fR (\fBBUNDLE_ONLY\fR)
164
- A space\-separated list of groups to install only gems of the specified groups\. Please check carefully if you want to install also gems without a group, because they get put inside \fBdefault\fR group\. For example \fBonly test:default\fR will install all gems specified in test group and without one\.
165
- .TP
166
- \fBpath\fR (\fBBUNDLE_PATH\fR)
167
- The location on disk where all gems in your bundle will be located regardless of \fB$GEM_HOME\fR or \fB$GEM_PATH\fR values\. Bundle gems not found in this location will be installed by \fBbundle install\fR\. When not set, Bundler install by default to a \fB\.bundle\fR directory relative to repository root in Bundler 4, and to the default system path (\fBGem\.dir\fR) before Bundler 4\. That means that before Bundler 4, Bundler shares this location with Rubygems, and \fBgem install \|\.\|\.\|\.\fR will have gems installed in the same location and therefore, gems installed without \fBpath\fR set will show up by calling \fBgem list\fR\. This will not be the case in Bundler 4\.
168
- .TP
169
- \fBpath\.system\fR (\fBBUNDLE_PATH__SYSTEM\fR)
170
- Whether Bundler will install gems into the default system path (\fBGem\.dir\fR)\.
171
- .TP
172
- \fBplugins\fR (\fBBUNDLE_PLUGINS\fR)
173
- Enable Bundler's experimental plugin system\.
174
- .TP
175
- \fBprefer_patch\fR (\fBBUNDLE_PREFER_PATCH\fR)
176
- Prefer updating only to next patch version during updates\. Makes \fBbundle update\fR calls equivalent to \fBbundler update \-\-patch\fR\.
177
- .TP
178
- \fBredirect\fR (\fBBUNDLE_REDIRECT\fR)
179
- The number of redirects allowed for network requests\. Defaults to \fB5\fR\.
180
- .TP
181
- \fBretry\fR (\fBBUNDLE_RETRY\fR)
182
- The number of times to retry failed network requests\. Defaults to \fB3\fR\.
183
- .TP
184
- \fBshebang\fR (\fBBUNDLE_SHEBANG\fR)
185
- The program name that should be invoked for generated binstubs\. Defaults to the ruby install name used to generate the binstub\.
186
- .TP
187
- \fBsilence_deprecations\fR (\fBBUNDLE_SILENCE_DEPRECATIONS\fR)
188
- Whether Bundler should silence deprecation warnings for behavior that will be changed in the next major version\.
189
- .TP
190
- \fBsilence_root_warning\fR (\fBBUNDLE_SILENCE_ROOT_WARNING\fR)
191
- Silence the warning Bundler prints when installing gems as root\.
192
- .TP
193
- \fBsimulate_version\fR (\fBBUNDLE_SIMULATE_VERSION\fR)
194
- The virtual version Bundler should use for activating feature flags\. Can be used to simulate all the new functionality that will be enabled in a future major version\.
195
- .TP
196
- \fBssl_ca_cert\fR (\fBBUNDLE_SSL_CA_CERT\fR)
197
- Path to a designated CA certificate file or folder containing multiple certificates for trusted CAs in PEM format\.
198
- .TP
199
- \fBssl_client_cert\fR (\fBBUNDLE_SSL_CLIENT_CERT\fR)
200
- Path to a designated file containing a X\.509 client certificate and key in PEM format\.
201
- .TP
202
- \fBssl_verify_mode\fR (\fBBUNDLE_SSL_VERIFY_MODE\fR)
203
- The SSL verification mode Bundler uses when making HTTPS requests\. Defaults to verify peer\.
204
- .TP
205
- \fBsystem_bindir\fR (\fBBUNDLE_SYSTEM_BINDIR\fR)
206
- The location where RubyGems installs binstubs\. Defaults to \fBGem\.bindir\fR\.
207
- .TP
208
- \fBtimeout\fR (\fBBUNDLE_TIMEOUT\fR)
209
- The seconds allowed before timing out for network requests\. Defaults to \fB10\fR\.
210
- .TP
211
- \fBupdate_requires_all_flag\fR (\fBBUNDLE_UPDATE_REQUIRES_ALL_FLAG\fR)
212
- Require passing \fB\-\-all\fR to \fBbundle update\fR when everything should be updated, and disallow passing no options to \fBbundle update\fR\.
213
- .TP
214
- \fBuser_agent\fR (\fBBUNDLE_USER_AGENT\fR)
215
- The custom user agent fragment Bundler includes in API requests\.
216
- .TP
217
- \fBverbose\fR (\fBBUNDLE_VERBOSE\fR)
218
- Whether Bundler should print verbose output\. Defaults to \fBfalse\fR, unless the \fB\-\-verbose\fR CLI flag is used\.
219
- .TP
220
- \fBversion\fR (\fBBUNDLE_VERSION\fR)
221
- The version of Bundler to use when running under Bundler environment\. Defaults to \fBlockfile\fR\. You can also specify \fBsystem\fR or \fBx\.y\.z\fR\. \fBlockfile\fR will use the Bundler version specified in the \fBGemfile\.lock\fR, \fBsystem\fR will use the system version of Bundler, and \fBx\.y\.z\fR will use the specified version of Bundler\.
222
- .TP
223
- \fBwith\fR (\fBBUNDLE_WITH\fR)
224
- A space\-separated or \fB:\fR\-separated list of groups whose gems bundler should install\.
225
- .TP
226
- \fBwithout\fR (\fBBUNDLE_WITHOUT\fR)
227
- A space\-separated or \fB:\fR\-separated list of groups whose gems bundler should not install\.
72
+ .IP "\(bu" 4
73
+ \fBapi_request_size\fR (\fBBUNDLE_API_REQUEST_SIZE\fR): Configure how many dependencies to fetch when resolving the specifications\. This configuration is only used when fetchig specifications from RubyGems servers that didn't implement the Compact Index API\. Defaults to 100\.
74
+ .IP "\(bu" 4
75
+ \fBauto_install\fR (\fBBUNDLE_AUTO_INSTALL\fR): Automatically run \fBbundle install\fR when gems are missing\.
76
+ .IP "\(bu" 4
77
+ \fBbin\fR (\fBBUNDLE_BIN\fR): If configured, \fBbundle binstubs\fR will install executables from gems in the bundle to the specified directory\. Otherwise it will create them in a \fBbin\fR directory relative to the Gemfile directory\. These executables run in Bundler's context\. If used, you might add this directory to your environment's \fBPATH\fR variable\. For instance, if the \fBrails\fR gem comes with a \fBrails\fR executable, \fBbundle binstubs\fR will create a \fBbin/rails\fR executable that ensures that all referred dependencies will be resolved using the bundled gems\.
78
+ .IP "\(bu" 4
79
+ \fBcache_all\fR (\fBBUNDLE_CACHE_ALL\fR): Cache all gems, including path and git gems\. This needs to be explicitly before bundler 4, but will be the default on bundler 4\.
80
+ .IP "\(bu" 4
81
+ \fBcache_all_platforms\fR (\fBBUNDLE_CACHE_ALL_PLATFORMS\fR): Cache gems for all platforms\.
82
+ .IP "\(bu" 4
83
+ \fBcache_path\fR (\fBBUNDLE_CACHE_PATH\fR): The directory that bundler will place cached gems in when running \fBbundle package\fR, and that bundler will look in when installing gems\. Defaults to \fBvendor/cache\fR\.
84
+ .IP "\(bu" 4
85
+ \fBclean\fR (\fBBUNDLE_CLEAN\fR): Whether Bundler should run \fBbundle clean\fR automatically after \fBbundle install\fR\. Defaults to \fBtrue\fR in Bundler 4, as long as \fBpath\fR is not explicitly configured\.
86
+ .IP "\(bu" 4
87
+ \fBconsole\fR (\fBBUNDLE_CONSOLE\fR): The console that \fBbundle console\fR starts\. Defaults to \fBirb\fR\.
88
+ .IP "\(bu" 4
89
+ \fBcooldown\fR (\fBBUNDLE_COOLDOWN\fR): Number of days a published gem version must age before bundler will resolve to it\. Defaults to unset (no cooldown)\. Pass \fB0\fR to disable cooldown for an individual run\.
90
+ .IP
91
+ The effective cooldown for any given gem is resolved from three layers, highest precedence first:
92
+ .IP "1." 4
93
+ CLI flag \fB\-\-cooldown N\fR on \fBinstall\fR, \fBupdate\fR, \fBadd\fR, and \fBoutdated\fR\.
94
+ .IP "2." 4
95
+ This setting (\fBbundle config set cooldown N\fR or \fBBUNDLE_COOLDOWN=N\fR)\.
96
+ .IP "3." 4
97
+ The per\-source \fBcooldown:\fR keyword in the Gemfile, such as \fBsource "https://rubygems\.org", cooldown: 7\fR\.
98
+ .IP "" 0
99
+ .IP
100
+ The CLI flag and this setting apply uniformly to every source, including ones declared with their own \fBcooldown:\fR value\. To keep a private registry permanently exempt while still cooling down public gems, declare \fBsource "https://internal", cooldown: 0\fR in the Gemfile; remember that \fB\-\-cooldown N\fR on the command line will still override it for that single run\.
101
+ .IP
102
+ Cooldown filtering depends on the gem server providing a per\-version \fBcreated_at\fR timestamp in the v2 compact\-index format\. Versions without that metadata \- older gem servers, historical entries that predate the v2 cutover on \fBrubygems\.org\fR, or private registries that still emit the v1 format \- are treated as outside the cooldown window and remain resolvable\. If you rely on cooldown for supply\-chain protection, confirm that the gem server emits \fBcreated_at\fR in its \fB/info/<gem>\fR responses\.
103
+ .IP "\(bu" 4
104
+ \fBdefault_cli_command\fR (\fBBUNDLE_DEFAULT_CLI_COMMAND\fR): The command that running \fBbundle\fR without arguments should run\. Defaults to \fBcli_help\fR since Bundler 4, but can also be \fBinstall\fR which was the previous default\.
105
+ .IP "\(bu" 4
106
+ \fBdeployment\fR (\fBBUNDLE_DEPLOYMENT\fR): Equivalent to setting \fBfrozen\fR to \fBtrue\fR and \fBpath\fR to \fBvendor/bundle\fR\.
107
+ .IP "\(bu" 4
108
+ \fBdisable_checksum_validation\fR (\fBBUNDLE_DISABLE_CHECKSUM_VALIDATION\fR): Allow installing gems even if they do not match the checksum provided by RubyGems\.
109
+ .IP "\(bu" 4
110
+ \fBdisable_exec_load\fR (\fBBUNDLE_DISABLE_EXEC_LOAD\fR): Stop Bundler from using \fBload\fR to launch an executable in\-process in \fBbundle exec\fR\.
111
+ .IP "\(bu" 4
112
+ \fBdisable_local_branch_check\fR (\fBBUNDLE_DISABLE_LOCAL_BRANCH_CHECK\fR): Allow Bundler to use a local git override without a branch specified in the Gemfile\.
113
+ .IP "\(bu" 4
114
+ \fBdisable_local_revision_check\fR (\fBBUNDLE_DISABLE_LOCAL_REVISION_CHECK\fR): Allow Bundler to use a local git override without checking if the revision present in the lockfile is present in the repository\.
115
+ .IP "\(bu" 4
116
+ \fBdisable_shared_gems\fR (\fBBUNDLE_DISABLE_SHARED_GEMS\fR): Stop Bundler from accessing gems installed to RubyGems' normal location\.
117
+ .IP "\(bu" 4
118
+ \fBdisable_version_check\fR (\fBBUNDLE_DISABLE_VERSION_CHECK\fR): Stop Bundler from checking if a newer Bundler version is available on rubygems\.org\.
119
+ .IP "\(bu" 4
120
+ \fBforce_ruby_platform\fR (\fBBUNDLE_FORCE_RUBY_PLATFORM\fR): Ignore the current machine's platform and install only \fBruby\fR platform gems\. As a result, gems with native extensions will be compiled from source\.
121
+ .IP "\(bu" 4
122
+ \fBfrozen\fR (\fBBUNDLE_FROZEN\fR): Disallow any automatic changes to \fBGemfile\.lock\fR\. Bundler commands will be blocked unless the lockfile can be installed exactly as written\. Usually this will happen when changing the \fBGemfile\fR manually and forgetting to update the lockfile through \fBbundle lock\fR or \fBbundle install\fR\.
123
+ .IP "\(bu" 4
124
+ \fBgem\.github_username\fR (\fBBUNDLE_GEM__GITHUB_USERNAME\fR): Sets a GitHub username or organization to be used in the \fBREADME\fR and \fB\.gemspec\fR files when you create a new gem via \fBbundle gem\fR command\. It can be overridden by passing an explicit \fB\-\-github\-username\fR flag to \fBbundle gem\fR\.
125
+ .IP "\(bu" 4
126
+ \fBgem\.push_key\fR (\fBBUNDLE_GEM__PUSH_KEY\fR): Sets the \fB\-\-key\fR parameter for \fBgem push\fR when using the \fBrake release\fR command with a private gemstash server\.
127
+ .IP "\(bu" 4
128
+ \fBgemfile\fR (\fBBUNDLE_GEMFILE\fR): The name of the file that bundler should use as the \fBGemfile\fR\. This location of this file also sets the root of the project, which is used to resolve relative paths in the \fBGemfile\fR, among other things\. By default, bundler will search up from the current working directory until it finds a \fBGemfile\fR\.
129
+ .IP "\(bu" 4
130
+ \fBglobal_gem_cache\fR (\fBBUNDLE_GLOBAL_GEM_CACHE\fR): Whether Bundler should cache all gems and compiled extensions globally, rather than locally to the configured installation path\.
131
+ .IP "\(bu" 4
132
+ \fBignore_funding_requests\fR (\fBBUNDLE_IGNORE_FUNDING_REQUESTS\fR): When set, no funding requests will be printed\.
133
+ .IP "\(bu" 4
134
+ \fBignore_messages\fR (\fBBUNDLE_IGNORE_MESSAGES\fR): When set, no post install messages will be printed\. To silence a single gem, use dot notation like \fBignore_messages\.httparty true\fR\.
135
+ .IP "\(bu" 4
136
+ \fBinit_gems_rb\fR (\fBBUNDLE_INIT_GEMS_RB\fR): Generate a \fBgems\.rb\fR instead of a \fBGemfile\fR when running \fBbundle init\fR\.
137
+ .IP "\(bu" 4
138
+ \fBjobs\fR (\fBBUNDLE_JOBS\fR): The number of gems Bundler can download and install in parallel\. Defaults to the number of available processors\.
139
+ .IP "\(bu" 4
140
+ \fBlockfile\fR (\fBBUNDLE_LOCKFILE\fR): The path to the lockfile that bundler should use\. By default, Bundler adds \fB\.lock\fR to the end of the \fBgemfile\fR entry\. Can be set to \fBfalse\fR in the Gemfile to disable lockfile creation entirely (see gemfile(5))\.
141
+ .IP "\(bu" 4
142
+ \fBlockfile_checksums\fR (\fBBUNDLE_LOCKFILE_CHECKSUMS\fR): Whether Bundler should include a checksums section in new lockfiles, to protect from compromised gem sources\. Defaults to true\.
143
+ .IP "\(bu" 4
144
+ \fBno_install\fR (\fBBUNDLE_NO_INSTALL\fR): Whether \fBbundle package\fR should skip installing gems\.
145
+ .IP "\(bu" 4
146
+ \fBno_prune\fR (\fBBUNDLE_NO_PRUNE\fR): Whether Bundler should leave outdated gems unpruned when caching\.
147
+ .IP "\(bu" 4
148
+ \fBonly\fR (\fBBUNDLE_ONLY\fR): A space\-separated list of groups to install only gems of the specified groups\. Please check carefully if you want to install also gems without a group, because they get put inside \fBdefault\fR group\. For example \fBonly test:default\fR will install all gems specified in test group and without one\.
149
+ .IP "\(bu" 4
150
+ \fBpath\fR (\fBBUNDLE_PATH\fR): The location on disk where all gems in your bundle will be located regardless of \fB$GEM_HOME\fR or \fB$GEM_PATH\fR values\. Bundle gems not found in this location will be installed by \fBbundle install\fR\. When not set, Bundler install by default to a \fB\.bundle\fR directory relative to repository root in Bundler 4, and to the default system path (\fBGem\.dir\fR) before Bundler 4\. That means that before Bundler 4, Bundler shares this location with Rubygems, and \fBgem install \|\.\|\.\|\.\fR will have gems installed in the same location and therefore, gems installed without \fBpath\fR set will show up by calling \fBgem list\fR\. This will not be the case in Bundler 4\.
151
+ .IP "\(bu" 4
152
+ \fBpath\.system\fR (\fBBUNDLE_PATH__SYSTEM\fR): Whether Bundler will install gems into the default system path (\fBGem\.dir\fR)\.
153
+ .IP "\(bu" 4
154
+ \fBplugins\fR (\fBBUNDLE_PLUGINS\fR): Enable Bundler's experimental plugin system\.
155
+ .IP "\(bu" 4
156
+ \fBprefer_patch\fR (\fBBUNDLE_PREFER_PATCH\fR): Prefer updating only to next patch version during updates\. Makes \fBbundle update\fR calls equivalent to \fBbundler update \-\-patch\fR\.
157
+ .IP "\(bu" 4
158
+ \fBredirect\fR (\fBBUNDLE_REDIRECT\fR): The number of redirects allowed for network requests\. Defaults to \fB5\fR\.
159
+ .IP "\(bu" 4
160
+ \fBretry\fR (\fBBUNDLE_RETRY\fR): The number of times to retry failed network requests\. Defaults to \fB3\fR\.
161
+ .IP "\(bu" 4
162
+ \fBshebang\fR (\fBBUNDLE_SHEBANG\fR): The program name that should be invoked for generated binstubs\. Defaults to the ruby install name used to generate the binstub\.
163
+ .IP "\(bu" 4
164
+ \fBsilence_deprecations\fR (\fBBUNDLE_SILENCE_DEPRECATIONS\fR): Whether Bundler should silence deprecation warnings for behavior that will be changed in the next major version\.
165
+ .IP "\(bu" 4
166
+ \fBsilence_root_warning\fR (\fBBUNDLE_SILENCE_ROOT_WARNING\fR): Silence the warning Bundler prints when installing gems as root\.
167
+ .IP "\(bu" 4
168
+ \fBsimulate_version\fR (\fBBUNDLE_SIMULATE_VERSION\fR): The virtual version Bundler should use for activating feature flags\. Can be used to simulate all the new functionality that will be enabled in a future major version\.
169
+ .IP "\(bu" 4
170
+ \fBssl_ca_cert\fR (\fBBUNDLE_SSL_CA_CERT\fR): Path to a designated CA certificate file or folder containing multiple certificates for trusted CAs in PEM format\.
171
+ .IP "\(bu" 4
172
+ \fBssl_client_cert\fR (\fBBUNDLE_SSL_CLIENT_CERT\fR): Path to a designated file containing a X\.509 client certificate and key in PEM format\.
173
+ .IP "\(bu" 4
174
+ \fBssl_verify_mode\fR (\fBBUNDLE_SSL_VERIFY_MODE\fR): The SSL verification mode Bundler uses when making HTTPS requests\. Defaults to verify peer\.
175
+ .IP "\(bu" 4
176
+ \fBsystem_bindir\fR (\fBBUNDLE_SYSTEM_BINDIR\fR): The location where RubyGems installs binstubs\. Defaults to \fBGem\.bindir\fR\.
177
+ .IP "\(bu" 4
178
+ \fBtimeout\fR (\fBBUNDLE_TIMEOUT\fR): The seconds allowed before timing out for network requests\. Defaults to \fB10\fR\.
179
+ .IP "\(bu" 4
180
+ \fBupdate_requires_all_flag\fR (\fBBUNDLE_UPDATE_REQUIRES_ALL_FLAG\fR): Require passing \fB\-\-all\fR to \fBbundle update\fR when everything should be updated, and disallow passing no options to \fBbundle update\fR\.
181
+ .IP "\(bu" 4
182
+ \fBuser_agent\fR (\fBBUNDLE_USER_AGENT\fR): The custom user agent fragment Bundler includes in API requests\.
183
+ .IP "\(bu" 4
184
+ \fBverbose\fR (\fBBUNDLE_VERBOSE\fR): Whether Bundler should print verbose output\. Defaults to \fBfalse\fR, unless the \fB\-\-verbose\fR CLI flag is used\.
185
+ .IP "\(bu" 4
186
+ \fBversion\fR (\fBBUNDLE_VERSION\fR): The version of Bundler to use when running under Bundler environment\. Defaults to \fBlockfile\fR\. You can also specify \fBsystem\fR or \fBx\.y\.z\fR\. \fBlockfile\fR will use the Bundler version specified in the \fBGemfile\.lock\fR, \fBsystem\fR will use the system version of Bundler, and \fBx\.y\.z\fR will use the specified version of Bundler\.
187
+ .IP "\(bu" 4
188
+ \fBwith\fR (\fBBUNDLE_WITH\fR): A space\-separated or \fB:\fR\-separated list of groups whose gems bundler should install\.
189
+ .IP "\(bu" 4
190
+ \fBwithout\fR (\fBBUNDLE_WITHOUT\fR): A space\-separated or \fB:\fR\-separated list of groups whose gems bundler should not install\.
191
+ .IP "" 0
228
192
  .SH "BUILD OPTIONS"
229
193
  You can use \fBbundle config\fR to give Bundler the flags to pass to the gem installer every time bundler tries to install a particular gem\.
230
194
  .P
@@ -137,6 +137,36 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
137
137
  explicitly configured.
138
138
  * `console` (`BUNDLE_CONSOLE`):
139
139
  The console that `bundle console` starts. Defaults to `irb`.
140
+ * `cooldown` (`BUNDLE_COOLDOWN`):
141
+ Number of days a published gem version must age before bundler will
142
+ resolve to it. Defaults to unset (no cooldown). Pass `0` to disable
143
+ cooldown for an individual run.
144
+
145
+ The effective cooldown for any given gem is resolved from three
146
+ layers, highest precedence first:
147
+
148
+ 1. CLI flag `--cooldown N` on `install`, `update`, `add`, and
149
+ `outdated`.
150
+ 2. This setting (`bundle config set cooldown N` or
151
+ `BUNDLE_COOLDOWN=N`).
152
+ 3. The per-source `cooldown:` keyword in the Gemfile, such as
153
+ `source "https://rubygems.org", cooldown: 7`.
154
+
155
+ The CLI flag and this setting apply uniformly to every source,
156
+ including ones declared with their own `cooldown:` value. To keep a
157
+ private registry permanently exempt while still cooling down public
158
+ gems, declare `source "https://internal", cooldown: 0` in the
159
+ Gemfile; remember that `--cooldown N` on the command line will
160
+ still override it for that single run.
161
+
162
+ Cooldown filtering depends on the gem server providing a per-version
163
+ `created_at` timestamp in the v2 compact-index format. Versions
164
+ without that metadata - older gem servers, historical entries that
165
+ predate the v2 cutover on `rubygems.org`, or private registries that
166
+ still emit the v1 format - are treated as outside the cooldown
167
+ window and remain resolvable. If you rely on cooldown for
168
+ supply-chain protection, confirm that the gem server emits
169
+ `created_at` in its `/info/<gem>` responses.
140
170
  * `default_cli_command` (`BUNDLE_DEFAULT_CLI_COMMAND`):
141
171
  The command that running `bundle` without arguments should run. Defaults to
142
172
  `cli_help` since Bundler 4, but can also be `install` which was the previous
@@ -4,7 +4,7 @@
4
4
  .SH "NAME"
5
5
  \fBbundle\-install\fR \- Install the dependencies specified in your Gemfile
6
6
  .SH "SYNOPSIS"
7
- \fBbundle install\fR [\-\-force] [\-\-full\-index] [\-\-gemfile=GEMFILE] [\-\-jobs=NUMBER] [\-\-local] [\-\-lockfile=LOCKFILE] [\-\-no\-cache] [\-\-no\-lock] [\-\-prefer\-local] [\-\-quiet] [\-\-retry=NUMBER] [\-\-standalone[=GROUP[ GROUP\|\.\|\.\|\.]]] [\-\-trust\-policy=TRUST\-POLICY] [\-\-target\-rbconfig=TARGET\-RBCONFIG]
7
+ \fBbundle install\fR [\-\-cooldown=NUMBER] [\-\-force] [\-\-full\-index] [\-\-gemfile=GEMFILE] [\-\-jobs=NUMBER] [\-\-local] [\-\-lockfile=LOCKFILE] [\-\-no\-cache] [\-\-no\-lock] [\-\-prefer\-local] [\-\-quiet] [\-\-retry=NUMBER] [\-\-standalone[=GROUP[ GROUP\|\.\|\.\|\.]]] [\-\-trust\-policy=TRUST\-POLICY] [\-\-target\-rbconfig=TARGET\-RBCONFIG]
8
8
  .SH "DESCRIPTION"
9
9
  Install the gems specified in your Gemfile(5)\. If this is the first time you run bundle install (and a \fBGemfile\.lock\fR does not exist), Bundler will fetch all remote sources, resolve dependencies and install all needed gems\.
10
10
  .P
@@ -13,6 +13,9 @@ If a \fBGemfile\.lock\fR does exist, and you have not updated your Gemfile(5), B
13
13
  If a \fBGemfile\.lock\fR does exist, and you have updated your Gemfile(5), Bundler will use the dependencies in the \fBGemfile\.lock\fR for all gems that you did not update, but will re\-resolve the dependencies of gems that you did update\. You can find more information about this update process below under \fICONSERVATIVE UPDATING\fR\.
14
14
  .SH "OPTIONS"
15
15
  .TP
16
+ \fB\-\-cooldown=<number>\fR
17
+ Only consider gem versions published at least \fInumber\fR days ago when resolving\. Pass \fB0\fR to disable cooldown for this run, overriding any per\-source or global configuration\. See \fBcooldown\fR in bundle\-config(1) for details on the precedence between the CLI flag, Bundler config, and Gemfile per\-source settings\.
18
+ .TP
16
19
  \fB\-\-force\fR, \fB\-\-redownload\fR
17
20
  Force reinstalling every gem, even if already installed\.
18
21
  .TP
@@ -3,7 +3,8 @@ bundle-install(1) -- Install the dependencies specified in your Gemfile
3
3
 
4
4
  ## SYNOPSIS
5
5
 
6
- `bundle install` [--force]
6
+ `bundle install` [--cooldown=NUMBER]
7
+ [--force]
7
8
  [--full-index]
8
9
  [--gemfile=GEMFILE]
9
10
  [--jobs=NUMBER]
@@ -37,6 +38,13 @@ update process below under [CONSERVATIVE UPDATING][].
37
38
 
38
39
  ## OPTIONS
39
40
 
41
+ * `--cooldown=<number>`:
42
+ Only consider gem versions published at least <number> days ago when
43
+ resolving. Pass `0` to disable cooldown for this run, overriding any
44
+ per-source or global configuration. See `cooldown` in bundle-config(1)
45
+ for details on the precedence between the CLI flag, Bundler config,
46
+ and Gemfile per-source settings.
47
+
40
48
  * `--force`, `--redownload`:
41
49
  Force reinstalling every gem, even if already installed.
42
50
 
@@ -4,7 +4,7 @@
4
4
  .SH "NAME"
5
5
  \fBbundle\-outdated\fR \- List installed gems with newer versions available
6
6
  .SH "SYNOPSIS"
7
- \fBbundle outdated\fR [GEM] [\-\-local] [\-\-pre] [\-\-source] [\-\-filter\-strict | \-\-strict] [\-\-update\-strict] [\-\-parseable | \-\-porcelain] [\-\-group=GROUP] [\-\-groups] [\-\-patch|\-\-minor|\-\-major] [\-\-filter\-major] [\-\-filter\-minor] [\-\-filter\-patch] [\-\-only\-explicit]
7
+ \fBbundle outdated\fR [GEM] [\-\-local] [\-\-pre] [\-\-source] [\-\-filter\-strict | \-\-strict] [\-\-update\-strict] [\-\-parseable | \-\-porcelain] [\-\-group=GROUP] [\-\-groups] [\-\-patch|\-\-minor|\-\-major] [\-\-filter\-major] [\-\-filter\-minor] [\-\-filter\-patch] [\-\-only\-explicit] [\-\-cooldown=NUMBER]
8
8
  .SH "DESCRIPTION"
9
9
  Outdated lists the names and versions of gems that have a newer version available in the given source\. Calling outdated with [GEM [GEM]] will only check for newer versions of the given gems\. Prerelease gems are ignored by default\. If your gems are up to date, Bundler will exit with a status of 0\. Otherwise, it will exit 1\.
10
10
  .SH "OPTIONS"
@@ -53,6 +53,9 @@ Only list patch newer versions\.
53
53
  .TP
54
54
  \fB\-\-only\-explicit\fR
55
55
  Only list gems specified in your Gemfile, not their dependencies\.
56
+ .TP
57
+ \fB\-\-cooldown=<number>\fR
58
+ Annotate (rather than hide) versions that are still inside the cooldown window of \fInumber\fR days\. The prose output appends "in cooldown for Nd more days" and the table form adds "(cooldown Nd)" to the Latest column\. See \fBcooldown\fR in bundle\-config(1)\.
56
59
  .SH "PATCH LEVEL OPTIONS"
57
60
  See bundle update(1) \fIbundle\-update\.1\.html\fR for details\.
58
61
  .SH "FILTERING OUTPUT"
@@ -61,42 +64,42 @@ The 3 filtering options do not affect the resolution of versions, merely what ve
61
64
  If the regular output shows the following:
62
65
  .IP "" 4
63
66
  .nf
64
- * Gem Current Latest Requested Groups
65
- * faker 1\.6\.5 1\.6\.6 ~> 1\.4 development, test
66
- * hashie 1\.2\.0 3\.4\.6 = 1\.2\.0 default
67
- * headless 2\.2\.3 2\.3\.1 = 2\.2\.3 test
67
+ * Gem Current Latest Requested Groups Release Date
68
+ * faker 1\.6\.5 1\.6\.6 ~> 1\.4 development, test 2024\-02\-05
69
+ * hashie 1\.2\.0 3\.4\.6 = 1\.2\.0 default 2023\-11\-10
70
+ * headless 2\.2\.3 2\.3\.1 = 2\.2\.3 test 2022\-08\-19
68
71
  .fi
69
72
  .IP "" 0
70
73
  .P
71
74
  \fB\-\-filter\-major\fR would only show:
72
75
  .IP "" 4
73
76
  .nf
74
- * Gem Current Latest Requested Groups
75
- * hashie 1\.2\.0 3\.4\.6 = 1\.2\.0 default
77
+ * Gem Current Latest Requested Groups Release Date
78
+ * hashie 1\.2\.0 3\.4\.6 = 1\.2\.0 default 2023\-11\-10
76
79
  .fi
77
80
  .IP "" 0
78
81
  .P
79
82
  \fB\-\-filter\-minor\fR would only show:
80
83
  .IP "" 4
81
84
  .nf
82
- * Gem Current Latest Requested Groups
83
- * headless 2\.2\.3 2\.3\.1 = 2\.2\.3 test
85
+ * Gem Current Latest Requested Groups Release Date
86
+ * headless 2\.2\.3 2\.3\.1 = 2\.2\.3 test 2022\-08\-19
84
87
  .fi
85
88
  .IP "" 0
86
89
  .P
87
90
  \fB\-\-filter\-patch\fR would only show:
88
91
  .IP "" 4
89
92
  .nf
90
- * Gem Current Latest Requested Groups
91
- * faker 1\.6\.5 1\.6\.6 ~> 1\.4 development, test
93
+ * Gem Current Latest Requested Groups Release Date
94
+ * faker 1\.6\.5 1\.6\.6 ~> 1\.4 development, test 2024\-02\-05
92
95
  .fi
93
96
  .IP "" 0
94
97
  .P
95
98
  Filter options can be combined\. \fB\-\-filter\-minor\fR and \fB\-\-filter\-patch\fR would show:
96
99
  .IP "" 4
97
100
  .nf
98
- * Gem Current Latest Requested Groups
99
- * faker 1\.6\.5 1\.6\.6 ~> 1\.4 development, test
101
+ * Gem Current Latest Requested Groups Release Date
102
+ * faker 1\.6\.5 1\.6\.6 ~> 1\.4 development, test 2024\-02\-05
100
103
  .fi
101
104
  .IP "" 0
102
105
  .P
@@ -16,6 +16,7 @@ bundle-outdated(1) -- List installed gems with newer versions available
16
16
  [--filter-minor]
17
17
  [--filter-patch]
18
18
  [--only-explicit]
19
+ [--cooldown=NUMBER]
19
20
 
20
21
  ## DESCRIPTION
21
22
 
@@ -71,6 +72,12 @@ are up to date, Bundler will exit with a status of 0. Otherwise, it will exit 1.
71
72
  * `--only-explicit`:
72
73
  Only list gems specified in your Gemfile, not their dependencies.
73
74
 
75
+ * `--cooldown=<number>`:
76
+ Annotate (rather than hide) versions that are still inside the
77
+ cooldown window of <number> days. The prose output appends "in
78
+ cooldown for Nd more days" and the table form adds "(cooldown Nd)" to
79
+ the Latest column. See `cooldown` in bundle-config(1).
80
+
74
81
  ## PATCH LEVEL OPTIONS
75
82
 
76
83
  See [bundle update(1)](bundle-update.1.html) for details.
@@ -82,29 +89,29 @@ in the output.
82
89
 
83
90
  If the regular output shows the following:
84
91
 
85
- * Gem Current Latest Requested Groups
86
- * faker 1.6.5 1.6.6 ~> 1.4 development, test
87
- * hashie 1.2.0 3.4.6 = 1.2.0 default
88
- * headless 2.2.3 2.3.1 = 2.2.3 test
92
+ * Gem Current Latest Requested Groups Release Date
93
+ * faker 1.6.5 1.6.6 ~> 1.4 development, test 2024-02-05
94
+ * hashie 1.2.0 3.4.6 = 1.2.0 default 2023-11-10
95
+ * headless 2.2.3 2.3.1 = 2.2.3 test 2022-08-19
89
96
 
90
97
  `--filter-major` would only show:
91
98
 
92
- * Gem Current Latest Requested Groups
93
- * hashie 1.2.0 3.4.6 = 1.2.0 default
99
+ * Gem Current Latest Requested Groups Release Date
100
+ * hashie 1.2.0 3.4.6 = 1.2.0 default 2023-11-10
94
101
 
95
102
  `--filter-minor` would only show:
96
103
 
97
- * Gem Current Latest Requested Groups
98
- * headless 2.2.3 2.3.1 = 2.2.3 test
104
+ * Gem Current Latest Requested Groups Release Date
105
+ * headless 2.2.3 2.3.1 = 2.2.3 test 2022-08-19
99
106
 
100
107
  `--filter-patch` would only show:
101
108
 
102
- * Gem Current Latest Requested Groups
103
- * faker 1.6.5 1.6.6 ~> 1.4 development, test
109
+ * Gem Current Latest Requested Groups Release Date
110
+ * faker 1.6.5 1.6.6 ~> 1.4 development, test 2024-02-05
104
111
 
105
112
  Filter options can be combined. `--filter-minor` and `--filter-patch` would show:
106
113
 
107
- * Gem Current Latest Requested Groups
108
- * faker 1.6.5 1.6.6 ~> 1.4 development, test
114
+ * Gem Current Latest Requested Groups Release Date
115
+ * faker 1.6.5 1.6.6 ~> 1.4 development, test 2024-02-05
109
116
 
110
117
  Combining all three `filter` options would be the same result as providing none of them.
@@ -4,7 +4,7 @@
4
4
  .SH "NAME"
5
5
  \fBbundle\-update\fR \- Update your gems to the latest available versions
6
6
  .SH "SYNOPSIS"
7
- \fBbundle update\fR \fI*gems\fR [\-\-all] [\-\-group=NAME] [\-\-source=NAME] [\-\-local] [\-\-ruby] [\-\-bundler[=VERSION]] [\-\-force] [\-\-full\-index] [\-\-gemfile=GEMFILE] [\-\-jobs=NUMBER] [\-\-quiet] [\-\-patch|\-\-minor|\-\-major] [\-\-pre] [\-\-strict] [\-\-conservative]
7
+ \fBbundle update\fR \fI*gems\fR [\-\-all] [\-\-group=NAME] [\-\-source=NAME] [\-\-local] [\-\-ruby] [\-\-bundler[=VERSION]] [\-\-cooldown=NUMBER] [\-\-force] [\-\-full\-index] [\-\-gemfile=GEMFILE] [\-\-jobs=NUMBER] [\-\-quiet] [\-\-patch|\-\-minor|\-\-major] [\-\-pre] [\-\-strict] [\-\-conservative]
8
8
  .SH "DESCRIPTION"
9
9
  Update the gems specified (all gems, if \fB\-\-all\fR flag is used), ignoring the previously installed gems specified in the \fBGemfile\.lock\fR\. In general, you should use bundle install(1) \fIbundle\-install\.1\.html\fR to install the same exact gems and versions across machines\.
10
10
  .P
@@ -64,6 +64,9 @@ Do not allow any gem to be updated past latest \fB\-\-patch\fR | \fB\-\-minor\fR
64
64
  .TP
65
65
  \fB\-\-conservative\fR
66
66
  Use bundle install conservative update behavior and do not allow indirect dependencies to be updated\.
67
+ .TP
68
+ \fB\-\-cooldown=<number>\fR
69
+ Only consider gem versions published at least \fInumber\fR days ago when resolving\. Pass \fB0\fR to disable cooldown for this run, overriding any per\-source or global configuration\. Combine with \fB\-\-conservative\fR to minimize transitive churn when bypassing cooldown for an urgent update\. See \fBcooldown\fR in bundle\-config(1)\.
67
70
  .SH "UPDATING ALL GEMS"
68
71
  If you run \fBbundle update \-\-all\fR, bundler will ignore any previously installed gems and resolve all dependencies again based on the latest versions of all gems available in the sources\.
69
72
  .P
@@ -9,6 +9,7 @@ bundle-update(1) -- Update your gems to the latest available versions
9
9
  [--local]
10
10
  [--ruby]
11
11
  [--bundler[=VERSION]]
12
+ [--cooldown=NUMBER]
12
13
  [--force]
13
14
  [--full-index]
14
15
  [--gemfile=GEMFILE]
@@ -91,6 +92,13 @@ gem.
91
92
  * `--conservative`:
92
93
  Use bundle install conservative update behavior and do not allow indirect dependencies to be updated.
93
94
 
95
+ * `--cooldown=<number>`:
96
+ Only consider gem versions published at least <number> days ago when
97
+ resolving. Pass `0` to disable cooldown for this run, overriding any
98
+ per-source or global configuration. Combine with `--conservative` to
99
+ minimize transitive churn when bypassing cooldown for an urgent
100
+ update. See `cooldown` in bundle-config(1).
101
+
94
102
  ## UPDATING ALL GEMS
95
103
 
96
104
  If you run `bundle update --all`, bundler will ignore
@@ -12,7 +12,7 @@ module Bundler
12
12
 
13
13
  attr_reader :name, :version, :platform
14
14
  attr_writer :dependencies
15
- attr_accessor :source, :remote, :locked_platform
15
+ attr_accessor :source, :remote, :locked_platform, :created_at
16
16
 
17
17
  def initialize(name, version, platform, spec_fetcher)
18
18
  @name = name
@@ -184,6 +184,9 @@ module Bundler
184
184
 
185
185
  platforms_explanation = specs_matching_other_platforms.any? ? " for any resolution platforms (#{package.platforms.join(", ")})" : ""
186
186
  custom_explanation = "#{constraint} could not be found in #{repository_for(package)}#{platforms_explanation}"
187
+ if hint = cooldown_hint(specs_matching_other_platforms)
188
+ custom_explanation += " (#{hint})"
189
+ end
187
190
 
188
191
  label = "#{name} (#{constraint_string})"
189
192
  extended_explanation = other_specs_matching_message(specs_matching_other_platforms, label) if specs_matching_other_platforms.any?
@@ -353,6 +356,10 @@ module Bundler
353
356
  message << "\n#{other_specs_matching_message(specs, matching_part)}"
354
357
  end
355
358
 
359
+ if hint = cooldown_hint(specs_matching_requirement)
360
+ message << "\n\n#{hint}."
361
+ end
362
+
356
363
  if specs_matching_requirement.any? && (hint = platform_mismatch_hint)
357
364
  message << "\n\n#{hint}"
358
365
  end
@@ -396,7 +403,7 @@ module Bundler
396
403
  end
397
404
 
398
405
  def filter_specs(specs, package)
399
- filter_remote_specs(filter_prereleases(specs, package), package)
406
+ filter_remote_specs(filter_cooldown(filter_prereleases(specs, package)), package)
400
407
  end
401
408
 
402
409
  def filter_prereleases(specs, package)
@@ -405,6 +412,40 @@ module Bundler
405
412
  specs.reject {|s| s.version.prerelease? }
406
413
  end
407
414
 
415
+ def filter_cooldown(specs)
416
+ return specs if specs.empty?
417
+ excluded_versions = cooldown_excluded_versions(specs)
418
+ return specs if excluded_versions.empty?
419
+ specs.reject {|s| excluded_versions.include?([s.name, s.version]) }
420
+ end
421
+
422
+ def cooldown_excluded_versions(specs)
423
+ excluded = {}
424
+ specs.each do |spec|
425
+ next unless cooldown_excluded?(spec)
426
+ excluded[[spec.name, spec.version]] = true
427
+ end
428
+ excluded
429
+ end
430
+
431
+ def cooldown_hint(specs)
432
+ excluded_versions = cooldown_excluded_versions(specs)
433
+ return nil if excluded_versions.empty?
434
+ "#{excluded_versions.size} version#{"s" if excluded_versions.size > 1} excluded by the cooldown setting; pass `--cooldown 0` to bypass"
435
+ end
436
+
437
+ def cooldown_excluded?(spec)
438
+ return false unless spec.respond_to?(:created_at) && spec.created_at
439
+ return false unless spec.respond_to?(:remote) && spec.remote
440
+ days = spec.remote.effective_cooldown
441
+ return false if days.nil? || days <= 0
442
+ (cooldown_now - spec.created_at) < (days * 86_400)
443
+ end
444
+
445
+ def cooldown_now
446
+ @cooldown_now ||= Time.now
447
+ end
448
+
408
449
  def filter_remote_specs(specs, package)
409
450
  if package.prefer_local?
410
451
  local_specs = specs.select {|s| s.is_a?(StubSpecification) }
@@ -465,6 +465,28 @@ module Gem
465
465
  Resolver::APISet::GemParser.prepend(UnfreezeCompactIndexParsedResponse)
466
466
  end
467
467
 
468
+ # RubyGems before 4.0.13 split compact index dependency/requirement entries
469
+ # on every colon, which mangles metadata values that contain colons such as
470
+ # the `created_at` timestamps the cooldown feature relies on. Split only on
471
+ # the first colon so those values survive on older RubyGems.
472
+ #
473
+ # The module is defined unconditionally so it stays testable on any RubyGems,
474
+ # but only prepended when the host RubyGems still has the buggy behavior.
475
+ module SplitCompactIndexEntryOnFirstColon
476
+ private
477
+
478
+ def parse_dependency(string)
479
+ dependency = string.split(":", 2)
480
+ dependency[-1] = dependency[-1].split("&") if dependency.size > 1
481
+ dependency[0] = -dependency[0]
482
+ dependency
483
+ end
484
+ end
485
+
486
+ unless Gem.rubygems_version >= Gem::Version.new("4.0.13")
487
+ Resolver::APISet::GemParser.prepend(SplitCompactIndexEntryOnFirstColon)
488
+ end
489
+
468
490
  if Gem.rubygems_version < Gem::Version.new("3.6.0")
469
491
  class Package; end
470
492
  require "rubygems/package/tar_reader"
@@ -20,7 +20,7 @@ module Bundler
20
20
  strict_rm_rf spec.extension_dir
21
21
 
22
22
  SharedHelpers.filesystem_access(gem_dir, :create) do
23
- FileUtils.mkdir_p gem_dir, mode: 0o755
23
+ FileUtils.mkdir_p gem_dir
24
24
  end
25
25
 
26
26
  SharedHelpers.filesystem_access(gem_dir, :write) do
@@ -42,6 +42,7 @@ module Bundler
42
42
  ].freeze
43
43
 
44
44
  NUMBER_KEYS = %w[
45
+ cooldown
45
46
  jobs
46
47
  redirect
47
48
  retry
@@ -432,9 +432,14 @@ module Bundler
432
432
  end
433
433
 
434
434
  def capture3_args_for(cmd, dir)
435
- return ["git", *cmd] unless dir
435
+ # Disable automatic maintenance so a background commit-graph write in
436
+ # the source repo can't race the hardlinking local clone and fail with
437
+ # "hardlink different from source".
438
+ opts = ["-c", "gc.auto=0", "-c", "maintenance.auto=false"]
436
439
 
437
- ["git", "-C", dir.to_s, *cmd]
440
+ return ["git", *opts, *cmd] unless dir
441
+
442
+ ["git", "-C", dir.to_s, *opts, *cmd]
438
443
  end
439
444
 
440
445
  def extra_clone_args
@@ -4,9 +4,9 @@ module Bundler
4
4
  class Source
5
5
  class Rubygems
6
6
  class Remote
7
- attr_reader :uri, :anonymized_uri, :original_uri
7
+ attr_reader :uri, :anonymized_uri, :original_uri, :cooldown
8
8
 
9
- def initialize(uri)
9
+ def initialize(uri, cooldown: nil)
10
10
  orig_uri = uri
11
11
  uri = Bundler.settings.mirror_for(uri)
12
12
  @original_uri = orig_uri if orig_uri != uri
@@ -14,6 +14,16 @@ module Bundler
14
14
 
15
15
  @uri = apply_auth(uri, fallback_auth).freeze
16
16
  @anonymized_uri = remove_auth(@uri).freeze
17
+ @cooldown = cooldown
18
+ end
19
+
20
+ # Returns the cooldown days that apply to this remote, resolving the
21
+ # precedence CLI > config > Gemfile per-source. Returns nil if no
22
+ # cooldown applies.
23
+ def effective_cooldown
24
+ override = Bundler.settings[:cooldown]
25
+ return override if override
26
+ @cooldown
17
27
  end
18
28
 
19
29
  MAX_CACHE_SLUG_HOST_SIZE = 255 - 1 - 32 # 255 minus dot minus MD5 length
@@ -16,6 +16,7 @@ module Bundler
16
16
  def initialize(options = {})
17
17
  @options = options
18
18
  @remotes = []
19
+ @remote_cooldowns = {}
19
20
  @dependency_names = []
20
21
  @allow_remote = false
21
22
  @allow_cached = false
@@ -25,7 +26,8 @@ module Bundler
25
26
  @gem_installers = {}
26
27
  @gem_installers_mutex = Mutex.new
27
28
 
28
- Array(options["remotes"]).reverse_each {|r| add_remote(r) }
29
+ cooldown = options["cooldown"]
30
+ Array(options["remotes"]).reverse_each {|r| add_remote(r, cooldown: cooldown) }
29
31
 
30
32
  @lockfile_remotes = @remotes if options["from_lockfile"]
31
33
  end
@@ -148,6 +150,13 @@ module Bundler
148
150
  # sources, and large_idx.merge! small_idx is way faster than
149
151
  # small_idx.merge! large_idx.
150
152
  index = @allow_remote ? remote_specs.dup : Index.new
153
+
154
+ # Snapshot per-version `created_at` from the remote info before installed
155
+ # / cached specs overwrite the EndpointSpecification objects that carry
156
+ # it. The cooldown filter consults `created_at` on every candidate, so
157
+ # local stubs need the published date back-filled to participate.
158
+ remote_created_at = collect_remote_created_at(index)
159
+
151
160
  index.merge!(cached_specs) if @allow_cached
152
161
  index.merge!(installed_specs) if @allow_local
153
162
 
@@ -161,6 +170,8 @@ module Bundler
161
170
  end
162
171
  end
163
172
 
173
+ backfill_created_at(index, remote_created_at) unless remote_created_at.empty?
174
+
164
175
  index
165
176
  end
166
177
  end
@@ -243,9 +254,14 @@ module Bundler
243
254
  cached_path
244
255
  end
245
256
 
246
- def add_remote(source)
257
+ def add_remote(source, cooldown: nil)
247
258
  uri = normalize_uri(source)
248
259
  @remotes.unshift(uri) unless @remotes.include?(uri)
260
+ @remote_cooldowns[uri] = cooldown if cooldown
261
+ end
262
+
263
+ def cooldown_for(uri)
264
+ @remote_cooldowns[uri]
249
265
  end
250
266
 
251
267
  def spec_names
@@ -266,7 +282,7 @@ module Bundler
266
282
 
267
283
  def remote_fetchers
268
284
  @remote_fetchers ||= remotes.to_h do |uri|
269
- remote = Source::Rubygems::Remote.new(uri)
285
+ remote = Source::Rubygems::Remote.new(uri, cooldown: cooldown_for(uri))
270
286
  [remote, Bundler::Fetcher.new(remote)]
271
287
  end.freeze
272
288
  end
@@ -314,6 +330,13 @@ module Bundler
314
330
  @allow_remote && api_fetchers.any?
315
331
  end
316
332
 
333
+ def clear_cache
334
+ @specs = nil
335
+ @installed_specs = nil
336
+ @default_specs = nil
337
+ @cached_specs = nil
338
+ end
339
+
317
340
  protected
318
341
 
319
342
  def remote_names
@@ -456,6 +479,31 @@ module Bundler
456
479
 
457
480
  private
458
481
 
482
+ def collect_remote_created_at(index)
483
+ return {} unless @allow_remote
484
+
485
+ snapshot = {}
486
+ index.each do |spec|
487
+ next unless spec.respond_to?(:created_at) && spec.created_at
488
+ # Remember the remote that supplied the date too: when a source has
489
+ # several remotes with different per-URI cooldown settings we must
490
+ # restore the same one during backfill so `effective_cooldown` agrees.
491
+ snapshot[[spec.name, spec.version]] = [spec.created_at, spec.remote]
492
+ end
493
+ snapshot
494
+ end
495
+
496
+ def backfill_created_at(index, snapshot)
497
+ index.each do |spec|
498
+ next unless spec.respond_to?(:created_at=)
499
+ next if spec.created_at
500
+ remote_created_at, remote = snapshot[[spec.name, spec.version]]
501
+ next unless remote_created_at
502
+ spec.created_at = remote_created_at
503
+ spec.remote ||= remote if remote && spec.respond_to?(:remote=)
504
+ end
505
+ end
506
+
459
507
  def lockfile_remotes
460
508
  @lockfile_remotes || credless_remotes
461
509
  end
@@ -59,8 +59,8 @@ module Bundler
59
59
  add_source_to_list Plugin.source(source).new(options), @plugin_sources
60
60
  end
61
61
 
62
- def add_global_rubygems_remote(uri)
63
- global_rubygems_source.add_remote(uri)
62
+ def add_global_rubygems_remote(uri, cooldown: nil)
63
+ global_rubygems_source.add_remote(uri, cooldown: cooldown)
64
64
  global_rubygems_source
65
65
  end
66
66
 
@@ -136,6 +136,10 @@ module Bundler
136
136
  all_sources.each(&:remote!)
137
137
  end
138
138
 
139
+ def clear_cache
140
+ rubygems_sources.each(&:clear_cache)
141
+ end
142
+
139
143
  private
140
144
 
141
145
  def map_sources(replacement_sources)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Bundler
4
- VERSION = "4.0.12".freeze
4
+ VERSION = "4.0.13".freeze
5
5
 
6
6
  def self.bundler_major_version
7
7
  @bundler_major_version ||= gem_version.segments.first
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundler
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.12
4
+ version: 4.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - André Arko