Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mktemp: strict type and allow #run without chdir #18560

Merged
merged 2 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions Library/Homebrew/formula.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2804,7 +2804,7 @@

mktemp("#{name}-test") do |staging|
staging.retain! if keep_tmp
@testpath = staging.tmpdir
@testpath = T.must(staging.tmpdir)

Check warning on line 2807 in Library/Homebrew/formula.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/formula.rb#L2807

Added line #L2807 was not covered by tests
test_env[:HOME] = @testpath
setup_home @testpath
begin
Expand Down Expand Up @@ -3125,8 +3125,16 @@
# 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 = {}, &block)
Mktemp.new(prefix, opts).run(&block)
sig {
params(

Check warning on line 3129 in Library/Homebrew/formula.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/formula.rb#L3129

Added line #L3129 was not covered by tests
prefix: String,
retain: T::Boolean,
retain_in_cache: T::Boolean,
block: T.proc.params(arg0: Mktemp).void,
).void
}
def mktemp(prefix = name, retain: false, retain_in_cache: false, &block)
Mktemp.new(prefix, retain:, retain_in_cache:).run(&block)

Check warning on line 3137 in Library/Homebrew/formula.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/formula.rb#L3137

Added line #L3137 was not covered by tests
end

# A version of `FileUtils.mkdir` that also changes to that folder in
Expand Down
39 changes: 29 additions & 10 deletions Library/Homebrew/mktemp.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
# typed: true # rubocop:todo Sorbet/StrictSigil
# typed: strict
# frozen_string_literal: true

# Performs {Formula#mktemp}'s functionality and tracks the results.
# Each instance is only intended to be used once.
# Can also be used to create a temporary directory with the brew instance's group.
class Mktemp
include FileUtils

# Path to the tmpdir used in this run, as a {Pathname}.
# Path to the tmpdir used in this run
sig { returns(T.nilable(Pathname)) }
attr_reader :tmpdir

def initialize(prefix, opts = {})
sig { params(prefix: String, retain: T::Boolean, retain_in_cache: T::Boolean).void }
def initialize(prefix, retain: false, retain_in_cache: false)
@prefix = prefix
@retain_in_cache = opts[:retain_in_cache]
@retain = opts[:retain] || @retain_in_cache
@quiet = false
@retain_in_cache = T.let(retain_in_cache, T::Boolean)
@retain = T.let(retain || @retain_in_cache, T::Boolean)
@quiet = T.let(false, T::Boolean)
@tmpdir = T.let(nil, T.nilable(Pathname))
end

# Instructs this {Mktemp} to retain the staged files.
Expand All @@ -23,11 +27,13 @@
end

# True if the staged temporary files should be retained.
sig { returns(T::Boolean) }
def retain?
@retain
end

# True if the source files should be retained.
sig { returns(T::Boolean) }
def retain_in_cache?
@retain_in_cache
end
Expand All @@ -43,7 +49,8 @@
"[Mktemp: #{tmpdir} retain=#{@retain} quiet=#{@quiet}]"
end

def run
sig { params(chdir: T::Boolean, _block: T.proc.params(arg0: Mktemp).void).void }
def run(chdir: true, &_block)
prefix_name = @prefix.tr "@", "AT"
@tmpdir = if retain_in_cache?
tmp_dir = HOMEBREW_CACHE/"Sources/#{prefix_name}"
Expand All @@ -66,13 +73,24 @@
Process.gid
end
begin
chown(nil, group_id, @tmpdir)
@tmpdir.chown(nil, group_id)
rescue Errno::EPERM
opoo "Failed setting group \"#{T.must(Etc.getgrgid(group_id)).name}\" on #{@tmpdir}"
require "etc"

Check warning on line 78 in Library/Homebrew/mktemp.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/mktemp.rb#L78

Added line #L78 was not covered by tests
group_name = begin
Etc.getgrgid(group_id)&.name
rescue ArgumentError
# Cover for misconfigured NSS setups
nil

Check warning on line 83 in Library/Homebrew/mktemp.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/mktemp.rb#L83

Added line #L83 was not covered by tests
end
opoo "Failed setting group \"#{group_name || group_id}\" on #{@tmpdir}"

Check warning on line 85 in Library/Homebrew/mktemp.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/mktemp.rb#L85

Added line #L85 was not covered by tests
end

begin
Dir.chdir(tmpdir) { yield self }
if chdir
Dir.chdir(@tmpdir) { yield self }
else
yield self
end
ensure
ignore_interrupts { chmod_rm_rf(@tmpdir) } unless retain?
end
Expand All @@ -85,6 +103,7 @@

private

sig { params(path: Pathname).void }
def chmod_rm_rf(path)
if path.directory? && !path.symlink?
chmod("u+rw", path) if path.owned? # Need permissions in order to see the contents
Expand Down
26 changes: 3 additions & 23 deletions Library/Homebrew/unpack_strategy.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# typed: strict
# frozen_string_literal: true

require "mktemp"
require "system_command"

# Module containing all available strategies for unpacking archives.
Expand Down Expand Up @@ -157,29 +158,8 @@ def extract(to: nil, basename: nil, verbose: false)
).returns(T.untyped)
}
def extract_nestedly(to: nil, basename: nil, verbose: false, prioritize_extension: false)
Dir.mktmpdir("homebrew-unpack", HOMEBREW_TEMP) do |tmp_unpack_dir|
tmp_unpack_dir = Pathname(tmp_unpack_dir)

# Make sure files inside the temporary directory have the same group as the brew instance.
#
# @see https://github.com/Homebrew/brew/blob/4.4.0/Library/Homebrew/mktemp.rb#L57-L72
group_id = if HOMEBREW_BREW_FILE.grpowned?
HOMEBREW_BREW_FILE.stat.gid
else
Process.gid
end
begin
tmp_unpack_dir.chown(nil, group_id)
rescue Errno::EPERM
require "etc"
group_name = begin
Etc.getgrgid(group_id)&.name
rescue ArgumentError
# Cover for misconfigured NSS setups
nil
end
opoo "Failed setting group \"#{group_name || group_id}\" on #{tmp_unpack_dir}"
end
Mktemp.new("homebrew-unpack").run(chdir: false) do |unpack_dir|
tmp_unpack_dir = T.must(unpack_dir.tmpdir)

extract(to: tmp_unpack_dir, basename:, verbose:)

Expand Down
Loading