Merge remote-tracking branch 'origin/master' into deprecate-method-formulae
This commit is contained in:
commit
4121659413
31
.github/workflows/tests.yml
vendored
31
.github/workflows/tests.yml
vendored
@ -3,6 +3,9 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches: master
|
branches: master
|
||||||
pull_request: []
|
pull_request: []
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
jobs:
|
jobs:
|
||||||
tests:
|
tests:
|
||||||
if: github.repository == 'Homebrew/brew'
|
if: github.repository == 'Homebrew/brew'
|
||||||
@ -78,6 +81,12 @@ jobs:
|
|||||||
sudo chmod -R g-w,o-w /home/linuxbrew /home/runner /opt
|
sudo chmod -R g-w,o-w /home/linuxbrew /home/runner /opt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
- name: Run brew style
|
||||||
|
run: brew style --display-cop-names
|
||||||
|
|
||||||
|
- name: Run brew man
|
||||||
|
run: brew man --fail-if-changed
|
||||||
|
|
||||||
- name: Run brew tests
|
- name: Run brew tests
|
||||||
run: |
|
run: |
|
||||||
# brew tests doesn't like world writable directories
|
# brew tests doesn't like world writable directories
|
||||||
@ -107,12 +116,6 @@ jobs:
|
|||||||
# These cannot be queried at the macOS level on GitHub Actions.
|
# These cannot be queried at the macOS level on GitHub Actions.
|
||||||
HOMEBREW_LANGUAGES: en-GB
|
HOMEBREW_LANGUAGES: en-GB
|
||||||
|
|
||||||
- name: Run brew style
|
|
||||||
run: brew style --display-cop-names
|
|
||||||
|
|
||||||
- name: Run brew man
|
|
||||||
run: brew man --fail-if-changed
|
|
||||||
|
|
||||||
- name: Run brew update-tests
|
- name: Run brew update-tests
|
||||||
run: |
|
run: |
|
||||||
git config --global user.name "BrewTestBot"
|
git config --global user.name "BrewTestBot"
|
||||||
@ -140,6 +143,22 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
if [ "$RUNNER_OS" = "Linux" ]; then
|
if [ "$RUNNER_OS" = "Linux" ]; then
|
||||||
docker-compose -f Dockerfile.yml run --rm -v $GITHUB_WORKSPACE:/tmp/test-bot sut
|
docker-compose -f Dockerfile.yml run --rm -v $GITHUB_WORKSPACE:/tmp/test-bot sut
|
||||||
|
docker tag homebrew_sut brew
|
||||||
else
|
else
|
||||||
brew test-bot
|
brew test-bot
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
- name: Deploy the latest Docker image
|
||||||
|
if: matrix.os == 'ubuntu-latest' && github.ref == 'refs/heads/master'
|
||||||
|
run: |
|
||||||
|
docker login docker.pkg.github.com -u BrewTestBot -p ${{secrets.GITHUB_TOKEN}}
|
||||||
|
docker tag brew docker.pkg.github.com/homebrew/brew/brew
|
||||||
|
docker push docker.pkg.github.com/homebrew/brew/brew
|
||||||
|
|
||||||
|
- name: Deploy the tagged Docker image
|
||||||
|
if: matrix.os == 'ubuntu-latest' && startsWith(github.ref, 'refs/tags/')
|
||||||
|
run: |
|
||||||
|
docker login docker.pkg.github.com -u BrewTestBot -p ${{secrets.GITHUB_TOKEN}}
|
||||||
|
v=${GITHUB_REF:10}
|
||||||
|
docker tag brew "docker.pkg.github.com/homebrew/brew/brew:$v"
|
||||||
|
docker push "docker.pkg.github.com/homebrew/brew/brew:$v"
|
||||||
|
|||||||
@ -2,7 +2,9 @@ inherit_from: ./.rubocop.yml
|
|||||||
|
|
||||||
AllCops:
|
AllCops:
|
||||||
Include:
|
Include:
|
||||||
- '**/*_spec.rb'
|
- '**/cmd/**/*.rb'
|
||||||
|
- '**/lib/**/*.rb'
|
||||||
|
- '**/spec/**/*.rb'
|
||||||
Exclude:
|
Exclude:
|
||||||
- '**/vendor/**/*'
|
- '**/vendor/**/*'
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
activesupport (6.0.2.1)
|
activesupport (6.0.2.2)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
minitest (~> 5.1)
|
minitest (~> 5.1)
|
||||||
@ -51,7 +51,7 @@ GEM
|
|||||||
parallel (1.19.1)
|
parallel (1.19.1)
|
||||||
parallel_tests (2.32.0)
|
parallel_tests (2.32.0)
|
||||||
parallel
|
parallel
|
||||||
parser (2.7.0.4)
|
parser (2.7.0.5)
|
||||||
ast (~> 2.4.0)
|
ast (~> 2.4.0)
|
||||||
plist (3.5.0)
|
plist (3.5.0)
|
||||||
rainbow (3.0.0)
|
rainbow (3.0.0)
|
||||||
@ -81,14 +81,14 @@ GEM
|
|||||||
rspec-support (3.9.2)
|
rspec-support (3.9.2)
|
||||||
rspec-wait (0.0.9)
|
rspec-wait (0.0.9)
|
||||||
rspec (>= 3, < 4)
|
rspec (>= 3, < 4)
|
||||||
rubocop (0.80.1)
|
rubocop (0.81.0)
|
||||||
jaro_winkler (~> 1.5.1)
|
jaro_winkler (~> 1.5.1)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
parser (>= 2.7.0.1)
|
parser (>= 2.7.0.1)
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
rexml
|
rexml
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 1.4.0, < 1.7)
|
unicode-display_width (>= 1.4.0, < 2.0)
|
||||||
rubocop-performance (1.5.2)
|
rubocop-performance (1.5.2)
|
||||||
rubocop (>= 0.71.0)
|
rubocop (>= 0.71.0)
|
||||||
rubocop-rspec (1.38.1)
|
rubocop-rspec (1.38.1)
|
||||||
@ -111,8 +111,8 @@ GEM
|
|||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
unf_ext
|
unf_ext
|
||||||
unf_ext (0.0.7.6)
|
unf_ext (0.0.7.7)
|
||||||
unicode-display_width (1.6.1)
|
unicode-display_width (1.7.0)
|
||||||
webrobots (0.1.2)
|
webrobots (0.1.2)
|
||||||
zeitwerk (2.3.0)
|
zeitwerk (2.3.0)
|
||||||
|
|
||||||
|
|||||||
135
Library/Homebrew/bintray.rb
Normal file
135
Library/Homebrew/bintray.rb
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "utils/curl"
|
||||||
|
require "json"
|
||||||
|
|
||||||
|
class Bintray
|
||||||
|
API_URL = "https://api.bintray.com"
|
||||||
|
|
||||||
|
class Error < RuntimeError
|
||||||
|
end
|
||||||
|
|
||||||
|
def inspect
|
||||||
|
"#<Bintray: user=#{@bintray_user} org=#{@bintray_org} key=***>"
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(user: ENV["HOMEBREW_BINTRAY_USER"], key: ENV["HOMEBREW_BINTRAY_KEY"], org: "homebrew", clear: true)
|
||||||
|
@bintray_user = user
|
||||||
|
@bintray_key = key
|
||||||
|
@bintray_org = org
|
||||||
|
|
||||||
|
if !@bintray_user || !@bintray_key
|
||||||
|
unless Homebrew.args.dry_run?
|
||||||
|
raise UsageError, "Missing HOMEBREW_BINTRAY_USER or HOMEBREW_BINTRAY_KEY variables!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
raise UsageError, "Must set a Bintray organisation!" unless @bintray_org
|
||||||
|
|
||||||
|
ENV["HOMEBREW_FORCE_HOMEBREW_ON_LINUX"] = "1" if @bintray_org == "homebrew" && !OS.mac?
|
||||||
|
|
||||||
|
ENV.delete "HOMEBREW_BINTRAY_KEY" if clear
|
||||||
|
end
|
||||||
|
|
||||||
|
def open_api(url, *extra_curl_args, auth: true)
|
||||||
|
args = extra_curl_args
|
||||||
|
args += ["--user", "#{@bintray_user}:#{@bintray_key}"] if auth
|
||||||
|
curl(*args, url,
|
||||||
|
show_output: Homebrew.args.verbose?,
|
||||||
|
secrets: @bintray_key)
|
||||||
|
end
|
||||||
|
|
||||||
|
def upload(local_file, repo:, package:, version:, remote_file:, sha256: nil)
|
||||||
|
url = "#{API_URL}/content/#{@bintray_org}/#{repo}/#{package}/#{version}/#{remote_file}"
|
||||||
|
args = ["--upload-file", local_file]
|
||||||
|
args += ["--header", "X-Checksum-Sha2: #{sha256}"] unless sha256.blank?
|
||||||
|
open_api url, *args
|
||||||
|
end
|
||||||
|
|
||||||
|
def publish(repo:, package:, version:)
|
||||||
|
url = "#{API_URL}/content/#{@bintray_org}/#{repo}/#{package}/#{version}/publish"
|
||||||
|
open_api url, "--request", "POST"
|
||||||
|
end
|
||||||
|
|
||||||
|
def official_org?(org: @bintray_org)
|
||||||
|
%w[homebrew linuxbrew].include? org
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_package(repo:, package:, **extra_data_args)
|
||||||
|
url = "#{API_URL}/packages/#{@bintray_org}/#{repo}/#{package}"
|
||||||
|
data = { name: package, public_download_numbers: true }
|
||||||
|
data[:public_stats] = official_org?
|
||||||
|
data.merge! extra_data_args
|
||||||
|
open_api url, "--request", "POST", "--data", data.to_json
|
||||||
|
end
|
||||||
|
|
||||||
|
def package_exists?(repo:, package:)
|
||||||
|
url = "#{API_URL}/packages/#{@bintray_org}/#{repo}/#{package}"
|
||||||
|
open_api url, "--output", "/dev/null", auth: false
|
||||||
|
end
|
||||||
|
|
||||||
|
def file_published?(repo:, remote_file:)
|
||||||
|
url = "https://dl.bintray.com/#{@bintray_org}/#{repo}/#{remote_file}"
|
||||||
|
begin
|
||||||
|
curl "--silent", "--head", "--output", "/dev/null", url
|
||||||
|
rescue ErrorDuringExecution => e
|
||||||
|
stderr = e.output.select { |type,| type == :stderr }
|
||||||
|
.map { |_, line| line }
|
||||||
|
.join
|
||||||
|
raise if e.status.exitstatus != 22 && !stderr.include?("404 Not Found")
|
||||||
|
|
||||||
|
false
|
||||||
|
else
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def upload_bottle_json(json_files, publish_package: false)
|
||||||
|
bottles_hash = json_files.reduce({}) do |hash, json_file|
|
||||||
|
hash.deep_merge(JSON.parse(IO.read(json_file)))
|
||||||
|
end
|
||||||
|
|
||||||
|
formula_packaged = {}
|
||||||
|
|
||||||
|
bottles_hash.each do |formula_name, bottle_hash|
|
||||||
|
version = bottle_hash["formula"]["pkg_version"]
|
||||||
|
bintray_package = bottle_hash["bintray"]["package"]
|
||||||
|
bintray_repo = bottle_hash["bintray"]["repository"]
|
||||||
|
|
||||||
|
bottle_hash["bottle"]["tags"].each do |_tag, tag_hash|
|
||||||
|
filename = tag_hash["filename"]
|
||||||
|
sha256 = tag_hash["sha256"]
|
||||||
|
|
||||||
|
odebug "Checking remote file #{@bintray_org}/#{bintray_repo}/#{filename}"
|
||||||
|
if file_published? repo: bintray_repo, remote_file: filename
|
||||||
|
raise Error, <<~EOS
|
||||||
|
#{filename} is already published.
|
||||||
|
Please remove it manually from:
|
||||||
|
https://bintray.com/#{@bintray_org}/#{bintray_repo}/#{bintray_package}/view#files
|
||||||
|
Or run:
|
||||||
|
curl -X DELETE -u $HOMEBREW_BINTRAY_USER:$HOMEBREW_BINTRAY_KEY \\
|
||||||
|
https://api.bintray.com/content/#{@bintray_org}/#{bintray_repo}/#{filename}
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
if !formula_packaged[formula_name] && !package_exists?(repo: bintray_repo, package: bintray_package)
|
||||||
|
odebug "Creating package #{@bintray_org}/#{bintray_repo}/#{package}"
|
||||||
|
create_package repo: bintray_repo, package: bintray_package
|
||||||
|
formula_packaged[formula_name] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
odebug "Uploading #{@bintray_org}/#{bintray_repo}/#{bintray_package}/#{version}/#{tag_hash["local_filename"]}"
|
||||||
|
upload(tag_hash["local_filename"],
|
||||||
|
repo: bintray_repo,
|
||||||
|
package: bintray_package,
|
||||||
|
version: version,
|
||||||
|
remote_file: filename,
|
||||||
|
sha256: sha256)
|
||||||
|
end
|
||||||
|
if publish_package
|
||||||
|
odebug "Publishing #{@bintray_org}/#{bintray_repo}/#{bintray_package}/#{version}"
|
||||||
|
publish repo: bintray_repo, package: bintray_package, version: version
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -35,6 +35,13 @@ rescue MissingEnvironmentVariables => e
|
|||||||
exec ENV["HOMEBREW_BREW_FILE"], *ARGV
|
exec ENV["HOMEBREW_BREW_FILE"], *ARGV
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def head_unsupported_error
|
||||||
|
$stderr.puts <<~EOS
|
||||||
|
Please create pull requests instead of asking for help on Homebrew's GitHub,
|
||||||
|
Discourse, Twitter or IRC.
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
trap("INT", std_trap) # restore default CTRL-C handler
|
trap("INT", std_trap) # restore default CTRL-C handler
|
||||||
|
|
||||||
@ -141,12 +148,18 @@ rescue Interrupt
|
|||||||
rescue BuildError => e
|
rescue BuildError => e
|
||||||
Utils::Analytics.report_build_error(e)
|
Utils::Analytics.report_build_error(e)
|
||||||
e.dump
|
e.dump
|
||||||
|
|
||||||
|
head_unsupported_error if Homebrew.args.HEAD?
|
||||||
|
|
||||||
exit 1
|
exit 1
|
||||||
rescue RuntimeError, SystemCallError => e
|
rescue RuntimeError, SystemCallError => e
|
||||||
raise if e.message.empty?
|
raise if e.message.empty?
|
||||||
|
|
||||||
onoe e
|
onoe e
|
||||||
$stderr.puts e.backtrace if ARGV.debug?
|
$stderr.puts e.backtrace if ARGV.debug?
|
||||||
|
|
||||||
|
head_unsupported_error if Homebrew.args.HEAD?
|
||||||
|
|
||||||
exit 1
|
exit 1
|
||||||
rescue MethodDeprecatedError => e
|
rescue MethodDeprecatedError => e
|
||||||
onoe e
|
onoe e
|
||||||
|
|||||||
@ -27,7 +27,7 @@ esac
|
|||||||
export HOMEBREW_COMMAND_DEPTH=$((HOMEBREW_COMMAND_DEPTH + 1))
|
export HOMEBREW_COMMAND_DEPTH=$((HOMEBREW_COMMAND_DEPTH + 1))
|
||||||
|
|
||||||
ohai() {
|
ohai() {
|
||||||
if [[ -t 1 && -z "$HOMEBREW_NO_COLOR" ]] # check whether stdout is a tty.
|
if [[ -n "$HOMEBREW_COLOR" || (-t 1 && -z "$HOMEBREW_NO_COLOR") ]] # check whether stdout is a tty.
|
||||||
then
|
then
|
||||||
echo -e "\\033[34m==>\\033[0m \\033[1m$*\\033[0m" # blue arrow and bold text
|
echo -e "\\033[34m==>\\033[0m \\033[1m$*\\033[0m" # blue arrow and bold text
|
||||||
else
|
else
|
||||||
@ -36,7 +36,7 @@ ohai() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onoe() {
|
onoe() {
|
||||||
if [[ -t 2 && -z "$HOMEBREW_NO_COLOR" ]] # check whether stderr is a tty.
|
if [[ -n "$HOMEBREW_COLOR" || (-t 2 && -z "$HOMEBREW_NO_COLOR") ]] # check whether stderr is a tty.
|
||||||
then
|
then
|
||||||
echo -ne "\\033[4;31mError\\033[0m: " >&2 # highlight Error with underline and red color
|
echo -ne "\\033[4;31mError\\033[0m: " >&2 # highlight Error with underline and red color
|
||||||
else
|
else
|
||||||
|
|||||||
@ -49,9 +49,11 @@ module Cask
|
|||||||
next if MacOS.version < :high_sierra
|
next if MacOS.version < :high_sierra
|
||||||
|
|
||||||
<<~EOS
|
<<~EOS
|
||||||
To install and/or use #{@cask} you may need to enable its kernel extension in:
|
#{@cask} requires a kernel extension to work.
|
||||||
|
If the installation fails, retry after you enable it in:
|
||||||
System Preferences → Security & Privacy → General
|
System Preferences → Security & Privacy → General
|
||||||
For more information refer to vendor documentation or this Apple Technical Note:
|
|
||||||
|
For more information, refer to vendor documentation or this Apple Technical Note:
|
||||||
#{Formatter.url("https://developer.apple.com/library/content/technotes/tn2459/_index.html")}
|
#{Formatter.url("https://developer.apple.com/library/content/technotes/tn2459/_index.html")}
|
||||||
EOS
|
EOS
|
||||||
end
|
end
|
||||||
|
|||||||
@ -68,6 +68,19 @@ module Homebrew
|
|||||||
named.blank?
|
named.blank?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# If the user passes any flags that trigger building over installing from
|
||||||
|
# a bottle, they are collected here and returned as an Array for checking.
|
||||||
|
def collect_build_args
|
||||||
|
build_flags = []
|
||||||
|
|
||||||
|
build_flags << "--HEAD" if head
|
||||||
|
build_flags << "--universal" if build_universal
|
||||||
|
build_flags << "--build-bottle" if build_bottle
|
||||||
|
build_flags << "--build-from-source" if build_from_source
|
||||||
|
|
||||||
|
build_flags
|
||||||
|
end
|
||||||
|
|
||||||
def formulae
|
def formulae
|
||||||
require "formula"
|
require "formula"
|
||||||
@formulae ||= (downcased_unique_named - casks).map do |name|
|
@formulae ||= (downcased_unique_named - casks).map do |name|
|
||||||
@ -141,6 +154,10 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_stable?
|
||||||
|
!(HEAD? || devel?)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def downcased_unique_named
|
def downcased_unique_named
|
||||||
@ -160,11 +177,33 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
def head
|
def head
|
||||||
(args_parsed && HEAD?) || cmdline_args.include?("--HEAD")
|
return true if args_parsed && HEAD?
|
||||||
|
|
||||||
|
cmdline_args.include?("--HEAD")
|
||||||
end
|
end
|
||||||
|
|
||||||
def devel
|
def devel
|
||||||
(args_parsed && devel?) || cmdline_args.include?("--devel")
|
return true if args_parsed && devel?
|
||||||
|
|
||||||
|
cmdline_args.include?("--devel")
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_universal
|
||||||
|
return true if args_parsed && universal?
|
||||||
|
|
||||||
|
cmdline_args.include?("--universal")
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_bottle
|
||||||
|
return true if args_parsed && build_bottle?
|
||||||
|
|
||||||
|
cmdline_args.include?("--build-bottle")
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_from_source
|
||||||
|
return true if args_parsed && (build_from_source? || s?)
|
||||||
|
|
||||||
|
cmdline_args.include?("--build-from-source") || cmdline_args.include?("-s")
|
||||||
end
|
end
|
||||||
|
|
||||||
def spec(default = :stable)
|
def spec(default = :stable)
|
||||||
|
|||||||
@ -95,6 +95,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
def comma_array(name, description: nil)
|
def comma_array(name, description: nil)
|
||||||
|
name = name.chomp "="
|
||||||
description = option_to_description(name) if description.nil?
|
description = option_to_description(name) if description.nil?
|
||||||
process_option(name, description)
|
process_option(name, description)
|
||||||
@parser.on(name, OptionParser::REQUIRED_ARGUMENT, Array, *wrap_option_desc(description)) do |list|
|
@parser.on(name, OptionParser::REQUIRED_ARGUMENT, Array, *wrap_option_desc(description)) do |list|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ homebrew-shellenv() {
|
|||||||
echo "set -gx HOMEBREW_PREFIX \"$HOMEBREW_PREFIX\";"
|
echo "set -gx HOMEBREW_PREFIX \"$HOMEBREW_PREFIX\";"
|
||||||
echo "set -gx HOMEBREW_CELLAR \"$HOMEBREW_CELLAR\";"
|
echo "set -gx HOMEBREW_CELLAR \"$HOMEBREW_CELLAR\";"
|
||||||
echo "set -gx HOMEBREW_REPOSITORY \"$HOMEBREW_REPOSITORY\";"
|
echo "set -gx HOMEBREW_REPOSITORY \"$HOMEBREW_REPOSITORY\";"
|
||||||
echo "set -g fish_user_paths \"$HOMEBREW_PREFIX/bin\" \"$HOMEBREW_PREFIX/sbin\" \$fish_user_paths;"
|
echo "set -q PATH; or set PATH ''; set -gx PATH \"$HOMEBREW_PREFIX/bin\" \"$HOMEBREW_PREFIX/sbin\" \$PATH;"
|
||||||
echo "set -q MANPATH; or set MANPATH ''; set -gx MANPATH \"$HOMEBREW_PREFIX/share/man\" \$MANPATH;"
|
echo "set -q MANPATH; or set MANPATH ''; set -gx MANPATH \"$HOMEBREW_PREFIX/share/man\" \$MANPATH;"
|
||||||
echo "set -q INFOPATH; or set INFOPATH ''; set -gx INFOPATH \"$HOMEBREW_PREFIX/share/info\" \$INFOPATH;"
|
echo "set -q INFOPATH; or set INFOPATH ''; set -gx INFOPATH \"$HOMEBREW_PREFIX/share/info\" \$INFOPATH;"
|
||||||
;;
|
;;
|
||||||
|
|||||||
@ -73,7 +73,6 @@ module Homebrew
|
|||||||
|
|
||||||
install_core_tap_if_necessary
|
install_core_tap_if_necessary
|
||||||
|
|
||||||
hub = ReporterHub.new
|
|
||||||
updated = false
|
updated = false
|
||||||
|
|
||||||
initial_revision = ENV["HOMEBREW_UPDATE_BEFORE"].to_s
|
initial_revision = ENV["HOMEBREW_UPDATE_BEFORE"].to_s
|
||||||
@ -86,6 +85,11 @@ module Homebrew
|
|||||||
updated = true
|
updated = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Homebrew.failed = true if ENV["HOMEBREW_UPDATE_FAILED"]
|
||||||
|
return if ENV["HOMEBREW_DISABLE_LOAD_FORMULA"]
|
||||||
|
|
||||||
|
hub = ReporterHub.new
|
||||||
|
|
||||||
updated_taps = []
|
updated_taps = []
|
||||||
Tap.each do |tap|
|
Tap.each do |tap|
|
||||||
next unless tap.git?
|
next unless tap.git?
|
||||||
@ -127,8 +131,6 @@ module Homebrew
|
|||||||
|
|
||||||
link_completions_manpages_and_docs
|
link_completions_manpages_and_docs
|
||||||
Tap.each(&:link_completions_and_manpages)
|
Tap.each(&:link_completions_and_manpages)
|
||||||
|
|
||||||
Homebrew.failed = true if ENV["HOMEBREW_UPDATE_FAILED"]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def shorten_revision(revision)
|
def shorten_revision(revision)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "compat/cask/dsl/version"
|
require "compat/cask/dsl/version"
|
||||||
|
require "compat/language/python"
|
||||||
require "compat/requirements/macos_requirement"
|
require "compat/requirements/macos_requirement"
|
||||||
require "compat/formula"
|
require "compat/formula"
|
||||||
|
|||||||
17
Library/Homebrew/compat/language/python.rb
Normal file
17
Library/Homebrew/compat/language/python.rb
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Language
|
||||||
|
module Python
|
||||||
|
class << self
|
||||||
|
module Compat
|
||||||
|
def rewrite_python_shebang(python_path)
|
||||||
|
Pathname.pwd.find do |f|
|
||||||
|
Utils::Shebang.rewrite_shebang(Shebang.python_shebang_rewrite_info(python_path), f)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
prepend Compat
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -292,7 +292,7 @@ module Homebrew
|
|||||||
unversioned_name = unversioned_formula.basename(".rb")
|
unversioned_name = unversioned_formula.basename(".rb")
|
||||||
problem "#{formula} is versioned but no #{unversioned_name} formula exists"
|
problem "#{formula} is versioned but no #{unversioned_name} formula exists"
|
||||||
end
|
end
|
||||||
elsif ARGV.build_stable? && formula.stable? &&
|
elsif Homebrew.args.build_stable? && formula.stable? &&
|
||||||
!(versioned_formulae = formula.versioned_formulae).empty?
|
!(versioned_formulae = formula.versioned_formulae).empty?
|
||||||
versioned_aliases = formula.aliases.grep(/.@\d/)
|
versioned_aliases = formula.aliases.grep(/.@\d/)
|
||||||
_, last_alias_version = versioned_formulae.map(&:name).last.split("@")
|
_, last_alias_version = versioned_formulae.map(&:name).last.split("@")
|
||||||
@ -520,6 +520,7 @@ module Homebrew
|
|||||||
gnupg@1.4
|
gnupg@1.4
|
||||||
lua@5.1
|
lua@5.1
|
||||||
numpy@1.16
|
numpy@1.16
|
||||||
|
libsigc++@2
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
return if keg_only_whitelist.include?(formula.name) || formula.name.start_with?("gcc@")
|
return if keg_only_whitelist.include?(formula.name) || formula.name.start_with?("gcc@")
|
||||||
|
|||||||
@ -40,7 +40,7 @@ module Homebrew
|
|||||||
description: "Print the pull request URL instead of opening in a browser."
|
description: "Print the pull request URL instead of opening in a browser."
|
||||||
switch "--no-fork",
|
switch "--no-fork",
|
||||||
description: "Don't try to fork the repository."
|
description: "Don't try to fork the repository."
|
||||||
comma_array "--mirror=",
|
comma_array "--mirror",
|
||||||
description: "Use the specified <URL> as a mirror URL. If <URL> is a comma-separated list "\
|
description: "Use the specified <URL> as a mirror URL. If <URL> is a comma-separated list "\
|
||||||
"of URLs, multiple mirrors will be added."
|
"of URLs, multiple mirrors will be added."
|
||||||
flag "--version=",
|
flag "--version=",
|
||||||
|
|||||||
@ -31,6 +31,8 @@ module Homebrew
|
|||||||
description: "Create a basic template for a Perl build."
|
description: "Create a basic template for a Perl build."
|
||||||
switch "--python",
|
switch "--python",
|
||||||
description: "Create a basic template for a Python build."
|
description: "Create a basic template for a Python build."
|
||||||
|
switch "--ruby",
|
||||||
|
description: "Create a basic template for a Ruby build."
|
||||||
switch "--rust",
|
switch "--rust",
|
||||||
description: "Create a basic template for a Rust build."
|
description: "Create a basic template for a Rust build."
|
||||||
switch "--no-fetch",
|
switch "--no-fetch",
|
||||||
@ -86,6 +88,8 @@ module Homebrew
|
|||||||
:perl
|
:perl
|
||||||
elsif args.python?
|
elsif args.python?
|
||||||
:python
|
:python
|
||||||
|
elsif args.ruby?
|
||||||
|
:ruby
|
||||||
elsif args.rust?
|
elsif args.rust?
|
||||||
:rust
|
:rust
|
||||||
end
|
end
|
||||||
|
|||||||
38
Library/Homebrew/dev-cmd/pr-publish.rb
Normal file
38
Library/Homebrew/dev-cmd/pr-publish.rb
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "cli/parser"
|
||||||
|
require "utils/github"
|
||||||
|
|
||||||
|
module Homebrew
|
||||||
|
module_function
|
||||||
|
|
||||||
|
def pr_publish_args
|
||||||
|
Homebrew::CLI::Parser.new do
|
||||||
|
usage_banner <<~EOS
|
||||||
|
`pr-publish` <pull_request>
|
||||||
|
|
||||||
|
Publishes bottles for a pull request with GitHub Actions.
|
||||||
|
Requires write access to the repository.
|
||||||
|
EOS
|
||||||
|
switch :verbose
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def pr_publish
|
||||||
|
pr_publish_args.parse
|
||||||
|
|
||||||
|
ENV["HOMEBREW_FORCE_HOMEBREW_ON_LINUX"] = "1" unless OS.mac?
|
||||||
|
|
||||||
|
odie "You need to specify at least one pull request number!" if Homebrew.args.named.empty?
|
||||||
|
|
||||||
|
args.named.each do |arg|
|
||||||
|
arg = "#{CoreTap.instance.default_remote}/pull/#{arg}" if arg.to_i.positive?
|
||||||
|
url_match = arg.match HOMEBREW_PULL_OR_COMMIT_URL_REGEX
|
||||||
|
_, user, repo, issue = *url_match
|
||||||
|
tap = Tap.fetch(user, repo) if repo.match?(HOMEBREW_OFFICIAL_REPO_PREFIXES_REGEX)
|
||||||
|
odie "Not a GitHub pull request: #{arg}" unless issue
|
||||||
|
ohai "Dispatching #{tap} pull request ##{issue}"
|
||||||
|
GitHub.dispatch_event(user, repo, "Publish ##{issue}", pull_request: issue)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
168
Library/Homebrew/dev-cmd/pr-pull.rb
Normal file
168
Library/Homebrew/dev-cmd/pr-pull.rb
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "cli/parser"
|
||||||
|
require "utils/github"
|
||||||
|
require "tmpdir"
|
||||||
|
require "bintray"
|
||||||
|
|
||||||
|
module Homebrew
|
||||||
|
module_function
|
||||||
|
|
||||||
|
def pr_pull_args
|
||||||
|
Homebrew::CLI::Parser.new do
|
||||||
|
usage_banner <<~EOS
|
||||||
|
`pr-pull` <pull_request>
|
||||||
|
|
||||||
|
Download and publish bottles, and apply the bottle commit from a
|
||||||
|
pull request with artifacts generated from GitHub Actions.
|
||||||
|
Requires write access to the repository.
|
||||||
|
EOS
|
||||||
|
switch "--no-publish",
|
||||||
|
description: "Download the bottles, apply the bottle commit, and "\
|
||||||
|
"upload the bottles to Bintray, but don't publish them."
|
||||||
|
switch "--no-upload",
|
||||||
|
description: "Download the bottles and apply the bottle commit, "\
|
||||||
|
"but don't upload to Bintray."
|
||||||
|
switch "--dry-run", "-n",
|
||||||
|
description: "Print what would be done rather than doing it."
|
||||||
|
switch "--clean",
|
||||||
|
description: "Do not amend the commits from pull requests."
|
||||||
|
switch "--branch-okay",
|
||||||
|
description: "Do not warn if pulling to a branch besides master (useful for testing)."
|
||||||
|
switch "--resolve",
|
||||||
|
description: "When a patch fails to apply, leave in progress and allow user to resolve, instead "\
|
||||||
|
"of aborting."
|
||||||
|
flag "--workflow=",
|
||||||
|
description: "Retrieve artifacts from the specified workflow (default: tests.yml)."
|
||||||
|
flag "--artifact=",
|
||||||
|
description: "Download artifacts with the specified name (default: bottles)."
|
||||||
|
flag "--bintray-org=",
|
||||||
|
description: "Upload to the specified Bintray organisation (default: homebrew)."
|
||||||
|
flag "--tap=",
|
||||||
|
description: "Target repository tap (default: homebrew/core)."
|
||||||
|
switch :verbose
|
||||||
|
switch :debug
|
||||||
|
min_named 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup_git_environment!
|
||||||
|
# Passthrough Git environment variables
|
||||||
|
ENV["GIT_COMMITTER_NAME"] = ENV["HOMEBREW_GIT_NAME"] if ENV["HOMEBREW_GIT_NAME"]
|
||||||
|
ENV["GIT_COMMITTER_EMAIL"] = ENV["HOMEBREW_GIT_EMAIL"] if ENV["HOMEBREW_GIT_EMAIL"]
|
||||||
|
|
||||||
|
# Depending on user configuration, git may try to invoke gpg.
|
||||||
|
return unless Utils.popen_read("git config --get --bool commit.gpgsign").chomp == "true"
|
||||||
|
|
||||||
|
begin
|
||||||
|
gnupg = Formula["gnupg"]
|
||||||
|
rescue FormulaUnavailableError
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
if gnupg.installed?
|
||||||
|
path = PATH.new(ENV.fetch("PATH"))
|
||||||
|
path.prepend(gnupg.installed_prefix/"bin")
|
||||||
|
ENV["PATH"] = path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def signoff!(pr, path: ".", dry_run: false)
|
||||||
|
message = Utils.popen_read "git", "-C", path, "log", "-1", "--pretty=%B"
|
||||||
|
close_message = "Closes ##{pr}."
|
||||||
|
message += "\n#{close_message}" unless message.include? close_message
|
||||||
|
if dry_run
|
||||||
|
puts "git commit --amend --signoff -m $message"
|
||||||
|
else
|
||||||
|
safe_system "git", "-C", path, "commit", "--amend", "--signoff", "--allow-empty", "-q", "-m", message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def cherry_pick_pr!(pr, path: ".", dry_run: false)
|
||||||
|
if dry_run
|
||||||
|
puts <<~EOS
|
||||||
|
git fetch --force origin +refs/pull/#{pr}/head
|
||||||
|
git merge-base HEAD FETCH_HEAD
|
||||||
|
git cherry-pick --ff --allow-empty $merge_base..FETCH_HEAD
|
||||||
|
EOS
|
||||||
|
else
|
||||||
|
safe_system "git", "-C", path, "fetch", "--quiet", "--force", "origin", "+refs/pull/#{pr}/head"
|
||||||
|
merge_base = Utils.popen_read("git", "-C", path, "merge-base", "HEAD", "FETCH_HEAD").strip
|
||||||
|
commit_count = Utils.popen_read("git", "-C", path, "rev-list", "#{merge_base}..FETCH_HEAD").lines.count
|
||||||
|
|
||||||
|
# git cherry-pick unfortunately has no quiet option
|
||||||
|
ohai "Cherry-picking #{commit_count} commit#{"s" unless commit_count == 1} from ##{pr}"
|
||||||
|
cherry_pick_args = "git", "-C", path, "cherry-pick", "--ff", "--allow-empty", "#{merge_base}..FETCH_HEAD"
|
||||||
|
result = Homebrew.args.verbose? ? system(*cherry_pick_args) : quiet_system(*cherry_pick_args)
|
||||||
|
|
||||||
|
unless result
|
||||||
|
if Homebrew.args.resolve?
|
||||||
|
odie "Cherry-pick failed: try to resolve it."
|
||||||
|
else
|
||||||
|
system "git", "-C", path, "cherry-pick", "--abort"
|
||||||
|
odie "Cherry-pick failed!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_branch(path, ref)
|
||||||
|
branch = Utils.popen_read("git", "-C", path, "symbolic-ref", "--short", "HEAD").strip
|
||||||
|
|
||||||
|
return if branch == ref || args.clean? || args.branch_okay?
|
||||||
|
|
||||||
|
opoo "Current branch is #{branch}: do you need to pull inside #{ref}?"
|
||||||
|
end
|
||||||
|
|
||||||
|
def pr_pull
|
||||||
|
pr_pull_args.parse
|
||||||
|
|
||||||
|
bintray_user = ENV["HOMEBREW_BINTRAY_USER"]
|
||||||
|
bintray_key = ENV["HOMEBREW_BINTRAY_KEY"]
|
||||||
|
bintray_org = args.bintray_org || "homebrew"
|
||||||
|
|
||||||
|
if bintray_user.blank? || bintray_key.blank?
|
||||||
|
odie "Missing HOMEBREW_BINTRAY_USER or HOMEBREW_BINTRAY_KEY variables!" if !args.dry_run? && !args.no_upload?
|
||||||
|
else
|
||||||
|
bintray = Bintray.new(user: bintray_user, key: bintray_key, org: bintray_org)
|
||||||
|
end
|
||||||
|
|
||||||
|
workflow = args.workflow || "tests.yml"
|
||||||
|
artifact = args.artifact || "bottles"
|
||||||
|
tap = Tap.fetch(args.tap || "homebrew/core")
|
||||||
|
|
||||||
|
setup_git_environment!
|
||||||
|
|
||||||
|
args.named.each do |arg|
|
||||||
|
arg = "#{tap.default_remote}/pull/#{arg}" if arg.to_i.positive?
|
||||||
|
url_match = arg.match HOMEBREW_PULL_OR_COMMIT_URL_REGEX
|
||||||
|
_, user, repo, pr = *url_match
|
||||||
|
odie "Not a GitHub pull request: #{arg}" unless pr
|
||||||
|
|
||||||
|
check_branch tap.path, "master"
|
||||||
|
|
||||||
|
ohai "Fetching #{tap} pull request ##{pr}"
|
||||||
|
Dir.mktmpdir pr do |dir|
|
||||||
|
cd dir do
|
||||||
|
GitHub.fetch_artifact(user, repo, pr, dir, workflow_id: workflow, artifact_name: artifact)
|
||||||
|
cherry_pick_pr! pr, path: tap.path, dry_run: args.dry_run?
|
||||||
|
signoff! pr, path: tap.path, dry_run: args.dry_run? unless args.clean?
|
||||||
|
|
||||||
|
if args.dry_run?
|
||||||
|
puts "brew bottle --merge --write #{Dir["*.json"].join " "}"
|
||||||
|
else
|
||||||
|
quiet_system "#{HOMEBREW_PREFIX}/bin/brew", "bottle", "--merge", "--write", *Dir["*.json"]
|
||||||
|
end
|
||||||
|
|
||||||
|
next if args.no_upload?
|
||||||
|
|
||||||
|
if args.dry_run?
|
||||||
|
puts "Upload bottles described by these JSON files to Bintray:\n #{Dir["*.json"].join("\n ")}"
|
||||||
|
else
|
||||||
|
bintray.upload_bottle_json Dir["*.json"], publish_package: !args.no_publish?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -36,6 +36,7 @@ module Homebrew
|
|||||||
test_args.parse
|
test_args.parse
|
||||||
|
|
||||||
require "formula_assertions"
|
require "formula_assertions"
|
||||||
|
require "formula_free_port"
|
||||||
|
|
||||||
args.resolved_formulae.each do |f|
|
args.resolved_formulae.each do |f|
|
||||||
# Cannot test uninstalled formulae
|
# Cannot test uninstalled formulae
|
||||||
|
|||||||
@ -43,14 +43,6 @@ module HomebrewArgvExtension
|
|||||||
include?("--no-sandbox") || !ENV["HOMEBREW_NO_SANDBOX"].nil?
|
include?("--no-sandbox") || !ENV["HOMEBREW_NO_SANDBOX"].nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_stable?
|
|
||||||
!(include?("--HEAD") || include?("--devel"))
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_universal?
|
|
||||||
include? "--universal"
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_bottle?
|
def build_bottle?
|
||||||
include?("--build-bottle")
|
include?("--build-bottle")
|
||||||
end
|
end
|
||||||
@ -84,19 +76,6 @@ module HomebrewArgvExtension
|
|||||||
value "env"
|
value "env"
|
||||||
end
|
end
|
||||||
|
|
||||||
# If the user passes any flags that trigger building over installing from
|
|
||||||
# a bottle, they are collected here and returned as an Array for checking.
|
|
||||||
def collect_build_flags
|
|
||||||
build_flags = []
|
|
||||||
|
|
||||||
build_flags << "--HEAD" if include?("--HEAD")
|
|
||||||
build_flags << "--universal" if build_universal?
|
|
||||||
build_flags << "--build-bottle" if build_bottle?
|
|
||||||
build_flags << "--build-from-source" if build_from_source?
|
|
||||||
|
|
||||||
build_flags
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def options_only
|
def options_only
|
||||||
|
|||||||
@ -6,6 +6,7 @@ require "lock_file"
|
|||||||
require "formula_pin"
|
require "formula_pin"
|
||||||
require "hardware"
|
require "hardware"
|
||||||
require "utils/bottles"
|
require "utils/bottles"
|
||||||
|
require "utils/shebang"
|
||||||
require "utils/shell"
|
require "utils/shell"
|
||||||
require "build_environment"
|
require "build_environment"
|
||||||
require "build_options"
|
require "build_options"
|
||||||
@ -50,6 +51,7 @@ require "find"
|
|||||||
class Formula
|
class Formula
|
||||||
include FileUtils
|
include FileUtils
|
||||||
include Utils::Inreplace
|
include Utils::Inreplace
|
||||||
|
include Utils::Shebang
|
||||||
include Utils::Shell
|
include Utils::Shell
|
||||||
include Utils::Deprecate
|
include Utils::Deprecate
|
||||||
extend Enumerable
|
extend Enumerable
|
||||||
|
|||||||
@ -112,6 +112,8 @@ module Homebrew
|
|||||||
uses_from_macos "perl"
|
uses_from_macos "perl"
|
||||||
<% elsif mode == :python %>
|
<% elsif mode == :python %>
|
||||||
depends_on "python"
|
depends_on "python"
|
||||||
|
<% elsif mode == :ruby %>
|
||||||
|
uses_from_macos "ruby"
|
||||||
<% elsif mode == :rust %>
|
<% elsif mode == :rust %>
|
||||||
depends_on "rust" => :build
|
depends_on "rust" => :build
|
||||||
<% elsif mode.nil? %>
|
<% elsif mode.nil? %>
|
||||||
@ -166,6 +168,12 @@ module Homebrew
|
|||||||
bin.env_script_all_files(libexec/"bin", :PERL5LIB => ENV["PERL5LIB"])
|
bin.env_script_all_files(libexec/"bin", :PERL5LIB => ENV["PERL5LIB"])
|
||||||
<% elsif mode == :python %>
|
<% elsif mode == :python %>
|
||||||
virtualenv_install_with_resources
|
virtualenv_install_with_resources
|
||||||
|
<% elsif mode == :ruby %>
|
||||||
|
ENV["GEM_HOME"] = libexec
|
||||||
|
system "gem", "build", "\#{name}.gemspec"
|
||||||
|
system "gem", "install", "\#{name}-\#{version}.gem"
|
||||||
|
bin.install libexec/"bin/\#{name}"
|
||||||
|
bin.env_script_all_files(libexec/"bin", :GEM_HOME => ENV["GEM_HOME"])
|
||||||
<% elsif mode == :rust %>
|
<% elsif mode == :rust %>
|
||||||
system "cargo", "install", "--locked", "--root", prefix, "--path", "."
|
system "cargo", "install", "--locked", "--root", prefix, "--path", "."
|
||||||
<% else %>
|
<% else %>
|
||||||
|
|||||||
15
Library/Homebrew/formula_free_port.rb
Normal file
15
Library/Homebrew/formula_free_port.rb
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Homebrew
|
||||||
|
module FreePort
|
||||||
|
require "socket"
|
||||||
|
|
||||||
|
def free_port
|
||||||
|
server = TCPServer.new 0
|
||||||
|
_, port, = server.addr
|
||||||
|
server.close
|
||||||
|
|
||||||
|
port
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -80,7 +80,7 @@ class FormulaInstaller
|
|||||||
# it's necessary to interrupt the user before any sort of installation
|
# it's necessary to interrupt the user before any sort of installation
|
||||||
# can proceed. Only invoked when the user has no developer tools.
|
# can proceed. Only invoked when the user has no developer tools.
|
||||||
def self.prevent_build_flags
|
def self.prevent_build_flags
|
||||||
build_flags = ARGV.collect_build_flags
|
build_flags = Homebrew.args.collect_build_args
|
||||||
return if build_flags.empty?
|
return if build_flags.empty?
|
||||||
|
|
||||||
all_bottled = ARGV.formulae.all?(&:bottled?)
|
all_bottled = ARGV.formulae.all?(&:bottled?)
|
||||||
@ -598,16 +598,16 @@ class FormulaInstaller
|
|||||||
oh1 "Installing #{formula.full_name} dependency: #{Formatter.identifier(dep.name)}"
|
oh1 "Installing #{formula.full_name} dependency: #{Formatter.identifier(dep.name)}"
|
||||||
fi.install
|
fi.install
|
||||||
fi.finish
|
fi.finish
|
||||||
rescue FormulaInstallationAlreadyAttemptedError
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
||||||
# We already attempted to install f as part of the dependency tree of
|
|
||||||
# another formula. In that case, don't generate an error, just move on.
|
|
||||||
nil
|
|
||||||
rescue Exception # rubocop:disable Lint/RescueException
|
|
||||||
ignore_interrupts do
|
ignore_interrupts do
|
||||||
tmp_keg.rename(installed_keg) if tmp_keg && !installed_keg.directory?
|
tmp_keg.rename(installed_keg) if tmp_keg && !installed_keg.directory?
|
||||||
linked_keg.link if keg_was_linked
|
linked_keg.link if keg_was_linked
|
||||||
end
|
end
|
||||||
raise
|
raise unless e.is_a? FormulaInstallationAlreadyAttemptedError
|
||||||
|
|
||||||
|
# We already attempted to install f as part of another formula's
|
||||||
|
# dependency tree. In that case, don't generate an error, just move on.
|
||||||
|
nil
|
||||||
else
|
else
|
||||||
ignore_interrupts { tmp_keg.rmtree if tmp_keg&.directory? }
|
ignore_interrupts { tmp_keg.rmtree if tmp_keg&.directory? }
|
||||||
end
|
end
|
||||||
|
|||||||
25
Library/Homebrew/language/perl.rb
Normal file
25
Library/Homebrew/language/perl.rb
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Language
|
||||||
|
module Perl
|
||||||
|
module Shebang
|
||||||
|
module_function
|
||||||
|
|
||||||
|
def detected_perl_shebang(formula = self)
|
||||||
|
perl_path = if formula.uses_from_macos_elements&.include? "perl"
|
||||||
|
"/usr/bin/perl"
|
||||||
|
elsif formula.deps.map(&:name).include? "perl"
|
||||||
|
Formula["perl"].opt_bin/"perl"
|
||||||
|
else
|
||||||
|
raise "Cannot detect Perl shebang: formula does not depend on Perl."
|
||||||
|
end
|
||||||
|
|
||||||
|
Utils::Shebang::RewriteInfo.new(
|
||||||
|
%r{^#! ?/usr/bin/(env )?perl$},
|
||||||
|
20, # the length of "#! /usr/bin/env perl"
|
||||||
|
perl_path,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -87,14 +87,26 @@ module Language
|
|||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.rewrite_python_shebang(python_path)
|
# Mixin module for {Formula} adding shebang rewrite features.
|
||||||
regex = %r{^#! ?/usr/bin/(env )?python([23](\.\d{1,2})?)?$}
|
module Shebang
|
||||||
maximum_regex_length = 28 # the length of "#! /usr/bin/env pythonx.yyy$"
|
module_function
|
||||||
Pathname(".").find do |f|
|
|
||||||
next unless f.file?
|
|
||||||
next unless regex.match?(f.read(maximum_regex_length))
|
|
||||||
|
|
||||||
Utils::Inreplace.inreplace f.to_s, regex, "#!#{python_path}"
|
# @private
|
||||||
|
def python_shebang_rewrite_info(python_path)
|
||||||
|
Utils::Shebang::RewriteInfo.new(
|
||||||
|
%r{^#! ?/usr/bin/(env )?python([23](\.\d{1,2})?)?$},
|
||||||
|
28, # the length of "#! /usr/bin/env pythonx.yyy$"
|
||||||
|
python_path,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def detected_python_shebang(formula = self)
|
||||||
|
python_deps = formula.deps.map(&:name).grep(/^python(@.*)?$/)
|
||||||
|
|
||||||
|
raise "Cannot detect Python shebang: formula does not depend on Python." if python_deps.empty?
|
||||||
|
raise "Cannot detect Python shebang: formula has multiple Python dependencies." if python_deps.length > 1
|
||||||
|
|
||||||
|
python_shebang_rewrite_info(Formula[python_deps.first].opt_bin/"python3")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,9 @@ require "pathname"
|
|||||||
|
|
||||||
HOMEBREW_LIBRARY_PATH = Pathname(__dir__).realpath.freeze
|
HOMEBREW_LIBRARY_PATH = Pathname(__dir__).realpath.freeze
|
||||||
|
|
||||||
$LOAD_PATH.push(HOMEBREW_LIBRARY_PATH.to_s) unless $LOAD_PATH.include?(HOMEBREW_LIBRARY_PATH.to_s)
|
$LOAD_PATH.push HOMEBREW_LIBRARY_PATH.to_s
|
||||||
|
|
||||||
require "vendor/bundle/bundler/setup"
|
require "vendor/bundle/bundler/setup"
|
||||||
|
|
||||||
|
$LOAD_PATH.select! { |d| Pathname(d).directory? }
|
||||||
|
$LOAD_PATH.uniq!
|
||||||
|
|||||||
@ -160,7 +160,7 @@ Note that environment variables must have a value set to be detected. For exampl
|
|||||||
`git`(1) remote. If set, instructs Homebrew to instead use the specified URL.
|
`git`(1) remote. If set, instructs Homebrew to instead use the specified URL.
|
||||||
|
|
||||||
* `HOMEBREW_CURLRC`:
|
* `HOMEBREW_CURLRC`:
|
||||||
If set, Homebrew will not pass `-q` when invoking `curl`(1), which disables
|
If set, Homebrew will not pass `--disable` when invoking `curl`(1), which disables
|
||||||
the use of `curlrc`.
|
the use of `curlrc`.
|
||||||
|
|
||||||
* `HOMEBREW_CURL_VERBOSE`:
|
* `HOMEBREW_CURL_VERBOSE`:
|
||||||
@ -168,6 +168,7 @@ Note that environment variables must have a value set to be detected. For exampl
|
|||||||
|
|
||||||
* `HOMEBREW_CURL_RETRIES`:
|
* `HOMEBREW_CURL_RETRIES`:
|
||||||
If set, Homebrew will pass the given retry count to `--retry` when invoking `curl`(1).
|
If set, Homebrew will pass the given retry count to `--retry` when invoking `curl`(1).
|
||||||
|
By default, `curl`(1) is invoked with `--retry 3`.
|
||||||
|
|
||||||
* `HOMEBREW_DEBUG`:
|
* `HOMEBREW_DEBUG`:
|
||||||
If set, any commands that can emit debugging information will do so.
|
If set, any commands that can emit debugging information will do so.
|
||||||
|
|||||||
@ -16,13 +16,13 @@ module OS
|
|||||||
when "10.11" then "8.2.1"
|
when "10.11" then "8.2.1"
|
||||||
when "10.12" then "9.2"
|
when "10.12" then "9.2"
|
||||||
when "10.13" then "10.1"
|
when "10.13" then "10.1"
|
||||||
when "10.14" then "11.3"
|
when "10.14" then "11.3.1"
|
||||||
when "10.15" then "11.3"
|
when "10.15" then "11.4"
|
||||||
else
|
else
|
||||||
raise "macOS '#{MacOS.version}' is invalid" unless OS::Mac.prerelease?
|
raise "macOS '#{MacOS.version}' is invalid" unless OS::Mac.prerelease?
|
||||||
|
|
||||||
# Default to newest known version of Xcode for unreleased macOS versions.
|
# Default to newest known version of Xcode for unreleased macOS versions.
|
||||||
"11.3"
|
"11.4"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -175,9 +175,9 @@ module OS
|
|||||||
when 81 then "8.3"
|
when 81 then "8.3"
|
||||||
when 90 then "9.2"
|
when 90 then "9.2"
|
||||||
when 91 then "9.4"
|
when 91 then "9.4"
|
||||||
when 100 then "10.2.1"
|
when 100 then "10.3"
|
||||||
when 110 then "11.3"
|
when 110 then "11.4"
|
||||||
else "11.3"
|
else "11.4"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -236,8 +236,8 @@ module OS
|
|||||||
# on the older supported platform for that Xcode release, i.e there's no
|
# on the older supported platform for that Xcode release, i.e there's no
|
||||||
# CLT package for 10.11 that contains the Clang version from Xcode 8.
|
# CLT package for 10.11 that contains the Clang version from Xcode 8.
|
||||||
case MacOS.version
|
case MacOS.version
|
||||||
when "10.15" then "1100.0.33.16"
|
when "10.15" then "1103.0.32.29"
|
||||||
when "10.14" then "1001.0.46.4"
|
when "10.14" then "1001.0.46.4" # Later versions are available, but not via Software Update
|
||||||
when "10.13" then "1000.10.44.2"
|
when "10.13" then "1000.10.44.2"
|
||||||
when "10.12" then "900.0.39.2"
|
when "10.12" then "900.0.39.2"
|
||||||
when "10.11" then "800.0.42.1"
|
when "10.11" then "800.0.42.1"
|
||||||
|
|||||||
@ -7,6 +7,7 @@ require "extend/ENV"
|
|||||||
require "timeout"
|
require "timeout"
|
||||||
require "debrew"
|
require "debrew"
|
||||||
require "formula_assertions"
|
require "formula_assertions"
|
||||||
|
require "formula_free_port"
|
||||||
require "fcntl"
|
require "fcntl"
|
||||||
require "socket"
|
require "socket"
|
||||||
require "cli/parser"
|
require "cli/parser"
|
||||||
@ -26,6 +27,7 @@ begin
|
|||||||
|
|
||||||
formula = Homebrew.args.resolved_formulae.first
|
formula = Homebrew.args.resolved_formulae.first
|
||||||
formula.extend(Homebrew::Assertions)
|
formula.extend(Homebrew::Assertions)
|
||||||
|
formula.extend(Homebrew::FreePort)
|
||||||
formula.extend(Debrew::Formula) if Homebrew.args.debug?
|
formula.extend(Debrew::Formula) if Homebrew.args.debug?
|
||||||
|
|
||||||
# tests can also return false to indicate failure
|
# tests can also return false to indicate failure
|
||||||
|
|||||||
25
Library/Homebrew/test/bintray_spec.rb
Normal file
25
Library/Homebrew/test/bintray_spec.rb
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "bintray"
|
||||||
|
|
||||||
|
describe Bintray, :needs_network do
|
||||||
|
bintray = described_class.new(user: "BrewTestBot", key: "deadbeef", org: "homebrew")
|
||||||
|
describe "::file_published?" do
|
||||||
|
it "detects a published file" do
|
||||||
|
results = bintray.file_published?(repo: "bottles", remote_file: "hello-2.10.catalina.bottle.tar.gz")
|
||||||
|
expect(results).to be true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails on a non-existant file" do
|
||||||
|
results = bintray.file_published?(repo: "bottles", remote_file: "my-fake-bottle-1.0.snow_hyena.tar.gz")
|
||||||
|
expect(results).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "::package_exists?" do
|
||||||
|
it "detects a package" do
|
||||||
|
results = bintray.package_exists?(repo: "bottles", package: "hello")
|
||||||
|
expect(results.status.exitstatus).to be 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -71,31 +71,6 @@ describe Cask::Cmd::Upgrade, :cask do
|
|||||||
expect(local_transmission_path).to be_a_directory
|
expect(local_transmission_path).to be_a_directory
|
||||||
expect(local_transmission.versions).to include("2.60")
|
expect(local_transmission.versions).to include("2.60")
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates "auto_updates" and "latest" Casks when their tokens are provided in the command line' do
|
|
||||||
local_caffeine = Cask::CaskLoader.load("local-caffeine")
|
|
||||||
local_caffeine_path = Cask::Config.global.appdir.join("Caffeine.app")
|
|
||||||
auto_updates = Cask::CaskLoader.load("auto-updates")
|
|
||||||
auto_updates_path = Cask::Config.global.appdir.join("MyFancyApp.app")
|
|
||||||
|
|
||||||
expect(local_caffeine).to be_installed
|
|
||||||
expect(local_caffeine_path).to be_a_directory
|
|
||||||
expect(local_caffeine.versions).to include("1.2.2")
|
|
||||||
|
|
||||||
expect(auto_updates).to be_installed
|
|
||||||
expect(auto_updates_path).to be_a_directory
|
|
||||||
expect(auto_updates.versions).to include("2.57")
|
|
||||||
|
|
||||||
described_class.run("local-caffeine", "auto-updates")
|
|
||||||
|
|
||||||
expect(local_caffeine).to be_installed
|
|
||||||
expect(local_caffeine_path).to be_a_directory
|
|
||||||
expect(local_caffeine.versions).to include("1.2.3")
|
|
||||||
|
|
||||||
expect(auto_updates).to be_installed
|
|
||||||
expect(auto_updates_path).to be_a_directory
|
|
||||||
expect(auto_updates.versions).to include("2.61")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "with --greedy it checks additional Casks" do
|
describe "with --greedy it checks additional Casks" do
|
||||||
|
|||||||
7
Library/Homebrew/test/dev-cmd/pr-publish_spec.rb
Normal file
7
Library/Homebrew/test/dev-cmd/pr-publish_spec.rb
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "cmd/shared_examples/args_parse"
|
||||||
|
|
||||||
|
describe "Homebrew.pr_publish_args" do
|
||||||
|
it_behaves_like "parseable arguments"
|
||||||
|
end
|
||||||
7
Library/Homebrew/test/dev-cmd/pr-pull_spec.rb
Normal file
7
Library/Homebrew/test/dev-cmd/pr-pull_spec.rb
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "cmd/shared_examples/args_parse"
|
||||||
|
|
||||||
|
describe "Homebrew.pr_pull_args" do
|
||||||
|
it_behaves_like "parseable arguments"
|
||||||
|
end
|
||||||
25
Library/Homebrew/test/formula_free_port_spec.rb
Normal file
25
Library/Homebrew/test/formula_free_port_spec.rb
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "socket"
|
||||||
|
require "formula_free_port"
|
||||||
|
|
||||||
|
module Homebrew
|
||||||
|
describe FreePort do
|
||||||
|
include described_class
|
||||||
|
|
||||||
|
describe "#free_port" do
|
||||||
|
# IANA suggests user port from 1024 to 49151
|
||||||
|
# and dynamic port for 49152 to 65535
|
||||||
|
# http://www.iana.org/assignments/port-numbers
|
||||||
|
MIN_PORT = 1024
|
||||||
|
MAX_PORT = 65535
|
||||||
|
|
||||||
|
it "returns a free TCP/IP port" do
|
||||||
|
port = free_port
|
||||||
|
|
||||||
|
expect(port).to be_between(MIN_PORT, MAX_PORT)
|
||||||
|
expect { TCPServer.new(port).close }.not_to raise_error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
52
Library/Homebrew/test/language/perl/shebang_spec.rb
Normal file
52
Library/Homebrew/test/language/perl/shebang_spec.rb
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "language/perl"
|
||||||
|
require "utils/shebang"
|
||||||
|
|
||||||
|
describe Language::Perl::Shebang do
|
||||||
|
let(:file) { Tempfile.new("perl-shebang") }
|
||||||
|
let(:perl_f) do
|
||||||
|
formula "perl" do
|
||||||
|
url "https://brew.sh/perl-1.0.tgz"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
let(:f) do
|
||||||
|
formula "foo" do
|
||||||
|
url "https://brew.sh/foo-1.0.tgz"
|
||||||
|
|
||||||
|
uses_from_macos "perl"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
file.write <<~EOS
|
||||||
|
#!/usr/bin/env perl
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
EOS
|
||||||
|
file.flush
|
||||||
|
end
|
||||||
|
|
||||||
|
after { file.unlink }
|
||||||
|
|
||||||
|
describe "#detected_perl_shebang" do
|
||||||
|
it "can be used to replace Perl shebangs" do
|
||||||
|
allow(Formulary).to receive(:factory).with(perl_f.name).and_return(perl_f)
|
||||||
|
Utils::Shebang.rewrite_shebang described_class.detected_perl_shebang(f), file
|
||||||
|
|
||||||
|
expected_shebang = if OS.mac?
|
||||||
|
"/usr/bin/perl"
|
||||||
|
else
|
||||||
|
HOMEBREW_PREFIX/"opt/perl/bin/perl"
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(File.read(file)).to eq <<~EOS
|
||||||
|
#!#{expected_shebang}
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
require "language/python"
|
require "language/python"
|
||||||
require "resource"
|
require "resource"
|
||||||
|
require "utils/shebang"
|
||||||
|
|
||||||
describe Language::Python, :needs_python do
|
describe Language::Python, :needs_python do
|
||||||
describe "#major_minor_version" do
|
describe "#major_minor_version" do
|
||||||
@ -32,6 +33,48 @@ describe Language::Python, :needs_python do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe Language::Python::Shebang do
|
||||||
|
let(:file) { Tempfile.new("python-shebang") }
|
||||||
|
let(:python_f) do
|
||||||
|
formula "python" do
|
||||||
|
url "https://brew.sh/python-1.0.tgz"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
let(:f) do
|
||||||
|
formula "foo" do
|
||||||
|
url "https://brew.sh/foo-1.0.tgz"
|
||||||
|
|
||||||
|
depends_on "python"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
file.write <<~EOS
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
EOS
|
||||||
|
file.flush
|
||||||
|
end
|
||||||
|
|
||||||
|
after { file.unlink }
|
||||||
|
|
||||||
|
describe "#detected_python_shebang" do
|
||||||
|
it "can be used to replace Python shebangs" do
|
||||||
|
expect(Formulary).to receive(:factory).with(python_f.name).and_return(python_f)
|
||||||
|
Utils::Shebang.rewrite_shebang described_class.detected_python_shebang(f), file
|
||||||
|
|
||||||
|
expect(File.read(file)).to eq <<~EOS
|
||||||
|
#!#{HOMEBREW_PREFIX}/opt/python/bin/python3
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe Language::Python::Virtualenv::Virtualenv do
|
describe Language::Python::Virtualenv::Virtualenv do
|
||||||
subject { described_class.new(formula, dir, "python") }
|
subject { described_class.new(formula, dir, "python") }
|
||||||
|
|
||||||
|
|||||||
@ -157,7 +157,7 @@ describe Resource do
|
|||||||
end
|
end
|
||||||
|
|
||||||
specify "#verify_download_integrity_mismatch" do
|
specify "#verify_download_integrity_mismatch" do
|
||||||
fn = double(file?: true)
|
fn = double(file?: true, basename: "foo")
|
||||||
checksum = subject.sha256(TEST_SHA256)
|
checksum = subject.sha256(TEST_SHA256)
|
||||||
|
|
||||||
expect(fn).to receive(:verify_checksum).with(checksum)
|
expect(fn).to receive(:verify_checksum).with(checksum)
|
||||||
|
|||||||
@ -4,19 +4,23 @@ require "utils/curl"
|
|||||||
|
|
||||||
describe "curl" do
|
describe "curl" do
|
||||||
describe "curl_args" do
|
describe "curl_args" do
|
||||||
it "returns -q as the first argument when HOMEBREW_CURLRC is not set" do
|
it "returns --disable as the first argument when HOMEBREW_CURLRC is not set" do
|
||||||
# -q must be the first argument according to "man curl"
|
# --disable must be the first argument according to "man curl"
|
||||||
expect(curl_args("foo").first).to eq("-q")
|
expect(curl_args("foo").first).to eq("--disable")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't return -q as the first argument when HOMEBREW_CURLRC is set" do
|
it "doesn't return --disable as the first argument when HOMEBREW_CURLRC is set" do
|
||||||
ENV["HOMEBREW_CURLRC"] = "1"
|
ENV["HOMEBREW_CURLRC"] = "1"
|
||||||
expect(curl_args("foo").first).not_to eq("-q")
|
expect(curl_args("foo").first).not_to eq("--disable")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns --retry when HOMEBREW_CURL_RETRIES is set" do
|
it "uses `--retry 3` when HOMEBREW_CURL_RETRIES is unset" do
|
||||||
ENV["HOMEBREW_CURL_RETRIES"] = "3"
|
|
||||||
expect(curl_args("foo").join(" ")).to include("--retry 3")
|
expect(curl_args("foo").join(" ")).to include("--retry 3")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "uses the given value for `--retry` when HOMEBREW_CURL_RETRIES is set" do
|
||||||
|
ENV["HOMEBREW_CURL_RETRIES"] = "10"
|
||||||
|
expect(curl_args("foo").join(" ")).to include("--retry 10")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -41,4 +41,18 @@ describe GitHub do
|
|||||||
expect(results.first["title"]).to eq("Shall we run `brew update` automatically?")
|
expect(results.first["title"]).to eq("Shall we run `brew update` automatically?")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "::fetch_artifact", :needs_network do
|
||||||
|
it "fails to find a nonexistant workflow" do
|
||||||
|
expect {
|
||||||
|
subject.fetch_artifact("Homebrew", "homebrew-core", 1, ".")
|
||||||
|
}.to raise_error(/No matching workflow run found/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "fails to find artifacts that don't exist" do
|
||||||
|
expect {
|
||||||
|
subject.fetch_artifact("Homebrew", "homebrew-core", 51971, ".", artifact_name: "false_bottles")
|
||||||
|
}.to raise_error(/No artifact .+ was found/)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -12,7 +12,7 @@ module Utils
|
|||||||
args = []
|
args = []
|
||||||
|
|
||||||
# do not load .curlrc unless requested (must be the first argument)
|
# do not load .curlrc unless requested (must be the first argument)
|
||||||
args << "-q" unless ENV["HOMEBREW_CURLRC"]
|
args << "--disable" unless ENV["HOMEBREW_CURLRC"]
|
||||||
|
|
||||||
args += %W[
|
args += %W[
|
||||||
--max-time 3
|
--max-time 3
|
||||||
|
|||||||
@ -17,7 +17,7 @@ def curl_args(*extra_args, show_output: false, user_agent: :default)
|
|||||||
args = []
|
args = []
|
||||||
|
|
||||||
# do not load .curlrc unless requested (must be the first argument)
|
# do not load .curlrc unless requested (must be the first argument)
|
||||||
args << "-q" unless ENV["HOMEBREW_CURLRC"]
|
args << "--disable" unless ENV["HOMEBREW_CURLRC"]
|
||||||
|
|
||||||
args << "--globoff"
|
args << "--globoff"
|
||||||
|
|
||||||
@ -39,7 +39,8 @@ def curl_args(*extra_args, show_output: false, user_agent: :default)
|
|||||||
args << "--silent" unless $stdout.tty?
|
args << "--silent" unless $stdout.tty?
|
||||||
end
|
end
|
||||||
|
|
||||||
args << "--retry" << ENV["HOMEBREW_CURL_RETRIES"] if ENV["HOMEBREW_CURL_RETRIES"]
|
# When changing the default value, the manpage has to be updated.
|
||||||
|
args << "--retry" << (ENV["HOMEBREW_CURL_RETRIES"] || "3")
|
||||||
|
|
||||||
args + extra_args
|
args + extra_args
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "uri"
|
require "download_strategy"
|
||||||
require "tempfile"
|
require "tempfile"
|
||||||
|
require "uri"
|
||||||
|
|
||||||
module GitHub
|
module GitHub
|
||||||
module_function
|
module_function
|
||||||
@ -171,7 +172,7 @@ module GitHub
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def open_api(url, data: nil, request_method: nil, scopes: [].freeze)
|
def open_api(url, data: nil, request_method: nil, scopes: [].freeze, parse_json: true)
|
||||||
# This is a no-op if the user is opting out of using the GitHub API.
|
# This is a no-op if the user is opting out of using the GitHub API.
|
||||||
return block_given? ? yield({}) : {} if ENV["HOMEBREW_NO_GITHUB_API"]
|
return block_given? ? yield({}) : {} if ENV["HOMEBREW_NO_GITHUB_API"]
|
||||||
|
|
||||||
@ -226,11 +227,11 @@ module GitHub
|
|||||||
|
|
||||||
return if http_code == "204" # No Content
|
return if http_code == "204" # No Content
|
||||||
|
|
||||||
json = JSON.parse output
|
output = JSON.parse output if parse_json
|
||||||
if block_given?
|
if block_given?
|
||||||
yield json
|
yield output
|
||||||
else
|
else
|
||||||
json
|
output
|
||||||
end
|
end
|
||||||
rescue JSON::ParserError => e
|
rescue JSON::ParserError => e
|
||||||
raise Error, "Failed to parse JSON response\n#{e.message}", e.backtrace
|
raise Error, "Failed to parse JSON response\n#{e.message}", e.backtrace
|
||||||
@ -431,6 +432,80 @@ module GitHub
|
|||||||
comments.any? { |comment| comment["body"].eql?(body) }
|
comments.any? { |comment| comment["body"].eql?(body) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def dispatch_event(user, repo, event, **payload)
|
||||||
|
url = "#{API_URL}/repos/#{user}/#{repo}/dispatches"
|
||||||
|
open_api(url, data: { event_type: event, client_payload: payload },
|
||||||
|
request_method: :POST,
|
||||||
|
scopes: CREATE_ISSUE_FORK_OR_PR_SCOPES)
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_artifact(user, repo, pr, dir, workflow_id: "tests.yml", artifact_name: "bottles")
|
||||||
|
scopes = CREATE_ISSUE_FORK_OR_PR_SCOPES
|
||||||
|
base_url = "#{API_URL}/repos/#{user}/#{repo}"
|
||||||
|
pr_payload = open_api("#{base_url}/pulls/#{pr}", scopes: scopes)
|
||||||
|
pr_sha = pr_payload["head"]["sha"]
|
||||||
|
pr_branch = pr_payload["head"]["ref"]
|
||||||
|
|
||||||
|
workflow = open_api("#{base_url}/actions/workflows/#{workflow_id}/runs?branch=#{pr_branch}", scopes: scopes)
|
||||||
|
workflow_run = workflow["workflow_runs"].select do |run|
|
||||||
|
run["head_sha"] == pr_sha
|
||||||
|
end
|
||||||
|
|
||||||
|
if workflow_run.empty?
|
||||||
|
raise Error, <<~EOS
|
||||||
|
No matching workflow run found for these criteria!
|
||||||
|
Commit SHA: #{pr_sha}
|
||||||
|
Branch ref: #{pr_branch}
|
||||||
|
Pull request: #{pr}
|
||||||
|
Workflow: #{workflow_id}
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
status = workflow_run.first["status"].sub("_", " ")
|
||||||
|
if status != "completed"
|
||||||
|
raise Error, <<~EOS
|
||||||
|
The newest workflow run for ##{pr} is still #{status}!
|
||||||
|
#{Formatter.url workflow_run.first["html_url"]}
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
artifacts = open_api(workflow_run.first["artifacts_url"], scopes: scopes)
|
||||||
|
|
||||||
|
artifact = artifacts["artifacts"].select do |art|
|
||||||
|
art["name"] == artifact_name
|
||||||
|
end
|
||||||
|
|
||||||
|
if artifact.empty?
|
||||||
|
raise Error, <<~EOS
|
||||||
|
No artifact with the name `#{artifact_name}` was found!
|
||||||
|
#{Formatter.url workflow_run.first["html_url"]}
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
artifact_url = artifact.first["archive_download_url"]
|
||||||
|
|
||||||
|
token, username = api_credentials
|
||||||
|
case api_credentials_type
|
||||||
|
when :env_username_password, :keychain_username_password
|
||||||
|
curl_args = { user: "#{username}:#{token}" }
|
||||||
|
when :env_token
|
||||||
|
curl_args = { header: "Authorization: token #{token}" }
|
||||||
|
when :none
|
||||||
|
raise Error, "Credentials must be set to access the Artifacts API"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Download the artifact as a zip file and unpack it into `dir`. This is
|
||||||
|
# preferred over system `curl` and `tar` as this leverages the Homebrew
|
||||||
|
# cache to avoid repeated downloads of (possibly large) bottles.
|
||||||
|
FileUtils.chdir dir do
|
||||||
|
curl_args[:cache] = Pathname.new(dir)
|
||||||
|
curl_args[:secrets] = [token]
|
||||||
|
downloader = CurlDownloadStrategy.new(artifact_url, "artifact", pr, **curl_args)
|
||||||
|
downloader.fetch
|
||||||
|
downloader.stage
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def api_errors
|
def api_errors
|
||||||
[GitHub::AuthenticationFailedError, GitHub::HTTPNotFoundError,
|
[GitHub::AuthenticationFailedError, GitHub::HTTPNotFoundError,
|
||||||
GitHub::RateLimitExceededError, GitHub::Error, JSON::ParserError].freeze
|
GitHub::RateLimitExceededError, GitHub::Error, JSON::ParserError].freeze
|
||||||
|
|||||||
27
Library/Homebrew/utils/shebang.rb
Normal file
27
Library/Homebrew/utils/shebang.rb
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Utils
|
||||||
|
module Shebang
|
||||||
|
module_function
|
||||||
|
|
||||||
|
class RewriteInfo
|
||||||
|
attr_reader :regex, :max_length, :replacement
|
||||||
|
|
||||||
|
def initialize(regex, max_length, replacement)
|
||||||
|
@regex = regex
|
||||||
|
@max_length = max_length
|
||||||
|
@replacement = replacement
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def rewrite_shebang(rewrite_info, *paths)
|
||||||
|
paths.each do |f|
|
||||||
|
f = Pathname(f)
|
||||||
|
next unless f.file?
|
||||||
|
next unless rewrite_info.regex.match?(f.read(rewrite_info.max_length))
|
||||||
|
|
||||||
|
Utils::Inreplace.inreplace f.to_s, rewrite_info.regex, "#!#{rewrite_info.replacement}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -9,7 +9,7 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.14.0/lib"
|
|||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-1.2.6/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-1.2.6/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/zeitwerk-2.3.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/zeitwerk-2.3.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-6.0.2.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-6.0.2.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ast-2.4.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ast-2.4.0/lib"
|
||||||
$:.unshift "#{path}/"
|
$:.unshift "#{path}/"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/connection_pool-2.2.2/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/connection_pool-2.2.2/lib"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user