blob: 3f8d28009390e66b6a46b137b87c46b020586da3 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#!/usr/bin/env python
2
3# documentation.conf update script
4#
5# Author: Paul Eggleton <paul.eggleton@linux.intel.com>
6#
7# Copyright (C) 2015 Intel Corporation
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License version 2 as
11# published by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License along
19# with this program; if not, write to the Free Software Foundation, Inc.,
20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22
23import sys
24import os
25import argparse
26import re
27from lxml import etree
28import logging
29
30def logger_create(name):
31 logger = logging.getLogger(name)
32 loggerhandler = logging.StreamHandler()
33 loggerhandler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
34 logger.addHandler(loggerhandler)
35 logger.setLevel(logging.INFO)
36 return logger
37logger = logger_create('docconfupdater')
38
39def main():
40 parser = argparse.ArgumentParser(description="documentation.conf updater")
41 parser.add_argument('basepath', help='Path to OE-Core base directory')
42 parser.add_argument('-q', '--quiet', help='Print only warnings/errors', action='store_true')
43
44 args = parser.parse_args()
45
46 if args.quiet:
47 logger.setLevel(logging.WARN)
48
49 if not os.path.isdir(args.basepath):
50 logger.error('Specified base path %s not found')
51 return 1
52
53 doc_conf = os.path.join(args.basepath, 'meta', 'conf', 'documentation.conf')
54 if not os.path.exists(doc_conf):
55 logger.error('Unable to find %s' % doc_conf)
56 return 1
57
58 allowed_flags = ['doc']
59 flag_re = re.compile(r'\[(.+?)\]')
60
61 infos = {}
62 tree = etree.parse('ref-manual/ref-variables.xml')
63 root = tree.getroot()
64 for glossary in root.findall('glossary'):
65 for glossdiv in glossary.findall('glossdiv'):
66 for glossentry in glossdiv.findall('glossentry'):
67 info = glossentry.find('info')
68 if info is not None:
69 infoline = ' '.join(info.text.split())
70 infolinesplit = infoline.split('=', 1)
71 if len(infoline) < 2:
72 logger.warn('Invalid info line (no = character), ignoring: %s' % infoline)
73 continue
74 flags = flag_re.findall(infolinesplit[0])
75 if not flags:
76 logger.warn('Invalid info line (no varflag), ignoring: %s' % infoline)
77 continue
78 for flag in flags:
79 if flag not in allowed_flags:
80 logger.warn('Invalid info line (varflag %s not in allowed list), ignoring: %s' % (flag, infoline))
81 continue
82 infos[infolinesplit[0].rstrip()] = infolinesplit[1].lstrip()
83
84 if not infos:
85 logger.error('ERROR: Unable to find any info tags in the glossary')
86 return 1
87
88 def sortkey(key):
89 # Underscores sort undesirably, so replace them
90 return key.split('[')[0].replace('_', '-')
91
92 changed = False
93 lines = []
94 invars = False
95 lastletter = None
96 added = []
97 with open(doc_conf, 'r') as dcf:
98 for line in dcf:
99 if not invars:
100 if line.startswith('#') and 'DESCRIPTIONS FOR VARIABLES' in line:
101 invars = True
102 elif not line.startswith('#'):
103 linesplit = line.split('=', 1)
104 if len(linesplit) > 1:
105 key = linesplit[0].rstrip()
106 lastletter = key[0]
107 # Find anything in the dict that should come before the current key
108 for dkey in sorted(infos.keys()):
109 if sortkey(dkey) < sortkey(key):
110 lines.append('%s = %s\n' % (dkey, infos[dkey]))
111 added.append(dkey)
112 del infos[dkey]
113 changed = True
114 newvalue = infos.get(key, None)
115 if newvalue:
116 del infos[key]
117 if newvalue != linesplit[1].strip():
118 lines.append('%s = %s\n' % (key, newvalue))
119 changed = True
120 continue
121 elif key in added:
122 # We already added a new value for this key, so skip it
123 continue
124 elif lastletter:
125 # Ensure we write out anything anything left over for this letter
126 for dkey in sorted(infos.keys()):
127 if dkey[0] == lastletter:
128 lines.append('%s = %s\n' % (dkey, infos[dkey]))
129 del infos[dkey]
130 changed = True
131 elif dkey[0] > lastletter:
132 # List is sorted, so we're done
133 break
134 lastletter = None
135 lines.append(line)
136
137 if not invars:
138 logger.error('ERROR: Unable to find variables section in documentation.conf')
139 return 1
140
141 if infos:
142 changed = True
143 # Write out anything left over
144 lines.append('\n\n')
145 for key in sorted(infos.keys()):
146 lines.append('%s = %s\n' % (key, infos[key]))
147
148 if changed:
149 logger.info('Updating %s' % doc_conf)
150 with open(doc_conf, 'w') as dcf:
151 for line in lines:
152 dcf.write(line)
153 else:
154 logger.info('No changes required')
155
156 return 0
157
158
159if __name__ == "__main__":
160 try:
161 ret = main()
162 except Exception:
163 ret = 1
164 import traceback
165 traceback.print_exc(5)
166 sys.exit(ret)
167
168