<commit_before>require 'statistrano/base/rake_tasks'

module Statistrano

  # A server instance
  class Base

    # @param [String] name Name of the server
    # @attribute name [String]
    attr_reader :name
    # @method remote [String]
    # @method user [String]
    # @method password [String]
    # @method keys [Array]
    # @method forward_agent [Boolean]
    attr_accessor :remote, :user, :password, :keys, :forward_agent
    # @method build_task [String]
    # @method releases [Boolean]
    # @method release_count [Integer]
    # @method release_dir [String]
    # @method public_dir [String]
    # @method local_dir [String]
    # @method project_root [String]
    attr_accessor :build_task, :releases, :release_count, :release_dir, :public_dir, :local_dir, :project_root
    # @method git_check_branch [String]
    attr_accessor :git_check_branch
    # @return [Void]
    def initialize(name)
      @name = name
      @releases             ||= true
      @release_count        ||= 5
      @release_dir          ||= 'releases'
      @public_dir           ||= 'current'
      @local_dir            ||= 'build'
      @build_task           ||= 'middleman:build'

      RakeTasks.register self
    end

    # Warn if deprecated argument is passed
    # @return [Void]
    def method_missing(meth, *args, &block)
      deprecated_args = [ :git_checks ]
      deprecated_args.each do |arg|
        if meth.to_s =~ /^#{arg}=$/
          LOG.error ":#{arg} is deprecated"
        else
          super
        end
      end
    end

    # Run ssh sync command and handle exceptions
    # @param [String] command the shell command to run
    # @return [Void]
    def run_ssh_command command # :yields: :channel, :stream, :data
      opts = {}
      [:user, :password, :keys, :forward_agent].each do |key|
        value = instance_variable_get("@#{key}")
        opts[key] = value if value
      end
      begin
        Net::SSH.start @remote, @user, opts do |ssh|
          ssh.exec command do |channel, stream, data|
            if stream == :stderr
              LOG.error "Error executing the command:\n\t\"#{command}\"" +
                        "\n" +
                        "\n\tRemote Error:\n\t#{data}"
              exit
            else
              yield(channel, stream, data) if block_given?
            end
          end
        end
      rescue Net::SSH::AuthenticationFailed
        puts "Authentication failed when connecting to '#{@remote}'".colorize :red
      end
    end

    # Deploy without git checks
    # @return [Void]
    def deploy
      LOG.msg "setting up #{name}", "deploying"
      build.invoke

      if @releases
        create_release
        prune_releases
      else
        release_to_public_path
      end

      LOG.msg "Cleaning up", nil
      FileUtils.rm_r local_path
    end

    # Deploy with git checks
    # @return [Void]
    def safe_deploy
      if !Util.working_tree_clean?
        LOG.error "You need to commit or stash your changes before deploying"
      # make sure you're on the branch selected to check against
      elsif Util.current_git_branch != @git_check_branch
        LOG.error "You shouldn't deploy from any branch but #{@git_check_branch}"
      # make sure you're up to date
      elsif !Util.remote_up_to_date?
        LOG.error "You need to update or push your changes before deploying"
      # do all that deployment stuff
      else
        deploy
      end
    end

    # create a single release at public path
    # used for doing feature branches
    # @return [Void]
    def release_to_public_path

      # Setup tasks for remote
      steps = []

      # make sure release_path is created & create new release
      steps << { cmd: "mkdir -p #{public_path}", env: :remote, log: "Preparing release directory" }
      # rsync build to the @public_path
      host_connection = @user ? "#{@user}@#{@remote}" : @remote
      steps << { cmd: "rsync -avqz --delete-after -e ssh #{local_path}/ #{host_connection}:#{public_path}/", env: :local, log: "Syncing files to remote" }

      run_commands(steps)

      LOG.msg "Created release at #{public_dir}"

    end

    # Create a new release
    # @return [Void]
    def create_release

      # Setup tasks for remote
      steps = []
      # timestamp for release folder
      release_name = Time.now.strftime("%Y%m%d%H%M%S")
      current_release = File.join release_path, release_name

      # make sure release_path is created & create new release
      steps << {cmd: "mkdir -p #{current_release}", env: :remote, log: "Preparing release directory"}
      # rsync build to the @current_release
      host_connection = @user ? "#{@user}@#{@remote}" : @remote
      steps << {cmd: "rsync -avqz -e ssh #{local_path}/ #{host_connection}:#{current_release}/", env: :local, log: "Syncing files to remote"}
      # update symlink of @current_release -> current, the -nf option updates in place
      steps << {cmd: "ln -nfs #{current_release} #{public_path}", env: :remote, log: "Symlinking public_dir to release"}

      run_commands(steps)

      LOG.msg "Created release at #{public_dir}: #{release_name}"

      add_manifest_release release_name
    end

    # Rollback to last release
    # @return [Void]<commit_msg>give a name and generate a manifest even for release = false deploys<commit_after>require 'statistrano/base/rake_tasks'

