diff options
Diffstat (limited to 'contrib/sanitize.py')
-rwxr-xr-x | contrib/sanitize.py | 556 |
1 files changed, 297 insertions, 259 deletions
diff --git a/contrib/sanitize.py b/contrib/sanitize.py index e38c28c13f..028b2cc535 100755 --- a/contrib/sanitize.py +++ b/contrib/sanitize.py @@ -1,290 +1,323 @@ #!/usr/bin/env python -# sanitize a bitbake file following the OpenEmbedded style guidelines -# see http://openembedded.org/wiki/StyleGuide -# (C) 2006 Cyril Romain <cyril.romain@gmail.com> -# MIT license +"""\ +Sanitize a bitbake file following the OpenEmbedded style guidelines, +see http://openembedded.org/wiki/StyleGuide -# TODO: -# - add the others OpenEmbedded variables commonly used -# ./ handle comments in .bb files -# - parse command arguments and print usage on misuse -# . prevent giving more than one .bb file in arguments -# - write result to a file -# - backup the original .bb file -# - make a diff and ask confirmation for patching ? -# - /!\ startswith('SOMETHING') is not taken into account due to the previous startswith('S'). -# - count rule breaks and displays them in the order frequence +(C) 2006 Cyril Romain <cyril.romain@gmail.com> +MIT license + +TODO: + - add the others OpenEmbedded variables commonly used: + - parse command arguments and print usage on misuse + . prevent giving more than one .bb file in arguments + - write result to a file + - backup the original .bb file + - make a diff and ask confirmation for patching ? + - do not use startswith only: + /!\ startswith('SOMETHING') is not taken into account due to the previous startswith('S'). + - count rule breaks and displays them in the order frequence +""" -from odict import OrderedDict import fileinput import string import re __author__ = "Cyril Romain <cyril.romain@gmail.com>" -__version__ = "$Revision: 0.3 $" +__version__ = "$Revision: 0.5 $" + +# The standard set of variables often found in .bb files in the preferred order +OE_vars = [ + 'DESCRIPTION', + 'AUTHOR', + 'HOMEPAGE', + 'SECTION', + 'PRIORITY', + 'MAINTAINER', + 'LICENSE', + 'DEPENDS', + 'RDEPENDS', + 'RRECOMMENDS', + 'RSUGGESTS', + 'PROVIDES', + 'RPROVIDES', + 'RCONFLICTS', + 'SRCDATE', + 'PV', + 'PR', + 'SRC_URI', + 'S', + 'GPE_TARBALL_SUFFIX', + 'inherit', + 'EXTRA_', + 'do_fetch', + 'do_unpack', + 'do_patch', + 'do_configure', + 'do_compile', + 'do_install', + 'do_package', + 'do_stage', + 'PACKAGE_ARCH', + 'PACKAGES', + 'FILES', + 'WORKDIR', + 'acpaths', + 'addhandler', + 'addtask', + 'bindir', + 'export', + 'headers', + 'include', + 'includedir', + 'python', + 'qtopiadir', + 'pkg_preins', + 'pkg_prerm', + 'pkg_postins', + 'pkg_postrm', + 'require', + 'sbindir', + 'basesysconfdir', + 'sysconfdir', + 'ALLOW_EMPTY', + 'ALTERNATIVE_NAME', + 'ALTERNATIVE_PATH', + 'ALTERNATIVE_LINK', + 'ALTERNATIVE_PRIORITY', + 'ALTNAME', + 'AMD_DRIVER_LABEL', + 'AMD_DRIVER_VERSION', + 'ANGSTROM_EXTRA_INSTALL', + 'APPDESKTOP', + 'APPIMAGE', + 'APPNAME', + 'APPTYPE', + 'APPWEB_BUILD', + 'APPWEB_HOST', + 'AR', + 'ARCH', + 'ARM_INSTRUCTION_SET', + 'ARM_MUTEX', + 'ART_CONFIG', + 'B', + 'BJAM_OPTS', + 'BJAM_TOOLS', + 'BONOBO_HEADERS', + 'BOOTSCRIPTS', + 'BROKEN', + 'BUILD_CPPFLAGS', + 'CFLAGS', + 'CCFLAGS', + 'CMDLINE', + 'COLLIE_MEMORY_SIZE', + 'COMPATIBLE_HOST', + 'COMPATIBLE_MACHINE', + 'COMPILE_HERMES', + 'CONFFILES', + 'CONFLICTS', + 'CORE_EXTRA_D', + 'CORE_PACKAGES_D', + 'CORE_PACKAGES_RD', + 'CPPFLAGS', + 'CVSDATE', + 'CXXFLAGS', + 'DEBIAN_NOAUTONAME', + 'DEBUG_APPS', + 'DEFAULT_PREFERENCE', + 'DB4_CONFIG', + 'EXCLUDE_FROM_SHLIBS', + 'EXCLUDE_FROM_WORLD', + 'FIXEDSRCDATE', + 'GLIBC_ADDONS', + 'GLIBC_EXTRA_OECONF', + 'GNOME_VFS_HEADERS', + 'HEADERS', + 'INHIBIT_DEFAULT_DEPS', + 'INITSCRIPT_PACKAGES', + 'INITSCRIPT_NAME', + 'INITSCRIPT_PARAMS', + 'IPKG_INSTALL', + 'KERNEL_IMAGETYPE', + 'KERNEL_IMAGEDEST', + 'KERNEL_OUTPUT', + 'KERNEL_RELEASE', + 'KERNEL_PRIORITY', + 'KERNEL_SOURCE', + 'KERNEL_SUFFIX', + 'KERNEL_VERSION', + 'K_MAJOR', + 'K_MICRO', + 'K_MINOR', + 'HHV', + 'KV', + 'LDFLAGS', + 'LD', + 'LD_SO', + 'LDLIBS', + 'LEAD_SONAME', + 'LIBTOOL', + 'LIBBDB_EXTRA', + 'LIBV', + 'MACHINE_ESSENTIAL_EXTRA_RDEPENDS', + 'MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS', + 'MACHINE_EXTRA_RDEPENDS', + 'MACHINE_EXTRA_RRECOMMENDS', + 'MACHINE_FEATURES', + 'MACHINE_TASKS', + 'MACHINE', + 'MACHTYPE', + 'MAKE_TARGETS', + 'MESSAGEUSER', + 'MESSAGEHOME', + 'MIRRORS', + 'MUTEX', + 'OE_QMAKE_INCDIR_QT', + 'OE_QMAKE_CXXFLAGS', + 'ORBIT_IDL_SRC', + 'PARALLEL_MAKE', + 'PAKCAGE_ARCH', + 'PCMCIA_MANAGER', + 'PKG_BASENAME', + 'PKG', + 'QEMU', + 'QMAKE_PROFILES', + 'QPEDIR', + 'QPF_DESCRIPTION', + 'QPF_PKGPATTERN', + 'QT_CONFIG_FLAGS', + 'QT_LIBRARY', + 'ROOTFS_POSTPROCESS_COMMAND', + 'RREPLACES', + 'TARGET_CFLAGS', + 'TARGET_CPPFLAGS', + 'TARGET_LDFLAGS', + 'UBOOT_MACHINE', + 'UCLIBC_BASE', + 'UCLIBC_PATCHES', + 'UNSLUNG_PACKAGES', + 'VIRTUAL_NAME', + 'XORG_PN', + 'XSERVER', + 'others' +] -# The ordered list of OpenEmbedded variables -OE_vars = OrderedDict([ - ('DESCRIPTION', []), - ('AUTHOR', []), - ('HOMEPAGE', []), - ('SECTION', []), - ('PRIORITY', []), - ('MAINTAINER', []), - ('LICENSE', []), - ('DEPENDS', []), - ('RDEPENDS', []), - ('RRECOMMENDS', []), - ('RSUGGESTS', []), - ('PROVIDES', []), - ('RPROVIDES', []), - ('RCONFLICTS', []), - ('SRCDATE', []), - ('PV', []), - ('PR', []), - ('SRC_URI', []), - ('S', []), - ('inherit', []), - ('EXTRA_', []), - ('do_fetch', []), - ('do_unpack', []), - ('do_patch', []), - ('do_configure', []), - ('do_compile', []), - ('do_install', []), - ('do_package', []), - ('do_stage', []), - ('PACKAGE_ARCH', []), - ('PACKAGES', []), - ('FILES', []), - ('WORKDIR', []), - ('acpaths', []), - ('addhandler', []), - ('addtask', []), - ('bindir', []), - ('export', []), - ('headers', []), - ('include', []), - ('includedir', []), - ('python', []), - ('qtopiadir', []), - ('pkg_postins', []), - ('pkg_postrm', []), - ('require', []), - ('sbindir', []), - ('basesysconfdir', []), - ('sysconfdir', []), - ('ALLOW_EMPTY', []), - ('ALTERNATIVE_LINK', []), - ('ALTERNATIVE_NAME', []), - ('ALTERNATIVE_PATH', []), - ('ALTERNATIVE_PRIORITY', []), - ('ALTNAME', []), - ('AMD_DRIVER_LABEL', []), - ('AMD_DRIVER_VERSION', []), - ('ANGSTROM_EXTRA_INSTALL', []), - ('APPDESKTOP', []), - ('APPIMAGE', []), - ('APPNAME', []), - ('APPTYPE', []), - ('APPWEB_BUILD', []), - ('APPWEB_HOST', []), - ('AR', []), - ('ARCH', []), - ('ARM_INSTRUCTION_SET', []), - ('ARM_MUTEX', []), - ('ART_CONFIG', []), - ('B', []), - ('BJAM_OPTS', []), - ('BJAM_TOOLS', []), - ('BONOBO_HEADERS', []), - ('BOOTSCRIPTS', []), - ('BROKEN', []), - ('BUILD_ALL_DEPS', []), - ('BUILD_CPPFLAGS', []), - ('CFLAGS', []), - ('CCFLAGS', []), - ('CMDLINE', []), - ('COLLIE_MEMORY_SIZE', []), - ('COMPATIBLE_HOST', []), - ('COMPATIBLE_MACHINE', []), - ('COMPILE_HERMES', []), - ('CONFFILES', []), - ('CONFLICTS', []), - ('CORE_EXTRA_D', []), - ('CORE_PACKAGES_D', []), - ('CORE_PACKAGES_RD', []), - ('CPPFLAGS', []), - ('CVSDATE', []), - ('CXXFLAGS', []), - ('DEBIAN_NOAUTONAME', []), - ('DEBUG_APPS', []), - ('DEFAULT_PREFERENCE', []), - ('DB4_CONFIG', []), - ('EXCLUDE_FROM_SHLIBS', []), - ('EXCLUDE_FROM_WORLD', []), - ('FIXEDSRCDATE', []), - ('GLIBC_ADDONS', []), - ('GLIBC_EXTRA_OECONF', []), - ('GNOME_VFS_HEADERS', []), - ('GPE_TARBALL_SUFFIX', []), - ('HEADERS', []), - ('INHIBIT_DEFAULT_DEPS', []), - ('INITSCRIPT_NAME', []), - ('INITSCRIPT_PACKAGES', []), - ('INITSCRIPT_PARAMS', []), - ('IPKG_INSTALL', []), - ('KERNEL_IMAGETYPE', []), - ('KERNEL_IMAGEDEST', []), - ('KERNEL_OUTPUT', []), - ('KERNEL_RELEASE', []), - ('KERNEL_PRIORITY', []), - ('KERNEL_SOURCE', []), - ('KERNEL_SUFFIX', []), - ('KERNEL_VERSION', []), - ('K_MAJOR', []), - ('K_MICRO', []), - ('K_MINOR', []), - ('HHV', []), - ('KV', []), - ('LDFLAGS', []), - ('LD', []), - ('LD_SO', []), - ('LDLIBS', []), - ('LEAD_SONAME', []), - ('LIBTOOL', []), - ('LIBBDB_EXTRA', []), - ('LIBV', []), - ('MACHINE', []), - ('MACHINE_ESSENTIAL_EXTRA_RDEPENDS', []), - ('MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS', []), - ('MACHINE_EXTRA_RDEPENDS', []), - ('MACHINE_EXTRA_RRECOMMENDS', []), - ('MACHINE_FEATURES', []), - ('MACHINE_TASKS', []), - ('MACHTYPE', []), - ('MAKE_TARGETS', []), - ('MESSAGEUSER', []), - ('MESSAGEHOME', []), - ('MIRRORS', []), - ('MUTEX', []), - ('OE_QMAKE_INCDIR_QT', []), - ('OE_QMAKE_CXXFLAGS', []), - ('ORBIT_IDL_SRC', []), - ('PARALLEL_MAKE', []), - ('PAKCAGE_ARCH', []), - ('PCMCIA_MANAGER', []), - ('PKG_BASENAME', []), - ('QEMU', []), - ('QMAKE_PROFILES', []), - ('QPEDIR', []), - ('QPF_DESCRIPTION', []), - ('QPF_PKGPATTERN', []), - ('QT_CONFIG_FLAGS', []), - ('QT_LIBRARY', []), - ('ROOTFS_POSTPROCESS_COMMAND', []), - ('RREPLACES', []), - ('TARGET_CFLAGS', []), - ('TARGET_CPPFLAGS', []), - ('TARGET_LDFLAGS', []), - ('UBOOT_MACHINE', []), - ('UCLIBC_BASE', []), - ('UCLIBC_PATCHES', []), - ('UNSLUNG_PACKAGES', []), - ('VIRTUAL_NAME', []), - ('XORG_PN', []), - ('XSERVER', []), - ('others', []) -]) +varRegexp = r'^([a-zA-Z_0-9${}-]*)([ \t]*)([+.:]?=[+.]?)([ \t]*)([^\t]+)' +routineRegexp = r'^([a-zA-Z0-9_ ${}-]+?)\(' -varRegexp = r'^([A-Z_0-9]*)([ \t]*?)([+.:]?=[+.]?)([ \t]*?)("[^"]*["\\]?)' -routineRegexp = r'^([a-zA-Z0-9_ -]+?)\(' +# Variables seen in the processed .bb +seen_vars = {} +for v in OE_vars: + seen_vars[v] = [] -# Style guideline #0: No spaces are allowed at the beginning of lines that define a variable or a do_ routine -def check_rule0(line): +# _Format guideline #0_: +# No spaces are allowed at the beginning of lines that define a variable or +# a do_ routine +def respect_rule0(line): return line.lstrip()==line -def follow_rule0(line): +def conformTo_rule0(line): return line.lstrip() -# Style guideline #1: No spaces are allowed behind the line continuation symbol '\' -def check_rule1(line): +# _Format guideline #1_: +# No spaces are allowed behind the line continuation symbol '\' +def respect_rule1(line): if line.rstrip().endswith('\\'): return line.endswith('\\') else: return True -def follow_rule1(line): +def conformTo_rule1(line): return line.rstrip() -# Style guideline #2: Tabs should not be used (use spaces instead). -def check_rule2(line): +# _Format guideline #2_: +# Tabs should not be used (use spaces instead). +def respect_rule2(line): return line.count('\t')==0 -def follow_rule2(line): +def conformTo_rule2(line): return line.expandtabs() -# Style guideline #3: Comments inside bb files are allowed using the '#' character at the beginning of a line. -def check_rule3(line): +# _Format guideline #3_: +# Comments inside bb files are allowed using the '#' character at the +# beginning of a line. +def respect_rule3(line): if line.lstrip().startswith('#'): return line.startswith('#') else: return True -def follow_rule3(line): +def conformTo_rule3(line): return line.lstrip() -# Style guideline #4: Use quotes on the right hand side of assignments: FOO = "BAR" -def check_rule4(line): - return re.match(varRegexp, line) is not None -def follow_rule4(line): - return follow_rule5(line) +# _Format guideline #4_: +# Use quotes on the right hand side of assignments FOO = "BAR" +def respect_rule4(line): + r = re.search(varRegexp, line) + if r is not None: + r2 = re.search(r'("?)([^"\\]*)(["\\]?)', r.group(5)) + # do not test for None it because always match + return r2.group(1)=='"' and r2.group(3)!='' + return False +def conformTo_rule4(line): + r = re.search(varRegexp, line) + return ''.join([r.group(1), ' ', r.group(3), ' "', r.group(5), r.group(5).endswith('"') and '' or '"']) -# Style guideline #5: The correct spacing for a variable is FOO = "BAR". -def check_rule5(line): +# _Format guideline #5_: +# The correct spacing for a variable is FOO = "BAR". +def respect_rule5(line): r = re.search(varRegexp, line) return r is not None and r.group(2)==" " and r.group(4)==" " -def follow_rule5(line): +def conformTo_rule5(line): r = re.search(varRegexp, line) return ''.join([r.group(1), ' ', r.group(3), ' ', r.group(5)]) -# Style guideline #6: Don't use spaces or tabs on empty lines -def check_rule6(line): +# _Format guideline #6_: +# Don't use spaces or tabs on empty lines +def respect_rule6(line): return not line.isspace() or line=="\n" -def follow_rule6(line): +def conformTo_rule6(line): return "" -# Style guideline #7: Indentation of multiline variables such as SRC_URI is desireable. -def check_rule7(line): +# _Format guideline #7_: +# Indentation of multiline variables such as SRC_URI is desireable. +def respect_rule7(line): return True -def follow_rule7(line): +def conformTo_rule7(line): return line rules = ( - (check_rule0, follow_rule0, "No spaces are allowed at the beginning of lines that define a variable or a do_ routine"), - (check_rule1, follow_rule1, "No spaces are allowed behind the line continuation symbol '\\'"), - (check_rule2, follow_rule2, "Tabs should not be used (use spaces instead)"), - (check_rule3, follow_rule3, "Comments inside bb files are allowed using the '#' character at the beginning of a line"), - (check_rule4, follow_rule4, "Use quotes on the right hand side of assignments: FOO = \"BAR\""), - (check_rule5, follow_rule5, "The correct spacing for a variable is FOO = \"BAR\""), - (check_rule6, follow_rule6, "Don't use spaces or tabs on empty lines"), - (check_rule7, follow_rule7, "Indentation of multiline variables such as SRC_URI is desireable"), + (respect_rule0, conformTo_rule0, "No spaces are allowed at the beginning of lines that define a variable or a do_ routine"), + (respect_rule1, conformTo_rule1, "No spaces are allowed behind the line continuation symbol '\\'"), + (respect_rule2, conformTo_rule2, "Tabs should not be used (use spaces instead)"), + (respect_rule3, conformTo_rule3, "Comments inside bb files are allowed using the '#' character at the beginning of a line"), + (respect_rule4, conformTo_rule4, "Use quotes on the right hand side of assignments FOO = \"BAR\""), + (respect_rule5, conformTo_rule5, "The correct spacing for a variable is FOO = \"BAR\""), + (respect_rule6, conformTo_rule6, "Don't use spaces or tabs on empty lines"), + (respect_rule7, conformTo_rule7, "Indentation of multiline variables such as SRC_URI is desireable"), ) +# Function to check that a line respects a rule. If not, it tries to conform +# the line to the rule. Reminder or Disgression message are dump accordingly. def follow_rule(i, line): oldline = line + # if the line does not respect the rule if not rules[i][0](line): + # try to conform it to the rule line = rules[i][1](line) + # if the line still does not respect the rule if not rules[i][0](line): - print "## Rule %d disgression: on this line: " % i, line - print "## Warning: ", rules[i][2] + # this is a rule disgression + print "## Disgression: ", rules[i][2], " in:", oldline else: + # just remind user about his/her errors print "## Reminder: ", rules[i][2], " in :", oldline return line if __name__ == "__main__": - # -- retrieves lines of the .bb file -- + # -- retrieves the lines of the .bb file -- lines = [] for line in fileinput.input(): + # use 'if True' to warn user about all the rule he/she breaks + # use 'if False' to conform to rules{2,1,6} without warnings if True: lines.append(line) else: @@ -301,12 +334,14 @@ if __name__ == "__main__": in_routine = False commentBloc = [] olines = [] - unknownVar = [] for line in lines: + originalLine = line + # rstrip line to remove line breaks characters line = line.rstrip() line = follow_rule(2, line) line = follow_rule(1, line) line = follow_rule(6, line) + # ignore empty lines if line.isspace() or line is '': # flush comments into the olines @@ -314,7 +349,8 @@ if __name__ == "__main__": commentBloc = [] continue - if line.startswith('}'): in_routine=False + if line.startswith('}'): + in_routine=False keep = line.endswith('\\') or in_routine # handles commented lines @@ -325,45 +361,47 @@ if __name__ == "__main__": commentBloc.append(line) continue - if OE_vars.has_key(var): - for c in commentBloc: - OE_vars[var].append(c) + if seen_vars.has_key(var): + for c in commentBloc: + seen_vars[var].append(c) commentBloc = [] - OE_vars[var].append(line) + seen_vars[var].append(line) else: - varexist = False for k in OE_vars: if line.startswith(k): - line = follow_rule(0, line) - varexist = True - if re.match(routineRegexp, line) is not None: - in_routine=True - elif re.match(varRegexp, line) is not None: - line = follow_rule(4, line) - line = follow_rule(5, line) - for c in commentBloc: - OE_vars[k].append(c) - commentBloc = [] - OE_vars[k].append(line) - var = (keep==True or in_routine==True) and k or "" + var = k break - if not varexist: - s = string.split(line)[0].rstrip().lstrip() - if s not in unknownVar: - unknownVar.append(s) + if re.match(routineRegexp, line) is not None: + in_routine=True + line = follow_rule(0, line) + elif re.match(varRegexp, line) is not None: + line = follow_rule(0, line) + line = follow_rule(4, line) + line = follow_rule(5, line) + if var == "": if not in_routine: - print "## Warning: unknown variable/routine \"%s\"" % line - OE_vars['others'].append(line) + print "## Warning: unknown variable/routine \"%s\"" % originalLine + var = 'others' + for c in commentBloc: + seen_vars[var].append(c) + commentBloc = [] + seen_vars[var].append(line) if not keep and not in_routine: var = "" - # -- prepare the sanitized .bb file -- - #for k in OE_vars: print k, OE_vars[k] + # -- dump the sanitized .bb file -- addEmptyLine = False + # write comments that are not related to variables nor routines + for l in olines: + olines.append(l) + # write variables and routines + previourVarPrefix = "unknown" for k in OE_vars: if k=='SRC_URI': addEmptyLine = True - if OE_vars[k] != []: - if addEmptyLine: olines.append("") - for l in OE_vars[k]: + if seen_vars[k] != []: + if addEmptyLine and not k.startswith(previourVarPrefix): + olines.append("") + for l in seen_vars[k]: olines.append(l) + previourVarPrefix = k.split('_')[0]=='' and "unknown" or k.split('_')[0] for line in olines: print line - #for i in unknownVar: print i, '\n' + |