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

dev-cmd/bottle: use system GNU tar if possible #18604

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
39 changes: 32 additions & 7 deletions Library/Homebrew/dev-cmd/bottle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
require "api"
require "extend/hash/deep_merge"
require "metafiles"
require "system_command"

module Homebrew
module DevCmd
class Bottle < AbstractCommand
include FileUtils
include SystemCommand::Mixin

BOTTLE_ERB = T.let(<<-EOS.freeze, String)
bottle do
Expand Down Expand Up @@ -345,8 +347,25 @@
].freeze
end

sig { returns(T::Boolean) }
def system_gnu_tar?
return @system_gnu_tar unless @system_gnu_tar.nil?

@system_gnu_tar = T.let(false, T.nilable(T::Boolean))
stdout, _, status = system_command("tar", args: ["--version"], print_stderr: false)
return false unless status.success?

tar_version = stdout[/\(GNU tar\) (\d+(?:\.\d+)*)$/, 1]
return false unless tar_version

# `--sort=name` was added in GNU tar 1.28
@system_gnu_tar = Version.new(tar_version) >= Version.new("1.28")
end

sig { returns(T.nilable(Formula)) }
def gnu_tar_formula_ensure_installed_if_needed!
return if system_gnu_tar?

gnu_tar_formula = begin
Formula["gnu-tar"]
rescue FormulaUnavailableError
Expand All @@ -359,18 +378,24 @@
gnu_tar_formula
end

sig { params(mtime: String, default_tar: T::Boolean).returns([String, T::Array[String]]) }
def setup_tar_and_args!(mtime, default_tar: false)
sig { params(mtime: String).returns([String, T::Array[String]]) }
def setup_tar_and_args!(mtime)
# Without --only-json-tab bottles are never reproducible
default_tar_args = ["tar", tar_args].freeze
return default_tar_args if !args.only_json_tab? || default_tar
return default_tar_args unless args.only_json_tab?

# Use gnu-tar as it can be set up for reproducibility better than libarchive
# and to be consistent between macOS and Linux.
gnu_tar_formula = gnu_tar_formula_ensure_installed_if_needed!
return default_tar_args if gnu_tar_formula.blank?
tar = if system_gnu_tar?

Check warning on line 389 in Library/Homebrew/dev-cmd/bottle.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/bottle.rb#L389

Added line #L389 was not covered by tests
"tar"
Comment on lines +389 to +390
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplest way to update this PR is probably following with additional input parameter for formula:

Suggested change
tar = if system_gnu_tar?
"tar"
tar = if formula.name == "gnu-tar" && system_gnu_tar?
"tar"

Though this won't handle case if a user runs brew bottle gnu-tar on an old LTS Linux. Seems like a very unlikely situation.


A more complete option would be to add OS-specific logic to only check this on Linux-only as macOS doesn't have the same problem in relation to rewritten ld.so.


Either way, if we do want to consider pure Ruby alternative, then these changes would be a stopgap measure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems fine to me 👍🏻

else
gnu_tar_formula = gnu_tar_formula_ensure_installed_if_needed!
return default_tar_args if gnu_tar_formula.blank?

gnu_tar(gnu_tar_formula)

Check warning on line 395 in Library/Homebrew/dev-cmd/bottle.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/bottle.rb#L395

Added line #L395 was not covered by tests
end

[gnu_tar(gnu_tar_formula), reproducible_gnutar_args(mtime)].freeze
[tar, reproducible_gnutar_args(mtime)].freeze

Check warning on line 398 in Library/Homebrew/dev-cmd/bottle.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/bottle.rb#L398

Added line #L398 was not covered by tests
end

sig { params(formula: T.untyped).returns(T::Array[T.untyped]) }
Expand Down Expand Up @@ -540,7 +565,7 @@
sudo_purge
# Tar then gzip for reproducible bottles.
tar_mtime = tab.source_modified_time.strftime("%Y-%m-%d %H:%M:%S")
tar, tar_args = setup_tar_and_args!(tar_mtime, default_tar: formula.name == "gnu-tar")
tar, tar_args = setup_tar_and_args!(tar_mtime)
safe_system tar, "--create", "--numeric-owner",
*tar_args,
"--file", tar_path, "#{formula.name}/#{formula.pkg_version}"
Expand Down
Loading