Class: Homebrew::FormulaCreator Private

Inherits:
Object
  • Object
show all
Includes:
Utils::Output::Mixin
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

Methods included from Utils::Output::Mixin

#odebug, #odeprecated, #odie, #odisabled, #ofail, #oh1, #oh1_title, #ohai, #ohai_title, #onoe, #opoo, #opoo_outside_github_actions, #pretty_duration, #pretty_installed, #pretty_outdated, #pretty_uninstalled

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)


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
101
102
103
# File 'formula_creator.rb', line 30

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)


24
25
26
# File 'formula_creator.rb', line 24

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:



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

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:



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

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:



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

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.



106
107
108
# File 'formula_creator.rb', line 106

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)


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
147
148
149
# File 'formula_creator.rb', line 111

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