Created
September 29, 2010 19:55
-
-
Save randy-girard/603424 to your computer and use it in GitHub Desktop.
New Capistrano CVS Deploy Recipe
This file contains hidden or 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
| # My new_cvs.rb file. Just drop it into capistrano/recipes/deploy/scm/ | |
| # Adds these variables: | |
| # set :scm, :new_cvs | |
| # set :branch, "some_branch_name" | |
| # set :cvs_rsh, "ssh" | |
| # | |
| # Author: Randy Girard | |
| # Website: http://www.freezzo.com | |
| require 'capistrano/recipes/deploy/scm/base' | |
| module Capistrano | |
| module Deploy | |
| module SCM | |
| # Implements the Capistrano SCM interface for the CVS revision | |
| # control system. | |
| class NewCvs < Base | |
| # Sets the default command name for this SCM. Users may override this | |
| # by setting the :scm_command variable. | |
| default_command "cvs" | |
| # CVS understands 'HEAD' to refer to the latest revision in the | |
| # repository. | |
| def head | |
| "HEAD" | |
| end | |
| # Grabs the branch variable from the deploy file. | |
| def branch | |
| variable(:branch) || nil | |
| end | |
| # Returns the command that will check out the given revision to the | |
| # given destination. | |
| def checkout(revision, destination) | |
| [ prep_destination(destination), | |
| scm(verbose, cvs_root, :checkout, cvs_revision(revision), cvs_destination(destination), variable(:scm_module)) | |
| ].join(' && ') | |
| end | |
| # Returns the command that will do an "cvs update" to the given | |
| # revision, for the working copy at the given destination. | |
| def sync(revision, destination) | |
| [ prep_destination(destination), | |
| scm(verbose, cvs_root, :update, cvs_revision(revision), cvs_destination(destination)) | |
| ].join(' && ') | |
| end | |
| # Returns the command that will do an "cvs export" of the given revision | |
| # to the given destination. | |
| def export(revision, destination) | |
| [ prep_destination(destination), | |
| scm(verbose, cvs_root, :export, cvs_revision(revision), cvs_destination(destination), variable(:scm_module)) | |
| ].join(' && ') | |
| end | |
| # Returns the command that will do an "cvs diff" for the two revisions. | |
| def diff(from, to=nil) | |
| rev_type = revision_type(from) | |
| if rev_type == :date | |
| range_args = "-D '#{from}' -D '#{to || 'now'}'" | |
| else | |
| range_args = "-r '#{from}' -r '#{to || head}'" | |
| end | |
| scm cvs_root, :diff, range_args | |
| end | |
| # Returns an "cvs log" command for the two revisions. | |
| def log(from, to=nil) | |
| rev_type = revision_type(from) | |
| if rev_type == :date | |
| range_arg = "-d '#{from}<#{to || 'now'}'" | |
| else | |
| range_arg = "-r '#{from}:#{to || head}'" | |
| end | |
| scm cvs_root, :log, range_arg | |
| end | |
| # Unfortunately, cvs doesn't support the concept of a revision number like | |
| # subversion and other SCM's do. For now, we'll rely on getting the timestamp | |
| # of the latest checkin under the revision that's passed to us. | |
| def query_revision(revision) | |
| # If a branch is set, return that as the revision | |
| return branch if revision_type(branch) == :tag | |
| return revision if revision_type(revision) == :date | |
| revision = yield(scm(cvs_root, :log, "-r#{revision}")). | |
| grep(/^date:/). | |
| map { |line| line[/^date: (.*?);/, 1] }. | |
| sort.last + " UTC" | |
| # This converts the revision date from YYYY-MM-DD to YYYY/MM/DD so the rest | |
| # of this module can handle it. | |
| if revision =~ /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2}).*UTC/ | |
| revision = "#{$1}/#{$2}/#{$3} #{$4}:#{$5}:#{$6} UTC" | |
| puts "Override revision to #{revision}" | |
| end | |
| return revision | |
| 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 | |
| # prompting for a password | |
| "#{variable(:scm_password) || variable(:password)}\n" | |
| when %r{\(yes/no\)} | |
| # let's be agreeable... | |
| "yes\n" | |
| end | |
| end | |
| private | |
| # Constructs the CVSROOT command-line option | |
| def cvs_root | |
| root = "" | |
| root << "-d #{repository} " if repository | |
| root | |
| end | |
| # Constructs the destination dir command-line option | |
| def cvs_destination(destination) | |
| dest = "" | |
| if destination | |
| dest_parts = destination.split(/\//); | |
| dest << "-d #{dest_parts.pop}" | |
| end | |
| dest | |
| end | |
| # attempts to guess what type of revision we're working with | |
| def revision_type(rev) | |
| return :date if rev =~ /^\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2} UTC$/ # i.e 2007-05-15 08:13:25 UTC | |
| return :date if rev =~ /^\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}$/ # i.e 2007-05-15 08:13:25 | |
| return :revision if rev =~ /^\d/ # i.e. 1.2.1 | |
| return :tag # i.e. RELEASE_1_2 | |
| end | |
| # constructs the appropriate command-line switch for specifying a | |
| # "revision" in CVS. This could be a tag, branch, revision (i.e. 1.3) | |
| # or a date (to be used with -d) | |
| def cvs_revision(rev) | |
| revision = "" | |
| revision << case revision_type(rev) | |
| when :date | |
| "-D \"#{rev}\"" if revision_type(rev) == :date | |
| when :revision | |
| "-r #{rev}" | |
| # Added this for branch support | |
| when :tag | |
| "-r #{rev}" | |
| else | |
| "-r #{head}" | |
| end | |
| return revision | |
| end | |
| # If verbose output is requested, return nil, otherwise return the | |
| # command-line switch for "quiet" ("-Q"). | |
| def verbose | |
| variable(:scm_verbose) ? nil : "-Q" | |
| end | |
| def prep_destination(destination) | |
| dest_parts = destination.split(/\//); | |
| checkout_dir = dest_parts.pop | |
| dest = dest_parts.join('/') | |
| out = [] | |
| # In my particular setup, I need this setup on the remote host. | |
| out << "export CVS_RSH=#{variable(:cvs_rsh)}" if variable(:cvs_rsh) | |
| out << "mkdir -p #{ dest } && cd #{ dest }" | |
| out.join(" && ") | |
| end | |
| end | |
| end | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment