settings: add module for managing git config settings

This commit is contained in:
Rylan Polster 2021-01-12 16:27:25 -05:00
parent e7b369273a
commit f1f3fdc315
9 changed files with 289 additions and 76 deletions

View File

@ -85,16 +85,14 @@ begin
ENV["PATH"] = path
require "commands"
require "settings"
if cmd
internal_cmd = Commands.valid_internal_cmd?(cmd)
internal_cmd ||= begin
internal_dev_cmd = Commands.valid_internal_dev_cmd?(cmd)
if internal_dev_cmd && !Homebrew::EnvConfig.developer?
if (HOMEBREW_REPOSITORY/".git/config").exist?
system "git", "config", "--file=#{HOMEBREW_REPOSITORY}/.git/config",
"--replace-all", "homebrew.devcmdrun", "true"
end
Settings.write "devcmdrun", true
ENV["HOMEBREW_DEV_CMD_RUN"] = "1"
end
internal_dev_cmd

View File

@ -8,6 +8,7 @@ require "descriptions"
require "cleanup"
require "description_cache_store"
require "cli/parser"
require "settings"
module Homebrew
extend T::Sig
@ -63,16 +64,12 @@ module Homebrew
Utils::Analytics.messages_displayed! if $stdout.tty?
end
HOMEBREW_REPOSITORY.cd do
donation_message_displayed =
Utils.popen_read("git", "config", "--get", "homebrew.donationmessage").chomp == "true"
if !donation_message_displayed && !args.quiet?
ohai "Homebrew is run entirely by unpaid volunteers. Please consider donating:"
puts " #{Formatter.url("https://github.com/Homebrew/brew#donations")}\n"
if Settings.read("donationmessage") != "true" && !args.quiet?
ohai "Homebrew is run entirely by unpaid volunteers. Please consider donating:"
puts " #{Formatter.url("https://github.com/Homebrew/brew#donations")}\n"
# Consider the message possibly missed if not a TTY.
safe_system "git", "config", "--replace-all", "homebrew.donationmessage", "true" if $stdout.tty?
end
# Consider the message possibly missed if not a TTY.
Settings.write "donationmessage", true if $stdout.tty?
end
install_core_tap_if_necessary
@ -89,19 +86,14 @@ module Homebrew
puts "Updated Homebrew from #{shorten_revision(initial_revision)} to #{shorten_revision(current_revision)}."
updated = true
old_tag = if (HOMEBREW_REPOSITORY/".git/config").exist?
Utils.popen_read(
"git", "config", "--file=#{HOMEBREW_REPOSITORY}/.git/config", "--get", "homebrew.latesttag"
).chomp.presence
end
old_tag = Settings.read "latesttag"
new_tag = Utils.popen_read(
"git", "-C", HOMEBREW_REPOSITORY, "tag", "--list", "--sort=-version:refname", "*.*"
).lines.first.chomp
if new_tag != old_tag
system "git", "config", "--file=#{HOMEBREW_REPOSITORY}/.git/config",
"--replace-all", "homebrew.latesttag", new_tag
Settings.write "latesttag", new_tag
new_repository_version = new_tag
end
end

View File

@ -2,6 +2,7 @@
# frozen_string_literal: true
require "utils/link"
require "settings"
# Helper functions for generating shell completions.
#
@ -13,7 +14,7 @@ module Completions
sig { void }
def link!
write_completions_option "yes"
Settings.write :linkcompletions, true
Tap.each do |tap|
Utils::Link.link_completions tap.path, "brew completions link"
end
@ -21,7 +22,7 @@ module Completions
sig { void }
def unlink!
write_completions_option "no"
Settings.write :linkcompletions, false
Tap.each do |tap|
next if tap.official?
@ -31,7 +32,7 @@ module Completions
sig { returns(T::Boolean) }
def link_completions?
read_completions_option == "yes"
Settings.read(:linkcompletions) == "true"
end
sig { returns(T::Boolean) }
@ -48,23 +49,9 @@ module Completions
false
end
sig { params(option: String).returns(String) }
def read_completions_option(option: "linkcompletions")
HOMEBREW_REPOSITORY.cd do
Utils.popen_read("git", "config", "--get", "homebrew.#{option}").chomp
end
end
sig { params(state: String, option: String).void }
def write_completions_option(state, option: "linkcompletions")
HOMEBREW_REPOSITORY.cd do
T.unsafe(self).safe_system "git", "config", "--replace-all", "homebrew.#{option}", state.to_s
end
end
sig { void }
def show_completions_message_if_needed
return if read_completions_option(option: "completionsmessageshown") == "yes"
return if Settings.read(:completionsmessageshown) == "true"
return unless completions_to_link?
T.unsafe(self).ohai "Homebrew completions for external commands are unlinked by default!"
@ -74,6 +61,6 @@ module Completions
Then, follow the directions at #{Formatter.url("https://docs.brew.sh/Shell-Completion")}
EOS
write_completions_option("yes", option: "completionsmessageshown")
Settings.write :completionsmessageshown, true
end
end

