forked from capistrano/capistrano
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
git-svn-id: http://svn.rubyonrails.org/rails/tools/capistrano@7695 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
- Loading branch information
Showing
3 changed files
with
305 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
require 'capistrano/recipes/deploy/scm/base' | ||
|
||
module Capistrano | ||
module Deploy | ||
module SCM | ||
|
||
# An SCM module for using Git as your source control tool with Capistrano | ||
# 2.0. If you are using Capistrano 1.x, use this plugin instead: | ||
# | ||
# http://scie.nti.st/2007/3/16/capistrano-with-git-shared-repository | ||
# | ||
# Assumes you are using a shared Git repository. | ||
# | ||
# Parts of this plugin borrowed from Scott Chacon's version, which I | ||
# found on the Capistrano mailing list but failed to be able to get | ||
# working. | ||
# | ||
# FEATURES: | ||
# | ||
# * Very simple, only requiring 2 lines in your deploy.rb. | ||
# * Can deploy different branches, tags, or any SHA1 easily. | ||
# * Supports prompting for password / passphrase upon checkout. | ||
# (I am amazed at how some plugins don't do this) | ||
# * Supports :scm_command, :scm_password, :scm_passphrase Capistrano | ||
# directives. | ||
# | ||
# REQUIREMENTS | ||
# ------------ | ||
# | ||
# Git is required to be installed on your remote machine(s), because a | ||
# clone and checkout is done to get the code up there. This is the way | ||
# I prefer to deploy; there is no alternative to this, so :deploy_via | ||
# is ignored. | ||
# | ||
# CONFIGURATION | ||
# ------------- | ||
# | ||
# Use this plugin by adding the following line in your config/deploy.rb: | ||
# | ||
# set :scm, :git | ||
# | ||
# Set <tt>:repository</tt> to the path of your Git repo: | ||
# | ||
# set :repository, "someuser@somehost:/home/myproject" | ||
# | ||
# The above two options are required to be set, the ones below are | ||
# optional. | ||
# | ||
# You may set <tt>:branch</tt>, which is the reference to the branch, tag, | ||
# or any SHA1 you are deploying, for example: | ||
# | ||
# set :branch, "origin/master" | ||
# | ||
# Otherwise, HEAD is assumed. I strongly suggest you set this. HEAD is | ||
# not always the best assumption. | ||
# | ||
# The <tt>:scm_command</tt> configuration variable, if specified, will | ||
# be used as the full path to the git executable on the *remote* machine: | ||
# | ||
# set :scm_command, "/opt/local/bin/git" | ||
# | ||
# For compatibility with deploy scripts that may have used the 1.x | ||
# version of this plugin before upgrading, <tt>:git</tt> is still | ||
# recognized as an alias for :scm_command. | ||
# | ||
# Set <tt>:scm_password</tt> to the password needed to clone your repo | ||
# if you don't have password-less (public key) entry: | ||
# | ||
# set :scm_password, "my_secret' | ||
# | ||
# Otherwise, you will be prompted for a password. | ||
# | ||
# <tt>:scm_passphrase</tt> is also supported. | ||
# | ||
# The remote cache strategy is also supported. | ||
# | ||
# set :repository_cache, "git_master" | ||
# set :deploy_via, :remote_cache | ||
# | ||
# For faster clone, you can also use shallow cloning. This will set the | ||
# '--depth' flag using the depth specified. This *cannot* be used | ||
# together with the :remote_cache strategy | ||
# | ||
# set :git_shallow_clone, 1 | ||
# | ||
# AUTHORS | ||
# ------- | ||
# | ||
# Garry Dolley http://scie.nti.st | ||
# Contributions by Geoffrey Grosenbach http://topfunky.com | ||
# and Scott Chacon http://jointheconversation.org | ||
|
||
class Git < Base | ||
# Sets the default command name for this SCM on your *local* machine. | ||
# Users may override this by setting the :scm_command variable. | ||
default_command "git" | ||
|
||
# When referencing "head", use the branch we want to deploy or, by | ||
# default, Git's reference of HEAD (the latest changeset in the default | ||
# branch, usually called "master"). | ||
def head | ||
configuration[:branch] || 'HEAD' | ||
end | ||
|
||
# Performs a clone on the remote machine, then checkout on the branch | ||
# you want to deploy. | ||
def checkout(revision, destination) | ||
git = command | ||
|
||
branch = head | ||
|
||
fail "No branch specified, use for example 'set :branch, \"origin/master\"' in your deploy.rb" unless branch | ||
|
||
if depth = configuration[:git_shallow_clone] | ||
execute = "#{git} clone --depth #{depth} #{configuration[:repository]} #{destination} && " | ||
else | ||
execute = "#{git} clone #{configuration[:repository]} #{destination} && " | ||
end | ||
|
||
execute += "cd #{destination} && #{git} checkout -b deploy #{branch}" | ||
|
||
execute | ||
end | ||
|
||
# Merges the changes to 'head' since the last fetch, for remote_cache | ||
# deployment strategy | ||
def sync(revision, destination) | ||
execute = "cd #{destination} && git fetch origin && " | ||
|
||
if head == 'HEAD' | ||
execute += "git merge origin/HEAD" | ||
else | ||
execute += "git merge #{head}" | ||
end | ||
|
||
execute | ||
end | ||
|
||
# Returns a string of diffs between two revisions | ||
def diff(from, to=nil) | ||
from << "..#{to}" if to | ||
scm :diff, from | ||
end | ||
|
||
# Returns a log of changes between the two revisions (inclusive). | ||
def log(from, to=nil) | ||
from << "..#{to}" if to | ||
scm :log, from | ||
end | ||
|
||
# Getting the actual commit id, in case we were passed a tag | ||
# or partial sha or something - it will return the sha if you pass a sha, too | ||
def query_revision(revision) | ||
yield(scm('rev-parse', revision)).chomp | ||
end | ||
|
||
def command | ||
# For backwards compatibility with 1.x version of this module | ||
configuration[:git] || super | ||
end | ||
|
||
# Determines what the response should be for a particular bit of text | ||
# from the SCM. Password prompts, connection requests, passphrases, | ||
# etc. are handled here. | ||
def handle_data(state, stream, text) | ||
logger.info "[#{stream}] #{text}" | ||
case text | ||
when /\bpassword.*:/i | ||
# git is prompting for a password | ||
unless pass = configuration[:scm_password] | ||
pass = Capistrano::CLI.password_prompt | ||
end | ||
"#{pass}\n" | ||
when %r{\(yes/no\)} | ||
# git is asking whether or not to connect | ||
"yes\n" | ||
when /passphrase/i | ||
# git is asking for the passphrase for the user's key | ||
unless pass = configuration[:scm_passphrase] | ||
pass = Capistrano::CLI.password_prompt | ||
end | ||
"#{pass}\n" | ||
when /accept \(t\)emporarily/ | ||
# git is asking whether to accept the certificate | ||
"t\n" | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
require "#{File.dirname(__FILE__)}/../../utils" | ||
require 'capistrano/recipes/deploy/scm/git' | ||
|
||
class DeploySCMGitTest < Test::Unit::TestCase | ||
class TestSCM < Capistrano::Deploy::SCM::Git | ||
default_command "git" | ||
end | ||
|
||
def setup | ||
@config = { } | ||
def @config.exists?(name); key?(name); end | ||
|
||
@source = TestSCM.new(@config) | ||
end | ||
|
||
def test_head | ||
assert_equal "HEAD", @source.head | ||
@config[:branch] = "master" | ||
assert_equal "master", @source.head | ||
end | ||
|
||
def test_checkout | ||
@config[:repository] = "git@somehost.com:project.git" | ||
dest = "/var/www" | ||
assert_equal "git clone git@somehost.com:project.git /var/www && cd /var/www && git checkout -b deploy HEAD", @source.checkout('Not used', dest) | ||
|
||
# With branch | ||
@config[:branch] = "origin/foo" | ||
assert_equal "git clone git@somehost.com:project.git /var/www && cd /var/www && git checkout -b deploy origin/foo", @source.checkout('Not used', dest) | ||
end | ||
|
||
def test_diff | ||
assert_equal "git diff master", @source.diff('master') | ||
assert_equal "git diff master..branch", @source.diff('master', 'branch') | ||
end | ||
|
||
def test_log | ||
assert_equal "git log master", @source.log('master') | ||
assert_equal "git log master..branch", @source.log('master', 'branch') | ||
end | ||
|
||
def test_query_revision | ||
assert_equal "git rev-parse HEAD", @source.query_revision('HEAD') { |o| o } | ||
end | ||
|
||
def test_command_should_be_backwards_compatible | ||
# 1.x version of this module used ":git", not ":scm_command" | ||
@config[:git] = "/srv/bin/git" | ||
assert_equal "/srv/bin/git", @source.command | ||
end | ||
|
||
def test_sync | ||
dest = "/var/www" | ||
assert_equal "cd #{dest} && git fetch origin && git merge origin/HEAD", @source.sync('Not used', dest) | ||
|
||
# With branch | ||
@config[:branch] = "origin/foo" | ||
assert_equal "cd #{dest} && git fetch origin && git merge origin/foo", @source.sync('Not used', dest) | ||
end | ||
|
||
def test_shallow_clone | ||
@config[:repository] = "git@somehost.com:project.git" | ||
@config[:git_shallow_clone] = 1 | ||
dest = "/var/www" | ||
assert_equal "git clone --depth 1 git@somehost.com:project.git /var/www && cd /var/www && git checkout -b deploy HEAD", @source.checkout('Not used', dest) | ||
|
||
# With branch | ||
@config[:branch] = "origin/foo" | ||
assert_equal "git clone --depth 1 git@somehost.com:project.git /var/www && cd /var/www && git checkout -b deploy origin/foo", @source.checkout('Not used', dest) | ||
end | ||
|
||
# Tests from base_test.rb, makin' sure we didn't break anything up there! | ||
def test_command_should_default_to_default_command | ||
assert_equal "git", @source.command | ||
@source.local { assert_equal "git", @source.command } | ||
end | ||
|
||
def test_command_should_use_scm_command_if_available | ||
@config[:scm_command] = "/opt/local/bin/git" | ||
assert_equal "/opt/local/bin/git", @source.command | ||
end | ||
|
||
def test_command_should_use_scm_command_in_local_mode_if_local_scm_command_not_set | ||
@config[:scm_command] = "/opt/local/bin/git" | ||
@source.local { assert_equal "/opt/local/bin/git", @source.command } | ||
end | ||
|
||
def test_command_should_use_local_scm_command_in_local_mode_if_local_scm_command_is_set | ||
@config[:scm_command] = "/opt/local/bin/git" | ||
@config[:local_scm_command] = "/usr/local/bin/git" | ||
assert_equal "/opt/local/bin/git", @source.command | ||
@source.local { assert_equal "/usr/local/bin/git", @source.command } | ||
end | ||
|
||
def test_command_should_use_default_if_scm_command_is_default | ||
@config[:scm_command] = :default | ||
assert_equal "git", @source.command | ||
end | ||
|
||
def test_command_should_use_default_in_local_mode_if_local_scm_command_is_default | ||
@config[:scm_command] = "/foo/bar/git" | ||
@config[:local_scm_command] = :default | ||
@source.local { assert_equal "git", @source.command } | ||
end | ||
|
||
def test_local_mode_proxy_should_treat_messages_as_being_in_local_mode | ||
@config[:scm_command] = "/foo/bar/git" | ||
@config[:local_scm_command] = :default | ||
assert_equal "git", @source.local.command | ||
assert_equal "/foo/bar/git", @source.command | ||
end | ||
end |