|
@@ -0,0 +1,168 @@
|
|
|
+#!/usr/bin/env python
|
|
|
+
|
|
|
+# documentation.conf update script
|
|
|
+#
|
|
|
+# Author: Paul Eggleton <paul.eggleton@linux.intel.com>
|
|
|
+#
|
|
|
+# Copyright (C) 2015 Intel Corporation
|
|
|
+#
|
|
|
+# This program is free software; you can redistribute it and/or modify
|
|
|
+# it under the terms of the GNU General Public License version 2 as
|
|
|
+# published by the Free Software Foundation.
|
|
|
+#
|
|
|
+# This program is distributed in the hope that it will be useful,
|
|
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
+# GNU General Public License for more details.
|
|
|
+#
|
|
|
+# You should have received a copy of the GNU General Public License along
|
|
|
+# with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
+
|
|
|
+
|
|
|
+import sys
|
|
|
+import os
|
|
|
+import argparse
|
|
|
+import re
|
|
|
+from lxml import etree
|
|
|
+import logging
|
|
|
+
|
|
|
+def logger_create(name):
|
|
|
+ logger = logging.getLogger(name)
|
|
|
+ loggerhandler = logging.StreamHandler()
|
|
|
+ loggerhandler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
|
|
|
+ logger.addHandler(loggerhandler)
|
|
|
+ logger.setLevel(logging.INFO)
|
|
|
+ return logger
|
|
|
+logger = logger_create('docconfupdater')
|
|
|
+
|
|
|
+def main():
|
|
|
+ parser = argparse.ArgumentParser(description="documentation.conf updater")
|
|
|
+ parser.add_argument('basepath', help='Path to OE-Core base directory')
|
|
|
+ parser.add_argument('-q', '--quiet', help='Print only warnings/errors', action='store_true')
|
|
|
+
|
|
|
+ args = parser.parse_args()
|
|
|
+
|
|
|
+ if args.quiet:
|
|
|
+ logger.setLevel(logging.WARN)
|
|
|
+
|
|
|
+ if not os.path.isdir(args.basepath):
|
|
|
+ logger.error('Specified base path %s not found')
|
|
|
+ return 1
|
|
|
+
|
|
|
+ doc_conf = os.path.join(args.basepath, 'meta', 'conf', 'documentation.conf')
|
|
|
+ if not os.path.exists(doc_conf):
|
|
|
+ logger.error('Unable to find %s' % doc_conf)
|
|
|
+ return 1
|
|
|
+
|
|
|
+ allowed_flags = ['doc']
|
|
|
+ flag_re = re.compile(r'\[(.+?)\]')
|
|
|
+
|
|
|
+ infos = {}
|
|
|
+ tree = etree.parse('ref-manual/ref-variables.xml')
|
|
|
+ root = tree.getroot()
|
|
|
+ for glossary in root.findall('glossary'):
|
|
|
+ for glossdiv in glossary.findall('glossdiv'):
|
|
|
+ for glossentry in glossdiv.findall('glossentry'):
|
|
|
+ info = glossentry.find('info')
|
|
|
+ if info is not None:
|
|
|
+ infoline = ' '.join(info.text.split())
|
|
|
+ infolinesplit = infoline.split('=', 1)
|
|
|
+ if len(infoline) < 2:
|
|
|
+ logger.warn('Invalid info line (no = character), ignoring: %s' % infoline)
|
|
|
+ continue
|
|
|
+ flags = flag_re.findall(infolinesplit[0])
|
|
|
+ if not flags:
|
|
|
+ logger.warn('Invalid info line (no varflag), ignoring: %s' % infoline)
|
|
|
+ continue
|
|
|
+ for flag in flags:
|
|
|
+ if flag not in allowed_flags:
|
|
|
+ logger.warn('Invalid info line (varflag %s not in allowed list), ignoring: %s' % (flag, infoline))
|
|
|
+ continue
|
|
|
+ infos[infolinesplit[0].rstrip()] = infolinesplit[1].lstrip()
|
|
|
+
|
|
|
+ if not infos:
|
|
|
+ logger.error('ERROR: Unable to find any info tags in the glossary')
|
|
|
+ return 1
|
|
|
+
|
|
|
+ def sortkey(key):
|
|
|
+ # Underscores sort undesirably, so replace them
|
|
|
+ return key.split('[')[0].replace('_', '-')
|
|
|
+
|
|
|
+ changed = False
|
|
|
+ lines = []
|
|
|
+ invars = False
|
|
|
+ lastletter = None
|
|
|
+ added = []
|
|
|
+ with open(doc_conf, 'r') as dcf:
|
|
|
+ for line in dcf:
|
|
|
+ if not invars:
|
|
|
+ if line.startswith('#') and 'DESCRIPTIONS FOR VARIABLES' in line:
|
|
|
+ invars = True
|
|
|
+ elif not line.startswith('#'):
|
|
|
+ linesplit = line.split('=', 1)
|
|
|
+ if len(linesplit) > 1:
|
|
|
+ key = linesplit[0].rstrip()
|
|
|
+ lastletter = key[0]
|
|
|
+ # Find anything in the dict that should come before the current key
|
|
|
+ for dkey in sorted(infos.keys()):
|
|
|
+ if sortkey(dkey) < sortkey(key):
|
|
|
+ lines.append('%s = %s\n' % (dkey, infos[dkey]))
|
|
|
+ added.append(dkey)
|
|
|
+ del infos[dkey]
|
|
|
+ changed = True
|
|
|
+ newvalue = infos.get(key, None)
|
|
|
+ if newvalue:
|
|
|
+ del infos[key]
|
|
|
+ if newvalue != linesplit[1].strip():
|
|
|
+ lines.append('%s = %s\n' % (key, newvalue))
|
|
|
+ changed = True
|
|
|
+ continue
|
|
|
+ elif key in added:
|
|
|
+ # We already added a new value for this key, so skip it
|
|
|
+ continue
|
|
|
+ elif lastletter:
|
|
|
+ # Ensure we write out anything anything left over for this letter
|
|
|
+ for dkey in sorted(infos.keys()):
|
|
|
+ if dkey[0] == lastletter:
|
|
|
+ lines.append('%s = %s\n' % (dkey, infos[dkey]))
|
|
|
+ del infos[dkey]
|
|
|
+ changed = True
|
|
|
+ elif dkey[0] > lastletter:
|
|
|
+ # List is sorted, so we're done
|
|
|
+ break
|
|
|
+ lastletter = None
|
|
|
+ lines.append(line)
|
|
|
+
|
|
|
+ if not invars:
|
|
|
+ logger.error('ERROR: Unable to find variables section in documentation.conf')
|
|
|
+ return 1
|
|
|
+
|
|
|
+ if infos:
|
|
|
+ changed = True
|
|
|
+ # Write out anything left over
|
|
|
+ lines.append('\n\n')
|
|
|
+ for key in sorted(infos.keys()):
|
|
|
+ lines.append('%s = %s\n' % (key, infos[key]))
|
|
|
+
|
|
|
+ if changed:
|
|
|
+ logger.info('Updating %s' % doc_conf)
|
|
|
+ with open(doc_conf, 'w') as dcf:
|
|
|
+ for line in lines:
|
|
|
+ dcf.write(line)
|
|
|
+ else:
|
|
|
+ logger.info('No changes required')
|
|
|
+
|
|
|
+ return 0
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ try:
|
|
|
+ ret = main()
|
|
|
+ except Exception:
|
|
|
+ ret = 1
|
|
|
+ import traceback
|
|
|
+ traceback.print_exc(5)
|
|
|
+ sys.exit(ret)
|
|
|
+
|
|
|
+
|