Merge branch 'master' into no-ostruct
This commit is contained in:
commit
69f2d3bf32
3
.github/workflows/actionlint.yml
vendored
3
.github/workflows/actionlint.yml
vendored
@ -2,8 +2,6 @@ name: actionlint
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths:
|
paths:
|
||||||
- '.github/workflows/*.ya?ml'
|
- '.github/workflows/*.ya?ml'
|
||||||
- '.github/actionlint.yaml'
|
- '.github/actionlint.yaml'
|
||||||
@ -11,7 +9,6 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- '.github/workflows/*.ya?ml'
|
- '.github/workflows/*.ya?ml'
|
||||||
- '.github/actionlint.yaml'
|
- '.github/actionlint.yaml'
|
||||||
merge_group:
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
HOMEBREW_DEVELOPER: 1
|
HOMEBREW_DEVELOPER: 1
|
||||||
|
|||||||
5
.github/workflows/docker.yml
vendored
5
.github/workflows/docker.yml
vendored
@ -2,9 +2,6 @@ name: Docker
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
merge_group:
|
merge_group:
|
||||||
release:
|
release:
|
||||||
types:
|
types:
|
||||||
@ -75,7 +72,7 @@ jobs:
|
|||||||
"homebrew/brew:latest"
|
"homebrew/brew:latest"
|
||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
elif [[ "${GITHUB_EVENT_NAME}" == "push" &&
|
elif [[ "${GITHUB_EVENT_NAME}" == "merge_group" &&
|
||||||
"${GITHUB_REF}" == "refs/heads/master" &&
|
"${GITHUB_REF}" == "refs/heads/master" &&
|
||||||
"${{ matrix.version }}" == "22.04" ]]; then
|
"${{ matrix.version }}" == "22.04" ]]; then
|
||||||
tags+=(
|
tags+=(
|
||||||
|
|||||||
3
.github/workflows/docs.yml
vendored
3
.github/workflows/docs.yml
vendored
@ -1,9 +1,6 @@
|
|||||||
name: Documentation CI
|
name: Documentation CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
pull_request:
|
||||||
merge_group:
|
merge_group:
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/pkg-installer.yml
vendored
2
.github/workflows/pkg-installer.yml
vendored
@ -133,7 +133,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Generate build provenance
|
- name: Generate build provenance
|
||||||
uses: actions/attest-build-provenance@c4fbc648846ca6f503a13a2281a5e7b98aa57202 # v2.0.1
|
uses: actions/attest-build-provenance@7668571508540a607bdfd90a87a560489fe372eb # v2.1.0
|
||||||
with:
|
with:
|
||||||
subject-path: Homebrew-${{ steps.homebrew-version.outputs.version }}.pkg
|
subject-path: Homebrew-${{ steps.homebrew-version.outputs.version }}.pkg
|
||||||
|
|
||||||
|
|||||||
3
.github/workflows/tests.yml
vendored
3
.github/workflows/tests.yml
vendored
@ -1,9 +1,6 @@
|
|||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
pull_request:
|
||||||
merge_group:
|
merge_group:
|
||||||
|
|
||||||
|
|||||||
@ -468,9 +468,7 @@ module Cask
|
|||||||
trashed = trashed.split(":")
|
trashed = trashed.split(":")
|
||||||
untrashable = untrashable.split(":")
|
untrashable = untrashable.split(":")
|
||||||
|
|
||||||
return trashed, untrashable if untrashable.empty?
|
trashed_with_permissions, untrashable = untrashable.partition do |path|
|
||||||
|
|
||||||
untrashable.delete_if do |path|
|
|
||||||
Utils.gain_permissions(path, ["-R"], SystemCommand) do
|
Utils.gain_permissions(path, ["-R"], SystemCommand) do
|
||||||
system_command! HOMEBREW_LIBRARY_PATH/"cask/utils/trash.swift",
|
system_command! HOMEBREW_LIBRARY_PATH/"cask/utils/trash.swift",
|
||||||
args: [path],
|
args: [path],
|
||||||
@ -482,6 +480,10 @@ module Cask
|
|||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
trashed += trashed_with_permissions
|
||||||
|
|
||||||
|
return trashed, untrashable if untrashable.empty?
|
||||||
|
|
||||||
opoo "The following files could not be trashed, please do so manually:"
|
opoo "The following files could not be trashed, please do so manually:"
|
||||||
$stderr.puts untrashable
|
$stderr.puts untrashable
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
require "abstract_command"
|
require "abstract_command"
|
||||||
require "fileutils"
|
require "fileutils"
|
||||||
require "tap"
|
require "tap"
|
||||||
|
require "utils/uid"
|
||||||
|
|
||||||
module Homebrew
|
module Homebrew
|
||||||
module DevCmd
|
module DevCmd
|
||||||
@ -172,16 +173,32 @@ module Homebrew
|
|||||||
write_path(tap, ".github/workflows/publish.yml", actions_publish)
|
write_path(tap, ".github/workflows/publish.yml", actions_publish)
|
||||||
|
|
||||||
unless args.no_git?
|
unless args.no_git?
|
||||||
cd tap.path do
|
cd tap.path do |path|
|
||||||
Utils::Git.set_name_email!
|
Utils::Git.set_name_email!
|
||||||
Utils::Git.setup_gpg!
|
Utils::Git.setup_gpg!
|
||||||
|
|
||||||
# Would be nice to use --initial-branch here but it's not available in
|
# Would be nice to use --initial-branch here but it's not available in
|
||||||
# older versions of Git that we support.
|
# older versions of Git that we support.
|
||||||
safe_system "git", "-c", "init.defaultBranch=#{branch}", "init"
|
safe_system "git", "-c", "init.defaultBranch=#{branch}", "init"
|
||||||
safe_system "git", "add", "--all"
|
|
||||||
safe_system "git", "commit", "-m", "Create #{tap} tap"
|
args = []
|
||||||
safe_system "git", "branch", "-m", branch
|
git_owner = File.stat(File.join(path, ".git")).uid
|
||||||
|
if git_owner != Process.uid && git_owner == Process.euid
|
||||||
|
# Under Homebrew user model, EUID is permitted to execute commands under the UID.
|
||||||
|
# Root users are never allowed (see brew.sh).
|
||||||
|
args << "-c" << "safe.directory=#{path}"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Use the configuration of the original user, which will have author information and signing keys.
|
||||||
|
Utils::UID.drop_euid do
|
||||||
|
env = { HOME: Utils::UID.uid_home }.compact
|
||||||
|
env[:TMPDIR] = nil if (tmpdir = ENV.fetch("TMPDIR", nil)) && !File.writable?(tmpdir)
|
||||||
|
with_env(env) do
|
||||||
|
safe_system "git", *args, "add", "--all"
|
||||||
|
safe_system "git", *args, "commit", "-m", "Create #{tap} tap"
|
||||||
|
safe_system "git", *args, "branch", "-m", branch
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -2005,6 +2005,8 @@ class Formula
|
|||||||
# If called with no parameters, does this with all compatible
|
# If called with no parameters, does this with all compatible
|
||||||
# universal binaries in a {Formula}'s {Keg}.
|
# universal binaries in a {Formula}'s {Keg}.
|
||||||
#
|
#
|
||||||
|
# Raises an error if no universal binaries are found to deuniversalize.
|
||||||
|
#
|
||||||
# @api public
|
# @api public
|
||||||
sig { params(targets: T.nilable(T.any(Pathname, String))).void }
|
sig { params(targets: T.nilable(T.any(Pathname, String))).void }
|
||||||
def deuniversalize_machos(*targets)
|
def deuniversalize_machos(*targets)
|
||||||
@ -2014,6 +2016,8 @@ class Formula
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
raise "No universal binaries found to deuniversalize" if targets.blank?
|
||||||
|
|
||||||
targets&.each do |target|
|
targets&.each do |target|
|
||||||
extract_macho_slice_from(Pathname(target), Hardware::CPU.arch)
|
extract_macho_slice_from(Pathname(target), Hardware::CPU.arch)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -58,8 +58,10 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Parses JSON text and identifies versions using a `strategy` block.
|
# Parses JSON text and identifies versions using a `strategy` block.
|
||||||
# If a regex is provided, it will be passed as the second argument to
|
# If the block has two parameters, the parsed JSON data will be used as
|
||||||
# the `strategy` block (after the parsed JSON data).
|
# the first argument and the regex (if any) will be the second.
|
||||||
|
# Otherwise, only the parsed JSON data will be passed to the block.
|
||||||
|
#
|
||||||
# @param content [String] the JSON text to parse and check
|
# @param content [String] the JSON text to parse and check
|
||||||
# @param regex [Regexp, nil] a regex used for matching versions in the
|
# @param regex [Regexp, nil] a regex used for matching versions in the
|
||||||
# content
|
# content
|
||||||
@ -77,10 +79,8 @@ module Homebrew
|
|||||||
json = parse_json(content)
|
json = parse_json(content)
|
||||||
return [] if json.blank?
|
return [] if json.blank?
|
||||||
|
|
||||||
block_return_value = if regex.present?
|
block_return_value = if block.arity == 2
|
||||||
yield(json, regex)
|
yield(json, regex)
|
||||||
elsif block.arity == 2
|
|
||||||
raise "Two arguments found in `strategy` block but no regex provided."
|
|
||||||
else
|
else
|
||||||
yield(json)
|
yield(json)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -20,10 +20,14 @@ module Homebrew
|
|||||||
|
|
||||||
# The default `strategy` block used to extract version information when
|
# The default `strategy` block used to extract version information when
|
||||||
# a `strategy` block isn't provided.
|
# a `strategy` block isn't provided.
|
||||||
DEFAULT_BLOCK = T.let(proc do |json|
|
DEFAULT_BLOCK = T.let(proc do |json, regex|
|
||||||
json.dig("info", "version").presence
|
version = json.dig("info", "version")
|
||||||
|
next if version.blank?
|
||||||
|
|
||||||
|
regex ? version[regex, 1] : version
|
||||||
end.freeze, T.proc.params(
|
end.freeze, T.proc.params(
|
||||||
arg0: T::Hash[String, T.untyped],
|
json: T::Hash[String, T.untyped],
|
||||||
|
regex: T.nilable(Regexp),
|
||||||
).returns(T.nilable(String)))
|
).returns(T.nilable(String)))
|
||||||
|
|
||||||
# The `Regexp` used to extract the package name and suffix (e.g. file
|
# The `Regexp` used to extract the package name and suffix (e.g. file
|
||||||
|
|||||||
@ -107,11 +107,6 @@ RSpec.describe Homebrew::Livecheck::Strategy::Json do
|
|||||||
expect(json.versions_from_content(content_simple, regex) { next }).to eq([])
|
expect(json.versions_from_content(content_simple, regex) { next }).to eq([])
|
||||||
end
|
end
|
||||||
|
|
||||||
it "errors if a block uses two arguments but a regex is not given" do
|
|
||||||
expect { json.versions_from_content(content_simple) { |json, regex| json["version"][regex, 1] } }
|
|
||||||
.to raise_error("Two arguments found in `strategy` block but no regex provided.")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "errors on an invalid return type from a block" do
|
it "errors on an invalid return type from a block" do
|
||||||
expect { json.versions_from_content(content_simple, regex) { 123 } }
|
expect { json.versions_from_content(content_simple, regex) { 123 } }
|
||||||
.to raise_error(TypeError, Homebrew::Livecheck::Strategy::INVALID_BLOCK_RETURN_VALUE_MSG)
|
.to raise_error(TypeError, Homebrew::Livecheck::Strategy::INVALID_BLOCK_RETURN_VALUE_MSG)
|
||||||
|
|||||||
@ -8,7 +8,7 @@ RSpec.describe Homebrew::Livecheck::Strategy::Pypi do
|
|||||||
let(:pypi_url) { "https://files.pythonhosted.org/packages/ab/cd/efg/example-package-1.2.3.tar.gz" }
|
let(:pypi_url) { "https://files.pythonhosted.org/packages/ab/cd/efg/example-package-1.2.3.tar.gz" }
|
||||||
let(:non_pypi_url) { "https://brew.sh/test" }
|
let(:non_pypi_url) { "https://brew.sh/test" }
|
||||||
|
|
||||||
let(:regex) { /^v?(\d+(?:\.\d+)+)$/i }
|
let(:regex) { /^v?(\d+(?:\.\d+)+)/i }
|
||||||
|
|
||||||
let(:generated) do
|
let(:generated) do
|
||||||
{
|
{
|
||||||
@ -17,25 +17,26 @@ RSpec.describe Homebrew::Livecheck::Strategy::Pypi do
|
|||||||
end
|
end
|
||||||
|
|
||||||
# This is a limited subset of a PyPI JSON API response object, for the sake
|
# This is a limited subset of a PyPI JSON API response object, for the sake
|
||||||
# of testing.
|
# of testing. Typical versions use a `1.2.3` format but this adds a suffix,
|
||||||
|
# so we can test regex matching.
|
||||||
let(:content) do
|
let(:content) do
|
||||||
<<~JSON
|
<<~JSON
|
||||||
{
|
{
|
||||||
"info": {
|
"info": {
|
||||||
"version": "1.2.3"
|
"version": "1.2.3-456"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JSON
|
JSON
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:matches) { ["1.2.3"] }
|
let(:matches) { ["1.2.3-456"] }
|
||||||
|
|
||||||
let(:find_versions_return_hash) do
|
let(:find_versions_return_hash) do
|
||||||
{
|
{
|
||||||
matches: {
|
matches: {
|
||||||
"1.2.3" => Version.new("1.2.3"),
|
"1.2.3-456" => Version.new("1.2.3-456"),
|
||||||
},
|
},
|
||||||
regex: nil,
|
regex:,
|
||||||
url: generated[:url],
|
url: generated[:url],
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@ -76,10 +77,17 @@ RSpec.describe Homebrew::Livecheck::Strategy::Pypi do
|
|||||||
{
|
{
|
||||||
cached:,
|
cached:,
|
||||||
cached_default: cached.merge({ matches: {} }),
|
cached_default: cached.merge({ matches: {} }),
|
||||||
|
cached_regex: cached.merge({
|
||||||
|
matches: { "1.2.3" => Version.new("1.2.3") },
|
||||||
|
regex:,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
it "finds versions in provided content" do
|
it "finds versions in provided content" do
|
||||||
|
expect(pypi.find_versions(url: pypi_url, regex:, provided_content: content))
|
||||||
|
.to eq(match_data[:cached_regex])
|
||||||
|
|
||||||
expect(pypi.find_versions(url: pypi_url, provided_content: content))
|
expect(pypi.find_versions(url: pypi_url, provided_content: content))
|
||||||
.to eq(match_data[:cached])
|
.to eq(match_data[:cached])
|
||||||
end
|
end
|
||||||
@ -92,7 +100,7 @@ RSpec.describe Homebrew::Livecheck::Strategy::Pypi do
|
|||||||
next if match.blank?
|
next if match.blank?
|
||||||
|
|
||||||
match[1]
|
match[1]
|
||||||
end).to eq(match_data[:cached].merge({ regex: }))
|
end).to eq(match_data[:cached_regex])
|
||||||
|
|
||||||
expect(pypi.find_versions(url: pypi_url, provided_content: content) do |json|
|
expect(pypi.find_versions(url: pypi_url, provided_content: content) do |json|
|
||||||
json.dig("info", "version").presence
|
json.dig("info", "version").presence
|
||||||
@ -100,10 +108,14 @@ RSpec.describe Homebrew::Livecheck::Strategy::Pypi do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "returns default match_data when block doesn't return version information" do
|
it "returns default match_data when block doesn't return version information" do
|
||||||
|
no_match_regex = /will_not_match/i
|
||||||
|
|
||||||
expect(pypi.find_versions(url: pypi_url, provided_content: '{"info":{"version":""}}'))
|
expect(pypi.find_versions(url: pypi_url, provided_content: '{"info":{"version":""}}'))
|
||||||
.to eq(match_data[:cached_default])
|
.to eq(match_data[:cached_default])
|
||||||
expect(pypi.find_versions(url: pypi_url, provided_content: '{"other":true}'))
|
expect(pypi.find_versions(url: pypi_url, provided_content: '{"other":true}'))
|
||||||
.to eq(match_data[:cached_default])
|
.to eq(match_data[:cached_default])
|
||||||
|
expect(pypi.find_versions(url: pypi_url, regex: no_match_regex, provided_content: content))
|
||||||
|
.to eq(match_data[:cached_default].merge({ regex: no_match_regex }))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns default match_data when url is blank" do
|
it "returns default match_data when url is blank" do
|
||||||
|
|||||||
@ -135,15 +135,6 @@ module GitHub
|
|||||||
JSON::ParserError,
|
JSON::ParserError,
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
sig { returns(T.nilable(String)) }
|
|
||||||
private_class_method def self.uid_home
|
|
||||||
require "etc"
|
|
||||||
Etc.getpwuid(Process.uid)&.dir
|
|
||||||
rescue ArgumentError
|
|
||||||
# Cover for misconfigured NSS setups
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
# Gets the token from the GitHub CLI for github.com.
|
# Gets the token from the GitHub CLI for github.com.
|
||||||
sig { returns(T.nilable(String)) }
|
sig { returns(T.nilable(String)) }
|
||||||
def self.github_cli_token
|
def self.github_cli_token
|
||||||
@ -152,7 +143,7 @@ module GitHub
|
|||||||
# Avoid `Formula["gh"].opt_bin` so this method works even with `HOMEBREW_DISABLE_LOAD_FORMULA`.
|
# Avoid `Formula["gh"].opt_bin` so this method works even with `HOMEBREW_DISABLE_LOAD_FORMULA`.
|
||||||
env = {
|
env = {
|
||||||
"PATH" => PATH.new(HOMEBREW_PREFIX/"opt/gh/bin", ENV.fetch("PATH")),
|
"PATH" => PATH.new(HOMEBREW_PREFIX/"opt/gh/bin", ENV.fetch("PATH")),
|
||||||
"HOME" => uid_home,
|
"HOME" => Utils::UID.uid_home,
|
||||||
}.compact
|
}.compact
|
||||||
gh_out, _, result = system_command "gh",
|
gh_out, _, result = system_command "gh",
|
||||||
args: ["auth", "token", "--hostname", "github.com"],
|
args: ["auth", "token", "--hostname", "github.com"],
|
||||||
@ -173,7 +164,7 @@ module GitHub
|
|||||||
git_credential_out, _, result = system_command "git",
|
git_credential_out, _, result = system_command "git",
|
||||||
args: ["credential-osxkeychain", "get"],
|
args: ["credential-osxkeychain", "get"],
|
||||||
input: ["protocol=https\n", "host=github.com\n"],
|
input: ["protocol=https\n", "host=github.com\n"],
|
||||||
env: { "HOME" => uid_home }.compact,
|
env: { "HOME" => Utils::UID.uid_home }.compact,
|
||||||
print_stderr: false
|
print_stderr: false
|
||||||
return unless result.success?
|
return unless result.success?
|
||||||
|
|
||||||
|
|||||||
@ -15,5 +15,14 @@ module Utils
|
|||||||
Process::Sys.seteuid(original_euid)
|
Process::Sys.seteuid(original_euid)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(String)) }
|
||||||
|
def self.uid_home
|
||||||
|
require "etc"
|
||||||
|
Etc.getpwuid(Process.uid)&.dir
|
||||||
|
rescue ArgumentError
|
||||||
|
# Cover for misconfigured NSS setups
|
||||||
|
nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user