summaryrefslogtreecommitdiff
path: root/lib/puppet/provider/vcsrepo/cvs.rb
blob: 01094b199206dec6578c17c2142fd895b88f3aec (plain)
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
require File.join(File.dirname(__FILE__), '..', 'vcsrepo')

Puppet::Type.type(:vcsrepo).provide(:cvs, :parent => Puppet::Provider::Vcsrepo) do
  desc "Supports CVS repositories/workspaces"

  commands :cvs => 'cvs'
  has_features :gzip_compression, :reference_tracking, :modules, :cvs_rsh

  def create
    if !@resource.value(:source)
      create_repository(@resource.value(:path))
    else
      checkout_repository
    end
    update_owner
  end

  def exists?
    if @resource.value(:source)
      directory = File.join(@resource.value(:path), 'CVS')
    else
      directory = File.join(@resource.value(:path), 'CVSROOT')
    end
    File.directory?(directory)
  end

  def working_copy_exists?
    File.directory?(File.join(@resource.value(:path), 'CVS'))
  end

  def destroy
    FileUtils.rm_rf(@resource.value(:path))
  end

  def latest?
    debug "Checking for updates because 'ensure => latest'"
    at_path do
      # We cannot use -P to prune empty dirs, otherwise
      # CVS would report those as "missing", regardless
      # if they have contents or updates.
      is_current = (runcvs('-nq', 'update', '-d').strip == "")
      if (!is_current) then debug "There are updates available on the checkout's current branch/tag." end
      return is_current
    end
  end

  def latest
    # CVS does not have a conecpt like commit-IDs or change
    # sets, so we can only have the current branch name (or the
    # requested one, if that differs) as the "latest" revision.
    should = @resource.value(:revision)
    current = self.revision
    return should != current ? should : current
  end

  def revision
    if !@rev
      if File.exist?(tag_file)
        contents = File.read(tag_file).strip
        # Note: Doesn't differentiate between N and T entries
        @rev = contents[1..-1]
      else
        @rev = 'HEAD'
      end
      debug "Checkout is on branch/tag '#{@rev}'"
    end
    return @rev
  end

  def revision=(desired)
    at_path do
      runcvs('update', '-dr', desired, '.')
      update_owner
      @rev = desired
    end
  end

  private

  def tag_file
    File.join(@resource.value(:path), 'CVS', 'Tag')
  end

  def checkout_repository
    dirname, basename = File.split(@resource.value(:path))
    Dir.chdir(dirname) do
      args = ['-d', @resource.value(:source)]
      if @resource.value(:compression)
        args.push('-z', @resource.value(:compression))
      end
      args.push('checkout')
      if @resource.value(:revision)
        args.push('-r', @resource.value(:revision))
      end
      args.push('-d', basename, module_name)
      runcvs(*args)
    end
  end

  # When the source:
  # * Starts with ':' (eg, :pserver:...)
  def module_name
    if (m = @resource.value(:module))
      m
    elsif (source = @resource.value(:source))
      source[0, 1] == ':' ? File.basename(source) : '.'
    end
  end

  def create_repository(path)
    runcvs('-d', path, 'init')
  end

  def update_owner
    if @resource.value(:owner) or @resource.value(:group)
      set_ownership
    end
  end

  def runcvs(*args)
    if @resource.value(:cvs_rsh)
      debug "Using CVS_RSH = " + @resource.value(:cvs_rsh)
      e = { :CVS_RSH => @resource.value(:cvs_rsh) }
    else
      e = {}
    end

    # The location of withenv changed from Puppet 2.x to 3.x
    withenv = Puppet::Util.method(:withenv) if Puppet::Util.respond_to?(:withenv)
    withenv = Puppet::Util::Execution.method(:withenv) if Puppet::Util::Execution.respond_to?(:withenv)
    fail("Cannot set custom environment #{e}") if e && !withenv

    withenv.call e do
      Puppet.debug cvs *args
    end
  end
end