# frozen_string_literal: true $:.unshift File.expand_path("../lib", __FILE__) require "benchmark" RUBYGEMS_REPO = if `git -C "#{File.expand_path("..")}" remote --verbose 2> #{IO::NULL}` =~ /rubygems/i File.expand_path("..") else File.expand_path("tmp/rubygems") end def development_dependencies @development_dependencies ||= Gem::Specification.load("bundler.gemspec").development_dependencies end # Benchmark task execution module Rake class Task alias_method :real_invoke, :invoke def invoke(*args) time = Benchmark.measure(@name) do real_invoke(*args) end puts "#{@name} ran for #{time}" end end end desc "Run specs" task :spec do sh("bin/rspec") end namespace :spec do def safe_task(&block) yield true rescue StandardError false end desc "Ensure spec dependencies are installed" task :deps do deps = Hash[development_dependencies.map do |d| [d.name, d.requirement.to_s] end] # JRuby can't build ronn, so we skip that deps.delete("ronn") if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" gem_install_command = "install --no-document --conservative " + deps.sort_by {|name, _| name }.map do |name, version| "'#{name}:#{version}'" end.join(" ") sh %(#{Gem.ruby} -S gem #{gem_install_command}) end namespace :travis do task :deps do # Give the travis user a name so that git won't fatally error system "sudo sed -i 's/1000::/1000:Travis:/g' /etc/passwd" # Strip secure_path so that RVM paths transmit through sudo -E system "sudo sed -i '/secure_path/d' /etc/sudoers" # Refresh packages index that the ones we need can be installed sh "sudo apt-get update" # Install groff so ronn can generate man/help pages sh "sudo apt-get install groff-base -y" # Install graphviz so that the viz specs can run sh "sudo apt-get install graphviz -y" # Install the gems with a consistent version of RubyGems sh "gem update --system 3.0.3" # Install the other gem deps, etc Rake::Task["spec:deps"].invoke end end task :clean do rm_rf "tmp" end desc "Run the real-world spec suite" task :realworld => %w[set_realworld spec] namespace :realworld do desc "Re-record cassettes for the realworld specs" task :record => %w[set_record realworld] task :set_record do ENV["BUNDLER_SPEC_FORCE_RECORD"] = "TRUE" end end task :set_realworld do ENV["BUNDLER_REALWORLD_TESTS"] = "1" end desc "Run the spec suite with the sudo tests" task :sudo => %w[set_sudo spec clean_sudo] task :set_sudo do ENV["BUNDLER_SUDO_TESTS"] = "1" end task :clean_sudo do puts "Cleaning up sudo test files..." system "sudo rm -rf #{File.expand_path("../tmp/sudo_gem_home", __FILE__)}" end # RubyGems specs by version namespace :rubygems do # When editing this list, also edit .travis.yml! branches = %w[master] releases = %w[v2.5.2 v2.6.14 v2.7.9 v3.0.3] (branches + releases).each do |rg| desc "Run specs with RubyGems #{rg}" task rg do sh("bin/rspec --format progress") end # Create tasks like spec:rubygems:v1.8.3:sudo to run the sudo specs namespace rg do task :sudo => ["set_sudo", rg, "clean_sudo"] task :realworld => ["set_realworld", rg] end task "set_#{rg}" do ENV["RGV"] = rg end task rg => ["set_#{rg}"] task "rubygems:all" => rg end desc "Run specs under a RubyGems checkout (set RGV=path)" task "co" do sh("bin/rspec --format progress") end namespace "co" do task :sudo => ["set_sudo", "co", "clean_sudo"] task :realworld => ["set_realworld", "co"] end task "setup_co" do ENV["RGV"] = RUBYGEMS_REPO end task "co" => "setup_co" task "rubygems:all" => "co" end desc "Run the tests on Travis CI against a RubyGem version (using ENV['RGV'])" task :travis do rg = ENV["RGV"] || raise("RubyGems version is required on Travis!") rg = "co" if File.directory?(File.expand_path(ENV["RGV"])) # disallow making network requests on CI ENV["BUNDLER_SPEC_PRE_RECORDED"] = "TRUE" puts "\n\e[1;33m[Travis CI] Running bundler specs against RubyGems #{rg}\e[m\n\n" specs = safe_task { Rake::Task["spec:rubygems:#{rg}"].invoke } Rake::Task["spec:rubygems:#{rg}"].reenable puts "\n\e[1;33m[Travis CI] Running bundler sudo specs against RubyGems #{rg}\e[m\n\n" sudos = system("sudo -E rake spec:rubygems:#{rg}:sudo") # clean up by chowning the newly root-owned tmp directory back to the travis user system("sudo chown -R #{ENV["USER"]} #{File.join(File.dirname(__FILE__), "tmp")}") Rake::Task["spec:rubygems:#{rg}"].reenable puts "\n\e[1;33m[Travis CI] Running bundler real world specs against RubyGems #{rg}\e[m\n\n" realworld = safe_task { Rake::Task["spec:rubygems:#{rg}:realworld"].invoke } { "specs" => specs, "sudo" => sudos, "realworld" => realworld }.each do |name, passed| if passed puts "\e[0;32m[Travis CI] #{name} passed\e[m" else puts "\e[0;31m[Travis CI] #{name} failed\e[m" end end unless specs && sudos && realworld raise "Spec run failed, please review the log for more information" end end end desc "Run RuboCop" task :rubocop do sh("bin/rubocop --parallel") end namespace :man do if RUBY_ENGINE == "jruby" task(:build) {} else ronn_dep = development_dependencies.find do |dep| dep.name == "ronn" end ronn_requirement = ronn_dep.requirement.to_s begin gem "ronn", ronn_requirement require "ronn" rescue LoadError task(:build) { abort "We couln't activate ronn (#{ronn_requirement}). Try `gem install ronn:'#{ronn_requirement}'` to be able to build the help pages" } else directory "man" index = [] sources = Dir["man/*.ronn"].map {|f| File.basename(f, ".ronn") } sources.map do |basename| ronn = "man/#{basename}.ronn" manual_section = ".1" unless basename =~ /\.(\d+)\Z/ roff = "man/#{basename}#{manual_section}" index << [ronn, File.basename(roff)] file roff => ["man", ronn] do sh "#{Gem.ruby} -S ronn --roff --pipe #{ronn} > #{roff}" end file "#{roff}.txt" => roff do sh "groff -Wall -mtty-char -mandoc -Tascii #{roff} | col -b > #{roff}.txt" end task :build_all_pages => "#{roff}.txt" end file "index.txt" do index.map! do |(ronn, roff)| [File.read(ronn).split(" ").first, roff] end index = index.sort_by(&:first) justification = index.map {|(n, _f)| n.length }.max + 4 File.open("man/index.txt", "w") do |f| index.each do |name, filename| f << name.ljust(justification) << filename << "\n" end end end task :build_all_pages => "index.txt" task :clean do leftovers = Dir["man/*"].reject do |f| File.extname(f) == ".ronn" end rm leftovers if leftovers.any? end desc "Build the man pages" task :build => ["man:clean", "man:build_all_pages"] desc "Remove all built man pages" task :clobber do rm_rf "lib/bundler/man" end end end end automatiek_dep = development_dependencies.find do |dep| dep.name == "automatiek" end automatiek_requirement = automatiek_dep.requirement.to_s begin gem "automatiek", automatiek_requirement require "automatiek" rescue LoadError namespace :vendor do desc "Vendor a specific version of molinillo" task(:molinillo) { abort "We couldn't activate automatiek (#{automatiek_requirement}). Try `gem install automatiek:'#{automatiek_requirement}'` to be able to vendor gems" } desc "Vendor a specific version of fileutils" task(:fileutils) { abort "We couldn't activate automatiek (#{automatiek_requirement}). Try `gem install automatiek:'#{automatiek_requirement}'` to be able to vendor gems" } desc "Vendor a specific version of thor" task(:thor) { abort "We couldn't activate automatiek (#{automatiek_requirement}). Try `gem install automatiek:'#{automatiek_requirement}'` to be able to vendor gems" } desc "Vendor a specific version of net-http-persistent" task(:"net-http-persistent") { abort "We couldn't activate automatiek (#{automatiek_requirement}). Try `gem install automatiek:'#{automatiek_requirement}'` to be able to vendor gems" } end else desc "Vendor a specific version of molinillo" Automatiek::RakeTask.new("molinillo") do |lib| lib.download = { :github => "https://github.com/CocoaPods/Molinillo" } lib.namespace = "Molinillo" lib.prefix = "Bundler" lib.vendor_lib = "lib/bundler/vendor/molinillo" end desc "Vendor a specific version of thor" Automatiek::RakeTask.new("thor") do |lib| lib.download = { :github => "https://github.com/erikhuda/thor" } lib.namespace = "Thor" lib.prefix = "Bundler" lib.vendor_lib = "lib/bundler/vendor/thor" end desc "Vendor a specific version of fileutils" Automatiek::RakeTask.new("fileutils") do |lib| lib.download = { :github => "https://github.com/ruby/fileutils" } lib.namespace = "FileUtils" lib.prefix = "Bundler" lib.vendor_lib = "lib/bundler/vendor/fileutils" end desc "Vendor a specific version of net-http-persistent" Automatiek::RakeTask.new("net-http-persistent") do |lib| lib.download = { :github => "https://github.com/drbrain/net-http-persistent" } lib.namespace = "Net::HTTP::Persistent" lib.prefix = "Bundler::Persistent" lib.vendor_lib = "lib/bundler/vendor/net-http-persistent" mixin = Module.new do def namespace_files super require_target = vendor_lib.sub(%r{^(.+?/)?lib/}, "") << "/lib" relative_files = files.map {|f| Pathname.new(f).relative_path_from(Pathname.new(vendor_lib) / "lib").sub_ext("").to_s } process_files(/require (['"])(#{Regexp.union(relative_files)})/, "require \\1#{require_target}/\\2") end end lib.send(:extend, mixin) end end task :override_version do next unless version = ENV["BUNDLER_SPEC_SUB_VERSION"] version_file = File.expand_path("../lib/bundler/version.rb", __FILE__) contents = File.read(version_file) unless contents.sub!(/(^\s+VERSION\s*=\s*)"#{Gem::Version::VERSION_PATTERN}"/, %(\\1"#{version}")) abort("Failed to change bundler version") end File.open(version_file, "w") {|f| f << contents } end task :default => :spec Dir["task/*.rake"].each(&method(:load)) task :generate_files => Rake::Task.tasks.select {|t| t.name.start_with?("lib/bundler/generated") }