Skip to content

Commit

Permalink
Merge pull request #34 from kbrock/gem_path
Browse files Browse the repository at this point in the history
Allow user to specify a PATH to search for gem overrides
  • Loading branch information
agrare committed Jan 9, 2024
2 parents f9db319 + 6a9ebc9 commit c1b0037
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 10 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ original declaration.

## Configuration

### Disabling warnings

To disable warnings that are output to the console when `override_gem` or
`ensure_gem` is in use, you can update a bundler setting:

Expand All @@ -95,6 +97,32 @@ $ export BUNDLE_BUNDLER_INJECT__DISABLE_WARN_OVERRIDE_GEM=true
There is a fallback for those that will check the `RAILS_ENV` environment
variable, and will disable the warning when in `"production"`.

### Specifying gem source directories

Many developers checkout gems into a single directory for enhancement.
Instead of specifying the full path of gems every time, specify a gem path
to locate these directories. This can be defined with a bundler setting:

```console
$ bundle config bundler_inject.gem_path ~/src:~/gem_src
```

or use an environment variable:

```console
$ export BUNDLE_BUNDLER_INJECT__GEM_PATH=~/src:~/gem_src
```

An override will find a gem in either of these two directories or in the directory
where the Gemfile override is located.

```Gemfile
# located in ~/src/ansi
override_gem "ansi"
# located in $PWD/mime_override
override_gem "mime/type", path: "mime_override"
```

## What is this sorcery?

While this is technically a bundler plugin, bundler-inject does not use the
Expand Down
29 changes: 26 additions & 3 deletions lib/bundler/inject/dsl_patch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def override_gem(name, *args)
calling_file = "#{calling_loc.path}:#{calling_loc.lineno}"

remove_dependencies_and_sources(dependency)
expand_gem_path(args, calling_file)
expand_gem_path(name, args, calling_file)
gem(name, *args).tap do
warn_override_gem(calling_file, name, args)
end
Expand Down Expand Up @@ -59,10 +59,17 @@ def remove_dependencies_and_sources(dependency)
end
end

def expand_gem_path(args, calling_file)
# Determine the path for the gem
#
# This is used when an override has no options or a path is specified
# This path is turned into an absolute path
def expand_gem_path(name, args, calling_file)
args << {:path => name} if args.empty?
return unless args.last.kind_of?(Hash) && args.last[:path]

args.last[:path] = File.expand_path(args.last[:path], File.dirname(calling_file))
possible_paths = [File.dirname(calling_file)] + bundler_inject_gem_path
full_path = possible_paths.map { |p| File.expand_path(args.last[:path], p) }.detect { |f| File.exist?(f) }
args.last[:path] = full_path if full_path
end

def extract_version_opts(args)
Expand Down Expand Up @@ -98,6 +105,22 @@ def load_bundler_d(dir)
eval_gemfile(f)
end
end

# Path to search for override gems
#
# The gem path can be set in two ways:
#
# - Via bundler's Bundler::Settings
#
# bundle config bundler_inject.gem_path ~/src:~/gems_src
#
# - Via an environment variable
#
# BUNDLE_BUNDLER_INJECT__GEM_PATH=~/src:~/gems_src
#
def bundler_inject_gem_path
@bundler_inject_gem_path ||= (Bundler.settings["bundler_inject.gem_path"] || "").split(File::PATH_SEPARATOR)
end
end
end
end
46 changes: 42 additions & 4 deletions spec/bundler_inject_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@
expect(err).to match %r{^\*\* override_gem\("ansi", :git=>"https://github.com/rubyworks/ansi"\) at .+/bundler\.d/local_overrides\.rb:1$}
end

it "with a path" do
with_path_based_gem("https://github.com/rubyworks/ansi") do |path|
it "with an absolute path" do
with_path_based_gem("https://github.com/rubyworks/ansi", "the_gem") do |path|
write_bundler_d_file <<~F
override_gem "ansi", :path => #{path.to_s.inspect}
F
Expand All @@ -129,8 +129,8 @@
end
end

it "with a path that includes ~" do
with_path_based_gem("https://github.com/rubyworks/ansi") do |path|
it "with a full path that includes ~" do
with_path_based_gem("https://github.com/rubyworks/ansi", "the_gem") do |path|
path = Pathname.new("~/#{path.relative_path_from(Pathname.new("~").expand_path)}")

write_bundler_d_file <<~F
Expand All @@ -143,6 +143,44 @@
end
end

it "with a filename path in a gem_path location" do
with_path_based_gem("https://github.com/rubyworks/ansi", "the_gem") do |path|
write_bundler_d_file <<~F
override_gem "ansi", :path => "the_gem"
F
bundle(:update, :env => {"BUNDLE_BUNDLER_INJECT__GEM_PATH" => path.dirname.to_s})

expect(lockfile_specs).to eq [["ansi", "1.5.0"]]
expect(err).to match %r{^\*\* override_gem\("ansi", :path=>#{path.expand_path.to_s.inspect}\) at .+/bundler\.d/local_overrides\.rb:1$}
end
end

it "with no path in a gem_path location" do
with_path_based_gem("https://github.com/rubyworks/ansi", "ansi") do |path|
write_bundler_d_file <<~F
override_gem "ansi"
F
bundle(:update, :env => {"BUNDLE_BUNDLER_INJECT__GEM_PATH" => path.dirname.to_s})

expect(lockfile_specs).to eq [["ansi", "1.5.0"]]
expect(err).to match %r{^\*\* override_gem\("ansi", :path=>#{path.expand_path.to_s.inspect}\) at .+/bundler\.d/local_overrides\.rb:1$}
end
end

it "with no path in a gem_path location and multiple paths" do
with_path_based_gem("https://github.com/rubyworks/ansi", "ansi") do |path|
Dir.mktmpdir do |empty_dir|
write_bundler_d_file <<~F
override_gem "ansi"
F
bundle(:update, :env => {"BUNDLE_BUNDLER_INJECT__GEM_PATH" => "/nonexistent-directory/:#{empty_dir.to_s}:#{path.dirname.to_s}"})

expect(lockfile_specs).to eq [["ansi", "1.5.0"]]
expect(err).to match %r{^\*\* override_gem\("ansi", :path=>#{path.expand_path.to_s.inspect}\) at .+/bundler\.d/local_overrides\.rb:1$}
end
end
end

it "when the gem doesn't exist" do
write_bundler_d_file <<~F
override_gem "omg"
Expand Down
6 changes: 3 additions & 3 deletions spec/support/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,14 @@ def rm_global_bundler_d_dir
FileUtils.rm_rf(Helpers.global_bundler_d_dir)
end

def with_path_based_gem(source_repo)
def with_path_based_gem(source_repo, dir_name)
Dir.mktmpdir do |path|
path = Pathname.new(path)
Dir.chdir(path) do
out, status = Open3.capture2e("git clone --depth 1 #{source_repo} the_gem")
out, status = Open3.capture2e("git clone --depth 1 #{source_repo} #{dir_name}")
raise "An error occured while cloning #{source_repo.inspect}...\n#{out}" unless status.exitstatus == 0
end
path = path.join("the_gem")
path = path.join(dir_name)

yield path
end
Expand Down

0 comments on commit c1b0037

Please sign in to comment.