After having read about "SwitchTower":http://manuals.rubyonrails.com/read/book/17, I decided to give it a try. SwitchTower is a tool to ease the deployment of your "Ruby on Rails":http://www.rubyonrails.com/ application. I immediatly liked SwitchTower concepts, but there was a big problem, it had no support for "Bazaar-NG":http://www.bazaar-ng.org/ which I use for revision control of my apps.

So I dived into the code and here is the result.

It Works For Me^TM^ drop this file to the scm directory of your SwitchTower installation.

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

require 'switchtower/scm/base'

module SwitchTower
  module SCM

    # An SCM module for using subversion as your source control tool. This
    # module is used by default, but you can explicitly specify it by
    # placing the following line in your configuration:
    #
    #   set :scm, :bzr
    #
    # Also, this module accepts a <tt>:bzr</tt> configuration variable,
    # which (if specified) will be used as the full path to the svn
    # executable on the remote machine:
    #
    #   set :bzr, "/opt/local/bin/bzr"
    class Bzr < Base
      # Return an integer identifying the last known revision in the bzr
      # repository. (This integer is currently the revision number.) 
      def latest_revision
        `#{bzr} revno #{configuration.repository}`.to_i
      end

      # Return the number of the revision currently deployed.
      def current_revision(actor)
        command = "#{bzr} revno #{actor.release_path} &&"        
        run_update(actor, command, &bzr_stream_handler(actor)) 
      end

      # Return a string containing the diff between the two revisions. +from+
      # and +to+ may be in any format that bzr recognizes as a valid revision
      # identifier. If +from+ is +nil+, it defaults to the last deployed
      # revision. If +to+ is +nil+, it defaults to the last developed revision.
      # Pay attention to the fact that as of now bzr does NOT support
      # diff on remote locations.
      def diff(actor, from=nil, to=nil)
        from ||= current_revision(actor)
        to ||= ""
        `#{bzr} diff -r #{from}..#{to} #{configuration.repository}`
      end

      # Check out (on all servers associated with the current task) the latest
      # revision. Uses the given actor instance to execute the command. If
      # bzr asks for a password this will automatically provide it (assuming
      # the requested password is the same as the password for logging into the
      # remote server.)
      def checkout(actor)
        op = configuration[:checkout] || "branch"
        command = "#{bzr} #{op} -r#{configuration.revision} #{configuration.repository} #{actor.release_path} &&"
        run_checkout(actor, command, &bzr_stream_handler(actor)) 
      end

      def update(actor)
        command = "cd #{actor.current_path} && #{bzr} pull -q &&"
        run_update(actor, command, &bzr_stream_handler(actor)) 
      end
      
      private
        def bzr
          configuration[:bzr] || "bzr"
        end

        def bzr_stream_handler(actor)
          Proc.new do |ch, stream, out|
            prefix = "#{stream} :: #{ch[:host]}"
            actor.logger.info out, prefix
          end
        end
    end
  end
end