Skip to content

Commit 48170b8

Browse files
authored
Merge pull request #20601 from Homebrew/copilot/fix-20600
Add cask support to `brew unpack` command
2 parents e6711c5 + 25ed81f commit 48170b8

File tree

3 files changed

+96
-23
lines changed

3 files changed

+96
-23
lines changed

Library/Homebrew/dev-cmd/unpack.rb

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
require "fileutils"
66
require "stringio"
77
require "formula"
8+
require "cask/download"
9+
require "unpack_strategy"
810

911
module Homebrew
1012
module DevCmd
@@ -13,7 +15,7 @@ class Unpack < AbstractCommand
1315

1416
cmd_args do
1517
description <<~EOS
16-
Unpack the source files for <formula> into subdirectories of the current
18+
Unpack the files for the <formula> or <cask> into subdirectories of the current
1719
working directory.
1820
EOS
1921
flag "--destdir=",
@@ -25,15 +27,28 @@ class Unpack < AbstractCommand
2527
"patches for the software."
2628
switch "-f", "--force",
2729
description: "Overwrite the destination directory if it already exists."
30+
switch "--formula", "--formulae",
31+
description: "Treat all named arguments as formulae."
32+
switch "--cask", "--casks",
33+
description: "Treat all named arguments as casks."
2834

2935
conflicts "--git", "--patch"
36+
conflicts "--formula", "--cask"
37+
conflicts "--cask", "--patch"
38+
conflicts "--cask", "--git"
3039

31-
named_args :formula, min: 1
40+
named_args [:formula, :cask], min: 1
3241
end
3342

3443
sig { override.void }
3544
def run
36-
formulae = args.named.to_formulae
45+
formulae_and_casks = if args.casks?
46+
args.named.to_formulae_and_casks(only: :cask)
47+
elsif args.formulae?
48+
args.named.to_formulae_and_casks(only: :formula)
49+
else
50+
args.named.to_formulae_and_casks
51+
end
3752

3853
if (dir = args.destdir)
3954
unpack_dir = Pathname.new(dir).expand_path
@@ -44,34 +59,69 @@ def run
4459

4560
odie "Cannot write to #{unpack_dir}" unless unpack_dir.writable?
4661

47-
formulae.each do |f|
48-
stage_dir = unpack_dir/"#{f.name}-#{f.version}"
62+
formulae_and_casks.each do |formula_or_cask|
63+
if formula_or_cask.is_a?(Cask::Cask)
64+
unpack_cask(formula_or_cask, unpack_dir)
65+
elsif (formula = T.cast(formula_or_cask, Formula))
66+
unpack_formula(formula, unpack_dir)
67+
end
68+
end
69+
end
4970

50-
if stage_dir.exist?
51-
odie "Destination #{stage_dir} already exists!" unless args.force?
71+
private
5272

53-
rm_rf stage_dir
54-
end
73+
sig { params(formula: Formula, unpack_dir: Pathname).void }
74+
def unpack_formula(formula, unpack_dir)
75+
stage_dir = unpack_dir/"#{formula.name}-#{formula.version}"
5576

56-
oh1 "Unpacking #{Formatter.identifier(f.full_name)} to: #{stage_dir}"
77+
if stage_dir.exist?
78+
odie "Destination #{stage_dir} already exists!" unless args.force?
5779

58-
# show messages about tar
59-
with_env VERBOSE: "1" do
60-
f.brew do
61-
f.patch if args.patch?
62-
cp_r getwd, stage_dir, preserve: true
63-
end
64-
end
80+
rm_rf stage_dir
81+
end
6582

66-
next unless args.git?
83+
oh1 "Unpacking #{Formatter.identifier(formula.full_name)} to: #{stage_dir}"
6784

68-
ohai "Setting up Git repository"
69-
cd(stage_dir) do
70-
system "git", "init", "-q"
71-
system "git", "add", "-A"
72-
system "git", "commit", "-q", "-m", "brew-unpack"
85+
# show messages about tar
86+
with_env VERBOSE: "1" do
87+
formula.brew do
88+
formula.patch if args.patch?
89+
cp_r getwd, stage_dir, preserve: true
7390
end
7491
end
92+
93+
return unless args.git?
94+
95+
ohai "Setting up Git repository"
96+
cd(stage_dir) do
97+
system "git", "init", "-q"
98+
system "git", "add", "-A"
99+
system "git", "commit", "-q", "-m", "brew-unpack"
100+
end
101+
end
102+
103+
sig { params(cask: Cask::Cask, unpack_dir: Pathname).void }
104+
def unpack_cask(cask, unpack_dir)
105+
stage_dir = unpack_dir/"#{cask.token}-#{cask.version}"
106+
107+
if stage_dir.exist?
108+
odie "Destination #{stage_dir} already exists!" unless args.force?
109+
110+
rm_rf stage_dir
111+
end
112+
113+
oh1 "Unpacking #{Formatter.identifier(cask.full_name)} to: #{stage_dir}"
114+
115+
download = Cask::Download.new(cask, quarantine: true)
116+
117+
downloaded_path = if download.downloaded?
118+
download.cached_download
119+
else
120+
download.fetch(quiet: false)
121+
end
122+
123+
stage_dir.mkpath
124+
UnpackStrategy.detect(downloaded_path).extract_nestedly(to: stage_dir, verbose: true)
75125
end
76126
end
77127
end

Library/Homebrew/sorbet/rbi/dsl/homebrew/dev_cmd/unpack.rbi

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Library/Homebrew/test/dev-cmd/unpack_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,15 @@
1616
expect(path/"testball-0.1").to be_a_directory
1717
end
1818
end
19+
20+
it "unpacks a given Cask's archive", :integration_test do
21+
caffeine_cask = Cask::CaskLoader.load(cask_path("local-caffeine"))
22+
23+
mktmpdir do |path|
24+
expect { brew "unpack", cask_path("local-caffeine"), "--destdir=#{path}" }
25+
.to be_a_success
26+
27+
expect(path/"local-caffeine-#{caffeine_cask.version}").to be_a_directory
28+
end
29+
end
1930
end

0 commit comments

Comments
 (0)