On Wed, 18 Jan 2017 19:15:54 +0200
Alexandru Elisei <alexandru.eli...@gmail.com> wrote:

> Module functions currently return a message to emaint after
> invocation. Emaint prints this message then exits normally (with a
> success return code) even if the module encountered an error. This
> patch aims to change this by having each module public function
> return a tuple of (returncode, message), where returncode is boolean
> True if the function was successful or False otherwise. Emaint will
> inspect the return codes and exit unsuccessfully if necessary.
> 
> The variable PORT_LOGDIR was added to the test environment to prevent
> CleanLogs.clean() from failing when the variable isn't set or not a
> directory.
> ---
>  pym/portage/emaint/main.py                    | 12 +++++++++---
>  pym/portage/emaint/modules/binhost/binhost.py |  6 ++++--
>  pym/portage/emaint/modules/config/config.py   |  6 ++++--
>  pym/portage/emaint/modules/logs/logs.py       |  9 +++++----
>  pym/portage/emaint/modules/merges/merges.py   | 18 +++++++++++-------
>  pym/portage/emaint/modules/move/move.py       |  9 +++++++--
>  pym/portage/emaint/modules/resume/resume.py   |  3 ++-
>  pym/portage/emaint/modules/sync/sync.py       | 20
> +++++++++++++------- pym/portage/emaint/modules/world/world.py     |
> 8 ++++++-- pym/portage/tests/emerge/test_simple.py       |  1 +
>  10 files changed, 62 insertions(+), 30 deletions(-)
> 
> diff --git a/pym/portage/emaint/main.py b/pym/portage/emaint/main.py
> index 65e3545..f448d6b 100644
> --- a/pym/portage/emaint/main.py
> +++ b/pym/portage/emaint/main.py
> @@ -115,6 +115,7 @@ class TaskHandler(object):
>               """Runs the module tasks"""
>               if tasks is None or func is None:
>                       return
> +             returncodes = []
>               for task in tasks:
>                       inst = task()
>                       show_progress = self.show_progress_bar and
> self.isatty @@ -135,14 +136,17 @@ class TaskHandler(object):
>                               # them for other tasks if there is
> more to do. 'options': options.copy()
>                               }
> -                     result = getattr(inst, func)(**kwargs)
> +                     returncode, msgs = getattr(inst,
> func)(**kwargs)
> +                     returncodes.append(returncode)
>                       if show_progress:
>                               # make sure the final progress is
> displayed self.progress_bar.display()
>                               print()
>                               self.progress_bar.stop()
>                       if self.callback:
> -                             self.callback(result)
> +                             self.callback(msgs)
> +
> +             return returncodes
> 
> 
>  def print_results(results):
> @@ -237,4 +241,6 @@ def emaint_main(myargv):
>       task_opts = options.__dict__
>       task_opts['return-messages'] = True
>       taskmaster = TaskHandler(callback=print_results,
> module_output=sys.stdout)
> -     taskmaster.run_tasks(tasks, func, status, options=task_opts)
> +     returncodes = taskmaster.run_tasks(tasks, func, status,
> options=task_opts) +
> +     sys.exit(False in returncodes)
> diff --git a/pym/portage/emaint/modules/binhost/binhost.py
> b/pym/portage/emaint/modules/binhost/binhost.py
> index cf1213e..527b02f 100644
> --- a/pym/portage/emaint/modules/binhost/binhost.py
> +++ b/pym/portage/emaint/modules/binhost/binhost.py
> @@ -86,7 +86,9 @@ class BinhostHandler(object):
>               stale = set(metadata).difference(cpv_all)
>               for cpv in stale:
>                       errors.append("'%s' is not in the
> repository" % cpv)
> -             return errors
> +             if errors:
> +                     return (False, errors)
> +             return (True, None)
> 
>       def fix(self,  **kwargs):
>               onProgress = kwargs.get('onProgress', None)
> @@ -177,4 +179,4 @@ class BinhostHandler(object):
>                       if maxval == 0:
>                               maxval = 1
>                       onProgress(maxval, maxval)
> -             return None
> +             return (True, None)
> diff --git a/pym/portage/emaint/modules/config/config.py
> b/pym/portage/emaint/modules/config/config.py
> index dad024b..a05a3c2 100644
> --- a/pym/portage/emaint/modules/config/config.py
> +++ b/pym/portage/emaint/modules/config/config.py
> @@ -36,7 +36,8 @@ class CleanConfig(object):
>                       if onProgress:
>                               onProgress(maxval, i+1)
>                               i += 1
> -             return self._format_output(messages)
> +             msgs = self._format_output(messages)
> +             return (True, msgs)
> 
>       def fix(self, **kwargs):
>               onProgress = kwargs.get('onProgress', None)
> @@ -65,7 +66,8 @@ class CleanConfig(object):
>                               i += 1
>               if modified:
>                       writedict(configs, self.target)
> -             return self._format_output(messages, True)
> +             msgs = self._format_output(messages, True)
> +             return (True, msgs)
> 
>       def _format_output(self, messages=[], cleaned=False):
>               output = []
> diff --git a/pym/portage/emaint/modules/logs/logs.py
> b/pym/portage/emaint/modules/logs/logs.py
> index fe65cf5..028084a 100644
> --- a/pym/portage/emaint/modules/logs/logs.py
> +++ b/pym/portage/emaint/modules/logs/logs.py
> @@ -40,7 +40,6 @@ class CleanLogs(object):
>                               'NUM': int: number of days
>                               'pretend': boolean
>               """
> -             messages = []
>               num_of_days = None
>               pretend = False
>               if kwargs:
> @@ -70,10 +69,12 @@ class CleanLogs(object):
>                                       clean_cmd.remove("-delete")
> 
>               if not clean_cmd:
> -                     return []
> +                     return (True, None)
>               rval = self._clean_logs(clean_cmd, settings)
> -             messages += self._convert_errors(rval)
> -             return messages
> +             errors = self._convert_errors(rval)
> +             if errors:
> +                     return (False, errors)
> +             return (True, None)
> 
> 
>       @staticmethod
> diff --git a/pym/portage/emaint/modules/merges/merges.py
> b/pym/portage/emaint/modules/merges/merges.py
> index 8f677c2..416a725 100644
> --- a/pym/portage/emaint/modules/merges/merges.py
> +++ b/pym/portage/emaint/modules/merges/merges.py
> @@ -239,7 +239,9 @@ class MergesHandler(object):
>               for pkg, mtime in failed_pkgs.items():
>                       mtime_str = time.ctime(int(mtime))
>                       errors.append("'%s' failed to merge on '%s'"
> % (pkg, mtime_str))
> -             return errors
> +             if errors:
> +                     return (False, errors)
> +             return (True, None)
> 
> 
>       def fix(self, **kwargs):
> @@ -247,13 +249,13 @@ class MergesHandler(object):
>               module_output = kwargs.get('module_output', None)
>               failed_pkgs = self._failed_pkgs()
>               if not failed_pkgs:
> -                     return ['No failed merges found.']
> +                     return (True, ['No failed merges found.'])
> 
>               pkg_invalid_entries = set()
>               pkg_atoms = set()
>               self._get_pkg_atoms(failed_pkgs, pkg_atoms,
> pkg_invalid_entries) if pkg_invalid_entries:
> -                     return pkg_invalid_entries
> +                     return (False, pkg_invalid_entries)
> 
>               try:
>                       self._tracking_file.save(failed_pkgs)
> @@ -261,7 +263,7 @@ class MergesHandler(object):
>                       errors = ['Unable to save failed merges to
> tracking file: %s\n' % str(ex)]
>                       errors.append(', '.join(sorted(failed_pkgs)))
> -                     return errors
> +                     return (False, errors)
>               self._remove_failed_dirs(failed_pkgs)
>               results = self._emerge_pkg_atoms(module_output,
> pkg_atoms) # list any new failed merges
> @@ -276,12 +278,14 @@ class MergesHandler(object):
>                       if not vardb.cpv_exists(pkg_name):
>                               still_failed_pkgs[pkg] = mtime
>               self._tracking_file.save(still_failed_pkgs)
> -             return results
> +             if still_failed_pkgs:
> +                     return (False, results)
> +             return (True, results)
> 
> 
>       def purge(self, **kwargs):
>               """Attempt to remove previously saved tracking
> file.""" if not self._tracking_file.exists():
> -                     return ['Tracking file not found.']
> +                     return (True, ['Tracking file not found.'])
>               self._tracking_file.purge()
> -             return ['Removed tracking file.']
> +             return (True, ['Removed tracking file.'])
> diff --git a/pym/portage/emaint/modules/move/move.py
> b/pym/portage/emaint/modules/move/move.py
> index 41ca167..1c2636d 100644
> --- a/pym/portage/emaint/modules/move/move.py
> +++ b/pym/portage/emaint/modules/move/move.py
> @@ -123,7 +123,10 @@ class MoveHandler(object):
>                               errors.append("'%s' has outdated
> metadata" % cpv) if onProgress:
>                               onProgress(maxval, i+1)
> -             return errors
> +
> +             if errors:
> +                     return (False, errors)
> +             return (True, None)
> 
>       def fix(self,  **kwargs):
>               onProgress = kwargs.get('onProgress', None)
> @@ -156,7 +159,9 @@ class MoveHandler(object):
>               # Searching for updates in all the metadata is
> relatively slow, so this # is where the progress bar comes out of
> indeterminate mode. self._tree.dbapi.update_ents(allupdates,
> onProgress=onProgress)
> -             return errors
> +             if errors:
> +                     return (False, errors)
> +             return (True, None)
> 
>  class MoveInstalled(MoveHandler):
> 
> diff --git a/pym/portage/emaint/modules/resume/resume.py
> b/pym/portage/emaint/modules/resume/resume.py
> index 1bada52..0d65d41 100644
> --- a/pym/portage/emaint/modules/resume/resume.py
> +++ b/pym/portage/emaint/modules/resume/resume.py
> @@ -37,7 +37,7 @@ class CleanResume(object):
>                       finally:
>                               if onProgress:
>                                       onProgress(maxval, i+1)
> -             return messages
> +             return (True, messages)
> 
>       def fix(self,  **kwargs):
>               onProgress = kwargs.get('onProgress', None)
> @@ -56,3 +56,4 @@ class CleanResume(object):
>                                       onProgress(maxval, i+1)
>               if delete_count:
>                       mtimedb.commit()
> +             return (True, None)
> diff --git a/pym/portage/emaint/modules/sync/sync.py
> b/pym/portage/emaint/modules/sync/sync.py
> index 15d63e2..d867699 100644
> --- a/pym/portage/emaint/modules/sync/sync.py
> +++ b/pym/portage/emaint/modules/sync/sync.py
> @@ -127,8 +127,8 @@ class SyncRepos(object):
>                               % (bold(", ".join(repos))) +
> "\n   ...returning" ]
>                       if return_messages:
> -                             return msgs
> -                     return
> +                             return (False, msgs)
> +                     return (False, None)
>               return self._sync(selected, return_messages,
>                       emaint_opts=options)
> 
> @@ -211,8 +211,8 @@ class SyncRepos(object):
>                       msgs.append("Emaint sync, nothing to sync...
> returning") if return_messages:
>                               msgs.extend(self.rmessage([('None',
> os.EX_OK)], 'sync'))
> -                             return msgs
> -                     return
> +                             return (True, msgs)
> +                     return (True, None)
>               # Portage needs to ensure a sane umask for the files
> it creates. os.umask(0o22)
> 
> @@ -232,9 +232,14 @@ class SyncRepos(object):
>               sync_scheduler.wait()
>               retvals = sync_scheduler.retvals
>               msgs.extend(sync_scheduler.msgs)
> +             returncode = True
> 
>               if retvals:
>                       msgs.extend(self.rmessage(retvals, 'sync'))
> +                     for repo, returncode in retvals:
> +                             if returncode != os.EX_OK:
> +                                     returncode = False
> +                                     break
>               else:
>                       msgs.extend(self.rmessage([('None',
> os.EX_OK)], 'sync'))
> 
> @@ -244,6 +249,8 @@ class SyncRepos(object):
>                       rcode =
> sync_manager.perform_post_sync_hook('') if rcode:
>                               msgs.extend(self.rmessage([('None',
> rcode)], 'post-sync'))
> +                             if rcode != os.EX_OK:
> +                                     returncode = False
> 
>               # Reload the whole config.
>               portage._sync_mode = False
> @@ -254,8 +261,8 @@ class SyncRepos(object):
>                       self.emerge_config.opts)
> 
>               if return_messages:
> -                     return msgs
> -             return
> +                     return (returncode, msgs)
> +             return (returncode, None)
> 
> 
>       def _do_pkg_moves(self):
> @@ -355,7 +362,6 @@ class SyncScheduler(AsyncScheduler):
>               # that hooks will be called in a backward-compatible
> manner # even if all sync tasks have failed.
>               hooks_enabled = True
> -             returncode = task.returncode
>               if task.returncode == os.EX_OK:
>                       returncode, message, updatecache_flg,
> hooks_enabled = task.result if message:
> diff --git a/pym/portage/emaint/modules/world/world.py
> b/pym/portage/emaint/modules/world/world.py
> index 2c9dbff..ebc3adc 100644
> --- a/pym/portage/emaint/modules/world/world.py
> +++ b/pym/portage/emaint/modules/world/world.py
> @@ -65,7 +65,9 @@ class WorldHandler(object):
>                       errors += ["'%s' is not installed" % x for x
> in self.not_installed] else:
>                       errors.append(self.world_file + " could not
> be opened for reading")
> -             return errors
> +             if errors:
> +                     return (False, errors)
> +             return (True, None)
> 
>       def fix(self, **kwargs):
>               onProgress = kwargs.get('onProgress', None)
> @@ -83,7 +85,9 @@ class WorldHandler(object):
>                               except
> portage.exception.PortageException: errors.append("%s could not be
> opened for writing" % \ self.world_file)
> -                     return errors
> +                     if errors:
> +                             return (False, errors)
> +                     return (True, None)
>               finally:
>                       world_set.unlock()
> 
> diff --git a/pym/portage/tests/emerge/test_simple.py
> b/pym/portage/tests/emerge/test_simple.py
> index b1a2af5..5930f6c 100644
> --- a/pym/portage/tests/emerge/test_simple.py
> +++ b/pym/portage/tests/emerge/test_simple.py
> @@ -382,6 +382,7 @@ pkg_preinst() {
>                       "PORTAGE_PYTHON" : portage_python,
>                       "PORTAGE_REPOSITORIES" :
> settings.repositories.config_string(), "PORTAGE_TMPDIR" :
> portage_tmpdir,
> +                     "PORT_LOGDIR" : portage_tmpdir,
>                       "PYTHONDONTWRITEBYTECODE" :
> os.environ.get("PYTHONDONTWRITEBYTECODE", ""), "PYTHONPATH" :
> pythonpath, "__PORTAGE_TEST_PATH_OVERRIDE" : fake_bin,

merged :) thank you

-- 
Brian Dolbec <dolsen>


Reply via email to