diff --git a/branches/ucs-3.2/ucs-3.2-3/base/univention-lib/python/package_manager.py b/branches/ucs-3.2/ucs-3.2-3/base/univention-lib/python/package_manager.py index d710d3a..e267b33 100644 --- a/branches/ucs-3.2/ucs-3.2-3/base/univention-lib/python/package_manager.py +++ b/branches/ucs-3.2/ucs-3.2-3/base/univention-lib/python/package_manager.py -55,12 +55,14 @@ _ = Translation('univention-lib').translate CMD_DISABLE_EXEC = '/usr/share/univention-updater/disable-apache2-umc' CMD_ENABLE_EXEC = ['/usr/share/univention-updater/enable-apache2-umc', '--no-restart'] + class LockError(Exception): '''Lock error for the package manager. Not to be confused with LockFailedException (apt) ''' pass + class ProgressState(object): def __init__(self, info_handler, step_handler, error_handler, handle_only_frontend_errors): self.info_handler = info_handler -135,6 +137,7 @@ class ProgressState(object): self.reset() return result + class MessageWriter(object): '''Mimics a file object supports flush and write. Writes no '\\r', -152,6 +155,7 @@ class MessageWriter(object): if msg: self.progress_state.info(msg) + class FetchProgress(apt.progress.text.AcquireProgress): '''Used to handle information about fetching packages. Writes a lot of __MSG__es, as it uses MessageWriter -170,6 +174,7 @@ class FetchProgress(apt.progress.text.AcquireProgress): def _write(self, msg, newline=True, maximize=True): super(FetchProgress, self)._write(msg, newline=False, maximize=False) + class DpkgProgress(apt.progress.base.InstallProgress): '''Progress when installing or removing software. Writes messages (and percentage) from apts status file descriptor -180,50 +185,50 @@ class DpkgProgress(apt.progress.base.InstallProgress): def fork(self): # start a new pipe - self.fd_pipe_read, self.fd_pipe_write = os.pipe() - - # wrap handle for reading end of the pipe... for convenience - self.pipe_read = os.fdopen(self.fd_pipe_read) + fd_pipe_read, fd_pipe_write = os.pipe() # we better have a real file when using low-level routines # basically taken from: https://bugs.launchpad.net/jockey/+bug/280291 p = os.fork() if p == 0: # child -> redirect stdout/stderr of dpkg to pipe - os.dup2(self.fd_pipe_write, sys.stdout.fileno()) - os.dup2(self.fd_pipe_write, sys.stderr.fileno()) + os.dup2(fd_pipe_write, sys.stdout.fileno()) + os.dup2(fd_pipe_write, sys.stderr.fileno()) # close unneeded pipe handles - os.close(self.fd_pipe_read) - os.close(self.fd_pipe_write) + os.close(fd_pipe_read) + os.close(fd_pipe_write) else: # parent -> close write handle - os.close(self.fd_pipe_write) - + os.close(fd_pipe_write) + + # wrap handle for reading end of the pipe... for convenience + pipe_read = os.fdopen(fd_pipe_read) + # start thread that monitors the pipes output - self._check_pipe_thread = threading.Thread(target=self.check_pipe) + self._check_pipe_thread = threading.Thread(target=self.check_pipe, args=(pipe_read,)) + self._check_pipe_thread.daemon = True self._check_pipe_thread.start() return p - def check_pipe(self): + def check_pipe(self, pipe_read): while True: try: # read the next line - output = self.pipe_read.readline() + output = pipe_read.readline() if not output: # pipe has been closed -> we are done - break + break # we got a new line -> send to info handler self.progress_state.info(output.strip()) - except (OSError, IOError): # something unexpected happened -> break loop break # close the pipe's read end - self.pipe_read.close() + pipe_read.close() # status == pmstatus def status_change(self, pkg, percent, status): -249,7 +254,8 @@ class DpkgProgress(apt.progress.base.InstallProgress): # # def processing(self, pkg, stage): # self.log('PROCESS', pkg, stage) -# + + class PackageManager(object): def __init__(self, lock=True, info_handler=None, step_handler=None, error_handler=None, handle_only_frontend_errors=False, always_noninteractive=False): self.cache = apt.Cache() -702,4 +708,3 @@ class PackageManager(object): def uninstall(self, *pkg_names): '''Instantly deletes packages when found''' return self.commit(install=self._always_install, remove=pkg_names) -