<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/capistrano/processable.rb</filename>
    </added>
    <added>
      <filename>lib/capistrano/transfer.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
 
   s.add_dependency 'net-ssh', &quot;&gt;= 1.99.2&quot;
   s.add_dependency 'net-sftp', &quot;&gt;= 1.99.1&quot;
+  s.add_dependency 'net-scp', &quot;&gt;= 0.99.0&quot;
   s.add_dependency 'net-ssh-gateway', &quot;&gt;= 0.99.0&quot;
   s.add_dependency 'highline'
 </diff>
      <filename>capistrano.gemspec</filename>
    </modified>
    <modified>
      <diff>@@ -1,31 +1,11 @@
 require 'capistrano/errors'
+require 'capistrano/processable'
 
 module Capistrano
 
   # This class encapsulates a single command to be executed on a set of remote
   # machines, in parallel.
   class Command
-    module Processable
-      def process_iteration(wait=nil, &amp;block)
-        sessions.each { |session| session.preprocess }
-        return false if block &amp;&amp; !block.call(self)
-
-        readers = sessions.map { |session| session.listeners.keys }.flatten.reject { |io| io.closed? }
-        writers = readers.select { |io| io.respond_to?(:pending_write?) &amp;&amp; io.pending_write? }
-
-        readers, writers, = IO.select(readers, writers, nil, wait)
-
-        if readers
-          sessions.each do |session|
-            ios = session.listeners.keys
-            session.postprocess(ios &amp; readers, ios &amp; writers)
-          end
-        end
-
-        true
-      end
-    end
-
     include Processable
 
     attr_reader :command, :sessions, :options</diff>
      <filename>lib/capistrano/command.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-require 'capistrano/upload'
+require 'capistrano/transfer'
 
 module Capistrano
   class Configuration
@@ -9,22 +9,29 @@ module Capistrano
         # by the current task. If &lt;tt&gt;:mode&lt;/tt&gt; is specified it is used to
         # set the mode on the file.
         def put(data, path, options={})
-          execute_on_servers(options) do |servers|
-            targets = servers.map { |s| sessions[s] }
-            Upload.process(targets, path, :data =&gt; data, :mode =&gt; options[:mode], :logger =&gt; logger)
-          end
+          upload(StringIO.new(data), path, options)
         end
     
-        # Get file remote_path from FIRST server targetted by
+        # Get file remote_path from FIRST server targeted by
         # the current task and transfer it to local machine as path.
         #
         # get &quot;#{deploy_to}/current/log/production.log&quot;, &quot;log/production.log.web&quot;
-        def get(remote_path, path, options = {})
-          execute_on_servers(options.merge(:once =&gt; true)) do |servers|
-            logger.info &quot;downloading `#{servers.first.host}:#{remote_path}' to `#{path}'&quot;
-            sftp = sessions[servers.first].sftp
-            sftp.download! remote_path, path
-            logger.debug &quot;download finished&quot; 
+        def get(remote_path, path, options={}, &amp;block)
+          download(remote_path, path, options.merge(:once =&gt; true), &amp;block)
+        end
+
+        def upload(from, to, options={}, &amp;block)
+          transfer(:up, from, to, options, &amp;block)
+        end
+
+        def download(from, to, options={}, &amp;block)
+          transfer(:down, from, to, options, &amp;block)
+        end
+
+        def transfer(direction, from, to, options={}, &amp;block)
+          execute_on_servers(options) do |servers|
+            targets = servers.map { |s| sessions[s] }
+            Transfer.process(direction, from, to, targets, options.merge(:logger =&gt; logger), &amp;block)
           end
         end
 </diff>
      <filename>lib/capistrano/configuration/actions/file_transfer.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,6 +10,6 @@ module Capistrano
   end
 
   class ConnectionError &lt; RemoteError; end
-  class UploadError &lt; RemoteError; end
+  class TransferError &lt; RemoteError; end
   class CommandError &lt; RemoteError; end
 end</diff>
      <filename>lib/capistrano/errors.rb</filename>
    </modified>
    <modified>
      <diff>@@ -253,7 +253,7 @@ HELP
       end
     end
 
-    # All open sessions
+    # All open sessions, needed to satisfy the Command::Processable include
     def sessions
       configuration.sessions.values
     end</diff>
      <filename>lib/capistrano/shell.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>lib/capistrano/upload.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>d099e45c6b6fda913550d61433523da416e79106</id>
    </parent>
  </parents>
  <author>
    <name>Jamis Buck</name>
    <email>jamis@37signals.com</email>
  </author>
  <url>http://github.com/jamis/capistrano/commit/06bfd0274ce858aa9cd97af200019d68695b3b9d</url>
  <id>06bfd0274ce858aa9cd97af200019d68695b3b9d</id>
  <committed-date>2008-04-24T21:54:50-07:00</committed-date>
  <authored-date>2008-04-24T08:51:54-07:00</authored-date>
  <message>generic file transfer mechanism using either SFTP or SCP</message>
  <tree>bde3da4395b84085b7ecc0d6f15349a494e3f776</tree>
  <committer>
    <name>Jamis Buck</name>
    <email>jamis@37signals.com</email>
  </committer>
</commit>
