Skip to content

Commit

Permalink
Run bundle-stats command with custom Gemfile path (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
ldlsegovia authored Jul 1, 2023
1 parent 2763c66 commit 3186c5d
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 21 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,14 @@ To consume information with a build job or somesuch, all commands can emit JSON.
]
}

### Custom Gemfile path

This gem by default attempts to locate the Gemfile and Gemfile.lock files in parent directories. If you want to specify a specific location for your Gemfile/gems.rb file, you can use the `--gemfile_path` option.

> bundle-stats show sass-rails --gemfile_path=/Users/user/project/Gemfile

Keep in mind that the location of the Gemfile.lock/gems.locked file will be inferred from the location of the Gemfile/gems.rb file.

Contributing
------------

Expand Down
1 change: 1 addition & 0 deletions lib/bundler/stats.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require_relative 'stats/calculator'
require_relative 'stats/file_path_resolver'
require_relative 'stats/printer'
require_relative 'stats/remover'
require_relative 'stats/skiplist'
Expand Down
31 changes: 10 additions & 21 deletions lib/bundler/stats/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class CLI < ::Thor
desc 'stats', 'Displays basic stats about the gems in your Gemfile'
method_option :format, aliases: "-f", description: "Output format, either JSON or text"
method_option :nofollow, description: "A comma delimited list of dependencies not to follow."
method_option :gemfile_path, description: "Custom path for Gemfile/gems.rb and Gemfile.lock/gems.locked"
def stats
calculator = build_calculator(options)
stats = calculator.stats
Expand All @@ -27,6 +28,7 @@ def stats
desc 'show TARGET', 'Prints the dependency tree for a single gem in your Gemfile'
method_option :format, aliases: "-f", description: "Output format, either JSON or text"
method_option :nofollow, description: "A comma delimited list of dependencies not to follow."
method_option :gemfile_path, description: "Custom path for Gemfile/gems.rb and Gemfile.lock/gems.locked"
def show(target)
calculator = build_calculator(options)
stats = calculator.summarize(target)
Expand All @@ -41,6 +43,7 @@ def show(target)
desc 'versions TARGET', 'Shows versions requirements for target in other dependencies'
method_option :format, aliases: "-f", description: "Output format, either JSON or text"
method_option :nofollow, description: "A comma delimited list of dependencies not to follow."
method_option :gemfile_path, description: "Custom path for Gemfile/gems.rb and Gemfile.lock/gems.locked"
def versions(target)
calculator = build_calculator(options)
stats = calculator.versions(target)
Expand Down Expand Up @@ -122,29 +125,15 @@ def draw_versions(stats, target)

def build_calculator(options)
skiplist = Bundler::Stats::Skiplist.new(options[:nofollow])
@calculator ||= Bundler::Stats::Calculator.new(gemfile_path, lockfile_path, skiplist)
@calculator ||= Bundler::Stats::Calculator.new(
file_path_resolver.gemfile_path,
file_path_resolver.lockfile_path,
skiplist
)
end

def gemfile_path
cwd = Pathname.new("./")
until cwd.realdirpath.root? do
%w(gems.rb Gemfile).each do |gemfile|
return (cwd + gemfile) if File.exist?(cwd + gemfile)
end
cwd = cwd.parent
end
raise ArgumentError, "Couldn't find gems.rb nor Gemfile in this directory or parents"
end

def lockfile_path
cwd = Pathname.new(".")
until cwd.realdirpath.root? do
%w(gems.locked Gemfile.lock).each do |lockfile|
return (cwd + lockfile) if File.exist?(cwd + lockfile)
end
cwd = cwd.parent
end
raise ArgumentError, "Couldn't find gems.locked nor Gemfile.lock in this directory or parents"
def file_path_resolver
@file_path_resolver ||= Bundler::Stats::FilePathResolver.new(options[:gemfile_path])
end
end
end
Expand Down
56 changes: 56 additions & 0 deletions lib/bundler/stats/file_path_resolver.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
module Bundler
module Stats
class FilePathResolver
FILES_MAP = {
"gems.rb" => "gems.locked",
"Gemfile" => "Gemfile.lock"
}

