<commit_before># encoding: utf-8

module Overcommit
  # Responsible for loading the hooks the repository has configured and running
  # them, collecting and displaying the results.
  class HookRunner
    def initialize(config, logger, context)
      @config = config
      @log = logger
      @context = context
      @hooks = []
    end

    # Loads and runs the hooks registered for this {HookRunner}.
    def run
      load_hooks
      @context.setup_environment
      run_hooks
    ensure
      @context.cleanup_environment
    end

  private

    attr_reader :log

    def run_hooks
      if @hooks.any? { |hook| hook.run? || hook.skip? }
        log.bold "Running #{hook_script_name} hooks"

        statuses = @hooks.map { |hook| run_hook(hook) }.compact

        log.log # Newline

        run_failed = statuses.include?(:bad)

        if run_failed
          log.error "✗ One or more #{hook_script_name} hooks failed"
        else
          log.success "✓ All #{hook_script_name} hooks passed"
        end

        log.log # Newline

        !run_failed
      else
        log.success "✓ No applicable #{hook_script_name} hooks to run"
        true # Run was successful
      end
    end

    def run_hook(hook)
      return unless hook.enabled?

      if hook.skip?
        if hook.required?
          log.warning "Cannot skip #{hook.name} since it is required"
        else
          log.warning "Skipping #{hook.name}"
          return
        end
      end

      return unless hook.run?

      unless hook.quiet?
        print_header(hook)
      end

      begin
        status, output = hook.run
      rescue => ex
        status = :bad
        output = "Hook raised unexpected error\n#{ex.message}"
      end

      # Want to print the header in the event the result wasn't good so that the
      # user knows what failed
      if hook.quiet? && status != :good
        print_header(hook)
      end

      case status
      when :good
        log.success 'OK' unless hook.quiet?
      when :warn
        log.warning 'WARNING'
        print_report(output, :bold_warning)
      when :bad
        log.error 'FAILED'
        print_report(output, :bold_error)
      end

      status
    end

    def print_header(hook)
      log.partial hook.description
      log.partial '.' * (70 - hook.description.length)
    end

    def print_report(output, format = :log)
      log.send(format, output) unless output.nil? || output.empty?
    end

    # Loads hooks that will be run.
    # This is done explicitly so that we only load hooks which will actually be
    # used.<commit_msg>Extract helper methods from run_hook<commit_after># encoding: utf-8

module Overcommit
  # Responsible for loading the hooks the repository has configured and running
  # them, collecting and displaying the results.
  class HookRunner
    def initialize(config, logger, context)
      @config = config
      @log = logger
      @context = context
      @hooks = []
    end

    # Loads and runs the hooks registered for this {HookRunner}.
    def run
      load_hooks
      @context.setup_environment
      run_hooks
    ensure
      @context.cleanup_environment
    end

  private

    attr_reader :log

    def run_hooks
      if @hooks.any? { |hook| hook.run? || hook.skip? }
        log.bold "Running #{hook_script_name} hooks"

        statuses = @hooks.map { |hook| run_hook(hook) }.compact

        log.log # Newline

        run_failed = statuses.include?(:bad)

        if run_failed
          log.error "✗ One or more #{hook_script_name} hooks failed"
        else
          log.success "✓ All #{hook_script_name} hooks passed"
        end

        log.log # Newline

        !run_failed
      else
        log.success "✓ No applicable #{hook_script_name} hooks to run"
        true # Run was successful
      end
    end

    def run_hook(hook)
      return if should_skip?(hook)

      unless hook.quiet?
        print_header(hook)
      end

      begin
        status, output = hook.run
      rescue => ex
        status = :bad
        output = "Hook raised unexpected error\n#{ex.message}"
      end

      # Want to print the header in the event the result wasn't good so that the
      # user knows what failed
      if hook.quiet? && status != :good
        print_header(hook)
      end

      print_result(hook, status, output)

      status
    end

    def print_header(hook)
      log.partial hook.description
      log.partial '.' * (70 - hook.description.length)
    end

    def should_skip?(hook)
      return true unless hook.enabled?

      if hook.skip?
        if hook.required?
          log.warning "Cannot skip #{hook.name} since it is required"
        else
          log.warning "Skipping #{hook.name}"
          return true
        end
      end

      !hook.run?
    end

    def print_result(hook, status, output)
      case status
      when :good
        log.success 'OK' unless hook.quiet?
      when :warn
        log.warning 'WARNING'
        print_report(output, :bold_warning)
      when :bad
        log.error 'FAILED'
        print_report(output, :bold_error)
      end
    end

    def print_report(output, format = :log)
      log.send(format, output) unless output.nil? || output.empty?
    end

    # Loads hooks that will be run.
    # This is done explicitly so that we only load hooks which will actually be
    # used.
{'fraction_non_alphanumeric': 0.07963446475195822, 'fraction_numerical': 0.0011189854531891085, 'mean_word_length': 2.0180078784468205, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2987209', 'n_tokens_mistral': 1559, 'n_tokens_neox': 1525, 'n_words': 507}