From 944bff4de2ec3821480ee9097e06016cce2b2925 Mon Sep 17 00:00:00 2001
From: Misty De Meo <mistydemeo@gmail.com>
Date: Sat, 15 Apr 2017 22:05:56 +0800
Subject: [PATCH] Mac Hardware: provide a more Mac-specific implementation of
 can_run?

---
 .../Homebrew/extend/os/mac/hardware/cpu.rb    | 43 ++++++++++++++
 Library/Homebrew/test/os/mac/hardware_spec.rb | 56 +++++++++++++++++++
 2 files changed, 99 insertions(+)
 create mode 100644 Library/Homebrew/test/os/mac/hardware_spec.rb

diff --git a/Library/Homebrew/extend/os/mac/hardware/cpu.rb b/Library/Homebrew/extend/os/mac/hardware/cpu.rb
index f180995fbb..22d118e1a5 100644
--- a/Library/Homebrew/extend/os/mac/hardware/cpu.rb
+++ b/Library/Homebrew/extend/os/mac/hardware/cpu.rb
@@ -107,6 +107,20 @@ module Hardware
         end
       end
 
+      # Determines whether the current CPU and macOS combination
+      # can run an executable of the specified architecture.
+      # `arch` is a symbol in the same format returned by
+      # Hardware::CPU.family
+      def can_run?(arch)
+        if Hardware::CPU.intel?
+          intel_can_run? arch
+        elsif Hardware::CPU.ppc?
+          ppc_can_run? arch
+        else
+          false
+        end
+      end
+
       def features
         @features ||= sysctl_n(
           "machdep.cpu.features",
@@ -162,6 +176,35 @@ module Hardware
           @properties[keys] = Utils.popen_read("/usr/sbin/sysctl", "-n", *keys)
         end
       end
+
+      def intel_can_run?(arch)
+        case arch
+        when :ppc
+          # Rosetta is still available
+          MacOS.version < :lion
+        when :ppc64
+          # Rosetta never supported PPC64
+          false
+        when :x86_64
+          Hardware::CPU.is_64_bit?
+        when :i386
+          true
+        else # dunno
+          false
+        end
+      end
+
+      def ppc_can_run?(arch)
+        case arch
+        when :ppc
+          true
+        when :ppc64
+          Hardware::CPU.is_64_bit?
+        else
+          # Intel is never supported
+          false
+        end
+      end
     end
   end
 end
diff --git a/Library/Homebrew/test/os/mac/hardware_spec.rb b/Library/Homebrew/test/os/mac/hardware_spec.rb
new file mode 100644
index 0000000000..fa577ba7d6
--- /dev/null
+++ b/Library/Homebrew/test/os/mac/hardware_spec.rb
@@ -0,0 +1,56 @@
+require "hardware"
+require "extend/os/mac/hardware/cpu"
+
+describe Hardware::CPU do
+  describe "::can_run?" do
+    it "reports that Intel Macs can run Intel executables" do
+      allow(Hardware::CPU).to receive(:type).and_return :intel
+      allow(Hardware::CPU).to receive(:bits).and_return 64
+      expect(Hardware::CPU.can_run?(:i386)).to be true
+      expect(Hardware::CPU.can_run?(:x86_64)).to be true
+    end
+
+    it "reports that PowerPC Macs can run PowerPC executables" do
+      allow(Hardware::CPU).to receive(:type).and_return :ppc
+      allow(Hardware::CPU).to receive(:bits).and_return 64
+      expect(Hardware::CPU.can_run?(:ppc)).to be true
+      expect(Hardware::CPU.can_run?(:ppc64)).to be true
+    end
+
+    it "reports that 32-bit Intel Macs can't run x86_64 executables" do
+      allow(Hardware::CPU).to receive(:type).and_return :intel
+      allow(Hardware::CPU).to receive(:bits).and_return 32
+      expect(Hardware::CPU.can_run?(:x86_64)).to be false
+    end
+
+    it "reports that 32-bit PowerPC Macs can't run ppc64 executables" do
+      allow(Hardware::CPU).to receive(:type).and_return :ppc
+      allow(Hardware::CPU).to receive(:bits).and_return 32
+      expect(Hardware::CPU.can_run?(:ppc64)).to be false
+    end
+
+    it "reports that Intel Macs can only run 32-bit PowerPC executables on 10.6 and older" do
+      allow(Hardware::CPU).to receive(:type).and_return :intel
+      allow(OS::Mac).to receive(:version).and_return OS::Mac::Version.new "10.6"
+      expect(Hardware::CPU.can_run?(:ppc)).to be true
+
+      allow(OS::Mac).to receive(:version).and_return OS::Mac::Version.new "10.7"
+      expect(Hardware::CPU.can_run?(:ppc)).to be false
+    end
+
+    it "reports that PowerPC Macs can't run Intel executables" do
+      allow(Hardware::CPU).to receive(:type).and_return :ppc
+      expect(Hardware::CPU.can_run?(:i386)).to be false
+      expect(Hardware::CPU.can_run?(:x86_64)).to be false
+    end
+
+    it "returns false for unknown CPU types" do
+      allow(Hardware::CPU).to receive(:type).and_return :dunno
+      expect(Hardware::CPU.can_run?(:i386)).to be false
+    end
+
+    it "returns false for unknown arches" do
+      expect(Hardware::CPU.can_run?(:blah)).to be false
+    end
+  end
+end
-- 
GitLab