<commit_before># encoding: UTF-8

module Gjp
  # facade to git, currently implemented with calls to the git command
  # prefixes all tags with "gjp_"
  class Git
    include Logger

    # inits a new git manager object pointing to the specified
    # directory
    def initialize(directory)
      @directory = directory
    end

    # inits a repo
    def init
      Dir.chdir(@directory) do
        if Dir.exists?(".git") == false
          `git init`
        else
          raise GitAlreadyInitedError
        end
      end
    end

    # returns a list of filenames that changed in the repo
    # since the specified tag
    def changed_files_since(tag)
      changed_files_between(tag, nil, ".")
    end

    # returns a list of filenames that changed in the repo
    # between specified tags, in a certain directory
    def changed_files_between(start_tag, end_tag, directory)
      Dir.chdir(@directory) do
        prefixed_start_tag = "gjp_#{start_tag}"
        prefixed_end_tag = if end_tag
          "gjp_#{end_tag}"
        else
          "HEAD"
        end
        `git diff-tree --no-commit-id --name-only -r #{prefixed_start_tag} #{prefixed_end_tag} -- #{directory}`.split("\n")
      end
    end

    # adds all files in the current directory and removes
    # all files not in the current directory.
    # if tag is given, commit is also tagged
    def commit_whole_directory(message, tag = nil, tag_message = nil)
      Dir.chdir(@directory) do
        log.debug "committing with message: #{message}"

        `git rm -r --cached --ignore-unmatch .`
        `git add .`
        `git commit -m "#{message}"`

        if tag != nil
          if tag_message != nil
            `git tag gjp_#{tag} -m "#{tag_message}"`
          else
            `git tag gjp_#{tag}`
          end
        end
      end
    end

    # returns the highest suffix found in tags with the given prefix
    def get_tag_maximum_suffix(prefix)
      Dir.chdir(@directory) do
        `git tag`.split.map do |tag|
          if tag =~ /^gjp_#{prefix}_([0-9]+)$/
            $1.to_i
          else
            0
          end
         end.max or 0
      end
    end

    # reverts path contents as per specified tag
    def revert_whole_directory(path, tag)
      Dir.chdir(@directory) do
        # reverts added and modified files, both in index and working tree
        `git checkout -f gjp_#{tag} -- #{path}`

        # compute the list of deleted files
        files_in_tag = `git ls-tree --name-only -r gjp_#{tag} -- #{path}`.split("\n")
        files_in_head = `git ls-tree --name-only -r HEAD -- #{path}`.split("\n")
        files_added_after_head = `git ls-files -o -- #{path}`.split("\n")
        files_to_delete = files_in_head - files_in_tag + files_added_after_head

        files_to_delete.each do |file|
          File.delete(file)
        end
      end
    end

    # 3-way merges the git file at path with the one in new_path
    # assuming they have a common ancestor at the specified tag
    # returns the conflict count<commit_msg>Bugfix: avoid error during finish when whole directories were added<commit_after># encoding: UTF-8

module Gjp
  # facade to git, currently implemented with calls to the git command
  # prefixes all tags with "gjp_"
  class Git
    include Logger

    # inits a new git manager object pointing to the specified
    # directory
    def initialize(directory)
      @directory = directory
    end

    # inits a repo
    def init
      Dir.chdir(@directory) do
        if Dir.exists?(".git") == false
          `git init`
        else
          raise GitAlreadyInitedError
        end
      end
    end

    # returns a list of filenames that changed in the repo
    # since the specified tag
    def changed_files_since(tag)
      changed_files_between(tag, nil, ".")
    end

    # returns a list of filenames that changed in the repo
    # between specified tags, in a certain directory
    def changed_files_between(start_tag, end_tag, directory)
      Dir.chdir(@directory) do
        prefixed_start_tag = "gjp_#{start_tag}"
        prefixed_end_tag = if end_tag
          "gjp_#{end_tag}"
        else
          "HEAD"
        end
        `git diff-tree --no-commit-id --name-only -r #{prefixed_start_tag} #{prefixed_end_tag} -- #{directory}`.split("\n")
      end
    end

    # adds all files in the current directory and removes
    # all files not in the current directory.
    # if tag is given, commit is also tagged
    def commit_whole_directory(message, tag = nil, tag_message = nil)
      Dir.chdir(@directory) do
        log.debug "committing with message: #{message}"

        `git rm -r --cached --ignore-unmatch .`
        `git add .`
        `git commit -m "#{message}"`

        if tag != nil
          if tag_message != nil
            `git tag gjp_#{tag} -m "#{tag_message}"`
          else
            `git tag gjp_#{tag}`
          end
        end
      end
    end

    # returns the highest suffix found in tags with the given prefix
    def get_tag_maximum_suffix(prefix)
      Dir.chdir(@directory) do
        `git tag`.split.map do |tag|
          if tag =~ /^gjp_#{prefix}_([0-9]+)$/
            $1.to_i
          else
            0
          end
         end.max or 0
      end
    end

    # reverts path contents as per specified tag
    def revert_whole_directory(path, tag)
      Dir.chdir(@directory) do
        # reverts added and modified files, both in index and working tree
        `git checkout -f gjp_#{tag} -- #{path}`

        # compute the list of deleted files
        files_in_tag = `git ls-tree --name-only -r gjp_#{tag} -- #{path}`.split("\n")
        files_in_head = `git ls-tree --name-only -r HEAD -- #{path}`.split("\n")
        files_added_after_head = `git ls-files -o -- #{path}`.split("\n")
        files_to_delete = files_in_head - files_in_tag + files_added_after_head

        files_to_delete.each do |file|
          FileUtils.rm_rf(file)
        end
      end
    end

    # 3-way merges the git file at path with the one in new_path
    # assuming they have a common ancestor at the specified tag
    # returns the conflict count
{'fraction_non_alphanumeric': 0.09222984002611818, 'fraction_numerical': 0.002285341168788769, 'mean_word_length': 2.0758032128514055, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '4960153', 'n_tokens_mistral': 1883, 'n_tokens_neox': 1820, 'n_words': 624}