diff --git a/Library/Homebrew/compat/fileutils.rb b/Library/Homebrew/compat/fileutils.rb new file mode 100644 index 0000000000..ed7d106f99 --- /dev/null +++ b/Library/Homebrew/compat/fileutils.rb @@ -0,0 +1,15 @@ +require "fileutils" + +module FileUtils + module Compat + def mktemp(prefix = name, opts = {}) + # odeprecated("FileUtils.mktemp", "mktemp") + Mktemp.new(prefix, opts).run do |staging| + yield staging + end + end + module_function :mktemp + end + + prepend Compat +end diff --git a/Library/Homebrew/extend/fileutils.rb b/Library/Homebrew/extend/fileutils.rb index eebe54e373..da65fe4f62 100644 --- a/Library/Homebrew/extend/fileutils.rb +++ b/Library/Homebrew/extend/fileutils.rb @@ -4,84 +4,6 @@ require "etc" # Homebrew extends Ruby's `FileUtils` to make our code more readable. # @see https://ruby-doc.org/stdlib-2.0.0/libdoc/fileutils/rdoc/FileUtils.html Ruby's FileUtils API module FileUtils - # Create a temporary directory then yield. When the block returns, - # recursively delete the temporary directory. Passing opts[:retain] - # or calling `do |staging| ... staging.retain!` in the block will skip - # the deletion and retain the temporary directory's contents. - def mktemp(prefix = name, opts = {}) - Mktemp.new(prefix, opts).run do |staging| - yield staging - end - end - - module_function :mktemp - - # Performs mktemp's functionality, and tracks the results. - # Each instance is only intended to be used once. - class Mktemp - include FileUtils - - # Path to the tmpdir used in this run, as a Pathname. - attr_reader :tmpdir - - def initialize(prefix = name, opts = {}) - @prefix = prefix - @retain = opts[:retain] - @quiet = false - end - - # Instructs this Mktemp to retain the staged files - def retain! - @retain = true - end - - # True if the staged temporary files should be retained - def retain? - @retain - end - - # Instructs this Mktemp to not emit messages when retention is triggered - def quiet! - @quiet = true - end - - def to_s - "[Mktemp: #{tmpdir} retain=#{@retain} quiet=#{@quiet}]" - end - - def run - @tmpdir = Pathname.new(Dir.mktmpdir("#{@prefix}-", HOMEBREW_TEMP)) - - # Make sure files inside the temporary directory have the same group as the - # brew instance. - # - # Reference from `man 2 open` - # > When a new file is created, it is given the group of the directory which - # contains it. - group_id = if HOMEBREW_BREW_FILE.grpowned? - HOMEBREW_BREW_FILE.stat.gid - else - Process.gid - end - begin - chown(nil, group_id, tmpdir) - rescue Errno::EPERM - opoo "Failed setting group \"#{Etc.getgrgid(group_id).name}\" on #{tmpdir}" - end - - begin - Dir.chdir(tmpdir) { yield self } - ensure - ignore_interrupts { rm_rf(tmpdir) } unless retain? - end - ensure - if retain? && !@tmpdir.nil? && !@quiet - ohai "Kept temporary files" - puts "Temporary files retained at #{@tmpdir}" - end - end - end - # @private alias old_mkdir mkdir diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index ea7340de96..f9fd1bf405 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -17,6 +17,7 @@ require "linkage_checker" require "extend/ENV" require "language/python" require "tab" +require "mktemp" # A formula provides instructions and metadata for Homebrew to install a piece # of software. Every Homebrew formula is a {Formula}. @@ -1688,7 +1689,7 @@ class Formula ENV.clear_sensitive_environment! - mktemp("#{name}-test") do |staging| + Formula.mktemp("#{name}-test") do |staging| staging.retain! if ARGV.keep_tmp? @testpath = staging.tmpdir test_env[:HOME] = @testpath @@ -2464,6 +2465,16 @@ class Formula @pour_bottle_check.instance_eval(&block) end + # Create a temporary directory then yield. When the block returns, + # recursively delete the temporary directory. Passing opts[:retain] + # or calling `do |staging| ... staging.retain!` in the block will skip + # the deletion and retain the temporary directory's contents. + def mktemp(prefix = name, opts = {}) + Mktemp.new(prefix, opts).run do |staging| + yield staging + end + end + # @private def link_overwrite(*paths) paths.flatten! diff --git a/Library/Homebrew/mktemp.rb b/Library/Homebrew/mktemp.rb new file mode 100644 index 0000000000..c84b0594c6 --- /dev/null +++ b/Library/Homebrew/mktemp.rb @@ -0,0 +1,65 @@ +# Performs `Formula.mktemp`'s functionality, and tracks the results. +# Each instance is only intended to be used once. +class Mktemp + include FileUtils + + # Path to the tmpdir used in this run, as a Pathname. + attr_reader :tmpdir + + def initialize(prefix = name, opts = {}) + @prefix = prefix + @retain = opts[:retain] + @quiet = false + end + + # Instructs this Mktemp to retain the staged files + def retain! + @retain = true + end + + # True if the staged temporary files should be retained + def retain? + @retain + end + + # Instructs this Mktemp to not emit messages when retention is triggered + def quiet! + @quiet = true + end + + def to_s + "[Mktemp: #{tmpdir} retain=#{@retain} quiet=#{@quiet}]" + end + + def run + @tmpdir = Pathname.new(Dir.mktmpdir("#{@prefix}-", HOMEBREW_TEMP)) + + # Make sure files inside the temporary directory have the same group as the + # brew instance. + # + # Reference from `man 2 open` + # > When a new file is created, it is given the group of the directory which + # contains it. + group_id = if HOMEBREW_BREW_FILE.grpowned? + HOMEBREW_BREW_FILE.stat.gid + else + Process.gid + end + begin + chown(nil, group_id, tmpdir) + rescue Errno::EPERM + opoo "Failed setting group \"#{Etc.getgrgid(group_id).name}\" on #{tmpdir}" + end + + begin + Dir.chdir(tmpdir) { yield self } + ensure + ignore_interrupts { rm_rf(tmpdir) } unless retain? + end + ensure + if retain? && !@tmpdir.nil? && !@quiet + ohai "Kept temporary files" + puts "Temporary files retained at #{@tmpdir}" + end + end +end diff --git a/Library/Homebrew/resource.rb b/Library/Homebrew/resource.rb index fba9328751..26945b4626 100644 --- a/Library/Homebrew/resource.rb +++ b/Library/Homebrew/resource.rb @@ -1,6 +1,7 @@ require "download_strategy" require "checksum" require "version" +require "mktemp" # Resource is the fundamental representation of an external resource. The # primary formula download, along with other declared resources, are instances @@ -195,6 +196,12 @@ class Resource end end + def mktemp(prefix) + Mktemp.new(prefix).run do |staging| + yield staging + end + end + class Go < Resource def stage(target) super(target/name) diff --git a/Library/Homebrew/test/download_strategies_spec.rb b/Library/Homebrew/test/download_strategies_spec.rb index 6f410358ed..66518015fa 100644 --- a/Library/Homebrew/test/download_strategies_spec.rb +++ b/Library/Homebrew/test/download_strategies_spec.rb @@ -10,7 +10,7 @@ describe AbstractDownloadStrategy do let(:args) { %w[foo bar baz] } specify "#source_modified_time" do - FileUtils.mktemp "mtime" do + Mktemp.new("mtime") do FileUtils.touch "foo", mtime: Time.now - 10 FileUtils.touch "bar", mtime: Time.now - 100 FileUtils.ln_s "not-exist", "baz"