Class: Brew::Vulns::Formula

Inherits:
Object
  • Object
show all
Defined in:
lib/brew/vulns/formula.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ Formula

Returns a new instance of Formula.



11
12
13
14
15
16
17
# File 'lib/brew/vulns/formula.rb', line 11

def initialize(data)
  @name = data["name"] || data["full_name"]
  @version = data.dig("versions", "stable") || data["version"]
  @source_url = data.dig("urls", "stable", "url")
  @head_url = data.dig("urls", "head", "url")
  @dependencies = data["dependencies"] || []
end

Instance Attribute Details

#dependenciesObject (readonly)

Returns the value of attribute dependencies.



9
10
11
# File 'lib/brew/vulns/formula.rb', line 9

def dependencies
  @dependencies
end

#head_urlObject (readonly)

Returns the value of attribute head_url.



9
10
11
# File 'lib/brew/vulns/formula.rb', line 9

def head_url
  @head_url
end

#nameObject (readonly)

Returns the value of attribute name.



9
10
11
# File 'lib/brew/vulns/formula.rb', line 9

def name
  @name
end

#source_urlObject (readonly)

Returns the value of attribute source_url.



9
10
11
# File 'lib/brew/vulns/formula.rb', line 9

def source_url
  @source_url
end

#versionObject (readonly)

Returns the value of attribute version.



9
10
11
# File 'lib/brew/vulns/formula.rb', line 9

def version
  @version
end

Class Method Details

.load_allObject

Raises:



53
54
55
56
57
58
59
# File 'lib/brew/vulns/formula.rb', line 53

def self.load_all
  json, status = Open3.capture2("brew", "info", "--json=v2", "--eval-all")
  raise Error, "brew info failed with status #{status.exitstatus}" unless status.success?

  data = JSON.parse(json)
  data["formulae"].map { |f| new(f) }
end

.load_from_brewfile(brewfile_path, include_deps: false) ⇒ Object

Raises:



99
100
101
102
103
104
# File 'lib/brew/vulns/formula.rb', line 99

def self.load_from_brewfile(brewfile_path, include_deps: false)
  raise Error, "Brewfile not found: #{brewfile_path}" unless File.exist?(brewfile_path)

  formula_names = parse_brewfile(brewfile_path)
  load_named(formula_names, include_deps: include_deps)
end

.load_installedObject

Raises:



61
62
63
64
65
66
67
# File 'lib/brew/vulns/formula.rb', line 61

def self.load_installed
  json, status = Open3.capture2("brew", "info", "--json=v2", "--installed")
  raise Error, "brew info failed with status #{status.exitstatus}" unless status.success?

  data = JSON.parse(json)
  data["formulae"].map { |f| new(f) }
end

.load_named(formula_names, include_deps: false) ⇒ Object

Raises:



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
# File 'lib/brew/vulns/formula.rb', line 69

def self.load_named(formula_names, include_deps: false)
  return [] if formula_names.empty?

  json, status = Open3.capture2("brew", "info", "--json=v2", *formula_names)
  raise Error, "brew info failed with status #{status.exitstatus}" unless status.success?

  data = JSON.parse(json)
  formulae = data["formulae"].map { |f| new(f) }

  if include_deps
    dep_names = []
    formula_names.each do |name|
      deps_output, = Open3.capture2("brew", "deps", name)
      dep_names.concat(deps_output.split("\n").map(&:strip))
    end
    dep_names.uniq!
    dep_names -= formula_names

    if dep_names.any?
      deps_json, deps_status = Open3.capture2("brew", "info", "--json=v2", *dep_names)
      if deps_status.success?
        deps_data = JSON.parse(deps_json)
        formulae.concat(deps_data["formulae"].map { |f| new(f) })
      end
    end
  end

  formulae.uniq { |f| f.name }
end

.parse_brewfile(brewfile_path) ⇒ Object

Raises:



106
107
108
109
110
111
# File 'lib/brew/vulns/formula.rb', line 106

def self.parse_brewfile(brewfile_path)
  output, status = Open3.capture2("brew", "bundle", "list", "--file=#{brewfile_path}", "--formula")
  raise Error, "brew bundle list failed with status #{status.exitstatus}" unless status.success?

  output.split("\n").map(&:strip).reject(&:empty?)
end

Instance Method Details

#codeberg?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/brew/vulns/formula.rb', line 39

def codeberg?
  repo_url&.include?("codeberg.org")
end

#github?Boolean

Returns:

  • (Boolean)


31
32
33
# File 'lib/brew/vulns/formula.rb', line 31

def github?
  repo_url&.include?("github.com")
end

#gitlab?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/brew/vulns/formula.rb', line 35

def gitlab?
  repo_url&.include?("gitlab.com")
end

#repo_urlObject



19
20
21
22
23
# File 'lib/brew/vulns/formula.rb', line 19

def repo_url
  return @repo_url if defined?(@repo_url)

  @repo_url = extract_repo_url(source_url) || extract_repo_url(head_url)
end

#supported_forge?Boolean

Returns:

  • (Boolean)


43
44
45
# File 'lib/brew/vulns/formula.rb', line 43

def supported_forge?
  github? || gitlab? || codeberg?
end

#tagObject



25
26
27
28
29
# File 'lib/brew/vulns/formula.rb', line 25

def tag
  return @tag if defined?(@tag)

  @tag = extract_tag_from_url(source_url)
end

#to_osv_queryObject



47
48
49
50
51
# File 'lib/brew/vulns/formula.rb', line 47

def to_osv_query
  return nil unless repo_url && tag

  { repo_url: repo_url, version: tag, name: name }
end