[rubygems/rubygems] Define bundler doctor as a subcommand

- See explanation in previous commit https://github.com/rubygems/rubygems/commit/170890befb4c

https://github.com/rubygems/rubygems/commit/8f1b5a4479
This commit is contained in:
Edouard CHIN 2025-04-04 00:45:06 +02:00 committed by Hiroshi SHIBATA
parent ef82273c04
commit c2e58a9043
No known key found for this signature in database
GPG Key ID: F9CF13417264FAC2
5 changed files with 35 additions and 23 deletions

View File

@ -610,17 +610,8 @@ module Bundler
end end
desc "doctor [OPTIONS]", "Checks the bundle for common problems" desc "doctor [OPTIONS]", "Checks the bundle for common problems"
long_desc <<-D require_relative "cli/doctor"
Doctor scans the OS dependencies of each of the gems requested in the Gemfile. If subcommand("doctor", Doctor)
missing dependencies are detected, Bundler prints them and exits status 1.
Otherwise, Bundler prints a success message and exits with a status of 0.
D
method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
def doctor
require_relative "cli/doctor"
Doctor.new(options).run
end
desc "issue", "Learn how to report an issue in Bundler" desc "issue", "Learn how to report an issue in Bundler"
def issue def issue

20
lib/bundler/cli/doctor.rb Normal file
View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
module Bundler
class CLI::Doctor < Thor
default_command(:diagnose)
desc "diagnose [OPTIONS]", "Checks the bundle for common problems"
long_desc <<-D
Doctor scans the OS dependencies of each of the gems requested in the Gemfile. If
missing dependencies are detected, Bundler prints them and exits status 1.
Otherwise, Bundler prints a success message and exits with a status of 0.
D
method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
def diagnose
require_relative "doctor/diagnose"
Diagnose.new(options).run
end
end
end

View File

@ -65,7 +65,7 @@ module Bundler
end end
def check! def check!
require_relative "check" require_relative "../check"
Bundler::CLI::Check.new({}).run Bundler::CLI::Check.new({}).run
end end

View File

@ -34,8 +34,8 @@ module Bundler
end end
def doctor def doctor
require_relative "doctor" require_relative "doctor/diagnose"
Bundler::CLI::Doctor.new({}).run Bundler::CLI::Doctor::Diagnose.new({}).run
end end
end end
end end

View File

