aboutsummaryrefslogtreecommitdiff
path: root/vendor/rsync_command/lib/rsync_command.rb
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rsync_command/lib/rsync_command.rb')
-rw-r--r--vendor/rsync_command/lib/rsync_command.rb96
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
+