2020-10-10 14:16:11 +02:00
|
|
|
# typed: false
|
2019-04-19 15:38:03 +09:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2015-08-03 13:09:07 +01:00
|
|
|
require "formula"
|
2018-06-03 15:28:48 +05:30
|
|
|
require "formula_creator"
|
2017-03-18 17:02:08 +02:00
|
|
|
require "missing_formula"
|
2019-04-17 18:25:08 +09:00
|
|
|
require "cli/parser"
|
2020-07-27 10:38:50 -04:00
|
|
|
require "utils/pypi"
|
2020-11-20 12:13:53 +01:00
|
|
|
require "cask/cask_loader"
|
2010-09-11 20:22:54 +01:00
|
|
|
|
2014-06-18 22:41:47 -05:00
|
|
|
module Homebrew
|
2020-10-20 12:03:48 +02:00
|
|
|
extend T::Sig
|
|
|
|
|
2016-09-26 01:44:51 +02:00
|
|
|
module_function
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(CLI::Parser) }
|
2018-07-30 18:25:38 +05:30
|
|
|
def create_args
|
|
|
|
Homebrew::CLI::Parser.new do
|
2018-09-28 21:39:52 +05:30
|
|
|
usage_banner <<~EOS
|
2018-10-15 15:06:33 -04:00
|
|
|
`create` [<options>] <URL>
|
2018-09-28 21:39:52 +05:30
|
|
|
|
2020-11-20 12:13:53 +01:00
|
|
|
Generate a formula or, with `--cask`, a cask for the downloadable file at <URL>
|
|
|
|
and open it in the editor. Homebrew will attempt to automatically derive the
|
|
|
|
formula name and version, but if it fails, you'll have to make your own template.
|
|
|
|
The `wget` formula serves as a simple example. For the complete API, see:
|
2020-07-23 16:00:03 -04:00
|
|
|
<https://rubydoc.brew.sh/Formula>
|
2018-09-28 21:39:52 +05:30
|
|
|
EOS
|
|
|
|
switch "--autotools",
|
2019-04-30 08:44:35 +01:00
|
|
|
description: "Create a basic template for an Autotools-style build."
|
2020-11-20 12:13:53 +01:00
|
|
|
switch "--cask",
|
|
|
|
description: "Create a basic template for a cask."
|
2018-09-28 21:39:52 +05:30
|
|
|
switch "--cmake",
|
2019-04-30 08:44:35 +01:00
|
|
|
description: "Create a basic template for a CMake-style build."
|
2020-06-25 17:17:42 +02:00
|
|
|
switch "--crystal",
|
|
|
|
description: "Create a basic template for a Crystal build."
|
2019-09-24 16:49:27 +02:00
|
|
|
switch "--go",
|
|
|
|
description: "Create a basic template for a Go build."
|
2018-09-28 21:39:52 +05:30
|
|
|
switch "--meson",
|
2019-04-30 08:44:35 +01:00
|
|
|
description: "Create a basic template for a Meson-style build."
|
2020-07-12 21:25:01 -07:00
|
|
|
switch "--node",
|
|
|
|
description: "Create a basic template for a Node build."
|
2019-09-25 21:52:16 +02:00
|
|
|
switch "--perl",
|
|
|
|
description: "Create a basic template for a Perl build."
|
2019-09-24 19:34:34 +02:00
|
|
|
switch "--python",
|
|
|
|
description: "Create a basic template for a Python build."
|
2020-03-21 15:32:52 +01:00
|
|
|
switch "--ruby",
|
|
|
|
description: "Create a basic template for a Ruby build."
|
2019-09-25 14:29:09 +02:00
|
|
|
switch "--rust",
|
|
|
|
description: "Create a basic template for a Rust build."
|
2018-09-28 21:39:52 +05:30
|
|
|
switch "--no-fetch",
|
2019-08-20 00:04:14 -04:00
|
|
|
description: "Homebrew will not download <URL> to the cache and will thus not add its SHA-256 "\
|
2019-04-30 08:44:35 +01:00
|
|
|
"to the formula for you, nor will it check the GitHub API for GitHub projects "\
|
|
|
|
"(to fill out its description and homepage)."
|
2018-10-08 22:49:03 -04:00
|
|
|
switch "--HEAD",
|
2019-04-30 08:44:35 +01:00
|
|
|
description: "Indicate that <URL> points to the package's repository rather than a file."
|
2018-09-28 21:39:52 +05:30
|
|
|
flag "--set-name=",
|
2020-12-07 23:37:54 -05:00
|
|
|
description: "Explicitly set the <name> of the new formula or cask."
|
2018-09-28 21:39:52 +05:30
|
|
|
flag "--set-version=",
|
2020-11-20 12:13:53 +01:00
|
|
|
description: "Explicitly set the <version> of the new formula or cask."
|
2020-06-17 22:52:25 +08:00
|
|
|
flag "--set-license=",
|
|
|
|
description: "Explicitly set the <license> of the new formula."
|
2018-09-28 21:39:52 +05:30
|
|
|
flag "--tap=",
|
2019-08-20 00:04:14 -04:00
|
|
|
description: "Generate the new formula within the given tap, specified as <user>`/`<repo>."
|
2020-07-27 03:59:52 +02:00
|
|
|
switch "-f", "--force",
|
2020-11-12 10:40:48 -05:00
|
|
|
description: "Ignore errors for disallowed formula names and names that shadow aliases."
|
2020-07-30 18:40:10 +02:00
|
|
|
|
2020-11-20 12:13:53 +01:00
|
|
|
conflicts "--autotools", "--cmake", "--crystal", "--go", "--meson", "--node",
|
|
|
|
"--perl", "--python", "--ruby", "--rust", "--cask"
|
|
|
|
conflicts "--cask", "--HEAD"
|
|
|
|
conflicts "--cask", "--set-license"
|
|
|
|
|
2021-01-10 14:26:40 -05:00
|
|
|
named_args number: 1
|
2018-06-03 01:15:28 +05:30
|
|
|
end
|
2018-07-30 18:25:38 +05:30
|
|
|
end
|
|
|
|
|
2020-11-05 17:17:03 -05:00
|
|
|
# Create a formula from a tarball URL.
|
2018-07-30 18:25:38 +05:30
|
|
|
def create
|
2020-07-23 03:08:19 +02:00
|
|
|
args = create_args.parse
|
2018-07-30 18:25:38 +05:30
|
|
|
|
2020-11-20 12:13:53 +01:00
|
|
|
path = if args.cask?
|
|
|
|
create_cask(args: args)
|
|
|
|
else
|
|
|
|
create_formula(args: args)
|
|
|
|
end
|
|
|
|
|
|
|
|
exec_editor path
|
|
|
|
end
|
|
|
|
|
|
|
|
def create_cask(args:)
|
|
|
|
url = args.named.first
|
|
|
|
|
|
|
|
if (token = args.set_name).nil?
|
|
|
|
raise UsageError, "The `--set-name` flag is required for creating casks."
|
|
|
|
end
|
|
|
|
|
2020-12-15 12:55:07 -05:00
|
|
|
cask_tap = Tap.fetch(args.tap || "homebrew/cask")
|
|
|
|
raise TapUnavailableError, args.tap unless cask_tap.installed?
|
|
|
|
|
|
|
|
cask_path = Cask::CaskLoader.path("#{cask_tap}/#{token}")
|
|
|
|
cask_path.dirname.mkpath unless cask_path.dirname.exist?
|
2020-11-20 12:13:53 +01:00
|
|
|
raise Cask::CaskAlreadyCreatedError, token if cask_path.exist?
|
|
|
|
|
|
|
|
version = if args.set_version
|
|
|
|
Version.create(args.set_version)
|
|
|
|
else
|
|
|
|
Version.detect(url.gsub(token, ""))
|
|
|
|
end
|
|
|
|
|
|
|
|
interpolated_url, sha256 = if version.null?
|
|
|
|
[url, ""]
|
|
|
|
else
|
|
|
|
sha256 = if args.no_fetch?
|
|
|
|
""
|
|
|
|
else
|
|
|
|
strategy = DownloadStrategyDetector.detect(url)
|
|
|
|
downloader = strategy.new(url, token, version.to_s, cache: Cask::Cache.path)
|
|
|
|
downloader.fetch
|
|
|
|
downloader.cached_location.sha256
|
|
|
|
end
|
|
|
|
|
|
|
|
[url.gsub(version.to_s, "\#{version}"), sha256]
|
|
|
|
end
|
2012-08-22 19:42:01 -07:00
|
|
|
|
2020-11-20 12:13:53 +01:00
|
|
|
cask_path.atomic_write <<~RUBY
|
|
|
|
cask "#{token}" do
|
|
|
|
version "#{version}"
|
|
|
|
sha256 "#{sha256}"
|
2012-08-22 19:42:01 -07:00
|
|
|
|
2020-11-20 12:13:53 +01:00
|
|
|
url "#{interpolated_url}"
|
|
|
|
name ""
|
|
|
|
desc ""
|
|
|
|
homepage ""
|
|
|
|
|
|
|
|
app ""
|
|
|
|
end
|
|
|
|
RUBY
|
|
|
|
|
|
|
|
puts "Please run `brew audit --cask --new #{token}` before submitting, thanks."
|
|
|
|
cask_path
|
|
|
|
end
|
2012-08-22 19:42:01 -07:00
|
|
|
|
2020-11-20 12:13:53 +01:00
|
|
|
def create_formula(args:)
|
2020-07-23 03:08:19 +02:00
|
|
|
fc = FormulaCreator.new(args)
|
2020-12-07 23:37:54 -05:00
|
|
|
fc.name = args.set_name
|
|
|
|
fc.version = args.set_version
|
|
|
|
fc.license = args.set_license
|
2020-11-20 12:13:53 +01:00
|
|
|
fc.tap = Tap.fetch(args.tap || "homebrew/core")
|
2020-12-15 12:55:07 -05:00
|
|
|
raise TapUnavailableError, args.tap unless fc.tap.installed?
|
2018-09-17 02:45:00 +02:00
|
|
|
|
2020-11-20 12:13:53 +01:00
|
|
|
fc.url = args.named.first # Pull the first (and only) url from ARGV
|
2012-08-22 19:42:01 -07:00
|
|
|
|
2020-12-07 23:37:54 -05:00
|
|
|
fc.mode = if args.autotools?
|
2012-08-22 19:42:01 -07:00
|
|
|
:autotools
|
2020-12-07 23:37:54 -05:00
|
|
|
elsif args.cmake?
|
|
|
|
:cmake
|
2020-06-25 17:17:42 +02:00
|
|
|
elsif args.crystal?
|
|
|
|
:crystal
|
2019-09-24 16:49:27 +02:00
|
|
|
elsif args.go?
|
|
|
|
:go
|
2020-12-07 23:37:54 -05:00
|
|
|
elsif args.meson?
|
|
|
|
:meson
|
2020-07-12 21:25:01 -07:00
|
|
|
elsif args.node?
|
|
|
|
:node
|
2019-09-25 21:52:16 +02:00
|
|
|
elsif args.perl?
|
|
|
|
:perl
|
2019-09-24 19:34:34 +02:00
|
|
|
elsif args.python?
|
|
|
|
:python
|
2020-03-21 15:32:52 +01:00
|
|
|
elsif args.ruby?
|
|
|
|
:ruby
|
2019-09-25 14:29:09 +02:00
|
|
|
elsif args.rust?
|
|
|
|
:rust
|
2012-08-22 19:42:01 -07:00
|
|
|
end
|
|
|
|
|
2014-07-17 19:40:44 -05:00
|
|
|
if fc.name.nil? || fc.name.strip.empty?
|
2020-12-07 23:37:54 -05:00
|
|
|
stem = Pathname.new(fc.url).stem.rpartition("=").last
|
2014-07-17 19:40:44 -05:00
|
|
|
print "Formula name [#{stem}]: "
|
|
|
|
fc.name = __gets || stem
|
2016-06-23 23:23:41 -07:00
|
|
|
fc.update_path
|
2012-08-22 19:42:01 -07:00
|
|
|
end
|
|
|
|
|
2020-06-06 21:10:16 +01:00
|
|
|
# Check for disallowed formula, or names that shadow aliases,
|
2012-08-22 19:42:01 -07:00
|
|
|
# unless --force is specified.
|
2018-06-03 01:15:28 +05:30
|
|
|
unless args.force?
|
2020-06-06 21:10:16 +01:00
|
|
|
if reason = MissingFormula.disallowed_reason(fc.name)
|
2018-09-02 16:15:09 +01:00
|
|
|
raise <<~EOS
|
2020-12-07 23:37:54 -05:00
|
|
|
The formula '#{fc.name}' is not allowed to be created.
|
2018-09-02 16:15:09 +01:00
|
|
|
#{reason}
|
2020-12-07 23:37:54 -05:00
|
|
|
If you really want to create this formula use `--force`.
|
2018-09-02 16:15:09 +01:00
|
|
|
EOS
|
2012-08-22 19:42:01 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
if Formula.aliases.include? fc.name
|
2014-06-22 15:00:15 -05:00
|
|
|
realname = Formulary.canonical_name(fc.name)
|
2017-10-15 02:28:32 +02:00
|
|
|
raise <<~EOS
|
2020-12-07 23:37:54 -05:00
|
|
|
The formula '#{realname}' is already aliased to '#{fc.name}'.
|
2012-08-22 19:42:01 -07:00
|
|
|
Please check that you are not creating a duplicate.
|
2020-12-07 23:37:54 -05:00
|
|
|
To force creation use `--force`.
|
2018-06-06 23:34:19 -04:00
|
|
|
EOS
|
2010-09-11 20:22:54 +01:00
|
|
|
end
|
|
|
|
end
|
2012-08-22 19:42:01 -07:00
|
|
|
|
|
|
|
fc.generate!
|
|
|
|
|
2020-07-27 10:38:50 -04:00
|
|
|
PyPI.update_python_resources! Formula[fc.name], ignore_non_pypi_packages: true if args.python?
|
|
|
|
|
2020-11-20 12:13:53 +01:00
|
|
|
puts "Please run `brew audit --new #{fc.name}` before submitting, thanks."
|
|
|
|
fc.path
|
2010-09-11 20:22:54 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def __gets
|
|
|
|
gots = $stdin.gets.chomp
|
2016-09-11 17:41:51 +01:00
|
|
|
gots.empty? ? nil : gots
|
2010-09-11 20:22:54 +01:00
|
|
|
end
|
|
|
|
end
|