diff --git a/src/UniGetUI.PackageEngine.Managers.Homebrew/Helpers/HomebrewPkgDetailsHelper.cs b/src/UniGetUI.PackageEngine.Managers.Homebrew/Helpers/HomebrewPkgDetailsHelper.cs index 6979a39d9c..43acf290a5 100644 --- a/src/UniGetUI.PackageEngine.Managers.Homebrew/Helpers/HomebrewPkgDetailsHelper.cs +++ b/src/UniGetUI.PackageEngine.Managers.Homebrew/Helpers/HomebrewPkgDetailsHelper.cs @@ -10,22 +10,16 @@ namespace UniGetUI.PackageEngine.Managers.HomebrewManager; internal sealed class HomebrewPkgDetailsHelper : BasePkgDetailsHelper { + private readonly Homebrew _brew; + public HomebrewPkgDetailsHelper(Homebrew manager) - : base(manager) { } + : base(manager) { _brew = manager; } protected override void GetDetails_UnSafe(IPackageDetails details) { using var p = new Process { - StartInfo = new ProcessStartInfo - { - FileName = Manager.Status.ExecutablePath, - Arguments = $"info --json=v2 {details.Package.Id}", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - }, + StartInfo = _brew.MakeBrewStartInfo($"info --json=v2 {details.Package.Id}"), }; IProcessTaskLogger logger = Manager.TaskLogger.CreateNew( diff --git a/src/UniGetUI.PackageEngine.Managers.Homebrew/Helpers/HomebrewSourceHelper.cs b/src/UniGetUI.PackageEngine.Managers.Homebrew/Helpers/HomebrewSourceHelper.cs index b83ac638d7..7919bff5d7 100644 --- a/src/UniGetUI.PackageEngine.Managers.Homebrew/Helpers/HomebrewSourceHelper.cs +++ b/src/UniGetUI.PackageEngine.Managers.Homebrew/Helpers/HomebrewSourceHelper.cs @@ -10,8 +10,10 @@ namespace UniGetUI.PackageEngine.Managers.HomebrewManager; internal sealed class HomebrewSourceHelper : BaseSourceHelper { + private readonly Homebrew _brew; + public HomebrewSourceHelper(Homebrew manager) - : base(manager) { } + : base(manager) { _brew = manager; } // ── Source listing ───────────────────────────────────────────────────── @@ -21,15 +23,7 @@ protected override IReadOnlyList GetSources_UnSafe() using var p = new Process { - StartInfo = new ProcessStartInfo - { - FileName = Manager.Status.ExecutablePath, - Arguments = "tap", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - }, + StartInfo = _brew.MakeBrewStartInfo("tap"), }; IProcessTaskLogger logger = Manager.TaskLogger.CreateNew(LoggableTaskType.ListSources, p); p.Start(); diff --git a/src/UniGetUI.PackageEngine.Managers.Homebrew/Homebrew.cs b/src/UniGetUI.PackageEngine.Managers.Homebrew/Homebrew.cs index 593e8f722c..e500766314 100644 --- a/src/UniGetUI.PackageEngine.Managers.Homebrew/Homebrew.cs +++ b/src/UniGetUI.PackageEngine.Managers.Homebrew/Homebrew.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Runtime.InteropServices; using System.Text.RegularExpressions; using UniGetUI.Core.Logging; using UniGetUI.Core.Tools; @@ -98,23 +99,38 @@ protected override void _loadManagerExecutableFile( out string callArguments) { (found, path) = GetExecutableFile(); - callArguments = ""; + // Force ARM64 when brew is at the Apple Silicon prefix. Without this, + // .NET's posix_spawn may select the x86_64 slice of universal binaries + // (bash, ruby) in the brew script chain, causing Homebrew to detect a + // Rosetta 2 context even when UniGetUI itself is ARM64-native. + if (path == BREW_PATHS[0] + && OperatingSystem.IsMacOS() + && RuntimeInformation.OSArchitecture == System.Runtime.InteropServices.Architecture.Arm64) + { + callArguments = $"-arm64 {path}"; + path = "/usr/bin/arch"; + } + else + { + callArguments = ""; + } } + internal ProcessStartInfo MakeBrewStartInfo(string arguments) => new() + { + FileName = Status.ExecutablePath, + Arguments = Status.ExecutableCallArgs.Length > 0 + ? $"{Status.ExecutableCallArgs} {arguments}" + : arguments, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true, + }; + protected override void _loadManagerVersion(out string version) { - using var p = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = Status.ExecutablePath, - Arguments = "--version", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - }, - }; + using var p = new Process { StartInfo = MakeBrewStartInfo("--version") }; p.Start(); // First line: "Homebrew 4.x.x" version = p.StandardOutput.ReadLine()?.Replace("Homebrew ", "").Trim() ?? ""; @@ -125,18 +141,7 @@ protected override void _loadManagerVersion(out string version) public override void RefreshPackageIndexes() { - using var p = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = Status.ExecutablePath, - Arguments = "update", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - }, - }; + using var p = new Process { StartInfo = MakeBrewStartInfo("update") }; IProcessTaskLogger logger = TaskLogger.CreateNew(LoggableTaskType.RefreshIndexes, p); p.Start(); logger.AddToStdOut(p.StandardOutput.ReadToEnd()); @@ -155,18 +160,7 @@ protected override IReadOnlyList FindPackages_UnSafe(string query) IManagerSource caskSource = SourcesHelper.Factory.GetSourceOrDefault("Homebrew Cask"); IManagerSource currentSection = formulaeSource; - using var p = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = Status.ExecutablePath, - Arguments = $"search {query}", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - }, - }; + using var p = new Process { StartInfo = MakeBrewStartInfo($"search {query}") }; IProcessTaskLogger logger = TaskLogger.CreateNew(LoggableTaskType.FindPackages, p); p.Start(); @@ -209,18 +203,7 @@ private IReadOnlyList ListInstalledByType(string typeFlag, string sourc var packages = new List(); IManagerSource source = SourcesHelper.Factory.GetSourceOrDefault(sourceName); - using var p = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = Status.ExecutablePath, - Arguments = $"list {typeFlag} --versions", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - }, - }; + using var p = new Process { StartInfo = MakeBrewStartInfo($"list {typeFlag} --versions") }; IProcessTaskLogger logger = TaskLogger.CreateNew(LoggableTaskType.ListInstalledPackages, p); p.Start(); @@ -250,18 +233,7 @@ protected override IReadOnlyList GetAvailableUpdates_UnSafe() foreach (var pkg in GetInstalledPackages()) installed.TryAdd(pkg.Id, pkg); - using var p = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = Status.ExecutablePath, - Arguments = "outdated --verbose", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - }, - }; + using var p = new Process { StartInfo = MakeBrewStartInfo("outdated --verbose") }; IProcessTaskLogger logger = TaskLogger.CreateNew(LoggableTaskType.ListUpdates, p); p.Start();