Merge pull request #31 from ghoneycutt/noticket/master/missing_trailing_comma
[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   optional_commands   :cvs => 'cvs'
7   defaultfor :cvs => :exists
8   has_features :gzip_compression, :reference_tracking, :modules
9
10   def create
11     if !@resource.value(:source)
12       create_repository(@resource.value(:path))
13     else
14       checkout_repository
15     end
16     update_owner
17   end
18
19   def exists?
20     if @resource.value(:source)
21       directory = File.join(@resource.value(:path), 'CVS')
22     else
23       directory = File.join(@resource.value(:path), 'CVSROOT')
24     end
25     File.directory?(directory)
26   end
27
28   def working_copy_exists?
29     File.directory?(File.join(@resource.value(:path), 'CVS'))
30   end
31
32   def destroy
33     FileUtils.rm_rf(@resource.value(:path))
34   end
35
36   def latest?
37     debug "Checking for updates because 'ensure => latest'"
38     at_path do
39       # We cannot use -P to prune empty dirs, otherwise
40       # CVS would report those as "missing", regardless
41       # if they have contents or updates.
42       is_current = (cvs('-nq', 'update', '-d').strip == "")
43       if (!is_current) then debug "There are updates available on the checkout's current branch/tag." end
44       return is_current
45     end
46   end
47
48   def latest
49     # CVS does not have a conecpt like commit-IDs or change
50     # sets, so we can only have the current branch name (or the
51     # requested one, if that differs) as the "latest" revision.
52     should = @resource.value(:revision)
53     current = self.revision
54     return should != current ? should : current
55   end
56
57   def revision
58     if !@rev
59       if File.exist?(tag_file)
60         contents = File.read(tag_file).strip
61         # Note: Doesn't differentiate between N and T entries
62         @rev = contents[1..-1]
63       else
64         @rev = 'HEAD'
65       end
66       debug "Checkout is on branch/tag '#{@rev}'"
67     end
68     return @rev
69   end
70
71   def revision=(desired)
72     at_path do
73       cvs('update', '-dr', desired, '.')
74       update_owner
75       @rev = desired
76     end
77   end
78
79   private
80
81   def tag_file
82     File.join(@resource.value(:path), 'CVS', 'Tag')
83   end
84
85   def checkout_repository
86     dirname, basename = File.split(@resource.value(:path))
87     Dir.chdir(dirname) do
88       args = ['-d', @resource.value(:source)]
89       if @resource.value(:compression)
90         args.push('-z', @resource.value(:compression))
91       end
92       args.push('checkout')
93       if @resource.value(:revision)
94         args.push('-r', @resource.value(:revision))
95       end
96       args.push('-d', basename, module_name)
97       cvs(*args)
98     end
99   end
100
101   # When the source:
102   # * Starts with ':' (eg, :pserver:...)
103   def module_name
104     if (m = @resource.value(:module))
105       m
106     elsif (source = @resource.value(:source))
107       source[0, 1] == ':' ? File.basename(source) : '.'
108     end
109   end
110
111   def create_repository(path)
112     cvs('-d', path, 'init')
113   end
114
115   def update_owner
116     if @resource.value(:owner) or @resource.value(:group)
117       set_ownership
118     end
119   end
120 end