View File

@ -0,0 +1,39 @@
# typed: true
# frozen_string_literal: true
# Helper functions for reading and writing settings.
#
# @api private
module Settings
extend T::Sig
module_function
sig { params(setting: T.any(String, Symbol), repo: Pathname).returns(T.nilable(String)) }
def read(setting, repo: HOMEBREW_REPOSITORY)
return unless (repo/".git/config").exist?
repo.cd do
Utils.popen_read("git", "config", "--get", "homebrew.#{setting}").chomp.presence
end
end
sig { params(setting: T.any(String, Symbol), value: T.any(String, T::Boolean), repo: Pathname).void }
def write(setting, value, repo: HOMEBREW_REPOSITORY)
return unless (repo/".git/config").exist?
repo.cd do
T.unsafe(self).safe_system "git", "config", "--replace-all", "homebrew.#{setting}", value.to_s
end
end
sig { params(setting: T.any(String, Symbol), repo: Pathname).void }
def delete(setting, repo: HOMEBREW_REPOSITORY)
return unless (repo/".git/config").exist?
return if read(setting, repo: repo).blank?
repo.cd do
T.unsafe(self).safe_system "git", "config", "--unset-all", "homebrew.#{setting}"
end
end
end

View File

@ -5,6 +5,7 @@ require "commands"
require "completions"
require "extend/cachable"
require "description_cache_store"
require "settings"
# A {Tap} is used to extend the formulae provided by Homebrew core.
# Usually, it's synced with a remote Git repository. And it's likely
@ -821,18 +822,14 @@ class TapConfig
return unless tap.git?
return unless Utils::Git.available?
tap.path.cd do
Utils.popen_read("git", "config", "--get", "homebrew.#{key}").chomp.presence
end
Settings.read key, repo: tap.path
end
def []=(key, value)
return unless tap.git?
return unless Utils::Git.available?
tap.path.cd do
safe_system "git", "config", "--replace-all", "homebrew.#{key}", value.to_s
end
Settings.write key, value.to_s, repo: tap.path
end
end

View File

@ -0,0 +1,143 @@
# typed: false
# frozen_string_literal: true
require "completions"
describe Completions do
let(:internal_path) { HOMEBREW_REPOSITORY/"Library/Taps/homebrew/homebrew-bar" }
let(:external_path) { HOMEBREW_REPOSITORY/"Library/Taps/foo/homebrew-bar" }
before do
HOMEBREW_REPOSITORY.cd do
system "git", "init"
end
internal_path.mkpath
external_path.mkpath
end
def setup_completions(external:)
(internal_path/"completions/bash/foo_internal").write "#foo completions"
if external
(external_path/"completions/bash/foo_external").write "#foo completions"
elsif (external_path/"completions/bash/foo_external").exist?
(external_path/"completions/bash/foo_external").delete
end
end
def setup_completions_setting(state, setting: "linkcompletions")
HOMEBREW_REPOSITORY.cd do
system "git", "config", "--replace-all", "homebrew.#{setting}", state.to_s
end
end
def read_completions_setting(setting: "linkcompletions")
HOMEBREW_REPOSITORY.cd do
Utils.popen_read("git", "config", "--get", "homebrew.#{setting}").chomp.presence
end
end
def delete_completions_setting(setting: "linkcompletions")
HOMEBREW_REPOSITORY.cd do
system "git", "config", "--unset-all", "homebrew.#{setting}"
end
end
after do
FileUtils.rm_rf internal_path
FileUtils.rm_rf external_path.dirname
end
describe ".link!" do
it "sets homebrew.linkcompletions to true" do
setup_completions_setting false
expect { described_class.link! }.not_to raise_error
expect(read_completions_setting).to eq "true"
end
it "sets homebrew.linkcompletions to true if unset" do
delete_completions_setting
expect { described_class.link! }.not_to raise_error
expect(read_completions_setting).to eq "true"
end
it "keeps homebrew.linkcompletions set to true" do
setup_completions_setting true
expect { described_class.link! }.not_to raise_error
expect(read_completions_setting).to eq "true"
end
end
describe ".unlink!" do
it "sets homebrew.linkcompletions to false" do
setup_completions_setting true
expect { described_class.unlink! }.not_to raise_error
expect(read_completions_setting).to eq "false"
end
it "sets homebrew.linkcompletions to false if unset" do
delete_completions_setting
expect { described_class.unlink! }.not_to raise_error
expect(read_completions_setting).to eq "false"
end
it "keeps homebrew.linkcompletions set to false" do
setup_completions_setting false
expect { described_class.unlink! }.not_to raise_error
expect(read_completions_setting).to eq "false"
end
end
describe ".link_completions?" do
it "returns true if homebrew.linkcompletions is true" do
setup_completions_setting true
expect(described_class.link_completions?).to be true
end
it "returns false if homebrew.linkcompletions is false" do
setup_completions_setting false
expect(described_class.link_completions?).to be false
end
it "returns false if homebrew.linkcompletions is not set" do
expect(described_class.link_completions?).to be false
end
end
describe ".completions_to_link?" do
it "returns false if only internal taps have completions" do
setup_completions external: false
expect(described_class.completions_to_link?).to be false
end
it "returns true if external taps have completions" do
setup_completions external: true
expect(described_class.completions_to_link?).to be true
end
end
describe ".show_completions_message_if_needed" do
it "doesn't show the message if there are no completions to link" do
setup_completions external: false
delete_completions_setting setting: :completionsmessageshown
expect { described_class.show_completions_message_if_needed }.not_to output.to_stdout
end
it "doesn't show the message if there are completions to link but the message has already been shown" do
setup_completions external: true
setup_completions_setting true, setting: :completionsmessageshown
expect { described_class.show_completions_message_if_needed }.not_to output.to_stdout
end
it "shows the message if there are completions to link and the message hasn't already been shown" do
setup_completions external: true
delete_completions_setting setting: :completionsmessageshown
# This will fail because the method calls `puts`.
# If we output the `ohai` andcatch the error, we can be usre that the message is showing.
error_message = "private method `puts' called for Completions:Module"
expect { described_class.show_completions_message_if_needed }
.to output.to_stdout
.and raise_error(NoMethodError, error_message)
end
end
end

View File

@ -0,0 +1,74 @@
# typed: false
# frozen_string_literal: true
require "settings"
describe Settings do
before do
HOMEBREW_REPOSITORY.cd do
system "git", "init"
end
end
def setup_setting
HOMEBREW_REPOSITORY.cd do
system "git", "config", "--replace-all", "homebrew.foo", "true"
end
end
describe ".read" do
it "returns the correct value for a setting" do
setup_setting
expect(described_class.read("foo")).to eq "true"
end
it "returns the correct value for a setting as a symbol" do
setup_setting
expect(described_class.read(:foo)).to eq "true"
end
it "returns nil when setting is not set" do
setup_setting
expect(described_class.read("bar")).to be_nil
end
it "runs on a repo without a configuration file" do
expect { described_class.read("foo", repo: HOMEBREW_REPOSITORY/"bar") }.not_to raise_error
end
end
describe ".write" do
it "writes over an existing value" do
setup_setting
described_class.write :foo, false
expect(described_class.read("foo")).to eq "false"
end
it "writes a new value" do
setup_setting
described_class.write :bar, "abcde"
expect(described_class.read("bar")).to eq "abcde"
end
it "returns if the repo doesn't have a configuration file" do
expect { described_class.write("foo", repo: HOMEBREW_REPOSITORY/"bar") }.not_to raise_error
end
end
describe ".delete" do
it "deletes an existing setting" do
setup_setting
described_class.delete(:foo)
expect(described_class.read("foo")).to be_nil
end
it "deletes a non-existing setting" do
setup_setting
expect { described_class.delete(:bar) }.not_to raise_error
end
it "returns if the repo doesn't have a configuration file" do
expect { described_class.delete("foo", repo: HOMEBREW_REPOSITORY/"bar") }.not_to raise_error
end
end
end

