]>
git.ipfire.org Git - pakfire.git/blob - pakfire/transaction.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 ###############################################################################
32 from constants
import *
35 PKG_DUMP_FORMAT
= " %-21s %-8s %-21s %-18s %6s "
37 # Import all actions directly.
40 class Transaction(object):
42 ActionInstall
.type : [ActionScriptPreIn
, ActionInstall
, ActionScriptPostIn
, ActionScriptPostTransIn
],
43 ActionReinstall
.type : [ActionScriptPreIn
, ActionReinstall
, ActionScriptPostIn
, ActionScriptPostTransIn
],
44 ActionRemove
.type : [ActionScriptPreUn
, ActionRemove
, ActionScriptPostUn
, ActionScriptPostTransUn
],
45 ActionUpdate
.type : [ActionScriptPreUp
, ActionUpdate
, ActionScriptPostUp
, ActionScriptPostTransUp
],
46 ActionCleanup
.type : [ActionCleanup
,],
47 ActionDowngrade
.type : [ActionScriptPreUp
, ActionDowngrade
, ActionScriptPostUp
, ActionScriptPostTransUp
],
48 ActionChange
.type : [ActionChange
,],
51 def __init__(self
, pakfire
):
52 self
.pakfire
= pakfire
55 self
.installsizechange
= 0
58 def from_solver(cls
, pakfire
, solver
, _transaction
):
59 # Create a new instance of our own transaction class.
60 transaction
= cls(pakfire
)
62 # Save installsizechange.
63 transaction
.installsizechange
= _transaction
.get_installsizechange()
65 # Get all steps that need to be done from the solver.
66 steps
= _transaction
.steps()
74 action_name
= step
.get_type()
75 pkg
= packages
.SolvPackage(pakfire
, step
.get_solvable())
78 classes
= transaction
.action_classes
[action_name
]
80 raise Exception, "Unknown action required: %s" % action_name
82 for action_cls
in classes
:
83 action
= action_cls(pakfire
, pkg
)
84 assert isinstance(action
, Action
), action
86 if isinstance(action
, ActionScriptPostTrans
):
87 actions_post
.append(action
)
89 actions
.append(action
)
91 transaction
.actions
+= actions
+ actions_post
97 return [a
.pkg
for a
in self
.actions
if isinstance(a
, ActionInstall
)]
100 def reinstalls(self
):
101 return [a
.pkg
for a
in self
.actions
if isinstance(a
, ActionReinstall
)]
105 return [a
.pkg
for a
in self
.actions
if isinstance(a
, ActionRemove
)]
109 return [a
.pkg
for a
in self
.actions
if isinstance(a
, ActionUpdate
)]
112 def downgrades(self
):
113 return [a
.pkg
for a
in self
.actions
if isinstance(a
, ActionDowngrade
)]
117 return sorted([a
for a
in self
.actions
if a
.needs_download
])
120 # Get all download actions as a list.
121 downloads
= [d
for d
in self
.downloads
]
124 # If there are no downloads, we can just stop here.
128 logging
.info(_("Downloading packages:"))
129 time_start
= time
.time()
131 # Calculate downloadsize.
133 for action
in downloads
:
134 download_size
+= action
.pkg
.size
137 for action
in downloads
:
139 action
.download(text
="(%d/%d): " % (i
, len(downloads
)))
141 # Write an empty line to the console when there have been any downloads.
142 width
, height
= util
.terminal_size()
145 logging
.info("-" * width
)
147 # Format and calculate download information.
148 time_stop
= time
.time()
149 download_time
= time_stop
- time_start
150 download_speed
= download_size
/ download_time
151 download_speed
= util
.format_speed(download_speed
)
152 download_size
= util
.format_size(download_size
)
153 download_time
= util
.format_time(download_time
)
155 line
= "%s | %5sB %s " % \
156 (download_speed
, download_size
, download_time
)
157 line
= " " * (width
- len(line
)) + line
161 def dump_pkg(self
, pkg
):
166 ret
.append(" %s" % name
)
169 ret
.append(PKG_DUMP_FORMAT
% (name
, pkg
.arch
, pkg
.friendly_version
,
170 pkg
.repo
.name
, util
.format_size(pkg
.size
)))
174 def dump_pkgs(self
, caption
, pkgs
):
179 for pkg
in sorted(pkgs
):
180 s
+= self
.dump_pkg(pkg
)
184 def dump(self
, logger
=None):
186 logger
= logging
.getLogger()
193 s
.append(PKG_DUMP_FORMAT
% (_("Package"), _("Arch"), _("Version"),
194 _("Repository"), _("Size")))
198 (_("Installing:"), self
.installs
),
199 (_("Reinstalling:"), self
.reinstalls
),
200 (_("Updating:"), self
.updates
),
201 (_("Downgrading:"), self
.downgrades
),
202 (_("Removing:"), self
.removes
),
205 for caption
, pkgs
in actions
:
206 s
+= self
.dump_pkgs(caption
, pkgs
)
208 s
.append(_("Transaction Summary"))
211 for caption
, pkgs
in actions
:
214 s
.append("%-20s %-4d %s" % (caption
, len(pkgs
),
215 _("package", "packages", len(pkgs
))))
217 # Calculate the size of all files that need to be downloaded this this
219 download_size
= sum([a
.pkg
.size
for a
in self
.downloads
])
221 s
.append(_("Total download size: %s") % util
.format_size(download_size
))
223 # Show the size that is consumed by the new packages.
224 if self
.installsizechange
> 0:
225 s
.append(_("Installed size: %s") % util
.format_size(self
.installsizechange
))
226 elif self
.installsizechange
< 0:
227 s
.append(_("Freed size: %s") % util
.format_size(self
.installsizechange
))
233 def cli_yesno(self
, logger
=None):
236 return util
.ask_user(_("Is this okay?"))
239 # Download all packages.
242 logging
.info(_("Running transaction"))
243 # Run all actions in order and catch all kinds of ActionError.
244 for action
in self
.actions
:
247 except ActionError
, e
:
248 logging
.error("Action finished with an error: %s - %s" % (action
, e
))