def initialize(specific_gemfile_path = nil)
@specific_gemfile_path = specific_gemfile_path
end

def gemfile_path
resolve_file_path(FILES_MAP.keys, specific_gemfile_path)
end

def lockfile_path
resolve_file_path(FILES_MAP.values, resolve_lockfile_path)
end

private

attr_reader :specific_gemfile_path

def resolve_lockfile_path
return unless specific_gemfile_path

file_path = Pathname.new(specific_gemfile_path)
file_name = file_path.basename.to_s
locked_file_name = FILES_MAP[file_name]
raise ArgumentError, "Invalid file name: #{file_name}" if locked_file_name.nil?
file_path.dirname.join(locked_file_name).to_s
end

def resolve_file_path(file_names, custom_path)
if custom_path
raise ArgumentError, "Couldn't find #{custom_path} file path" unless File.exist?(custom_path)
return custom_path
end

find_file_path(file_names)
end

def find_file_path(file_names)
cwd = Pathname.new(".")
until cwd.realdirpath.root? do
file_names.each do |file|
return (cwd + file).to_s if File.exist?(cwd + file)
end
cwd = cwd.parent
end
raise ArgumentError, "Couldn't find #{file_names.join(" nor ")} in this directory or parents"
end
end
end
end
85 changes: 85 additions & 0 deletions spec/lib/bundler/stats/file_path_resolver_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
require 'spec_helper'

describe Bundler::Stats::FilePathResolver do
let(:file_path_resolver) { described_class.new(specific_gemfile_path) }

context "with undefined specific gemfile path" do
let(:specific_gemfile_path) { nil }

before do
allow(File).to receive(:exist?).and_return(false)
end

context "without files found" do
it do
expect { file_path_resolver.gemfile_path }.to raise_error(
ArgumentError, "Couldn't find gems.rb nor Gemfile in this directory or parents"
)
end

it do
expect { file_path_resolver.lockfile_path }.to raise_error(
ArgumentError, "Couldn't find gems.locked nor Gemfile.lock in this directory or parents"
)
end
end

context "with files found" do
before do
allow(File).to receive(:exist?).with(Pathname.new("../Gemfile")).and_return(true)
allow(File).to receive(:exist?).with(Pathname.new("../../gems.locked")).and_return(true)
end

it { expect(file_path_resolver.gemfile_path).to eq("../Gemfile") }
it { expect(file_path_resolver.lockfile_path).to eq("../../gems.locked") }
end
end

context "with specific gemfile path" do
let(:specific_gemfile_path) { "some-project/Gemfile" }

context "with valid file path" do
before do
allow(File).to receive(:exist?).and_return(true)
end

it { expect(file_path_resolver.gemfile_path).to eq("some-project/Gemfile") }
it { expect(file_path_resolver.lockfile_path).to eq("some-project/Gemfile.lock") }

context "with gems.rb file" do
let(:specific_gemfile_path) { "some-project/gems.rb" }

it { expect(file_path_resolver.gemfile_path).to eq("some-project/gems.rb") }
it { expect(file_path_resolver.lockfile_path).to eq("some-project/gems.locked") }
end

context "with invalid file name" do
let(:specific_gemfile_path) { "some-project/yeimfile" }

it do
expect { file_path_resolver.lockfile_path }.to raise_error(
ArgumentError, "Invalid file name: yeimfile"
)
end
end
end

context "with invalid file path" do
before do
allow(File).to receive(:exist?).and_return(false)
end

it do
expect { file_path_resolver.gemfile_path }.to raise_error(
ArgumentError, "Couldn't find some-project/Gemfile file path"
)
end

it do
expect { file_path_resolver.lockfile_path }.to raise_error(
ArgumentError, "Couldn't find some-project/Gemfile.lock file path"
)
end
end
end
end

0 comments on commit 3186c5d

Please sign in to comment.