From e390c3b9e880f209511d805ea94aeb3e971d0ff7 Mon Sep 17 00:00:00 2001 From: Andreas Grapentin Date: Sun, 7 Apr 2019 08:45:50 +0200 Subject: adding a fixer to the linter --- parabola-repolint.conf.example | 5 ++++ parabola_repolint/__main__.py | 5 ++++ parabola_repolint/fixer.py | 37 +++++++++++++++++++++++++ parabola_repolint/linter.py | 29 +++++++++++++------ parabola_repolint/linter_checks/dependencies.py | 8 ++++++ 5 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 parabola_repolint/fixer.py diff --git a/parabola-repolint.conf.example b/parabola-repolint.conf.example index 4a12d19..52d7a77 100644 --- a/parabola-repolint.conf.example +++ b/parabola-repolint.conf.example @@ -5,6 +5,11 @@ parabola: abslibre: git://git.parabola.nu/abslibre/abslibre.git mirror: rsync://repo.parabola.nu:875/repos/ +fixhooks: + enabled: no + scriptroot: /usr/lib/parabola-repolint/fixhooks/ + abslibre: null + notify: etherpad_url: https://pad.riseup.net/p/ParabolaRepolint smtp_host: null diff --git a/parabola_repolint/__main__.py b/parabola_repolint/__main__.py index 7900fc9..83ffd01 100644 --- a/parabola_repolint/__main__.py +++ b/parabola_repolint/__main__.py @@ -9,6 +9,7 @@ import sys from parabola_repolint.config import CONFIG from parabola_repolint.linter import Linter +from parabola_repolint.fixer import Fixer from parabola_repolint.repocache import RepoCache from parabola_repolint.notify import etherpad_replace, send_mail, write_log @@ -74,6 +75,10 @@ def checked_main(args): res = linter.format() logging.info(res) + if CONFIG.fixhooks.enabled: + fixer = Fixer(cache) + fixer.run_fixes(linter.triggered_checks) + if CONFIG.notify.etherpad_url: etherpad_replace(res) if CONFIG.notify.smtp_host: diff --git a/parabola_repolint/fixer.py b/parabola_repolint/fixer.py new file mode 100644 index 0000000..fc0eb5a --- /dev/null +++ b/parabola_repolint/fixer.py @@ -0,0 +1,37 @@ +''' +this module provides the linter issue autofixer +''' + +import os +import sh +import logging + +from parabola_repolint.config import CONFIG + + +class Fixer(): + ''' the master fixer class ''' + + def __init__(self, repo_cache): + ''' constructor ''' + self._cache = repo_cache + + def run_fixes(self, checks): + ''' run the fixes for the given issues ''' + for check in checks: + base_path = os.path.join(CONFIG.fixhooks.scriptroot, str(check)) + if not os.path.exists(base_path): + continue + + for issue in check.issues: + fixbase = check.fixhook_base(issue) + fixargs = check.fixhook_args(issue) + + path = os.path.join(base_path, fixbase + '.sh') + if not os.path.exists(path): + continue + + try: + sh.bash(path, fixbase, fixargs, _cwd=CONFIG.fixhooks.abslibre) + except sh.ErrorReturnCode: + logging.exception('%s fixhook failed for %s (%s)', check, fixbase, ', '.join(fixargs)) diff --git a/parabola_repolint/linter.py b/parabola_repolint/linter.py index 3bc4bed..4cd418f 100644 --- a/parabola_repolint/linter.py +++ b/parabola_repolint/linter.py @@ -39,6 +39,14 @@ class LinterCheckBase(metaclass=LinterCheckMeta): res.append(' ' + issue[0] % issue[1:]) return "\n".join(sorted(res)) + def fixhook_base(self, issue): + ''' produce the default fixhook base path ''' + return issue[1] + + def fixhook_args(self, issue): + ''' produce the default fixhook arguments ''' + return issue[2:] + def __repr__(self): ''' produce a string representation of the check ''' return str(type(self)) @@ -163,6 +171,11 @@ class Linter(): except LinterIssue as i: check.issues.append(i.args) + @property + def triggered_checks(self): + ''' produce a list of all checks with issues ''' + return [ check for check in self._enabled_checks if check.issues ] + def format(self): ''' return a formatted string of the linter issues ''' now = self._end_time.strftime("%Y-%m-%d %H:%M:%S") @@ -173,11 +186,10 @@ Generated by parabola-repolint on %s at %s ============================================================================== ''' % (socket.gethostname(), now) - for check in self._enabled_checks: - if check.issues: - header = '%s:\n%s' % (check.header, '-' * (len(check.header) + 1)) - out += '\n\n\n%s\n%s\nissues:\n' % (header, check.__doc__) - out += check.format() + for check in self.triggered_checks: + header = '%s:\n%s' % (check.header, '-' * (len(check.header) + 1)) + out += '\n\n\n%s\n%s\nissues:\n' % (header, check.__doc__) + out += check.format() return out def short_format(self): @@ -185,9 +197,8 @@ Generated by parabola-repolint on %s at %s now = self._end_time.strftime("%Y-%m-%d %H:%M:%S") out = 'repolint digest at %s' % now - for check in self._enabled_checks: - if check.issues: - out += '\n %s: %i' % (check, len(check.issues)) + for check in self.triggered_checks: + out += '\n %s: %i' % (check, len(check.issues)) out += '\ntotal issues: %i' % self.total_issues return out @@ -196,7 +207,7 @@ Generated by parabola-repolint on %s at %s def total_issues(self): ''' produce the total number of found issues ''' res = 0 - for check in self._enabled_checks: + for check in self.triggered_checks: res += len(check.issues) return res diff --git a/parabola_repolint/linter_checks/dependencies.py b/parabola_repolint/linter_checks/dependencies.py index 08b4871..0d261e0 100644 --- a/parabola_repolint/linter_checks/dependencies.py +++ b/parabola_repolint/linter_checks/dependencies.py @@ -89,6 +89,14 @@ class UnsatisfiableDepends(LinterCheckBase): if missing: raise LinterIssue('%s (%s)', pkgentry, ','.join(missing)) + def fixhook_base(self, issue): + ''' produce a custom fixhook base ''' + return '/'.join(str(issue[1]).split('/')[::2]) + + def fixhook_args(self, issue): + ''' produce custom fixhook arguments ''' + return [ str(issue[1]).split('/')[1], *issue[2].split(',') ] + class UnsatisfiableMakedepends(LinterCheckBase): ''' -- cgit v1.2.2