From 819c8e11f8e88e62108602ee842366b28920654f Mon Sep 17 00:00:00 2001 From: Postmodern Date: Wed, 13 Sep 2023 09:41:57 -0700 Subject: [PATCH] Raise a `GitnotInstalled` exception if `git` is not installed (closes #387). --- lib/bundler/audit/cli.rb | 13 +++------ lib/bundler/audit/database.rb | 35 ++++++++++++++++++++--- spec/cli_spec.rb | 30 ++++++++++++-------- spec/database_spec.rb | 52 +++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 25 deletions(-) diff --git a/lib/bundler/audit/cli.rb b/lib/bundler/audit/cli.rb index bada72da..60333fe0 100644 --- a/lib/bundler/audit/cli.rb +++ b/lib/bundler/audit/cli.rb @@ -116,7 +116,7 @@ def download(path=Database.path) begin Database.download(path: path, quiet: options.quiet?) - rescue Database::DownloadFailed => error + rescue Database::GitNotInstalled, Database::DownloadFailed => error say error.message, :red exit 1 end @@ -142,16 +142,11 @@ def update(path=Database.path) when true say("Updated ruby-advisory-db", :green) unless options.quiet? when nil - if Bundler.git_present? - unless options.quiet? - say "Skipping update, ruby-advisory-db is not a git repository", :yellow - end - else - say_error "Git is not installed!", :red - exit 1 + unless options.quiet? + say "Skipping update, ruby-advisory-db is not a git repository", :yellow end end - rescue Database::UpdateFailed => error + rescue Database::GitNotInstalled, Database::UpdateFailed => error say error.message, :red exit 1 end diff --git a/lib/bundler/audit/database.rb b/lib/bundler/audit/database.rb index 320e2af1..6beda45e 100644 --- a/lib/bundler/audit/database.rb +++ b/lib/bundler/audit/database.rb @@ -28,6 +28,12 @@ module Audit # class Database + # + # @since 0.10.0 + # + class GitNotInstalled < RuntimeError + end + class DownloadFailed < RuntimeError end @@ -103,8 +109,9 @@ def self.exists?(path=DEFAULT_PATH) # @return [Dataase] # The newly downloaded database. # - # @raise [DownloadFailed] - # Indicates that the download failed. + # @raise [DownloadFailed, GitNotInstalled] + # * {DownloadFailed} - the `git clone` command failed. + # * {GitNotInstalled} - the `git` command is not installed. # # @note # Requires network access. @@ -116,8 +123,11 @@ def self.download(path: DEFAULT_PATH, quiet: false) command << '--quiet' if quiet command << URL << path - unless system(*command) + case system(*command) + when false raise(DownloadFailed,"failed to download #{URL} to #{path.inspect}") + when nil + raise(GitNotInstalled,"the git command is not installed") end return new(path) @@ -182,6 +192,10 @@ def git? # @raise [UpdateFailed] # Could not update the ruby-advisory-db git repository. # + # @raise [UpdateFailed, GitNotInstalled] + # * {UpdateFailed} - the `git pull` command failed. + # * {GitNotInstalled} - the `git` command is not installed. + # # @since 0.8.0 # def update!(quiet: false) @@ -191,8 +205,11 @@ def update!(quiet: false) command << '--quiet' if quiet command << 'origin' << 'master' - unless system(*command) + case system(*command) + when false raise(UpdateFailed,"failed to update #{@path.inspect}") + when nil + raise(GitNotInstalled,"the git command is not installed") end return true @@ -206,12 +223,17 @@ def update!(quiet: false) # @return [String, nil] # The commit hash or `nil` if the database is not a git repository. # + # @raise [GitNotInstalled] + # The `git` command is not installed. + # # @since 0.9.0 # def commit_id if git? Dir.chdir(@path) do `git rev-parse HEAD`.chomp + rescue Errno::ENOENT + raise(GitNotInstalled,"the git command is not installed") end end end @@ -221,12 +243,17 @@ def commit_id # # @return [Time] # + # @raise [GitNotInstalled] + # The `git` command is not installed. + # # @since 0.8.0 # def last_updated_at if git? Dir.chdir(@path) do Time.parse(`git log --date=iso8601 --pretty="%cd" -1`) + rescue Errno::ENOENT + raise(GitNotInstalled,"the git command is not installed") end else File.mtime(@path) diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 11e4f256..96fcf376 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -96,27 +96,33 @@ end end - context "when git is not installed" do + context "when the ruby-advisory-db is not a git repository" do before do expect(database).to receive(:update!).and_return(nil) - - expect(Bundler).to receive(:git_present?).and_return(false) end - it "prints failure message" do + it "must print a warning message and then the stats" do + allow(subject).to receive(:stats) + expect { - begin - subject.update - rescue SystemExit - end - }.to output(/Git is not installed!/).to_stderr + subject.update + }.to output(/Skipping update, ruby-advisory-db is not a git repository/).to_stdout + end + end + + context "when git is not installed" do + before do + expect(database).to receive(:update!).and_raise( + Bundler::Audit::Database::GitNotInstalled, + "the git command is not installed" + ) end it "exits with error status code" do expect { - # Capture output of `update` only to keep spec output clean. - # The test regarding specific output is above. - expect { subject.update }.to output.to_stdout + expect { + subject.update + }.to output("the git command is not installed").to_stderr }.to raise_error(SystemExit) do |error| expect(error.success?).to eq(false) expect(error.status).to eq(1) diff --git a/spec/database_spec.rb b/spec/database_spec.rb index 4b203835..ec176afa 100644 --- a/spec/database_spec.rb +++ b/spec/database_spec.rb @@ -94,6 +94,16 @@ end end + context "when git is not installed" do + it do + expect(subject).to receive(:system).with('git', 'clone', url, path).and_return(nil) + + expect { + subject.download + }.to raise_error(described_class::GitNotInstalled,"the git command is not installed") + end + end + context "with an unknown option" do it do expect { @@ -131,6 +141,18 @@ end end + context "when git is not installed" do + before { stub_const("#{described_class}::URL",'https://example.com/') } + + it do + expect(subject).to receive(:system).with('git', 'clone', url, path).and_return(nil) + + expect { + subject.update!(quiet: false) + }.to raise_error(described_class::GitNotInstalled,"the git command is not installed") + end + end + after { FileUtils.rm_rf(dest_dir) } end @@ -155,6 +177,16 @@ expect(subject.update!(quiet: false)).to eq(false) end end + + context "when git is not installed" do + it do + expect_any_instance_of(subject).to receive(:system).with('git', 'pull', 'origin', 'master').and_return(nil) + + expect { + subject.update!(quiet: false) + }.to raise_error(described_class::GitNotInstalled,"the git command is not installed") + end + end end end @@ -264,6 +296,16 @@ it "should return the last commit ID" do expect(subject.commit_id).to be == last_commit end + + context "when git is not installed" do + it do + expect(subject).to receive(:`).with('git rev-parse HEAD').and_raise(Errno::ENOENT) + + expect { + subject.commit_id + }.to raise_error(described_class::GitNotInstalled,"the git command is not installed") + end + end end context "when the database is a bare directory" do @@ -293,6 +335,16 @@ it "should return the timestamp of the last commit" do expect(subject.last_updated_at).to be == last_commit_timestamp end + + context "when git is not installed" do + it do + expect(subject).to receive(:`).with('git log --date=iso8601 --pretty="%cd" -1').and_raise(Errno::ENOENT) + + expect { + subject.last_updated_at + }.to raise_error(described_class::GitNotInstalled,"the git command is not installed") + end + end end context "when the database is a bare directory" do