Class: Homebrew::FormulaCreator Private

Inherits:
Object
  • Object
show all
Defined in:
formula_creator.rb

Overview

This class is part of a private API. This class may only be used in the Homebrew/brew repository. Third parties should avoid using this class if possible, as it may be removed or changed without warning.

Class for generating a formula from a template.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url:, name: nil, version: nil, tap: nil, mode: nil, license: nil, fetch: false, head: false) ⇒ void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

  • url (String)
  • name (String, nil) (defaults to: nil)
  • version (String, nil) (defaults to: nil)
  • tap (String, nil) (defaults to: nil)
  • mode (Symbol, nil) (defaults to: nil)
  • license (String, nil) (defaults to: nil)
  • fetch (Boolean) (defaults to: false)
  • head (Boolean) (defaults to: false)


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'formula_creator.rb', line 27

def initialize(url:, name: nil, version: nil, tap: nil, mode: nil, license: nil, fetch: false, head: false)
  @url = url
  @mode = mode
  @license = license
  @fetch = fetch

  tap = if tap.blank?
    CoreTap.instance
  else
    Tap.fetch(tap)
  end
  @tap = T.let(tap, Tap)

  if (match_github = url.match %r{github\.com/(?<user>[^/]+)/(?<repo>[^/]+).*})
    user = T.must(match_github[:user])
    repository = T.must(match_github[:repo])
    if repository.end_with?(".git")
      # e.g. https://github.com/Homebrew/brew.git
      repository.delete_suffix!(".git")
      head = true
    end
    odebug "github: #{user} #{repository} head:#{head}"
    if name.blank?
      name = repository
      odebug "name from github: #{name}"
    end
  elsif name.blank?
    stem = Pathname.new(url).stem
    name = if stem.start_with?("index.cgi") && stem.include?("=")
      # special cases first
      # gitweb URLs e.g. http://www.codesrc.com/gitweb/index.cgi?p=libzipper.git;a=summary
      stem.rpartition("=").last
    else
      # e.g. http://digit-labs.org/files/tools/synscan/releases/synscan-5.02.tar.gz
      pathver = Version.parse(stem).to_s
      stem.sub(/[-_.]?#{Regexp.escape(pathver)}$/, "")
    end
    odebug "name from url: #{name}"
  end
  @name = T.let(name, String)
  @head = head

  if version.present?
    version = Version.new(version)
    odebug "version from user: #{version}"
  else
    version = Version.detect(url)
    odebug "version from url: #{version}"
  end

  if fetch && user && repository
    github = GitHub.repository(user, repository)

    if version.null? && !head
      begin
        latest_release = GitHub.get_latest_release(user, repository)
        version = Version.new(latest_release.fetch("tag_name"))
        odebug "github: version from latest_release: #{version}"

        @url = "https://github.com/#{user}/#{repository}/archive/refs/tags/#{version}.tar.gz"
        odebug "github: url changed to source archive #{@url}"
      rescue GitHub::API::HTTPNotFoundError
        odebug "github: latest_release lookup failed: #{url}"
      end
    end
  end
  @github = T.let(github, T.untyped)
  @version = T.let(version, Version)

  @sha256 = T.let(nil, T.nilable(String))
  @desc = T.let(nil, T.nilable(String))
  @homepage = T.let(nil, T.nilable(String))
  @license = T.let(nil, T.nilable(String))
end

Instance Attribute Details

#headBoolean (readonly)

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


21
22
23
# File 'formula_creator.rb', line 21

def head
  @head
end

#nameString

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



12
13
14
# File 'formula_creator.rb', line 12

def name
  @name
end

#urlString (readonly)

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



18
19
20
# File 'formula_creator.rb', line 18

def url
  @url
end

#versionVersion (readonly)

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



15
16
17
# File 'formula_creator.rb', line 15

def version
  @version
end

Instance Method Details

#verify_tap_available!void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

This method returns an undefined value.



103
104
105
# File 'formula_creator.rb', line 103

def verify_tap_available!
  raise TapUnavailableError, @tap.name unless @tap.installed?
end

#write_formula!Pathname

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

Raises:

  • (ArgumentError)


108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'formula_creator.rb', line 108

def write_formula!
  raise ArgumentError, "name is blank!" if @name.blank?
  raise ArgumentError, "tap is blank!" if @tap.blank?

  path = @tap.new_formula_path(@name)
  raise "#{path} already exists" if path.exist?

  if @version.nil? || @version.null?
    odie "Version cannot be determined from URL. Explicitly set the version with `--set-version` instead."
  end

  if @fetch
    unless @head
      r = Resource.new
      r.url(@url)
      r.owner = self
      filepath = r.fetch
      html_doctype_prefix = "<!doctype html"
      # Number of bytes to read from file start to ensure it is not HTML.
      # HTML may start with arbitrary number of whitespace lines.
      bytes_to_read = 100
      if File.read(filepath, bytes_to_read).strip.downcase.start_with?(html_doctype_prefix)
        raise "Downloaded URL is not archive"
      end

      @sha256 = T.let(filepath.sha256, T.nilable(String))
    end

    if @github
      @desc = @github["description"]
      @homepage = @github["homepage"].presence || "https://github.com/#{@github["full_name"]}"
      @license = @github["license"]["spdx_id"] if @github["license"]
    end
  end

  path.dirname.mkpath
  path.write ERB.new(template, trim_mode: ">").result(binding)
  path
end