<commit_before>require 'fileutils'

module MCollective
  module Agent
    class Puppetupdate < RPC::Agent
      action "update_all" do
        begin
          update_all_branches
          reply[:output] = "Done"
        rescue Exception => e
          reply.fail! "Exception: #{e}"
        end
      end

      action "update" do
        validate :revision, String
        validate :revision, :shellsafe
        validate :branch, String
        validate :branch, :shellsafe

        begin
          ret = update_single_branch(request[:branch], request[:revision])
          if ret
            reply[:status] = "Done"
            [:from, :to].each { |s| reply[s] = ret[s] }
          else
            reply[:status] = "Deleted"
          end
        rescue Exception => e
          reply.fail! "Exception: #{e}"
        end
      end

      action "git_gc" do
        git_gc
      end

      attr_accessor :dir, :repo_url, :ignore_branches, :run_after_checkout, :remove_branches

      def initialize
        @dir                = config('directory', '/etc/puppet')
        @repo_url           = config('repository', 'http://git/puppet')
        @ignore_branches    = config('ignore_branches', '').split(',').map { |i| regexy_string(i) }
        @remove_branches    = config('remove_branches', '').split(',').map { |r| regexy_string(r) }
        @run_after_checkout = config('run_after_checkout', nil)
        super
      end

      def git_dir
        config('clone_at', "#{@dir}/puppet.git")
      end

      def env_dir
        "#{@dir}/environments"
      end

      def update_single_branch(branch, revision = '')
        whilst_locked do
          update_bare_repo
          ret = update_branch(branch, revision)
          cleanup_old_branches
          ret
        end
      end

      def strip_ignored_branches(branch_list)
        branch_list.reject do |branch|
          branch == '(no branch)' ||
            branch =~ /detached from/ ||
            ignore_branches.select { |b| b.match(branch) }.count > 0
        end
      end

      def git_branches
        strip_ignored_branches `cd #{git_dir} && git branch -a`.lines.
          map { |l| l.gsub(/\*/, '').strip }
      end

      def env_branches
        strip_ignored_branches `ls -1 #{env_dir}`.lines.map(&:strip)
      end

      def update_all_branches
        whilst_locked do
          update_bare_repo
          git_branches.reject do |branch|
            remove_branches.select { |b| b.match(branch) }.count > 0
          end.each { |branch| update_branch(branch) }
          cleanup_old_branches
        end
      end

      def cleanup_old_branches(config = nil)
        return if config && config !~ /yes|1|true/

        keep = git_branches.reject do |branch|
          remove_branches.select { |b| b.match(branch) }.count > 0
        end.map { |b| branch_dir(b) }
        (env_branches - keep).each do |branch|
          run "rm -rf '#{env_dir}/#{branch}'"
        end
      end

      def update_branch(branch, revision = '')
        return unless git_branches.include? branch

        branch_path = "#{env_dir}/#{branch_dir(branch)}/"
        Dir.mkdir(env_dir) unless File.exist?(env_dir)
        Dir.mkdir(branch_path) unless File.exist?(branch_path)

        ret = git_reset(revision.length > 0 ? revision : branch, branch_path)
        if run_after_checkout
          Dir.chdir(branch_path) { ret[:after_checkout] = system run_after_checkout }
        end
        ret
      end

      def git_reset(revision, work_tree)
        from = File.exist?("#{work_tree}/.git_revision") ? run("cat #{work_tree}/.git_revision").chomp : 'unknown'
        run "git --git-dir=#{git_dir} --work-tree=#{work_tree} checkout --detach --force #{revision}"
        run "git --git-dir=#{git_dir} --work-tree=#{work_tree} clean -dxf"
        to = run "git --git-dir=#{git_dir} --work-tree=#{work_tree} rev-parse HEAD"
        File.open("#{work_tree}/.git_revision", 'w') { |f| f.puts to }<commit_msg>Rubocop fixes.<commit_after>require 'fileutils'