module Statistrano

  # A server instance
  class Base

    # @param [String] name Name of the server
    # @attribute name [String]
    attr_reader :name
    # @method remote [String]
    # @method user [String]
    # @method password [String]
    # @method keys [Array]
    # @method forward_agent [Boolean]
    attr_accessor :remote, :user, :password, :keys, :forward_agent
    # @method build_task [String]
    # @method releases [Boolean]
    # @method release_count [Integer]
    # @method release_dir [String]
    # @method public_dir [String]
    # @method local_dir [String]
    # @method project_root [String]
    attr_accessor :build_task, :releases, :release_count, :release_dir, :public_dir, :local_dir, :project_root
    # @method git_check_branch [String]
    attr_accessor :git_check_branch
    # @return [Void]
    def initialize(name)
      @name = name
      @releases             ||= true
      @release_count        ||= 5
      @release_dir          ||= 'releases'
      @public_dir           ||= 'current'
      @local_dir            ||= 'build'
      @build_task           ||= 'middleman:build'

      RakeTasks.register self
    end

    # Warn if deprecated argument is passed
    # @return [Void]
    def method_missing(meth, *args, &block)
      deprecated_args = [ :git_checks ]
      deprecated_args.each do |arg|
        if meth.to_s =~ /^#{arg}=$/
          LOG.error ":#{arg} is deprecated"
        else
          super
        end
      end
    end

    # Run ssh sync command and handle exceptions
    # @param [String] command the shell command to run
    # @return [Void]
    def run_ssh_command command # :yields: :channel, :stream, :data
      opts = {}
      [:user, :password, :keys, :forward_agent].each do |key|
        value = instance_variable_get("@#{key}")
        opts[key] = value if value
      end
      begin
        Net::SSH.start @remote, @user, opts do |ssh|
          ssh.exec command do |channel, stream, data|
            if stream == :stderr
              LOG.error "Error executing the command:\n\t\"#{command}\"" +
                        "\n" +
                        "\n\tRemote Error:\n\t#{data}"
              exit
            else
              yield(channel, stream, data) if block_given?
            end
          end
        end
      rescue Net::SSH::AuthenticationFailed
        puts "Authentication failed when connecting to '#{@remote}'".colorize :red
      end
    end

    # Deploy without git checks
    # @return [Void]
    def deploy
      LOG.msg "setting up #{name}", "deploying"
      build.invoke

      if @releases
        create_release
        prune_releases
      else
        release_to_public_path
      end

      LOG.msg "Cleaning up", nil
      FileUtils.rm_r local_path
    end

    # Deploy with git checks
    # @return [Void]
    def safe_deploy
      if !Util.working_tree_clean?
        LOG.error "You need to commit or stash your changes before deploying"
      # make sure you're on the branch selected to check against
      elsif Util.current_git_branch != @git_check_branch
        LOG.error "You shouldn't deploy from any branch but #{@git_check_branch}"
      # make sure you're up to date
      elsif !Util.remote_up_to_date?
        LOG.error "You need to update or push your changes before deploying"
      # do all that deployment stuff
      else
        deploy
      end
    end

    # create a single release at public path
    # used for doing feature branches
    # @return [Void]
    def release_to_public_path

      # Setup tasks for remote
      steps = []

      release_name = @public_dir

      # make sure release_path is created & create new release
      steps << { cmd: "mkdir -p #{public_path}", env: :remote, log: "Preparing release directory" }
      # rsync build to the @public_path
      host_connection = @user ? "#{@user}@#{@remote}" : @remote
      steps << { cmd: "rsync -avqz --delete-after -e ssh #{local_path}/ #{host_connection}:#{public_path}/", env: :local, log: "Syncing files to remote" }

      run_commands(steps)

      LOG.msg "Created release at #{public_dir}"
      add_manifest_release release_name

    end

    # Create a new release
    # @return [Void]
    def create_release

      # Setup tasks for remote
      steps = []
      # timestamp for release folder
      release_name = Time.now.strftime("%Y%m%d%H%M%S")
      current_release = File.join release_path, release_name

      # make sure release_path is created & create new release
      steps << {cmd: "mkdir -p #{current_release}", env: :remote, log: "Preparing release directory"}
      # rsync build to the @current_release
      host_connection = @user ? "#{@user}@#{@remote}" : @remote
      steps << {cmd: "rsync -avqz -e ssh #{local_path}/ #{host_connection}:#{current_release}/", env: :local, log: "Syncing files to remote"}
      # update symlink of @current_release -> current, the -nf option updates in place
      steps << {cmd: "ln -nfs #{current_release} #{public_path}", env: :remote, log: "Symlinking public_dir to release"}

      run_commands(steps)

      LOG.msg "Created release at #{public_dir}: #{release_name}"

      add_manifest_release release_name
    end

    # Rollback to last release
    # @return [Void]
{'fraction_non_alphanumeric': 0.10504003768252473, 'fraction_numerical': 0.00018841262364578426, 'mean_word_length': 2.423411802644308, 'pattern_counts': {'":': 2, '<': 23, '<?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': '7355790', 'n_tokens_mistral': 3199, 'n_tokens_neox': 3108, 'n_words': 988}