[systemd-devel] [PATCH 1/2] build-sys: move python helpers to tools directory
Tom Gundersen
teg at jklm.no
Mon Feb 10 04:11:53 PST 2014
On Mon, Feb 10, 2014 at 10:37 AM, Karel Zak <kzak at redhat.com> wrote:
> Note that make-man-rules.py is missing in EXTRA_DIST=, this patch
> fixes this mistake too.
Applied both patches. Thanks!
Cheers,
Tom
> ---
> Makefile.am | 13 +-
> make-directive-index.py | 320 ------------------------------------------
> make-man-index.py | 136 ------------------
> make-man-rules.py | 113 ---------------
> tools/make-directive-index.py | 320 ++++++++++++++++++++++++++++++++++++++++++
> tools/make-man-index.py | 136 ++++++++++++++++++
> tools/make-man-rules.py | 113 +++++++++++++++
> tools/xml_helper.py | 41 ++++++
> xml_helper.py | 41 ------
> 9 files changed, 617 insertions(+), 616 deletions(-)
> delete mode 100755 make-directive-index.py
> delete mode 100755 make-man-index.py
> delete mode 100644 make-man-rules.py
> create mode 100755 tools/make-directive-index.py
> create mode 100755 tools/make-man-index.py
> create mode 100644 tools/make-man-rules.py
> create mode 100644 tools/xml_helper.py
> delete mode 100644 xml_helper.py
>
> diff --git a/Makefile.am b/Makefile.am
> index 4f5e036..e3c1145 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -610,16 +610,16 @@ XML_GLOB = $(wildcard $(top_srcdir)/man/*.xml $(top_builddir)/man/*.xml)
> NON_INDEX_XML_FILES = $(filter-out man/systemd.index.xml,$(XML_FILES))
> SOURCE_XML_FILES = $(filter-out man/systemd.directives.xml,$(NON_INDEX_XML_FILES))
>
> -update-man-list: make-man-rules.py $(XML_GLOB)
> +update-man-list: $(top_srcdir)/tools/make-man-rules.py $(XML_GLOB)
> $(AM_V_GEN)$(PYTHON) $^ > $(top_srcdir)/Makefile-man.tmp
> $(AM_V_at)mv $(top_srcdir)/Makefile-man.tmp $(top_srcdir)/Makefile-man.am
> @echo "Makefile-man.am has been regenerated"
>
> -man/systemd.index.xml: make-man-index.py $(NON_INDEX_XML_FILES)
> +man/systemd.index.xml: $(top_srcdir)/tools/make-man-index.py $(NON_INDEX_XML_FILES)
> $(AM_V_at)$(MKDIR_P) $(dir $@)
> $(AM_V_GEN)$(PYTHON) $< $@ $(filter-out $<,$^)
>
> -man/systemd.directives.xml: make-directive-index.py $(SOURCE_XML_FILES)
> +man/systemd.directives.xml: $(top_srcdir)/tools/make-directive-index.py $(SOURCE_XML_FILES)
> $(AM_V_at)$(MKDIR_P) $(dir $@)
> $(AM_V_GEN)$(PYTHON) $< $@ $(filter-out $<,$^)
>
> @@ -641,9 +641,10 @@ EXTRA_DIST += \
> $(HTML_FILES) \
> $(HTML_ALIAS) \
> $(man_MANS) \
> - make-man-index.py \
> - make-directive-index.py \
> - xml_helper.py
> + tools/make-man-index.py \
> + tools/make-directive-index.py \
> + tools/make-man-rules.py \
> + tools/xml_helper.py
>
> # ------------------------------------------------------------------------------
> noinst_LTLIBRARIES += \
> diff --git a/make-directive-index.py b/make-directive-index.py
> deleted file mode 100755
> index 2ff304f..0000000
> --- a/make-directive-index.py
> +++ /dev/null
> @@ -1,320 +0,0 @@
> -# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
> -#
> -# This file is part of systemd.
> -#
> -# Copyright 2012-2013 Zbigniew Jędrzejewski-Szmek
> -#
> -# systemd is free software; you can redistribute it and/or modify it
> -# under the terms of the GNU Lesser General Public License as published by
> -# the Free Software Foundation; either version 2.1 of the License, or
> -# (at your option) any later version.
> -#
> -# systemd 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
> -# Lesser General Public License for more details.
> -#
> -# You should have received a copy of the GNU Lesser General Public License
> -# along with systemd; If not, see <http://www.gnu.org/licenses/>.
> -
> -import sys
> -import collections
> -import re
> -from xml_helper import *
> -from copy import deepcopy
> -
> -TEMPLATE = '''\
> -<refentry id="systemd.directives" conditional="HAVE_PYTHON">
> -
> - <refentryinfo>
> - <title>systemd.directives</title>
> - <productname>systemd</productname>
> -
> - <authorgroup>
> - <author>
> - <contrib>Developer</contrib>
> - <firstname>Zbigniew</firstname>
> - <surname>Jędrzejewski-Szmek</surname>
> - <email>zbyszek at in.waw.pl</email>
> - </author>
> - </authorgroup>
> - </refentryinfo>
> -
> - <refmeta>
> - <refentrytitle>systemd.directives</refentrytitle>
> - <manvolnum>7</manvolnum>
> - </refmeta>
> -
> - <refnamediv>
> - <refname>systemd.directives</refname>
> - <refpurpose>Index of configuration directives</refpurpose>
> - </refnamediv>
> -
> - <refsect1>
> - <title>Unit directives</title>
> -
> - <para>Directives for configuring units, used in unit
> - files.</para>
> -
> - <variablelist id='unit-directives' />
> - </refsect1>
> -
> - <refsect1>
> - <title>Options on the kernel command line</title>
> -
> - <para>Kernel boot options for configuring the behaviour of the
> - systemd process.</para>
> -
> - <variablelist id='kernel-commandline-options' />
> - </refsect1>
> -
> - <refsect1>
> - <title>Environment variables</title>
> -
> - <para>Environment variables understood by the systemd
> - manager and other programs.</para>
> -
> - <variablelist id='environment-variables' />
> - </refsect1>
> -
> - <refsect1>
> - <title>UDEV directives</title>
> -
> - <para>Directives for configuring systemd units through the
> - udev database.</para>
> -
> - <variablelist id='udev-directives' />
> - </refsect1>
> -
> - <refsect1>
> - <title>Network directives</title>
> -
> - <para>Directives for configuring network links through the
> - net-setup-link udev builtin and networks through
> - systemd-networkd.</para>
> -
> - <variablelist id='network-directives' />
> - </refsect1>
> -
> - <refsect1>
> - <title>Journal fields</title>
> -
> - <para>Fields in the journal events with a well known meaning.</para>
> -
> - <variablelist id='journal-directives' />
> - </refsect1>
> -
> - <refsect1>
> - <title>PAM configuration directives</title>
> -
> - <para>Directives for configuring PAM behaviour.</para>
> -
> - <variablelist id='pam-directives' />
> - </refsect1>
> -
> - <refsect1>
> - <title>crypttab options</title>
> -
> - <para>Options which influence mounted filesystems and
> - encrypted volumes.</para>
> -
> - <variablelist id='crypttab-options' />
> - </refsect1>
> -
> - <refsect1>
> - <title>System manager directives</title>
> -
> - <para>Directives for configuring the behaviour of the
> - systemd process.</para>
> -
> - <variablelist id='systemd-directives' />
> - </refsect1>
> -
> - <refsect1>
> - <title>bootchart.conf directives</title>
> -
> - <para>Directives for configuring the behaviour of the
> - systemd-bootchart process.</para>
> -
> - <variablelist id='bootchart-directives' />
> - </refsect1>
> -
> - <refsect1>
> - <title>command-line options</title>
> -
> - <para>Command-line options accepted by programs in the
> - systemd suite.</para>
> -
> - <variablelist id='options' />
> - </refsect1>
> -
> - <refsect1>
> - <title>Constants</title>
> -
> - <para>Various constant used and/or defined by systemd.</para>
> -
> - <variablelist id='constants' />
> - </refsect1>
> -
> - <refsect1>
> - <title>Miscellaneous options and directives</title>
> -
> - <para>Other configuration elements which don't fit in
> - any of the above groups.</para>
> -
> - <variablelist id='miscellaneous' />
> - </refsect1>
> -
> - <refsect1>
> - <title>Files and directories</title>
> -
> - <para>Paths and file names referred to in the
> - documentation.</para>
> -
> - <variablelist id='filenames' />
> - </refsect1>
> -
> - <refsect1>
> - <title>Colophon</title>
> - <para id='colophon' />
> - </refsect1>
> -</refentry>
> -'''
> -
> -COLOPHON = '''\
> -This index contains {count} entries in {sections} sections,
> -referring to {pages} individual manual pages.
> -'''
> -
> -def _extract_directives(directive_groups, formatting, page):
> - t = xml_parse(page)
> - section = t.find('./refmeta/manvolnum').text
> - pagename = t.find('./refmeta/refentrytitle').text
> -
> - storopt = directive_groups['options']
> - for variablelist in t.iterfind('.//variablelist'):
> - klass = variablelist.attrib.get('class')
> - storvar = directive_groups[klass or 'miscellaneous']
> - # <option>s go in OPTIONS, unless class is specified
> - for xpath, stor in (('./varlistentry/term/varname', storvar),
> - ('./varlistentry/term/option',
> - storvar if klass else storopt)):
> - for name in variablelist.iterfind(xpath):
> - text = re.sub(r'([= ]).*', r'\1', name.text).rstrip()
> - stor[text].append((pagename, section))
> - if text not in formatting:
> - # use element as formatted display
> - if name.text[-1] in '= ':
> - name.clear()
> - else:
> - name.tail = ''
> - name.text = text
> - formatting[text] = name
> -
> - storfile = directive_groups['filenames']
> - for xpath, absolute_only in (('.//refsynopsisdiv//filename', False),
> - ('.//refsynopsisdiv//command', False),
> - ('.//filename', True)):
> - for name in t.iterfind(xpath):
> - if absolute_only and not (name.text and name.text.startswith('/')):
> - continue
> - if name.attrib.get('noindex'):
> - continue
> - name.tail = ''
> - if name.text:
> - if name.text.endswith('*'):
> - name.text = name.text[:-1]
> - if not name.text.startswith('.'):
> - text = name.text.partition(' ')[0]
> - if text != name.text:
> - name.clear()
> - name.text = text
> - if text.endswith('/'):
> - text = text[:-1]
> - storfile[text].append((pagename, section))
> - if text not in formatting:
> - # use element as formatted display
> - formatting[text] = name
> - else:
> - text = ' '.join(name.itertext())
> - storfile[text].append((pagename, section))
> - formatting[text] = name
> -
> - storfile = directive_groups['constants']
> - for name in t.iterfind('.//constant'):
> - if name.attrib.get('noindex'):
> - continue
> - name.tail = ''
> - if name.text.startswith('('): # a cast, strip it
> - name.text = name.text.partition(' ')[2]
> - storfile[name.text].append((pagename, section))
> - formatting[name.text] = name
> -
> -def _make_section(template, name, directives, formatting):
> - varlist = template.find(".//*[@id='{}']".format(name))
> - for varname, manpages in sorted(directives.items()):
> - entry = tree.SubElement(varlist, 'varlistentry')
> - term = tree.SubElement(entry, 'term')
> - display = deepcopy(formatting[varname])
> - term.append(display)
> -
> - para = tree.SubElement(tree.SubElement(entry, 'listitem'), 'para')
> -
> - b = None
> - for manpage, manvolume in sorted(set(manpages)):
> - if b is not None:
> - b.tail = ', '
> - b = tree.SubElement(para, 'citerefentry')
> - c = tree.SubElement(b, 'refentrytitle')
> - c.text = manpage
> - d = tree.SubElement(b, 'manvolnum')
> - d.text = manvolume
> - entry.tail = '\n\n'
> -
> -def _make_colophon(template, groups):
> - count = 0
> - pages = set()
> - for group in groups:
> - count += len(group)
> - for pagelist in group.values():
> - pages |= set(pagelist)
> -
> - para = template.find(".//para[@id='colophon']")
> - para.text = COLOPHON.format(count=count,
> - sections=len(groups),
> - pages=len(pages))
> -
> -def _make_page(template, directive_groups, formatting):
> - """Create an XML tree from directive_groups.
> -
> - directive_groups = {
> - 'class': {'variable': [('manpage', 'manvolume'), ...],
> - 'variable2': ...},
> - ...
> - }
> - """
> - for name, directives in directive_groups.items():
> - _make_section(template, name, directives, formatting)
> -
> - _make_colophon(template, directive_groups.values())
> -
> - return template
> -
> -def make_page(*xml_files):
> - "Extract directives from xml_files and return XML index tree."
> - template = tree.fromstring(TEMPLATE)
> - names = [vl.get('id') for vl in template.iterfind('.//variablelist')]
> - directive_groups = {name:collections.defaultdict(list)
> - for name in names}
> - formatting = {}
> - for page in xml_files:
> - try:
> - _extract_directives(directive_groups, formatting, page)
> - except Exception:
> - raise ValueError("failed to process " + page)
> -
> - return _make_page(template, directive_groups, formatting)
> -
> -if __name__ == '__main__':
> - with open(sys.argv[1], 'wb') as f:
> - f.write(xml_print(make_page(*sys.argv[2:])))
> diff --git a/make-man-index.py b/make-man-index.py
> deleted file mode 100755
> index 74a47b8..0000000
> --- a/make-man-index.py
> +++ /dev/null
> @@ -1,136 +0,0 @@
> -# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
> -#
> -# This file is part of systemd.
> -#
> -# Copyright 2012 Lennart Poettering
> -# Copyright 2013 Zbigniew Jędrzejewski-Szmek
> -#
> -# systemd is free software; you can redistribute it and/or modify it
> -# under the terms of the GNU Lesser General Public License as published by
> -# the Free Software Foundation; either version 2.1 of the License, or
> -# (at your option) any later version.
> -#
> -# systemd 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
> -# Lesser General Public License for more details.
> -#
> -# You should have received a copy of the GNU Lesser General Public License
> -# along with systemd; If not, see <http://www.gnu.org/licenses/>.
> -
> -import collections
> -import sys
> -import re
> -from xml_helper import *
> -
> -MDASH = ' — ' if sys.version_info.major >= 3 else ' -- '
> -
> -TEMPLATE = '''\
> -<refentry id="systemd.index" conditional="HAVE_PYTHON">
> -
> - <refentryinfo>
> - <title>systemd.index</title>
> - <productname>systemd</productname>
> -
> - <authorgroup>
> - <author>
> - <contrib>Developer</contrib>
> - <firstname>Lennart</firstname>
> - <surname>Poettering</surname>
> - <email>lennart at poettering.net</email>
> - </author>
> - </authorgroup>
> - </refentryinfo>
> -
> - <refmeta>
> - <refentrytitle>systemd.index</refentrytitle>
> - <manvolnum>7</manvolnum>
> - </refmeta>
> -
> - <refnamediv>
> - <refname>systemd.index</refname>
> - <refpurpose>List all manpages from the systemd project</refpurpose>
> - </refnamediv>
> -</refentry>
> -'''
> -
> -SUMMARY = '''\
> - <refsect1>
> - <title>See Also</title>
> - <para>
> - <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
> - </para>
> -
> - <para id='counts' />
> - </refsect1>
> -'''
> -
> -COUNTS = '\
> -This index contains {count} entries, referring to {pages} individual manual pages.'
> -
> -
> -def check_id(page, t):
> - id = t.getroot().get('id')
> - if not re.search('/' + id + '[.]', page):
> - raise ValueError("id='{}' is not the same as page name '{}'".format(id, page))
> -
> -def make_index(pages):
> - index = collections.defaultdict(list)
> - for p in pages:
> - t = xml_parse(p)
> - check_id(p, t)
> - section = t.find('./refmeta/manvolnum').text
> - refname = t.find('./refnamediv/refname').text
> - purpose = ' '.join(t.find('./refnamediv/refpurpose').text.split())
> - for f in t.findall('./refnamediv/refname'):
> - infos = (f.text, section, purpose, refname)
> - index[f.text[0].upper()].append(infos)
> - return index
> -
> -def add_letter(template, letter, pages):
> - refsect1 = tree.SubElement(template, 'refsect1')
> - title = tree.SubElement(refsect1, 'title')
> - title.text = letter
> - para = tree.SubElement(refsect1, 'para')
> - for info in sorted(pages, key=lambda info: str.lower(info[0])):
> - refname, section, purpose, realname = info
> -
> - b = tree.SubElement(para, 'citerefentry')
> - c = tree.SubElement(b, 'refentrytitle')
> - c.text = refname
> - d = tree.SubElement(b, 'manvolnum')
> - d.text = section
> -
> - b.tail = MDASH + purpose # + ' (' + p + ')'
> -
> - tree.SubElement(para, 'sbr')
> -
> -def add_summary(template, indexpages):
> - count = 0
> - pages = set()
> - for group in indexpages:
> - count += len(group)
> - for info in group:
> - refname, section, purpose, realname = info
> - pages.add((realname, section))
> -
> - refsect1 = tree.fromstring(SUMMARY)
> - template.append(refsect1)
> -
> - para = template.find(".//para[@id='counts']")
> - para.text = COUNTS.format(count=count, pages=len(pages))
> -
> -def make_page(*xml_files):
> - template = tree.fromstring(TEMPLATE)
> - index = make_index(xml_files)
> -
> - for letter in sorted(index):
> - add_letter(template, letter, index[letter])
> -
> - add_summary(template, index.values())
> -
> - return template
> -
> -if __name__ == '__main__':
> - with open(sys.argv[1], 'wb') as f:
> - f.write(xml_print(make_page(*sys.argv[2:])))
> diff --git a/make-man-rules.py b/make-man-rules.py
> deleted file mode 100644
> index 0d1ca24..0000000
> --- a/make-man-rules.py
> +++ /dev/null
> @@ -1,113 +0,0 @@
> -# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
> -#
> -# This file is part of systemd.
> -#
> -# Copyright 2013 Zbigniew Jędrzejewski-Szmek
> -#
> -# systemd is free software; you can redistribute it and/or modify it
> -# under the terms of the GNU Lesser General Public License as published by
> -# the Free Software Foundation; either version 2.1 of the License, or
> -# (at your option) any later version.
> -#
> -# systemd 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
> -# Lesser General Public License for more details.
> -#
> -# You should have received a copy of the GNU Lesser General Public License
> -# along with systemd; If not, see <http://www.gnu.org/licenses/>.
> -
> -from __future__ import print_function
> -import collections
> -import sys
> -import os.path
> -from xml_helper import *
> -
> -SECTION = '''\
> -MANPAGES += \\
> - {manpages}
> -MANPAGES_ALIAS += \\
> - {aliases}
> -{rules}
> -{htmlrules}
> -'''
> -
> -CONDITIONAL = '''\
> -if {conditional}
> -''' \
> -+ SECTION + \
> -'''\
> -endif
> -'''
> -
> -HEADER = '''\
> -# Do not edit. Generated by make-man-rules.py.
> -# Regenerate with 'make all update-man-list'.
> -
> -'''
> -
> -HTML_ALIAS_RULE = '''\
> -{}.html: {}.html
> - $(html-alias)
> -'''
> -
> -FOOTER = '''\
> -
> -EXTRA_DIST += \\
> - {files}
> -'''
> -
> -def man(page, number):
> - return 'man/{}.{}'.format(page, number)
> -
> -def xml(file):
> - return 'man/{}'.format(os.path.basename(file))
> -
> -def add_rules(rules, name):
> - xml = xml_parse(name)
> - # print('parsing {}'.format(name), file=sys.stderr)
> - conditional = xml.getroot().get('conditional') or ''
> - rulegroup = rules[conditional]
> - refmeta = xml.find('./refmeta')
> - title = refmeta.find('./refentrytitle').text
> - number = refmeta.find('./manvolnum').text
> - refnames = xml.findall('./refnamediv/refname')
> - target = man(refnames[0].text, number)
> - if title != refnames[0].text:
> - raise ValueError('refmeta and refnamediv disagree: ' + name)
> - for refname in refnames:
> - assert all(refname not in group
> - for group in rules.values()), "duplicate page name"
> - alias = man(refname.text, number)
> - rulegroup[alias] = target
> - # print('{} => {} [{}]'.format(alias, target, conditional), file=sys.stderr)
> -
> -def create_rules(xml_files):
> - " {conditional => {alias-name => source-name}} "
> - rules = collections.defaultdict(dict)
> - for name in xml_files:
> - add_rules(rules, name)
> - return rules
> -
> -def mjoin(files):
> - return ' \\\n\t'.join(sorted(files) or '#')
> -
> -def make_makefile(rules, files):
> - return HEADER + '\n'.join(
> - (CONDITIONAL if conditional else SECTION).format(
> - manpages=mjoin(set(rulegroup.values())),
> - aliases=mjoin(k for k,v in rulegroup.items() if k != v),
> - rules='\n'.join('{}: {}'.format(k,v)
> - for k,v in sorted(rulegroup.items())
> - if k != v),
> - htmlrules='\n'.join(HTML_ALIAS_RULE.format(k[:-2],v[:-2])
> - for k,v in sorted(rulegroup.items())
> - if k != v),
> - conditional=conditional)
> - for conditional,rulegroup in sorted(rules.items())
> - ) + FOOTER.format(files=mjoin(sorted(files)))
> -
> -if __name__ == '__main__':
> - rules = create_rules(sys.argv[1:])
> - files = (xml(file) for file in sys.argv[1:])
> - print(make_makefile(rules, files), end='')
> diff --git a/tools/make-directive-index.py b/tools/make-directive-index.py
> new file mode 100755
> index 0000000..2ff304f
> --- /dev/null
> +++ b/tools/make-directive-index.py
> @@ -0,0 +1,320 @@
> +# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
> +#
> +# This file is part of systemd.
> +#
> +# Copyright 2012-2013 Zbigniew Jędrzejewski-Szmek
> +#
> +# systemd is free software; you can redistribute it and/or modify it
> +# under the terms of the GNU Lesser General Public License as published by
> +# the Free Software Foundation; either version 2.1 of the License, or
> +# (at your option) any later version.
> +#
> +# systemd 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
> +# Lesser General Public License for more details.
> +#
> +# You should have received a copy of the GNU Lesser General Public License
> +# along with systemd; If not, see <http://www.gnu.org/licenses/>.
> +
> +import sys
> +import collections
> +import re
> +from xml_helper import *
> +from copy import deepcopy
> +
> +TEMPLATE = '''\
> +<refentry id="systemd.directives" conditional="HAVE_PYTHON">
> +
> + <refentryinfo>
> + <title>systemd.directives</title>
> + <productname>systemd</productname>
> +
> + <authorgroup>
> + <author>
> + <contrib>Developer</contrib>
> + <firstname>Zbigniew</firstname>
> + <surname>Jędrzejewski-Szmek</surname>
> + <email>zbyszek at in.waw.pl</email>
> + </author>
> + </authorgroup>
> + </refentryinfo>
> +
> + <refmeta>
> + <refentrytitle>systemd.directives</refentrytitle>
> + <manvolnum>7</manvolnum>
> + </refmeta>
> +
> + <refnamediv>
> + <refname>systemd.directives</refname>
> + <refpurpose>Index of configuration directives</refpurpose>
> + </refnamediv>
> +
> + <refsect1>
> + <title>Unit directives</title>
> +
> + <para>Directives for configuring units, used in unit
> + files.</para>
> +
> + <variablelist id='unit-directives' />
> + </refsect1>
> +
> + <refsect1>
> + <title>Options on the kernel command line</title>
> +
> + <para>Kernel boot options for configuring the behaviour of the
> + systemd process.</para>
> +
> + <variablelist id='kernel-commandline-options' />
> + </refsect1>
> +
> + <refsect1>
> + <title>Environment variables</title>
> +
> + <para>Environment variables understood by the systemd
> + manager and other programs.</para>
> +
> + <variablelist id='environment-variables' />
> + </refsect1>
> +
> + <refsect1>
> + <title>UDEV directives</title>
> +
> + <para>Directives for configuring systemd units through the
> + udev database.</para>
> +
> + <variablelist id='udev-directives' />
> + </refsect1>
> +
> + <refsect1>
> + <title>Network directives</title>
> +
> + <para>Directives for configuring network links through the
> + net-setup-link udev builtin and networks through
> + systemd-networkd.</para>
> +
> + <variablelist id='network-directives' />
> + </refsect1>
> +
> + <refsect1>
> + <title>Journal fields</title>
> +
> + <para>Fields in the journal events with a well known meaning.</para>
> +
> + <variablelist id='journal-directives' />
> + </refsect1>
> +
> + <refsect1>
> + <title>PAM configuration directives</title>
> +
> + <para>Directives for configuring PAM behaviour.</para>
> +
> + <variablelist id='pam-directives' />
> + </refsect1>
> +
> + <refsect1>
> + <title>crypttab options</title>
> +
> + <para>Options which influence mounted filesystems and
> + encrypted volumes.</para>
> +
> + <variablelist id='crypttab-options' />
> + </refsect1>
> +
> + <refsect1>
> + <title>System manager directives</title>
> +
> + <para>Directives for configuring the behaviour of the
> + systemd process.</para>
> +
> + <variablelist id='systemd-directives' />
> + </refsect1>
> +
> + <refsect1>
> + <title>bootchart.conf directives</title>
> +
> + <para>Directives for configuring the behaviour of the
> + systemd-bootchart process.</para>
> +
> + <variablelist id='bootchart-directives' />
> + </refsect1>
> +
> + <refsect1>
> + <title>command-line options</title>
> +
> + <para>Command-line options accepted by programs in the
> + systemd suite.</para>
> +
> + <variablelist id='options' />
> + </refsect1>
> +
> + <refsect1>
> + <title>Constants</title>
> +
> + <para>Various constant used and/or defined by systemd.</para>
> +
> + <variablelist id='constants' />
> + </refsect1>
> +
> + <refsect1>
> + <title>Miscellaneous options and directives</title>
> +
> + <para>Other configuration elements which don't fit in
> + any of the above groups.</para>
> +
> + <variablelist id='miscellaneous' />
> + </refsect1>
> +
> + <refsect1>
> + <title>Files and directories</title>
> +
> + <para>Paths and file names referred to in the
> + documentation.</para>
> +
> + <variablelist id='filenames' />
> + </refsect1>
> +
> + <refsect1>
> + <title>Colophon</title>
> + <para id='colophon' />
> + </refsect1>
> +</refentry>
> +'''
> +
> +COLOPHON = '''\
> +This index contains {count} entries in {sections} sections,
> +referring to {pages} individual manual pages.
> +'''
> +
> +def _extract_directives(directive_groups, formatting, page):
> + t = xml_parse(page)
> + section = t.find('./refmeta/manvolnum').text
> + pagename = t.find('./refmeta/refentrytitle').text
> +
> + storopt = directive_groups['options']
> + for variablelist in t.iterfind('.//variablelist'):
> + klass = variablelist.attrib.get('class')
> + storvar = directive_groups[klass or 'miscellaneous']
> + # <option>s go in OPTIONS, unless class is specified
> + for xpath, stor in (('./varlistentry/term/varname', storvar),
> + ('./varlistentry/term/option',
> + storvar if klass else storopt)):
> + for name in variablelist.iterfind(xpath):
> + text = re.sub(r'([= ]).*', r'\1', name.text).rstrip()
> + stor[text].append((pagename, section))
> + if text not in formatting:
> + # use element as formatted display
> + if name.text[-1] in '= ':
> + name.clear()
> + else:
> + name.tail = ''
> + name.text = text
> + formatting[text] = name
> +
> + storfile = directive_groups['filenames']
> + for xpath, absolute_only in (('.//refsynopsisdiv//filename', False),
> + ('.//refsynopsisdiv//command', False),
> + ('.//filename', True)):
> + for name in t.iterfind(xpath):
> + if absolute_only and not (name.text and name.text.startswith('/')):
> + continue
> + if name.attrib.get('noindex'):
> + continue
> + name.tail = ''
> + if name.text:
> + if name.text.endswith('*'):
> + name.text = name.text[:-1]
> + if not name.text.startswith('.'):
> + text = name.text.partition(' ')[0]
> + if text != name.text:
> + name.clear()
> + name.text = text
> + if text.endswith('/'):
> + text = text[:-1]
> + storfile[text].append((pagename, section))
> + if text not in formatting:
> + # use element as formatted display
> + formatting[text] = name
> + else:
> + text = ' '.join(name.itertext())
> + storfile[text].append((pagename, section))
> + formatting[text] = name
> +
> + storfile = directive_groups['constants']
> + for name in t.iterfind('.//constant'):
> + if name.attrib.get('noindex'):
> + continue
> + name.tail = ''
> + if name.text.startswith('('): # a cast, strip it
> + name.text = name.text.partition(' ')[2]
> + storfile[name.text].append((pagename, section))
> + formatting[name.text] = name
> +
> +def _make_section(template, name, directives, formatting):
> + varlist = template.find(".//*[@id='{}']".format(name))
> + for varname, manpages in sorted(directives.items()):
> + entry = tree.SubElement(varlist, 'varlistentry')
> + term = tree.SubElement(entry, 'term')
> + display = deepcopy(formatting[varname])
> + term.append(display)
> +
> + para = tree.SubElement(tree.SubElement(entry, 'listitem'), 'para')
> +
> + b = None
> + for manpage, manvolume in sorted(set(manpages)):
> + if b is not None:
> + b.tail = ', '
> + b = tree.SubElement(para, 'citerefentry')
> + c = tree.SubElement(b, 'refentrytitle')
> + c.text = manpage
> + d = tree.SubElement(b, 'manvolnum')
> + d.text = manvolume
> + entry.tail = '\n\n'
> +
> +def _make_colophon(template, groups):
> + count = 0
> + pages = set()
> + for group in groups:
> + count += len(group)
> + for pagelist in group.values():
> + pages |= set(pagelist)
> +
> + para = template.find(".//para[@id='colophon']")
> + para.text = COLOPHON.format(count=count,
> + sections=len(groups),
> + pages=len(pages))
> +
> +def _make_page(template, directive_groups, formatting):
> + """Create an XML tree from directive_groups.
> +
> + directive_groups = {
> + 'class': {'variable': [('manpage', 'manvolume'), ...],
> + 'variable2': ...},
> + ...
> + }
> + """
> + for name, directives in directive_groups.items():
> + _make_section(template, name, directives, formatting)
> +
> + _make_colophon(template, directive_groups.values())
> +
> + return template
> +
> +def make_page(*xml_files):
> + "Extract directives from xml_files and return XML index tree."
> + template = tree.fromstring(TEMPLATE)
> + names = [vl.get('id') for vl in template.iterfind('.//variablelist')]
> + directive_groups = {name:collections.defaultdict(list)
> + for name in names}
> + formatting = {}
> + for page in xml_files:
> + try:
> + _extract_directives(directive_groups, formatting, page)
> + except Exception:
> + raise ValueError("failed to process " + page)
> +
> + return _make_page(template, directive_groups, formatting)
> +
> +if __name__ == '__main__':
> + with open(sys.argv[1], 'wb') as f:
> + f.write(xml_print(make_page(*sys.argv[2:])))
> diff --git a/tools/make-man-index.py b/tools/make-man-index.py
> new file mode 100755
> index 0000000..74a47b8
> --- /dev/null
> +++ b/tools/make-man-index.py
> @@ -0,0 +1,136 @@
> +# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
> +#
> +# This file is part of systemd.
> +#
> +# Copyright 2012 Lennart Poettering
> +# Copyright 2013 Zbigniew Jędrzejewski-Szmek
> +#
> +# systemd is free software; you can redistribute it and/or modify it
> +# under the terms of the GNU Lesser General Public License as published by
> +# the Free Software Foundation; either version 2.1 of the License, or
> +# (at your option) any later version.
> +#
> +# systemd 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
> +# Lesser General Public License for more details.
> +#
> +# You should have received a copy of the GNU Lesser General Public License
> +# along with systemd; If not, see <http://www.gnu.org/licenses/>.
> +
> +import collections
> +import sys
> +import re
> +from xml_helper import *
> +
> +MDASH = ' — ' if sys.version_info.major >= 3 else ' -- '
> +
> +TEMPLATE = '''\
> +<refentry id="systemd.index" conditional="HAVE_PYTHON">
> +
> + <refentryinfo>
> + <title>systemd.index</title>
> + <productname>systemd</productname>
> +
> + <authorgroup>
> + <author>
> + <contrib>Developer</contrib>
> + <firstname>Lennart</firstname>
> + <surname>Poettering</surname>
> + <email>lennart at poettering.net</email>
> + </author>
> + </authorgroup>
> + </refentryinfo>
> +
> + <refmeta>
> + <refentrytitle>systemd.index</refentrytitle>
> + <manvolnum>7</manvolnum>
> + </refmeta>
> +
> + <refnamediv>
> + <refname>systemd.index</refname>
> + <refpurpose>List all manpages from the systemd project</refpurpose>
> + </refnamediv>
> +</refentry>
> +'''
> +
> +SUMMARY = '''\
> + <refsect1>
> + <title>See Also</title>
> + <para>
> + <citerefentry><refentrytitle>systemd.directives</refentrytitle><manvolnum>7</manvolnum></citerefentry>
> + </para>
> +
> + <para id='counts' />
> + </refsect1>
> +'''
> +
> +COUNTS = '\
> +This index contains {count} entries, referring to {pages} individual manual pages.'
> +
> +
> +def check_id(page, t):
> + id = t.getroot().get('id')
> + if not re.search('/' + id + '[.]', page):
> + raise ValueError("id='{}' is not the same as page name '{}'".format(id, page))
> +
> +def make_index(pages):
> + index = collections.defaultdict(list)
> + for p in pages:
> + t = xml_parse(p)
> + check_id(p, t)
> + section = t.find('./refmeta/manvolnum').text
> + refname = t.find('./refnamediv/refname').text
> + purpose = ' '.join(t.find('./refnamediv/refpurpose').text.split())
> + for f in t.findall('./refnamediv/refname'):
> + infos = (f.text, section, purpose, refname)
> + index[f.text[0].upper()].append(infos)
> + return index
> +
> +def add_letter(template, letter, pages):
> + refsect1 = tree.SubElement(template, 'refsect1')
> + title = tree.SubElement(refsect1, 'title')
> + title.text = letter
> + para = tree.SubElement(refsect1, 'para')
> + for info in sorted(pages, key=lambda info: str.lower(info[0])):
> + refname, section, purpose, realname = info
> +
> + b = tree.SubElement(para, 'citerefentry')
> + c = tree.SubElement(b, 'refentrytitle')
> + c.text = refname
> + d = tree.SubElement(b, 'manvolnum')
> + d.text = section
> +
> + b.tail = MDASH + purpose # + ' (' + p + ')'
> +
> + tree.SubElement(para, 'sbr')
> +
> +def add_summary(template, indexpages):
> + count = 0
> + pages = set()
> + for group in indexpages:
> + count += len(group)
> + for info in group:
> + refname, section, purpose, realname = info
> + pages.add((realname, section))
> +
> + refsect1 = tree.fromstring(SUMMARY)
> + template.append(refsect1)
> +
> + para = template.find(".//para[@id='counts']")
> + para.text = COUNTS.format(count=count, pages=len(pages))
> +
> +def make_page(*xml_files):
> + template = tree.fromstring(TEMPLATE)
> + index = make_index(xml_files)
> +
> + for letter in sorted(index):
> + add_letter(template, letter, index[letter])
> +
> + add_summary(template, index.values())
> +
> + return template
> +
> +if __name__ == '__main__':
> + with open(sys.argv[1], 'wb') as f:
> + f.write(xml_print(make_page(*sys.argv[2:])))
> diff --git a/tools/make-man-rules.py b/tools/make-man-rules.py
> new file mode 100644
> index 0000000..0d1ca24
> --- /dev/null
> +++ b/tools/make-man-rules.py
> @@ -0,0 +1,113 @@
> +# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
> +#
> +# This file is part of systemd.
> +#
> +# Copyright 2013 Zbigniew Jędrzejewski-Szmek
> +#
> +# systemd is free software; you can redistribute it and/or modify it
> +# under the terms of the GNU Lesser General Public License as published by
> +# the Free Software Foundation; either version 2.1 of the License, or
> +# (at your option) any later version.
> +#
> +# systemd 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
> +# Lesser General Public License for more details.
> +#
> +# You should have received a copy of the GNU Lesser General Public License
> +# along with systemd; If not, see <http://www.gnu.org/licenses/>.
> +
> +from __future__ import print_function
> +import collections
> +import sys
> +import os.path
> +from xml_helper import *
> +
> +SECTION = '''\
> +MANPAGES += \\
> + {manpages}
> +MANPAGES_ALIAS += \\
> + {aliases}
> +{rules}
> +{htmlrules}
> +'''
> +
> +CONDITIONAL = '''\
> +if {conditional}
> +''' \
> ++ SECTION + \
> +'''\
> +endif
> +'''
> +
> +HEADER = '''\
> +# Do not edit. Generated by make-man-rules.py.
> +# Regenerate with 'make all update-man-list'.
> +
> +'''
> +
> +HTML_ALIAS_RULE = '''\
> +{}.html: {}.html
> + $(html-alias)
> +'''
> +
> +FOOTER = '''\
> +
> +EXTRA_DIST += \\
> + {files}
> +'''
> +
> +def man(page, number):
> + return 'man/{}.{}'.format(page, number)
> +
> +def xml(file):
> + return 'man/{}'.format(os.path.basename(file))
> +
> +def add_rules(rules, name):
> + xml = xml_parse(name)
> + # print('parsing {}'.format(name), file=sys.stderr)
> + conditional = xml.getroot().get('conditional') or ''
> + rulegroup = rules[conditional]
> + refmeta = xml.find('./refmeta')
> + title = refmeta.find('./refentrytitle').text
> + number = refmeta.find('./manvolnum').text
> + refnames = xml.findall('./refnamediv/refname')
> + target = man(refnames[0].text, number)
> + if title != refnames[0].text:
> + raise ValueError('refmeta and refnamediv disagree: ' + name)
> + for refname in refnames:
> + assert all(refname not in group
> + for group in rules.values()), "duplicate page name"
> + alias = man(refname.text, number)
> + rulegroup[alias] = target
> + # print('{} => {} [{}]'.format(alias, target, conditional), file=sys.stderr)
> +
> +def create_rules(xml_files):
> + " {conditional => {alias-name => source-name}} "
> + rules = collections.defaultdict(dict)
> + for name in xml_files:
> + add_rules(rules, name)
> + return rules
> +
> +def mjoin(files):
> + return ' \\\n\t'.join(sorted(files) or '#')
> +
> +def make_makefile(rules, files):
> + return HEADER + '\n'.join(
> + (CONDITIONAL if conditional else SECTION).format(
> + manpages=mjoin(set(rulegroup.values())),
> + aliases=mjoin(k for k,v in rulegroup.items() if k != v),
> + rules='\n'.join('{}: {}'.format(k,v)
> + for k,v in sorted(rulegroup.items())
> + if k != v),
> + htmlrules='\n'.join(HTML_ALIAS_RULE.format(k[:-2],v[:-2])
> + for k,v in sorted(rulegroup.items())
> + if k != v),
> + conditional=conditional)
> + for conditional,rulegroup in sorted(rules.items())
> + ) + FOOTER.format(files=mjoin(sorted(files)))
> +
> +if __name__ == '__main__':
> + rules = create_rules(sys.argv[1:])
> + files = (xml(file) for file in sys.argv[1:])
> + print(make_makefile(rules, files), end='')
> diff --git a/tools/xml_helper.py b/tools/xml_helper.py
> new file mode 100644
> index 0000000..08e226f
> --- /dev/null
> +++ b/tools/xml_helper.py
> @@ -0,0 +1,41 @@
> +# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
> +#
> +# This file is part of systemd.
> +#
> +# Copyright 2012-2013 Zbigniew Jędrzejewski-Szmek
> +#
> +# systemd is free software; you can redistribute it and/or modify it
> +# under the terms of the GNU Lesser General Public License as published by
> +# the Free Software Foundation; either version 2.1 of the License, or
> +# (at your option) any later version.
> +#
> +# systemd 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
> +# Lesser General Public License for more details.
> +#
> +# You should have received a copy of the GNU Lesser General Public License
> +# along with systemd; If not, see <http://www.gnu.org/licenses/>.
> +
> +try:
> + from lxml import etree as tree
> +
> + class CustomResolver(tree.Resolver):
> + def resolve(self, url, id, context):
> + if 'custom-entities.ent' in url:
> + return self.resolve_filename('man/custom-entities.ent', context)
> +
> + _parser = tree.XMLParser()
> + _parser.resolvers.add(CustomResolver())
> + xml_parse = lambda page: tree.parse(page, _parser)
> + xml_print = lambda xml: tree.tostring(xml, pretty_print=True,
> + encoding='utf-8')
> +except ImportError:
> + import xml.etree.ElementTree as tree
> + import re as _re
> + import io as _io
> +
> + def xml_parse(page):
> + s = _re.sub(b'&[a-zA-Z0-9_]+;', b'', open(page, 'rb').read())
> + return tree.parse(_io.BytesIO(s))
> + xml_print = lambda xml: tree.tostring(xml, encoding='utf-8')
> diff --git a/xml_helper.py b/xml_helper.py
> deleted file mode 100644
> index 08e226f..0000000
> --- a/xml_helper.py
> +++ /dev/null
> @@ -1,41 +0,0 @@
> -# -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
> -#
> -# This file is part of systemd.
> -#
> -# Copyright 2012-2013 Zbigniew Jędrzejewski-Szmek
> -#
> -# systemd is free software; you can redistribute it and/or modify it
> -# under the terms of the GNU Lesser General Public License as published by
> -# the Free Software Foundation; either version 2.1 of the License, or
> -# (at your option) any later version.
> -#
> -# systemd 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
> -# Lesser General Public License for more details.
> -#
> -# You should have received a copy of the GNU Lesser General Public License
> -# along with systemd; If not, see <http://www.gnu.org/licenses/>.
> -
> -try:
> - from lxml import etree as tree
> -
> - class CustomResolver(tree.Resolver):
> - def resolve(self, url, id, context):
> - if 'custom-entities.ent' in url:
> - return self.resolve_filename('man/custom-entities.ent', context)
> -
> - _parser = tree.XMLParser()
> - _parser.resolvers.add(CustomResolver())
> - xml_parse = lambda page: tree.parse(page, _parser)
> - xml_print = lambda xml: tree.tostring(xml, pretty_print=True,
> - encoding='utf-8')
> -except ImportError:
> - import xml.etree.ElementTree as tree
> - import re as _re
> - import io as _io
> -
> - def xml_parse(page):
> - s = _re.sub(b'&[a-zA-Z0-9_]+;', b'', open(page, 'rb').read())
> - return tree.parse(_io.BytesIO(s))
> - xml_print = lambda xml: tree.tostring(xml, encoding='utf-8')
> --
> 1.8.5.3
>
>
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
>
More information about the systemd-devel
mailing list