From 1003aa72c9b976a83fa145004001e8638353c763 Mon Sep 17 00:00:00 2001 From: Caleb Xu Date: Mon, 30 Jul 2018 18:41:45 -0400 Subject: [PATCH] Additional fixups for extract command - Rework command line options - Make specifying a version optional - Remove stdout option and require a tap to be specified - Do not allow user to extract into homebrew/core - Rework new class name generation to use existing Formulary tools --- Library/Homebrew/dev-cmd/extract.rb | 87 +++++++++++++++++------------ 1 file changed, 51 insertions(+), 36 deletions(-) diff --git a/Library/Homebrew/dev-cmd/extract.rb b/Library/Homebrew/dev-cmd/extract.rb index d412e6a949..759109546e 100644 --- a/Library/Homebrew/dev-cmd/extract.rb +++ b/Library/Homebrew/dev-cmd/extract.rb @@ -1,14 +1,15 @@ -#: * `extract` [`--force`] [`--stdout`] []: +#: * `extract` [`--force`] `--tap=` [`--version=`]: #: Looks through repository history to find the of and #: creates a copy in /Formula/@.rb. If the tap is #: not installed yet, attempts to install/clone the tap before continuing. +#: A tap must be passed through `--tap` in order for `extract` to work. #: #: If `--force` is passed, the file at the destination will be overwritten #: if it already exists. Otherwise, existing files will be preserved. #: -#: If `--stdout` is passed, the file will be written to stdout on the -#: terminal instead of written to a file. A cannot be passed when -#: using `--stdout`. +#: If an argument is passed through `--version`, of +#: will be extracted and placed in the destination tap. Otherwise, the most +#: recent version that can be found will be used. require "utils/git" require "formula_versions" @@ -20,51 +21,65 @@ module Homebrew def extract Homebrew::CLI::Parser.parse do - switch "--stdout", description: "Output to stdout on terminal instead of file" - switch :debug - switch :force + flag "--tap=" + flag "--version=" + switch :debug + switch :force end - odie "Cannot use a tap and --stdout at the same time!" if ARGV.named.length == 3 && args.stdout? - raise UsageError unless (ARGV.named.length == 3 && !args.stdout?) || (ARGV.named.length == 2 && args.stdout?) + # If no formula args are given, ask specifically for a formula to be specified + raise FormulaUnspecifiedError if ARGV.named.empty? + + # If some other number of args are given, provide generic usage information + raise UsageError if ARGV.named.length != 1 + + odie "The tap to which the formula is extracted must be specified!" if args.tap.nil? formula = Formulary.factory(ARGV.named.first) - version = ARGV.named[1] - destination_tap = Tap.fetch(ARGV.named[2]) unless args.stdout? - destination_tap.install unless destination_tap.installed? || args.stdout? + if args.version.nil? + version = formula.version + else + version = args.version + end + destination_tap = Tap.fetch(args.tap) + destination_tap.install unless destination_tap.installed? - unless args.stdout? - path = Pathname.new("#{destination_tap.path}/Formula/#{formula}@#{version}.rb") - if path.exist? - unless ARGV.force? - odie <<~EOS - Destination formula already exists: #{path} - To overwrite it and continue anyways, run `brew extract #{formula} #{version} #{destination_tap.name} --force`. - EOS - end - ohai "Overwriting existing formula at #{path}" if ARGV.debug? - path.delete + odie "Cannot extract formula to homebrew/core!" if destination_tap.name == "homebrew/core" + + path = Pathname.new("#{destination_tap.path}/Formula/#{formula}@#{version}.rb") + if path.exist? + unless ARGV.force? + odie <<~EOS + Destination formula already exists: #{path} + To overwrite it and continue anyways, run: + `brew extract #{formula} --version=#{version} --tap=#{destination_tap.name} --force` + EOS end + ohai "Overwriting existing formula at #{path}" if ARGV.debug? + path.delete end - rev = "HEAD" - version_resolver = FormulaVersions.new(formula) - until version_resolver.formula_at_revision(rev) { |f| version_matches?(f, version, rev) || rev.empty? } do - rev = Git.last_revision_commit_of_file(formula.path.parent.parent, formula.path, before_commit: "#{rev}~1") + if args.version.nil? + rev = Git.last_revision_commit_of_file(formula.path.parent.parent, formula.path) + odie "Could not find #{formula} #{version}!" if rev.empty? + version_resolver = FormulaVersions.new(formula) + else + rev = "HEAD" + version_resolver = FormulaVersions.new(formula) + until version_resolver.formula_at_revision(rev) { |f| version_matches?(f, version, rev) || rev.empty? } do + rev = Git.last_revision_commit_of_file(formula.path.parent.parent, formula.path, before_commit: "#{rev}~1") + end + odie "Could not find #{formula} #{version}!" if rev.empty? end - odie "Could not find #{formula} #{version}!" if rev.empty? - result = version_resolver.file_contents_at_revision(rev) # The class name has to be renamed to match the new filename, e.g. Foo version 1.2.3 becomes FooAT123 and resides in Foo@1.2.3.rb. - result.gsub!("class #{formula.name.capitalize} < Formula", "class #{formula.name.capitalize}AT#{version.gsub(/[^0-9a-z ]/i, "")} < Formula") - if args.stdout? - puts result if args.stdout? - else - ohai "Writing formula for #{formula} from #{rev} to #{path}" - path.write result - end + name = formula.name.capitalize + versioned_name = Formulary.class_s("#{name}@#{version}") + result.gsub!("class #{name} < Formula", "class #{versioned_name} < Formula") + ohai "Writing formula for #{formula} from #{rev} to #{path}" + path.write result end # @private