Skip to content

Commit fa41de0

Browse files
committed
Add gzipped executable action
Several binary formulae ship a gzipped executable that needs the same guarded post-install expansion and mode handling. - resolve serialised source and destination path bases - skip absent payloads and replace stale expanded sources - install each executable with an explicit literal permission mode
1 parent b221d24 commit fa41de0

6 files changed

Lines changed: 72 additions & 3 deletions

File tree

‎Library/Homebrew/install_steps.rb‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,20 @@ def configure_gcc_runtime
597597
add_step("configure_gcc_runtime")
598598
end
599599

600+
sig {
601+
params(
602+
source: ::T.any(::String, ::Pathname),
603+
target: ::T.any(::String, ::Pathname),
604+
source_base: ::T.nilable(::T.any(::String, ::Symbol)),
605+
target_base: ::T.nilable(::T.any(::String, ::Symbol)),
606+
).void
607+
}
608+
def install_gzipped_executable(source, target, source_base: nil, target_base: nil)
609+
add_step("install_gzipped_executable",
610+
"source" => path_spec(source, base: source_base, default_base: @default_source_base),
611+
"target" => path_spec(target, base: target_base, default_base: @default_target_base))
612+
end
613+
600614
private
601615

602616
sig { params(guard: PathSpec, block: ::T.proc.void).void }
@@ -841,6 +855,8 @@ def run_install_step(step)
841855
opoo expand_template_tokens(step_string(step, "message"))
842856
when "configure_gcc_runtime"
843857
run_configure_gcc_runtime
858+
when "install_gzipped_executable"
859+
run_install_gzipped_executable(step)
844860
when "set_permissions"
845861
run_set_permissions(step)
846862
when "set_ownership"

‎Library/Homebrew/install_steps/formula_actions.rb‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,29 @@ def run_configure_gcc_runtime
6161
EOS
6262
specs.write(specs.read.gsub(" %o ", "\\0%(homebrew_rpath) ")) if homebrew_rpath
6363
end
64+
65+
sig { params(step: Step).void }
66+
def run_install_gzipped_executable(step)
67+
source = resolve_path(step_path(step, "source"))
68+
return unless source.exist?
69+
70+
require "unpack_strategy"
71+
72+
target = resolve_path(step_path(step, "target"))
73+
target.dirname.mkpath
74+
temporary_target = target.dirname/".#{target.basename}.install-step"
75+
temporary_gzip = Pathname("#{temporary_target}.gz")
76+
FileUtils.rm_f [temporary_target, temporary_gzip]
77+
begin
78+
UnpackStrategy::Gzip.new(source).extract(to: target.dirname, basename: temporary_gzip.basename)
79+
FileUtils.rm_f target
80+
FileUtils.mv temporary_target, target
81+
source.unlink
82+
ensure
83+
FileUtils.rm_f [temporary_target, temporary_gzip]
84+
end
85+
target.chmod 0755
86+
end
6487
end
6588
end
6689
end

