Skip to content

Instantly share code, notes, and snippets.

@randyjhunt
Created July 22, 2009 04:56
Show Gist options
  • Select an option

  • Save randyjhunt/151824 to your computer and use it in GitHub Desktop.

Select an option

Save randyjhunt/151824 to your computer and use it in GitHub Desktop.
require 'capistrano/recipes/deploy/strategy/base'
require 'fileutils'
require 'tempfile' # Dir.tmpdir
require 'net/ssh'
require 'net/sftp'
require 'find'
module Capistrano
module Deploy
module Strategy
# Special Strategy for a special price!
# This strategy is created in favor of the sftp only apps, in lack of ssh login support
#
# * exports the repository to a local directory
# * uploads all the files to the remote server using an sftp script
# * renames current directory to a directory with a timestamp of 1 hour ago
# * renames the uploaded directory to current
class SftpCopy < Base
def deploy!
logger.debug "getting (via #{copy_strategy}) revision #{revision} to #{destination}"
system(command)
File.open(File.join(destination, "REVISION"), "w") { |f| f.puts(revision) }
logger.debug "Connecting to sftp user = #{configuration[:user]}"
Net::SSH.start(configuration[:host], configuration[:user], configuration[:password]) do |ssh|
ssh.sftp.connect do |sftp|
logger.debug "Creating directory: #{remote_dir}"
sftp.mkdir remote_dir, :permissions => 0755
logger.debug "Uploading files from #{destination} to #{remote_dir}"
logger.debug "Why don't you grab a cup of coffee while you wait, i might be busy for some time...\nJust sit back and enjoy the show..."
Find.find(destination) do |file|
if File.stat(file).directory?
remote_directory = remote_dir + file.sub(destination, '')
begin
sftp.stat(remote_directory)
rescue Net::SFTP::Operations::StatusException => e
raise "BOEM" unless e.code == 2
sftp.mkdir(remote_directory, :permissions => 0755)
end
else
remote_file = remote_dir + file.sub(destination, '')
sftp.put_file file, remote_file
sftp.setstat(remote_file, :permissions => 0644)
end
end
logger.debug "RENAMING DIRECTORIES"
sftp.rename "#{configuration[:copy_remote_dir]}/current", "#{configuration[:copy_remote_dir]}/#{(Time.now - 1.hour).utc.strftime("%Y%m%d%H%M%S")}"
sftp.rename "#{remote_dir}", "#{configuration[:copy_remote_dir]}/current"
end
end
ensure
logger.debug "Remove local export"
FileUtils.rm_rf destination rescue nil
end
def check!
super.check do |d|
end
end
private
# Returns the basename of the release_path, which will be used to
# name the local copy and archive file.
def destination
@destination ||= File.join(tmpdir, File.basename(configuration[:release_path]))
end
# Returns the value of the :copy_strategy variable, defaulting to
# :checkout if it has not been set.
def copy_strategy
@copy_strategy ||= configuration.fetch(:copy_strategy, :checkout)
end
# Should return the command(s) necessary to obtain the source code
# locally.
def command
@command ||= case copy_strategy
when :checkout
source.checkout(revision, destination)
when :export
source.export(revision, destination)
end
end
# Returns the name of the file that the source code will be
# compressed to.
def filename
@filename ||= File.join(tmpdir, "#{File.basename(destination)}.#{compression_extension}")
end
# The directory to which the copy should be checked out
def tmpdir
@tmpdir ||= configuration[:copy_dir] || Dir.tmpdir
end
# The directory on the remote server to which the archive should be
# copied
def remote_dir
@remote_dir ||= "#{configuration[:copy_remote_dir]}/#{File.basename(configuration[:release_path])}" || "/tmp"
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment