Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #4150: hg.rb

File hg.rb, 3.9 kB (added by nullstyle@gmail.com, 3 years ago)

hg plugin for capistrano

Line 
1 # Please note that this code is heavily derived from the Bzr module for capistrano
2 # written by Damien Merenne.  Cheers and thanks for the help!
3
4 require 'capistrano/scm/base'
5
6 module Capistrano
7   module SCM
8     ID_REGEX =  /([[:xdigit:]]+)\+?\s(\w+\s+)*/
9     SSH_REPO_REGEX = /ssh:\/\/(([[:alnum:]]+)@)?([a-zA-Z.-]+)\/(.+)/
10     # An SCM module for using Mercurial (hg) as your source control tool.
11     # You can use it by placing the following line in your configuration:
12     #
13     #   set :scm, :hg
14     #
15     # Also, this module accepts a <tt>:hg</tt> configuration variable,
16     # which (if specified) will be used as the full path to the hg
17     # executable on the remote machine:
18     #
19     #   set :hg, "/opt/local/bin/hg"
20     #
21     # SSH and Local repositories are supported, although a ssh repositories
22     # require a little finagling to mesh well.  below is a typical repository
23     # line for SSH:
24     #
25     #   set(:repository) { "ssh://#{user}@nullstyle.com/hg/nullstyle.com" }
26     #
27     # that will ensure that the user that attemps the login is correct, whether
28     # the :user variable is changed or not.
29     class Hg < Base
30      
31       def latest_revision
32         case repository_type(configuration.repository)
33         when :local
34           extract_revision `#{hg} -R #{directory} id`
35         when :ssh
36           host, directory = extract_host_and_dir(configuration.repository)
37           extract_revision `ssh #{configuration.user}@#{host} #{hg} -R #{directory} id`
38         end
39       end
40
41       # Return the number of the revision currently deployed.
42       def current_revision(actor)
43         command = "#{hg} -R #{actor.release_path} id &&"       
44         extract_revision run_update(actor, command, &hg_stream_handler(actor))
45       end
46
47       # Check out (on all servers associated with the current task) the latest
48       # revision. Uses the given actor instance to execute the command. If
49       # hg asks for a password this will automatically provide it (assuming
50       # the requested password is the same as the password for logging into the
51       # remote server.)
52       def checkout(actor)
53         op = configuration[:checkout] || "clone"
54         command = "#{hg} -q #{op} #{configuration.repository} #{actor.release_path} && #{hg} -R #{actor.release_path} up #{configuration.revision} && "
55         run_checkout(actor, command, &hg_stream_handler(actor))
56       end
57
58       def update(actor)
59         command = "cd #{actor.current_path} && #{hg} pull -u -q &&"
60         run_update(actor, command, &hg_stream_handler(actor))
61       end
62      
63       private
64         def hg
65           configuration[:hg] || "hg"
66         end
67        
68         def hg_password
69           configuration[:hg_password] || configuration[:password]
70         end
71
72         def hg_stream_handler(actor)
73           Proc.new do |ch, stream, out|
74             prefix = "#{stream} :: #{ch[:host]}"
75             actor.logger.info out, prefix
76            
77             if out =~ /\bpassword.*:/i
78               actor.logger.info "hg is asking for a password", prefix
79               ch.send_data "#{hg_password}\n"
80             elsif out =~ %r{\(yes/no\)}
81               actor.logger.info "hg is asking whether to connect or not",
82                 prefix
83               ch.send_data "yes\n"
84             elsif out =~ %r{passphrase}
85               message = "hg needs your key's passphrase, sending empty string"
86               actor.logger.info message, prefix
87               ch.send_data "\n"
88             end
89        
90           end
91         end
92        
93         def extract_revision(rev_string)
94           ID_REGEX.match(rev_string)[1] 
95         end
96        
97         def extract_host_and_dir(repository)
98           match = SSH_REPO_REGEX.match repository
99           [match[3],match[4]]
100         end
101        
102         def repository_type(repository)
103           if SSH_REPO_REGEX.match repository
104             :ssh
105           else
106             :local
107           end
108         end
109     end
110   end
111 end