<commit_before># -*- encoding: utf-8 -*-

require 'emeril/logging'

module Emeril

  # Exception class raised when a git repo is not clean.
  #
  class GitNotCleanError < StandardError ; end

  # Exception class raised when a git push does not return successfully.
  #
  class GitPushError < StandardError ; end

  # Applies a version tag on a git repository and pushes it to the origin
  # remote.
  #
  # @author <NAME> <<EMAIL>>
  #
  class GitTagger

    include Logging

    # Creates a new instance.
    #
    # @param [Hash] options configuration for a git tagger
    # @option options [Logger] an optional logger instance
    # @option options [String] source_path the path to a git repository
    # @option options [String] tag_prefix a prefix for a git tag version string
    # @option options [String] version (required) a version string
    # @raise [ArgumentError] if any required options are not set
    #
    def initialize(options = {})
      @logger = options[:logger]
      @source_path = options.fetch(:source_path, Dir.pwd)
      @tag_prefix = case options[:tag_prefix]
      when nil then
        DEFAULT_TAG_PREFIX
      when false
        ""
      else
        options[:tag_prefix]
      end
      @version = options.fetch(:version) do
        raise ArgumentError, ":version must be set"
      end
    end

    # Applies a version tag on a git repository and pushes it to the origin
    # remote.
    #
    def run
      guard_clean
      tag_version { git_push } unless already_tagged?
    end

    private

    DEFAULT_TAG_PREFIX = "v".freeze

    attr_reader :logger, :source_path, :tag_prefix, :version

    def already_tagged?
      if sh_with_code('git tag')[0].split(/\n/).include?(version_tag)
        info("Tag #{version_tag} has already been created.")
        true
      end
    end

    def clean?
      sh_with_code("git status --porcelain")[0].empty?
    end

    def git_push
      perform_git_push
      perform_git_push ' --tags'
      info("Pushed git commits and tags.")
    end

    def guard_clean
      clean? or raise GitNotCleanError,
        "There are files that need to be committed first."
    end

    def perform_git_push(options = '')
      cmd = "git push origin master #{options}"
      out, code = sh_with_code(cmd)
      if code != 0
        raise GitPushError,
          "Couldn't git push. `#{cmd}' failed with the following output:" +
            "\n\n#{out}\n"
      end
    end

    def sh_with_code(cmd, &block)
      cmd << " 2>&1"
      outbuf = ''
      debug(cmd)
      Dir.chdir(source_path) {
        outbuf = `#{cmd}`
        if $? == 0
          block.call(outbuf) if block
        end<commit_msg>Replace or flow control with a conditional (style).<commit_after># -*- encoding: utf-8 -*-

require 'emeril/logging'

module Emeril

  # Exception class raised when a git repo is not clean.
  #
  class GitNotCleanError < StandardError ; end

  # Exception class raised when a git push does not return successfully.
  #
  class GitPushError < StandardError ; end

  # Applies a version tag on a git repository and pushes it to the origin
  # remote.
  #
  # @author <NAME> <<EMAIL>>
  #
  class GitTagger

    include Logging

    # Creates a new instance.
    #
    # @param [Hash] options configuration for a git tagger
    # @option options [Logger] an optional logger instance
    # @option options [String] source_path the path to a git repository
    # @option options [String] tag_prefix a prefix for a git tag version string
    # @option options [String] version (required) a version string
    # @raise [ArgumentError] if any required options are not set
    #
    def initialize(options = {})
      @logger = options[:logger]
      @source_path = options.fetch(:source_path, Dir.pwd)
      @tag_prefix = case options[:tag_prefix]
      when nil then
        DEFAULT_TAG_PREFIX
      when false
        ""
      else
        options[:tag_prefix]
      end
      @version = options.fetch(:version) do
        raise ArgumentError, ":version must be set"
      end
    end

    # Applies a version tag on a git repository and pushes it to the origin
    # remote.
    #
    def run
      guard_clean
      tag_version { git_push } unless already_tagged?
    end

    private

    DEFAULT_TAG_PREFIX = "v".freeze

    attr_reader :logger, :source_path, :tag_prefix, :version

    def already_tagged?
      if sh_with_code('git tag')[0].split(/\n/).include?(version_tag)
        info("Tag #{version_tag} has already been created.")
        true
      end
    end

    def clean?
      sh_with_code("git status --porcelain")[0].empty?
    end

    def git_push
      perform_git_push
      perform_git_push ' --tags'
      info("Pushed git commits and tags.")
    end

    def guard_clean
      if !clean?
        raise GitNotCleanError,
          "There are files that need to be committed first."
      end
    end

    def perform_git_push(options = '')
      cmd = "git push origin master #{options}"
      out, code = sh_with_code(cmd)
      if code != 0
        raise GitPushError,
          "Couldn't git push. `#{cmd}' failed with the following output:" +
            "\n\n#{out}\n"
      end
    end

    def sh_with_code(cmd, &block)
      cmd << " 2>&1"
      outbuf = ''
      debug(cmd)
      Dir.chdir(source_path) {
        outbuf = `#{cmd}`
        if $? == 0
          block.call(outbuf) if block
        end
{'fraction_non_alphanumeric': 0.0907911802853437, 'fraction_numerical': 0.0025940337224383916, 'mean_word_length': 2.3444857496902105, 'pattern_counts': {'":': 2, '<': 17, '<?xml version=': 0, '>': 11, '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': '3709369', 'n_tokens_mistral': 1621, 'n_tokens_neox': 1581, 'n_words': 543}