]>
git.ipfire.org Git - pakfire.git/blob - python/pakfire/actions.py
2 ###############################################################################
4 # Pakfire - The IPFire package management system #
5 # Copyright (C) 2011 Pakfire development team #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
29 log
= logging
.getLogger("pakfire")
31 from constants
import *
35 def __init__(self
, pakfire
, pkg
):
36 self
.pakfire
= pakfire
37 self
.pkg_solv
= self
.pkg
= pkg
39 # Try to get the binary version of the package from the cache if
41 binary_package
= self
.pkg
.get_from_cache()
43 self
.pkg
= binary_package
47 def __cmp__(self
, other
):
48 return cmp(self
.pkg
, other
.pkg
)
51 return "<%s %s>" % (self
.__class
__.__name
__, self
.pkg
.friendly_name
)
54 # A function to run additional initialization.
57 def check(self
, filelist
):
58 # This is just a dummy test that does nothing at all.
62 def needs_download(self
):
63 return self
.type in ("install", "reinstall", "upgrade", "downgrade", "change",) \
64 and not isinstance(self
.pkg
, packages
.BinaryPackage
)
66 def download(self
, text
):
67 if not self
.needs_download
:
70 self
.pkg
= self
.pkg
.download(text
)
73 raise NotImplementedError
78 Reference to local repository.
80 return self
.pakfire
.repos
.local
82 def do(self
, cmd
, **kwargs
):
83 # If we are running in /, we do not need to chroot there.
85 if not self
.pakfire
.path
== "/":
86 chroot_path
= self
.pakfire
.path
90 for i
in ("tmp", "root"):
92 _cwd
= os
.path
.join(chroot_path
, i
)
96 if os
.path
.exists(_cwd
):
103 "personality" : self
.pakfire
.distro
.personality
,
105 "timeout" : SCRIPTLET_TIMEOUT
,
108 # Overwrite by args that were passed.
111 # You can never overwrite chrootPath.
113 "chrootPath" : chroot_path
,
116 return chroot
.do(cmd
, **args
)
119 class ActionScript(Action
):
125 self
.scriptlet
= self
.pkg
.get_scriptlet(self
.script_action
)
128 def interpreter(self
):
130 Get the interpreter of this scriptlet.
132 return util
.scriptlet_interpreter(self
.scriptlet
)
139 # Exit immediately, if the scriptlet is empty.
140 if not self
.scriptlet
:
143 # Actually run the scriplet.
144 log
.debug("Running scriptlet %s" % self
)
146 # Check if the interpreter does exist and is executable.
148 interpreter
= "%s/%s" % (self
.pakfire
.path
, self
.interpreter
)
149 if not os
.path
.exists(interpreter
):
150 raise ActionError
, _("Cannot run scriptlet because no interpreter is available: %s" \
153 if not os
.access(interpreter
, os
.X_OK
):
154 raise ActionError
, _("Cannot run scriptlet because the interpreter is not executable: %s" \
157 # Create a name for the temporary script file.
158 script_file_chroot
= os
.path
.join("/", LOCAL_TMP_PATH
,
159 "scriptlet_%s" % util
.random_string(10))
160 script_file
= os
.path
.join(self
.pakfire
.path
, script_file_chroot
[1:])
161 assert script_file
.startswith(self
.pakfire
.path
)
163 # Create script directory, if it does not exist.
164 script_dir
= os
.path
.dirname(script_file
)
165 if not os
.path
.exists(script_dir
):
166 os
.makedirs(script_dir
)
168 # Write the scriptlet to a file that we can execute it.
170 f
= open(script_file
, "wb")
171 f
.write(self
.scriptlet
)
174 # The file is only accessable by root.
175 os
.chmod(script_file
, 700)
177 # Remove the file if an error occurs.
179 os
.unlink(script_file
)
183 # XXX catch errors and return a beautiful message to the user
186 # Generate the script command.
187 command
= [script_file_chroot
] + self
.args
193 raise ActionError
, _("The scriptlet returned an error:\n%s" % e
)
195 except commandTimeoutExpired
:
196 raise ActionError
, _("The scriptlet ran more than %s seconds and was killed." \
200 # Remove the script file.
202 os
.unlink(script_file
)
204 log
.debug("Could not remove scriptlet file: %s" % script_file
)
207 class ActionScriptPreIn(ActionScript
):
208 script_action
= "prein"
211 class ActionScriptPostIn(ActionScript
):
212 script_action
= "postin"
215 class ActionScriptPreUn(ActionScript
):
216 script_action
= "preun"
219 class ActionScriptPostUn(ActionScript
):
220 script_action
= "postun"
223 class ActionScriptPreUp(ActionScript
):
224 script_action
= "preup"
227 class ActionScriptPostUp(ActionScript
):
228 script_action
= "postup"
231 class ActionScriptPostTrans(ActionScript
):
235 class ActionScriptPostTransIn(ActionScriptPostTrans
):
236 script_action
= "posttransin"
239 class ActionScriptPostTransUn(ActionScriptPostTrans
):
240 script_action
= "posttransun"
243 class ActionScriptPostTransUp(ActionScriptPostTrans
):
244 script_action
= "posttransup"
247 class ActionInstall(Action
):
250 def check(self
, check
):
251 log
.debug(_("Running transaction test for %s") % self
.pkg
.friendly_name
)
253 # Check if this package can be installed.
254 check
.install(self
.pkg
)
257 # Add package to the database.
258 self
.local
.add_package(self
.pkg
)
260 self
.pkg
.extract(_("Installing"), prefix
=self
.pakfire
.path
)
262 # Check if shared objects were extracted. If this is the case, we need
264 ldconfig_needed
= False
265 for file in self
.pkg
.filelist
:
266 if ".so." in file.name
:
267 ldconfig_needed
= True
270 if "etc/ld.so.conf" in file.name
:
271 ldconfig_needed
= True
275 # Check if ldconfig is present.
276 ldconfig
= os
.path
.join(self
.pakfire
.path
, LDCONFIG
[1:])
278 if os
.path
.exists(ldconfig
) and os
.access(ldconfig
, os
.X_OK
):
282 log
.debug("ldconfig is not present or not executable.")
285 class ActionUpdate(Action
):
288 def check(self
, check
):
289 log
.debug(_("Running transaction test for %s") % self
.pkg
.friendly_name
)
291 # Check if this package can be updated.
292 check
.update(self
.pkg
)
295 # Add new package to the database.
296 self
.local
.add_package(self
.pkg
)
298 self
.pkg
.extract(_("Updating"), prefix
=self
.pakfire
.path
)
301 class ActionRemove(Action
):
304 def __init__(self
, *args
, **kwargs
):
305 Action
.__init
__(self
, *args
, **kwargs
)
307 # XXX This is ugly, but works for the moment.
308 self
.pkg
= self
.local
.index
.db
.get_package_from_solv(self
.pkg_solv
)
311 def check(self
, check
):
312 log
.debug(_("Running transaction test for %s") % self
.pkg
.friendly_name
)
314 # Check if this package can be removed.
315 check
.remove(self
.pkg
)
318 self
.pkg
.cleanup(_("Removing"), prefix
=self
.pakfire
.path
)
320 # Remove package from the database.
321 self
.local
.rem_package(self
.pkg
)
324 class ActionCleanup(Action
):
327 def __init__(self
, *args
, **kwargs
):
328 Action
.__init
__(self
, *args
, **kwargs
)
330 # XXX This is ugly, but works for the moment.
331 self
.pkg
= self
.local
.index
.db
.get_package_from_solv(self
.pkg_solv
)
334 def check(self
, check
):
335 log
.debug(_("Running transaction test for %s") % self
.pkg
.friendly_name
)
337 # Check if this package can be removed.
338 check
.cleanup(self
.pkg
)
341 # Cleaning up leftover files and stuff.
342 self
.pkg
.cleanup(_("Cleanup"), prefix
=self
.pakfire
.path
)
344 # Remove package from the database.
345 self
.local
.rem_package(self
.pkg
)
348 class ActionReinstall(Action
):
351 def check(self
, check
):
352 log
.debug(_("Running transaction test for %s") % self
.pkg
.friendly_name
)
354 # Check if this package can be reinstalled.
355 check
.remove(self
.pkg
)
356 check
.install(self
.pkg
)
359 # Remove package from the database and add it afterwards.
360 # Sounds weird, but fixes broken entries in the database.
361 self
.local
.rem_package(self
.pkg
)
362 self
.local
.add_package(self
.pkg
)
364 self
.pkg
.extract(_("Installing"), prefix
=self
.pakfire
.path
)
367 class ActionDowngrade(Action
):
370 def check(self
, check
):
371 log
.debug(_("Running transaction test for %s") % self
.pkg
.friendly_name
)
373 # Check if this package can be downgraded.
374 check
.install(self
.pkg
)
377 # Add new package to database.
378 self
.local
.add_package(self
.pkg
)
380 self
.pkg
.extract(_("Downgrading"), prefix
=self
.pakfire
.path
)