From a9cd0c4b5dfae6b177e9079518fdf7154bbe1831 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 28 Aug 2025 23:36:49 +0000 Subject: [PATCH] Add cask support to brew unpack command Co-authored-by: p-linnane <105994585+p-linnane@users.noreply.github.com> --- Library/Homebrew/dev-cmd/unpack.rb | 99 +++++++++++++++----- Library/Homebrew/test/dev-cmd/unpack_spec.rb | 9 ++ 2 files changed, 84 insertions(+), 24 deletions(-) diff --git a/Library/Homebrew/dev-cmd/unpack.rb b/Library/Homebrew/dev-cmd/unpack.rb index 8ecc1c1f2e..a268b1900c 100644 --- a/Library/Homebrew/dev-cmd/unpack.rb +++ b/Library/Homebrew/dev-cmd/unpack.rb @@ -5,6 +5,8 @@ require "abstract_command" require "fileutils" require "stringio" require "formula" +require "cask/download" +require "unpack_strategy" module Homebrew module DevCmd @@ -13,7 +15,7 @@ module Homebrew cmd_args do description <<~EOS - Unpack the source files for into subdirectories of the current + Unpack the source files for and binaries for into subdirectories of the current working directory. EOS flag "--destdir=", @@ -25,15 +27,22 @@ module Homebrew "patches for the software." switch "-f", "--force", description: "Overwrite the destination directory if it already exists." + switch "--formula", "--formulae", + description: "Treat all named arguments as formulae." + switch "--cask", "--casks", + description: "Treat all named arguments as casks." conflicts "--git", "--patch" + conflicts "--formula", "--cask" + conflicts "--cask", "--patch" + conflicts "--cask", "--git" - named_args :formula, min: 1 + named_args [:formula, :cask], min: 1 end sig { override.void } def run - formulae = args.named.to_formulae + formulae_and_casks = args.named.to_formulae_and_casks if (dir = args.destdir) unpack_dir = Pathname.new(dir).expand_path @@ -44,33 +53,75 @@ module Homebrew odie "Cannot write to #{unpack_dir}" unless unpack_dir.writable? - formulae.each do |f| - stage_dir = unpack_dir/"#{f.name}-#{f.version}" - - if stage_dir.exist? - odie "Destination #{stage_dir} already exists!" unless args.force? - - rm_rf stage_dir + formulae_and_casks.each do |formula_or_cask| + case formula_or_cask + when Formula + unpack_formula(formula_or_cask, unpack_dir) + when Cask::Cask + unpack_cask(formula_or_cask, unpack_dir) end + end + end - oh1 "Unpacking #{Formatter.identifier(f.full_name)} to: #{stage_dir}" + private - # show messages about tar - with_env VERBOSE: "1" do - f.brew do - f.patch if args.patch? - cp_r getwd, stage_dir, preserve: true - end + sig { params(formula: Formula, unpack_dir: Pathname).void } + def unpack_formula(formula, unpack_dir) + stage_dir = unpack_dir/"#{formula.name}-#{formula.version}" + + if stage_dir.exist? + odie "Destination #{stage_dir} already exists!" unless args.force? + + rm_rf stage_dir + end + + oh1 "Unpacking #{Formatter.identifier(formula.full_name)} to: #{stage_dir}" + + # show messages about tar + with_env VERBOSE: "1" do + formula.brew do + formula.patch if args.patch? + cp_r getwd, stage_dir, preserve: true end + end - next unless args.git? + return unless args.git? - ohai "Setting up Git repository" - cd(stage_dir) do - system "git", "init", "-q" - system "git", "add", "-A" - system "git", "commit", "-q", "-m", "brew-unpack" - end + ohai "Setting up Git repository" + cd(stage_dir) do + system "git", "init", "-q" + system "git", "add", "-A" + system "git", "commit", "-q", "-m", "brew-unpack" + end + end + + sig { params(cask: Cask::Cask, unpack_dir: Pathname).void } + def unpack_cask(cask, unpack_dir) + stage_dir = unpack_dir/"#{cask.token}-#{cask.version}" + + if stage_dir.exist? + odie "Destination #{stage_dir} already exists!" unless args.force? + + rm_rf stage_dir + end + + oh1 "Unpacking #{Formatter.identifier(cask.full_name)} to: #{stage_dir}" + + # Download the cask + download = Cask::Download.new(cask, quarantine: false) + downloaded_path = download.fetch(quiet: false) + + # Extract to destination + stage_dir.mkpath + UnpackStrategy.detect(downloaded_path).extract_nestedly(to: stage_dir, verbose: true) + + return unless args.git? + + ohai "Setting up Git repository" + cd(stage_dir) do + system "git", "init", "-q" + system "git", "add", "-A" + system "git", "commit", "-q", "-m", "brew-unpack" end end end diff --git a/Library/Homebrew/test/dev-cmd/unpack_spec.rb b/Library/Homebrew/test/dev-cmd/unpack_spec.rb index 10251c7dda..420cd33cca 100644 --- a/Library/Homebrew/test/dev-cmd/unpack_spec.rb +++ b/Library/Homebrew/test/dev-cmd/unpack_spec.rb @@ -16,4 +16,13 @@ RSpec.describe Homebrew::DevCmd::Unpack do expect(path/"testball-0.1").to be_a_directory end end + + it "unpacks a given Cask's archive", :integration_test do + mktmpdir do |path| + expect { brew "unpack", "local-caffeine", "--destdir=#{path}", "--cask" } + .to be_a_success + + expect(path/"local-caffeine-1.2.3").to be_a_directory + end + end end