razor-x/config_curator

View on GitHub
lib/config_curator/units/component.rb

Summary

Maintainability
A
1 hr
Test Coverage
require 'mkmf'

module ConfigCurator
  # A component is a folder that should be copied.
  # The {#destination} will become a mirror of the {#source}.
  # The contents of the {#destination_path} is
  # completely replaced by the contents of the {#source_path}.
  class Component < Unit
    attr_accessor :fmode, :dmode, :owner, :group, :backend

    # (see Unit#uninstall)
    def uninstall(*args)
      s = super(*args)
      return s unless s
      uninstall_component
      true
    end

    # (see Unit#install)
    def install
      s = super
      return s unless s
      install_component
      set_mode
      set_owner
      true
    end

    # (see Unit#install?)
    def install?
      s = super
      return s unless s
      fail InstallFailed, 'No component source path specified.' if source_path.nil?
      fail InstallFailed, 'No component install path specified.' if destination_path.nil?
      fail InstallFailed, "Source path does not exist: #{source}" unless Dir.exist? source_path
      true
    end

    private

    # Uninstalls the component by removing the directory.
    def uninstall_component
      FileUtils.remove_entry_secure destination_path if Dir.exist? destination_path
    end

    # Recursively creates the necessary directories and installs the component.
    # Any files in the install directory not in the source directory are removed.
    # Use rsync if available.
    def install_component
      if (backend != :stdlib && command?('rsync')) || backend == :rsync
        FileUtils.mkdir_p destination_path
        cmd = [command?('rsync'), '-rtc', '--del', '--links', "#{source_path}/", destination_path]
        logger.debug { "Running command: #{cmd.join ' '}" }
        system(*cmd)
      else
        FileUtils.remove_entry_secure destination_path if Dir.exist? destination_path
        FileUtils.mkdir_p destination_path
        FileUtils.cp_r "#{source_path}/.", destination_path, preserve: true
      end
    end

    # Recursively sets file mode.
    # @todo Make this more platform independent.
    def set_mode
      chmod = command? 'chmod'
      find = command? 'find'

      return unless chmod && find

      {fmode: 'f', dmode: 'd'}.each do |k, v|
        next if send(k).nil?
        cmd = [find, destination_path, '-type', v, '-exec']
        cmd.concat [chmod, send(k).to_s(8), '{}', '+']
        logger.debug { "Running command: #{cmd.join ' '}" }
        system(*cmd)
      end
    end

    # Recursively sets file owner and group.
    # @todo Make this more platform independent.
    def set_owner
      return unless owner || group
      chown = command? 'chown'

      return unless chown

      cmd = [chown, '-R', "#{owner}:#{group}", destination_path]
      logger.debug { "Running command: #{cmd.join ' '}" }
      system(*cmd)
    end
  end
end