]>
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 from constants
import *
33 def __init__(self
, pakfire
, pkg
):
34 self
.pakfire
= pakfire
35 self
.pkg_solv
= self
.pkg
= pkg
37 # Try to get the binary version of the package from the cache if
39 binary_package
= self
.pkg
.get_from_cache()
41 self
.pkg
= binary_package
45 def __cmp__(self
, other
):
46 return cmp(self
.pkg
, other
.pkg
)
49 return "<%s %s>" % (self
.__class
__.__name
__, self
.pkg
.friendly_name
)
52 # A function to run additional initialization.
55 def check(self
, filelist
):
56 # This is just a dummy test that does nothing at all.
60 def needs_download(self
):
61 return self
.type in ("install", "reinstall", "upgrade", "downgrade",) \
62 and not isinstance(self
.pkg
, packages
.BinaryPackage
)
64 def download(self
, text
):
65 if not self
.needs_download
:
68 self
.pkg
= self
.pkg
.download(text
)
71 raise NotImplementedError
76 Reference to local repository.
78 return self
.pakfire
.repos
.local
81 class ActionScript(Action
):
87 self
.scriptlet
= self
.pkg
.get_scriptlet(self
.script_action
)
90 def interpreter(self
):
92 Get the interpreter of this scriptlet.
94 return util
.scriptlet_interpreter(self
.scriptlet
)
101 # Exit immediately, if the scriptlet is empty.
102 if not self
.scriptlet
:
105 # Actually run the scriplet.
106 logging
.debug("Running scriptlet %s" % self
)
108 # Check if the interpreter does exist and is executable.
110 interpreter
= "%s/%s" % (self
.pakfire
.path
, self
.interpreter
)
111 if not os
.path
.exists(interpreter
):
112 raise ActionError
, _("Cannot run scriptlet because no interpreter is available: %s" \
115 if not os
.access(interpreter
, os
.X_OK
):
116 raise ActionError
, _("Cannot run scriptlet because the interpreter is not executable: %s" \
119 # Create a name for the temporary script file.
120 script_file_chroot
= os
.path
.join("/", LOCAL_TMP_PATH
,
121 "scriptlet_%s" % util
.random_string(10))
122 script_file
= os
.path
.join(self
.pakfire
.path
, script_file_chroot
[1:])
123 assert script_file
.startswith("%s/" % self
.pakfire
.path
)
125 # Create script directory, if it does not exist.
126 script_dir
= os
.path
.dirname(script_file
)
127 if not os
.path
.exists(script_dir
):
128 os
.makedirs(script_dir
)
130 # Write the scriptlet to a file that we can execute it.
132 f
= open(script_file
, "wb")
133 f
.write(self
.scriptlet
)
136 # The file is only accessable by root.
137 os
.chmod(script_file
, 700)
139 # Remove the file if an error occurs.
141 os
.unlink(script_file
)
145 # XXX catch errors and return a beautiful message to the user
148 # Generate the script command.
149 command
= [script_file_chroot
] + self
.args
151 # If we are running in /, we do not need to chroot there.
153 if not self
.pakfire
.path
== "/":
154 chroot_path
= self
.pakfire
.path
157 ret
= chroot
.do(command
, cwd
="/tmp",
158 chrootPath
=chroot_path
,
159 personality
=self
.pakfire
.distro
.personality
,
161 timeout
=SCRIPTLET_TIMEOUT
,
162 logger
=logging
.getLogger())
165 raise ActionError
, _("The scriptlet returned an error:\n%s" % e
)
167 except commandTimeoutExpired
:
168 raise ActionError
, _("The scriptlet ran more than %s seconds and was killed." \
172 # Remove the script file.
174 os
.unlink(script_file
)
176 logging
.debug("Could not remove scriptlet file: %s" % script_file
)
179 class ActionScriptPreIn(ActionScript
):
180 script_action
= "prein"
183 class ActionScriptPostIn(ActionScript
):
184 script_action
= "postin"
187 class ActionScriptPreUn(ActionScript
):
188 script_action
= "preun"
191 class ActionScriptPostUn(ActionScript
):
192 script_action
= "postun"
195 class ActionScriptPreUp(ActionScript
):
196 script_action
= "preup"
199 class ActionScriptPostUp(ActionScript
):
200 script_action
= "postup"
203 class ActionScriptPostTrans(ActionScript
):
207 class ActionScriptPostTransIn(ActionScriptPostTrans
):
208 script_action
= "posttransin"
211 class ActionScriptPostTransUn(ActionScriptPostTrans
):
212 script_action
= "posttransun"
215 class ActionScriptPostTransUp(ActionScriptPostTrans
):
216 script_action
= "posttransup"
219 class ActionInstall(Action
):
222 def check(self
, check
):
223 logging
.debug(_("Running transaction test for %s") % self
.pkg
.friendly_name
)
225 # Check if this package can be installed.
226 check
.install(self
.pkg
)
229 # Add package to the database.
230 self
.local
.add_package(self
.pkg
)
232 self
.pkg
.extract(_("Installing"), prefix
=self
.pakfire
.path
)
235 class ActionUpdate(Action
):
238 def check(self
, check
):
239 logging
.debug(_("Running transaction test for %s") % self
.pkg
.friendly_name
)
241 # Check if this package can be updated.
242 check
.update(self
.pkg
)
245 # Add new package to the database.
246 self
.local
.add_package(self
.pkg
)
248 self
.pkg
.extract(_("Updating"), prefix
=self
.pakfire
.path
)
251 class ActionRemove(Action
):
254 def __init__(self
, *args
, **kwargs
):
255 Action
.__init
__(self
, *args
, **kwargs
)
257 # XXX This is ugly, but works for the moment.
258 self
.pkg
= self
.local
.index
.db
.get_package_from_solv(self
.pkg_solv
)
261 def check(self
, check
):
262 logging
.debug(_("Running transaction test for %s") % self
.pkg
.friendly_name
)
264 # Check if this package can be removed.
265 check
.remove(self
.pkg
)
268 self
.pkg
.cleanup(_("Removing"), prefix
=self
.pakfire
.path
)
270 # Remove package from the database.
271 self
.local
.rem_package(self
.pkg
)
274 class ActionCleanup(Action
):
277 def __init__(self
, *args
, **kwargs
):
278 Action
.__init
__(self
, *args
, **kwargs
)
280 # XXX This is ugly, but works for the moment.
281 self
.pkg
= self
.local
.index
.db
.get_package_from_solv(self
.pkg_solv
)
284 def check(self
, check
):
285 logging
.debug(_("Running transaction test for %s") % self
.pkg
.friendly_name
)
287 # Check if this package can be removed.
288 check
.cleanup(self
.pkg
)
291 # Cleaning up leftover files and stuff.
292 self
.pkg
.cleanup(_("Cleanup"), prefix
=self
.pakfire
.path
)
294 # Remove package from the database.
295 self
.local
.rem_package(self
.pkg
)
298 class ActionReinstall(Action
):
301 def check(self
, check
):
302 logging
.debug(_("Running transaction test for %s") % self
.pkg
.friendly_name
)
304 # Check if this package can be reinstalled.
305 check
.remove(self
.pkg
)
306 check
.install(self
.pkg
)
309 # Remove package from the database and add it afterwards.
310 # Sounds weird, but fixes broken entries in the database.
311 self
.local
.rem_package(self
.pkg
)
312 self
.local
.add_package(self
.pkg
)
314 self
.pkg
.extract(_("Installing"), prefix
=self
.pakfire
.path
)
317 class ActionDowngrade(Action
):
320 def check(self
, check
):
321 logging
.debug(_("Running transaction test for %s") % self
.pkg
.friendly_name
)
323 # Check if this package can be downgraded.
324 check
.install(self
.pkg
)
327 # Add new package to database.
328 self
.local
.add_package(self
.pkg
)
330 self
.pkg
.extract(_("Downgrading"), prefix
=self
.pakfire
.path
)
333 class ActionChange(Action
):
336 # XXX still need to find out what this should be doing
339 print "XXX Change: %s" % self
.pkg