Merge pull request #145 from hunner/fix_beaker_tests
[puppet_vcsrepo.git] / lib / puppet / provider / vcsrepo / hg.rb
1 require File.join(File.dirname(__FILE__), '..', 'vcsrepo')
2
3 Puppet::Type.type(:vcsrepo).provide(:hg, :parent => Puppet::Provider::Vcsrepo) do
4   desc "Supports Mercurial repositories"
5
6   commands :hg => 'hg'
7   optional_commands :su => 'su'
8
9   has_features :reference_tracking, :ssh_identity, :user
10
11   def create
12     if !@resource.value(:source)
13       create_repository(@resource.value(:path))
14     else
15       clone_repository(@resource.value(:revision))
16     end
17     update_owner
18   end
19
20   def working_copy_exists?
21     File.directory?(File.join(@resource.value(:path), '.hg'))
22   end
23
24   def exists?
25     working_copy_exists?
26   end
27
28   def destroy
29     FileUtils.rm_rf(@resource.value(:path))
30   end
31
32   def latest?
33     at_path do
34       return self.revision == self.latest
35     end
36   end
37
38   def latest
39     at_path do
40       begin
41         hg_wrapper('incoming', '--branch', '.', '--newest-first', '--limit', '1', { :remote => true })[/^changeset:\s+(?:-?\d+):(\S+)/m, 1]
42       rescue Puppet::ExecutionFailure
43         # If there are no new changesets, return the current nodeid
44         self.revision
45       end
46     end
47   end
48
49   def revision
50     at_path do
51       current = hg_wrapper('parents')[/^changeset:\s+(?:-?\d+):(\S+)/m, 1]
52       desired = @resource.value(:revision)
53       if desired
54         # Return the tag name if it maps to the current nodeid
55         mapped = hg_wrapper('tags')[/^#{Regexp.quote(desired)}\s+\d+:(\S+)/m, 1]
56         if current == mapped
57           desired
58         else
59           current
60         end
61       else
62         current
63       end
64     end
65   end
66
67   def revision=(desired)
68     at_path do
69       begin
70         hg_wrapper('pull', { :remote => true })
71       rescue
72       end
73       begin
74         hg_wrapper('merge')
75       rescue Puppet::ExecutionFailure
76         # If there's nothing to merge, just skip
77       end
78       hg_wrapper('update', '--clean', '-r', desired)
79     end
80     update_owner
81   end
82
83   private
84
85   def create_repository(path)
86     hg_wrapper('init', path)
87   end
88
89   def clone_repository(revision)
90     args = ['clone']
91     if revision
92       args.push('-u', revision)
93     end
94     args.push(@resource.value(:source),
95               @resource.value(:path))
96     args.push({ :remote => true })
97     hg_wrapper(*args)
98   end
99
100   def update_owner
101     if @resource.value(:owner) or @resource.value(:group)
102       set_ownership
103     end
104   end
105
106   def hg_wrapper(*args)
107     options = { :remote => false }
108     if args.length > 0 and args[-1].is_a? Hash
109       options.merge!(args.pop)
110     end
111     if options[:remote] and @resource.value(:identity)
112       args += ["--ssh", "ssh -oStrictHostKeyChecking=no -oPasswordAuthentication=no -oKbdInteractiveAuthentication=no -oChallengeResponseAuthentication=no -i #{@resource.value(:identity)}"]
113     end
114     if @resource.value(:user) and @resource.value(:user) != Facter['id'].value
115       args.map! { |a| if a =~ /\s/ then "'#{a}'" else a end }  # Adds quotes to arguments with whitespaces.
116       su(@resource.value(:user), '-c', "hg #{args.join(' ')}")
117     else
118       hg(*args)
119     end
120   end
121 end