diff options
| author | Mike McQuaid | 2016-09-05 21:37:02 +0100 | 
|---|---|---|
| committer | Mike McQuaid | 2016-09-08 20:46:37 +0100 | 
| commit | af8605ea4ba1d9856c055c8c76b447e030540e3f (patch) | |
| tree | d093b11340406c21a4b873a80effe3b068fd07d4 /Library/Homebrew/dev-cmd/create.rb | |
| parent | 4f6bae46f9c0f7b713cdbb999318460135f423de (diff) | |
| download | brew-af8605ea4ba1d9856c055c8c76b447e030540e3f.tar.bz2 | |
Move developer-focused commands to dev-cmd.
Diffstat (limited to 'Library/Homebrew/dev-cmd/create.rb')
| -rw-r--r-- | Library/Homebrew/dev-cmd/create.rb | 218 | 
1 files changed, 218 insertions, 0 deletions
diff --git a/Library/Homebrew/dev-cmd/create.rb b/Library/Homebrew/dev-cmd/create.rb new file mode 100644 index 000000000..9be990318 --- /dev/null +++ b/Library/Homebrew/dev-cmd/create.rb @@ -0,0 +1,218 @@ +#:  * `create` <URL> [`--autotools`|`--cmake`] [`--no-fetch`] [`--set-name` <name>] [`--set-version` <version>] [`--tap` <user>`/`<repo>]: +#:    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 have a look at +#: +#:    <http://www.rubydoc.info/github/Homebrew/brew/master/Formula> +#: +#:    If `--autotools` is passed, create a basic template for an Autotools-style build. +#:    If `--cmake` is passed, create a basic template for a CMake-style build. +#: +#:    If `--no-fetch` is passed, Homebrew will not download <URL> to the cache and +#:    will thus not add the SHA256 to the formula for you. +#: +#:    The options `--set-name` and `--set-version` each take an argument and allow +#:    you to explicitly set the name and version of the package you are creating. +#: +#:    The option `--tap` takes a tap as its argument and generates the formula in +#:    the specified tap. + +require "formula" +require "blacklist" +require "digest" +require "erb" + +module Homebrew +  # Create a formula from a tarball URL +  def create +    # Allow searching MacPorts or Fink. +    if ARGV.include? "--macports" +      opoo "`brew create --macports` is deprecated; use `brew search --macports` instead" +      exec_browser "https://www.macports.org/ports.php?by=name&substr=#{ARGV.next}" +    elsif ARGV.include? "--fink" +      opoo "`brew create --fink` is deprecated; use `brew search --fink` instead" +      exec_browser "http://pdb.finkproject.org/pdb/browse.php?summary=#{ARGV.next}" +    end + +    raise UsageError if ARGV.named.empty? + +    # Ensure that the cache exists so we can fetch the tarball +    HOMEBREW_CACHE.mkpath + +    url = ARGV.named.first # Pull the first (and only) url from ARGV + +    version = ARGV.next if ARGV.include? "--set-version" +    name = ARGV.next if ARGV.include? "--set-name" +    tap = ARGV.next if ARGV.include? "--tap" + +    fc = FormulaCreator.new +    fc.name = name +    fc.version = version +    fc.tap = Tap.fetch(tap || "homebrew/core") +    raise TapUnavailableError, tap unless fc.tap.installed? +    fc.url = url + +    fc.mode = if ARGV.include? "--cmake" +      :cmake +    elsif ARGV.include? "--autotools" +      :autotools +    end + +    if fc.name.nil? || fc.name.strip.empty? +      stem = Pathname.new(url).stem +      print "Formula name [#{stem}]: " +      fc.name = __gets || stem +      fc.update_path +    end + +    # Don't allow blacklisted formula, or names that shadow aliases, +    # unless --force is specified. +    unless ARGV.force? +      if msg = blacklisted?(fc.name) +        raise "#{fc.name} is blacklisted for creation.\n#{msg}\nIf you really want to create this formula use --force." +      end + +      if Formula.aliases.include? fc.name +        realname = Formulary.canonical_name(fc.name) +        raise <<-EOS.undent +          The formula #{realname} is already aliased to #{fc.name} +          Please check that you are not creating a duplicate. +          To force creation use --force. +          EOS +      end +    end + +    fc.generate! + +    puts "Please `brew audit --new-formula #{fc.name}` before submitting, thanks." +    exec_editor fc.path +  end + +  def __gets +    gots = $stdin.gets.chomp +    if gots.empty? then nil else gots end +  end +end + +class FormulaCreator +  attr_reader :url, :sha256 +  attr_accessor :name, :version, :tap, :path, :mode + +  def url=(url) +    @url = url +    path = Pathname.new(url) +    if @name.nil? +      case url +      when %r{github\.com/\S+/(\S+)\.git} +        @name = $1 +        @head = true +      when %r{github\.com/\S+/(\S+)/archive/} +        @name = $1 +      else +        @name = path.basename.to_s[/(.*?)[-_.]?#{Regexp.escape(path.version.to_s)}/, 1] +      end +    end +    update_path +    if @version +      @version = Version.create(@version) +    else +      @version = Pathname.new(url).version +    end +  end + +  def update_path +    return if @name.nil? || @tap.nil? +    @path = Formulary.path "#{@tap}/#{@name}" +  end + +  def fetch? +    !head? && !ARGV.include?("--no-fetch") +  end + +  def head? +    @head || ARGV.build_head? +  end + +  def generate! +    raise "#{path} already exists" if path.exist? + +    if version.nil? +      opoo "Version cannot be determined from URL." +      puts "You'll need to add an explicit 'version' to the formula." +    end + +    if fetch? && version +      r = Resource.new +      r.url(url) +      r.version(version) +      r.owner = self +      @sha256 = r.fetch.sha256 if r.download_strategy == CurlDownloadStrategy +    end + +    path.write ERB.new(template, nil, ">").result(binding) +  end + +  def template; <<-EOS.undent +    # Documentation: https://github.com/Homebrew/brew/blob/master/share/doc/homebrew/Formula-Cookbook.md +    #                http://www.rubydoc.info/github/Homebrew/brew/master/Formula +    # PLEASE REMOVE ALL GENERATED COMMENTS BEFORE SUBMITTING YOUR PULL REQUEST! + +    class #{Formulary.class_s(name)} < Formula +      desc "" +      homepage "" +    <% if head? %> +      head "#{url}" +    <% else %> +      url "#{url}" +    <% unless version.nil? or version.detected_from_url? %> +      version "#{version}" +    <% end %> +      sha256 "#{sha256}" +    <% end %> + +    <% if mode == :cmake %> +      depends_on "cmake" => :build +    <% elsif mode.nil? %> +      # depends_on "cmake" => :build +    <% end %> +      depends_on :x11 # if your formula requires any X11/XQuartz components + +      def install +        # ENV.deparallelize  # if your formula fails when building in parallel + +    <% if mode == :cmake %> +        system "cmake", ".", *std_cmake_args +    <% elsif mode == :autotools %> +        # Remove unrecognized options if warned by configure +        system "./configure", "--disable-debug", +                              "--disable-dependency-tracking", +                              "--disable-silent-rules", +                              "--prefix=\#{prefix}" +    <% else %> +        # Remove unrecognized options if warned by configure +        system "./configure", "--disable-debug", +                              "--disable-dependency-tracking", +                              "--disable-silent-rules", +                              "--prefix=\#{prefix}" +        # system "cmake", ".", *std_cmake_args +    <% end %> +        system "make", "install" # if this fails, try separate make/make install steps +      end + +      test do +        # `test do` will create, run in and delete a temporary directory. +        # +        # This test will fail and we won't accept that! It's enough to just replace +        # "false" with the main program this formula installs, but it'd be nice if you +        # were more thorough. 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 +    EOS +  end +end  | 
