Class: Sprout::SFTPTask

Inherits:
Rake::Task
  • Object
show all
Defined in:
lib/sprout/tasks/sftp_task.rb

Overview

The SFTPTask provides a simple rake task interface to the SFTP client RubyGem. This task can allow you to easily push build artifacts to a remote server with a single shell command.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(task_name, app) ⇒ SFTPTask

Returns a new instance of SFTPTask.



80
81
82
83
84
85
86
87
# File 'lib/sprout/tasks/sftp_task.rb', line 80

def initialize(task_name, app)
  super(task_name, app)
  @name = name
  @files = []
  @dir_mode = 0755
  @file_mode = 0644
  @host = nil
end

Instance Attribute Details

#dir_modeObject

the mode for created directories. Defaults to 0755



61
62
63
# File 'lib/sprout/tasks/sftp_task.rb', line 61

def dir_mode
  @dir_mode
end

#file_modeObject

The mode for transmitted files. Defaults to 0644



59
60
61
# File 'lib/sprout/tasks/sftp_task.rb', line 59

def file_mode
  @file_mode
end

#filesObject

Collection of files that should be transmitted to the remote server



50
51
52
# File 'lib/sprout/tasks/sftp_task.rb', line 50

def files
  @files
end

#hostObject

Host name of the server to connect to with no protocol prefix, like: sub.yourhost.com



52
53
54
# File 'lib/sprout/tasks/sftp_task.rb', line 52

def host
  @host
end

#local_pathObject

The local path to mask from transmitted files. This is key feature for automated file transmission. For example, if you are sending a file:

bin/assets/img/SomeImage.jpg

into a directory on your server like:

/var/www/someproject/

You don’t necessarily want the ‘bin’ folder copied over, so you set the local_path to ‘bin’ like:

t.local_path = 'bin'

and your server will have the file uploaded to:

/var/www/someproject/assets/img/SomeImage.jpg


71
72
73
# File 'lib/sprout/tasks/sftp_task.rb', line 71

def local_path
  @local_path
end

#passwordObject

Password to send to the remote host. You will be prompted for this value if it is left null.

NOTE: You should never check a file into version control with this field filled in, it is provided here as a convenience for getting set up.



78
79
80
# File 'lib/sprout/tasks/sftp_task.rb', line 78

def password
  @password
end

#remote_pathObject

The Remote base path where files should be transmitted, can be absolute or relative.



73
74
75
# File 'lib/sprout/tasks/sftp_task.rb', line 73

def remote_path
  @remote_path
end

#usernameObject

Username to send to the remote host. You will be prompted for this value if it is left null.

NOTE: You should never check a file into version control with this field filled in, it is provided here as a convenience for getting set up.



57
58
59
# File 'lib/sprout/tasks/sftp_task.rb', line 57

def username
  @username
end

Class Method Details

.define_task(args) {|t| ... } ⇒ Object

:nodoc:

Yields:

  • (t)


89
90
91
92
# File 'lib/sprout/tasks/sftp_task.rb', line 89

def self.define_task(args, &block) # :nodoc:
  t = super
  yield t if block_given?
end

Instance Method Details

#create_remote_dir(path, sftp) ⇒ Object

:nodoc:



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/sprout/tasks/sftp_task.rb', line 161

def create_remote_dir(path, sftp) # :nodoc:
  begin
    sftp.stat(File.dirname(path))
  rescue Net::SFTP::Operations::StatusException => e
    raise unless e.code == 2
    dir = File.dirname(path.sub(@remote_path, ''))
    parts = dir.split(File::SEPARATOR)
    part = File.join(@remote_path, parts.shift)
    while(part)
      begin
        sftp.stat(part)
      rescue Net::SFTP::Operations::StatusException => ne
        raise unless ne.code == 2
        sftp.mkdir(part, :permissions => @dir_mode)
      end
      if(parts.size > 0)
        part = File.join(part, parts.shift)
      else
        part = nil
      end
    end
  end
end

#execute(*args) ⇒ Object

:nodoc:



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/sprout/tasks/sftp_task.rb', line 94

def execute(*args) # :nodoc:
  if(@files.size == 0)
    if(@local_path)
      expr = @local_path + '/**/**/*'
      @files = FileList[expr]
    else
      raise SFTPError.new('SFTP requires either a local_path or files to be transmitted')
    end
  else
    if(!@local_path)
      @local_path = ''
    end
  end

  if(@host.nil?)
    raise SFTPError.new('SFTP requires non-nil host parameter')
  end

  if(@username.nil?)
    print "Username: "
    @username = $stdin.gets.chomp!
    raise SFTPError.new('SFTP requires username parameter') unless @username
  end

  if(@password.nil?)
    print "Password: "
    @password = $stdin.gets.chomp!
#        @password = Password.get
    raise SFTPError.new('SFTP requires password parameter') unless @password
  end

  if(get_confirmation)
    puts ">> Connecting to Remote Server: #{@username}@#{@host}:#{@remote_path}"
    
    Net::SFTP.start(@host, @username, :password => @password, :keys => []) do |sftp|
      begin
        dir = sftp.opendir(@remote_path)
      rescue Net::SFTP::Operations::StatusException
        puts "[ERROR] [#{@remote_path}] does not exist on the server"
        return
      end
      for file in @files
        next if File.stat(file).directory?
        remote_file = remote_file_name(file)
        put_file(file, remote_file, sftp)
      end
    end
  else
    puts "[WARNING] Publish aborted by user request"
  end
end

#file_changed(local_file, remote_file, sftp) ⇒ Object

:nodoc:



185
186
187
188
189
190
191
# File 'lib/sprout/tasks/sftp_task.rb', line 185

def file_changed(local_file, remote_file, sftp) # :nodoc:
  local_stat = File.stat(local_file)
  remote_stat = sftp.stat(remote_file)
  time_difference = (local_stat.mtime > Time.at(remote_stat.mtime))
  size_difference = (local_stat.size != remote_stat.size)
  return (time_difference || size_difference)
end

#get_confirmationObject

:nodoc:



197
198
199
200
201
202
203
# File 'lib/sprout/tasks/sftp_task.rb', line 197

def get_confirmation # :nodoc:
  puts "-----------------------------------------"
  puts "Are you sure you want to publish #{@files.size} files to:"
  puts "#{@username}@#{@host}:#{@remote_path}? [Yn]"
  response = $stdin.gets.chomp!
  return (response.downcase == 'y' || response == "")
end

#put_file(local_file, remote_file, sftp) ⇒ Object

:nodoc:



146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/sprout/tasks/sftp_task.rb', line 146

def put_file(local_file, remote_file, sftp) # :nodoc:
  begin
    create_remote_dir(remote_file, sftp)
    
    if(file_changed(local_file, remote_file, sftp))
      puts ">> Pushing #{local_file} to: #{remote_file}"
      sftp.put_file(local_file, remote_file)
    end
  rescue Net::SFTP::Operations::StatusException => e
    raise unless e.code == 2
    sftp.put_file(local_file, remote_file)
    sftp.setstat(remote_file, :permissions => @file_mode)
  end
end

#remote_file_name(file) ⇒ Object

:nodoc:



193
194
195
# File 'lib/sprout/tasks/sftp_task.rb', line 193

def remote_file_name(file) # :nodoc:
  return @remote_path + file.sub(@local_path, '')
end