1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/spec/bundler/support/helpers.rb

505 lines
13 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
module Spec
module Helpers
def reset!
Dir.glob("#{tmp}/{gems/*,*}", File::FNM_DOTMATCH).each do |dir|
next if %w(base remote1 gems rubygems . ..).include?(File.basename(dir))
if ENV["BUNDLER_SUDO_TESTS"]
`sudo rm -rf "#{dir}"`
else
FileUtils.rm_rf(dir)
end
end
FileUtils.mkdir_p(home)
FileUtils.mkdir_p(tmpdir)
Bundler.reset!
Bundler.ui = nil
Bundler.ui # force it to initialize
end
def self.bang(method)
define_method("#{method}!") do |*args, &blk|
send(method, *args, &blk).tap do
if exitstatus && exitstatus != 0
error = out + "\n" + err
error.strip!
raise RuntimeError,
"Invoking #{method}!(#{args.map(&:inspect).join(", ")}) failed:\n#{error}",
caller.drop_while {|bt| bt.start_with?(__FILE__) }
end
end
end
end
attr_reader :out, :err, :exitstatus
def the_bundle(*args)
TheBundle.new(*args)
end
def in_app_root(&blk)
Dir.chdir(bundled_app, &blk)
end
def in_app_root2(&blk)
Dir.chdir(bundled_app2, &blk)
end
def in_app_root_custom(root, &blk)
Dir.chdir(root, &blk)
end
def run(cmd, *args)
opts = args.last.is_a?(Hash) ? args.pop : {}
groups = args.map(&:inspect).join(", ")
setup = "require 'rubygems' ; require 'bundler' ; Bundler.setup(#{groups})\n"
@out = ruby(setup + cmd, opts)
end
bang :run
def load_error_run(ruby, name, *args)
cmd = <<-RUBY
begin
#{ruby}
rescue LoadError => e
$stderr.puts "ZOMG LOAD ERROR" if e.message.include?("-- #{name}")
end
RUBY
opts = args.last.is_a?(Hash) ? args.pop : {}
args += [opts]
run(cmd, *args)
end
def lib
root.join("lib")
end
def spec
spec_dir.to_s
end
def bundle(cmd, options = {})
with_sudo = options.delete(:sudo)
sudo = with_sudo == :preserve_env ? "sudo -E" : "sudo" if with_sudo
options["no-color"] = true unless options.key?("no-color") || cmd.to_s =~ /\A(e|ex|exe|exec|conf|confi|config)(\s|\z)/
bundle_bin = options.delete("bundle_bin") || bindir.join("bundle")
if system_bundler = options.delete(:system_bundler)
bundle_bin = "-S bundle"
end
requires = options.delete(:requires) || []
if artifice = options.delete(:artifice) { "fail" unless RSpec.current_example.metadata[:realworld] }
requires << File.expand_path("../artifice/#{artifice}.rb", __FILE__)
end
requires << "support/hax"
requires_str = requires.map {|r| "-r#{r}" }.join(" ")
load_path = []
load_path << lib unless system_bundler
load_path << spec
load_path_str = "-I#{load_path.join(File::PATH_SEPARATOR)}"
env = (options.delete(:env) || {}).map {|k, v| "#{k}='#{v}'" }.join(" ")
env["PATH"].gsub!(Path.bindir, "") if env["PATH"] && system_bundler
args = options.map do |k, v|
v == true ? " --#{k}" : " --#{k} #{v}" if v
end.join
cmd = "#{env} #{sudo} #{Gem.ruby} #{load_path_str} #{requires_str} #{bundle_bin} #{cmd}#{args}"
sys_exec(cmd) {|i, o, thr| yield i, o, thr if block_given? }
end
bang :bundle
def bundler(cmd, options = {})
options["bundle_bin"] = bindir.join("bundler")
bundle(cmd, options)
end
def bundle_ruby(options = {})
options["bundle_bin"] = bindir.join("bundle_ruby")
bundle("", options)
end
def ruby(ruby, options = {})
env = (options.delete(:env) || {}).map {|k, v| "#{k}='#{v}' " }.join
ruby = ruby.gsub(/["`\$]/) {|m| "\\#{m}" }
lib_option = options[:no_lib] ? "" : " -I#{lib}"
sys_exec(%(#{env}#{Gem.ruby}#{lib_option} -e "#{ruby}"))
end
bang :ruby
def load_error_ruby(ruby, name, opts = {})
ruby(<<-R)
begin
#{ruby}
rescue LoadError => e
$stderr.puts "ZOMG LOAD ERROR"# if e.message.include?("-- #{name}")
end
R
end
def gembin(cmd)
lib = File.expand_path("../../../lib", __FILE__)
old = ENV["RUBYOPT"]
ENV["RUBYOPT"] = "#{ENV["RUBYOPT"]} -I#{lib}"
cmd = bundled_app("bin/#{cmd}") unless cmd.to_s.include?("/")
sys_exec(cmd.to_s)
ensure
ENV["RUBYOPT"] = old
end
def gem_command(command, args = "", options = {})
if command == :exec && !options[:no_quote]
args = args.gsub(/(?=")/, "\\")
args = %("#{args}")
end
gem = ENV['BUNDLE_GEM'] || "#{Gem.ruby} -rubygems -S gem --backtrace"
sys_exec("#{gem} #{command} #{args}")
end
bang :gem_command
def rake
if ENV['BUNDLE_RUBY'] && ENV['BUNDLE_GEM']
"#{ENV['BUNDLE_RUBY']} #{ENV['GEM_PATH']}/bin/rake"
else
'rake'
end
end
def sys_exec(cmd)
Open3.popen3(cmd.to_s) do |stdin, stdout, stderr, wait_thr|
yield stdin, stdout, wait_thr if block_given?
stdin.close
@exitstatus = wait_thr && wait_thr.value.exitstatus
@out = Thread.new { stdout.read }.value.strip
@err = Thread.new { stderr.read }.value.strip
end
(@all_output ||= String.new) << [
"$ #{cmd.to_s.strip}",
out,
err,
@exitstatus ? "# $? => #{@exitstatus}" : "",
"\n",
].reject(&:empty?).join("\n")
@out
end
bang :sys_exec
def config(config = nil, path = bundled_app(".bundle/config"))
return YAML.load_file(path) unless config
FileUtils.mkdir_p(File.dirname(path))
File.open(path, "w") do |f|
f.puts config.to_yaml
end
config
end
def global_config(config = nil)
config(config, home(".bundle/config"))
end
def create_file(*args)
path = bundled_app(args.shift)
path = args.shift if args.first.is_a?(Pathname)
str = args.shift || ""
path.dirname.mkpath
File.open(path.to_s, "w") do |f|
f.puts strip_whitespace(str)
end
end
def gemfile(*args)
if args.empty?
File.open("Gemfile", "r", &:read)
else
create_file("Gemfile", *args)
end
end
def lockfile(*args)
if args.empty?
File.open("Gemfile.lock", "r", &:read)
else
create_file("Gemfile.lock", *args)
end
end
def strip_whitespace(str)
# Trim the leading spaces
spaces = str[/\A\s+/, 0] || ""
str.gsub(/^#{spaces}/, "")
end
def install_gemfile(*args)
gemfile(*args)
opts = args.last.is_a?(Hash) ? args.last : {}
opts[:retry] ||= 0
bundle :install, opts
end
bang :install_gemfile
def lock_gemfile(*args)
gemfile(*args)
opts = args.last.is_a?(Hash) ? args.last : {}
opts[:retry] ||= 0
bundle :lock, opts
end
def install_gems(*gems)
options = gems.last.is_a?(Hash) ? gems.pop : {}
gem_repo = options.fetch(:gem_repo) { gem_repo1 }
gems.each do |g|
path = if g == :bundler
Dir.chdir(root) { gem_command! :build, gemspec.to_s }
bundler_path = root + "bundler-#{Bundler::VERSION}.gem"
elsif g.to_s =~ %r{\A/.*\.gem\z}
g
else
"#{gem_repo}/gems/#{g}.gem"
end
raise "OMG `#{path}` does not exist!" unless File.exist?(path)
gem_command! :install, "--no-rdoc --no-ri --ignore-dependencies '#{path}'"
bundler_path && bundler_path.rmtree
end
end
alias_method :install_gem, :install_gems
def with_gem_path_as(path)
backup = ENV.to_hash
ENV["GEM_HOME"] = path.to_s
ENV["GEM_PATH"] = path.to_s
ENV["BUNDLER_ORIG_GEM_PATH"] = nil
yield
ensure
ENV.replace(backup)
end
def with_path_as(path)
backup = ENV.to_hash
ENV["PATH"] = path.to_s
ENV["BUNDLER_ORIG_PATH"] = nil
yield
ensure
ENV.replace(backup)
end
def with_path_added(path)
with_path_as(path.to_s + ":" + ENV["PATH"]) do
yield
end
end
def break_git!
FileUtils.mkdir_p(tmp("broken_path"))
File.open(tmp("broken_path/git"), "w", 0o755) do |f|
f.puts "#!/usr/bin/env ruby\nSTDERR.puts 'This is not the git you are looking for'\nexit 1"
end
ENV["PATH"] = "#{tmp("broken_path")}:#{ENV["PATH"]}"
end
def with_fake_man
FileUtils.mkdir_p(tmp("fake_man"))
File.open(tmp("fake_man/man"), "w", 0o755) do |f|
f.puts "#!/usr/bin/env ruby\nputs ARGV.inspect\n"
end
with_path_added(tmp("fake_man")) { yield }
end
def system_gems(*gems)
gems = gems.flatten
FileUtils.rm_rf(system_gem_path)
FileUtils.mkdir_p(system_gem_path)
Gem.clear_paths
env_backup = ENV.to_hash
ENV["GEM_HOME"] = system_gem_path.to_s
ENV["GEM_PATH"] = system_gem_path.to_s
ENV["BUNDLER_ORIG_GEM_PATH"] = nil
install_gems(*gems)
return unless block_given?
begin
yield
ensure
ENV.replace(env_backup)
end
end
def realworld_system_gems(*gems)
gems = gems.flatten
FileUtils.rm_rf(system_gem_path)
FileUtils.mkdir_p(system_gem_path)
Gem.clear_paths
gem_home = ENV["GEM_HOME"]
gem_path = ENV["GEM_PATH"]
path = ENV["PATH"]
ENV["GEM_HOME"] = system_gem_path.to_s
ENV["GEM_PATH"] = system_gem_path.to_s
gems.each do |gem|
gem_command :install, "--no-rdoc --no-ri #{gem}"
end
return unless block_given?
begin
yield
ensure
ENV["GEM_HOME"] = gem_home
ENV["GEM_PATH"] = gem_path
ENV["PATH"] = path
end
end
def cache_gems(*gems)
gems = gems.flatten
FileUtils.rm_rf("#{bundled_app}/vendor/cache")
FileUtils.mkdir_p("#{bundled_app}/vendor/cache")
gems.each do |g|
path = "#{gem_repo1}/gems/#{g}.gem"
raise "OMG `#{path}` does not exist!" unless File.exist?(path)
FileUtils.cp(path, "#{bundled_app}/vendor/cache")
end
end
def simulate_new_machine
system_gems []
FileUtils.rm_rf default_bundle_path
FileUtils.rm_rf bundled_app(".bundle")
end
def simulate_platform(platform)
old = ENV["BUNDLER_SPEC_PLATFORM"]
ENV["BUNDLER_SPEC_PLATFORM"] = platform.to_s
yield if block_given?
ensure
ENV["BUNDLER_SPEC_PLATFORM"] = old if block_given?
end
def simulate_ruby_version(version)
return if version == RUBY_VERSION
old = ENV["BUNDLER_SPEC_RUBY_VERSION"]
ENV["BUNDLER_SPEC_RUBY_VERSION"] = version
yield if block_given?
ensure
ENV["BUNDLER_SPEC_RUBY_VERSION"] = old if block_given?
end
def simulate_ruby_engine(engine, version = "1.6.0")
return if engine == local_ruby_engine
old = ENV["BUNDLER_SPEC_RUBY_ENGINE"]
ENV["BUNDLER_SPEC_RUBY_ENGINE"] = engine
old_version = ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"]
ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] = version
yield if block_given?
ensure
ENV["BUNDLER_SPEC_RUBY_ENGINE"] = old if block_given?
ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] = old_version if block_given?
end
def simulate_bundler_version(version)
old = ENV["BUNDLER_SPEC_VERSION"]
ENV["BUNDLER_SPEC_VERSION"] = version.to_s
yield if block_given?
ensure
ENV["BUNDLER_SPEC_VERSION"] = old if block_given?
end
def simulate_windows
old = ENV["BUNDLER_SPEC_WINDOWS"]
ENV["BUNDLER_SPEC_WINDOWS"] = "true"
simulate_platform mswin do
yield
end
ensure
ENV["BUNDLER_SPEC_WINDOWS"] = old
end
def revision_for(path)
Dir.chdir(path) { `git rev-parse HEAD`.strip }
end
def capture_output
capture(:stdout)
end
def with_read_only(pattern)
chmod = lambda do |dirmode, filemode|
lambda do |f|
mode = File.directory?(f) ? dirmode : filemode
File.chmod(mode, f)
end
end
Dir[pattern].each(&chmod[0o555, 0o444])
yield
ensure
Dir[pattern].each(&chmod[0o755, 0o644])
end
def process_file(pathname)
changed_lines = pathname.readlines.map do |line|
yield line
end
File.open(pathname, "w") {|file| file.puts(changed_lines.join) }
end
def with_env_vars(env_hash, &block)
current_values = {}
env_hash.each do |k, v|
current_values[k] = ENV[k]
ENV[k] = v
end
block.call if block_given?
env_hash.each do |k, _|
ENV[k] = current_values[k]
end
end
def require_rack
# need to hack, so we can require rack
old_gem_home = ENV["GEM_HOME"]
ENV["GEM_HOME"] = Spec::Path.base_system_gems.to_s
require "rack"
ENV["GEM_HOME"] = old_gem_home
end
def wait_for_server(host, port, seconds = 15)
tries = 0
sleep 0.5
TCPSocket.new(host, port)
rescue => e
raise(e) if tries > (seconds * 2)
tries += 1
retry
end
def find_unused_port
port = 21_453
begin
port += 1 while TCPSocket.new("127.0.0.1", port)
rescue
false
end
port
end
end
end