01094b199206dec6578c17c2142fd895b88f3aec
[puppet_vcsrepo.git] / lib / puppet / provider / vcsrepo / cvs.rb
1 require File.join(File.dirname(__FILE__), '..', 'vcsrepo')
2
3 Puppet::Type.type(:vcsrepo).provide(:cvs, :parent => Puppet::Provider::Vcsrepo) do
4   desc "Supports CVS repositories/workspaces"
5
6   commands :cvs => 'cvs'
7   has_features :gzip_compression, :reference_tracking, :modules, :cvs_rsh
8
9   def create
10     if !@resource.value(:source)
11       create_repository(@resource.value(:path))
12     else
13       checkout_repository
14     end
15     update_owner
16   end
17
18   def exists?
19     if @resource.value(:source)
20       directory = File.join(@resource.value(:path), 'CVS')
21     else
22       directory = File.join(@resource.value(:path), 'CVSROOT')
23     end
24     File.directory?(directory)
25   end
26
27   def working_copy_exists?
28     File.directory?(File.join(@resource.value(:path), 'CVS'))
29   end
30
31   def destroy
32     FileUtils.rm_rf(@resource.value(:path))
33   end
34
35   def latest?
36     debug "Checking for updates because 'ensure => latest'"
37     at_path do
38       # We cannot use -P to prune empty dirs, otherwise
39       # CVS would report those as "missing", regardless
40       # if they have contents or updates.
41       is_current = (runcvs('-nq', 'update', '-d').strip == "")
42       if (!is_current) then debug "There are updates available on the checkout's current branch/tag." end
43       return is_current
44     end
45   end
46
47   def latest
48     # CVS does not have a conecpt like commit-IDs or change
49     # sets, so we can only have the current branch name (or the
50     # requested one, if that differs) as the "latest" revision.
51     should = @resource.value(:revision)
52     current = self.revision
53     return should != current ? should : current
54   end
55
56   def revision
57     if !@rev
58       if File.exist?(tag_file)
59         contents = File.read(tag_file).strip
60         # Note: Doesn't differentiate between N and T entries
61         @rev = contents[1..-1]
62       else
63         @rev = 'HEAD'
64       end
65       debug "Checkout is on branch/tag '#{@rev}'"
66     end
67     return @rev
68   end
69
70   def revision=(desired)
71     at_path do
72       runcvs('update', '-dr', desired, '.')
73       update_owner
74       @rev = desired
75     end
76   end
77
78   private
79
80   def tag_file
81     File.join(@resource.value(:path), 'CVS', 'Tag')
82   end
83
84   def checkout_repository
85     dirname, basename = File.split(@resource.value(:path))
86     Dir.chdir(dirname) do
87       args = ['-d', @resource.value(:source)]
88       if @resource.value(:compression)
89         args.push('-z', @resource.value(:compression))
90       end
91       args.push('checkout')
92       if @resource.value(:revision)
93         args.push('-r', @resource.value(:revision))
94       end
95       args.push('-d', basename, module_name)
96       runcvs(*args)
97     end
98   end
99
100   # When the source:
101   # * Starts with ':' (eg, :pserver:...)
102   def module_name
103     if (m = @resource.value(:module))
104       m
105     elsif (source = @resource.value(:source))
106       source[0, 1] == ':' ? File.basename(source) : '.'
107     end
108   end
109
110   def create_repository(path)
111     runcvs('-d', path, 'init')
112   end
113
114   def update_owner
115     if @resource.value(:owner) or @resource.value(:group)
116       set_ownership
117     end
118   end
119
120   def runcvs(*args)
121     if @resource.value(:cvs_rsh)
122       debug "Using CVS_RSH = " + @resource.value(:cvs_rsh)
123       e = { :CVS_RSH => @resource.value(:cvs_rsh) }
124     else
125       e = {}
126     end
127
128     # The location of withenv changed from Puppet 2.x to 3.x
129     withenv = Puppet::Util.method(:withenv) if Puppet::Util.respond_to?(:withenv)
130     withenv = Puppet::Util::Execution.method(:withenv) if Puppet::Util::Execution.respond_to?(:withenv)
131     fail("Cannot set custom environment #{e}") if e && !withenv
132
133     withenv.call e do
134       Puppet.debug cvs *args
135     end
136   end
137 end