refactored MenuXDGCheck (rpm-software-management#225)
This commit is contained in:
parent
eb352739e5
commit
0b3add2728
|
@ -11,12 +11,14 @@ from pathlib import Path
|
|||
import subprocess
|
||||
|
||||
from rpmlint.checks.AbstractCheck import AbstractFilesCheck
|
||||
from rpmlint.pkg import is_utf8
|
||||
|
||||
STANDARD_BIN_DIRS = ('/bin', '/sbin', '/usr/bin', '/usr/sbin')
|
||||
|
||||
|
||||
class MenuXDGCheck(AbstractFilesCheck):
|
||||
"""
|
||||
Check whether MenuXDG files installed by a package are valid.
|
||||
"""
|
||||
def __init__(self, config, output):
|
||||
# desktop file need to be in $XDG_DATA_DIRS
|
||||
# $ echo $XDG_DATA_DIRS/applications
|
||||
|
@ -24,44 +26,19 @@ class MenuXDGCheck(AbstractFilesCheck):
|
|||
super().__init__(config, output, r'(?:/usr|/etc/opt|/opt/.*)/share/applications/.*\.desktop$')
|
||||
|
||||
def parse_desktop_file(self, pkg, root, f, filename):
|
||||
"""
|
||||
Check the structure of a desktop file.
|
||||
"""
|
||||
cfp = cfgparser.RawConfigParser()
|
||||
try:
|
||||
with codecs.open(f, encoding='utf-8') as inputf:
|
||||
cfp.read_file(inputf, filename)
|
||||
except cfgparser.DuplicateSectionError as e:
|
||||
self.output.add_info('E',
|
||||
pkg, 'desktopfile-duplicate-section', filename,
|
||||
'[%s]' % e.section)
|
||||
except cfgparser.MissingSectionHeaderError:
|
||||
self.output.add_info('E', pkg, 'desktopfile-missing-header', filename)
|
||||
except cfgparser.Error as e:
|
||||
# Only in Python >= 3.2
|
||||
if (hasattr(cfgparser, 'DuplicateOptionError') and
|
||||
isinstance(e, cfgparser.DuplicateOptionError)):
|
||||
self.output.add_info('E', pkg, 'desktopfile-duplicate-option', filename,
|
||||
'[%s]/%s' % (e.section, e.option))
|
||||
else:
|
||||
self.output.add_info('W', pkg, 'invalid-desktopfile', filename,
|
||||
e.message.partition(':')[0])
|
||||
self._handle_parser_error(pkg, filename, e)
|
||||
except UnicodeDecodeError as e:
|
||||
self.output.add_info('W', pkg, 'invalid-desktopfile', filename, 'Unicode error: %s' % (e))
|
||||
self.output.add_info('E', pkg, 'non-utf8-desktopfile', filename, f'Unicode error: {e}')
|
||||
else:
|
||||
binary = None
|
||||
if cfp.has_option('Desktop Entry', 'Exec'):
|
||||
binary = cfp.get('Desktop Entry', 'Exec').partition(' ')[0]
|
||||
if binary:
|
||||
found = False
|
||||
if binary.startswith('/'):
|
||||
found = Path(root + binary).exists()
|
||||
else:
|
||||
for i in STANDARD_BIN_DIRS:
|
||||
if Path(root + i + '/' + binary).exists():
|
||||
# no need to check if the binary is +x, rpmlint does it
|
||||
# in another place
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
self.output.add_info('W', pkg, 'desktopfile-without-binary', filename, binary)
|
||||
self._has_binary(pkg, root, cfp, filename)
|
||||
|
||||
def check_file(self, pkg, filename):
|
||||
root = pkg.dirName()
|
||||
|
@ -77,7 +54,45 @@ class MenuXDGCheck(AbstractFilesCheck):
|
|||
error_printed = True
|
||||
if not error_printed:
|
||||
self.output.add_info('E', pkg, 'invalid-desktopfile', filename)
|
||||
if not is_utf8(f):
|
||||
self.output.add_info('E', pkg, 'non-utf8-desktopfile', filename)
|
||||
|
||||
self.parse_desktop_file(pkg, root, f, filename)
|
||||
|
||||
def _handle_parser_error(self, pkg, filename, e):
|
||||
"""
|
||||
Determine what to do with a caught configparser error.
|
||||
"""
|
||||
# I would love to use switch, however, each warning is printed differently
|
||||
if (isinstance(e, cfgparser.MissingSectionHeaderError)):
|
||||
self.output.add_info('E', pkg, 'desktopfile-missing-header', filename)
|
||||
elif (isinstance(e, cfgparser.DuplicateSectionError)):
|
||||
self.output.add_info('E', pkg, 'desktopfile-duplicate-section', filename,
|
||||
'[{e.section}]')
|
||||
elif (isinstance(e, cfgparser.DuplicateOptionError)):
|
||||
self.output.add_info('E', pkg, 'desktopfile-duplicate-option', filename,
|
||||
'[{e.section}]/{e.option}')
|
||||
else:
|
||||
self.output.add_info('E', pkg, 'invalid-desktopfile', filename,
|
||||
e.message.partition(':')[0])
|
||||
|
||||
def _has_binary(self, pkg, root, cfp, filename):
|
||||
"""
|
||||
Check whether there is a binarry assigned to the desktop file.
|
||||
|
||||
Needs configparser instance, it is assumed to be called in parse_desktop_file.
|
||||
"""
|
||||
binary = None
|
||||
if cfp.has_option('Desktop Entry', 'Exec'):
|
||||
binary = cfp.get('Desktop Entry', 'Exec').partition(' ')[0]
|
||||
# If there is no binary mentioned it is OK
|
||||
if not binary:
|
||||
return
|
||||
if binary.startswith('/'):
|
||||
if (Path(root + binary).exists()):
|
||||
return
|
||||
else:
|
||||
for i in STANDARD_BIN_DIRS:
|
||||
if Path(root + i + '/' + binary).exists():
|
||||
# no need to check if the binary is +x, rpmlint does it
|
||||
# in another place
|
||||
return
|
||||
self.output.add_info('W', pkg, 'desktopfile-without-binary', filename, binary)
|
||||
|
|
Loading…
Reference in New Issue