Class: Homebrew::Livecheck::Strategy::Xml
- Defined in:
- livecheck/strategy/xml.rb
Overview
The Xml strategy fetches content at a URL, parses it as XML using
REXML
, and provides the REXML::Document
to a strategy
block.
If a regex is present in the livecheck
block, it should be passed
as the second argument to the strategy
block.
This is a generic strategy that doesn’t contain any logic for finding
versions, as the structure of XML data varies. Instead, a strategy
block must be used to extract version information from the XML data.
For more information on how to work with an REXML::Document
object,
please refer to the REXML::Document
and REXML::Element
documentation.
This strategy is not applied automatically and it is necessary to use
strategy :xml
in a livecheck
block (in conjunction with a
strategy
block) to use it.
This strategy’s Xml.find_versions method can be used in other strategies that work with XML content, so it should only be necessary to write the version-finding logic that works with the parsed XML data.
Constant Summary collapse
- NICE_NAME =
"XML"
- PRIORITY =
A priority of zero causes livecheck to skip the strategy. We do this for Homebrew::Livecheck::Strategy::Xml so we can selectively apply it only when a strategy block is provided in a
livecheck
block. 0
- URL_MATCH_REGEX =
The
Regexp
used to determine if the strategy applies to the URL. %r{^https?://}i.freeze
Class Method Summary collapse
-
.find_versions(url:, regex: nil, provided_content: nil, homebrew_curl: false, **_unused, &block) ⇒ Hash{Symbol => T.untyped}
Checks the XML content at the URL for versions, using the provided
strategy
block to extract version information. -
.match?(url) ⇒ Boolean
Whether the strategy can be applied to the provided URL.
-
.parse_xml(content) ⇒ REXML::Document?
Parses XML text and returns an
REXML::Document
object. -
.versions_from_content(content, regex = nil, &block) ⇒ Array<String>
Parses XML text and identifies versions using a
strategy
block.
Class Method Details
.find_versions(url:, regex: nil, provided_content: nil, homebrew_curl: false, **_unused, &block) ⇒ Hash{Symbol => T.untyped}
Checks the XML content at the URL for versions, using the provided
strategy
block to extract version information.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'livecheck/strategy/xml.rb', line 127 def self.find_versions(url:, regex: nil, provided_content: nil, homebrew_curl: false, **_unused, &block) raise ArgumentError, "#{Utils.demodulize(T.must(name))} requires a `strategy` block" if block.blank? match_data = { matches: {}, regex: regex, url: url } return match_data if url.blank? || block.blank? content = if provided_content.is_a?(String) match_data[:cached] = true provided_content else match_data.merge!(Strategy.page_content(url, homebrew_curl: homebrew_curl)) match_data[:content] end return match_data if content.blank? versions_from_content(content, regex, &block).each do |match_text| match_data[:matches][match_text] = Version.new(match_text) end match_data end |
.match?(url) ⇒ Boolean
Whether the strategy can be applied to the provided URL.
Homebrew::Livecheck::Strategy::Xml will technically match any HTTP URL but is only usable with
a livecheck
block containing a strategy
block.
49 50 51 |
# File 'livecheck/strategy/xml.rb', line 49 def self.match?(url) URL_MATCH_REGEX.match?(url) end |
.parse_xml(content) ⇒ REXML::Document?
Parses XML text and returns an REXML::Document
object.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'livecheck/strategy/xml.rb', line 57 def self.parse_xml(content) parsing_tries = 0 begin REXML::Document.new(content) rescue REXML::UndefinedNamespaceException => e undefined_prefix = e.to_s[/Undefined prefix ([^ ]+) found/i, 1] raise "Could not identify undefined prefix." if undefined_prefix.blank? # Only retry parsing once after removing prefix from content parsing_tries += 1 raise "Could not parse XML after removing undefined prefix." if parsing_tries > 1 # When an XML document contains a prefix without a corresponding # namespace, it's necessary to remove the prefix from the content # to be able to successfully parse it using REXML content = content.gsub(%r{(</?| )#{Regexp.escape(undefined_prefix)}:}, '\1') retry end end |
.versions_from_content(content, regex = nil, &block) ⇒ Array<String>
Parses XML text and identifies versions using a strategy
block.
If a regex is provided, it will be passed as the second argument to
the strategy
block (after the parsed XML data).
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'livecheck/strategy/xml.rb', line 91 def self.versions_from_content(content, regex = nil, &block) return [] if content.blank? || block.blank? require "rexml" xml = parse_xml(content) return [] if xml.blank? block_return_value = if regex.present? yield(xml, regex) elsif block.arity == 2 raise "Two arguments found in `strategy` block but no regex provided." else yield(xml) end Strategy.handle_block_return(block_return_value) end |