From ac2d8886722af6b84ec03e7439d3ea3bd9db6f21 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Sep 2025 12:11:06 +0000 Subject: [PATCH] Simplify keg relocation fix with minimal changes Co-authored-by: MikeMcQuaid <125011+MikeMcQuaid@users.noreply.github.com> --- Library/Homebrew/keg_relocate.rb | 18 +++++++++++++++++- Library/Homebrew/test/keg_spec.rb | 26 +++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/keg_relocate.rb b/Library/Homebrew/keg_relocate.rb index e01ac7aa9c..f4fda4fceb 100644 --- a/Library/Homebrew/keg_relocate.rb +++ b/Library/Homebrew/keg_relocate.rb @@ -128,6 +128,12 @@ class Keg } end + sig { params(file: Pathname).returns(T::Boolean) } + def homebrew_created_file?(file) + basename = file.basename.to_s + basename.start_with?("homebrew.") && %w[.plist .service .timer].include?(file.extname) + end + sig { returns(Relocation) } def prepare_relocation_to_placeholders relocation = Relocation.new @@ -251,7 +257,17 @@ class Keg regular_files.each do |first, *rest| s = first.open("rb", &:read) - next unless relocation.replace_text!(s) + # Use full prefix replacement for Homebrew-created files when using selective relocation + current_relocation = if new_usr_local_relocation? && homebrew_created_file?(first) + full_relocation = Relocation.new + full_relocation.add_replacement_pair(:prefix, HOMEBREW_PREFIX.to_s, PREFIX_PLACEHOLDER, path: true) + full_relocation.add_replacement_pair(:cellar, HOMEBREW_CELLAR.to_s, CELLAR_PLACEHOLDER, path: true) + full_relocation + else + relocation + end + + next unless current_relocation.replace_text!(s) changed_files += [first, *rest].map { |file| file.relative_path_from(path) } diff --git a/Library/Homebrew/test/keg_spec.rb b/Library/Homebrew/test/keg_spec.rb index ffac76b7f0..03e143cf18 100644 --- a/Library/Homebrew/test/keg_spec.rb +++ b/Library/Homebrew/test/keg_spec.rb @@ -1,3 +1,4 @@ +# typed: strict # frozen_string_literal: true require "keg" @@ -6,7 +7,7 @@ require "stringio" RSpec.describe Keg do include FileUtils - def setup_test_keg(name, version) + define_method(:setup_test_keg) do |name, version| path = HOMEBREW_CELLAR/name/version (path/"bin").mkpath @@ -319,6 +320,29 @@ RSpec.describe Keg do end end + describe "#homebrew_created_file?" do + it "identifies Homebrew service files" do + plist_file = instance_double(Pathname, extname: ".plist", basename: Pathname.new("homebrew.foo.plist")) + service_file = instance_double(Pathname, extname: ".service", basename: Pathname.new("homebrew.foo.service")) + timer_file = instance_double(Pathname, extname: ".timer", basename: Pathname.new("homebrew.foo.timer")) + regular_file = instance_double(Pathname, extname: ".txt", basename: Pathname.new("readme.txt")) + non_homebrew_plist = instance_double(Pathname, extname: ".plist", + basename: Pathname.new("com.example.foo.plist")) + + allow(plist_file.basename).to receive(:to_s).and_return("homebrew.foo.plist") + allow(service_file.basename).to receive(:to_s).and_return("homebrew.foo.service") + allow(timer_file.basename).to receive(:to_s).and_return("homebrew.foo.timer") + allow(regular_file.basename).to receive(:to_s).and_return("readme.txt") + allow(non_homebrew_plist.basename).to receive(:to_s).and_return("com.example.foo.plist") + + expect(keg.homebrew_created_file?(plist_file)).to be true + expect(keg.homebrew_created_file?(service_file)).to be true + expect(keg.homebrew_created_file?(timer_file)).to be true + expect(keg.homebrew_created_file?(regular_file)).to be false + expect(keg.homebrew_created_file?(non_homebrew_plist)).to be false + end + end + specify "#link and #unlink" do expect(keg).not_to be_linked keg.link