summaryrefslogtreecommitdiffstats
path: root/lib/puppet/provider/package/ports.rb
blob: 014f31530742ef11fae942fb0ab6ffd1b9aaa676 (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
Puppet::Type.type(:package).provide :ports, :parent => :freebsd, :source => :freebsd do
    desc "Support for FreeBSD's ports.  Again, this still mixes packages and ports."

    commands :portupgrade => "/usr/local/sbin/portupgrade",
        :portversion => "/usr/local/sbin/portversion",
        :portuninstall => "/usr/local/sbin/pkg_deinstall",
        :portinfo => "/usr/sbin/pkg_info"

    defaultfor :operatingsystem => :freebsd

    # I hate ports
    %w{INTERACTIVE UNAME}.each do |var|
        ENV.delete(var) if ENV.include?(var)
    end

    def install
        # -N: install if the package is missing, otherwise upgrade
        # -M: yes, we're a batch, so don't ask any questions
        cmd = %w{-N -M BATCH=yes} << @resource[:name]

        output = portupgrade(*cmd)
        if output =~ /\*\* No such /
            raise Puppet::ExecutionFailure, "Could not find package #{@resource[:name]}"
        end
    end

    # If there are multiple packages, we only use the last one
    def latest
        cmd = ["-v", @resource[:name]]

        begin
            output = portversion(*cmd)
        rescue Puppet::ExecutionFailure
            raise Puppet::Error.new(output)
        end
        line = output.split("\n").pop

        unless line =~ /^(\S+)\s+(\S)\s+(.+)$/
            # There's no "latest" version, so just return a placeholder
            return :latest
        end

        pkgstuff = $1
        match = $2
        info = $3

        unless pkgstuff =~ /^(\S+)-([^-\s]+)$/
            raise Puppet::Error,
                "Could not match package info '#{pkgstuff}'"
        end

        name, version = $1, $2

        if match == "=" or match == ">"
            # we're up to date or more recent
            return version
        end

        # Else, we need to be updated; we need to pull out the new version

        unless info =~ /\((\w+) has (.+)\)/
            raise Puppet::Error,
                "Could not match version info '#{info}'"
        end

        source, newversion = $1, $2

        debug "Newer version in #{source}"
        newversion
    end

    def query
        # support portorigin_glob such as "mail/postfix"
        name = self.name
        if name =~ /\//
            name = self.name.split(/\//).slice(1)
        end
        self.class.instances.each do |instance|
            if instance.name == name
                return instance.properties
            end
        end

        nil
    end

    def uninstall
        portuninstall @resource[:name]
    end

    def update
        install()
    end
end