<commit_before># typed: true
# frozen_string_literal: true

require "download_strategy"
require "checksum"
require "version"
require "mktemp"
require "extend/on_os"

# Resource is the fundamental representation of an external resource. The
# primary formula download, along with other declared resources, are instances
# of this class.
#
# @api private
class Resource
  extend T::Sig

  include Context
  include FileUtils
  include OnOS

  attr_reader :mirrors, :specs, :using, :source_modified_time, :patches, :owner
  attr_writer :version
  attr_accessor :download_strategy, :checksum

  # Formula name must be set after the DSL, as we have no access to the
  # formula name before initialization of the formula.
  attr_accessor :name

  def initialize(name = nil, &block)
    @name = name
    @url = nil
    @version = nil
    @mirrors = []
    @specs = {}
    @checksum = nil
    @using = nil
    @patches = []
    instance_eval(&block) if block
  end

  def owner=(owner)
    @owner = owner
    patches.each { |p| p.owner = owner }

    return if !owner.respond_to?(:full_name) || owner.full_name != "ca-certificates"
    return if Homebrew::EnvConfig.no_insecure_redirect?

    @specs[:insecure] = !specs[:bottle] && !DevelopmentTools.ca_file_handles_most_https_certificates?
  end

  def downloader
    @downloader ||= download_strategy.new(url, download_name, version,
                                          mirrors: mirrors.dup, **specs)
  end

  # Removes /s from resource names; this allows Go package names
  # to be used as resource names without confusing software that
  # interacts with {download_name}, e.g. `github.com/foo/bar`.
  def escaped_name
    name.tr("/", "-")
  end

  def download_name
    return owner.name if name.nil?
    return escaped_name if owner.nil?

    "#{owner.name}--#{escaped_name}"
  end

  def downloaded?
    cached_download.exist?
  end

  def cached_download
    downloader.cached_location
  end

  def clear_cache
    downloader.clear_cache
  end

  # Verifies download and unpacks it.
  # The block may call `|resource, staging| staging.retain!` to retain the staging
  # directory. Subclasses that override stage should implement the tmp
  # dir using {Mktemp} so that works with all subtypes.
  #
  # @api public
  def stage(target = nil, &block)
    raise ArgumentError, "target directory or block is required" if !target && block.blank?

    prepare_patches
    fetch_patches(skip_downloaded: true)
    fetch unless downloaded?

    unpack(target, &block)
  end

  def prepare_patches
    patches.grep(DATAPatch) { |p| p.path = owner.owner.path }
  end

  def fetch_patches(skip_downloaded: false)
    external_patches = patches.select(&:external?)
    external_patches.reject!(&:downloaded?) if skip_downloaded
    external_patches.each(&:fetch)
  end

  def apply_patches
    return if patches.empty?

    ohai "Patching #{name}"
    patches.each(&:apply)
  end

  # If a target is given, unpack there; else unpack to a temp folder.
  # If block is given, yield to that block with `|stage|`, where stage
  # is a {ResourceStageContext}.
  # A target or a block must be given, but not both.
  def unpack(target = nil)
    mktemp(download_name) do |staging|
      downloader.stage do
        @source_modified_time = downloader.source_modified_time
        apply_patches
        if block_given?
          yield ResourceStageContext.new(self, staging)
        elsif target
          target = Pathname(target)
          target.install Pathname.pwd.children
        end
      end
    end
  end

  Partial = Struct.new(:resource, :files)

  def files(*files)
    Partial.new(self, files)
  end

  def fetch(verify_download_integrity: true)
    HOMEBREW_CACHE.mkpath

    fetch_patches

    begin
      downloader.fetch
    rescue ErrorDuringExecution, CurlDownloadStrategyError => e
      raise DownloadError.new(self, e)
    end

    download = cached_download
    verify_download_integrity(download) if verify_download_integrity
    download
  end

  def verify_download_integrity(fn)
    if fn.file?
      ohai "Verifying checksum for '#{fn.basename}'" if verbose?
      fn.verify_checksum(checksum)
    end
  rescue ChecksumMissingError
    opoo <<~EOS
      Cannot verify integrity of '#{fn.basename}'.
      No checksum was provided for this resource.
      For your reference, the checksum is:
        sha256 "#{fn.sha256}"
    EOS
  end

  def sha256(val)
    @checksum = Checksum.new(val)
  end

  def url(val = nil, **specs)
    return @url if val.nil?

    specs = specs.dup
    # Don't allow this to be set.
    specs.delete(:insecure)

    @url = val
    @using = specs.delete(:using)<commit_msg>Extended the livecheck DSL to work for resources<commit_after># typed: true
# frozen_string_literal: true

require "download_strategy"
require "checksum"
require "version"
require "mktemp"
require "livecheck"
require "extend/on_os"

