Merge pull request #7227 from Bo98/perl
utils/shebang: add rewrite_shebang (+ Perl & improved Python support)
This commit is contained in:
commit
6530e333b3
@ -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
|
||||||
@ -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
|
||||||
extend Enumerable
|
extend Enumerable
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
|
|||||||
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
|
||||||
|
|
||||||
|
|||||||
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)
|
||||||
|
|||||||
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
|
||||||
Loading…
x
Reference in New Issue
Block a user