2020-10-10 14:16:11 +02:00
|
|
|
# typed: true
|
2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2018-06-03 15:28:48 +05:30
|
|
|
require "digest"
|
|
|
|
require "erb"
|
|
|
|
|
|
|
|
module Homebrew
|
2020-08-17 05:53:46 +02:00
|
|
|
# Class for generating a formula from a template.
|
|
|
|
#
|
|
|
|
# @api private
|
2018-06-03 15:28:48 +05:30
|
|
|
class FormulaCreator
|
2023-11-27 20:16:45 +00:00
|
|
|
attr_reader :url, :sha256, :desc, :homepage
|
2023-11-20 14:03:50 +00:00
|
|
|
attr_accessor :name, :version, :tap, :mode, :license
|
2018-06-03 15:28:48 +05:30
|
|
|
|
2023-11-27 20:16:45 +00:00
|
|
|
def initialize(fetch=true, head=false)
|
2023-11-27 20:10:23 +00:00
|
|
|
@fetch = fetch
|
2023-11-27 20:16:45 +00:00
|
|
|
@head = head
|
2020-07-23 03:08:19 +02:00
|
|
|
end
|
|
|
|
|
2018-06-03 15:28:48 +05:30
|
|
|
def url=(url)
|
|
|
|
@url = url
|
|
|
|
path = Pathname.new(url)
|
|
|
|
if @name.nil?
|
|
|
|
case url
|
|
|
|
when %r{github\.com/(\S+)/(\S+)\.git}
|
|
|
|
@user = Regexp.last_match(1)
|
|
|
|
@name = Regexp.last_match(2)
|
|
|
|
@head = true
|
|
|
|
@github = true
|
|
|
|
when %r{github\.com/(\S+)/(\S+)/(archive|releases)/}
|
|
|
|
@user = Regexp.last_match(1)
|
|
|
|
@name = Regexp.last_match(2)
|
|
|
|
@github = true
|
|
|
|
else
|
|
|
|
@name = path.basename.to_s[/(.*?)[-_.]?#{Regexp.escape(path.version.to_s)}/, 1]
|
|
|
|
end
|
|
|
|
end
|
2020-03-13 21:14:24 +00:00
|
|
|
@version = if @version
|
2023-07-06 16:47:09 +01:00
|
|
|
Version.new(@version)
|
2018-06-03 15:28:48 +05:30
|
|
|
else
|
2020-08-09 02:59:18 +02:00
|
|
|
Version.detect(url)
|
2018-06-03 15:28:48 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-11-23 18:04:03 +03:00
|
|
|
def write_formula!
|
2023-11-23 18:53:22 +03:00
|
|
|
raise ArgumentError, "name is blank!" if @name.blank?
|
|
|
|
raise ArgumentError, "tap is blank!" if @tap.blank?
|
2023-11-23 18:12:12 +03:00
|
|
|
|
2023-11-20 14:03:50 +00:00
|
|
|
path = @tap.new_formula_path(@name)
|
2018-06-03 15:28:48 +05:30
|
|
|
raise "#{path} already exists" if path.exist?
|
|
|
|
|
|
|
|
if version.nil? || version.null?
|
2023-09-08 14:46:15 -04:00
|
|
|
odie "Version cannot be determined from URL. Explicitly set the version with `--set-version` instead."
|
2023-11-27 20:10:23 +00:00
|
|
|
elsif @fetch
|
2023-11-27 20:16:45 +00:00
|
|
|
unless @head
|
2018-06-03 15:28:48 +05:30
|
|
|
r = Resource.new
|
|
|
|
r.url(url)
|
|
|
|
r.version(version)
|
|
|
|
r.owner = self
|
|
|
|
@sha256 = r.fetch.sha256 if r.download_strategy == CurlDownloadStrategy
|
|
|
|
end
|
|
|
|
|
|
|
|
if @user && @name
|
|
|
|
begin
|
|
|
|
metadata = GitHub.repository(@user, @name)
|
|
|
|
@desc = metadata["description"]
|
|
|
|
@homepage = metadata["homepage"]
|
2020-09-04 00:12:05 -04:00
|
|
|
@license = metadata["license"]["spdx_id"] if metadata["license"]
|
2021-02-15 21:48:21 +05:30
|
|
|
rescue GitHub::API::HTTPNotFoundError
|
2018-06-03 15:28:48 +05:30
|
|
|
# If there was no repository found assume the network connection is at
|
|
|
|
# fault rather than the input URL.
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-05-03 13:24:32 +01:00
|
|
|
path.dirname.mkpath
|
2019-10-13 10:09:38 +01:00
|
|
|
path.write ERB.new(template, trim_mode: ">").result(binding)
|
2023-11-20 14:03:50 +00:00
|
|
|
path
|
2018-06-03 15:28:48 +05:30
|
|
|
end
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(String) }
|
2018-06-03 15:28:48 +05:30
|
|
|
def template
|
2018-07-11 15:17:40 +02:00
|
|
|
<<~ERB
|
2018-06-03 15:28:48 +05:30
|
|
|
# Documentation: https://docs.brew.sh/Formula-Cookbook
|
2019-03-28 21:15:50 +00:00
|
|
|
# https://rubydoc.brew.sh/Formula
|
2018-06-03 15:28:48 +05:30
|
|
|
# PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST!
|
2020-07-12 21:25:01 -07:00
|
|
|
<% if mode == :node %>
|
|
|
|
require "language/node"
|
|
|
|
|
|
|
|
<% end %>
|
2018-06-03 15:28:48 +05:30
|
|
|
class #{Formulary.class_s(name)} < Formula
|
2019-09-24 19:34:34 +02:00
|
|
|
<% if mode == :python %>
|
|
|
|
include Language::Python::Virtualenv
|
|
|
|
|
|
|
|
<% end %>
|
2018-06-03 15:28:48 +05:30
|
|
|
desc "#{desc}"
|
|
|
|
homepage "#{homepage}"
|
2023-11-27 20:16:45 +00:00
|
|
|
<% unless @head %>
|
2018-06-03 15:28:48 +05:30
|
|
|
url "#{url}"
|
2023-07-22 12:46:45 -04:00
|
|
|
<% unless version.detected_from_url? %>
|
2018-06-03 15:28:48 +05:30
|
|
|
version "#{version}"
|
|
|
|
<% end %>
|
|
|
|
sha256 "#{sha256}"
|
|
|
|
<% end %>
|
2020-06-16 01:18:40 +08:00
|
|
|
license "#{license}"
|
2023-11-27 20:16:45 +00:00
|
|
|
<% if @head %>
|
2020-07-14 17:37:55 -07:00
|
|
|
head "#{url}"
|
|
|
|
<% end %>
|
2019-07-17 14:26:32 +10:00
|
|
|
|
2018-06-03 15:28:48 +05:30
|
|
|
<% if mode == :cmake %>
|
|
|
|
depends_on "cmake" => :build
|
2020-06-25 17:17:42 +02:00
|
|
|
<% elsif mode == :crystal %>
|
|
|
|
depends_on "crystal" => :build
|
2019-09-24 16:49:27 +02:00
|
|
|
<% elsif mode == :go %>
|
2019-09-20 16:09:01 +02:00
|
|
|
depends_on "go" => :build
|
2018-06-03 15:28:48 +05:30
|
|
|
<% elsif mode == :meson %>
|
2019-05-12 09:14:25 +01:00
|
|
|
depends_on "meson" => :build
|
2018-06-03 15:28:48 +05:30
|
|
|
depends_on "ninja" => :build
|
2020-07-12 21:25:01 -07:00
|
|
|
<% elsif mode == :node %>
|
|
|
|
depends_on "node"
|
2019-09-25 21:52:16 +02:00
|
|
|
<% elsif mode == :perl %>
|
|
|
|
uses_from_macos "perl"
|
2019-09-24 19:34:34 +02:00
|
|
|
<% elsif mode == :python %>
|
|
|
|
depends_on "python"
|
2020-03-21 15:32:52 +01:00
|
|
|
<% elsif mode == :ruby %>
|
|
|
|
uses_from_macos "ruby"
|
2019-09-25 14:29:09 +02:00
|
|
|
<% elsif mode == :rust %>
|
|
|
|
depends_on "rust" => :build
|
2018-06-03 15:28:48 +05:30
|
|
|
<% elsif mode.nil? %>
|
|
|
|
# depends_on "cmake" => :build
|
|
|
|
<% end %>
|
|
|
|
|
2020-07-27 10:38:50 -04:00
|
|
|
<% if mode == :perl %>
|
2019-09-25 21:52:16 +02:00
|
|
|
# Additional dependency
|
2019-09-25 13:41:56 +02:00
|
|
|
# resource "" do
|
|
|
|
# url ""
|
|
|
|
# sha256 ""
|
|
|
|
# end
|
|
|
|
|
|
|
|
<% end %>
|
2018-06-03 15:28:48 +05:30
|
|
|
def install
|
|
|
|
# ENV.deparallelize # if your formula fails when building in parallel
|
|
|
|
<% if mode == :cmake %>
|
2021-03-15 03:22:41 +00:00
|
|
|
system "cmake", "-S", ".", "-B", "build", *std_cmake_args
|
|
|
|
system "cmake", "--build", "build"
|
|
|
|
system "cmake", "--install", "build"
|
2018-06-03 15:28:48 +05:30
|
|
|
<% elsif mode == :autotools %>
|
|
|
|
# Remove unrecognized options if warned by configure
|
2021-03-08 12:57:35 -08:00
|
|
|
# https://rubydoc.brew.sh/Formula.html#std_configure_args-instance_method
|
2021-03-06 13:13:58 -08:00
|
|
|
system "./configure", *std_configure_args, "--disable-silent-rules"
|
2021-03-15 03:22:41 +00:00
|
|
|
system "make", "install" # if this fails, try separate make/make install steps
|
2020-06-25 17:17:42 +02:00
|
|
|
<% elsif mode == :crystal %>
|
|
|
|
system "shards", "build", "--release"
|
|
|
|
bin.install "bin/#{name}"
|
2019-09-24 16:49:27 +02:00
|
|
|
<% elsif mode == :go %>
|
2021-08-22 14:30:26 -04:00
|
|
|
system "go", "build", *std_go_args(ldflags: "-s -w")
|
2018-06-03 15:28:48 +05:30
|
|
|
<% elsif mode == :meson %>
|
2022-11-30 12:27:46 -08:00
|
|
|
system "meson", "setup", "build", *std_meson_args
|
|
|
|
system "meson", "compile", "-C", "build", "--verbose"
|
|
|
|
system "meson", "install", "-C", "build"
|
2020-07-12 21:25:01 -07:00
|
|
|
<% elsif mode == :node %>
|
|
|
|
system "npm", "install", *Language::Node.std_npm_install_args(libexec)
|
|
|
|
bin.install_symlink Dir["\#{libexec}/bin/*"]
|
2019-09-25 21:52:16 +02:00
|
|
|
<% elsif mode == :perl %>
|
|
|
|
ENV.prepend_create_path "PERL5LIB", libexec/"lib/perl5"
|
|
|
|
ENV.prepend_path "PERL5LIB", libexec/"lib"
|
|
|
|
|
|
|
|
# Stage additional dependency (Makefile.PL style)
|
|
|
|
# resource("").stage do
|
|
|
|
# system "perl", "Makefile.PL", "INSTALL_BASE=\#{libexec}"
|
|
|
|
# system "make"
|
|
|
|
# system "make", "install"
|
|
|
|
# end
|
|
|
|
|
|
|
|
# Stage additional dependency (Build.PL style)
|
|
|
|
# resource("").stage do
|
|
|
|
# system "perl", "Build.PL", "--install_base", libexec
|
|
|
|
# system "./Build"
|
|
|
|
# system "./Build", "install"
|
|
|
|
# end
|
|
|
|
|
|
|
|
bin.install name
|
2020-12-28 14:17:36 -08:00
|
|
|
bin.env_script_all_files(libexec/"bin", PERL5LIB: ENV["PERL5LIB"])
|
2019-09-24 19:34:34 +02:00
|
|
|
<% elsif mode == :python %>
|
|
|
|
virtualenv_install_with_resources
|
2020-03-21 15:32:52 +01:00
|
|
|
<% elsif mode == :ruby %>
|
|
|
|
ENV["GEM_HOME"] = libexec
|
|
|
|
system "gem", "build", "\#{name}.gemspec"
|
|
|
|
system "gem", "install", "\#{name}-\#{version}.gem"
|
|
|
|
bin.install libexec/"bin/\#{name}"
|
2020-12-28 14:17:36 -08:00
|
|
|
bin.env_script_all_files(libexec/"bin", GEM_HOME: ENV["GEM_HOME"])
|
2019-09-25 14:29:09 +02:00
|
|
|
<% elsif mode == :rust %>
|
2020-06-22 13:24:41 +02:00
|
|
|
system "cargo", "install", *std_cargo_args
|
2018-06-03 15:28:48 +05:30
|
|
|
<% else %>
|
|
|
|
# Remove unrecognized options if warned by configure
|
2021-03-08 12:57:35 -08:00
|
|
|
# https://rubydoc.brew.sh/Formula.html#std_configure_args-instance_method
|
2021-03-06 13:13:58 -08:00
|
|
|
system "./configure", *std_configure_args, "--disable-silent-rules"
|
2021-03-15 03:22:41 +00:00
|
|
|
# system "cmake", "-S", ".", "-B", "build", *std_cmake_args
|
2018-06-03 15:28:48 +05:30
|
|
|
<% end %>
|
|
|
|
end
|
|
|
|
|
|
|
|
test do
|
|
|
|
# `test do` will create, run in and delete a temporary directory.
|
|
|
|
#
|
|
|
|
# This test will fail and we won't accept that! For Homebrew/homebrew-core
|
|
|
|
# this will need to be a test that verifies the functionality of the
|
|
|
|
# software. Run the test with `brew test #{name}`. Options passed
|
|
|
|
# to `brew install` such as `--HEAD` also need to be provided to `brew test`.
|
|
|
|
#
|
|
|
|
# The installed folder is not in the path, so use the entire path to any
|
|
|
|
# executables being tested: `system "\#{bin}/program", "do", "something"`.
|
|
|
|
system "false"
|
|
|
|
end
|
|
|
|
end
|
2018-07-11 15:17:40 +02:00
|
|
|
ERB
|
2018-06-03 15:28:48 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|