| | 1 | require 'capistrano/recipes/deploy/scm/base' |
|---|
| | 2 | |
|---|
| | 3 | module Capistrano |
|---|
| | 4 | module Deploy |
|---|
| | 5 | module SCM |
|---|
| | 6 | |
|---|
| | 7 | # An SCM module for using Git as your source control tool with Capistrano |
|---|
| | 8 | # 2.0. If you are using Capistrano 1.x, use this plugin instead: |
|---|
| | 9 | # |
|---|
| | 10 | # http://scie.nti.st/2007/3/16/capistrano-with-git-shared-repository |
|---|
| | 11 | # |
|---|
| | 12 | # Assumes you are using a shared Git repository. |
|---|
| | 13 | # |
|---|
| | 14 | # Parts of this plugin borrowed from Scott Chacon's version, which I |
|---|
| | 15 | # found on the Capistrano mailing list but failed to be able to get |
|---|
| | 16 | # working. |
|---|
| | 17 | # |
|---|
| | 18 | # FEATURES: |
|---|
| | 19 | # |
|---|
| | 20 | # * Very simple, only requiring 2 lines in your deploy.rb. |
|---|
| | 21 | # * Can deploy different branches, tags, or any SHA1 easily. |
|---|
| | 22 | # * Supports prompting for password / passphrase upon checkout. |
|---|
| | 23 | # (I am amazed at how some plugins don't do this) |
|---|
| | 24 | # * Supports :scm_command, :scm_password, :scm_passphrase Capistrano |
|---|
| | 25 | # directives. |
|---|
| | 26 | # |
|---|
| | 27 | # REQUIREMENTS |
|---|
| | 28 | # ------------ |
|---|
| | 29 | # |
|---|
| | 30 | # Git is required to be installed on your remote machine(s), because a |
|---|
| | 31 | # clone and checkout is done to get the code up there. This is the way |
|---|
| | 32 | # I prefer to deploy; there is no alternative to this, so :deploy_via |
|---|
| | 33 | # is ignored. |
|---|
| | 34 | # |
|---|
| | 35 | # INSTALLATION |
|---|
| | 36 | # ------------ |
|---|
| | 37 | # |
|---|
| | 38 | # Place this file in: |
|---|
| | 39 | # |
|---|
| | 40 | # $GEMPATH/capistrano-2.x.x/lib/capistrano/recipes/deploy/scm/ |
|---|
| | 41 | # |
|---|
| | 42 | # CONFIGURATION |
|---|
| | 43 | # ------------- |
|---|
| | 44 | # |
|---|
| | 45 | # Use this plugin by adding the following line in your config/deploy.rb: |
|---|
| | 46 | # |
|---|
| | 47 | # set :scm, :git |
|---|
| | 48 | # |
|---|
| | 49 | # Set <tt>:repository</tt> to the path of your Git repo: |
|---|
| | 50 | # |
|---|
| | 51 | # set :repository, "someuser@somehost:/home/myproject" |
|---|
| | 52 | # |
|---|
| | 53 | # The above two options are required to be set, the ones below are |
|---|
| | 54 | # optional. |
|---|
| | 55 | # |
|---|
| | 56 | # You may set <tt>:branch</tt>, which is the reference to the branch, tag, |
|---|
| | 57 | # or any SHA1 you are deploying, for example: |
|---|
| | 58 | # |
|---|
| | 59 | # set :branch, "origin/master" |
|---|
| | 60 | # |
|---|
| | 61 | # Otherwise, HEAD is assumed. I strongly suggest you set this. HEAD is |
|---|
| | 62 | # not always the best assumption. |
|---|
| | 63 | # |
|---|
| | 64 | # The <tt>:scm_command</tt> configuration variable, if specified, will |
|---|
| | 65 | # be used as the full path to the git executable on the *remote* machine: |
|---|
| | 66 | # |
|---|
| | 67 | # set :scm_command, "/opt/local/bin/git" |
|---|
| | 68 | # |
|---|
| | 69 | # For compatibility with deploy scripts that may have used the 1.x |
|---|
| | 70 | # version of this plugin before upgrading, <tt>:git</tt> is still |
|---|
| | 71 | # recognized as an alias for :scm_command. |
|---|
| | 72 | # |
|---|
| | 73 | # Set <tt>:scm_password</tt> to the password needed to clone your repo |
|---|
| | 74 | # if you don't have password-less (public key) entry: |
|---|
| | 75 | # |
|---|
| | 76 | # set :scm_password, "my_secret' |
|---|
| | 77 | # |
|---|
| | 78 | # Otherwise, you will be prompted for a password. |
|---|
| | 79 | # |
|---|
| | 80 | # <tt>:scm_passphrase</tt> is also supported. |
|---|
| | 81 | # |
|---|
| | 82 | # The remote cache strategy is also supported. |
|---|
| | 83 | # |
|---|
| | 84 | # set :repository_cache, "git_master" |
|---|
| | 85 | # set :deploy_via, :remote_cache |
|---|
| | 86 | # |
|---|
| | 87 | # For faster clone, you can also use shallow cloning. This will set the |
|---|
| | 88 | # '--depth' flag using the depth specified. This *cannot* be used |
|---|
| | 89 | # together with the :remote_cache strategy |
|---|
| | 90 | # |
|---|
| | 91 | # set :git_shallow_clone, 1 |
|---|
| | 92 | # |
|---|
| | 93 | # AUTHORS |
|---|
| | 94 | # ------- |
|---|
| | 95 | # |
|---|
| | 96 | # Garry Dolley http://scie.nti.st |
|---|
| | 97 | # Contributions by Geoffrey Grosenbach http://topfunky.com |
|---|
| | 98 | # and Scott Chacon http://jointheconversation.org |
|---|
| | 99 | |
|---|
| | 100 | class Git < Base |
|---|
| | 101 | # Sets the default command name for this SCM on your *local* machine. |
|---|
| | 102 | # Users may override this by setting the :scm_command variable. |
|---|
| | 103 | default_command "git" |
|---|
| | 104 | |
|---|
| | 105 | # When referencing "head", use the branch we want to deploy or, by |
|---|
| | 106 | # default, Git's reference of HEAD (the latest changeset in the default |
|---|
| | 107 | # branch, usually called "master"). |
|---|
| | 108 | def head |
|---|
| | 109 | configuration[:branch] || 'HEAD' |
|---|
| | 110 | end |
|---|
| | 111 | |
|---|
| | 112 | # Performs a clone on the remote machine, then checkout on the branch |
|---|
| | 113 | # you want to deploy. |
|---|
| | 114 | def checkout(revision, destination) |
|---|
| | 115 | git = command |
|---|
| | 116 | |
|---|
| | 117 | branch = head |
|---|
| | 118 | |
|---|
| | 119 | fail "No branch specified, use for example 'set :branch, \"origin/master\"' in your deploy.rb" unless branch |
|---|
| | 120 | |
|---|
| | 121 | if depth = configuration[:git_shallow_clone] |
|---|
| | 122 | execute = "#{git} clone --depth #{depth} #{configuration[:repository]} #{destination} && " |
|---|
| | 123 | else |
|---|
| | 124 | execute = "#{git} clone #{configuration[:repository]} #{destination} && " |
|---|
| | 125 | end |
|---|
| | 126 | |
|---|
| | 127 | execute += "cd #{destination} && #{git} checkout -b deploy #{branch}" |
|---|
| | 128 | |
|---|
| | 129 | execute |
|---|
| | 130 | end |
|---|
| | 131 | |
|---|
| | 132 | # Merges the changes to 'head' since the last fetch, for remote_cache |
|---|
| | 133 | # deployment strategy |
|---|
| | 134 | def sync(revision, destination) |
|---|
| | 135 | execute = "cd #{destination} && git fetch origin && " |
|---|
| | 136 | |
|---|
| | 137 | if head == 'HEAD' |
|---|
| | 138 | execute += "git merge origin/HEAD" |
|---|
| | 139 | else |
|---|
| | 140 | execute += "git merge #{head}" |
|---|
| | 141 | end |
|---|
| | 142 | |
|---|
| | 143 | execute |
|---|
| | 144 | end |
|---|
| | 145 | |
|---|
| | 146 | # Returns a string of diffs between two revisions |
|---|
| | 147 | def diff(from, to=nil) |
|---|
| | 148 | from << "..#{to}" if to |
|---|
| | 149 | scm :diff, from |
|---|
| | 150 | end |
|---|
| | 151 | |
|---|
| | 152 | # Returns a log of changes between the two revisions (inclusive). |
|---|
| | 153 | def log(from, to=nil) |
|---|
| | 154 | from << "..#{to}" if to |
|---|
| | 155 | scm :log, from |
|---|
| | 156 | end |
|---|
| | 157 | |
|---|
| | 158 | # Getting the actual commit id, in case we were passed a tag |
|---|
| | 159 | # or partial sha or something - it will return the sha if you pass a sha, too |
|---|
| | 160 | def query_revision(revision) |
|---|
| | 161 | yield(scm('rev-parse', revision)).chomp |
|---|
| | 162 | end |
|---|
| | 163 | |
|---|
| | 164 | def command |
|---|
| | 165 | # For backwards compatibility with 1.x version of this module |
|---|
| | 166 | configuration[:git] || super |
|---|
| | 167 | end |
|---|
| | 168 | |
|---|
| | 169 | # Determines what the response should be for a particular bit of text |
|---|
| | 170 | # from the SCM. Password prompts, connection requests, passphrases, |
|---|
| | 171 | # etc. are handled here. |
|---|
| | 172 | def handle_data(state, stream, text) |
|---|
| | 173 | logger.info "[#{stream}] #{text}" |
|---|
| | 174 | case text |
|---|
| | 175 | when /\bpassword.*:/i |
|---|
| | 176 | # git is prompting for a password |
|---|
| | 177 | unless pass = configuration[:scm_password] |
|---|
| | 178 | pass = Capistrano::CLI.password_prompt |
|---|
| | 179 | end |
|---|
| | 180 | "#{pass}\n" |
|---|
| | 181 | when %r{\(yes/no\)} |
|---|
| | 182 | # git is asking whether or not to connect |
|---|
| | 183 | "yes\n" |
|---|
| | 184 | when /passphrase/i |
|---|
| | 185 | # git is asking for the passphrase for the user's key |
|---|
| | 186 | unless pass = configuration[:scm_passphrase] |
|---|
| | 187 | pass = Capistrano::CLI.password_prompt |
|---|
| | 188 | end |
|---|
| | 189 | "#{pass}\n" |
|---|
| | 190 | when /accept \(t\)emporarily/ |
|---|
| | 191 | # git is asking whether to accept the certificate |
|---|
| | 192 | "t\n" |
|---|
| | 193 | end |
|---|
| | 194 | end |
|---|
| | 195 | end |
|---|
| | 196 | end |
|---|
| | 197 | end |
|---|
| | 198 | end |