summaryrefslogtreecommitdiff
path: root/apt/progress.py
diff options
context:
space:
mode:
Diffstat (limited to 'apt/progress.py')
-rw-r--r--apt/progress.py84
1 files changed, 80 insertions, 4 deletions
diff --git a/apt/progress.py b/apt/progress.py
index 86cd6594..4119067c 100644
--- a/apt/progress.py
+++ b/apt/progress.py
@@ -19,9 +19,9 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
-import sys
+import sys, apt_pkg, os, fcntl, string, re
-class OpProgress:
+class OpProgress(object):
""" Abstract class to implement reporting on cache opening
Subclass this class to implement simple Operation progress reporting
"""
@@ -62,6 +62,8 @@ class FetchProgress(object):
dlIgnored : "Ignored"}
def __init__(self):
+ self.eta = 0.0
+ self.percent = 0.0
pass
def start(self):
@@ -104,7 +106,7 @@ class TextFetchProgress(FetchProgress):
sys.stdout.flush()
return True
def stop(self):
- print "\rDone "
+ print "\rDone downloading "
def mediaChange(self, medium, drive):
""" react to media change events """
res = True;
@@ -115,7 +117,7 @@ class TextFetchProgress(FetchProgress):
res = false;
return res
-class InstallProgress:
+class DumbInstallProgress(object):
""" Report the install progress
Subclass this class to implement install progress reporting
"""
@@ -123,11 +125,85 @@ class InstallProgress:
pass
def startUpdate(self):
pass
+ def run(self, pm):
+ return pm.DoInstall()
def finishUpdate(self):
pass
def updateInterface(self):
pass
+class InstallProgress(DumbInstallProgress):
+ """ A InstallProgress that is pretty useful.
+ It supports the attributes 'percent' 'status' and callbacks
+ for the dpkg errors and conffiles and status changes
+ """
+ def __init__(self):
+ DumbInstallProgress.__init__(self)
+ (read, write) = os.pipe()
+ self.writefd=write
+ self.statusfd = os.fdopen(read, "r")
+ fcntl.fcntl(self.statusfd.fileno(), fcntl.F_SETFL,os.O_NONBLOCK)
+ self.read = ""
+ self.percent = 0.0
+ self.status = ""
+ def error(self, pkg, errormsg):
+ " called when a error is detected during the install "
+ pass
+ def conffile(self,current,new):
+ " called when a conffile question from dpkg is detected "
+ pass
+ def statusChange(self, pkg, percent, status):
+ " called when the status changed "
+ pass
+ def updateInterface(self):
+ if self.statusfd != None:
+ try:
+ while not self.read.endswith("\n"):
+ self.read += os.read(self.statusfd.fileno(),1)
+ except OSError, (errno,errstr):
+ # resource temporarly unavailable is ignored
+ if errno != 11:
+ print errstr
+ if self.read.endswith("\n"):
+ s = self.read
+ #print s
+ (status, pkg, percent, status_str) = string.split(s, ":")
+ #print "percent: %s %s" % (pkg, float(percent)/100.0)
+ if status == "pmerror":
+ self.error(pkg,status_str)
+ elif status == "pmconffile":
+ # we get a string like this:
+ # 'current-conffile' 'new-conffile' useredited distedited
+ match = re.compile("\s*\'(.*)\'\s*\'(.*)\'.*").match(status_str)
+ if match:
+ self.conffile(match.group(1), match.group(2))
+ elif status == "pmstatus":
+ if float(percent) != self.percent or \
+ status_str != self.status:
+ self.statusChange(pkg, float(percent), status_str.strip())
+ self.percent = float(percent)
+ self.status = string.strip(status_str)
+ self.read = ""
+
+ def fork(self):
+ return os.fork()
+ def waitChild(self):
+ while True:
+ (pid, res) = os.waitpid(self.child_pid,os.WNOHANG)
+ if pid == self.child_pid:
+ break
+ self.updateInterface()
+ return os.WEXITSTATUS(res)
+ def run(self, pm):
+ pid = self.fork()
+ if pid == 0:
+ # child
+ res = pm.DoInstall(self.writefd)
+ sys.exit(res)
+ self.child_pid = pid
+ res = self.waitChild()
+ return res
+
class CdromProgress:
""" Report the cdrom add progress
Subclass this class to implement cdrom add progress reporting