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.
CONFIGURATION
Use this plugin by adding the following line in your config/deploy.rb:
set :scm, :git
Set :repository 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 :branch, which is the reference to the branch, tag, or any SHA1 you are deploying, for example:
set :branch, "master"
Otherwise, HEAD is assumed. I strongly suggest you set this. HEAD is not always the best assumption.
You may also set :remote, which will be used as a name for remote tracking of repositories. This option is intended for use with the :remote_cache strategy in a distributed git environment.
For example in the projects config/deploy.rb:
set :repository, "#{scm_user}@somehost:~/projects/project.git" set :remote, "#{scm_user}"
Then each person with deploy priveledges can add the following to their local ~/.caprc file:
set :scm_user, 'someuser'
Now any time a person deploys the project, their repository will be setup as a remote git repository within the cached repository.
The :scm_command 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, :git is still recognized as an alias for :scm_command.
Set :scm_password 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.
:scm_passphrase 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
For those that don’t like to leave your entire repository on your production server you can:
set :deploy_via, :export
To deploy from a local repository:
set :repository, "file://." set :deploy_via, :copy
AUTHORS
Garry Dolley scie.nti.st Contributions by Geoffrey Grosenbach topfunky.com
Scott Chacon http://jointheconversation.org Alex Arnell http://twologic.com and Phillip Goldenburg
Performs a clone on the remote machine, then checkout on the branch you want to deploy.
# File lib/capistrano/recipes/deploy/scm/git.rb, line 132 132: def checkout(revision, destination) 133: git = command 134: remote = origin 135: 136: args = [] 137: args << "-o #{remote}" unless remote == 'origin' 138: if depth = variable(:git_shallow_clone) 139: args << "--depth #{depth}" 140: end 141: 142: execute = [] 143: execute << "#{git} clone #{verbose} #{args.join(' ')} #{variable(:repository)} #{destination}" 144: 145: # checkout into a local branch rather than a detached HEAD 146: execute << "cd #{destination} && #{git} checkout #{verbose} -b deploy #{revision}" 147: 148: if variable(:git_enable_submodules) 149: execute << "#{git} submodule #{verbose} init" 150: execute << "#{git} submodule #{verbose} sync" 151: if false == variable(:git_submodules_recursive) 152: execute << "#{git} submodule #{verbose} update --init" 153: else 154: execute << %(export GIT_RECURSIVE=$([ ! "`#{git} --version`" \\< "git version 1.6.5" ] && echo --recursive)) 155: execute << "#{git} submodule #{verbose} update --init $GIT_RECURSIVE" 156: end 157: end 158: 159: execute.compact.join(" && ").gsub(/\s+/, ' ') 160: end
# File lib/capistrano/recipes/deploy/scm/git.rb, line 247 247: def command 248: # For backwards compatibility with 1.x version of this module 249: variable(:git) || super 250: end
Returns a string of diffs between two revisions
# File lib/capistrano/recipes/deploy/scm/git.rb, line 211 211: def diff(from, to=nil) 212: return scm :diff, from unless to 213: scm :diff, "#{from}..#{to}" 214: end
An expensive export. Performs a checkout as above, then removes the repo.
# File lib/capistrano/recipes/deploy/scm/git.rb, line 164 164: def export(revision, destination) 165: checkout(revision, destination) << " && rm -Rf #{destination}/.git" 166: 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.
# File lib/capistrano/recipes/deploy/scm/git.rb, line 255 255: def handle_data(state, stream, text) 256: host = state[:channel][:host] 257: logger.info "[#{host} :: #{stream}] #{text}" 258: case text 259: when /\bpassword.*:/ 260: # git is prompting for a password 261: unless pass = variable(:scm_password) 262: pass = Capistrano::CLI.password_prompt 263: end 264: "#{pass}\n" 265: when %{\(yes/no\)} 266: # git is asking whether or not to connect 267: "yes\n" 268: when /passphrase/ 269: # git is asking for the passphrase for the user's key 270: unless pass = variable(:scm_passphrase) 271: pass = Capistrano::CLI.password_prompt 272: end 273: "#{pass}\n" 274: when /accept \(t\)emporarily/ 275: # git is asking whether to accept the certificate 276: "t\n" 277: end 278: end
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”).
# File lib/capistrano/recipes/deploy/scm/git.rb, line 122 122: def head 123: variable(:branch) || 'HEAD' 124: end
Returns a log of changes between the two revisions (inclusive).
# File lib/capistrano/recipes/deploy/scm/git.rb, line 217 217: def log(from, to=nil) 218: scm :log, "#{from}..#{to}" 219: end
# File lib/capistrano/recipes/deploy/scm/git.rb, line 126 126: def origin 127: variable(:remote) || 'origin' 128: 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
# File lib/capistrano/recipes/deploy/scm/git.rb, line 223 223: def query_revision(revision) 224: raise ArgumentError, "Deploying remote branches is no longer supported. Specify the remote branch as a local branch for the git repository you're deploying from (ie: '#{revision.gsub('origin/', '')}' rather than '#{revision}')." if revision =~ /^origin\// 225: return revision if revision =~ /^[0-9a-f]{40}$/ 226: command = scm('ls-remote', repository, revision) 227: result = yield(command) 228: revdata = result.split(/[\t\n]/) 229: newrev = nil 230: revdata.each_slice(2) do |refs| 231: rev, ref = *refs 232: if ref.sub(/refs\/.*?\//, '').strip == revision.to_s 233: newrev = rev 234: break 235: end 236: end 237: return newrev if newrev =~ /^[0-9a-f]{40}$/ 238: 239: # If sha is not found on remote, try expanding from local repository 240: command = scm('rev-parse --revs-only', revision) 241: newrev = yield(command).to_s.strip 242: 243: raise "Unable to resolve revision for '#{revision}' on repository '#{repository}'." unless newrev =~ /^[0-9a-f]{40}$/ 244: return newrev 245: end
Merges the changes to ‘head’ since the last fetch, for remote_cache deployment strategy
# File lib/capistrano/recipes/deploy/scm/git.rb, line 170 170: def sync(revision, destination) 171: git = command 172: remote = origin 173: 174: execute = [] 175: execute << "cd #{destination}" 176: 177: # Use git-config to setup a remote tracking branches. Could use 178: # git-remote but it complains when a remote of the same name already 179: # exists, git-config will just silenty overwrite the setting every 180: # time. This could cause wierd-ness in the remote cache if the url 181: # changes between calls, but as long as the repositories are all 182: # based from each other it should still work fine. 183: if remote != 'origin' 184: execute << "#{git} config remote.#{remote}.url #{variable(:repository)}" 185: execute << "#{git} config remote.#{remote}.fetch +refs/heads/*:refs/remotes/#{remote}/*" 186: end 187: 188: # since we're in a local branch already, just reset to specified revision rather than merge 189: execute << "#{git} fetch #{verbose} #{remote} && #{git} fetch --tags #{verbose} #{remote} && #{git} reset #{verbose} --hard #{revision}" 190: 191: if variable(:git_enable_submodules) 192: execute << "#{git} submodule #{verbose} init" 193: execute << "for mod in `#{git} submodule status | awk '{ print $2 }'`; do #{git} config -f .git/config submodule.${mod}.url `#{git} config -f .gitmodules --get submodule.${mod}.url` && echo Synced $mod; done" 194: execute << "#{git} submodule #{verbose} sync" 195: if false == variable(:git_submodules_recursive) 196: execute << "#{git} submodule #{verbose} update --init" 197: else 198: execute << %(export GIT_RECURSIVE=$([ ! "`#{git} --version`" \\< "git version 1.6.5" ] && echo --recursive)) 199: execute << "#{git} submodule #{verbose} update --init $GIT_RECURSIVE" 200: end 201: end 202: 203: # Make sure there's nothing else lying around in the repository (for 204: # example, a submodule that has subsequently been removed). 205: execute << "#{git} clean #{verbose} -d -x -f" 206: 207: execute.join(" && ") 208: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.