From cb7dbbae55a8abbd5f984d4cf633eb61742067b6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Sep 2025 07:26:44 +0000 Subject: [PATCH 1/5] Initial plan From fb65fa9de928f705c5a5825f0d824ac543a279be Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Sep 2025 07:47:53 +0000 Subject: [PATCH 2/5] Fix brew bundle dump --global to respect XDG_CONFIG_HOME - Remove File.exist? check in brewfile.rb to use XDG path even when Brewfile doesn't exist yet - Add directory creation in dumper.rb to ensure parent directories exist before writing - Add test case for XDG behavior when Brewfile doesn't exist initially Co-authored-by: MikeMcQuaid <125011+MikeMcQuaid@users.noreply.github.com> --- Library/Homebrew/bundle/brewfile.rb | 2 +- Library/Homebrew/bundle/dumper.rb | 1 + Library/Homebrew/test/bundle/brewfile_spec.rb | 9 +++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/bundle/brewfile.rb b/Library/Homebrew/bundle/brewfile.rb index 60e1a1fba4a61..4c526504d058e 100644 --- a/Library/Homebrew/bundle/brewfile.rb +++ b/Library/Homebrew/bundle/brewfile.rb @@ -24,7 +24,7 @@ def self.path(dash_writes_to_stdout: false, global: false, file: nil) else raise "'HOMEBREW_BUNDLE_FILE' cannot be specified with '--global'" if env_bundle_file.present? - if user_config_home && File.exist?("#{user_config_home}/Brewfile") + if user_config_home "#{user_config_home}/Brewfile" else Bundle.exchange_uid_if_needed! do diff --git a/Library/Homebrew/bundle/dumper.rb b/Library/Homebrew/bundle/dumper.rb index 218b297890ef6..c5ef1ddb17755 100644 --- a/Library/Homebrew/bundle/dumper.rb +++ b/Library/Homebrew/bundle/dumper.rb @@ -81,6 +81,7 @@ def self.brewfile_path(global: false, file: nil) sig { params(file: Pathname, content: String).void } def self.write_file(file, content) Bundle.exchange_uid_if_needed! do + FileUtils.mkdir_p file.parent file.open("w") { |io| io.write content } end end diff --git a/Library/Homebrew/test/bundle/brewfile_spec.rb b/Library/Homebrew/test/bundle/brewfile_spec.rb index 9be511c2a5628..febdcb0afea2b 100644 --- a/Library/Homebrew/test/bundle/brewfile_spec.rb +++ b/Library/Homebrew/test/bundle/brewfile_spec.rb @@ -1,3 +1,4 @@ +# typed: strict # frozen_string_literal: true require "bundle" @@ -171,6 +172,14 @@ expect(path).to eq(expected_pathname) end end + + context "when HOMEBREW_USER_CONFIG_HOME is set but Brewfile does not exist" do + let(:config_dir_brewfile_exist) { false } + + it "returns the XDG-compliant path when HOMEBREW_USER_CONFIG_HOME is set" do + expect(path).to eq(Pathname.new("#{env_user_config_home_value}/Brewfile")) + end + end end context "when HOMEBREW_BUNDLE_FILE has a value" do From 3a358905ac3953f9b655e77c91aeb6f901194ec5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Sep 2025 12:17:15 +0000 Subject: [PATCH 3/5] Address backwards compatibility concerns and use Pathname#mkpath - Restore backwards compatibility by checking both XDG and legacy Brewfile paths - Use existing file when available, only use XDG path for new file creation - Replace FileUtils.mkdir_p with Pathname#mkpath as requested - Add comprehensive test coverage for all scenarios Co-authored-by: MikeMcQuaid <125011+MikeMcQuaid@users.noreply.github.com> --- Library/Homebrew/bundle/brewfile.rb | 10 +++++++++- Library/Homebrew/bundle/dumper.rb | 2 +- Library/Homebrew/test/bundle/brewfile_spec.rb | 11 ++++++++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Library/Homebrew/bundle/brewfile.rb b/Library/Homebrew/bundle/brewfile.rb index 4c526504d058e..992ce4fe03a4d 100644 --- a/Library/Homebrew/bundle/brewfile.rb +++ b/Library/Homebrew/bundle/brewfile.rb @@ -25,7 +25,15 @@ def self.path(dash_writes_to_stdout: false, global: false, file: nil) raise "'HOMEBREW_BUNDLE_FILE' cannot be specified with '--global'" if env_bundle_file.present? if user_config_home - "#{user_config_home}/Brewfile" + xdg_path = "#{user_config_home}/Brewfile" + legacy_path = Bundle.exchange_uid_if_needed! { "#{Dir.home}/.Brewfile" } + + # Prefer existing file to maintain backwards compatibility + if File.exist?(xdg_path) || !File.exist?(legacy_path) + xdg_path + else + legacy_path + end else Bundle.exchange_uid_if_needed! do "#{Dir.home}/.Brewfile" diff --git a/Library/Homebrew/bundle/dumper.rb b/Library/Homebrew/bundle/dumper.rb index c5ef1ddb17755..c48687583a1a7 100644 --- a/Library/Homebrew/bundle/dumper.rb +++ b/Library/Homebrew/bundle/dumper.rb @@ -81,7 +81,7 @@ def self.brewfile_path(global: false, file: nil) sig { params(file: Pathname, content: String).void } def self.write_file(file, content) Bundle.exchange_uid_if_needed! do - FileUtils.mkdir_p file.parent + file.parent.mkpath file.open("w") { |io| io.write content } end end diff --git a/Library/Homebrew/test/bundle/brewfile_spec.rb b/Library/Homebrew/test/bundle/brewfile_spec.rb index febdcb0afea2b..4b0832341827e 100644 --- a/Library/Homebrew/test/bundle/brewfile_spec.rb +++ b/Library/Homebrew/test/bundle/brewfile_spec.rb @@ -1,4 +1,3 @@ -# typed: strict # frozen_string_literal: true require "bundle" @@ -173,10 +172,16 @@ end end - context "when HOMEBREW_USER_CONFIG_HOME is set but Brewfile does not exist" do + context "when HOMEBREW_USER_CONFIG_HOME is set but neither Brewfile exists" do let(:config_dir_brewfile_exist) { false } - it "returns the XDG-compliant path when HOMEBREW_USER_CONFIG_HOME is set" do + before do + # Mock that both XDG and legacy Brewfiles don't exist + allow(File).to receive(:exist?).with("/Users/username/.homebrew/Brewfile").and_return(false) + allow(File).to receive(:exist?).with("#{Dir.home}/.Brewfile").and_return(false) + end + + it "returns the XDG path for initial Brewfile creation" do expect(path).to eq(Pathname.new("#{env_user_config_home_value}/Brewfile")) end end From 040fd9cd91b31cd6e2738b654436250ccbbe8a2b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Sep 2025 12:50:51 +0000 Subject: [PATCH 4/5] Address reviewer feedback: check XDG mode properly and make lazy Co-authored-by: MikeMcQuaid <125011+MikeMcQuaid@users.noreply.github.com> --- Library/Homebrew/bundle/brewfile.rb | 22 +++++++++------ Library/Homebrew/test/bundle/brewfile_spec.rb | 28 +++++++++++++++---- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/Library/Homebrew/bundle/brewfile.rb b/Library/Homebrew/bundle/brewfile.rb index 992ce4fe03a4d..2b139e4900ec4 100644 --- a/Library/Homebrew/bundle/brewfile.rb +++ b/Library/Homebrew/bundle/brewfile.rb @@ -24,16 +24,22 @@ def self.path(dash_writes_to_stdout: false, global: false, file: nil) else raise "'HOMEBREW_BUNDLE_FILE' cannot be specified with '--global'" if env_bundle_file.present? - if user_config_home - xdg_path = "#{user_config_home}/Brewfile" - legacy_path = Bundle.exchange_uid_if_needed! { "#{Dir.home}/.Brewfile" } - - # Prefer existing file to maintain backwards compatibility - if File.exist?(xdg_path) || !File.exist?(legacy_path) - xdg_path + # Determine if we're in XDG mode by checking if user_config_home is XDG-based + # In bin/brew: XDG_CONFIG_HOME set -> HOMEBREW_USER_CONFIG_HOME="${XDG_CONFIG_HOME}/homebrew" + # XDG_CONFIG_HOME not set -> HOMEBREW_USER_CONFIG_HOME="${HOME}/.homebrew" + using_xdg = user_config_home&.end_with?("/homebrew") + + if using_xdg && user_config_home + # XDG mode: check both XDG and legacy locations, preferring existing files + xdg_brewfile = "#{user_config_home}/Brewfile" + if File.exist?(xdg_brewfile) + xdg_brewfile else - legacy_path + legacy_brewfile = Bundle.exchange_uid_if_needed! { "#{Dir.home}/.Brewfile" } + File.exist?(legacy_brewfile) ? legacy_brewfile : xdg_brewfile end + elsif user_config_home && File.exist?("#{user_config_home}/Brewfile") + "#{user_config_home}/Brewfile" else Bundle.exchange_uid_if_needed! do "#{Dir.home}/.Brewfile" diff --git a/Library/Homebrew/test/bundle/brewfile_spec.rb b/Library/Homebrew/test/bundle/brewfile_spec.rb index 4b0832341827e..279def04b9ac4 100644 --- a/Library/Homebrew/test/bundle/brewfile_spec.rb +++ b/Library/Homebrew/test/bundle/brewfile_spec.rb @@ -26,8 +26,11 @@ allow(ENV).to receive(:fetch).with("HOMEBREW_USER_CONFIG_HOME", any_args) .and_return(env_user_config_home_value) + allow(ENV).to receive(:[]).with("XDG_CONFIG_HOME").and_return(nil) allow(File).to receive(:exist?).with("/Users/username/.homebrew/Brewfile") .and_return(config_dir_brewfile_exist) + # Allow any other File.exist? calls to return false by default + allow(File).to receive(:exist?).and_return(false) end context "when `file` is specified with a relative path" do @@ -175,14 +178,27 @@ context "when HOMEBREW_USER_CONFIG_HOME is set but neither Brewfile exists" do let(:config_dir_brewfile_exist) { false } - before do - # Mock that both XDG and legacy Brewfiles don't exist - allow(File).to receive(:exist?).with("/Users/username/.homebrew/Brewfile").and_return(false) - allow(File).to receive(:exist?).with("#{Dir.home}/.Brewfile").and_return(false) + context "when XDG_CONFIG_HOME is set" do + before do + allow(ENV).to receive(:[]).with("XDG_CONFIG_HOME").and_return("/custom/xdg") + # Mock that both XDG and legacy Brewfiles don't exist + allow(File).to receive(:exist?).with("/Users/username/.homebrew/Brewfile").and_return(false) + allow(File).to receive(:exist?).with("#{Dir.home}/.Brewfile").and_return(false) + end + + it "returns the XDG path for initial Brewfile creation" do + expect(path).to eq(Pathname.new("#{env_user_config_home_value}/Brewfile")) + end end - it "returns the XDG path for initial Brewfile creation" do - expect(path).to eq(Pathname.new("#{env_user_config_home_value}/Brewfile")) + context "when XDG_CONFIG_HOME is not set" do + before do + allow(ENV).to receive(:[]).with("XDG_CONFIG_HOME").and_return(nil) + end + + it "returns the legacy path" do + expect(path).to eq(Pathname.new("#{Dir.home}/.Brewfile")) + end end end end From 890e7ab9a8e5b32fb017c01174ad9020e2cc06b6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Sep 2025 12:58:04 +0000 Subject: [PATCH 5/5] Finalize XDG support with proper backwards compatibility Co-authored-by: MikeMcQuaid <125011+MikeMcQuaid@users.noreply.github.com> --- Library/Homebrew/bundle/brewfile.rb | 2 +- Library/Homebrew/test/bundle/brewfile_spec.rb | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/bundle/brewfile.rb b/Library/Homebrew/bundle/brewfile.rb index 2b139e4900ec4..77354a682835e 100644 --- a/Library/Homebrew/bundle/brewfile.rb +++ b/Library/Homebrew/bundle/brewfile.rb @@ -28,7 +28,7 @@ def self.path(dash_writes_to_stdout: false, global: false, file: nil) # In bin/brew: XDG_CONFIG_HOME set -> HOMEBREW_USER_CONFIG_HOME="${XDG_CONFIG_HOME}/homebrew" # XDG_CONFIG_HOME not set -> HOMEBREW_USER_CONFIG_HOME="${HOME}/.homebrew" using_xdg = user_config_home&.end_with?("/homebrew") - + if using_xdg && user_config_home # XDG mode: check both XDG and legacy locations, preferring existing files xdg_brewfile = "#{user_config_home}/Brewfile" diff --git a/Library/Homebrew/test/bundle/brewfile_spec.rb b/Library/Homebrew/test/bundle/brewfile_spec.rb index 279def04b9ac4..a8bcf75c58a2b 100644 --- a/Library/Homebrew/test/bundle/brewfile_spec.rb +++ b/Library/Homebrew/test/bundle/brewfile_spec.rb @@ -29,8 +29,9 @@ allow(ENV).to receive(:[]).with("XDG_CONFIG_HOME").and_return(nil) allow(File).to receive(:exist?).with("/Users/username/.homebrew/Brewfile") .and_return(config_dir_brewfile_exist) - # Allow any other File.exist? calls to return false by default + # Allow any other File.exist? calls and Dir.home calls for flexibility allow(File).to receive(:exist?).and_return(false) + allow(Dir).to receive(:home).and_return("/Users/username") end context "when `file` is specified with a relative path" do