# typed: strong # frozen_string_literal: true module Homebrew module Livecheck # Options to modify livecheck's behavior. These primarily come from # `livecheck` blocks but they can also be set by livecheck at runtime. # # Option values use a `nil` default to indicate that the value has not been # set. class Options < T::Struct # Whether to use brewed curl. prop :homebrew_curl, T.nilable(T::Boolean) # Form data to use when making a `POST` request. prop :post_form, T.nilable(T::Hash[Symbol, String]) # JSON data to use when making a `POST` request. prop :post_json, T.nilable(T::Hash[Symbol, T.anything]) # Returns a `Hash` of options that are provided as arguments to `url`. sig { returns(T::Hash[Symbol, T.untyped]) } def url_options { homebrew_curl:, post_form:, post_json:, } end # Returns a `Hash` of all instance variables, using `String` keys. sig { returns(T::Hash[String, T.untyped]) } def to_hash T.let(serialize, T::Hash[String, T.untyped]) end # Returns a `Hash` of all instance variables, using `Symbol` keys. sig { returns(T::Hash[Symbol, T.untyped]) } def to_h = to_hash.transform_keys(&:to_sym) # Returns a new object formed by merging `other` values with a copy of # `self`. # # `nil` values are removed from `other` before merging if it is an # `Options` object, as these are unitiailized values. This ensures that # existing values in `self` aren't unexpectedly overwritten with defaults. sig { params(other: T.any(Options, T::Hash[Symbol, T.untyped])).returns(Options) } def merge(other) return dup if other.empty? this_hash = to_h other_hash = other.is_a?(Options) ? other.to_h : other return dup if this_hash == other_hash new_options = this_hash.merge(other_hash) Options.new(**new_options) end # Merges values from `other` into `self` and returns `self`. # # `nil` values are removed from `other` before merging if it is an # `Options` object, as these are unitiailized values. This ensures that # existing values in `self` aren't unexpectedly overwritten with defaults. sig { params(other: T.any(Options, T::Hash[Symbol, T.untyped])).returns(Options) } def merge!(other) return self if other.empty? if other.is_a?(Options) return self if self == other other.instance_variables.each do |ivar| next if (v = T.let(other.instance_variable_get(ivar), Object)).nil? instance_variable_set(ivar, v) end else other.each do |k, v| cmd = :"#{k}=" send(cmd, v) if respond_to?(cmd) end end self end sig { params(other: Object).returns(T::Boolean) } def ==(other) return false unless other.is_a?(Options) @homebrew_curl == other.homebrew_curl && @post_form == other.post_form && @post_json == other.post_json end alias eql? == # Whether the object has only default values. sig { returns(T::Boolean) } def empty? = to_hash.empty? # Whether the object has any non-default values. sig { returns(T::Boolean) } def present? = !empty? end end end