From e325dc6410437e5a65505454973e24275d0090c7 Mon Sep 17 00:00:00 2001
From: Sam Bostock <sam.bostock@shopify.com>
Date: Fri, 20 Jan 2023 14:57:39 -0500
Subject: [PATCH] Allow specifying pkg target

Currently, we always use the `/` target, but other volumes can be
provided as targets, as well as special targets like
`CurrentUserHomeDirectory`. See `installer -help` for more info.

In particular, if installing to `CurrentUserHomeDirectory` it seems
reasonable to assume we wouldn't need `sudo`.
---
 Library/Homebrew/cask/artifact/pkg.rb         | 11 +++--
 .../Homebrew/test/cask/artifact/pkg_spec.rb   | 48 +++++++++++++++++++
 ...-pkg-target-current-user-home-directory.rb | 11 +++++
 .../fixtures/cask/Casks/with-pkg-target.rb    | 11 +++++
 4 files changed, 78 insertions(+), 3 deletions(-)
 create mode 100644 Library/Homebrew/test/support/fixtures/cask/Casks/with-pkg-target-current-user-home-directory.rb
 create mode 100644 Library/Homebrew/test/support/fixtures/cask/Casks/with-pkg-target.rb

diff --git a/Library/Homebrew/cask/artifact/pkg.rb b/Library/Homebrew/cask/artifact/pkg.rb
index 924f731ae484f..c1a6847e2a1e6 100644
--- a/Library/Homebrew/cask/artifact/pkg.rb
+++ b/Library/Homebrew/cask/artifact/pkg.rb
@@ -18,7 +18,7 @@ class Pkg < AbstractArtifact
       attr_reader :path, :stanza_options
 
       def self.from_args(cask, path, **stanza_options)
-        stanza_options.assert_valid_keys!(:allow_untrusted, :choices)
+        stanza_options.assert_valid_keys!(:allow_untrusted, :choices, :target)
         new(cask, path, **stanza_options)
       end
 
@@ -54,7 +54,7 @@ def run_installer(command: nil, verbose: false, **_options)
 
         args = [
           "-pkg",    path,
-          "-target", "/"
+          "-target", target
         ]
         args << "-verboseR" if verbose
         args << "-allowUntrusted" if stanza_options.fetch(:allow_untrusted, false)
@@ -65,7 +65,8 @@ def run_installer(command: nil, verbose: false, **_options)
             "USER"     => User.current,
             "USERNAME" => User.current,
           }
-          command.run!("/usr/sbin/installer", sudo: true, args: args, print_stdout: true, env: env)
+          sudo = target != "CurrentUserHomeDirectory"
+          command.run!("/usr/sbin/installer", sudo: sudo, args: args, print_stdout: true, env: env)
         end
       end
 
@@ -81,6 +82,10 @@ def with_choices_file
           file.unlink
         end
       end
+
+      def target
+        stanza_options.fetch(:target, "/")
+      end
     end
   end
 end
diff --git a/Library/Homebrew/test/cask/artifact/pkg_spec.rb b/Library/Homebrew/test/cask/artifact/pkg_spec.rb
index 85234faf6733e..b6f275d5bf54a 100644
--- a/Library/Homebrew/test/cask/artifact/pkg_spec.rb
+++ b/Library/Homebrew/test/cask/artifact/pkg_spec.rb
@@ -77,4 +77,52 @@
       pkg.install_phase(command: fake_system_command)
     end
   end
+
+  describe "target" do
+    describe "with volume target" do
+      let(:cask) { Cask::CaskLoader.load(cask_path("with-pkg-target")) }
+
+      it "runs the system installer on the specified pkgs with the specified target" do
+        pkg = cask.artifacts.find { |a| a.is_a?(described_class) }
+
+        expect(fake_system_command).to receive(:run!).with(
+          "/usr/sbin/installer",
+          args:         ["-pkg", cask.staged_path.join("MyFancyPkg", "Fancy.pkg"),
+                         "-target", "/Volumes/Macintosh HD2"],
+          sudo:         true,
+          print_stdout: true,
+          env:          {
+            "LOGNAME"  => ENV.fetch("USER"),
+            "USER"     => ENV.fetch("USER"),
+            "USERNAME" => ENV.fetch("USER"),
+          },
+        )
+
+        pkg.install_phase(command: fake_system_command)
+      end
+    end
+
+    describe "with CurrentUserHomeDirectory target" do
+      let(:cask) { Cask::CaskLoader.load(cask_path("with-pkg-target-current-user-home-directory")) }
+
+      it "runs the system installer on the specified pkgs with the specified target" do
+        pkg = cask.artifacts.find { |a| a.is_a?(described_class) }
+
+        expect(fake_system_command).to receive(:run!).with(
+          "/usr/sbin/installer",
+          args:         ["-pkg", cask.staged_path.join("MyFancyPkg", "Fancy.pkg"),
+                         "-target", "CurrentUserHomeDirectory"],
+          sudo:         false,
+          print_stdout: true,
+          env:          {
+            "LOGNAME"  => ENV.fetch("USER"),
+            "USER"     => ENV.fetch("USER"),
+            "USERNAME" => ENV.fetch("USER"),
+          },
+        )
+
+        pkg.install_phase(command: fake_system_command)
+      end
+    end
+  end
 end
diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-pkg-target-current-user-home-directory.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-pkg-target-current-user-home-directory.rb
new file mode 100644
index 0000000000000..7d6616f7b3bae
--- /dev/null
+++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-pkg-target-current-user-home-directory.rb
@@ -0,0 +1,11 @@
+cask "with-pkg-target-current-user-home-directory" do
+  version "1.2.3"
+  sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
+
+  url "file://#{TEST_FIXTURE_DIR}/cask/MyFancyPkg.zip"
+  homepage "https://brew.sh/fancy-pkg"
+
+  pkg "MyFancyPkg/Fancy.pkg", target: "CurrentUserHomeDirectory"
+
+  uninstall pkgutil: "my.fancy.package"
+end
diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-pkg-target.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-pkg-target.rb
new file mode 100644
index 0000000000000..3ae7e3795703a
--- /dev/null
+++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-pkg-target.rb
@@ -0,0 +1,11 @@
+cask "with-pkg-target" do
+  version "1.2.3"
+  sha256 "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
+
+  url "file://#{TEST_FIXTURE_DIR}/cask/MyFancyPkg.zip"
+  homepage "https://brew.sh/fancy-pkg"
+
+  pkg "MyFancyPkg/Fancy.pkg", target: "/Volumes/Macintosh HD2"
+
+  uninstall pkgutil: "my.fancy.package"
+end