diff --git a/Library/Homebrew/cask/exceptions.rb b/Library/Homebrew/cask/exceptions.rb index 9778c297255fe0231d64e8be8d78f28bd8519f56..852fa8b3edbfe218ad7e2754096d3a20465b3d5d 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 ea4b8a38a122582f24b9815f615ea44ec8bccd75..3575710c4d1cccfde424a25e8d0db166cf86e8d8 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` [<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: <https://rubydoc.brew.sh/Formula> 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 <URL> points to the package's repository rather than a file." flag "--set-name=", - description: "Explicitly set the <name> of the new formula." + description: "Explicitly set the <name> of the new formula or cask.", + required_for: "--cask" flag "--set-version=", - description: "Explicitly set the <version> of the new formula." + description: "Explicitly set the <version> of the new formula or cask." flag "--set-license=", description: "Explicitly set the <license> 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 + + 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 + + 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 - url = args.named.first # Pull the first (and only) url from ARGV + cask_path.atomic_write <<~RUBY + cask "#{token}" do + version "#{version}" + sha256 "#{sha256}" - version = args.set_version - name = args.set_name - license = args.set_license - tap = args.tap + 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 9e25a8c0c8046c8ee6697c33d22c03bdb58ff891..586a1639b7513fd08e79c6a33a631d9f7d51f80d 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: <https://rubydoc.brew.sh/Formula> * `--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 ffa16f11d4678996f7d7fadc084d3168badff817..0b237b463f3f6158588e701599831c221173048e 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