diff options
-rw-r--r-- | lib/bundler.rb | 4 | ||||
-rw-r--r-- | lib/bundler/cli.rb | 5 | ||||
-rw-r--r-- | lib/bundler/cli/add.rb | 9 | ||||
-rw-r--r-- | lib/bundler/injector.rb | 12 | ||||
-rw-r--r-- | lib/bundler/installer.rb | 2 | ||||
-rw-r--r-- | lib/bundler/plugin.rb | 7 | ||||
-rw-r--r-- | lib/bundler/plugin/events.rb | 39 | ||||
-rw-r--r-- | lib/bundler/templates/newgem/travis.yml.tt | 2 | ||||
-rw-r--r-- | man/bundle-add.ronn | 15 | ||||
-rw-r--r-- | man/bundle-binstubs.ronn | 2 | ||||
-rw-r--r-- | man/bundle-config.ronn | 8 | ||||
-rw-r--r-- | man/bundle-exec.ronn | 4 | ||||
-rw-r--r-- | man/bundle-gem.ronn | 2 | ||||
-rw-r--r-- | man/bundle-install.ronn | 2 | ||||
-rw-r--r-- | man/bundle-lock.ronn | 2 | ||||
-rw-r--r-- | man/bundle-outdated.ronn | 2 | ||||
-rw-r--r-- | man/bundle-package.ronn | 6 | ||||
-rw-r--r-- | man/bundle-update.ronn | 16 | ||||
-rw-r--r-- | man/bundle-viz.ronn | 2 | ||||
-rw-r--r-- | man/bundle.ronn | 36 | ||||
-rw-r--r-- | man/gemfile.5.ronn | 4 | ||||
-rw-r--r-- | spec/bundler/plugin/events_spec.rb | 18 | ||||
-rw-r--r-- | spec/bundler/plugin_spec.rb | 40 | ||||
-rw-r--r-- | spec/commands/add_spec.rb | 42 |
24 files changed, 219 insertions, 62 deletions
diff --git a/lib/bundler.rb b/lib/bundler.rb index 3239e83885..7904496e96 100644 --- a/lib/bundler.rb +++ b/lib/bundler.rb @@ -421,7 +421,9 @@ EOF end def read_file(file) - File.open(file, "rb", &:read) + SharedHelpers.filesystem_access(file, :read) do + File.open(file, "rb", &:read) + end end def load_marshal(data) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 1b913024e2..926a748231 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -333,7 +333,10 @@ module Bundler method_option "version", :aliases => "-v", :type => :string method_option "group", :aliases => "-g", :type => :string method_option "source", :aliases => "-s", :type => :string - + method_option "skip-install", :type => :boolean, :banner => + "Adds gem to the Gemfile but does not install it" + method_option "optimistic", :type => :boolean, :banner => "Adds optimistic declaration of version to gem" + method_option "strict", :type => :boolean, :banner => "Adds strict declaration of version to gem" def add(gem_name) require "bundler/cli/add" Add.new(options.dup, gem_name).run diff --git a/lib/bundler/cli/add.rb b/lib/bundler/cli/add.rb index 1fcbd22f28..6adccb13d0 100644 --- a/lib/bundler/cli/add.rb +++ b/lib/bundler/cli/add.rb @@ -9,6 +9,8 @@ module Bundler end def run + raise InvalidOption, "You can not specify `--strict` and `--optimistic` at the same time." if @options[:strict] && @options[:optimistic] + version = @options[:version].nil? ? nil : @options[:version].split(",").map(&:strip) unless version.nil? @@ -18,8 +20,11 @@ module Bundler end dependency = Bundler::Dependency.new(@gem_name, version, @options) - Injector.inject([dependency], :conservative_versioning => @options[:version].nil?) # Perform conservative versioning only when version is not specified - Installer.install(Bundler.root, Bundler.definition) + Injector.inject([dependency], + :conservative_versioning => @options[:version].nil?, # Perform conservative versioning only when version is not specified + :optimistic => @options[:optimistic], + :strict => @options[:strict]) + Installer.install(Bundler.root, Bundler.definition) unless @options["skip-install"] end end end diff --git a/lib/bundler/injector.rb b/lib/bundler/injector.rb index 9c67a80777..b62279b94c 100644 --- a/lib/bundler/injector.rb +++ b/lib/bundler/injector.rb @@ -61,7 +61,17 @@ module Bundler seg_end_index = version >= Gem::Version.new("1.0") ? 1 : 2 prerelease_suffix = version.to_s.gsub(version.release.to_s, "") if version.prerelease? - "~> #{segments[0..seg_end_index].join(".")}#{prerelease_suffix}" + "#{version_prefix}#{segments[0..seg_end_index].join(".")}#{prerelease_suffix}" + end + + def version_prefix + if @options[:strict] + "= " + elsif @options[:optimistic] + ">= " + else + "~> " + end end def build_gem_lines(conservative_versioning) diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb index 33f5d62844..b934c38b94 100644 --- a/lib/bundler/installer.rb +++ b/lib/bundler/installer.rb @@ -21,7 +21,7 @@ module Bundler # For more information see the #run method on this class. def self.install(root, definition, options = {}) installer = new(root, definition) - Plugin.hook("before-install-all", definition.dependencies) + Plugin.hook(Plugin::Events::GEM_BEFORE_INSTALL_ALL, definition.dependencies) installer.run(options) installer end diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb index 127f1f64c0..422d4acfbc 100644 --- a/lib/bundler/plugin.rb +++ b/lib/bundler/plugin.rb @@ -5,6 +5,7 @@ require "bundler/plugin/api" module Bundler module Plugin autoload :DSL, "bundler/plugin/dsl" + autoload :Events, "bundler/plugin/events" autoload :Index, "bundler/plugin/index" autoload :Installer, "bundler/plugin/installer" autoload :SourceList, "bundler/plugin/source_list" @@ -175,6 +176,9 @@ module Bundler # To be called via the API to register a hooks and corresponding block that # will be called to handle the hook def add_hook(event, &block) + unless Events.defined_event?(event) + raise ArgumentError, "Event '#{event}' not defined in Bundler::Plugin::Events" + end @hooks_by_event[event.to_s] << block end @@ -186,6 +190,9 @@ module Bundler # @param [String] event def hook(event, *args, &arg_blk) return unless Bundler.feature_flag.plugins? + unless Events.defined_event?(event) + raise ArgumentError, "Event '#{event}' not defined in Bundler::Plugin::Events" + end plugins = index.hook_plugins(event) return unless plugins.any? diff --git a/lib/bundler/plugin/events.rb b/lib/bundler/plugin/events.rb new file mode 100644 index 0000000000..26bd59e5cf --- /dev/null +++ b/lib/bundler/plugin/events.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Bundler + module Plugin + module Events + def self.define(const, event) + const = const.to_sym.freeze + if const_defined?(const) && const_get(const) != event + raise ArgumentError, "Attempting to reassign #{const} to a different value" + end + const_set(const, event) unless const_defined?(const) + @events ||= {} + @events[event] = const + end + private_class_method :define + + def self.reset + @events.each_value do |const| + remove_const(const) + end + @events = nil + end + private_class_method :reset + + # Check if an event has been defined + # @param event [String] An event to check + # @return [Boolean] A boolean indicating if the event has been defined + def self.defined_event?(event) + @events ||= {} + @events.key?(event) + end + + # @!parse + # # A hook called before any gems install + # GEM_BEFORE_INSTALL_ALL = "before-install-all" + define :GEM_BEFORE_INSTALL_ALL, "before-install-all" + end + end +end diff --git a/lib/bundler/templates/newgem/travis.yml.tt b/lib/bundler/templates/newgem/travis.yml.tt index fe0761cc23..7a3381a889 100644 --- a/lib/bundler/templates/newgem/travis.yml.tt +++ b/lib/bundler/templates/newgem/travis.yml.tt @@ -1,5 +1,7 @@ +--- sudo: false language: ruby +cache: bundler rvm: - <%= RUBY_VERSION %> before_install: gem install bundler -v <%= Bundler::VERSION %> diff --git a/man/bundle-add.ronn b/man/bundle-add.ronn index f0f9b54d8f..1e2d732ec6 100644 --- a/man/bundle-add.ronn +++ b/man/bundle-add.ronn @@ -3,10 +3,10 @@ bundle-add(1) -- Add gem to the Gemfile and run bundle install ## SYNOPSIS -`bundle add` <GEM_NAME> [--group=GROUP] [--version=VERSION] [--source=SOURCE] +`bundle add` <GEM_NAME> [--group=GROUP] [--version=VERSION] [--source=SOURCE] [--skip-install] [--strict] [--optimistic] ## DESCRIPTION -Adds the named gem to the Gemfile and run `bundle install`. +Adds the named gem to the Gemfile and run `bundle install`. `bundle install` can be avoided by using the flag `--skip-install`. Example: @@ -16,6 +16,8 @@ bundle add rails --version "< 3.0, > 1.1" bundle add rails --version "~> 5.0.0" --source "https://gems.example.com" --group "development" +bundle add rails --skip-install + bundle add rails --group "development, test" ## OPTIONS @@ -27,3 +29,12 @@ bundle add rails --group "development, test" * `--source`, , `-s`: Specify the source for the added gem. + +* `--skip-install`: + Adds the gem to the Gemfile but does not install it. + +* `--optimistic`: + Adds optimistic declaration of version + +* `--strict`: + Adds strict declaration of version diff --git a/man/bundle-binstubs.ronn b/man/bundle-binstubs.ronn index 550c0f6d66..c1ae0988cd 100644 --- a/man/bundle-binstubs.ronn +++ b/man/bundle-binstubs.ronn @@ -40,4 +40,4 @@ Calling binstubs with [GEM [GEM]] will create binstubs for all given gems. ## BUNDLE INSTALL --BINSTUBS To create binstubs for all the gems in the bundle you can use the `--binstubs` -flag in [bundle install(1)][bundle-install(1)]. +flag in [bundle install(1)](bundle-install.1.html). diff --git a/man/bundle-config.ronn b/man/bundle-config.ronn index 74f562fedf..15f78937dd 100644 --- a/man/bundle-config.ronn +++ b/man/bundle-config.ronn @@ -102,11 +102,11 @@ After running this command, every time bundler needs to install the Configuration keys in bundler have two forms: the canonical form and the environment variable form. -For instance, passing the `--without` flag to [bundle install(1)][bundle-install(1)] +For instance, passing the `--without` flag to [bundle install(1)](bundle-install.1.html) prevents Bundler from installing certain groups specified in the Gemfile(5). Bundler persists this value in `app/.bundle/config` so that calls to `Bundler.setup` do not try to find gems from the `Gemfile` that you didn't install. Additionally, -subsequent calls to [bundle install(1)][bundle-install(1)] remember this setting +subsequent calls to [bundle install(1)](bundle-install.1.html) remember this setting and skip those groups. The canonical form of this configuration is `"without"`. To convert the canonical @@ -120,7 +120,7 @@ the environment variable `BUNDLE_LOCAL__RACK`. ## LIST OF AVAILABLE KEYS The following is a list of all configuration keys and their purpose. You can -learn more about their operation in [bundle install(1)][bundle-install(1)]. +learn more about their operation in [bundle install(1)](bundle-install.1.html). * `allow_bundler_dependency_conflicts` (`BUNDLE_ALLOW_BUNDLER_DEPENDENCY_CONFLICTS`): Allow resolving to specifications that have dependencies on `bundler` that @@ -285,7 +285,7 @@ learn more about their operation in [bundle install(1)][bundle-install(1)]. A `:`-separated list of groups whose gems bundler should not install. In general, you should set these settings per-application by using the applicable -flag to the [bundle install(1)][bundle-install(1)] or [bundle package(1)][bundle-package(1)] command. +flag to the [bundle install(1)](bundle-install.1.html) or [bundle package(1)](bundle-package.1.html) command. You can set them globally either via environment variables or `bundle config`, whichever is preferable for your setup. If you use both, environment variables diff --git a/man/bundle-exec.ronn b/man/bundle-exec.ronn index 7b63cc7b47..aa680f4c5d 100644 --- a/man/bundle-exec.ronn +++ b/man/bundle-exec.ronn @@ -12,7 +12,7 @@ This command executes the command, making all gems specified in the Essentially, if you would normally have run something like `rspec spec/my_spec.rb`, and you want to use the gems specified -in the [`Gemfile(5)`][Gemfile(5)] and installed via [bundle install(1)][bundle-install(1)], you +in the [`Gemfile(5)`][Gemfile(5)] and installed via [bundle install(1)](bundle-install.1.html), you should run `bundle exec rspec spec/my_spec.rb`. Note that `bundle exec` does not require that an executable is @@ -27,7 +27,7 @@ available on your shell's `$PATH`. ## BUNDLE INSTALL --BINSTUBS -If you use the `--binstubs` flag in [bundle install(1)][bundle-install(1)], Bundler will +If you use the `--binstubs` flag in [bundle install(1)](bundle-install.1.html), Bundler will automatically create a directory (which defaults to `app_root/bin`) containing all of the executables available from gems in the bundle. diff --git a/man/bundle-gem.ronn b/man/bundle-gem.ronn index 0002f05c40..cf3d037df2 100644 --- a/man/bundle-gem.ronn +++ b/man/bundle-gem.ronn @@ -75,4 +75,4 @@ configuration file using the following names: ## SEE ALSO -* [bundle config(1)][bundle-config(1)] +* [bundle config(1)](bundle-config.1.html) diff --git a/man/bundle-install.ronn b/man/bundle-install.ronn index a4034bc506..0bfd29234a 100644 --- a/man/bundle-install.ronn +++ b/man/bundle-install.ronn @@ -375,7 +375,7 @@ which other gems in the Gemfile(5) still depend on, run `Summary`: In general, after making a change to the Gemfile(5) , you should first try to run `bundle install`, which will guarantee that no other gem in the Gemfile(5) is impacted by the change. If that -does not work, run [bundle update(1)][bundle-update(1)]. +does not work, run [bundle update(1)](bundle-update.1.html). ## SEE ALSO diff --git a/man/bundle-lock.ronn b/man/bundle-lock.ronn index 951194715f..3aa5920f5a 100644 --- a/man/bundle-lock.ronn +++ b/man/bundle-lock.ronn @@ -91,4 +91,4 @@ For a full explanation of gem platforms, see `gem help platform`. ## PATCH LEVEL OPTIONS -See [bundle update(1)][bundle-update(1)] for details. +See [bundle update(1)](bundle-update.1.html) for details. diff --git a/man/bundle-outdated.ronn b/man/bundle-outdated.ronn index 76baa3d755..8b05af1e52 100644 --- a/man/bundle-outdated.ronn +++ b/man/bundle-outdated.ronn @@ -69,7 +69,7 @@ are up to date, Bundler will exit with a status of 0. Otherwise, it will exit 1. ## PATCH LEVEL OPTIONS -See [bundle update(1)][bundle-update(1)] for details. +See [bundle update(1)](bundle-update.1.html) for details. One difference between the patch level options in `bundle update` and here is the `--strict` option. `--strict` was already an option on outdated before the patch level options were added. `--strict` diff --git a/man/bundle-package.ronn b/man/bundle-package.ronn index e2d83c092f..bc137374da 100644 --- a/man/bundle-package.ronn +++ b/man/bundle-package.ronn @@ -27,8 +27,8 @@ in your local bundler configuration. ## REMOTE FETCHING -By default, if you run `bundle install(1)`][bundle-install(1)] after running -[bundle package(1)][bundle-package(1)], bundler will still connect to `rubygems.org` +By default, if you run `bundle install(1)`](bundle-install.1.html) after running +[bundle package(1)](bundle-package.1.html), bundler will still connect to `rubygems.org` to check whether a platform-specific gem exists for any of the gems in `vendor/cache`. @@ -66,7 +66,7 @@ machine and check in the gems. For instance, you can run staging process, and check in the `vendor/cache` before deploying to production. -By default, [bundle package(1)][bundle-package(1)] fetches and also +By default, [bundle package(1)](bundle-package.1.html) fetches and also installs the gems to the default location. To package the dependencies to `vendor/cache` without installing them to the local install location, you can run `bundle package --no-install`. diff --git a/man/bundle-update.ronn b/man/bundle-update.ronn index 493986a7a4..2ad678f424 100644 --- a/man/bundle-update.ronn +++ b/man/bundle-update.ronn @@ -21,7 +21,7 @@ bundle-update(1) -- Update your gems to the latest available versions 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 +general, you should use [bundle install(1)](bundle-install.1.html) to install the same exact gems and versions across machines. You would use `bundle update` to explicitly update the version of a @@ -95,7 +95,7 @@ Consider the following Gemfile(5): gem "rails", "3.0.0.rc" gem "nokogiri" -When you run [bundle install(1)][bundle-install(1)] the first time, bundler will resolve +When you run [bundle install(1)](bundle-install.1.html) the first time, bundler will resolve all of the dependencies, all the way down, and install what you need: Fetching gem metadata from https://rubygems.org/......... @@ -132,11 +132,11 @@ all of the dependencies, all the way down, and install what you need: As you can see, even though you have two gems in the Gemfile(5), your application needs 26 different gems in order to run. Bundler remembers the exact versions -it installed in `Gemfile.lock`. The next time you run [bundle install(1)][bundle-install(1)], bundler skips +it installed in `Gemfile.lock`. The next time you run [bundle install(1)](bundle-install.1.html), bundler skips the dependency resolution and installs the same gems as it installed last time. After checking in the `Gemfile.lock` into version control and cloning it on another -machine, running [bundle install(1)][bundle-install(1)] will _still_ install the gems that you installed +machine, running [bundle install(1)](bundle-install.1.html) will _still_ install the gems that you installed last time. You don't need to worry that a new release of `erubis` or `mail` changes the gems you use. @@ -196,12 +196,12 @@ update all dependencies of that gem, including those that are also dependencies of another gem. To prevent updating shared dependencies, prior to version 1.14 the only option -was the `CONSERVATIVE UPDATING` behavior in [bundle install(1)][bundle-install(1)]: +was the `CONSERVATIVE UPDATING` behavior in [bundle install(1)](bundle-install.1.html): In this scenario, updating the `thin` version manually in the Gemfile(5), -and then running [bundle install(1)][bundle-install(1)] will only update `daemons` and `eventmachine`, +and then running [bundle install(1)](bundle-install.1.html) will only update `daemons` and `eventmachine`, but not `rack`. For more information, see the `CONSERVATIVE UPDATING` section -of [bundle install(1)][bundle-install(1)]. +of [bundle install(1)](bundle-install.1.html). Starting with 1.14, specifying the `--conservative` option will also prevent shared dependencies from being updated. @@ -339,7 +339,7 @@ use the following workflow: $ git add Gemfile.lock -* If [bundle install(1)][bundle-install(1)] reports a conflict, manually update the specific +* If [bundle install(1)](bundle-install.1.html) reports a conflict, manually update the specific gems that you changed in the Gemfile(5) $ bundle update rails thin diff --git a/man/bundle-viz.ronn b/man/bundle-viz.ronn index 762558c184..701df5415e 100644 --- a/man/bundle-viz.ronn +++ b/man/bundle-viz.ronn @@ -14,7 +14,7 @@ bundle-viz(1) -- Generates a visual dependency graph for your Gemfile `viz` generates a PNG file of the current `Gemfile(5)` as a dependency graph. `viz` requires the ruby-graphviz gem (and its dependencies). -The associated gems must also be installed via [`bundle install(1)`][bundle-install(1)]. +The associated gems must also be installed via [`bundle install(1)`](bundle-install.1.html). ## OPTIONS diff --git a/man/bundle.ronn b/man/bundle.ronn index a3a651ba3c..c03201a30c 100644 --- a/man/bundle.ronn +++ b/man/bundle.ronn @@ -30,20 +30,20 @@ We divide `bundle` subcommands into primary commands and utilities: ## PRIMARY COMMANDS -* [`bundle install(1)`][bundle-install(1)]: +* [`bundle install(1)`](bundle-install.1.html): Install the gems specified by the `Gemfile` or `Gemfile.lock` -* [`bundle update(1)`][bundle-update(1)]: +* [`bundle update(1)`](bundle-update.1.html): Update dependencies to their latest versions -* [`bundle package(1)`][bundle-package(1)]: +* [`bundle package(1)`](bundle-package.1.html): Package the .gem files required by your application into the `vendor/cache` directory -* [`bundle exec(1)`][bundle-exec(1)]: +* [`bundle exec(1)`](bundle-exec.1.html): Execute a script in the current bundle -* [`bundle config(1)`][bundle-config(1)]: +* [`bundle config(1)`](bundle-config.1.html): Specify and read configuration options for Bundler * `bundle help(1)`: @@ -51,47 +51,47 @@ We divide `bundle` subcommands into primary commands and utilities: ## UTILITIES -* [`bundle add(1)`][bundle-add(1)]: +* [`bundle add(1)`](bundle-add.1.html): Add the named gem to the Gemfile and run `bundle install` -* [`bundle binstubs(1)`][bundle-binstubs(1)]: +* [`bundle binstubs(1)`](bundle-binstubs.1.html): Generate binstubs for executables in a gem -* [`bundle check(1)`][bundle-check(1)]: +* [`bundle check(1)`](bundle-check.1.html): Determine whether the requirements for your application are installed and available to Bundler -* [`bundle show(1)`][bundle-show(1)]: +* [`bundle show(1)`](bundle-show.1.html): Show the source location of a particular gem in the bundle -* [`bundle outdated(1)`][bundle-outdated(1)]: +* [`bundle outdated(1)`](bundle-outdated.1.html): Show all of the outdated gems in the current bundle * `bundle console(1)`: Start an IRB session in the current bundle -* [`bundle open(1)`][bundle-open(1)]: +* [`bundle open(1)`](bundle-open.1.html): Open an installed gem in the editor -* [`bundle lock(1)`][bundle-lock]: +* [`bundle lock(1)`](bundle-lock.1.hmtl): Generate a lockfile for your dependencies -* [`bundle viz(1)`][bundle-viz(1)]: +* [`bundle viz(1)`](bundle-viz.1.html): Generate a visual representation of your dependencies -* [`bundle init(1)`][bundle-init(1)]: +* [`bundle init(1)`](bundle-init.1.html): Generate a simple `Gemfile`, placed in the current directory -* [`bundle gem(1)`][bundle-gem(1)]: +* [`bundle gem(1)`](bundle-gem.1.html): Create a simple gem, suitable for development with Bundler -* [`bundle platform(1)`][bundle-platform(1)]: +* [`bundle platform(1)`](bundle-platform.1.html): Display platform compatibility information -* [`bundle clean(1)`][bundle-clean(1)]: +* [`bundle clean(1)`](bundle-clean.1.html): Clean up unused gems in your Bundler directory -* `bundle doctor(1)`: +* [`bundle doctor(1)`](bundle-doctor.1.html): Display warnings about common problems ## PLUGINS diff --git a/man/gemfile.5.ronn b/man/gemfile.5.ronn index 9f6bbce93a..5c7ba23b29 100644 --- a/man/gemfile.5.ronn +++ b/man/gemfile.5.ronn @@ -35,7 +35,7 @@ this warning, by using the [`:source` option](#SOURCE) or a ### CREDENTIALS -Some gem sources require a username and password. Use [bundle config(1)][bundle-config(1)] to set +Some gem sources require a username and password. Use [bundle config(1)](bundle-config.1.html) to set the username and password for any of the sources that need it. The command must be run once on each computer that will install the Gemfile, but this keeps the credentials from being stored in plain text in version control. @@ -228,7 +228,7 @@ As with groups, you can specify one or more platforms: gem "ruby-debug", :platforms => :mri_18 gem "nokogiri", :platforms => [:mri_18, :jruby] -All operations involving groups ([`bundle install`][bundle-install(1)], `Bundler.setup`, +All operations involving groups ([`bundle install`](bundle-install.1.html), `Bundler.setup`, `Bundler.require`) behave exactly the same as if any groups not matching the current platform were explicitly excluded. diff --git a/spec/bundler/plugin/events_spec.rb b/spec/bundler/plugin/events_spec.rb new file mode 100644 index 0000000000..b09e915682 --- /dev/null +++ b/spec/bundler/plugin/events_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +RSpec.describe Bundler::Plugin::Events do + context "plugin events" do + describe "#define" do + it "raises when redefining a constant" do + expect do + Bundler::Plugin::Events.send(:define, :GEM_BEFORE_INSTALL_ALL, "another-value") + end.to raise_error(ArgumentError) + end + + it "can define a new constant" do + Bundler::Plugin::Events.send(:define, :NEW_CONSTANT, "value") + expect(Bundler::Plugin::Events::NEW_CONSTANT).to eq("value") + end + end + end +end diff --git a/spec/bundler/plugin_spec.rb b/spec/bundler/plugin_spec.rb index 68a7e32ad1..eaa0b80905 100644 --- a/spec/bundler/plugin_spec.rb +++ b/spec/bundler/plugin_spec.rb @@ -251,6 +251,16 @@ RSpec.describe Bundler::Plugin do end end + describe "#add_hook" do + it "raises an ArgumentError on an unregistered event" do + ran = false + expect do + Plugin.add_hook("unregistered-hook") { ran = true } + end.to raise_error(ArgumentError) + expect(ran).to be(false) + end + end + describe "#hook" do before do path = lib_path("foo-plugin") @@ -258,7 +268,13 @@ RSpec.describe Bundler::Plugin do s.write "plugins.rb", code end - allow(index).to receive(:hook_plugins).with(event). + Bundler::Plugin::Events.send(:reset) + Bundler::Plugin::Events.send(:define, :EVENT_1, "event-1") + Bundler::Plugin::Events.send(:define, :EVENT_2, "event-2") + + allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT_1). + and_return(["foo-plugin"]) + allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT_2). and_return(["foo-plugin"]) allow(index).to receive(:plugin_path).with("foo-plugin").and_return(path) allow(index).to receive(:load_paths).with("foo-plugin").and_return([]) @@ -268,11 +284,15 @@ RSpec.describe Bundler::Plugin do Bundler::Plugin::API.hook("event-1") { puts "hook for event 1" } RUBY - let(:event) { "event-1" } + it "raises an ArgumentError on an unregistered event" do + expect do + Plugin.hook("unregistered-hook") + end.to raise_error(ArgumentError) + end it "executes the hook" do out = capture(:stdout) do - Plugin.hook("event-1") + Plugin.hook(Bundler::Plugin::Events::EVENT_1) end.strip expect(out).to eq("hook for event 1") @@ -280,17 +300,15 @@ RSpec.describe Bundler::Plugin do context "single plugin declaring more than one hook" do let(:code) { <<-RUBY } - Bundler::Plugin::API.hook("event-1") {} - Bundler::Plugin::API.hook("event-2") {} + Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT_1) {} + Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT_2) {} puts "loaded" RUBY - let(:event) { /event-1|event-2/ } - it "evals plugins.rb once" do out = capture(:stdout) do - Plugin.hook("event-1") - Plugin.hook("event-2") + Plugin.hook(Bundler::Plugin::Events::EVENT_1) + Plugin.hook(Bundler::Plugin::Events::EVENT_2) end.strip expect(out).to eq("loaded") @@ -299,12 +317,12 @@ RSpec.describe Bundler::Plugin do context "a block is passed" do let(:code) { <<-RUBY } - Bundler::Plugin::API.hook("#{event}") { |&blk| blk.call } + Bundler::Plugin::API.hook(Bundler::Plugin::Events::EVENT_1) { |&blk| blk.call } RUBY it "is passed to the hook" do out = capture(:stdout) do - Plugin.hook("event-1") { puts "win" } + Plugin.hook(Bundler::Plugin::Events::EVENT_1) { puts "win" } end.strip expect(out).to eq("win") diff --git a/spec/commands/add_spec.rb b/spec/commands/add_spec.rb index d1f2050aa0..bf3b4e1759 100644 --- a/spec/commands/add_spec.rb +++ b/spec/commands/add_spec.rb @@ -75,11 +75,21 @@ RSpec.describe "bundle add" do describe "with --source" do it "adds dependency with specified source" do bundle "add 'foo' --source='file://#{gem_repo2}'" + expect(bundled_app("Gemfile").read).to match(%r{gem "foo", "~> 2.0", :source => "file:\/\/#{gem_repo2}"}) expect(the_bundle).to include_gems "foo 2.0" end end + describe "with --skip-install" do + it "adds gem to Gemfile but is not installed" do + bundle "add foo --skip-install --version=2.0" + + expect(bundled_app("Gemfile").read).to match(/gem "foo", "= 2.0"/) + expect(the_bundle).to_not include_gems "foo 2.0" + end + end + it "using combination of short form options works like long form" do bundle "add 'foo' -s='file://#{gem_repo2}' -g='development' -v='~>1.0'" expect(bundled_app("Gemfile").read).to include %(gem "foo", "~> 1.0", :group => [:development], :source => "file://#{gem_repo2}") @@ -106,4 +116,36 @@ RSpec.describe "bundle add" do bundle "add 'baz' --source='file://does/not/exist'" expect(out).to include("Could not fetch specs from file://does/not/exist/") end + + describe "with --optimistic" do + it "adds optimistic version" do + bundle! "add 'foo' --optimistic" + expect(bundled_app("Gemfile").read).to include %(gem "foo", ">= 2.0") + expect(the_bundle).to include_gems "foo 2.0" + end + end + + describe "with --strict option" do + it "adds strict version" do + bundle! "add 'foo' --strict" + expect(bundled_app("Gemfile").read).to include %(gem "foo", "= 2.0") + expect(the_bundle).to include_gems "foo 2.0" + end + end + + describe "with no option" do + it "adds pessimistic version" do + bundle! "add 'foo'" + expect(bundled_app("Gemfile").read).to include %(gem "foo", "~> 2.0") + expect(the_bundle).to include_gems "foo 2.0" + end + end + + describe "with --optimistic and --strict" do + it "throws error" do + bundle "add 'foo' --strict --optimistic" + + expect(out).to include("You can not specify `--strict` and `--optimistic` at the same time") + end + end end |