diff --git a/Library/Homebrew/cask/exceptions.rb b/Library/Homebrew/cask/exceptions.rb index 9778c29725..852fa8b3ed 100644 --- a/Library/Homebrew/cask/exceptions.rb +++ b/Library/Homebrew/cask/exceptions.rb @@ -111,7 +111,7 @@ module Cask sig { returns(String) } def to_s - %Q(Cask '#{token}' already exists. Run #{Formatter.identifier("brew cask edit #{token}")} to edit it.) + %Q(Cask '#{token}' already exists. Run #{Formatter.identifier("brew edit --cask #{token}")} to edit it.) end end diff --git a/Library/Homebrew/dev-cmd/create.rb b/Library/Homebrew/dev-cmd/create.rb index ea4b8a38a1..3575710c4d 100644 --- a/Library/Homebrew/dev-cmd/create.rb +++ b/Library/Homebrew/dev-cmd/create.rb @@ -6,6 +6,7 @@ require "formula_creator" require "missing_formula" require "cli/parser" require "utils/pypi" +require "cask/cask_loader" module Homebrew extend T::Sig @@ -18,14 +19,16 @@ module Homebrew usage_banner <<~EOS `create` [] - Generate a formula for the downloadable file at 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: + Generate a formula or, with `--cask`, a cask for the downloadable file at + 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: EOS switch "--autotools", description: "Create a basic template for an Autotools-style build." + switch "--cask", + description: "Create a basic template for a cask." switch "--cmake", description: "Create a basic template for a CMake-style build." switch "--crystal", @@ -51,9 +54,10 @@ module Homebrew switch "--HEAD", description: "Indicate that points to the package's repository rather than a file." flag "--set-name=", - description: "Explicitly set the of the new formula." + description: "Explicitly set the of the new formula or cask.", + required_for: "--cask" flag "--set-version=", - description: "Explicitly set the of the new formula." + description: "Explicitly set the of the new formula or cask." flag "--set-license=", description: "Explicitly set the of the new formula." flag "--tap=", @@ -61,7 +65,12 @@ module Homebrew switch "-f", "--force", description: "Ignore errors for disallowed formula names and names that shadow aliases." - conflicts "--autotools", "--cmake", "--crystal", "--go", "--meson", "--node", "--perl", "--python", "--rust" + conflicts "--autotools", "--cmake", "--crystal", "--go", "--meson", "--node", + "--perl", "--python", "--ruby", "--rust", "--cask" + conflicts "--cask", "--HEAD" + conflicts "--cask", "--set-license" + conflicts "--cask", "--tap" + named 1 end end @@ -70,24 +79,73 @@ module Homebrew def create args = create_args.parse - # Ensure that the cache exists so we can fetch the tarball - HOMEBREW_CACHE.mkpath + path = if args.cask? + create_cask(args: args) + else + create_formula(args: args) + end - url = args.named.first # Pull the first (and only) url from ARGV + exec_editor path + end - version = args.set_version - name = args.set_name - license = args.set_license - tap = args.tap + 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 + + cask_path = Cask::CaskLoader.path(token) + 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 + + cask_path.atomic_write <<~RUBY + cask "#{token}" do + version "#{version}" + sha256 "#{sha256}" + + url "#{interpolated_url}" + name "" + desc "" + homepage "" + + app "" + end + RUBY + + puts "Please run `brew audit --cask --new #{token}` before submitting, thanks." + cask_path + end + + def create_formula(args:) fc = FormulaCreator.new(args) - fc.name = name - fc.version = version - fc.license = license - fc.tap = Tap.fetch(tap || "homebrew/core") + fc.name = args.name + fc.version = args.version + fc.license = args.license + fc.tap = Tap.fetch(args.tap || "homebrew/core") raise TapUnavailableError, tap unless fc.tap.installed? - fc.url = url + fc.url = args.named.first # Pull the first (and only) url from ARGV fc.mode = if args.cmake? :cmake @@ -143,8 +201,8 @@ module Homebrew PyPI.update_python_resources! Formula[fc.name], ignore_non_pypi_packages: true if args.python? - puts "Please run `brew audit --new-formula #{fc.name}` before submitting, thanks." - exec_editor fc.path + puts "Please run `brew audit --new #{fc.name}` before submitting, thanks." + fc.path end def __gets diff --git a/docs/Manpage.md b/docs/Manpage.md index 9e25a8c0c8..586a1639b7 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -946,14 +946,16 @@ Display the path to the file being used when invoking `brew` *`cmd`*. ### `create` [*`options`*] *`URL`* -Generate a formula 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: +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: * `--autotools`: Create a basic template for an Autotools-style build. +* `--cask`: + Create a basic template for a cask. * `--cmake`: Create a basic template for a CMake-style build. * `--crystal`: @@ -977,9 +979,9 @@ a simple example. For the complete API, see: * `--HEAD`: Indicate that *`URL`* points to the package's repository rather than a file. * `--set-name`: - Explicitly set the *`name`* of the new formula. + Explicitly set the *`name`* of the new formula or cask. * `--set-version`: - Explicitly set the *`version`* of the new formula. + Explicitly set the *`version`* of the new formula or cask. * `--set-license`: Explicitly set the *`license`* of the new formula. * `--tap`: diff --git a/manpages/brew.1 b/manpages/brew.1 index ffa16f11d4..0b237b463f 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -1316,13 +1316,17 @@ Treat all named arguments as casks\. Display the path to the file being used when invoking \fBbrew\fR \fIcmd\fR\. . .SS "\fBcreate\fR [\fIoptions\fR] \fIURL\fR" -Generate a formula for the downloadable file at \fIURL\fR 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 \fBwget\fR formula serves as a simple example\. For the complete API, see: \fIhttps://rubydoc\.brew\.sh/Formula\fR +Generate a formula or, with \fB\-\-cask\fR, a cask for the downloadable file at \fIURL\fR 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 \fBwget\fR formula serves as a simple example\. For the complete API, see: \fIhttps://rubydoc\.brew\.sh/Formula\fR . .TP \fB\-\-autotools\fR Create a basic template for an Autotools\-style build\. . .TP +\fB\-\-cask\fR +Create a basic template for a cask\. +. +.TP \fB\-\-cmake\fR Create a basic template for a CMake\-style build\. . @@ -1368,11 +1372,11 @@ Indicate that \fIURL\fR points to the package\'s repository rather than a file\. . .TP \fB\-\-set\-name\fR -Explicitly set the \fIname\fR of the new formula\. +Explicitly set the \fIname\fR of the new formula or cask\. . .TP \fB\-\-set\-version\fR -Explicitly set the \fIversion\fR of the new formula\. +Explicitly set the \fIversion\fR of the new formula or cask\. . .TP \fB\-\-set\-license\fR