public
Description: Remote multi-server automation tool. This repository is no longer being actively maintained. Please ask on the mailing list to find someone who has a well-maintained fork. Thanks!
Homepage: http://www.capify.org
Clone URL: git://github.com/jamis/capistrano.git
capistrano / lib / capistrano / recipes / deploy / scm / mercurial.rb
100644 137 lines (119 sloc) 4.755 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# Copyright 2007 Matthew Elder <sseses@gmail.com>
# based on work by Tobias Luetke
 
require 'capistrano/recipes/deploy/scm/base'
 
module Capistrano
  module Deploy
    module SCM
 
      # Implements the Capistrano SCM interface for the Mercurial revision
      # control system (http://www.selenic.com/mercurial/).
      # Latest updates at http://tackletechnology.org/oss/cap2-mercurial
      class Mercurial < Base
        # Sets the default command name for this SCM. Users may override this
        # by setting the :scm_command variable.
        default_command "hg"
 
        # For mercurial HEAD == tip except that it bases this assumption on what
        # tip is in the current repository (so push before you deploy)
        def head
          "tip"
        end
 
        # Clone the repository and update to the specified changeset.
        def checkout(changeset, destination)
          clone(destination) + " && " + update(changeset, destination)
        end
 
        # Pull from the repository and update to the specified changeset.
        def sync(changeset, destination)
          pull(destination) + " && " + update(changeset, destination)
        end
 
        # One day we will have hg archive, although i think its not needed
        def export(revision, destination)
          raise NotImplementedError, "`diff' is not implemented by #{self.class.name}" +
          "use checkout strategy"
        end
 
        # Compute the difference between the two changesets +from+ and +to+
        # as a unified diff.
        def diff(from, to=nil)
          scm :diff,
              "--rev #{from}",
              (to ? "--rev #{to}" : nil)
        end
 
        # Return a log of all changes between the two specified changesets,
        # +from+ and +to+, inclusive or the log for +from+ if +to+ is omitted.
        def log(from, to=nil)
          scm :log,
              verbose,
              "--rev #{from}" +
              (to ? ":#{to}" : "")
        end
 
        # Translates a tag to a changeset if needed or just returns changeset.
        def query_revision(changeset)
          cmd = scm :log,
                    verbose,
                    "-r #{changeset}",
                    "--template '{node|short}'"
                    yield cmd
        end
 
        # Determine response for SCM prompts
        # user/pass can come from ssh and http distribution methods
        # yes/no is for when ssh asks you about fingerprints
        def handle_data(state, stream, text)
          host = state[:channel][:host]
          logger.info "[#{host} :: #{stream}] #{text}"
          case text
          when /^user:/mi
            # support :scm_user for backwards compatibility of this module
            if user = variable(:scm_username) || variable(:scm_user)
              "#{user}\n"
            else
              raise "No variable :scm_username specified and Mercurial asked!\n" +
                "Prompt was: #{text}"
            end
          when /\bpassword:/mi
            unless pass = scm_password_or_prompt
              # fall back on old behavior of erroring out with msg
              raise "No variable :scm_password specified and Mercurial asked!\n" +
                "Prompt was: #{text}"
            end
            "#{pass}\n"
          when /yes\/no/i
            "yes\n"
          end
        end
        
        private
 
        # Fine grained mercurial commands
        def clone(destination)
          scm :clone,
              verbose,
              "--noupdate", # do not update to tip when cloning is done
              repository, # clone which repository?
              destination # and put the clone where?
        end
 
        def pull(destination)
          scm :pull,
              verbose,
              "--repository #{destination}", # pull changes into what?
              repository # and pull the changes from?
        end
 
        def update(changeset, destination)
          scm :update,
              verbose,
              "--repository #{destination}", # update what?
              "--clean", # ignore untracked changes
              changeset # update to this changeset
        end
 
        # verbosity configuration grokking :)
        def verbose
          case variable(:scm_verbose)
            when nil then nil
            when false then "--quiet"
            else "--verbose"
          end
        end
        
        # honor Cap 2.1+'s :scm_prefer_prompt if present
        def scm_password_or_prompt
          @scm_password_or_prompt ||= variable(:scm_password) ||
            (Capistrano::CLI.password_prompt("hg password: ") if variable(:scm_prefer_prompt))
        end
 
      end
    end
  end
end