]>
git.immae.eu Git - perso/Immae/Projets/Puppet.git/blob - modules/base_installation/lib/puppet/provider/package/pacman.rb
1 require 'puppet/provider/package'
5 Puppet
::Type.type(:package).provide
:pacman, :parent => Puppet
::Provider::Package do
6 desc
"Support for the Package Manager Utility (pacman) used in Archlinux.
8 This provider supports the `install_options` attribute, which allows command-line flags to be passed to pacman.
9 These options should be specified as a string (e.g. '--flag'), a hash (e.g. {'--flag' => 'value'}),
10 or an array where each element is either a string or a hash."
12 # If aura is installed, we can make use of it
14 @aura ||= Puppet
::FileSystem.exist
?('/usr/bin/aura')
17 commands
:pacman => "/usr/bin/pacman"
18 # Aura is a common AUR helper which, if installed, we can use to query the AUR
19 commands
:aura => "/usr/bin/aura" if aura
?
21 confine
:operatingsystem => [:archlinux, :manjarolinux]
22 defaultfor
:operatingsystem => [:archlinux, :manjarolinux]
23 has_feature
:install_options
24 has_feature
:uninstall_options
25 has_feature
:upgradeable
26 has_feature
:virtual_packages
28 # Checks if a given name is a group
31 !
pacman("-Sg", name
).empty
?
32 rescue Puppet
::ExecutionFailure
33 # pacman returns an expected non-zero exit code when the name is not a group
38 # Install a package using 'pacman', or 'aura' if available.
39 # Installs quietly, without confirmation or progress bar, updates package
40 # list from servers defined in pacman.conf.
49 fail(_("Could not find package '%{name}'") % { name
: @resource[:name] })
53 # Fetch the list of packages and package groups that are currently installed on the system.
54 # Only package groups that are fully installed are included. If a group adds packages over time, it will not
55 # be considered as fully installed any more, and we would install the new packages on the next run.
56 # If a group removes packages over time, nothing will happen. This is intended.
60 # Get the installed packages
61 installed_packages
= get_installed_packages
62 installed_packages
.sort_by
{ |k
, _
| k
}.each
do |package
, version|
63 instances
<< new(to_resource_hash(package
, version))
66 # Get the installed groups
67 get_installed_groups(installed_packages
).each
do |group
, version|
68 instances
<< new(to_resource_hash(group
, version))
74 # returns a hash package => version of installed packages
75 def self.get_installed_packages
78 execpipe([command(:pacman), "-Q"]) do |pipe
|
79 # pacman -Q output is 'packagename version-rel'
80 regex
= %r
{^
(\S+
)\
s(\S+
)}
81 pipe
.each_line
do |line
|
82 if match
= regex
.match(line
)
83 packages
[match
.captures
[0]] = match
.captures
[1]
85 warning(_("Failed to match line '%{line}'") % { line
: line
})
90 rescue Puppet
::ExecutionFailure
91 fail(_("Error getting installed packages"))
95 # returns a hash of group => version of installed groups
96 def self.get_installed_groups(installed_packages
, filter
= nil)
99 # Build a hash of group name => list of packages
100 command
= [command(:pacman), "-Sgg"]
101 command
<< filter
if filter
102 execpipe(command
) do |pipe
|
103 pipe
.each_line
do |line
|
104 name
, package
= line
.split
105 packages
= (groups
[name
] ||= [])
110 # Remove any group that doesn't have all its packages installed
111 groups
.delete_if
do |_
, packages
|
112 !packages
.all
? { |package
| installed_packages
[package
] }
115 # Replace the list of packages with a version string consisting of packages that make up the group
116 groups
.each
do |name
, packages
|
117 groups
[name
] = packages
.sort
.map
{|package
| "#{package} #{installed_packages[package]}"}.join
', '
119 rescue Puppet
::ExecutionFailure
120 # pacman returns an expected non-zero exit code when the filter name is not a group
126 # Because Archlinux is a rolling release based distro, installing a package
127 # should always result in the newest release.
129 # Install in pacman can be used for update, too
133 # We rescue the main check from Pacman with a check on the AUR using aura, if installed
135 # Synchronize the database
138 resource_name
= @resource[:name]
140 # If target is a group, construct the group version
141 return pacman("-Sp", "--print-format", "%n %v", resource_name
).lines
.map
{ |line
| line
.chomp
}.sort
.join(', ') if self.class.group
?(resource_name
)
143 # Start by querying with pacman first
144 # If that fails, retry using aura against the AUR
148 output
= pacman
"-Sp", "--print-format", "%v", resource_name
151 output
= aura
"-Ai", resource_name
152 output
.split("\n").each
do |line
|
153 return line
.split
[2].chomp
if line
.split
[0] =~
/Version/
156 rescue Puppet
::ExecutionFailure
157 if pacman_check
and self.class.aura
?
158 pacman_check
= false # now try the AUR
166 # Queries information for a package or package group
168 installed_packages
= self.class.get_installed_packages
169 resource_name
= @resource[:name]
171 # Check for the resource being a group
172 version = self.class.get_installed_groups(installed_packages
, resource_name
)[resource_name
]
175 unless @resource.allow_virtual
?
176 warning(_("%{resource_name} is a group, but allow_virtual is false.") % { resource_name
: resource_name
})
180 version = installed_packages
[resource_name
]
183 # Return nil if no package or group found
184 return nil unless version
186 self.class.to_resource_hash(resource_name
, version)
189 def self.to_resource_hash(name
, version)
193 :provider => self.name
197 # Removes a package from the system.
199 resource_name
= @resource[:name]
201 is_group
= self.class.group
?(resource_name
)
203 fail(_("Refusing to uninstall package group %{resource_name}, because allow_virtual is false.") % { resource_name
: resource_name
}) if is_group
&& !
@resource.allow_virtual
?
205 cmd
= %w
{--noconfirm
--noprogressbar
}
206 cmd +
= uninstall_options
if @resource[:uninstall_options]
208 cmd
<< '-s' if is_group
220 def install_with_aura
?
221 resource_name
= @resource[:name]
227 pacman
"-Sp", resource_name
229 rescue Puppet
::ExecutionFailure
235 join_options(@resource[:install_options])
238 def uninstall_options
239 join_options(@resource[:uninstall_options])
242 def install_from_file
243 source
= @resource[:source]
245 source_uri
= URI
.parse source
247 self.fail Puppet
::Error, _("Invalid source '%{source}': %{detail}") % { source
: source
, detail
: detail
}, detail
250 source
= case source_uri
.scheme
252 when /https?/i
then source
253 when /ftp/i
then source
254 when /file/i
then source_uri
.path
256 fail
_("puppet:// URL is not supported by pacman")
258 fail
_("Source %{source} is not supported by pacman") % { source
: source
}
260 pacman
"--noconfirm", "--noprogressbar", "-Sy"
261 pacman
"--noconfirm", "--noprogressbar", "-U", source
264 def install_from_repo
265 resource_name
= @resource[:name]
267 # Refuse to install if not allowing virtual packages and the resource is a group
268 fail(_("Refusing to install package group %{resource_name}, because allow_virtual is false.") % { resource_name
: resource_name
}) if self.class.group
?(resource_name
) && !
@resource.allow_virtual
?
270 cmd
= %w
{--noconfirm
--needed
}
271 cmd +
= install_options
if @resource[:install_options]
273 if install_with_aura
?
274 cmd
<< "-Aq" << resource_name
277 cmd
<< "--noprogressbar"
278 cmd
<< "-Sy" << resource_name