# Resource is the fundamental representation of an external resource. The
# primary formula download, along with other declared resources, are instances
# of this class.
#
# @api private
class Resource
  extend T::Sig

  include Context
  include FileUtils
  include OnOS

  attr_reader :mirrors, :specs, :using, :source_modified_time, :patches, :owner
  attr_writer :version
  attr_accessor :download_strategy, :checksum

  # Formula name must be set after the DSL, as we have no access to the
  # formula name before initialization of the formula.
  attr_accessor :name

  def initialize(name = nil, &block)
    @name = name
    @url = nil
    @version = nil
    @mirrors = []
    @specs = {}
    @checksum = nil
    @using = nil
    @patches = []
    @livecheck = nil
    @livecheckable = false
    instance_eval(&block) if block
  end

  def owner=(owner)
    @owner = owner
    patches.each { |p| p.owner = owner }

    return if !owner.respond_to?(:full_name) || owner.full_name != "ca-certificates"
    return if Homebrew::EnvConfig.no_insecure_redirect?

    @specs[:insecure] = !specs[:bottle] && !DevelopmentTools.ca_file_handles_most_https_certificates?
  end

  def downloader
    @downloader ||= download_strategy.new(url, download_name, version,
                                          mirrors: mirrors.dup, **specs)
  end

  # Removes /s from resource names; this allows Go package names
  # to be used as resource names without confusing software that
  # interacts with {download_name}, e.g. `github.com/foo/bar`.
  def escaped_name
    name.tr("/", "-")
  end

  def download_name
    return owner.name if name.nil?
    return escaped_name if owner.nil?

    "#{owner.name}--#{escaped_name}"
  end

  def downloaded?
    cached_download.exist?
  end

  def cached_download
    downloader.cached_location
  end

  def clear_cache
    downloader.clear_cache
  end

  # Verifies download and unpacks it.
  # The block may call `|resource, staging| staging.retain!` to retain the staging
  # directory. Subclasses that override stage should implement the tmp
  # dir using {Mktemp} so that works with all subtypes.
  #
  # @api public
  def stage(target = nil, &block)
    raise ArgumentError, "target directory or block is required" if !target && block.blank?

    prepare_patches
    fetch_patches(skip_downloaded: true)
    fetch unless downloaded?

    unpack(target, &block)
  end

  def prepare_patches
    patches.grep(DATAPatch) { |p| p.path = owner.owner.path }
  end

  def fetch_patches(skip_downloaded: false)
    external_patches = patches.select(&:external?)
    external_patches.reject!(&:downloaded?) if skip_downloaded
    external_patches.each(&:fetch)
  end

  def apply_patches
    return if patches.empty?

    ohai "Patching #{name}"
    patches.each(&:apply)
  end

  # If a target is given, unpack there; else unpack to a temp folder.
  # If block is given, yield to that block with `|stage|`, where stage
  # is a {ResourceStageContext}.
  # A target or a block must be given, but not both.
  def unpack(target = nil)
    mktemp(download_name) do |staging|
      downloader.stage do
        @source_modified_time = downloader.source_modified_time
        apply_patches
        if block_given?
          yield ResourceStageContext.new(self, staging)
        elsif target
          target = Pathname(target)
          target.install Pathname.pwd.children
        end
      end
    end
  end

  Partial = Struct.new(:resource, :files)

  def files(*files)
    Partial.new(self, files)
  end

  def fetch(verify_download_integrity: true)
    HOMEBREW_CACHE.mkpath

    fetch_patches

    begin
      downloader.fetch
    rescue ErrorDuringExecution, CurlDownloadStrategyError => e
      raise DownloadError.new(self, e)
    end

    download = cached_download
    verify_download_integrity(download) if verify_download_integrity
    download
  end

  def verify_download_integrity(fn)
    if fn.file?
      ohai "Verifying checksum for '#{fn.basename}'" if verbose?
      fn.verify_checksum(checksum)
    end
  rescue ChecksumMissingError
    opoo <<~EOS
      Cannot verify integrity of '#{fn.basename}'.
      No checksum was provided for this resource.
      For your reference, the checksum is:
        sha256 "#{fn.sha256}"
    EOS
  end

  # @!attribute [w] livecheck
  # {Livecheck} can be used to check for newer versions of the software.
  # This method evaluates the DSL specified in the livecheck block of the
  # {Resource} (if it exists) and sets the instance variables of a {Livecheck}
  # object accordingly. This is used by `brew livecheck` to check for newer
  # versions of the software.
  #
  # <pre>livecheck do
  #   url "https://example.com/foo/releases"
  #   regex /foo-(\d+(?:\.\d+)+)\.tar/
  # end</pre>
  def livecheck(&block)
    @livecheck ||= Livecheck.new(self)
    return @livecheck unless block

    @livecheckable = true
    @livecheck.instance_eval(&block)
  end

  # Whether a livecheck specification is defined or not.
  # It returns true when a livecheck block is present in the {Resource} and
  # false otherwise, and is used by livecheck.
  def livecheckable?
    @livecheckable == true
  end

  def sha256(val)
    @checksum = Checksum.new(val)
  end

  def url(val = nil, **specs)
    return @url if val.nil?

    specs = specs.dup
    # Don't allow this to be set.
    specs.delete(:insecure)

    @url = val
    @using = specs.delete(:using)
{'fraction_non_alphanumeric': 0.08830086265387226, 'fraction_numerical': 0.0017446932247746438, 'mean_word_length': 3.1621621621621623, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 74, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4597766', 'n_tokens_mistral': 3273, 'n_tokens_neox': 3141, 'n_words': 995}