dev-cmd/bottle: use gnu-tar's --mtime.

This allows us to remove all the manual timestamp fiddling and lets
`gnu-tar` handle it for us instead (as-per the most recent
recommendations on https://reproducible-builds.org/docs/archives/).
This commit is contained in:
Mike McQuaid 2022-12-12 16:47:56 +00:00
parent 11cdffb4fe
commit 4a0e16fbd9
No known key found for this signature in database
GPG Key ID: 3338A31AFDB1D829
3 changed files with 21 additions and 17 deletions

View File

@ -234,7 +234,7 @@ module Homebrew
system "/usr/bin/sudo", "--non-interactive", "/usr/sbin/purge" system "/usr/bin/sudo", "--non-interactive", "/usr/sbin/purge"
end end
def setup_tar_and_args!(args) def setup_tar_and_args!(args, mtime)
# Without --only-json-tab bottles are never reproducible # Without --only-json-tab bottles are never reproducible
default_tar_args = ["tar", [].freeze].freeze default_tar_args = ["tar", [].freeze].freeze
return default_tar_args unless args.only_json_tab? return default_tar_args unless args.only_json_tab?
@ -242,7 +242,7 @@ module Homebrew
# Ensure tar is set up for reproducibility. # Ensure tar is set up for reproducibility.
# https://reproducible-builds.org/docs/archives/ # https://reproducible-builds.org/docs/archives/
gnutar_args = [ gnutar_args = [
"--format", "pax", "--owner", "0", "--group", "0", "--sort", "name", "--format", "pax", "--owner", "0", "--group", "0", "--sort", "name", "--mtime=#{mtime}",
# Set exthdr names to exclude PID (for GNU tar <1.33). Also don't store atime and ctime. # Set exthdr names to exclude PID (for GNU tar <1.33). Also don't store atime and ctime.
"--pax-option", "globexthdr.name=/GlobalHead.%n,exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime" "--pax-option", "globexthdr.name=/GlobalHead.%n,exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime"
].freeze ].freeze
@ -409,28 +409,18 @@ module Homebrew
tab.write tab.write
end end
keg.find do |file| keg.consistent_reproducible_symlink_permissions!
# Set the times for reproducible bottles.
if file.symlink?
# Need to make symlink permissions consistent on macOS and Linux
# TODO: Refactor and move to extend/os
File.lchmod 0777, file if OS.mac? # rubocop:disable Homebrew/MoveToExtendOS
File.lutime(tab.source_modified_time, tab.source_modified_time, file)
else
file.utime(tab.source_modified_time, tab.source_modified_time)
end
end
cd cellar do cd cellar do
sudo_purge sudo_purge
# Tar then gzip for reproducible bottles. # Tar then gzip for reproducible bottles.
tar, tar_args = setup_tar_and_args!(args) tar_mtime = tab.source_modified_time.strftime("%Y-%m-%d %H:%M:%S")
tar, tar_args = setup_tar_and_args!(args, tar_mtime)
safe_system tar, "--create", "--numeric-owner", safe_system tar, "--create", "--numeric-owner",
*tar_args, *tar_args,
"--file", tar_path, "#{f.name}/#{f.pkg_version}" "--file", tar_path, "#{f.name}/#{f.pkg_version}"
sudo_purge sudo_purge
# Set more times for reproducible bottles. # Set filename as it affects the tarball checksum.
tar_path.utime(tab.source_modified_time, tab.source_modified_time)
relocatable_tar_path = "#{f}-bottle.tar" relocatable_tar_path = "#{f}-bottle.tar"
mv tar_path, relocatable_tar_path mv tar_path, relocatable_tar_path
# Use gzip, faster to compress than bzip2, faster to uncompress than bzip2 # Use gzip, faster to compress than bzip2, faster to uncompress than bzip2

View File

@ -1,4 +1,4 @@
# typed: true # typed: false
# frozen_string_literal: true # frozen_string_literal: true
class Keg class Keg
@ -86,6 +86,8 @@ class Keg
end end
end end
undef prepare_debug_symbols
def prepare_debug_symbols def prepare_debug_symbols
binary_executable_or_library_files.each do |file| binary_executable_or_library_files.each do |file|
odebug "Extracting symbols #{file}" odebug "Extracting symbols #{file}"
@ -100,4 +102,14 @@ class Keg
EOS EOS
end end
end end
undef consistent_reproducible_symlink_permissions!
# Needed to make symlink permissions consistent on macOS and Linux for
# reproducible bottles.
def consistent_reproducible_symlink_permissions!
find do |file|
File.lchmod 0777, file if file.symlink?
end
end
end end

View File

@ -485,6 +485,8 @@ class Keg
def prepare_debug_symbols; end def prepare_debug_symbols; end
def consistent_reproducible_symlink_permissions!; end
def remove_oldname_opt_record def remove_oldname_opt_record
return unless oldname_opt_record return unless oldname_opt_record
return if oldname_opt_record.resolved_path != path return if oldname_opt_record.resolved_path != path