summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/bundler.rb2
-rw-r--r--lib/bundler/cli.rb2
-rw-r--r--lib/bundler/cli/binstubs.rb10
-rw-r--r--lib/bundler/definition.rb3
-rw-r--r--lib/bundler/injector.rb3
-rw-r--r--lib/bundler/plugin/index.rb7
-rw-r--r--lib/bundler/rubygems_integration.rb6
-rw-r--r--lib/bundler/source/git.rb3
-rw-r--r--lib/bundler/source/rubygems.rb5
-rw-r--r--lib/bundler/templates/Executable2
-rw-r--r--man/bundle-update.ronn16
-rw-r--r--spec/bundler/bundler_spec.rb67
-rw-r--r--spec/bundler/plugin/index_spec.rb8
-rw-r--r--spec/bundler/source/git_spec.rb28
-rw-r--r--spec/commands/add_spec.rb5
-rw-r--r--spec/commands/binstubs_spec.rb23
-rw-r--r--spec/commands/exec_spec.rb16
-rw-r--r--spec/commands/lock_spec.rb8
-rw-r--r--spec/install/gems/resolving_spec.rb5
-rw-r--r--spec/install/path_spec.rb12
20 files changed, 197 insertions, 34 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 9056c1aa42..9944ebd051 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -365,7 +365,7 @@ EOF
bin_dir = bin_dir.parent until bin_dir.exist?
# if any directory is not writable, we need sudo
- files = [path, bin_dir] | Dir[path.join("build_info/*").to_s] | Dir[path.join("*").to_s]
+ files = [path, bin_dir] | Dir[bundle_path.join("build_info/*").to_s] | Dir[bundle_path.join("*").to_s]
sudo_needed = files.any? {|f| !File.writable?(f) }
end
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index d86441f5ae..1b913024e2 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -319,6 +319,8 @@ module Bundler
"Specify a different shebang executable name than the default (usually 'ruby')"
method_option "standalone", :type => :boolean, :banner =>
"Make binstubs that can work without the Bundler runtime"
+ method_option "all", :type => :boolean, :banner =>
+ "Install binstubs for all gems"
def binstubs(*gems)
require "bundler/cli/binstubs"
Binstubs.new(options, gems).run
diff --git a/lib/bundler/cli/binstubs.rb b/lib/bundler/cli/binstubs.rb
index 449204d821..266396eedc 100644
--- a/lib/bundler/cli/binstubs.rb
+++ b/lib/bundler/cli/binstubs.rb
@@ -16,7 +16,13 @@ module Bundler
Bundler.settings.set_command_option_if_given :shebang, options["shebang"]
installer = Installer.new(Bundler.root, Bundler.definition)
- if gems.empty?
+ installer_opts = { :force => options[:force], :binstubs_cmd => true }
+
+ if options[:all]
+ raise InvalidOption, "Cannot specify --all with specific gems" unless gems.empty?
+ @gems = Bundler.definition.specs.map(&:name)
+ installer_opts.delete(:binstubs_cmd)
+ elsif gems.empty?
Bundler.ui.error "`bundle binstubs` needs at least one gem to run."
exit 1
end
@@ -35,7 +41,7 @@ module Bundler
installer.generate_standalone_bundler_executable_stubs(spec)
end
else
- installer.generate_bundler_executable_stubs(spec, :force => options[:force], :binstubs_cmd => true)
+ installer.generate_bundler_executable_stubs(spec, installer_opts)
end
end
end
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 91d34ad150..bec3cadbb4 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -337,7 +337,8 @@ module Bundler
end
preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
- return if lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
+
+ return if file && File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
if Bundler.frozen_bundle?
Bundler.ui.error "Cannot write a changed lockfile while frozen."
diff --git a/lib/bundler/injector.rb b/lib/bundler/injector.rb
index 6f9669ae4f..9c67a80777 100644
--- a/lib/bundler/injector.rb
+++ b/lib/bundler/injector.rb
@@ -12,6 +12,9 @@ module Bundler
@options = options
end
+ # @param [Pathname] gemfile_path The Gemfile in which to inject the new dependency.
+ # @param [Pathname] lockfile_path The lockfile in which to inject the new dependency.
+ # @return [Array]
def inject(gemfile_path, lockfile_path)
if Bundler.frozen_bundle?
# ensure the lock and Gemfile are synced
diff --git a/lib/bundler/plugin/index.rb b/lib/bundler/plugin/index.rb
index cd7a5093b3..642e7c8163 100644
--- a/lib/bundler/plugin/index.rb
+++ b/lib/bundler/plugin/index.rb
@@ -29,7 +29,12 @@ module Bundler
@hooks = {}
@load_paths = {}
- load_index(global_index_file, true)
+ begin
+ load_index(global_index_file, true)
+ rescue GenericSystemCallError
+ # no need to fail when on a read-only FS, for example
+ nil
+ end
load_index(local_index_file) if SharedHelpers.in_bundle?
end
diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb
index 57abeda088..783d106e7b 100644
--- a/lib/bundler/rubygems_integration.rb
+++ b/lib/bundler/rubygems_integration.rb
@@ -132,7 +132,11 @@ module Bundler
end
def inflate(obj)
- Gem::Util.inflate(obj)
+ if defined?(Gem::Util)
+ Gem::Util.inflate(obj)
+ else
+ Gem.inflate(obj)
+ end
end
def sources=(val)
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb
index a1a59ddce5..0b00608bdd 100644
--- a/lib/bundler/source/git.rb
+++ b/lib/bundler/source/git.rb
@@ -21,6 +21,7 @@ module Bundler
%w[ref branch tag revision].each {|k| options[k] = options[k].to_s if options[k] }
@uri = options["uri"] || ""
+ @safe_uri = URICredentialsFilter.credential_filtered_uri(@uri)
@branch = options["branch"]
@ref = options["ref"] || options["branch"] || options["tag"] || "master"
@submodules = options["submodules"]
@@ -77,7 +78,7 @@ module Bundler
nil
end
- "#{uri} (at #{at}#{rev})"
+ "#{@safe_uri} (at #{at}#{rev})"
end
def name
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index 72dbc0c588..1759838b57 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -485,7 +485,10 @@ module Bundler
else
uri = spec.remote.uri
Bundler.ui.confirm("Fetching #{version_message(spec)}")
- Bundler.rubygems.download_gem(spec, uri, download_path)
+ rubygems_local_path = Bundler.rubygems.download_gem(spec, uri, download_path)
+ if rubygems_local_path != local_path
+ FileUtils.mv(rubygems_local_path, local_path)
+ end
cache_globally(spec, local_path)
end
end
diff --git a/lib/bundler/templates/Executable b/lib/bundler/templates/Executable
index 414a75898d..3e8d5b317a 100644
--- a/lib/bundler/templates/Executable
+++ b/lib/bundler/templates/Executable
@@ -15,7 +15,7 @@ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../<%= relative_gemfile_path %>",
bundle_binstub = File.expand_path("../bundle", __FILE__)
if File.file?(bundle_binstub)
- if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
load(bundle_binstub)
else
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
diff --git a/man/bundle-update.ronn b/man/bundle-update.ronn
index 413a446c60..493986a7a4 100644
--- a/man/bundle-update.ronn
+++ b/man/bundle-update.ronn
@@ -3,7 +3,8 @@ bundle-update(1) -- Update your gems to the latest available versions
## SYNOPSIS
-`bundle update` <*gems> [--group=NAME]
+`bundle update` <*gems> [--all]
+ [--group=NAME]
[--source=NAME]
[--local]
[--ruby]
@@ -18,7 +19,7 @@ bundle-update(1) -- Update your gems to the latest available versions
## DESCRIPTION
-Update the gems specified (all gems, if none are specified), ignoring
+Update the gems specified (all gems, if `--all` flag is used), ignoring
the previously installed gems specified in the `Gemfile.lock`. In
general, you should use [bundle install(1)][bundle-install(1)] to install the same exact
gems and versions across machines.
@@ -28,6 +29,9 @@ gem.
## OPTIONS
+* `--all`:
+ Update all gems specified in Gemfile.
+
* `--group=<name>`, `-g=[<name>]`:
Only update the gems in the specified group. For instance, you can update all gems
in the development group with `bundle update --group development`. You can also
@@ -80,7 +84,7 @@ gem.
## UPDATING ALL GEMS
-If you run `bundle update` with no parameters, bundler will ignore
+If you run `bundle update --all`, bundler will ignore
any previously installed gems and resolve all dependencies again
based on the latest versions of all gems available in the sources.
@@ -139,10 +143,10 @@ the gems you use.
However, from time to time, you might want to update the gems you are using to the
newest versions that still match the gems in your Gemfile(5).
-To do this, run `bundle update`, which will ignore the `Gemfile.lock`, and resolve
+To do this, run `bundle update --all`, which will ignore the `Gemfile.lock`, and resolve
all the dependencies again. Keep in mind that this process can result in a significantly
different set of the 25 gems, based on the requirements of new gems that the gem
-authors released since the last time you ran `bundle update`.
+authors released since the last time you ran `bundle update --all`.
## UPDATING A LIST OF GEMS
@@ -343,4 +347,4 @@ use the following workflow:
* If you want to update all the gems to the latest possible versions that
still match the gems listed in the Gemfile(5), run
- $ bundle update
+ $ bundle update --all
diff --git a/spec/bundler/bundler_spec.rb b/spec/bundler/bundler_spec.rb
index 94d4096cd3..131146119e 100644
--- a/spec/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler_spec.rb
@@ -2,6 +2,7 @@
# frozen_string_literal: true
require "bundler"
+require "tmpdir"
RSpec.describe Bundler do
describe "#load_gemspec_uncached" do
@@ -228,6 +229,72 @@ EOF
end
end
+ describe "#requires_sudo?" do
+ let!(:tmpdir) { Dir.mktmpdir }
+ let(:bundle_path) { Pathname("#{tmpdir}/bundle") }
+
+ def clear_cached_requires_sudo
+ # Private in ruby 1.8.7
+ return unless Bundler.instance_variable_defined?(:@requires_sudo_ran)
+ Bundler.send(:remove_instance_variable, :@requires_sudo_ran)
+ Bundler.send(: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/bundler/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
+ end
+
context "user cache dir" do
let(:home_path) { Pathname.new(ENV["HOME"]) }
diff --git a/spec/bundler/plugin/index_spec.rb b/spec/bundler/plugin/index_spec.rb
index 163b563b2a..ca3476ea2a 100644
--- a/spec/bundler/plugin/index_spec.rb
+++ b/spec/bundler/plugin/index_spec.rb
@@ -175,4 +175,12 @@ RSpec.describe Bundler::Plugin::Index do
include_examples "it cleans up"
end
end
+
+ describe "readonly disk without home" do
+ it "ignores being unable to create temp home dir" do
+ expect_any_instance_of(Bundler::Plugin::Index).to receive(:global_index_file).
+ and_raise(Bundler::GenericSystemCallError.new("foo", "bar"))
+ Bundler::Plugin::Index.new
+ end
+ end
end
diff --git a/spec/bundler/source/git_spec.rb b/spec/bundler/source/git_spec.rb
new file mode 100644
index 0000000000..f7475a35aa
--- /dev/null
+++ b/spec/bundler/source/git_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::Source::Git do
+ before do
+ allow(Bundler).to receive(:root) { Pathname.new("root") }
+ end
+
+ let(:uri) { "https://github.com/foo/bar.git" }
+ let(:options) do
+ { "uri" => uri }
+ end
+
+ subject { described_class.new(options) }
+
+ describe "#to_s" do
+ it "returns a description" do
+ expect(subject.to_s).to eq "https://github.com/foo/bar.git (at master)"
+ end
+
+ context "when the URI contains credentials" do
+ let(:uri) { "https://my-secret-token:x-oauth-basic@github.com/foo/bar.git" }
+
+ it "filters credentials" do
+ expect(subject.to_s).to eq "https://x-oauth-basic@github.com/foo/bar.git (at master)"
+ end
+ end
+ end
+end
diff --git a/spec/commands/add_spec.rb b/spec/commands/add_spec.rb
index 7916db960a..d1f2050aa0 100644
--- a/spec/commands/add_spec.rb
+++ b/spec/commands/add_spec.rb
@@ -51,8 +51,9 @@ RSpec.describe "bundle add" do
end
it "adds multiple version constraints when specified" do
- bundle "add 'foo' --version='< 3.0, > 1.1'"
- expect(bundled_app("Gemfile").read).to match(/gem "foo", "< 3.0", "> 1.1"/)
+ requirements = ["< 3.0", "> 1.0"]
+ bundle "add 'foo' --version='#{requirements.join(", ")}'"
+ expect(bundled_app("Gemfile").read).to match(/gem "foo", #{Gem::Requirement.new(requirements).as_list.map(&:dump).join(', ')}/)
expect(the_bundle).to include_gems "foo 2.0"
end
end
diff --git a/spec/commands/binstubs_spec.rb b/spec/commands/binstubs_spec.rb
index 8157173b42..ad859a21d5 100644
--- a/spec/commands/binstubs_spec.rb
+++ b/spec/commands/binstubs_spec.rb
@@ -39,6 +39,18 @@ RSpec.describe "bundle binstubs <gem>" do
expect(bundled_app("bin/rails")).to exist
end
+ it "allows installing all binstubs" do
+ install_gemfile! <<-G
+ source "file://#{gem_repo1}"
+ gem "rails"
+ G
+
+ bundle! :binstubs, :all => true
+
+ expect(bundled_app("bin/rails")).to exist
+ expect(bundled_app("bin/rake")).to exist
+ end
+
it "displays an error when used without any gem" do
install_gemfile <<-G
source "file://#{gem_repo1}"
@@ -50,6 +62,17 @@ RSpec.describe "bundle binstubs <gem>" do
expect(out).to include("`bundle binstubs` needs at least one gem to run.")
end
+ it "displays an error when used with --all and gems" do
+ install_gemfile <<-G
+ source "file://#{gem_repo1}"
+ gem "rack"
+ G
+
+ bundle "binstubs rack", :all => true
+ expect(last_command).to be_failure
+ expect(last_command.bundler_err).to include("Cannot specify --all with specific gems")
+ end
+
context "when generating bundle binstub outside bundler" do
it "should abort" do
install_gemfile <<-G
diff --git a/spec/commands/exec_spec.rb b/spec/commands/exec_spec.rb
index 30972b5e46..2fe2667363 100644
--- a/spec/commands/exec_spec.rb
+++ b/spec/commands/exec_spec.rb
@@ -610,13 +610,7 @@ RSpec.describe "bundle exec" do
let(:executable) { super() << "\nclass Err < Exception\ndef backtrace; end;\nend\nraise Err" }
let(:exit_code) { 1 }
let(:expected) { super() << "\nbundler: failed to load command: #{path} (#{path})" }
- let(:expected_err) do
- if ENV["BUNDLER_SPEC_SUB_VERSION"] == "1.98"
- "Err: Err"
- else
- "bundler: failed to load command: #{path} (#{path})\nErr: Err"
- end
- end
+ let(:expected_err) { "Err: Err" }
it_behaves_like "it runs"
end
@@ -625,13 +619,7 @@ RSpec.describe "bundle exec" do
let(:executable) { super() << "\nclass Err < Exception\ndef backtrace; end;\nend\nraise Err" }
let(:exit_code) { 1 }
let(:expected_err) { "bundler: failed to load command: #{path} (#{path})\nErr: Err" }
- let(:expected) do
- if ENV["BUNDLER_SPEC_SUB_VERSION"] == "1.98"
- super() << "\nbundler: failed to load command: #{path} (#{path})"
- else
- super()
- end
- end
+ let(:expected) { super() }
it_behaves_like "it runs"
end
diff --git a/spec/commands/lock_spec.rb b/spec/commands/lock_spec.rb
index bd5bdfff2f..81eba1ceda 100644
--- a/spec/commands/lock_spec.rb
+++ b/spec/commands/lock_spec.rb
@@ -97,6 +97,14 @@ RSpec.describe "bundle lock" do
expect { read_lockfile }.to raise_error(Errno::ENOENT)
end
+ it "writes to custom location using --lockfile when a default lockfile is present" do
+ bundle "install"
+ bundle "lock --lockfile=lock"
+
+ expect(out).to match(/Writing lockfile to.+lock/)
+ expect(read_lockfile("lock")).to eq(@lockfile)
+ end
+
it "update specific gems using --update" do
lockfile @lockfile.gsub("2.3.2", "2.3.1").gsub("10.0.2", "10.0.1")
diff --git a/spec/install/gems/resolving_spec.rb b/spec/install/gems/resolving_spec.rb
index 2925542d86..e58f32836c 100644
--- a/spec/install/gems/resolving_spec.rb
+++ b/spec/install/gems/resolving_spec.rb
@@ -166,8 +166,9 @@ RSpec.describe "bundle install with install-time dependencies" do
end
describe "with a compound requirement" do
- let(:ruby_requirement) { %("< 5000", "> 0.1") }
- let(:error_message_requirement) { "< 5000, > 0.1" }
+ let(:reqs) { ["> 0.1", "< 5000"] }
+ let(:ruby_requirement) { reqs.map(&:dump).join(", ") }
+ let(:error_message_requirement) { Gem::Requirement.new(reqs).to_s }
it_behaves_like "ruby version conflicts"
end
diff --git a/spec/install/path_spec.rb b/spec/install/path_spec.rb
index 467e95ec57..3ed2b30cce 100644
--- a/spec/install/path_spec.rb
+++ b/spec/install/path_spec.rb
@@ -98,7 +98,7 @@ RSpec.describe "bundle install" do
if type == :env
ENV["BUNDLE_PATH"] = location
elsif type == :global
- bundle "config path #{location}", "no-color" => nil
+ bundle! "config path #{location}", "no-color" => nil
end
end
@@ -112,6 +112,16 @@ RSpec.describe "bundle install" do
expect(the_bundle).to include_gems "rack 1.0.0"
end
+ it "installs gems to ." do
+ set_bundle_path(type, ".")
+ bundle! "config --global disable_shared_gems true"
+
+ bundle! :install
+
+ expect([bundled_app("cache/rack-1.0.0.gem"), bundled_app("gems/rack-1.0.0"), bundled_app("specifications/rack-1.0.0.gemspec")]).to all exist
+ expect(the_bundle).to include_gems "rack 1.0.0"
+ end
+
it "installs gems to BUNDLE_PATH with #{type}" do
set_bundle_path(type, bundled_app("vendor").to_s)