require_relative 'filesystem' require_relative 'command_runner' require_relative 'version' module Tests class Bundle def initialize @already_updating = false @fs = Filesystem.new end def updating if already_updating? yield self return end @already_updating = true yield self @already_updating = false install_gems end def add_gem(gem, *args) updating do options = args.last.is_a?(Hash) ? args.pop : {} version = args.shift line = assemble_gem_line(gem, version, options) fs.append_to_file('Gemfile', line) end end def remove_gem(gem) updating do fs.comment_lines_matching('Gemfile', /^ *gem ("|')#{gem}\1/) end end def install_gems CommandRunner.run!('bundle install --local') do |runner| runner.retries = 5 end end def version_of(gem) Version.new(Bundler.definition.specs[gem][0].version) end def includes?(gem) Bundler.definition.dependencies.any? do |dependency| dependency.name == gem end end def version Bundler::VERSION end protected attr_reader :fs private def already_updating? @already_updating end def assemble_gem_line(gem, version, options) formatted_options = options. map { |key, value| "#{key}: #{formatted_value(value)}" }. join(', ') line = %(gem '#{gem}') if version line << %(, '#{version}') end if options.any? line << %(, #{formatted_options}) end line << "\n" end def formatted_value(value) if value.is_a?(Pathname) value.to_s.inspect else value.inspect end end end end