summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/bundler.rb61
-rw-r--r--lib/bundler/cli/install.rb5
-rw-r--r--lib/bundler/definition.rb6
-rw-r--r--lib/bundler/errors.rb1
-rw-r--r--lib/bundler/feature_flag.rb1
-rw-r--r--lib/bundler/gem_version_promoter.rb22
-rw-r--r--lib/bundler/man/bundle-add.12
-rw-r--r--lib/bundler/man/bundle-binstubs.12
-rw-r--r--lib/bundler/man/bundle-cache.12
-rw-r--r--lib/bundler/man/bundle-check.12
-rw-r--r--lib/bundler/man/bundle-clean.12
-rw-r--r--lib/bundler/man/bundle-config.113
-rw-r--r--lib/bundler/man/bundle-config.1.ronn5
-rw-r--r--lib/bundler/man/bundle-doctor.12
-rw-r--r--lib/bundler/man/bundle-exec.12
-rw-r--r--lib/bundler/man/bundle-gem.12
-rw-r--r--lib/bundler/man/bundle-help.113
-rw-r--r--lib/bundler/man/bundle-help.1.ronn12
-rw-r--r--lib/bundler/man/bundle-info.12
-rw-r--r--lib/bundler/man/bundle-init.12
-rw-r--r--lib/bundler/man/bundle-inject.12
-rw-r--r--lib/bundler/man/bundle-install.131
-rw-r--r--lib/bundler/man/bundle-install.1.ronn29
-rw-r--r--lib/bundler/man/bundle-list.12
-rw-r--r--lib/bundler/man/bundle-lock.12
-rw-r--r--lib/bundler/man/bundle-open.12
-rw-r--r--lib/bundler/man/bundle-outdated.12
-rw-r--r--lib/bundler/man/bundle-platform.12
-rw-r--r--lib/bundler/man/bundle-plugin.181
-rw-r--r--lib/bundler/man/bundle-plugin.1.ronn59
-rw-r--r--lib/bundler/man/bundle-pristine.12
-rw-r--r--lib/bundler/man/bundle-remove.12
-rw-r--r--lib/bundler/man/bundle-show.12
-rw-r--r--lib/bundler/man/bundle-update.12
-rw-r--r--lib/bundler/man/bundle-viz.12
-rw-r--r--lib/bundler/man/bundle.18
-rw-r--r--lib/bundler/man/bundle.1.ronn5
-rw-r--r--lib/bundler/man/gemfile.52
-rw-r--r--lib/bundler/man/index.txt2
-rw-r--r--lib/bundler/match_remote_metadata.rb5
-rw-r--r--lib/bundler/plugin.rb2
-rw-r--r--lib/bundler/plugin/installer/rubygems.rb4
-rw-r--r--lib/bundler/resolver.rb149
-rw-r--r--lib/bundler/resolver/base.rb50
-rw-r--r--lib/bundler/rubygems_integration.rb4
-rw-r--r--lib/bundler/settings.rb7
-rw-r--r--lib/bundler/source/git.rb10
-rw-r--r--lib/bundler/source/path/installer.rb23
-rw-r--r--lib/bundler/source/rubygems.rb62
-rw-r--r--lib/bundler/spec_set.rb10
-rw-r--r--spec/bundler/bundler/bundler_spec.rb128
-rw-r--r--spec/bundler/bundler/endpoint_specification_spec.rb27
-rw-r--r--spec/bundler/bundler/gem_version_promoter_spec.rb9
-rw-r--r--spec/bundler/install/binstubs_spec.rb4
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb53
-rw-r--r--spec/bundler/install/gems/compact_index_spec.rb12
-rw-r--r--spec/bundler/install/gems/dependency_api_spec.rb12
-rw-r--r--spec/bundler/install/gems/flex_spec.rb75
-rw-r--r--spec/bundler/install/gems/sudo_spec.rb205
-rw-r--r--spec/bundler/plugins/install_spec.rb23
-rw-r--r--spec/bundler/plugins/source/example_spec.rb8
-rw-r--r--spec/bundler/quality_spec.rb1
-rw-r--r--spec/bundler/spec_helper.rb6
-rw-r--r--spec/bundler/support/filters.rb3
-rw-r--r--spec/bundler/support/helpers.rb9
-rw-r--r--spec/bundler/support/sudo.rb22
-rw-r--r--test/rubygems/helper.rb7
-rw-r--r--tool/bundler/rubocop_gems.rb.lock1
-rw-r--r--tool/bundler/standard_gems.rb.lock1
69 files changed, 499 insertions, 831 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 24785ef5eb..dc88bbdcb9 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -488,41 +488,9 @@ EOF
configured_bundle_path.use_system_gems?
end
- def requires_sudo?
- return @requires_sudo if defined?(@requires_sudo_ran)
-
- sudo_present = which "sudo" if settings.allow_sudo?
-
- if sudo_present
- # the bundle path and subdirectories need to be writable for RubyGems
- # to be able to unpack and install gems without exploding
- path = bundle_path
- path = path.parent until path.exist?
-
- # bins are written to a different location on OS X
- bin_dir = Pathname.new(Bundler.system_bindir)
- bin_dir = bin_dir.parent until bin_dir.exist?
-
- # if any directory is not writable, we need sudo
- files = [path, bin_dir] | Dir[bundle_path.join("build_info/*").to_s] | Dir[bundle_path.join("*").to_s]
- unwritable_files = files.reject {|f| File.writable?(f) }
- sudo_needed = !unwritable_files.empty?
- if sudo_needed
- Bundler.ui.warn "Following files may not be writable, so sudo is needed:\n #{unwritable_files.map(&:to_s).sort.join("\n ")}"
- end
- end
-
- @requires_sudo_ran = true
- @requires_sudo = settings.allow_sudo? && sudo_present && sudo_needed
- end
-
def mkdir_p(path, options = {})
- if requires_sudo? && !options[:no_sudo]
- sudo "mkdir -p '#{path}'" unless File.exist?(path)
- else
- SharedHelpers.filesystem_access(path, :write) do |p|
- FileUtils.mkdir_p(p)
- end
+ SharedHelpers.filesystem_access(path, :write) do |p|
+ FileUtils.mkdir_p(p)
end
end
@@ -539,31 +507,6 @@ EOF
end
end
- def sudo(str)
- SUDO_MUTEX.synchronize do
- prompt = "\n\n" + <<-PROMPT.gsub(/^ {6}/, "").strip + " "
- Your user account isn't allowed to install to the system RubyGems.
- You can cancel this installation and run:
-
- bundle config set --local path 'vendor/bundle'
- bundle install
-
- to install the gems into ./vendor/bundle/, or you can enter your password
- and install the bundled gems to RubyGems using sudo.
-
- Password:
- PROMPT
-
- unless @prompted_for_sudo ||= system(%(sudo -k -p "#{prompt}" true))
- raise SudoNotPermittedError,
- "Bundler requires sudo access to install at the moment. " \
- "Try installing again, granting Bundler sudo access when prompted, or installing into a different path."
- end
-
- `sudo -p "#{prompt}" #{str}`
- end
- end
-
def read_file(file)
SharedHelpers.filesystem_access(file, :read) do
File.open(file, "r:UTF-8", &:read)
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index 851ae9b840..1765621cb3 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -94,9 +94,8 @@ module Bundler
def warn_if_root
return if Bundler.settings[:silence_root_warning] || Gem.win_platform? || !Process.uid.zero?
- Bundler.ui.warn "Don't run Bundler as root. Bundler can ask for sudo " \
- "if it is needed, and installing your bundle as root will break this " \
- "application for all non-root users on this machine.", :wrap => true
+ Bundler.ui.warn "Don't run Bundler as root. Installing your bundle as root " \
+ "will break this application for all non-root users on this machine.", :wrap => true
end
def dependencies_count_for(definition)
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 8bd9e11f32..79369ec374 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -485,7 +485,7 @@ module Bundler
@resolver ||= begin
last_resolve = converge_locked_specs
remove_ruby_from_platforms_if_necessary!(dependencies)
- Resolver.new(source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
+ Resolver.new(source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve(last_resolve), platforms)
end
end
@@ -878,9 +878,9 @@ module Bundler
end
end
- def additional_base_requirements_for_resolve
+ def additional_base_requirements_for_resolve(last_resolve)
return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
- converge_specs(@originally_locked_specs).map do |locked_spec|
+ converge_specs(@originally_locked_specs - last_resolve).map do |locked_spec|
Dependency.new(locked_spec.name, ">= #{locked_spec.version}")
end.uniq
end
diff --git a/lib/bundler/errors.rb b/lib/bundler/errors.rb
index f10b6cc68f..15069065ff 100644
--- a/lib/bundler/errors.rb
+++ b/lib/bundler/errors.rb
@@ -55,7 +55,6 @@ module Bundler
class CyclicDependencyError < BundlerError; status_code(21); end
class GemfileLockNotFound < BundlerError; status_code(22); end
class PluginError < BundlerError; status_code(29); end
- class SudoNotPermittedError < BundlerError; status_code(30); end
class ThreadCreationError < BundlerError; status_code(33); end
class APIResponseMismatchError < BundlerError; status_code(34); end
class APIResponseInvalidDependenciesError < BundlerError; status_code(35); end
diff --git a/lib/bundler/feature_flag.rb b/lib/bundler/feature_flag.rb
index e441b941c2..983de3137c 100644
--- a/lib/bundler/feature_flag.rb
+++ b/lib/bundler/feature_flag.rb
@@ -39,7 +39,6 @@ module Bundler
settings_flag(:setup_makes_kernel_gem_public) { !bundler_3_mode? }
settings_flag(:suppress_install_using_messages) { bundler_3_mode? }
settings_flag(:update_requires_all_flag) { bundler_4_mode? }
- settings_flag(:use_gem_version_promoter_for_major_updates) { bundler_3_mode? }
settings_option(:default_cli_command) { bundler_3_mode? ? :cli_help : :install }
diff --git a/lib/bundler/gem_version_promoter.rb b/lib/bundler/gem_version_promoter.rb
index ddf7446dd2..1ae41e2928 100644
--- a/lib/bundler/gem_version_promoter.rb
+++ b/lib/bundler/gem_version_promoter.rb
@@ -55,19 +55,17 @@ module Bundler
@level = v
end
- # Given a Dependency and an Array of SpecGroups of available versions for a
- # gem, this method will return the Array of SpecGroups sorted (and possibly
+ # Given a Dependency and an Array of Specifications of available versions for a
+ # gem, this method will return the Array of Specifications sorted (and possibly
# truncated if strict is true) in an order to give preference to the current
# level (:major, :minor or :patch) when resolution is deciding what versions
# best resolve all dependencies in the bundle.
# @param dep [Dependency] The Dependency of the gem.
- # @param spec_groups [SpecGroup] An array of SpecGroups for the same gem
+ # @param spec_groups [Specification] An array of Specifications for the same gem
# named in the @dep param.
- # @return [SpecGroup] A new instance of the SpecGroup Array sorted and
+ # @return [Specification] A new instance of the Specification Array sorted and
# possibly filtered.
def sort_versions(dep, spec_groups)
- before_result = "before sort_versions: #{debug_format_result(dep, spec_groups).inspect}" if DEBUG
-
@sort_versions[dep] ||= begin
gem_name = dep.name
@@ -79,11 +77,6 @@ module Bundler
filter_dep_specs(spec_groups, locked_spec)
else
sort_dep_specs(spec_groups, locked_spec)
- end.tap do |specs|
- if DEBUG
- puts before_result
- puts " after sort_versions: #{debug_format_result(dep, specs).inspect}"
- end
end
end
end
@@ -183,12 +176,5 @@ module Bundler
move, keep = result.partition {|s| s.version.to_s == version.to_s }
keep.concat(move)
end
-
- def debug_format_result(dep, spec_groups)
- a = [dep.to_s,
- spec_groups.map {|sg| [sg.version, sg.dependencies_for_activated_platforms.map {|dp| [dp.name, dp.requirement.to_s] }] }]
- last_map = a.last.map {|sg_data| [sg_data.first.version, sg_data.last.map {|aa| aa.join(" ") }] }
- [a.first, last_map, level, strict ? :strict : :not_strict]
- end
end
end
diff --git a/lib/bundler/man/bundle-add.1 b/lib/bundler/man/bundle-add.1
index 62177095d0..e5f1e228b5 100644
--- a/lib/bundler/man/bundle-add.1
+++ b/lib/bundler/man/bundle-add.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-ADD" "1" "July 2022" "" ""
+.TH "BUNDLE\-ADD" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1
index 9c57c7c9c5..d1204104b1 100644
--- a/lib/bundler/man/bundle-binstubs.1
+++ b/lib/bundler/man/bundle-binstubs.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-BINSTUBS" "1" "July 2022" "" ""
+.TH "BUNDLE\-BINSTUBS" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1
index fdaaa3b92a..1393caec65 100644
--- a/lib/bundler/man/bundle-cache.1
+++ b/lib/bundler/man/bundle-cache.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CACHE" "1" "July 2022" "" ""
+.TH "BUNDLE\-CACHE" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application
diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1
index 5be7886274..71ddb5cee3 100644
--- a/lib/bundler/man/bundle-check.1
+++ b/lib/bundler/man/bundle-check.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CHECK" "1" "July 2022" "" ""
+.TH "BUNDLE\-CHECK" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems
diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1
index 2bb95ed2de..e5dc4ccf92 100644
--- a/lib/bundler/man/bundle-clean.1
+++ b/lib/bundler/man/bundle-clean.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CLEAN" "1" "July 2022" "" ""
+.TH "BUNDLE\-CLEAN" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory
diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1
index 9f7887ca91..ffc91ed492 100644
--- a/lib/bundler/man/bundle-config.1
+++ b/lib/bundler/man/bundle-config.1
@@ -1,13 +1,22 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-CONFIG" "1" "July 2022" "" ""
+.TH "BUNDLE\-CONFIG" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-config\fR \- Set bundler configuration options
.
.SH "SYNOPSIS"
-\fBbundle config\fR [list|get|set|unset] [\fIname\fR [\fIvalue\fR]]
+\fBbundle config\fR list
+.
+.br
+\fBbundle config\fR [get] NAME
+.
+.br
+\fBbundle config\fR [set] NAME VALUE
+.
+.br
+\fBbundle config\fR unset NAME
.
.SH "DESCRIPTION"
This command allows you to interact with Bundler\'s configuration system\.
diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn
index 905c85fcd9..6f9edc9c39 100644
--- a/lib/bundler/man/bundle-config.1.ronn
+++ b/lib/bundler/man/bundle-config.1.ronn
@@ -3,7 +3,10 @@ bundle-config(1) -- Set bundler configuration options
## SYNOPSIS
-`bundle config` [list|get|set|unset] [<name> [<value>]]
+`bundle config` list<br>
+`bundle config` [get] NAME<br>
+`bundle config` [set] NAME VALUE<br>
+`bundle config` unset NAME
## DESCRIPTION
diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1
index 6aad9858db..3f18aaf569 100644
--- a/lib/bundler/man/bundle-doctor.1
+++ b/lib/bundler/man/bundle-doctor.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-DOCTOR" "1" "July 2022" "" ""
+.TH "BUNDLE\-DOCTOR" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-doctor\fR \- Checks the bundle for common problems
diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1
index 210dd178e8..7f6a892f6c 100644
--- a/lib/bundler/man/bundle-exec.1
+++ b/lib/bundler/man/bundle-exec.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-EXEC" "1" "July 2022" "" ""
+.TH "BUNDLE\-EXEC" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-exec\fR \- Execute a command in the context of the bundle
diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1
index 0fb6f7d0ab..63d611bdd2 100644
--- a/lib/bundler/man/bundle-gem.1
+++ b/lib/bundler/man/bundle-gem.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-GEM" "1" "July 2022" "" ""
+.TH "BUNDLE\-GEM" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem
diff --git a/lib/bundler/man/bundle-help.1 b/lib/bundler/man/bundle-help.1
new file mode 100644
index 0000000000..c089342582
--- /dev/null
+++ b/lib/bundler/man/bundle-help.1
@@ -0,0 +1,13 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-HELP" "1" "August 2022" "" ""
+.
+.SH "NAME"
+\fBbundle\-help\fR \- Displays detailed help for each subcommand
+.
+.SH "SYNOPSIS"
+\fBbundle help\fR [COMMAND]
+.
+.SH "DESCRIPTION"
+Displays detailed help for the given subcommand\. You can specify a single \fBCOMMAND\fR at the same time\. When \fBCOMMAND\fR is omitted, help for \fBhelp\fR command will be displayed\.
diff --git a/lib/bundler/man/bundle-help.1.ronn b/lib/bundler/man/bundle-help.1.ronn
new file mode 100644
index 0000000000..0e144aead7
--- /dev/null
+++ b/lib/bundler/man/bundle-help.1.ronn
@@ -0,0 +1,12 @@
+bundle-help(1) -- Displays detailed help for each subcommand
+============================================================
+
+## SYNOPSIS
+
+`bundle help` [COMMAND]
+
+## DESCRIPTION
+
+Displays detailed help for the given subcommand.
+You can specify a single `COMMAND` at the same time.
+When `COMMAND` is omitted, help for `help` command will be displayed.
diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1
index d3bad843b8..ae9bc48539 100644
--- a/lib/bundler/man/bundle-info.1
+++ b/lib/bundler/man/bundle-info.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INFO" "1" "July 2022" "" ""
+.TH "BUNDLE\-INFO" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-info\fR \- Show information for the given gem in your bundle
diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1
index 0b3abfeefc..0b06ce8997 100644
--- a/lib/bundler/man/bundle-init.1
+++ b/lib/bundler/man/bundle-init.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INIT" "1" "July 2022" "" ""
+.TH "BUNDLE\-INIT" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-init\fR \- Generates a Gemfile into the current working directory
diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1
index 53f2eaae0a..4ad37ec3eb 100644
--- a/lib/bundler/man/bundle-inject.1
+++ b/lib/bundler/man/bundle-inject.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INJECT" "1" "July 2022" "" ""
+.TH "BUNDLE\-INJECT" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile
diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1
index 8e94fe2437..077a58f415 100644
--- a/lib/bundler/man/bundle-install.1
+++ b/lib/bundler/man/bundle-install.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-INSTALL" "1" "July 2022" "" ""
+.TH "BUNDLE\-INSTALL" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-install\fR \- Install the dependencies specified in your Gemfile
@@ -170,35 +170,6 @@ As a result, \fBbundle install \-\-deployment\fR installs gems to the \fBvendor/
.
.IP "" 0
.
-.SH "SUDO USAGE"
-By default, Bundler installs gems to the same location as \fBgem install\fR\.
-.
-.P
-In some cases, that location may not be writable by your Unix user\. In that case, Bundler will stage everything in a temporary directory, then ask you for your \fBsudo\fR password in order to copy the gems into their system location\.
-.
-.P
-From your perspective, this is identical to installing the gems directly into the system\.
-.
-.P
-You should never use \fBsudo bundle install\fR\. This is because several other steps in \fBbundle install\fR must be performed as the current user:
-.
-.IP "\(bu" 4
-Updating your \fBGemfile\.lock\fR
-.
-.IP "\(bu" 4
-Updating your \fBvendor/cache\fR, if necessary
-.
-.IP "\(bu" 4
-Checking out private git repositories using your user\'s SSH keys
-.
-.IP "" 0
-.
-.P
-Of these three, the first two could theoretically be performed by \fBchown\fRing the resulting files to \fB$SUDO_USER\fR\. The third, however, can only be performed by invoking the \fBgit\fR command as the current user\. Therefore, git gems are downloaded and installed into \fB~/\.bundle\fR rather than $GEM_HOME or $BUNDLE_PATH\.
-.
-.P
-As a result, you should run \fBbundle install\fR as the current user, and Bundler will ask for your password if it is needed to put the gems into their final location\.
-.
.SH "INSTALLING GROUPS"
By default, \fBbundle install\fR will install all gems in all groups in your Gemfile(5), except those declared for a different platform\.
.
diff --git a/lib/bundler/man/bundle-install.1.ronn b/lib/bundler/man/bundle-install.1.ronn
index 47200ac2d5..be9ed0f974 100644
--- a/lib/bundler/man/bundle-install.1.ronn
+++ b/lib/bundler/man/bundle-install.1.ronn
@@ -224,35 +224,6 @@ will cause an error when the Gemfile(5) is modified.
the `vendor/bundle` directory in the application. This may be
overridden using the `--path` option.
-## SUDO USAGE
-
-By default, Bundler installs gems to the same location as `gem install`.
-
-In some cases, that location may not be writable by your Unix user. In
-that case, Bundler will stage everything in a temporary directory,
-then ask you for your `sudo` password in order to copy the gems into
-their system location.
-
-From your perspective, this is identical to installing the gems
-directly into the system.
-
-You should never use `sudo bundle install`. This is because several
-other steps in `bundle install` must be performed as the current user:
-
-* Updating your `Gemfile.lock`
-* Updating your `vendor/cache`, if necessary
-* Checking out private git repositories using your user's SSH keys
-
-Of these three, the first two could theoretically be performed by
-`chown`ing the resulting files to `$SUDO_USER`. The third, however,
-can only be performed by invoking the `git` command as
-the current user. Therefore, git gems are downloaded and installed
-into `~/.bundle` rather than $GEM_HOME or $BUNDLE_PATH.
-
-As a result, you should run `bundle install` as the current user,
-and Bundler will ask for your password if it is needed to put the
-gems into their final location.
-
## INSTALLING GROUPS
By default, `bundle install` will install all gems in all groups
diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1
index 3a9cc9a237..6e89f810a1 100644
--- a/lib/bundler/man/bundle-list.1
+++ b/lib/bundler/man/bundle-list.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-LIST" "1" "July 2022" "" ""
+.TH "BUNDLE\-LIST" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-list\fR \- List all the gems in the bundle
diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1
index ac03c5478e..f5f0ce2bdb 100644
--- a/lib/bundler/man/bundle-lock.1
+++ b/lib/bundler/man/bundle-lock.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-LOCK" "1" "July 2022" "" ""
+.TH "BUNDLE\-LOCK" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-lock\fR \- Creates / Updates a lockfile without installing
diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1
index be6c5af248..7bda0afd33 100644
--- a/lib/bundler/man/bundle-open.1
+++ b/lib/bundler/man/bundle-open.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-OPEN" "1" "July 2022" "" ""
+.TH "BUNDLE\-OPEN" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1
index fc3d5e8caf..a2b8e2bf92 100644
--- a/lib/bundler/man/bundle-outdated.1
+++ b/lib/bundler/man/bundle-outdated.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-OUTDATED" "1" "July 2022" "" ""
+.TH "BUNDLE\-OUTDATED" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-outdated\fR \- List installed gems with newer versions available
diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1
index f5a90c59e9..7fda4ef046 100644
--- a/lib/bundler/man/bundle-platform.1
+++ b/lib/bundler/man/bundle-platform.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-PLATFORM" "1" "July 2022" "" ""
+.TH "BUNDLE\-PLATFORM" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-platform\fR \- Displays platform compatibility information
diff --git a/lib/bundler/man/bundle-plugin.1 b/lib/bundler/man/bundle-plugin.1
new file mode 100644
index 0000000000..7210806327
--- /dev/null
+++ b/lib/bundler/man/bundle-plugin.1
@@ -0,0 +1,81 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-PLUGIN" "1" "August 2022" "" ""
+.
+.SH "NAME"
+\fBbundle\-plugin\fR \- Manage Bundler plugins
+.
+.SH "SYNOPSIS"
+\fBbundle plugin\fR install PLUGINS [\-\-source=\fISOURCE\fR] [\-\-version=\fIversion\fR] [\-\-git|\-\-local_git=\fIgit\-url\fR] [\-\-branch=\fIbranch\fR|\-\-ref=\fIrev\fR]
+.
+.br
+\fBbundle plugin\fR uninstall PLUGINS
+.
+.br
+\fBbundle plugin\fR list
+.
+.br
+\fBbundle plugin\fR help [COMMAND]
+.
+.SH "DESCRIPTION"
+You can install, uninstall, and list plugin(s) with this command to extend functionalities of Bundler\.
+.
+.SH "SUB\-COMMANDS"
+.
+.SS "install"
+Install the given plugin(s)\.
+.
+.IP "\(bu" 4
+\fBbundle plugin install bundler\-graph\fR: Install bundler\-graph gem from RubyGems\.org\. The global source, specified in source in Gemfile is ignored\.
+.
+.IP "\(bu" 4
+\fBbundle plugin install bundler\-graph \-\-source https://example\.com\fR: Install bundler\-graph gem from example\.com\. The global source, specified in source in Gemfile is not considered\.
+.
+.IP "\(bu" 4
+\fBbundle plugin install bundler\-graph \-\-version 0\.2\.1\fR: You can specify the version of the gem via \fB\-\-version\fR\.
+.
+.IP "\(bu" 4
+\fBbundle plugin install bundler\-graph \-\-git https://github\.com/rubygems/bundler\-graph\fR: Install bundler\-graph gem from Git repository\. \fB\-\-git\fR can be replaced with \fB\-\-local\-git\fR\. You cannot use both \fB\-\-git\fR and \fB\-\-local\-git\fR\. You can use standard Git URLs like:
+.
+.IP "\(bu" 4
+\fBssh://[user@]host\.xz[:port]/path/to/repo\.git\fR
+.
+.IP "\(bu" 4
+\fBhttp[s]://host\.xz[:port]/path/to/repo\.git\fR
+.
+.IP "\(bu" 4
+\fB/path/to/repo\fR
+.
+.IP "\(bu" 4
+\fBfile:///path/to/repo\fR
+.
+.IP "" 0
+.
+.IP
+When you specify \fB\-\-git\fR/\fB\-\-local\-git\fR, you can use \fB\-\-branch\fR or \fB\-\-ref\fR to specify any branch, tag, or commit hash (revision) to use\. When you specify both, only the latter is used\.
+.
+.IP "" 0
+.
+.SS "uninstall"
+Uninstall the plugin(s) specified in PLUGINS\.
+.
+.SS "list"
+List the installed plugins and available commands\.
+.
+.P
+No options\.
+.
+.SS "help"
+Describe subcommands or one specific subcommand\.
+.
+.P
+No options\.
+.
+.SH "SEE ALSO"
+.
+.IP "\(bu" 4
+How to write a Bundler plugin \fIhttps://bundler\.io/guides/bundler_plugins\.html\fR
+.
+.IP "" 0
+
diff --git a/lib/bundler/man/bundle-plugin.1.ronn b/lib/bundler/man/bundle-plugin.1.ronn
new file mode 100644
index 0000000000..4f234eeba7
--- /dev/null
+++ b/lib/bundler/man/bundle-plugin.1.ronn
@@ -0,0 +1,59 @@
+bundle-plugin(1) -- Manage Bundler plugins
+==========================================
+
+## SYNOPSIS
+
+`bundle plugin` install PLUGINS [--source=<SOURCE>] [--version=<version>]
+ [--git|--local_git=<git-url>] [--branch=<branch>|--ref=<rev>]<br>
+`bundle plugin` uninstall PLUGINS<br>
+`bundle plugin` list<br>
+`bundle plugin` help [COMMAND]
+
+## DESCRIPTION
+
+You can install, uninstall, and list plugin(s) with this command to extend functionalities of Bundler.
+
+## SUB-COMMANDS
+
+### install
+
+Install the given plugin(s).
+
+* `bundle plugin install bundler-graph`:
+ Install bundler-graph gem from RubyGems.org. The global source, specified in source in Gemfile is ignored.
+
+* `bundle plugin install bundler-graph --source https://example.com`:
+ Install bundler-graph gem from example.com. The global source, specified in source in Gemfile is not considered.
+
+* `bundle plugin install bundler-graph --version 0.2.1`:
+ You can specify the version of the gem via `--version`.
+
+* `bundle plugin install bundler-graph --git https://github.com/rubygems/bundler-graph`:
+ Install bundler-graph gem from Git repository. `--git` can be replaced with `--local-git`. You cannot use both `--git` and `--local-git`. You can use standard Git URLs like:
+
+ * `ssh://[user@]host.xz[:port]/path/to/repo.git`
+ * `http[s]://host.xz[:port]/path/to/repo.git`
+ * `/path/to/repo`
+ * `file:///path/to/repo`
+
+ When you specify `--git`/`--local-git`, you can use `--branch` or `--ref` to specify any branch, tag, or commit hash (revision) to use. When you specify both, only the latter is used.
+
+### uninstall
+
+Uninstall the plugin(s) specified in PLUGINS.
+
+### list
+
+List the installed plugins and available commands.
+
+No options.
+
+### help
+
+Describe subcommands or one specific subcommand.
+
+No options.
+
+## SEE ALSO
+
+* [How to write a Bundler plugin](https://bundler.io/guides/bundler_plugins.html)
diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1
index 44e5a83a01..d635d24e2d 100644
--- a/lib/bundler/man/bundle-pristine.1
+++ b/lib/bundler/man/bundle-pristine.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-PRISTINE" "1" "July 2022" "" ""
+.TH "BUNDLE\-PRISTINE" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition
diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1
index 29ec246018..4952e8094e 100644
--- a/lib/bundler/man/bundle-remove.1
+++ b/lib/bundler/man/bundle-remove.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-REMOVE" "1" "July 2022" "" ""
+.TH "BUNDLE\-REMOVE" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-remove\fR \- Removes gems from the Gemfile
diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1
index 227b1c8a1e..72ef3283cc 100644
--- a/lib/bundler/man/bundle-show.1
+++ b/lib/bundler/man/bundle-show.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-SHOW" "1" "July 2022" "" ""
+.TH "BUNDLE\-SHOW" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem
diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1
index 7d0988bfa5..06ceef85db 100644
--- a/lib/bundler/man/bundle-update.1
+++ b/lib/bundler/man/bundle-update.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-UPDATE" "1" "July 2022" "" ""
+.TH "BUNDLE\-UPDATE" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-update\fR \- Update your gems to the latest available versions
diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1
index f6f51cde0e..cf63dd8f9e 100644
--- a/lib/bundler/man/bundle-viz.1
+++ b/lib/bundler/man/bundle-viz.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE\-VIZ" "1" "July 2022" "" ""
+.TH "BUNDLE\-VIZ" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile
diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1
index f683e78cc6..d178b2f5dc 100644
--- a/lib/bundler/man/bundle.1
+++ b/lib/bundler/man/bundle.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "BUNDLE" "1" "July 2022" "" ""
+.TH "BUNDLE" "1" "August 2022" "" ""
.
.SH "NAME"
\fBbundle\fR \- Ruby Dependency Management
@@ -55,7 +55,7 @@ Execute a script in the current bundle
Specify and read configuration options for Bundler
.
.TP
-\fBbundle help(1)\fR
+\fBbundle help(1)\fR \fIbundle\-help\.1\.html\fR
Display detailed help for each subcommand
.
.SH "UTILITIES"
@@ -120,6 +120,10 @@ Display warnings about common problems
\fBbundle remove(1)\fR \fIbundle\-remove\.1\.html\fR
Removes gems from the Gemfile
.
+.TP
+\fBbundle plugin(1)\fR \fIbundle\-plugin\.1\.html\fR
+Manage Bundler plugins
+.
.SH "PLUGINS"
When running a command that isn\'t listed in PRIMARY COMMANDS or UTILITIES, Bundler will try to find an executable on your path named \fBbundler\-<command>\fR and execute it, passing down any extra arguments to it\.
.
diff --git a/lib/bundler/man/bundle.1.ronn b/lib/bundler/man/bundle.1.ronn
index 8f0159eee5..35c0a7ef87 100644
--- a/lib/bundler/man/bundle.1.ronn
+++ b/lib/bundler/man/bundle.1.ronn
@@ -46,7 +46,7 @@ We divide `bundle` subcommands into primary commands and utilities:
* [`bundle config(1)`](bundle-config.1.html):
Specify and read configuration options for Bundler
-* `bundle help(1)`:
+* [`bundle help(1)`](bundle-help.1.html):
Display detailed help for each subcommand
## UTILITIES
@@ -97,6 +97,9 @@ We divide `bundle` subcommands into primary commands and utilities:
* [`bundle remove(1)`](bundle-remove.1.html):
Removes gems from the Gemfile
+* [`bundle plugin(1)`](bundle-plugin.1.html):
+ Manage Bundler plugins
+
## PLUGINS
When running a command that isn't listed in PRIMARY COMMANDS or UTILITIES,
diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5
index 63a16ca3ff..3d3994153b 100644
--- a/lib/bundler/man/gemfile.5
+++ b/lib/bundler/man/gemfile.5
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "GEMFILE" "5" "July 2022" "" ""
+.TH "GEMFILE" "5" "August 2022" "" ""
.
.SH "NAME"
\fBGemfile\fR \- A format for describing gem dependencies for Ruby programs
diff --git a/lib/bundler/man/index.txt b/lib/bundler/man/index.txt
index ef2956b2f9..6de81ea027 100644
--- a/lib/bundler/man/index.txt
+++ b/lib/bundler/man/index.txt
@@ -9,6 +9,7 @@ bundle-config(1) bundle-config.1
bundle-doctor(1) bundle-doctor.1
bundle-exec(1) bundle-exec.1
bundle-gem(1) bundle-gem.1
+bundle-help(1) bundle-help.1
bundle-info(1) bundle-info.1
bundle-init(1) bundle-init.1
bundle-inject(1) bundle-inject.1
@@ -18,6 +19,7 @@ bundle-lock(1) bundle-lock.1
bundle-open(1) bundle-open.1
bundle-outdated(1) bundle-outdated.1
bundle-platform(1) bundle-platform.1
+bundle-plugin(1) bundle-plugin.1
bundle-pristine(1) bundle-pristine.1
bundle-remove(1) bundle-remove.1
bundle-show(1) bundle-show.1
diff --git a/lib/bundler/match_remote_metadata.rb b/lib/bundler/match_remote_metadata.rb
index e1b2f4d0e2..5e46d52441 100644
--- a/lib/bundler/match_remote_metadata.rb
+++ b/lib/bundler/match_remote_metadata.rb
@@ -2,8 +2,11 @@
module Bundler
module FetchMetadata
+ # A fallback is included because the original version of the specification
+ # API didn't include that field, so some marshalled specs in the index have it
+ # set to +nil+.
def matches_current_ruby?
- @required_ruby_version ||= _remote_specification.required_ruby_version
+ @required_ruby_version ||= _remote_specification.required_ruby_version || Gem::Requirement.default
super
end
diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb
index 158c69e1a1..26458bd596 100644
--- a/lib/bundler/plugin.rb
+++ b/lib/bundler/plugin.rb
@@ -36,6 +36,8 @@ module Bundler
# @param [Hash] options various parameters as described in description.
# Refer to cli/plugin for available options
def install(names, options)
+ raise InvalidOption, "You cannot specify `--branch` and `--ref` at the same time." if options["branch"] && options["ref"]
+
specs = Installer.new.install(names, options)
save_plugins names, specs
diff --git a/lib/bundler/plugin/installer/rubygems.rb b/lib/bundler/plugin/installer/rubygems.rb
index 7277234d9a..cb5db9c30e 100644
--- a/lib/bundler/plugin/installer/rubygems.rb
+++ b/lib/bundler/plugin/installer/rubygems.rb
@@ -6,10 +6,6 @@ module Bundler
class Rubygems < Bundler::Source::Rubygems
private
- def requires_sudo?
- false # Will change on implementation of project level plugins
- end
-
def rubygems_dir
Plugin.root
end
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index a74af45027..fcb3812c5a 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -3,6 +3,7 @@
module Bundler
class Resolver
require_relative "vendored_molinillo"
+ require_relative "resolver/base"
require_relative "resolver/spec_group"
include GemHelpers
@@ -25,15 +26,13 @@ module Bundler
def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
@source_requirements = source_requirements
- @base = base
+ @base = Resolver::Base.new(base, additional_base_requirements)
@resolver = Molinillo::Resolver.new(self, self)
@results_for = {}
@search_for = {}
- @additional_base_requirements = additional_base_requirements
@platforms = platforms
@resolving_only_for_ruby = platforms == [Gem::Platform::RUBY]
@gem_version_promoter = gem_version_promoter
- @use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
end
def start(requirements, exclude_specs: [])
@@ -43,18 +42,11 @@ module Bundler
remove_from_candidates(spec)
end
- @base_dg = Molinillo::DependencyGraph.new
- @base.each do |ls|
- dep = Dependency.new(ls.name, ls.version)
- @base_dg.add_vertex(ls.name, DepProxy.get_proxy(dep, ls.platform), true)
- end
- @additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) }
-
@gem_version_promoter.prerelease_specified = @prerelease_specified = {}
requirements.each {|dep| @prerelease_specified[dep.name] ||= dep.prerelease? }
verify_gemfile_dependencies_are_found!(requirements)
- result = @resolver.resolve(requirements, @base_dg).
+ result = @resolver.resolve(requirements).
map(&:payload).
reject {|sg| sg.name.end_with?("\0") }.
map(&:to_specs).
@@ -62,8 +54,20 @@ module Bundler
SpecSet.new(SpecSet.new(result).for(regular_requirements, false, @platforms))
rescue Molinillo::VersionConflict => e
+ conflicts = e.conflicts
+
+ deps_to_unlock = conflicts.values.inject([]) do |deps, conflict|
+ deps |= conflict.requirement_trees.flatten.map {|req| base_requirements[req.name] }.compact
+ end
+
+ if deps_to_unlock.any?
+ @base.unlock_deps(deps_to_unlock)
+ reset_spec_cache
+ retry
+ end
+
message = version_conflict_message(e)
- raise VersionConflict.new(e.conflicts.keys.uniq, message)
+ raise VersionConflict.new(conflicts.keys.uniq, message)
rescue Molinillo::CircularDependencyError => e
names = e.dependencies.sort_by(&:name).map {|d| "gem '#{d.name}'" }
raise CyclicDependencyError, "Your bundle requires gems that depend" \
@@ -118,31 +122,22 @@ module Bundler
dependency = dependency_proxy.dep
name = dependency.name
@search_for[dependency_proxy] ||= begin
- results = results_for(dependency) + @base[name].select {|spec| requirement_satisfied_by?(dependency, nil, spec) }
+ locked_results = @base[name].select {|spec| requirement_satisfied_by?(dependency, nil, spec) }
+ locked_requirement = base_requirements[name]
+ results = results_for(dependency) + locked_results
+ results = results.select {|spec| requirement_satisfied_by?(locked_requirement, nil, spec) } if locked_requirement
- if vertex = @base_dg.vertex_named(name)
- locked_requirement = vertex.payload.requirement
- end
-
- if !@prerelease_specified[name] && (!@use_gvp || locked_requirement.nil?)
+ if !@prerelease_specified[name] && locked_results.empty?
# Move prereleases to the beginning of the list, so they're considered
# last during resolution.
pre, results = results.partition {|spec| spec.version.prerelease? }
results = pre + results
end
- spec_groups = if results.any?
- nested = []
- results.each do |spec|
- version, specs = nested.last
- if version == spec.version
- specs << spec
- else
- nested << [spec.version, [spec]]
- end
- end
- nested.reduce([]) do |groups, (version, specs)|
- next groups if locked_requirement && !locked_requirement.satisfied_by?(version)
+ if results.any?
+ results = @gem_version_promoter.sort_versions(dependency, results)
+
+ results.group_by(&:version).reduce([]) do |groups, (_, specs)|
next groups unless specs.any? {|spec| spec.match_platform(platform) }
specs_by_platform = Hash.new do |current_specs, current_platform|
@@ -165,13 +160,6 @@ module Bundler
else
[]
end
- # GVP handles major itself, but it's still a bit risky to trust it with it
- # until we get it settled with new behavior. For 2.x it can take over all cases.
- if !@use_gvp
- spec_groups
- else
- @gem_version_promoter.sort_versions(dependency, spec_groups)
- end
end
end
@@ -197,12 +185,6 @@ module Bundler
"Gemfile"
end
- def name_for_locking_dependency_source
- Bundler.default_lockfile.basename.to_s
- rescue StandardError
- "Gemfile.lock"
- end
-
def requirement_satisfied_by?(requirement, activated, spec)
requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
end
@@ -216,7 +198,7 @@ module Bundler
name = name_for(dependency)
vertex = activated.vertex_named(name)
[
- @base_dg.vertex_named(name) ? 0 : 1,
+ @base[name].any? ? 0 : 1,
vertex.payload ? 0 : 1,
vertex.root? ? 0 : 1,
amount_constrained(dependency),
@@ -235,9 +217,12 @@ module Bundler
private
+ def base_requirements
+ @base.base_requirements
+ end
+
def remove_from_candidates(spec)
@base.delete(spec)
- @gem_version_promoter.reset
@results_for.keys.each do |dep|
next unless dep.name == spec.name
@@ -245,7 +230,12 @@ module Bundler
@results_for[dep].reject {|s| s.name == spec.name && s.version == spec.version }
end
+ reset_spec_cache
+ end
+
+ def reset_spec_cache
@search_for = {}
+ @gem_version_promoter.reset
end
# returns an integer \in (-\infty, 0]
@@ -337,18 +327,6 @@ module Bundler
e.message_with_trees(
:full_message_for_conflict => lambda do |name, conflict|
- o = if name.end_with?("\0")
- String.new("Bundler found conflicting requirements for the #{name} version:")
- else
- String.new("Bundler could not find compatible versions for gem \"#{name}\":")
- end
- o << %(\n)
- if conflict.locked_requirement
- o << %( In snapshot (#{name_for_locking_dependency_source}):\n)
- o << %( #{SharedHelpers.pretty_dependency(conflict.locked_requirement)}\n)
- o << %(\n)
- end
- o << %( In #{name_for_explicit_dependency_source}:\n)
trees = conflict.requirement_trees
# called first, because we want to reduce the amount of work required to find maximal empty sets
@@ -367,30 +345,41 @@ module Bundler
trees.sort_by! {|t| t.reverse.map(&:name) }
end
- o << trees.map do |tree|
- t = "".dup
- depth = 2
+ if trees.size > 1 || name == "bundler"
+ o = if name.end_with?("\0")
+ String.new("Bundler found conflicting requirements for the #{name} version:")
+ else
+ String.new("Bundler could not find compatible versions for gem \"#{name}\":")
+ end
+ o << %(\n)
+ o << %( In #{name_for_explicit_dependency_source}:\n)
+ o << trees.map do |tree|
+ t = "".dup
+ depth = 2
- base_tree = tree.first
- base_tree_name = base_tree.name
+ base_tree = tree.first
+ base_tree_name = base_tree.name
- if base_tree_name.end_with?("\0")
- t = nil
- else
- tree.each do |req|
- t << " " * depth << SharedHelpers.pretty_dependency(req)
- unless tree.last == req
- if spec = conflict.activated_by_name[req.name]
- t << %( was resolved to #{spec.version}, which)
+ if base_tree_name.end_with?("\0")
+ t = nil
+ else
+ tree.each do |req|
+ t << " " * depth << SharedHelpers.pretty_dependency(req)
+ unless tree.last == req
+ if spec = conflict.activated_by_name[req.name]
+ t << %( was resolved to #{spec.version}, which)
+ end
+ t << %( depends on)
end
- t << %( depends on)
+ t << %(\n)
+ depth += 1
end
- t << %(\n)
- depth += 1
end
- end
- t
- end.compact.join("\n")
+ t
+ end.compact.join("\n")
+ else
+ o = String.new
+ end
if name == "bundler"
o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
@@ -414,17 +403,13 @@ module Bundler
end
elsif name.end_with?("\0")
o << %(\n Current #{name} version:\n #{SharedHelpers.pretty_dependency(@metadata_requirements.find {|req| req.name == name })}\n\n)
- elsif conflict.locked_requirement
- o << "\n"
- o << %(Deleting your #{name_for_locking_dependency_source} file and running `bundle install` will rebuild your snapshot from scratch, using only\n)
- o << %(the gems in your Gemfile, which may resolve the conflict.\n)
elsif !conflict.existing
o << "\n"
relevant_source = conflict.requirement.source || source_for(name)
- extra_message = if conflict.requirement_trees.first.size > 1
- ", which is required by gem '#{SharedHelpers.pretty_dependency(conflict.requirement_trees.first[-2])}',"
+ extra_message = if trees.first.size > 1
+ ", which is required by gem '#{SharedHelpers.pretty_dependency(trees.first[-2])}',"
else
""
end
diff --git a/lib/bundler/resolver/base.rb b/lib/bundler/resolver/base.rb
new file mode 100644
index 0000000000..84e087b0ae
--- /dev/null
+++ b/lib/bundler/resolver/base.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Bundler
+ class Resolver
+ class Base
+ def initialize(base, additional_base_requirements)
+ @base = base
+ @additional_base_requirements = additional_base_requirements
+ end
+
+ def [](name)
+ @base[name]
+ end
+
+ def delete(spec)
+ @base.delete(spec)
+ end
+
+ def base_requirements
+ @base_requirements ||= build_base_requirements
+ end
+
+ def unlock_deps(deps)
+ exact, lower_bound = deps.partition(&:specific?)
+
+ exact.each do |exact_dep|
+ @base.delete_by_name_and_version(exact_dep.name, exact_dep.requirement.requirements.first.last)
+ end
+
+ lower_bound.each do |lower_bound_dep|
+ @additional_base_requirements.delete(lower_bound_dep)
+ end
+
+ @base_requirements = nil
+ end
+
+ private
+
+ def build_base_requirements
+ base_requirements = {}
+ @base.each do |ls|
+ dep = Dependency.new(ls.name, ls.version)
+ base_requirements[ls.name] = DepProxy.get_proxy(dep, ls.platform)
+ end
+ @additional_base_requirements.each {|d| base_requirements[d.name] = d }
+ base_requirements
+ end
+ end
+ end
+end
diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb
index 08af0610c6..d14075c96b 100644
--- a/lib/bundler/rubygems_integration.rb
+++ b/lib/bundler/rubygems_integration.rb
@@ -504,10 +504,6 @@ module Bundler
Gem::Package.build(spec, skip_validation)
end
- def repository_subdirectories
- Gem::REPOSITORY_SUBDIRECTORIES
- end
-
def path_separator
Gem.path_separator
end
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb
index cf5675274e..a76a792743 100644
--- a/lib/bundler/settings.rb
+++ b/lib/bundler/settings.rb
@@ -45,7 +45,6 @@ module Bundler
silence_root_warning
suppress_install_using_messages
update_requires_all_flag
- use_gem_version_promoter_for_major_updates
].freeze
NUMBER_KEYS = %w[
@@ -278,12 +277,6 @@ module Bundler
end
end
- def allow_sudo?
- key = key_for(:path)
- path_configured = @temporary.key?(key) || @local_config.key?(key)
- !path_configured
- end
-
def ignore_config?
ENV["BUNDLE_IGNORE_CONFIG"]
end
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb
index ed66dcdc12..fd34edffb7 100644
--- a/lib/bundler/source/git.rb
+++ b/lib/bundler/source/git.rb
@@ -102,13 +102,7 @@ module Bundler
@install_path ||= begin
git_scope = "#{base_name}-#{shortref_for_path(revision)}"
- path = Bundler.install_path.join(git_scope)
-
- if !path.exist? && Bundler.requires_sudo?
- Bundler.user_bundle_path.join(Bundler.ruby_scope).join(git_scope)
- else
- path
- end
+ Bundler.install_path.join(git_scope)
end
end
@@ -219,7 +213,7 @@ module Bundler
# across different projects, this cache will be shared.
# When using local git repos, this is set to the local repo.
def cache_path
- @cache_path ||= if Bundler.requires_sudo? || Bundler.feature_flag.global_gem_cache?
+ @cache_path ||= if Bundler.feature_flag.global_gem_cache?
Bundler.user_cache
else
Bundler.bundle_path.join("cache", "bundler")
diff --git a/lib/bundler/source/path/installer.rb b/lib/bundler/source/path/installer.rb
index a70973bde7..0af28fe770 100644
--- a/lib/bundler/source/path/installer.rb
+++ b/lib/bundler/source/path/installer.rb
@@ -18,13 +18,7 @@ module Bundler
@build_args = options[:build_args] || Bundler.rubygems.build_args
@gem_bin_dir = "#{Bundler.rubygems.gem_dir}/bin"
@disable_extensions = options[:disable_extensions]
-
- if Bundler.requires_sudo?
- @tmp_dir = Bundler.tmp(spec.full_name).to_s
- @bin_dir = "#{@tmp_dir}/bin"
- else
- @bin_dir = @gem_bin_dir
- end
+ @bin_dir = @gem_bin_dir
end
def post_install
@@ -38,25 +32,10 @@ module Bundler
generate_bin unless spec.executables.empty?
run_hooks(:post_install)
- ensure
- Bundler.rm_rf(@tmp_dir) if Bundler.requires_sudo?
end
private
- def generate_bin
- super
-
- if Bundler.requires_sudo?
- SharedHelpers.filesystem_access(@gem_bin_dir) do |p|
- Bundler.mkdir_p(p)
- end
- spec.executables.each do |exe|
- Bundler.sudo "cp -R #{@bin_dir}/#{exe} #{@gem_bin_dir}"
- end
- end
- end
-
def run_hooks(type)
hooks_meth = "#{type}_hooks"
return unless Gem.respond_to?(hooks_meth)
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index a50934b315..396465f0cb 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -160,15 +160,10 @@ module Bundler
return if Bundler.settings[:no_install]
- if requires_sudo?
- install_path = Bundler.tmp(spec.full_name)
- bin_path = install_path.join("bin")
- else
- install_path = rubygems_dir
- bin_path = Bundler.system_bindir
- end
+ install_path = rubygems_dir
+ bin_path = Bundler.system_bindir
- Bundler.mkdir_p bin_path, :no_sudo => true unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5")
+ Bundler.mkdir_p bin_path unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5")
require_relative "../rubygems_gem_installer"
@@ -209,34 +204,7 @@ module Bundler
spec.full_gem_path = installed_spec.full_gem_path
spec.loaded_from = installed_spec.loaded_from
- # SUDO HAX
- if requires_sudo?
- Bundler.rubygems.repository_subdirectories.each do |name|
- src = File.join(install_path, name, "*")
- dst = File.join(rubygems_dir, name)
- if name == "extensions" && Dir.glob(src).any?
- src = File.join(src, "*/*")
- ext_src = Dir.glob(src).first
- ext_src.gsub!(src[0..-6], "")
- dst = File.dirname(File.join(dst, ext_src))
- end
- SharedHelpers.filesystem_access(dst) do |p|
- Bundler.mkdir_p(p)
- end
- Bundler.sudo "cp -R #{src} #{dst}" if Dir[src].any?
- end
-
- spec.executables.each do |exe|
- SharedHelpers.filesystem_access(Bundler.system_bindir) do |p|
- Bundler.mkdir_p(p)
- end
- Bundler.sudo "cp -R #{install_path}/bin/#{exe} #{Bundler.system_bindir}/"
- end
- end
-
spec.post_install_message
- ensure
- Bundler.rm_rf(install_path) if requires_sudo?
end
def cache(spec, custom_path = nil)
@@ -475,38 +443,18 @@ module Bundler
gem_path = package_path(cache_path, spec)
return gem_path if File.exist?(gem_path)
- if requires_sudo?
- download_path = Bundler.tmp(spec.full_name)
- download_cache_path = default_cache_path_for(download_path)
- else
- download_cache_path = cache_path
- end
-
- SharedHelpers.filesystem_access(download_cache_path) do |p|
+ SharedHelpers.filesystem_access(cache_path) do |p|
FileUtils.mkdir_p(p)
end
- download_gem(spec, download_cache_path, previous_spec)
-
- if requires_sudo?
- SharedHelpers.filesystem_access(cache_path) do |p|
- Bundler.mkdir_p(p)
- end
- Bundler.sudo "mv #{package_path(download_cache_path, spec)} #{gem_path}"
- end
+ download_gem(spec, cache_path, previous_spec)
gem_path
- ensure
- Bundler.rm_rf(download_path) if requires_sudo?
end
def installed?(spec)
installed_specs[spec].any? && !spec.deleted_gem?
end
- def requires_sudo?
- Bundler.requires_sudo?
- end
-
def rubygems_dir
Bundler.bundle_path
end
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index 4965ca9e60..1d0b7a460d 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -114,10 +114,20 @@ module Bundler
SpecSet.new(arr)
end
+ def -(other)
+ SpecSet.new(to_a - other.to_a)
+ end
+
def find_by_name_and_platform(name, platform)
@specs.detect {|spec| spec.name == name && spec.match_platform(platform) }
end
+ def delete_by_name_and_version(name, version)
+ @specs.reject! {|spec| spec.name == name && spec.version == version }
+ @lookup = nil
+ @sorted = nil
+ end
+
def what_required(spec)
unless req = find {|s| s.dependencies.any? {|d| d.type == :runtime && d.name == spec.name } }
return [spec]
diff --git a/spec/bundler/bundler/bundler_spec.rb b/spec/bundler/bundler/bundler_spec.rb
index 9e79bc165f..764c55a91f 100644
--- a/spec/bundler/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler/bundler_spec.rb
@@ -189,22 +189,6 @@ EOF
Bundler.mkdir_p(bundled_app.join("foo", "bar"))
expect(bundled_app.join("foo", "bar")).to exist
end
-
- context "when mkdir_p requires sudo" do
- it "creates a new folder using sudo" do
- expect(Bundler).to receive(:requires_sudo?).and_return(true)
- expect(Bundler).to receive(:sudo).and_return true
- Bundler.mkdir_p(bundled_app.join("foo"))
- end
- end
-
- context "with :no_sudo option" do
- it "forces mkdir_p to not use sudo" do
- expect(Bundler).to receive(:requires_sudo?).and_return(true)
- expect(Bundler).to_not receive(:sudo)
- Bundler.mkdir_p(bundled_app.join("foo"), :no_sudo => true)
- end
- end
end
describe "#user_home" do
@@ -268,118 +252,6 @@ EOF
end
end
- describe "#requires_sudo?" do
- let!(:tmpdir) { Dir.mktmpdir }
- let(:bundle_path) { Pathname("#{tmpdir}/bundle") }
-
- def clear_cached_requires_sudo
- return unless Bundler.instance_variable_defined?(:@requires_sudo_ran)
- Bundler.remove_instance_variable(:@requires_sudo_ran)
- Bundler.remove_instance_variable(:@requires_sudo)
- end
-
- before do
- clear_cached_requires_sudo
- allow(Bundler).to receive(:which).with("sudo").and_return("/usr/bin/sudo")
- allow(Bundler).to receive(:bundle_path).and_return(bundle_path)
- end
-
- after do
- FileUtils.rm_rf(tmpdir)
- clear_cached_requires_sudo
- end
-
- subject { Bundler.requires_sudo? }
-
- context "bundle_path doesn't exist" do
- it { should be false }
-
- context "and parent dir can't be written" do
- before do
- FileUtils.chmod(0o500, tmpdir)
- end
-
- it { should be true }
- end
-
- context "with unwritable files in a parent dir" do
- # Regression test for https://github.com/rubygems/bundler/pull/6316
- # It doesn't matter if there are other unwritable files so long as
- # bundle_path can be created
- before do
- file = File.join(tmpdir, "unrelated_file")
- FileUtils.touch(file)
- FileUtils.chmod(0o400, file)
- end
-
- it { should be false }
- end
- end
-
- context "bundle_path exists" do
- before do
- FileUtils.mkdir_p(bundle_path)
- end
-
- it { should be false }
-
- context "and is unwritable" do
- before do
- FileUtils.chmod(0o500, bundle_path)
- end
-
- it { should be true }
- end
- end
-
- context "path writability" do
- before do
- FileUtils.mkdir_p("tmp/vendor/bundle")
- FileUtils.mkdir_p("tmp/vendor/bin_dir")
- end
- after do
- FileUtils.rm_rf("tmp/vendor/bundle")
- FileUtils.rm_rf("tmp/vendor/bin_dir")
- end
- context "writable paths" do
- it "should return false and display nothing" do
- allow(Bundler).to receive(:bundle_path).and_return(Pathname("tmp/vendor/bundle"))
- expect(Bundler.ui).to_not receive(:warn)
- expect(Bundler.requires_sudo?).to eq(false)
- end
- end
- context "unwritable paths" do
- before do
- FileUtils.touch("tmp/vendor/bundle/unwritable1.txt")
- FileUtils.touch("tmp/vendor/bundle/unwritable2.txt")
- FileUtils.touch("tmp/vendor/bin_dir/unwritable3.txt")
- FileUtils.chmod(0o400, "tmp/vendor/bundle/unwritable1.txt")
- FileUtils.chmod(0o400, "tmp/vendor/bundle/unwritable2.txt")
- FileUtils.chmod(0o400, "tmp/vendor/bin_dir/unwritable3.txt")
- end
- it "should return true and display warn message" do
- allow(Bundler).to receive(:bundle_path).and_return(Pathname("tmp/vendor/bundle"))
- bin_dir = Pathname("tmp/vendor/bin_dir/")
-
- # allow File#writable? to be called with args other than the stubbed on below
- allow(File).to receive(:writable?).and_call_original
-
- # fake make the directory unwritable
- allow(File).to receive(:writable?).with(bin_dir).and_return(false)
- allow(Bundler).to receive(:system_bindir).and_return(Pathname("tmp/vendor/bin_dir/"))
- message = <<-MESSAGE.chomp
-Following files may not be writable, so sudo is needed:
- tmp/vendor/bin_dir/
- tmp/vendor/bundle/unwritable1.txt
- tmp/vendor/bundle/unwritable2.txt
-MESSAGE
- expect(Bundler.ui).to receive(:warn).with(message)
- expect(Bundler.requires_sudo?).to eq(true)
- end
- end
- end
- end
-
context "user cache dir" do
let(:home_path) { Pathname.new(ENV["HOME"]) }
diff --git a/spec/bundler/bundler/endpoint_specification_spec.rb b/spec/bundler/bundler/endpoint_specification_spec.rb
index 02a90d507a..81fcd76e01 100644
--- a/spec/bundler/bundler/endpoint_specification_spec.rb
+++ b/spec/bundler/bundler/endpoint_specification_spec.rb
@@ -48,6 +48,33 @@ RSpec.describe Bundler::EndpointSpecification do
end
end
+ describe "#required_ruby_version" do
+ context "required_ruby_version is already set on endpoint specification" do
+ existing_value = "already set value"
+ let(:required_ruby_version) { existing_value }
+
+ it "should return the current value when already set on endpoint specification" do
+ remote_spec = double(:remote_spec, :required_ruby_version => "remote_value", :required_rubygems_version => nil)
+
+ expect(spec.required_ruby_version). eql?(existing_value)
+ end
+ end
+
+ it "should return the remote spec value when not set on endpoint specification and remote spec has one" do
+ remote_value = "remote_value"
+ remote_spec = double(:remote_spec, :required_ruby_version => remote_value, :required_rubygems_version => nil)
+ allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec)
+
+ expect(spec.required_ruby_version). eql?(remote_value)
+ end
+
+ it "should use the default Gem Requirement value when not set on endpoint specification and not set on remote spec" do
+ remote_spec = double(:remote_spec, :required_ruby_version => nil, :required_rubygems_version => nil)
+ allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec)
+ expect(spec.required_ruby_version). eql?(Gem::Requirement.default)
+ end
+ end
+
it "supports equality comparison" do
remote_spec = double(:remote_spec, :required_ruby_version => nil, :required_rubygems_version => nil)
allow(spec_fetcher).to receive(:fetch_spec).and_return(remote_spec)
diff --git a/spec/bundler/bundler/gem_version_promoter_spec.rb b/spec/bundler/bundler/gem_version_promoter_spec.rb
index 43a3630bbb..99e008bfbc 100644
--- a/spec/bundler/bundler/gem_version_promoter_spec.rb
+++ b/spec/bundler/bundler/gem_version_promoter_spec.rb
@@ -166,14 +166,5 @@ RSpec.describe Bundler::GemVersionPromoter do
end
end
end
-
- context "debug output" do
- it "should not kerblooie on its own debug output" do
- gvp = unlocking(:level => :patch)
- dep = Bundler::DepProxy.get_proxy(dep("foo", "1.2.0").first, "ruby")
- result = gvp.send(:debug_format_result, dep, build_spec_groups("foo", %w[1.2.0 1.3.0]))
- expect(result.class).to eq Array
- end
- end
end
end
diff --git a/spec/bundler/install/binstubs_spec.rb b/spec/bundler/install/binstubs_spec.rb
index 6961171f4f..928ba80b15 100644
--- a/spec/bundler/install/binstubs_spec.rb
+++ b/spec/bundler/install/binstubs_spec.rb
@@ -2,10 +2,8 @@
RSpec.describe "bundle install" do
describe "when system_bindir is set" do
- # On OS X, Gem.bindir defaults to /usr/bin, so system_bindir is useful if
- # you want to avoid sudo installs for system gems with OS X's default ruby
it "overrides Gem.bindir" do
- expect(Pathname.new("/usr/bin")).not_to be_writable unless Process.euid == 0
+ expect(Pathname.new("/usr/bin")).not_to be_writable
gemfile <<-G
def Gem.bindir; "/usr/bin"; end
source "#{file_uri_for(gem_repo1)}"
diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb
index ee0aa2a347..d2733993bb 100644
--- a/spec/bundler/install/gemfile/sources_spec.rb
+++ b/spec/bundler/install/gemfile/sources_spec.rb
@@ -1470,6 +1470,59 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
+ context "when default source includes old gems with nil required_ruby_version" do
+ before do
+ build_repo2 do
+ build_gem "ruport", "1.7.0.3" do |s|
+ s.add_dependency "pdf-writer", "1.1.8"
+ end
+ end
+
+ build_repo gem_repo4 do
+ build_gem "pdf-writer", "1.1.8"
+ end
+
+ path = "#{gem_repo4}/#{Gem::MARSHAL_SPEC_DIR}/pdf-writer-1.1.8.gemspec.rz"
+ spec = Marshal.load(Bundler.rubygems.inflate(File.binread(path)))
+ spec.instance_variable_set(:@required_ruby_version, nil)
+ File.open(path, "wb") do |f|
+ f.write Gem.deflate(Marshal.dump(spec))
+ end
+
+ gemfile <<~G
+ source "https://localgemserver.test"
+
+ gem "ruport", "= 1.7.0.3", :source => "https://localgemserver.test/extra"
+ G
+ end
+
+ it "handles that fine" do
+ bundle "install", :artifice => "compact_index_extra", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ pdf-writer (1.1.8)
+
+ GEM
+ remote: https://localgemserver.test/extra/
+ specs:
+ ruport (1.7.0.3)
+ pdf-writer (= 1.1.8)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ ruport (= 1.7.0.3)!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
context "when default source includes old gems with nil required_rubygems_version" do
before do
build_repo2 do
diff --git a/spec/bundler/install/gems/compact_index_spec.rb b/spec/bundler/install/gems/compact_index_spec.rb
index 5c25b1092a..b6c361186a 100644
--- a/spec/bundler/install/gems/compact_index_spec.rb
+++ b/spec/bundler/install/gems/compact_index_spec.rb
@@ -519,18 +519,6 @@ The checksum of /versions does not match the checksum provided by the server! So
expect(out).to include("Fetching gem metadata from #{source_uri}")
end
- it "should install when EndpointSpecification has a bin dir owned by root", :sudo => true do
- sudo "mkdir -p #{system_gem_path("bin")}"
- sudo "chown -R root #{system_gem_path("bin")}"
-
- gemfile <<-G
- source "#{source_uri}"
- gem "rails"
- G
- bundle :install, :artifice => "compact_index"
- expect(the_bundle).to include_gems "rails 2.3.2"
- end
-
it "installs the binstubs", :bundler => "< 3" do
gemfile <<-G
source "#{source_uri}"
diff --git a/spec/bundler/install/gems/dependency_api_spec.rb b/spec/bundler/install/gems/dependency_api_spec.rb
index 9a83e5ffad..6cb3d9697d 100644
--- a/spec/bundler/install/gems/dependency_api_spec.rb
+++ b/spec/bundler/install/gems/dependency_api_spec.rb
@@ -476,18 +476,6 @@ RSpec.describe "gemcutter's dependency API" do
expect(out).to include("Fetching gem metadata from #{source_uri}")
end
- it "should install when EndpointSpecification has a bin dir owned by root", :sudo => true do
- sudo "mkdir -p #{system_gem_path("bin")}"
- sudo "chown -R root #{system_gem_path("bin")}"
-
- gemfile <<-G
- source "#{source_uri}"
- gem "rails"
- G
- bundle :install, :artifice => "endpoint"
- expect(the_bundle).to include_gems "rails 2.3.2"
- end
-
it "installs the binstubs", :bundler => "< 3" do
gemfile <<-G
source "#{source_uri}"
diff --git a/spec/bundler/install/gems/flex_spec.rb b/spec/bundler/install/gems/flex_spec.rb
index ed61531574..ed30d2cc35 100644
--- a/spec/bundler/install/gems/flex_spec.rb
+++ b/spec/bundler/install/gems/flex_spec.rb
@@ -190,28 +190,33 @@ RSpec.describe "bundle flex_install" do
expect(err).to match(/could not find gem 'rack-obama/i)
end
- it "suggests deleting the Gemfile.lock file when the Gemfile requires different versions than the lock" do
+ it "discards the locked gems when the Gemfile requires different versions than the lock" do
bundle "config set force_ruby_platform true"
nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "rack":
- In snapshot (Gemfile.lock):
- rack (= 0.9.1)
+ Could not find gem 'rack (= 1.2)', which is required by gem 'rack-obama (= 2.0)', in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally.
- In Gemfile:
- rack-obama (= 2.0) was resolved to 2.0, which depends on
- rack (= 1.2)
-
- rack_middleware was resolved to 1.0, which depends on
- rack (= 0.9.1)
-
- Deleting your Gemfile.lock file and running `bundle install` will rebuild your snapshot from scratch, using only
- the gems in your Gemfile, which may resolve the conflict.
+ The source contains the following gems matching 'rack':
+ * rack-0.9.1
+ * rack-1.0.0
E
bundle :install, :retry => 0, :raise_on_error => false
expect(err).to end_with(nice_error)
end
+
+ it "does not include conflicts with a single requirement tree, because that can't possibly be a conflict" do
+ bundle "config set force_ruby_platform true"
+
+ bad_error = <<-E.strip.gsub(/^ {8}/, "")
+ Bundler could not find compatible versions for gem "rack-obama":
+ In Gemfile:
+ rack-obama (= 2.0)
+ E
+
+ bundle "update rack_middleware", :retry => 0, :raise_on_error => false
+ expect(err).not_to end_with(bad_error)
+ end
end
describe "when running bundle update and Gemfile conflicts with lockfile" do
@@ -230,22 +235,6 @@ RSpec.describe "bundle flex_install" do
gem "jekyll-feed", "~> 0.12"
G
- lockfile <<-L
- GEM
- remote: #{file_uri_for(gem_repo4)}/
- specs:
- jekyll-feed (0.16.0)
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- jekyll-feed
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
-
gemfile <<-G
source "#{file_uri_for(gem_repo4)}"
gem "github-pages", "~> 226"
@@ -253,24 +242,9 @@ RSpec.describe "bundle flex_install" do
G
end
- it "suggests deleting the Gemfile.lock file when the Gemfile requires different versions than the lock" do
- nice_error = <<-E.strip.gsub(/^ {8}/, "")
- Bundler could not find compatible versions for gem "jekyll-feed":
- In snapshot (Gemfile.lock):
- jekyll-feed (>= 0.16.0)
-
- In Gemfile:
- jekyll-feed (~> 0.12)
-
- github-pages (~> 226) was resolved to 226, which depends on
- jekyll-feed (= 0.15.1)
-
- Deleting your Gemfile.lock file and running `bundle install` will rebuild your snapshot from scratch, using only
- the gems in your Gemfile, which may resolve the conflict.
- E
-
- bundle :update, :raise_on_error => false
- expect(err).to end_with(nice_error)
+ it "discards the conflicting lockfile information and resolves properly" do
+ bundle :update, :raise_on_error => false, :all => true
+ expect(err).to be_empty
end
end
@@ -374,7 +348,7 @@ RSpec.describe "bundle flex_install" do
end
end
- it "prints the correct error message" do
+ it "resolves them" do
# install Rails 3.0.0.rc
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -383,13 +357,12 @@ RSpec.describe "bundle flex_install" do
G
# upgrade Rails to 3.0.0 and then install again
- install_gemfile <<-G, :raise_on_error => false
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "rails", "3.0.0"
gem "capybara", "0.3.9"
G
-
- expect(err).to include("Gemfile.lock")
+ expect(err).to be_empty
end
end
end
diff --git a/spec/bundler/install/gems/sudo_spec.rb b/spec/bundler/install/gems/sudo_spec.rb
deleted file mode 100644
index 41b241da25..0000000000
--- a/spec/bundler/install/gems/sudo_spec.rb
+++ /dev/null
@@ -1,205 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "when using sudo", :sudo => true do
- describe "and BUNDLE_PATH is writable" do
- context "but BUNDLE_PATH/build_info is not writable" do
- let(:subdir) do
- system_gem_path("cache")
- end
-
- before do
- bundle "config set path.system true"
- subdir.mkpath
- sudo "chmod u-w #{subdir}"
- end
-
- after do
- sudo "chmod u+w #{subdir}"
- end
-
- it "installs" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
-
- expect(out).to_not match(/an error occurred/i)
- expect(system_gem_path("cache/rack-1.0.0.gem")).to exist
- expect(the_bundle).to include_gems "rack 1.0"
- end
- end
- end
-
- describe "and GEM_HOME is owned by root" do
- before :each do
- bundle "config set path.system true"
- chown_system_gems_to_root
- end
-
- it "installs" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- gem "thin"
- G
-
- expect(system_gem_path("gems/rack-1.0.0")).to exist
- expect(system_gem_path("gems/rack-1.0.0").stat.uid).to eq(0)
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "installs rake and a gem dependent on rake in the same session" do
- build_repo2 do
- build_gem "another_implicit_rake_dep" do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- path = File.expand_path("lib", __dir__)
- FileUtils.mkdir_p(path)
- File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f|
- f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'"
- end
- end
- RUBY
- end
- end
-
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rake"
- gem "another_implicit_rake_dep"
- G
- bundle "install"
- expect(system_gem_path("gems/another_implicit_rake_dep-1.0")).to exist
- end
-
- it "installs when BUNDLE_PATH is owned by root" do
- bundle_path = tmp("owned_by_root")
- FileUtils.mkdir_p bundle_path
- sudo "chown -R root #{bundle_path}"
-
- ENV["BUNDLE_PATH"] = bundle_path.to_s
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- G
-
- expect(bundle_path.join(Bundler.ruby_scope, "gems/rack-1.0.0")).to exist
- expect(bundle_path.join(Bundler.ruby_scope, "gems/rack-1.0.0").stat.uid).to eq(0)
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "installs when BUNDLE_PATH does not exist" do
- root_path = tmp("owned_by_root")
- FileUtils.mkdir_p root_path
- sudo "chown -R root #{root_path}"
- bundle_path = root_path.join("does_not_exist")
-
- ENV["BUNDLE_PATH"] = bundle_path.to_s
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- G
-
- expect(bundle_path.join(Bundler.ruby_scope, "gems/rack-1.0.0")).to exist
- expect(bundle_path.join(Bundler.ruby_scope, "gems/rack-1.0.0").stat.uid).to eq(0)
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "installs extensions/" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "very_simple_binary"
- G
-
- expect(system_gem_path("gems/very_simple_binary-1.0")).to exist
- binary_glob = system_gem_path("extensions/*/*/very_simple_binary-1.0")
- expect(Dir.glob(binary_glob).first).to be
- end
- end
-
- describe "and BUNDLE_PATH is not writable" do
- before do
- bundle "config set --local path .bundle"
- sudo "chmod ugo-w .bundle"
- end
-
- after do
- sudo "chmod ugo+w .bundle"
- end
-
- it "installs" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- G
-
- expect(local_gem_path("gems/rack-1.0.0")).to exist
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "cleans up the tmpdirs generated" do
- require "tmpdir"
- Dir.glob("#{Dir.tmpdir}/bundler*").each do |tmpdir|
- FileUtils.remove_entry_secure(tmpdir)
- end
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
- tmpdirs = Dir.glob("#{Dir.tmpdir}/bundler*")
-
- expect(tmpdirs).to be_empty
- end
- end
-
- describe "and GEM_HOME is not writable" do
- it "installs" do
- bundle "config set path.system true"
- gem_home = tmp("sudo_gem_home")
- sudo "mkdir -p #{gem_home}"
- sudo "chmod ugo-w #{gem_home}"
-
- system_gems :bundler, :path => gem_home
-
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '1.0'
- G
-
- bundle :install, :env => { "GEM_HOME" => gem_home.to_s, "GEM_PATH" => nil }
- expect(gem_home.join("bin/rackup")).to exist
- expect(the_bundle).to include_gems "rack 1.0", :env => { "GEM_HOME" => gem_home.to_s, "GEM_PATH" => nil }
-
- sudo "rm -rf #{tmp("sudo_gem_home")}"
- end
- end
-
- describe "and root runs install" do
- let(:warning) { "Don't run Bundler as root." }
-
- before do
- gemfile %(source "#{file_uri_for(gem_repo1)}")
- end
-
- it "warns against that" do
- bundle :install, :sudo => :preserve_env
- expect(err).to include(warning)
- end
-
- context "when ENV['BUNDLE_SILENCE_ROOT_WARNING'] is set" do
- it "skips the warning" do
- bundle :install, :sudo => :preserve_env, :env => { "BUNDLE_SILENCE_ROOT_WARNING" => "true" }
- expect(err).to_not include(warning)
- end
- end
-
- context "when silence_root_warning = false" do
- it "warns against that" do
- bundle :install, :sudo => :preserve_env, :env => { "BUNDLE_SILENCE_ROOT_WARNING" => "false" }
- expect(err).to include(warning)
- end
- end
- end
-end
diff --git a/spec/bundler/plugins/install_spec.rb b/spec/bundler/plugins/install_spec.rb
index 009516260a..efee5fdd23 100644
--- a/spec/bundler/plugins/install_spec.rb
+++ b/spec/bundler/plugins/install_spec.rb
@@ -32,7 +32,8 @@ RSpec.describe "bundler plugin install" do
it "shows help when --help flag is given" do
bundle "plugin install --help"
- expect(out).to include("bundle plugin install PLUGINS # Install the plugin from the source")
+ # The help message defined in ../../lib/bundler/man/bundle-plugin.1.ronn will be output.
+ expect(out).to include("You can install, uninstall, and list plugin(s)")
end
context "plugin is already installed" do
@@ -84,6 +85,26 @@ RSpec.describe "bundler plugin install" do
expect(out).to include("Using foo 1.1")
end
+ it "installs when --branch specified" do
+ bundle "plugin install foo --branch main --source #{file_uri_for(gem_repo2)}"
+
+ expect(out).to include("Installed plugin foo")
+ end
+
+ it "installs when --ref specified" do
+ bundle "plugin install foo --ref v1.2.3 --source #{file_uri_for(gem_repo2)}"
+
+ expect(out).to include("Installed plugin foo")
+ end
+
+ it "raises error when both --branch and --ref options are specified" do
+ bundle "plugin install foo --source #{file_uri_for(gem_repo2)} --branch main --ref v1.2.3", :raise_on_error => false
+
+ expect(out).not_to include("Installed plugin foo")
+
+ expect(err).to include("You cannot specify `--branch` and `--ref` at the same time.")
+ end
+
it "works with different load paths" do
build_repo2 do
build_plugin "testing" do |s|
diff --git a/spec/bundler/plugins/source/example_spec.rb b/spec/bundler/plugins/source/example_spec.rb
index 412de04d44..9d153b6063 100644
--- a/spec/bundler/plugins/source/example_spec.rb
+++ b/spec/bundler/plugins/source/example_spec.rb
@@ -304,13 +304,7 @@ RSpec.describe "real source plugins" do
@install_path ||= begin
git_scope = "\#{base_name}-\#{shortref_for_path(revision)}"
- path = gem_install_dir.join(git_scope)
-
- if !path.exist? && requires_sudo?
- user_bundle_path.join(ruby_scope).join(git_scope)
- else
- path
- end
+ gem_install_dir.join(git_scope)
end
end
diff --git a/spec/bundler/quality_spec.rb b/spec/bundler/quality_spec.rb
index ee98bcd4d7..86a927c361 100644
--- a/spec/bundler/quality_spec.rb
+++ b/spec/bundler/quality_spec.rb
@@ -151,7 +151,6 @@ RSpec.describe "The library itself" do
git.allow_insecure
inline
trust-policy
- use_gem_version_promoter_for_major_updates
]
all_settings = Hash.new {|h, k| h[k] = [] }
diff --git a/spec/bundler/spec_helper.rb b/spec/bundler/spec_helper.rb
index 892ad10e98..4f67092bc7 100644
--- a/spec/bundler/spec_helper.rb
+++ b/spec/bundler/spec_helper.rb
@@ -23,7 +23,6 @@ require_relative "support/indexes"
require_relative "support/matchers"
require_relative "support/permissions"
require_relative "support/platforms"
-require_relative "support/sudo"
$debug = false
@@ -40,7 +39,6 @@ RSpec.configure do |config|
config.include Spec::Matchers
config.include Spec::Path
config.include Spec::Platforms
- config.include Spec::Sudo
config.include Spec::Permissions
# Enable flags like --only-failures and --next-failure
@@ -115,10 +113,6 @@ RSpec.configure do |config|
end
end
- config.before :each, :sudo => true do
- Spec::Sudo.write_safe_config
- end
-
config.after :suite do
FileUtils.rm_r Spec::Path.pristine_system_gem_path
end
diff --git a/spec/bundler/support/filters.rb b/spec/bundler/support/filters.rb
index c3b7a425ae..523f7c742c 100644
--- a/spec/bundler/support/filters.rb
+++ b/spec/bundler/support/filters.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require_relative "sudo"
-
class RequirementChecker < Proc
def self.against(present)
provided = Gem::Version.new(present)
@@ -21,7 +19,6 @@ class RequirementChecker < Proc
end
RSpec.configure do |config|
- config.filter_run_excluding :sudo => true
config.filter_run_excluding :realworld => true
git_version = Bundler::Source::Git::GitProxy.new(nil, nil, nil).version
diff --git a/spec/bundler/support/helpers.rb b/spec/bundler/support/helpers.rb
index f4ee93ccc0..dfc358796a 100644
--- a/spec/bundler/support/helpers.rb
+++ b/spec/bundler/support/helpers.rb
@@ -78,9 +78,6 @@ module Spec
end
def bundle(cmd, options = {}, &block)
- with_sudo = options.delete(:sudo)
- sudo = with_sudo == :preserve_env ? "sudo -E --preserve-env=RUBYOPT" : "sudo" if with_sudo
-
bundle_bin = options.delete(:bundle_bin)
bundle_bin ||= installed_bindir.join("bundle")
@@ -119,7 +116,7 @@ module Spec
end
end.join
- ruby_cmd = build_ruby_cmd({ :sudo => sudo, :load_path => load_path, :requires => requires })
+ ruby_cmd = build_ruby_cmd({ :load_path => load_path, :requires => requires })
cmd = "#{ruby_cmd} #{bundle_bin} #{cmd}#{args}"
sys_exec(cmd, { :env => env, :dir => dir, :raise_on_error => raise_on_error }, &block)
end
@@ -146,8 +143,6 @@ module Spec
end
def build_ruby_cmd(options = {})
- sudo = options.delete(:sudo)
-
libs = options.delete(:load_path)
lib_option = libs ? "-I#{libs.join(File::PATH_SEPARATOR)}" : []
@@ -155,7 +150,7 @@ module Spec
requires << "#{Path.spec_dir}/support/hax.rb"
require_option = requires.map {|r| "-r#{r}" }
- [sudo, Gem.ruby, *lib_option, *require_option].compact.join(" ")
+ [Gem.ruby, *lib_option, *require_option].compact.join(" ")
end
def gembin(cmd, options = {})
diff --git a/spec/bundler/support/sudo.rb b/spec/bundler/support/sudo.rb
deleted file mode 100644
index 7b9b392754..0000000000
--- a/spec/bundler/support/sudo.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Spec
- module Sudo
- def self.present?
- @which_sudo ||= Bundler.which("sudo")
- end
-
- def self.write_safe_config
- File.write(Spec::Path.tmp("gitconfig"), "[safe]\n\tdirectory = #{Spec::Path.git_root}")
- end
-
- def sudo(cmd)
- raise "sudo not present" unless Sudo.present?
- sys_exec("sudo #{cmd}")
- end
-
- def chown_system_gems_to_root
- sudo "chown -R root #{system_gem_path}"
- end
- end
-end
diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb
index e569986ef2..258107bf04 100644
--- a/test/rubygems/helper.rb
+++ b/test/rubygems/helper.rb
@@ -463,14 +463,7 @@ class Gem::TestCase < Test::Unit::TestCase
Dir.chdir @current_dir
- # Prevent a race condition on removing TMPDIR being written by MJIT
- if defined?(RubyVM::MJIT.enabled?) && RubyVM::MJIT.enabled?
- RubyVM::MJIT.pause(wait: false)
- end
FileUtils.rm_rf @tempdir
- if defined?(RubyVM::MJIT.enabled?) && RubyVM::MJIT.enabled?
- RubyVM::MJIT.resume
- end
ENV.replace(@orig_env)
diff --git a/tool/bundler/rubocop_gems.rb.lock b/tool/bundler/rubocop_gems.rb.lock
index 13e541bcfa..9b097ba710 100644
--- a/tool/bundler/rubocop_gems.rb.lock
+++ b/tool/bundler/rubocop_gems.rb.lock
@@ -44,6 +44,7 @@ GEM
unicode-display_width (2.1.0)
PLATFORMS
+ aarch64-linux
arm64-darwin-20
arm64-darwin-21
universal-java-11
diff --git a/tool/bundler/standard_gems.rb.lock b/tool/bundler/standard_gems.rb.lock
index df346ad7ce..03d8195557 100644
--- a/tool/bundler/standard_gems.rb.lock
+++ b/tool/bundler/standard_gems.rb.lock
@@ -50,6 +50,7 @@ GEM
unicode-display_width (2.1.0)
PLATFORMS
+ aarch64-linux
arm64-darwin-20
arm64-darwin-21
universal-java-11