@ -4,6 +4,7 @@ require "find"
require "stringio" require "stringio"
require "bundler/cli" require "bundler/cli"
require "bundler/cli/doctor" require "bundler/cli/doctor"
require "bundler/cli/doctor/diagnose"
RSpec.describe "bundle doctor" do RSpec.describe "bundle doctor" do
before(:each) do before(:each) do
@ -46,14 +47,14 @@ RSpec.describe "bundle doctor" do
end end
it "exits with a success message if the installed gem has no C extensions" do it "exits with a success message if the installed gem has no C extensions" do
doctor = Bundler::CLI::Doctor.new({}) doctor = Bundler::CLI::Doctor::Diagnose.new({})
allow(doctor).to receive(:lookup_with_fiddle).and_return(false) allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
expect { doctor.run }.not_to raise_error expect { doctor.run }.not_to raise_error
expect(@stdout.string).to include("No issues") expect(@stdout.string).to include("No issues")
end end
it "exits with a success message if the installed gem's C extension dylib breakage is fine" do it "exits with a success message if the installed gem's C extension dylib breakage is fine" do
doctor = Bundler::CLI::Doctor.new({}) doctor = Bundler::CLI::Doctor::Diagnose.new({})
expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/myrack/myrack.bundle"] expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/myrack/myrack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/lib/libSystem.dylib"] expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/lib/libSystem.dylib"]
allow(doctor).to receive(:lookup_with_fiddle).with("/usr/lib/libSystem.dylib").and_return(false) allow(doctor).to receive(:lookup_with_fiddle).with("/usr/lib/libSystem.dylib").and_return(false)
@ -62,7 +63,7 @@ RSpec.describe "bundle doctor" do
end end
it "exits with a message if one of the linked libraries is missing" do it "exits with a message if one of the linked libraries is missing" do
doctor = Bundler::CLI::Doctor.new({}) doctor = Bundler::CLI::Doctor::Diagnose.new({})
expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/myrack/myrack.bundle"] expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/myrack/myrack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib"] expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib"]
allow(doctor).to receive(:lookup_with_fiddle).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_return(true) allow(doctor).to receive(:lookup_with_fiddle).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_return(true)
@ -84,7 +85,7 @@ RSpec.describe "bundle doctor" do
end end
it "exits with an error if home contains files that are not readable/writable" do it "exits with an error if home contains files that are not readable/writable" do
doctor = Bundler::CLI::Doctor.new({}) doctor = Bundler::CLI::Doctor::Diagnose.new({})
allow(doctor).to receive(:lookup_with_fiddle).and_return(false) allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
expect { doctor.run }.not_to raise_error expect { doctor.run }.not_to raise_error
expect(@stdout.string).to include( expect(@stdout.string).to include(
@ -106,7 +107,7 @@ RSpec.describe "bundle doctor" do
end end
it "exits with an error if home contains files that are not readable" do it "exits with an error if home contains files that are not readable" do
doctor = Bundler::CLI::Doctor.new({}) doctor = Bundler::CLI::Doctor::Diagnose.new({})
allow(doctor).to receive(:lookup_with_fiddle).and_return(false) allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
allow(@stat).to receive(:uid) { Process.uid } allow(@stat).to receive(:uid) { Process.uid }
allow(File).to receive(:writable?).with(@unwritable_file) { false } allow(File).to receive(:writable?).with(@unwritable_file) { false }
@ -119,7 +120,7 @@ RSpec.describe "bundle doctor" do
end end
it "exits without an error if home contains files that are not writable" do it "exits without an error if home contains files that are not writable" do
doctor = Bundler::CLI::Doctor.new({}) doctor = Bundler::CLI::Doctor::Diagnose.new({})
allow(doctor).to receive(:lookup_with_fiddle).and_return(false) allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
allow(@stat).to receive(:uid) { Process.uid } allow(@stat).to receive(:uid) { Process.uid }
allow(File).to receive(:writable?).with(@unwritable_file) { false } allow(File).to receive(:writable?).with(@unwritable_file) { false }
@ -137,7 +138,7 @@ RSpec.describe "bundle doctor" do
end end
it "exits with an error if home contains files that are not readable/writable and are not owned by the current user" do it "exits with an error if home contains files that are not readable/writable and are not owned by the current user" do
doctor = Bundler::CLI::Doctor.new({}) doctor = Bundler::CLI::Doctor::Diagnose.new({})
allow(doctor).to receive(:lookup_with_fiddle).and_return(false) allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
allow(File).to receive(:writable?).with(@unwritable_file) { false } allow(File).to receive(:writable?).with(@unwritable_file) { false }
allow(File).to receive(:readable?).with(@unwritable_file) { false } allow(File).to receive(:readable?).with(@unwritable_file) { false }
@ -149,7 +150,7 @@ RSpec.describe "bundle doctor" do
end end
it "exits with a warning if home contains files that are read/write but not owned by current user" do it "exits with a warning if home contains files that are read/write but not owned by current user" do
doctor = Bundler::CLI::Doctor.new({}) doctor = Bundler::CLI::Doctor::Diagnose.new({})
allow(doctor).to receive(:lookup_with_fiddle).and_return(false) allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
allow(File).to receive(:writable?).with(@unwritable_file) { true } allow(File).to receive(:writable?).with(@unwritable_file) { true }
allow(File).to receive(:readable?).with(@unwritable_file) { true } allow(File).to receive(:readable?).with(@unwritable_file) { true }
@ -164,7 +165,7 @@ RSpec.describe "bundle doctor" do
context "when home contains filenames with special characters" do context "when home contains filenames with special characters" do
it "escape filename before command execute" do it "escape filename before command execute" do
doctor = Bundler::CLI::Doctor.new({}) doctor = Bundler::CLI::Doctor::Diagnose.new({})
expect(doctor).to receive(:`).with("/usr/bin/otool -L \\$\\(date\\)\\ \\\"\\'\\\\.bundle").and_return("dummy string") expect(doctor).to receive(:`).with("/usr/bin/otool -L \\$\\(date\\)\\ \\\"\\'\\\\.bundle").and_return("dummy string")
doctor.dylibs_darwin('$(date) "\'\.bundle') doctor.dylibs_darwin('$(date) "\'\.bundle')
expect(doctor).to receive(:`).with("/usr/bin/ldd \\$\\(date\\)\\ \\\"\\'\\\\.bundle").and_return("dummy string") expect(doctor).to receive(:`).with("/usr/bin/ldd \\$\\(date\\)\\ \\\"\\'\\\\.bundle").and_return("dummy string")