Skip to content

Commit

Permalink
dev-cmd/bottle: use system GNU tar if possible
Browse files Browse the repository at this point in the history
  • Loading branch information
cho-m committed Oct 21, 2024
1 parent 35ebf4a commit 7926eda
Showing 1 changed file with 32 additions and 7 deletions.
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 @@ def reproducible_gnutar_args(mtime)
].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 @@ def gnu_tar_formula_ensure_installed_if_needed!
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"
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 @@ def bottle_formula(formula)
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

0 comments on commit 7926eda

Please sign in to comment.