View File

@ -87,8 +87,8 @@ describe Tap do
def setup_completion(link:)
HOMEBREW_REPOSITORY.cd do
system "git", "init"
system "git", "config", "--replace-all", "homebrew.linkcompletions", link
system "git", "config", "--replace-all", "homebrew.completionsmessageshown", "yes"
system "git", "config", "--replace-all", "homebrew.linkcompletions", link.to_s
system "git", "config", "--replace-all", "homebrew.completionsmessageshown", "true"
end
end
@ -293,7 +293,7 @@ describe Tap do
specify "#install and #uninstall" do
setup_tap_files
setup_git_repo
setup_completion link: "yes"
setup_completion link: true
tap = described_class.new("Homebrew", "bar")
@ -320,7 +320,7 @@ describe Tap do
specify "#link_completions_and_manpages when completions are enabled for non-official tap" do
setup_tap_files
setup_git_repo
setup_completion link: "yes"
setup_completion link: true
tap = described_class.new("NotHomebrew", "baz")
tap.install clone_target: subject.path/".git"
(HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").delete
@ -341,7 +341,7 @@ describe Tap do
specify "#link_completions_and_manpages when completions are disabled for non-official tap" do
setup_tap_files
setup_git_repo
setup_completion link: "no"
setup_completion link: false
tap = described_class.new("NotHomebrew", "baz")
tap.install clone_target: subject.path/".git"
(HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").delete
@ -359,7 +359,7 @@ describe Tap do
specify "#link_completions_and_manpages when completions are enabled for official tap" do
setup_tap_files
setup_git_repo
setup_completion link: "no"
setup_completion link: false
tap = described_class.new("Homebrew", "baz")
tap.install clone_target: subject.path/".git"
(HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").delete

View File

@ -3,6 +3,7 @@
require "context"
require "erb"
require "settings"
module Utils
# Helper module for fetching and reporting analytics data.
@ -102,27 +103,27 @@ module Utils
end
def uuid
config_get(:analyticsuuid)
Settings.read :analyticsuuid
end
def messages_displayed!
config_set(:analyticsmessage, true)
config_set(:caskanalyticsmessage, true)
Settings.write :analyticsmessage, true
Settings.write :caskanalyticsmessage, true
end
def enable!
config_set(:analyticsdisabled, false)
Settings.write :analyticsdisabled, false
messages_displayed!
end
def disable!
config_set(:analyticsdisabled, true)
Settings.write :analyticsdisabled, true
regenerate_uuid!
end
def regenerate_uuid!
# it will be regenerated in next run unless disabled.
config_delete(:analyticsuuid)
Settings.delete :analyticsuuid
end
def output(args:, filter: nil)
@ -313,25 +314,7 @@ module Utils
end
def config_true?(key)
config_get(key) == "true"
end
def config_get(key)
HOMEBREW_REPOSITORY.cd do
Utils.popen_read("git", "config", "--get", "homebrew.#{key}").chomp
end
end
def config_set(key, value)
HOMEBREW_REPOSITORY.cd do
safe_system "git", "config", "--replace-all", "homebrew.#{key}", value.to_s
end
end
def config_delete(key)
HOMEBREW_REPOSITORY.cd do
system "git", "config", "--unset-all", "homebrew.#{key}"
end
Settings.read(key) == "true"
end
def formulae_brew_sh_json(endpoint)