module MCollective
  module Agent
    class Puppetupdate < RPC::Agent
      action "update_all" do
        begin
          update_all_branches
          reply[:output] = "Done"
        rescue Exception => e
          reply.fail! "Exception: #{e}"
        end
      end

      action "update" do
        validate :revision, String
        validate :revision, :shellsafe
        validate :branch, String
        validate :branch, :shellsafe

        begin
          ret = update_single_branch(request[:branch], request[:revision])
          if ret
            reply[:status] = "Done"
            [:from, :to].each { |s| reply[s] = ret[s] }
          else
            reply[:status] = "Deleted"
          end
        rescue Exception => e
          reply.fail! "Exception: #{e}"
        end
      end

      action "git_gc" do
        git_gc
      end

      attr_accessor :dir, :repo_url, :ignore_branches, :run_after_checkout, :remove_branches

      def initialize
        @dir                = config('directory', '/etc/puppet')
        @repo_url           = config('repository', 'http://git/puppet')
        @ignore_branches    = config('ignore_branches', '').split(',').map { |i| regexy_string(i) }
        @remove_branches    = config('remove_branches', '').split(',').map { |r| regexy_string(r) }
        @run_after_checkout = config('run_after_checkout', nil)
        super
      end

      def git_dir
        config('clone_at', "#{@dir}/puppet.git")
      end

      def env_dir
        "#{@dir}/environments"
      end

      def update_single_branch(branch, revision = '')
        whilst_locked do
          update_bare_repo
          ret = update_branch(branch, revision)
          cleanup_old_branches
          ret
        end
      end

      def strip_ignored_branches(branch_list)
        branch_list.reject do |branch|
          branch == '(no branch)' ||
            branch =~ /detached from/ ||
            ignore_branches.count { |b| b.match(branch) } > 0
        end
      end

      def git_branches
        strip_ignored_branches `cd #{git_dir} && git branch -a`.lines.
          map { |l| l.gsub(/\*/, '').strip }
      end

      def env_branches
        strip_ignored_branches `ls -1 #{env_dir}`.lines.map(&:strip)
      end

      def update_all_branches
        whilst_locked do
          update_bare_repo
          git_branches.reject do |branch|
            remove_branches.count { |b| b.match(branch) } > 0
          end.each { |branch| update_branch(branch) }
          cleanup_old_branches
        end
      end

      def cleanup_old_branches(config = nil)
        return if config && config !~ /yes|1|true/

        keep = git_branches.reject do |branch|
          remove_branches.count { |b| b.match(branch) } > 0
        end.map { |b| branch_dir(b) }
        (env_branches - keep).each do |branch|
          run "rm -rf '#{env_dir}/#{branch}'"
        end
      end

      def update_branch(branch, revision = '')
        return unless git_branches.include? branch

        branch_path = "#{env_dir}/#{branch_dir(branch)}/"
        Dir.mkdir(env_dir) unless File.exist?(env_dir)
        Dir.mkdir(branch_path) unless File.exist?(branch_path)

        ret = git_reset(revision.length > 0 ? revision : branch, branch_path)
        if run_after_checkout
          Dir.chdir(branch_path) { ret[:after_checkout] = system run_after_checkout }
        end
        ret
      end

      def git_reset(revision, work_tree)
        from = File.exist?("#{work_tree}/.git_revision") ? run("cat #{work_tree}/.git_revision").chomp : 'unknown'
        run "git --git-dir=#{git_dir} --work-tree=#{work_tree} checkout --detach --force #{revision}"
        run "git --git-dir=#{git_dir} --work-tree=#{work_tree} clean -dxf"
        to = run "git --git-dir=#{git_dir} --work-tree=#{work_tree} rev-parse HEAD"
        File.open("#{work_tree}/.git_revision", 'w') { |f| f.puts to }
{'fraction_non_alphanumeric': 0.12465233881163085, 'fraction_numerical': 0.0015170670037926676, 'mean_word_length': 2.0734265734265733, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 15, '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': '3059645', 'n_tokens_mistral': 2518, 'n_tokens_neox': 2473, 'n_words': 540}