Skip to content

Instantly share code, notes, and snippets.

@yyuu
Created April 18, 2012 09:42
Show Gist options
  • Save yyuu/2412394 to your computer and use it in GitHub Desktop.
Save yyuu/2412394 to your computer and use it in GitHub Desktop.
a capistrano strategy to deploy sub-directory in repository with "copy" strategy
#!/usr/bin/env ruby
#
# a capistrano strategy to deploy sub-directory in the repository.
# this is a stuff like "remote_cache_subdir" strategy described in following page,
# but based on "copy" strategy of capistrano deploy recipe.
#
# http://stackoverflow.com/questions/29168/deploying-a-git-subdirectory-in-capistrano
#
require 'capistrano'
require 'capistrano/recipes/deploy/strategy/copy'
require 'tmpdir'
class CopySubdir < Capistrano::Deploy::Strategy::Copy
def deploy!
update_repository_cache
copy_repository_cache
distribute!
ensure
FileUtils.rm filename rescue nil
FileUtils.rm_rf destination rescue nil
FileUtils.rm_rf repository_cache rescue nil if remove_repository_cache?
end
private
def update_repository_cache
if File.exists?(repository_cache)
logger.debug "refreshing local cache to revision #{revision} at #{repository_cache}"
system(source.sync(revision, repository_cache))
else
logger.debug "preparing local cache at #{repository_cache}"
system(source.checkout(revision, repository_cache))
end
# Check the return code of last system command and rollback if not 0
unless $? == 0
raise Capistrano::Error, "shell command failed with return code #{$?}"
end
end
def copy_repository_cache
logger.debug "copying cache from #{repository_cache_subdir} to deployment staging area #{destination}"
if copy_exclude.empty?
run_locally "cp -RPp #{repository_cache_subdir} #{destination} && #{mark}"
else
exclusions = copy_exclude.map { |e| "--exclude=\"#{e}\"" }.join(' ')
run_locally "rsync -lrpt #{exclusions} #{repository_cache_subdir}/ #{destination} && #{mark}"
end
logger.trace "compressing #{destination} to #{filename}"
Dir.chdir(copy_dir) { system(compress(File.basename(destination), File.basename(filename)).join(" ")) }
end
# Returns the command which will write the identifier of the
# revision being deployed to the REVISION file on each host.
def mark
"(echo #{revision} > #{destination}/REVISION)"
end
# Remote filename should be differ from local filename to allow deploy to localhost.
def remote_filename
@remote_filename ||= File.join(remote_dir, "copy-#{File.basename(destination)}.#{compression.extension}")
end
# Local repository path.
def repository_cache
@repository_cache ||= copy_cache || Dir.mktmpdir('cached-copy', copy_dir) { |dir| dir }
end
# Deploy subtree specified as :deploy_subdir in local repository.
def repository_cache_subdir
@repository_cache_subdir ||= if configuration[:deploy_subdir] then
File.join(repository_cache, configuration[:deploy_subdir])
else
repository_cache
end
end
# Remove local repository cache if :copy_cache is not enabled.
def remove_repository_cache?
!copy_cache
end
end
set :strategy, CopySubdir.new(self)
# vim:set ft=ruby :
@yyuu
Copy link
Author

yyuu commented Aug 10, 2012

Created as new gem project.

Also uploaded gem to rubygems.org.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment