bundler 4.0.9 → 4.0.18

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +147 -0
  3. data/bundler.gemspec +2 -2
  4. data/lib/bundler/build_metadata.rb +1 -1
  5. data/lib/bundler/cli/add.rb +3 -0
  6. data/lib/bundler/cli/check.rb +1 -3
  7. data/lib/bundler/cli/common.rb +6 -0
  8. data/lib/bundler/cli/config.rb +8 -3
  9. data/lib/bundler/cli/gem.rb +2 -3
  10. data/lib/bundler/cli/install.rb +3 -0
  11. data/lib/bundler/cli/issue.rb +2 -2
  12. data/lib/bundler/cli/lock.rb +3 -0
  13. data/lib/bundler/cli/open.rb +12 -2
  14. data/lib/bundler/cli/outdated.rb +42 -2
  15. data/lib/bundler/cli/update.rb +2 -0
  16. data/lib/bundler/cli.rb +18 -12
  17. data/lib/bundler/compact_index_client/cache.rb +11 -0
  18. data/lib/bundler/compact_index_client/cache_file.rb +1 -1
  19. data/lib/bundler/compact_index_client/parser.rb +4 -1
  20. data/lib/bundler/definition.rb +51 -12
  21. data/lib/bundler/dsl.rb +10 -3
  22. data/lib/bundler/endpoint_specification.rb +17 -2
  23. data/lib/bundler/fetcher/base.rb +3 -0
  24. data/lib/bundler/fetcher/compact_index.rb +13 -0
  25. data/lib/bundler/fetcher/gem_remote_fetcher.rb +2 -0
  26. data/lib/bundler/fetcher.rb +12 -2
  27. data/lib/bundler/injector.rb +1 -2
  28. data/lib/bundler/installer/parallel_installer.rb +68 -23
  29. data/lib/bundler/installer.rb +12 -1
  30. data/lib/bundler/lockfile_generator.rb +39 -1
  31. data/lib/bundler/lockfile_parser.rb +23 -1
  32. data/lib/bundler/man/bundle-add.1 +6 -3
  33. data/lib/bundler/man/bundle-add.1.ronn +7 -2
  34. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  35. data/lib/bundler/man/bundle-cache.1 +4 -1
  36. data/lib/bundler/man/bundle-cache.1.ronn +6 -0
  37. data/lib/bundler/man/bundle-check.1 +1 -1
  38. data/lib/bundler/man/bundle-clean.1 +1 -1
  39. data/lib/bundler/man/bundle-config.1 +121 -157
  40. data/lib/bundler/man/bundle-config.1.ronn +33 -1
  41. data/lib/bundler/man/bundle-console.1 +3 -3
  42. data/lib/bundler/man/bundle-console.1.ronn +2 -2
  43. data/lib/bundler/man/bundle-doctor.1 +1 -1
  44. data/lib/bundler/man/bundle-env.1 +1 -1
  45. data/lib/bundler/man/bundle-exec.1 +1 -1
  46. data/lib/bundler/man/bundle-fund.1 +1 -1
  47. data/lib/bundler/man/bundle-gem.1 +1 -1
  48. data/lib/bundler/man/bundle-help.1 +1 -1
  49. data/lib/bundler/man/bundle-info.1 +1 -1
  50. data/lib/bundler/man/bundle-init.1 +2 -2
  51. data/lib/bundler/man/bundle-init.1.ronn +1 -1
  52. data/lib/bundler/man/bundle-install.1 +5 -2
  53. data/lib/bundler/man/bundle-install.1.ronn +9 -1
  54. data/lib/bundler/man/bundle-issue.1 +1 -1
  55. data/lib/bundler/man/bundle-licenses.1 +1 -1
  56. data/lib/bundler/man/bundle-list.1 +1 -1
  57. data/lib/bundler/man/bundle-lock.1 +5 -2
  58. data/lib/bundler/man/bundle-lock.1.ronn +6 -0
  59. data/lib/bundler/man/bundle-open.1 +1 -1
  60. data/lib/bundler/man/bundle-outdated.1 +17 -14
  61. data/lib/bundler/man/bundle-outdated.1.ronn +19 -12
  62. data/lib/bundler/man/bundle-platform.1 +1 -1
  63. data/lib/bundler/man/bundle-plugin.1 +2 -2
  64. data/lib/bundler/man/bundle-plugin.1.ronn +1 -1
  65. data/lib/bundler/man/bundle-pristine.1 +1 -1
  66. data/lib/bundler/man/bundle-remove.1 +1 -1
  67. data/lib/bundler/man/bundle-show.1 +1 -1
  68. data/lib/bundler/man/bundle-update.1 +5 -2
  69. data/lib/bundler/man/bundle-update.1.ronn +8 -0
  70. data/lib/bundler/man/bundle-version.1 +1 -1
  71. data/lib/bundler/man/bundle.1 +23 -2
  72. data/lib/bundler/man/bundle.1.ronn +22 -1
  73. data/lib/bundler/man/gemfile.5 +13 -2
  74. data/lib/bundler/man/gemfile.5.ronn +20 -1
  75. data/lib/bundler/mirror.rb +7 -7
  76. data/lib/bundler/plugin/unloaded_source.rb +25 -0
  77. data/lib/bundler/plugin.rb +12 -6
  78. data/lib/bundler/remote_specification.rb +1 -1
  79. data/lib/bundler/resolver/base.rb +9 -0
  80. data/lib/bundler/resolver/strategy.rb +6 -3
  81. data/lib/bundler/resolver.rb +80 -1
  82. data/lib/bundler/rubygems_ext.rb +22 -0
  83. data/lib/bundler/rubygems_gem_installer.rb +35 -2
  84. data/lib/bundler/runtime.rb +11 -11
  85. data/lib/bundler/self_manager.rb +6 -1
  86. data/lib/bundler/settings/validator.rb +7 -0
  87. data/lib/bundler/settings.rb +2 -0
  88. data/lib/bundler/shared_helpers.rb +6 -1
  89. data/lib/bundler/source/git/git_proxy.rb +13 -2
  90. data/lib/bundler/source/git.rb +1 -1
  91. data/lib/bundler/source/metadata.rb +4 -0
  92. data/lib/bundler/source/path.rb +3 -2
  93. data/lib/bundler/source/rubygems/remote.rb +12 -2
  94. data/lib/bundler/source/rubygems.rb +81 -13
  95. data/lib/bundler/source_list.rb +44 -3
  96. data/lib/bundler/spec_set.rb +2 -2
  97. data/lib/bundler/stub_specification.rb +1 -0
  98. data/lib/bundler/templates/newgem/newgem.gemspec.tt +10 -1
  99. data/lib/bundler/vendored_tsort.rb +19 -2
  100. data/lib/bundler/version.rb +1 -1
  101. data/lib/bundler.rb +11 -1
  102. metadata +5 -6
  103. data/lib/bundler/vendor/tsort/LICENSE.txt +0 -22
  104. data/lib/bundler/vendor/tsort/lib/tsort.rb +0 -455
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff315eb3319300026b3ab3422e82399e6b0ce63ef727f94e125a226623101c27
4
- data.tar.gz: 00bb903a5564f2565ebcbc350837283f724d1ef42d4f586b37a972fe568015da
3
+ metadata.gz: ce6bf9b503cf8fbe56890d80055e7b66389f1454eb93c13b4fb18dfc62158cd1
4
+ data.tar.gz: e1f51fdb265c4717df5797824a7a4b89693fa259655f95e33d04a3596157b886
5
5
  SHA512:
6
- metadata.gz: c6a4c93541bd76ee07370d4995487fe663f10d8aa021f1d9104d6adfeb373a36bbc47fd3498094da011c561702d7a84ebb1854c80c99176578b0fbc666e2dba2
7
- data.tar.gz: 29943339931f1e5b37c836346171c51f2a00a2cadbd7d7b5f30da5dd5bacb1f1024b7601ded1e1d895a3da4e11cf1d6ea35768a7196b351e237179d63759cd13
6
+ metadata.gz: 9382209cbfdbddee4c21dcb2d9f22039ebcc2079b0998ff3cf133b14efa93ae146ebcc5570a9d157ce1cd383bcd6b0192ea89ff7590b990e21490f0c874aff8e
7
+ data.tar.gz: 9889c94bcbf7c3eb0d91aeaf650c1bfdbcd3f42c0386c3a603bbc777552b95cd973511d700814e1ecceb881a931c2b1045da9059d3b1eb33bbf88babda3b5a81
data/CHANGELOG.md CHANGED
@@ -1,5 +1,152 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.0.18 / 2026-08-05
4
+
5
+ ### Enhancements:
6
+
7
+ * Don't mask install errors when no Gemfile can be located. Pull request [#9757](https://github.com/ruby/rubygems/pull/9757) by hsbt
8
+ * Warn when duplicate source declarations conflict on cooldown. Pull request [#9736](https://github.com/ruby/rubygems/pull/9736) by hsbt
9
+ * Redact URI userinfo from settings names in Bundler User-Agent. Pull request [#9716](https://github.com/ruby/rubygems/pull/9716) by hsbt
10
+ * Validate gem name before building compact index cache paths. Pull request [#9717](https://github.com/ruby/rubygems/pull/9717) by hsbt
11
+
12
+ ### Bug fixes:
13
+
14
+ * Fail `bundle check` when frozen mode needs lockfile changes. Pull request [#9715](https://github.com/ruby/rubygems/pull/9715) by hsbt
15
+ * Skip empty checksum values in compact index metadata. Pull request [#9713](https://github.com/ruby/rubygems/pull/9713) by hsbt
16
+
17
+ ### Security:
18
+
19
+ * Add --cooldown flag to bundle lock and bundle cache. Pull request [#9725](https://github.com/ruby/rubygems/pull/9725) by hsbt
20
+
21
+ ### Documentation:
22
+
23
+ * Point bundler.io URLs at guides.rubygems.org. Pull request [#9737](https://github.com/ruby/rubygems/pull/9737) by hsbt
24
+ * Document Bundler checksum behavior for default gems. Pull request [#9735](https://github.com/ruby/rubygems/pull/9735) by p-linnane
25
+ * List missing subcommands in bundle(1) UTILITIES section. Pull request [#9721](https://github.com/ruby/rubygems/pull/9721) by hsbt
26
+ * Document pessimistic operator and eval_gemfile in gemfile(5). Pull request [#9719](https://github.com/ruby/rubygems/pull/9719) by hsbt
27
+
28
+ ## 4.0.17 / 2026-07-22
29
+
30
+ ### Enhancements:
31
+
32
+ * Open compact index cache in binary mode when appending. Pull request [#9679](https://github.com/ruby/rubygems/pull/9679) by hsbt
33
+
34
+ ### Bug fixes:
35
+
36
+ * Unquote Gem.ruby when spawning it as a separate argv element. Pull request [#9695](https://github.com/ruby/rubygems/pull/9695) by hsbt
37
+ * Escape glob metacharacters in install paths when globbing. Pull request [#9687](https://github.com/ruby/rubygems/pull/9687) by hsbt
38
+ * Avoid space-containing absolute path in RUBYOPT. Pull request [#9696](https://github.com/ruby/rubygems/pull/9696) by hsbt
39
+ * Preserve the locked Bundler checksum when the gem isn't cached. Pull request [#9658](https://github.com/ruby/rubygems/pull/9658) by rwstauner
40
+
41
+ ### Documentation:
42
+
43
+ * Point Bundler gemspec metadata at the moved docs. Pull request [#9648](https://github.com/ruby/rubygems/pull/9648) by hsbt
44
+
45
+ ## 4.0.16 / 2026-07-10
46
+
47
+ ### Enhancements:
48
+
49
+ * Bundler: Fix Bundler::Fetcher for PQC support, adding integration connection tests. Pull request [#9637](https://github.com/ruby/rubygems/pull/9637) by junaruga
50
+ * Reuse RubyGems' vendored tsort in Bundler. Pull request [#9647](https://github.com/ruby/rubygems/pull/9647) by hsbt
51
+
52
+ ### Bug fixes:
53
+
54
+ * Initialize the new gem's git repo without a subshell. Pull request [#9670](https://github.com/ruby/rubygems/pull/9670) by hsbt
55
+ * Preserve CRLF lockfile line endings on Windows. Pull request [#9669](https://github.com/ruby/rubygems/pull/9669) by hsbt
56
+ * Fix the gemspec error snippet on Windows drive-letter paths. Pull request [#9668](https://github.com/ruby/rubygems/pull/9668) by hsbt
57
+
58
+ ### Documentation:
59
+
60
+ * Point Bundler gemspec metadata at the moved docs. Pull request [#9648](https://github.com/ruby/rubygems/pull/9648) by hsbt
61
+
62
+ ## 4.0.15 / 2026-06-24
63
+
64
+ ### Enhancements:
65
+
66
+ * Resolve Git LFS files in git sources from the real remote. Pull request [#9632](https://github.com/ruby/rubygems/pull/9632) by hsbt
67
+ * Suggest access issues, not only yanking, for missing locked gems. Pull request [#9631](https://github.com/ruby/rubygems/pull/9631) by hsbt
68
+ * Implement a make jobserver (continuation of #9210). Pull request [#9625](https://github.com/ruby/rubygems/pull/9625) by hsbt
69
+ * Reduce peak memory usage of full index loading and bundle install. Pull request [#9618](https://github.com/ruby/rubygems/pull/9618) by hsbt
70
+ * Bump up to rb-sys 0.9.128. Pull request [#9569](https://github.com/ruby/rubygems/pull/9569) by hsbt
71
+
72
+ ### Bug fixes:
73
+
74
+ * Skip the make jobserver on Windows. Pull request [#9630](https://github.com/ruby/rubygems/pull/9630) by hsbt
75
+ * Don't require source plugins to be installed to parse a lockfile: 4.0.x. Pull request [#9621](https://github.com/ruby/rubygems/pull/9621) by hsbt
76
+ * Exempt lockfile versions from cooldown on every resolution path. Pull request [#9619](https://github.com/ruby/rubygems/pull/9619) by hsbt
77
+ * Set `Bundler.settings[:ssl_ca_cert]` to download gems. Pull request [#9610](https://github.com/ruby/rubygems/pull/9610) by junaruga
78
+
79
+ ## 4.0.14 / 2026-06-10
80
+
81
+ ### Bug fixes:
82
+
83
+ * Preserve per-source cooldown when converging sources from the lockfile. Pull request [#9601](https://github.com/ruby/rubygems/pull/9601) by bryanwoods
84
+ * Don't exclude the locked version from cooldown during bundle update. Pull request [#9599](https://github.com/ruby/rubygems/pull/9599) by hsbt
85
+
86
+ ## 4.0.13 / 2026-06-03
87
+
88
+ ### Enhancements:
89
+
90
+ * 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
91
+ * Clear gem specification cache after acquiring process lock. Pull request [#9310](https://github.com/ruby/rubygems/pull/9310) by ngan
92
+ * Show release date with bundle outdated. Pull request [#9337](https://github.com/ruby/rubygems/pull/9337) by hsbt
93
+
94
+ ### Bug fixes:
95
+
96
+ * Apply cooldown to locally installed gem versions. Pull request [#9582](https://github.com/ruby/rubygems/pull/9582) by hsbt
97
+
98
+ ### Security:
99
+
100
+ * Add `cooldown` to delay newly published gem. Pull request [#9576](https://github.com/ruby/rubygems/pull/9576) by hsbt
101
+
102
+ ## 4.0.12 / 2026-05-20
103
+
104
+ ### Enhancements:
105
+
106
+ * 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
107
+ * Use Pathname#absolute?. Pull request [#9529](https://github.com/ruby/rubygems/pull/9529) by nobu
108
+ * Deprecate parsing non-lockfile content in LockfileParser. Pull request [#9502](https://github.com/ruby/rubygems/pull/9502) by kurotaky
109
+ * Print a warning for a potential confusion from the indirect dependencies. Pull request [#5029](https://github.com/ruby/rubygems/pull/5029) by junaruga
110
+ * Respect Gemfile bundler setting in `Bundler.setup`. Pull request [#4892](https://github.com/ruby/rubygems/pull/4892) by godfat
111
+
112
+ ### Bug fixes:
113
+
114
+ * Gracefully handle missing checksums in Compact Index. Pull request [#9492](https://github.com/ruby/rubygems/pull/9492) by jneen
115
+ * Skip git source exclusion when lockfile cannot backfill. Pull request [#9544](https://github.com/ruby/rubygems/pull/9544) by yahonda
116
+ * Fix bundle config gemfile unset behavior. Pull request [#9514](https://github.com/ruby/rubygems/pull/9514) by afurm
117
+
118
+ ## 4.0.11 / 2026-04-30
119
+
120
+ ### Enhancements:
121
+
122
+ * Update gem creation guide URL to rubygems.org. Pull request [#9500](https://github.com/ruby/rubygems/pull/9500) by nissyi-gh
123
+ * Lock the checksum of Bundler itself in the lockfile. Pull request [#9366](https://github.com/ruby/rubygems/pull/9366) by Edouard-chin
124
+
125
+ ### Bug fixes:
126
+
127
+ * Fix installing gems with native extensions + transitive dependencies. Pull request [#9477](https://github.com/ruby/rubygems/pull/9477) by nicholasdower
128
+ * Fix the bundler version not being updated in dev/test lockfile. Pull request [#9463](https://github.com/ruby/rubygems/pull/9463) by Edouard-chin
129
+ * Ensure the release CI doesn't break due to the Bundler checksum feature. Pull request [#9436](https://github.com/ruby/rubygems/pull/9436) by Edouard-chin
130
+
131
+ ### Documentation:
132
+
133
+ * Fix formatting for BUNDLE_PREFER_PATCH variable in man page. Pull request [#9474](https://github.com/ruby/rubygems/pull/9474) by toy
134
+
135
+ ## 4.0.10 / 2026-04-08
136
+
137
+ ### Enhancements:
138
+
139
+ * Ignore warnings with spec different platforms. Pull request [#8508](https://github.com/ruby/rubygems/pull/8508) by hsbt
140
+ * Improve error message when current platform is not in lockfile. Pull request [#9439](https://github.com/ruby/rubygems/pull/9439) by 55728
141
+ * Cache package version selection. Pull request [#9410](https://github.com/ruby/rubygems/pull/9410) by Edouard-chin
142
+ * Check happy path first when comparing gem version. Pull request [#9417](https://github.com/ruby/rubygems/pull/9417) by Edouard-chin
143
+ * [feature] default_cli_command for config what command bundler runs when no specific command is provided. Pull request [#8886](https://github.com/ruby/rubygems/pull/8886) by jonbarlo
144
+ * Introduce a fast path for comparing Gem::Version. Pull request [#9414](https://github.com/ruby/rubygems/pull/9414) by Edouard-chin
145
+
146
+ ### Bug fixes:
147
+
148
+ * Restore rb_sys dependency for Rust. Pull request [#9416](https://github.com/ruby/rubygems/pull/9416) by bangseongbeom
149
+
3
150
  ## 4.0.9 / 2026-03-25
4
151
 
5
152
  ### Enhancements:
data/bundler.gemspec CHANGED
@@ -24,9 +24,9 @@ Gem::Specification.new do |s|
24
24
 
25
25
  s.metadata = {
26
26
  "bug_tracker_uri" => "https://github.com/ruby/rubygems/issues?q=is%3Aopen+is%3Aissue+label%3ABundler",
27
- "changelog_uri" => "https://github.com/ruby/rubygems/blob/master/bundler/CHANGELOG.md",
27
+ "changelog_uri" => "https://github.com/ruby/rubygems/blob/master/CHANGELOG-bundler.md",
28
28
  "homepage_uri" => "https://bundler.io/",
29
- "source_code_uri" => "https://github.com/ruby/rubygems/tree/master/bundler",
29
+ "source_code_uri" => "https://github.com/ruby/rubygems",
30
30
  }
31
31
 
32
32
  s.required_ruby_version = ">= 3.2.0"
@@ -5,7 +5,7 @@ module Bundler
5
5
  module BuildMetadata
6
6
  # begin ivars
7
7
  @built_at = nil
8
- @git_commit_sha = "3ce4a32411".freeze
8
+ @git_commit_sha = "7e934435ff".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"]
@@ -12,6 +12,7 @@ module Bundler
12
12
  Bundler.settings.set_command_option_if_given :path, options[:path]
13
13
 
14
14
  definition = Bundler.definition
15
+ definition.ensure_equivalent_gemfile_and_lockfile
15
16
  definition.validate_runtime!
16
17
 
17
18
  begin
@@ -28,9 +29,6 @@ module Bundler
28
29
  not_installed.each {|s| Bundler.ui.error " * #{s.name} (#{s.version})" }
29
30
  Bundler.ui.warn "Install missing gems with `bundle install`"
30
31
  exit 1
31
- elsif !Bundler.default_lockfile.file? && Bundler.frozen_bundle?
32
- Bundler.ui.error "This bundle has been frozen, but there is no #{SharedHelpers.relative_lockfile_path} present"
33
- exit 1
34
32
  else
35
33
  definition.lock(true) unless options[:"dry-run"]
36
34
  Bundler.ui.info "The Gemfile's dependencies are satisfied"
@@ -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
@@ -256,8 +256,7 @@ module Bundler
256
256
 
257
257
  if use_git
258
258
  Bundler.ui.info "\nInitializing git repo in #{target}"
259
- require "shellwords"
260
- `git init #{target.to_s.shellescape}`
259
+ IO.popen(["git", "init", target.to_s], &:read)
261
260
 
262
261
  config[:git_default_branch] = File.read("#{target}/.git/HEAD").split("/").last.chomp
263
262
  end
@@ -288,7 +287,7 @@ module Bundler
288
287
  open_editor(options["edit"], target.join("#{name}.gemspec")) if options[:edit]
289
288
 
290
289
  Bundler.ui.info "\nGem '#{name}' was successfully created. " \
291
- "For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html"
290
+ "For more information on making a RubyGem visit https://guides.rubygems.org/make-your-own-gem/"
292
291
  end
293
292
 
294
293
  private
@@ -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"]
@@ -13,10 +13,10 @@ module Bundler
13
13
  https://github.com/ruby/rubygems/blob/master/doc/bundler/TROUBLESHOOTING.md
14
14
 
15
15
  2. Instructions for common Bundler uses can be found on the documentation
16
- site: https://bundler.io/
16
+ site: https://guides.rubygems.org/
17
17
 
18
18
  3. Information about each Bundler command can be found in the Bundler
19
- man pages: https://bundler.io/man/bundle.1.html
19
+ man pages: https://guides.rubygems.org/command-reference/bundle/
20
20
 
21
21
  Hopefully the troubleshooting steps above resolved your problem! If things
22
22
  still aren't working the way you expect them to, please let us know so
@@ -16,6 +16,9 @@ module Bundler
16
16
 
17
17
  check_for_conflicting_options
18
18
 
19
+ Bundler::CLI::Common.validate_cooldown!(options[:cooldown])
20
+ Bundler.settings.set_command_option_if_given :cooldown, options[:cooldown]
21
+
19
22
  print = options[:print]
20
23
  previous_output_stream = Bundler.ui.output_stream
21
24
  Bundler.ui.output_stream = :stderr if print
@@ -18,12 +18,22 @@ module Bundler
18
18
  Bundler.ui.info "Unable to open #{name} because it's a default gem, so the directory it would normally be installed to does not exist."
19
19
  else
20
20
  root_path = spec.full_gem_path
21
- require "shellwords"
22
- command = Shellwords.split(editor) << File.join([root_path, path].compact)
21
+ command = editor_command(editor) << File.join([root_path, path].compact)
23
22
  Bundler.with_original_env do
24
23
  system(*command, { chdir: root_path })
25
24
  end || Bundler.ui.info("Could not run '#{command.join(" ")}'")
26
25
  end
27
26
  end
27
+
28
+ def editor_command(editor)
29
+ # On Windows an editor is often configured with a full path such as
30
+ # C:\Program Files\Microsoft VS Code\Code.exe, which shell splitting
31
+ # would corrupt. Take a value that names an existing file as a
32
+ # single word.
33
+ return [editor] if Gem.win_platform? && File.file?(editor)
34
+
35
+ require "shellwords"
36
+ Shellwords.split(editor)
37
+ end
28
38
  end
29
39
  end
@@ -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
@@ -457,6 +461,7 @@ module Bundler
457
461
  method_option "path", type: :string, banner: "Specify a different path than the system default, namely, $BUNDLE_PATH or $GEM_HOME (removed)."
458
462
  method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
459
463
  method_option "frozen", type: :boolean, banner: "Do not allow the Gemfile.lock to be updated after this bundle cache operation's install (removed)"
464
+ method_option "cooldown", type: :numeric, banner: "Only consider gem versions published at least N days ago. Use 0 to disable."
460
465
  long_desc <<-D
461
466
  The cache command will copy the .gem files for every gem in the bundle into the
462
467
  directory ./vendor/cache. If you then check that directory into your source
@@ -638,6 +643,7 @@ module Bundler
638
643
  method_option "strict", type: :boolean, banner: "If updating, do not allow any gem to be updated past latest --patch | --minor | --major"
639
644
  method_option "conservative", type: :boolean, banner: "If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated"
640
645
  method_option "bundler", type: :string, lazy_default: "> 0.a", banner: "Update the locked version of bundler"
646
+ method_option "cooldown", type: :numeric, banner: "Only consider gem versions published at least N days ago. Use 0 to disable."
641
647
  def lock
642
648
  require_relative "cli/lock"
643
649
  Lock.new(options).run
@@ -50,6 +50,7 @@ module Bundler
50
50
 
51
51
  def info_path(name)
52
52
  name = name.to_s
53
+ validate_name!(name)
53
54
  # TODO: converge this into the info_root by hashing all filenames like info_etag_path
54
55
  if /[^a-z0-9_-]/.match?(name)
55
56
  name += "-#{SharedHelpers.digest(:MD5).hexdigest(name).downcase}"
@@ -61,9 +62,19 @@ module Bundler
61
62
 
62
63
  def info_etag_path(name)
63
64
  name = name.to_s
65
+ validate_name!(name)
64
66
  @info_etag_root.join("#{name}-#{SharedHelpers.digest(:MD5).hexdigest(name).downcase}")
65
67
  end
66
68
 
69
+ # Gem names come from the remote index and are not otherwise
70
+ # validated, so refuse anything that would escape the cache
71
+ # directory when used as a path component.
72
+ def validate_name!(name)
73
+ return if File.basename(name) == name
74
+
75
+ raise SecurityError, "malformed gem name: #{name.inspect}"
76
+ end
77
+
67
78
  def mkdir(name)
68
79
  directory.join(name).tap do |dir|
69
80
  SharedHelpers.filesystem_access(dir) do
@@ -103,7 +103,7 @@ module Bundler
103
103
  # Returns false without appending when no digests since appending is too error prone to do without digests.
104
104
  def append(data)
105
105
  return false unless digests?
106
- open("a") {|f| f.write data }
106
+ open("ab") {|f| f.write data }
107
107
  verify && commit
108
108
  end
109
109
 
@@ -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