‎Library/Homebrew/rubocops/shared/install_steps_helper.rb‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module InstallStepsHelper
1717
PERMISSION_STEP_METHODS = [:set_permissions, :set_ownership].freeze
1818
COMMAND_STEP_METHODS = [:run, :terminate_process].freeze
1919
NOTICE_STEP_METHODS = [:warn_if_exists].freeze
20-
FORMULA_ACTION_STEP_METHODS = [:configure_gcc_runtime].freeze
20+
FORMULA_ACTION_STEP_METHODS = [:configure_gcc_runtime, :install_compressed_executable].freeze
2121
ALLOWED_STEP_METHODS = T.let(
2222
[*FILE_PREPARATION_STEP_METHODS, *LINK_STEP_METHODS, *CONFIG_WRITE_STEP_METHODS, *SERVICE_DATA_STEP_METHODS,
2323
*REBUILD_ACTION_STEP_METHODS, :set_permissions, *COMMAND_STEP_METHODS, *NOTICE_STEP_METHODS,

‎Library/Homebrew/test/install_steps_spec.rb‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,34 @@
682682
runner.run(steps)
683683
end
684684

685+
specify "dispatches gzipped executable installation" do
686+
steps = Homebrew::InstallSteps::DSL.build do
687+
install_gzipped_executable "compressed.gz", "bin/executable"
688+
end
689+
690+
runner = Homebrew::InstallSteps::Runner.new(context:)
691+
expect(runner).to receive(:run_install_gzipped_executable)
692+
693+
runner.run(steps)
694+
end
695+
696+
specify "installs a gzipped executable with a fixed mode" do
697+
require "zlib"
698+
699+
source = root/"prefix/bin/executable.gz"
700+
source.dirname.mkpath
701+
Zlib::GzipWriter.open(source.to_s) { |gzip| gzip.write "executable" }
702+
steps = Homebrew::InstallSteps::DSL.build(default_source_base: :prefix, default_target_base: :prefix) do
703+
install_gzipped_executable "bin/executable.gz", "bin/executable"
704+
end
705+
706+
Homebrew::InstallSteps::Runner.new(context:).run(steps)
707+
708+
target = root/"prefix/bin/executable"
709+
expect(target).to be_executable.and have_attributes(read: "executable")
710+
expect(source).not_to exist
711+
end
712+
685713
describe "runs gtk_update_icon_cache rebuild action" do
686714
let(:formula) { instance_double(Formula, opt_bin: root/"opt/bin") }
687715
let(:steps) do

‎Library/Homebrew/test/rubocops/install_steps_spec.rb‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class Foo < Formula
4242
4343
post_install_steps do
4444
system "true"
45-
^^^^^^^^^^^^^ FormulaAudit/InstallSteps: Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `link_dir`, `link_children`, `write`, `init_data_dir`, `compile_gsettings_schemas`, `gdk_pixbuf_query_loaders`, `gtk_update_icon_cache`, `update_mime_database`, `update_desktop_database`, `set_permissions`, `run`, `terminate_process`, `warn_if_exists`, `configure_gcc_runtime`.
45+
^^^^^^^^^^^^^ FormulaAudit/InstallSteps: Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `link_dir`, `link_children`, `write`, `init_data_dir`, `compile_gsettings_schemas`, `gdk_pixbuf_query_loaders`, `gtk_update_icon_cache`, `update_mime_database`, `update_desktop_database`, `set_permissions`, `run`, `terminate_process`, `warn_if_exists`, `configure_gcc_runtime`, `install_compressed_executable`.
4646
end
4747
end
4848
RUBY
@@ -66,6 +66,7 @@ class Foo < Formula
6666
terminate_process "foo", retries: 2
6767
warn_if_exists "foo", "foo exists"
6868
configure_gcc_runtime
69+
install_compressed_executable "compressed", "bin/executable"
6970
write "foo/banner", <<~TEXT
7071
literal banner
7172
TEXT
@@ -89,7 +90,7 @@ class Foo < Formula
8990
9091
post_install_steps do
9192
write "foo.conf", "prefix = #{prefix}"
92-
^^^^^^^^^ FormulaAudit/InstallSteps: Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `link_dir`, `link_children`, `write`, `init_data_dir`, `compile_gsettings_schemas`, `gdk_pixbuf_query_loaders`, `gtk_update_icon_cache`, `update_mime_database`, `update_desktop_database`, `set_permissions`, `run`, `terminate_process`, `warn_if_exists`, `configure_gcc_runtime`.
93+
^^^^^^^^^ FormulaAudit/InstallSteps: Steps blocks may only contain install step DSL calls: `mkdir`, `mkdir_p`, `touch`, `move`, `mv`, `move_children`, `copy`, `remove`, `inreplace`, `symlink`, `ln_s`, `ln_sf`, `link_dir`, `link_children`, `write`, `init_data_dir`, `compile_gsettings_schemas`, `gdk_pixbuf_query_loaders`, `gtk_update_icon_cache`, `update_mime_database`, `update_desktop_database`, `set_permissions`, `run`, `terminate_process`, `warn_if_exists`, `configure_gcc_runtime`, `install_compressed_executable`.
9394
end
9495
end
9596
RUBY

‎docs/Formula-Cookbook.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,7 @@ warn_if_exists "foo.conf", "Remove the old foo.conf before continuing", base: :e
12381238
Use the named actions below for formula families that share post-install algorithms. Unique complex logic should be installed as a packaged helper and invoked with `run` instead of adding a formula-specific action.
12391239

12401240
* `configure_gcc_runtime`: generate the Linux GCC runtime links and specs.
1241+
* `install_compressed_executable`: unpack and install a gzipped executable.
12411242

12421243
#### Service data directory steps
12431244

0 commit comments

Comments
 (0)