diff options
Diffstat (limited to 'vendor/rsync_command/lib/rsync_command.rb')
| -rw-r--r-- | vendor/rsync_command/lib/rsync_command.rb | 96 | 
1 files changed, 96 insertions, 0 deletions
diff --git a/vendor/rsync_command/lib/rsync_command.rb b/vendor/rsync_command/lib/rsync_command.rb new file mode 100644 index 0000000..39e5945 --- /dev/null +++ b/vendor/rsync_command/lib/rsync_command.rb @@ -0,0 +1,96 @@ +require "rsync_command/version" +require "rsync_command/ssh_options" +require "rsync_command/thread_pool" + +require 'monitor' + +class RsyncCommand +  attr_accessor :failures, :logger + +  def initialize(options={}) +    @options = options.dup +    @logger = @options.delete(:logger) +    @flags = @options.delete(:flags) +    @failures = [] +    @failures.extend(MonitorMixin) +  end + +  # +  # takes an Enumerable and iterates each item in the list in parallel. +  # +  def asynchronously(array, &block) +    pool = ThreadPool.new +    array.each do |item| +      pool.schedule(item, &block) +    end +    pool.shutdown +  end + +  # +  # runs rsync, recording failures +  # +  def exec(src, dest, options={}) +    @failures.synchronize do +      @failures.clear +    end +    rsync_cmd = command(src, dest, options) +    if options[:chdir] +      rsync_cmd = "cd '#{options[:chdir]}'; #{rsync_cmd}" +    end +    @logger.debug rsync_cmd if @logger +    ok = system(rsync_cmd) +    unless ok +      @failures.synchronize do +        @failures << {:source => src, :dest => dest, :options => options.dup} +      end +    end +  end + +  # +  # returns true if last exec returned a failure +  # +  def failed? +    @failures && @failures.any? +  end + +  # +  # build rsync command +  # +  def command(src, dest, options={}) +    src = remote_address(src) +    dest = remote_address(dest) +    options = @options.merge(options) +    flags = [] +    flags << @flags if @flags +    flags << options[:flags] if options.has_key?(:flags) +    flags << '--delete' if options[:delete] +    flags << includes(options[:includes]) if options.has_key?(:includes) +    flags << excludes(options[:excludes]) if options.has_key?(:excludes) +    flags << SshOptions.new(options[:ssh]).to_flags if options.has_key?(:ssh) +    "rsync #{flags.compact.join(' ')} #{src} #{dest}" +  end + +  private + +  # +  # Creates an rsync location if the +address+ is a hash with keys :user, :host, and :path +  # (each component is optional). If +address+ is a string, we just pass it through. +  # +  def remote_address(address) +    if address.is_a? String +      address # assume it is already formatted. +    elsif address.is_a? Hash +      [[address[:user], address[:host]].compact.join('@'), address[:path]].compact.join(':') +    end +  end + +  def excludes(patterns) +    [patterns].flatten.compact.map { |p| "--exclude='#{p}'" } +  end + +  def includes(patterns) +    [patterns].flatten.compact.map { |p| "--include='#{p}'" } +  end + +end +  | 
