13
13
__author__ = "Sebastian Heinlein <devel@glatzor.de>"
15
__all__ = ("DaemonAcquireProgress", "DaemonOpenProgress",
16
"DaemonInstallProgress", "DaemonDpkgInstallProgress",
17
"DaemonDpkgRecoverProgress")
15
19
from gettext import gettext as _
48
53
REGEX_ANSI_ESCAPE_CODE = chr(27) + "\[[;?0-9]*[A-Za-z]"
50
class DaemonOpenProgress(apt.progress.OpProgress):
55
class DaemonOpenProgress(apt.progress.base.OpProgress):
52
57
"""Handles the progress of the cache opening."""
60
65
end -- end of the progress range (defaults to 100)
61
66
quiet -- do not emit any progress information for the transaction
63
apt.progress.OpProgress.__init__(self)
68
apt.progress.base.OpProgress.__init__(self)
64
69
self._transaction = transaction
65
70
self.steps = [begin + (end - begin) * modifier
66
71
for modifier in [0.12, 0.25, 0.50, 0.75, 1.00]]
95
98
log.warning("An additional step to open the cache is required")
98
class DaemonFetchProgress(apt.progress.FetchProgress):
101
class DaemonAcquireProgress(apt.progress.base.AcquireProgress):
100
103
Handle the package download process
102
105
def __init__(self, transaction, begin=0, end=100):
103
apt.progress.FetchProgress.__init__(self)
106
apt.progress.base.AcquireProgress.__init__(self)
104
107
self.transaction = transaction
105
108
self.progress_end = end
106
109
self.progress_begin = begin
107
110
self.progress = 0
109
#FIXME: This should already be part of python-apt
110
self.currentItems = 0
112
self.currentBytes = 0
112
def pulse(self, owner):
117
113
"""Callback to update progress information"""
118
apt.progress.FetchProgress.pulse(self)
119
114
if self.transaction.cancelled:
121
self.transaction.progress_details = (self.currentItems, self.totalItems,
122
self.currentBytes, self.totalBytes,
123
self.currentCPS, self.eta)
124
progress = int(self.progress_begin + self.percent/100 * \
116
self.transaction.progress_details = (self.current_items,
122
percent = (((self.current_bytes + self.current_items) * 100.0) /
123
float(self.total_bytes + self.total_items))
124
progress = int(self.progress_begin + percent/100 * \
125
125
(self.progress_end - self.progress_begin))
126
126
# If the progress runs backwards emit an illegal progress value
127
127
# e.g. during cache updates.
131
131
self.transaction.progress = progress
132
132
self.progress = progress
133
# Show all currently downloaded files
135
for worker in owner.workers:
136
if not worker.current_item or not \
137
worker.current_item.owner.status == \
138
apt_pkg.AcquireItem.STAT_FETCHING:
140
if worker.current_item.owner.id:
141
items.append(worker.current_item.owner.id)
143
items.append(worker.current_item.shortdesc)
145
#FIXME: Would be nice to have a subprogress signal
146
msg = gettext.ngettext("Downloading %s", "Downloading %s",
147
len(items)) % " ".join(items)
148
self.transaction.status_details = msg
133
150
while gobject.main_context_default().pending():
134
151
gobject.main_context_default().iteration()
137
def updateStatus(self, uri, descr, shortDescr, status):
138
"""Callback to update the status information"""
139
if status != self.dlQueued:
140
log.debug("%s %s" % (self.dlStatusStr[status], uri))
141
if status == self.dlQueued:
142
self.transaction.status_details = _("Downloading %s") % shortDescr
143
self.items[uri] = status
146
155
"""Callback at the beginning of the operation"""
147
156
self.transaction.status = enums.STATUS_DOWNLOADING
153
162
self.transaction.progress = self.progress_end
154
163
self.transaction.cancellable = False
156
def mediaChange(self, medium, drive):
165
def media_change(self, medium, drive):
157
166
"""Callback for media changes"""
158
167
#FIXME: make use of DeviceKit/hal
159
168
self.transaction.required_medium = medium, drive
183
192
self._line_buffer = ""
185
def startUpdate(self):
194
def start_update(self):
186
195
log.debug("Start update")
187
196
self.transaction.status = enums.STATUS_COMMITTING
188
197
self.transaction.term_attached = True
189
198
self.last_activity = time.time()
190
199
self.start_time = time.time()
192
def finishUpdate(self):
201
def finish_update(self):
193
202
"""Callback at the end of the operation"""
194
#if self.conffile_prompts:
195
# self._transaction.Message(MESSAGE_CONFIG_FILES_CHANGED,
196
# "The following conffile prompts were found "
197
# "and need investiagtion: %s" % \
198
# "\n".join(self.conffile_prompts))
199
# Check for required restarts
200
#if os.path.exists("/var/run/reboot-required") and \
201
# os.path.getmtime("/var/run/reboot-required") > self.start_time:
202
#self._transaction.RequireRestart(RESTART_SYSTEM, "")
203
203
self.transaction.term_attached = False
205
205
def _child(self, pm):
207
res = pm.DoInstall(self.status_child_fd)
207
res = pm.do_install(self.status_child_fd)
209
os._exit(pm.ResultFailed)
209
os._exit(apt_pkg.PackageManager.RESULT_FAILED)
301
301
"""Fork and create a master/slave pty pair by which the forked process
302
302
can be controlled.
304
# process all pending events in the main loop, since we will quit
305
# the loop in the child process
306
context = gobject.main_context_default()
307
while context.pending():
309
304
pid, self.master_fd = os.forkpty()
331
326
os.putenv("DEBIAN_FRONTEND", "noninteractive")
332
327
# Proxy configuration
333
328
if self.transaction.http_proxy:
334
apt_pkg.Config.Set("Acquire::http::Proxy", self.transaction.http_proxy)
329
apt_pkg.config.set("Acquire::http::Proxy",
330
self.transaction.http_proxy)
337
333
def _copy_io_master(self, source, condition, target):