[elbe-devel] [PATCH v4 1/2] preprocess: allow building variants of a xml file

Torben Hohn torben.hohn at linutronix.de
Tue Jan 9 10:56:16 CET 2018


On Mon, Jan 08, 2018 at 08:08:58PM +0100, Manuel Traut wrote:
> Other build-systems allow building different flavours or variants of a
> image based on some config values. This eases the maintainance of very
> similar images.
> 
> The elbe preprocess subcommand allows modifying XML files before they are
> used with other elbe subcommands. The XML file used by the preprocess
> subcommand doesn't need to validate with 'dbsfed.xsd', but the output needs
> to.
> 
> This adds a new parameter '--variant' to the 'preprocess' subcommand. A
> XML tag inside the XML file given to 'preprocess' can contain a 'variant'
> attribute. If the value of the variant attribute inside XML matches with
> a variant given as parameter to the preprocess command, the XML tag
> stays inside the XML file. If the XML tag has a variant attribute but
> doesn't match with the variant given as parameter to 'preprocess' the
> XML tag will be dropped. If no 'variant' parameter is given to the
> 'preprocess' subcommand all tags with a 'variant' parameter are dropped.
> 
> This allows XML snippets like this:
> 
>   <url variant='security'>
>           <binary>http://security.debian.org/ stretch/updates main</binary>
>           <source>http://security.debian.org/ stretch/updates main</source>
>   </url>
> 
>   <pkg-list>
>           <pkg variant='security'>openssh-server</pkg>
>           <pkg variant='audio,video'>totem</pkg>
>   </pkg-list>
> 
> It is also possible to use multiple sections with variant attributes like this:
> 
> <pkg-list variant='audio>
>   <pkg>alsa</pkg>
>   <pkg>pavucontrol</pkg>
> </pkg-list>
> <pkg-list variant='video>
>   <pkg>totem</pkg>
>   <pkg>ffmpeg</pkg>
> </pkg-list>
> 
> This needs defining mergeable sections by xpath.
> A list of mergeable sections is hardcoded in elbepack/xmlpreprocess.py
> If one of these sections occure multiple times the contents are merged into a
> single section.
> 
> Signed-off-by: Manuel Traut <manut at linutronix.de>

Reviewed-by: Torben Hohn <torben.hohn at linutronix.de>


> ---
>  elbepack/commands/preprocess.py |  9 +++++-
>  elbepack/xmlpreprocess.py       | 64 ++++++++++++++++++++++++++++++++++++++---
>  2 files changed, 68 insertions(+), 5 deletions(-)
> 
> diff --git a/elbepack/commands/preprocess.py b/elbepack/commands/preprocess.py
> index 63dd0295..7b2be1f9 100644
> --- a/elbepack/commands/preprocess.py
> +++ b/elbepack/commands/preprocess.py
> @@ -29,6 +29,9 @@ def run_command(argv):
>      oparser.add_option("-o", "--output", dest="output",
>                         default="preprocess.xml",
>                         help="preprocessed output file", metavar="<xmlfile>")
> +    oparser.add_option("-v", "--variants", dest="variant",
> +                       default=None,
> +                       help="enable only tags with empty or given variant")
>      (opt, args) = oparser.parse_args(argv)
>  
>      if len(args) != 1:
> @@ -40,8 +43,12 @@ def run_command(argv):
>          print("%s doesn't exist" % args[0], file=sys.stderr)
>          sys.exit(20)
>  
> +    variants = []
> +    if opt.variant:
> +        variants = opt.variant.split(',')
> +
>      try:
> -        xmlpreprocess(args[0], opt.output)
> +        xmlpreprocess(args[0], opt.output, variants)
>      except XMLPreprocessError as e:
>          print(e, file=sys.stderr)
>          sys.exit(20)
> diff --git a/elbepack/xmlpreprocess.py b/elbepack/xmlpreprocess.py
> index 86eec9a6..d24f0801 100644
> --- a/elbepack/xmlpreprocess.py
> +++ b/elbepack/xmlpreprocess.py
> @@ -17,16 +17,26 @@
>  # along with ELBE.  If not, see <http://www.gnu.org/licenses/>.
>  
>  import sys
> +import re
>  from lxml import etree
>  from lxml.etree import XMLParser, parse
>  
> +# list of sections that are allowed to exists multiple times before
> +# preprocess and that childrens are merge into one section during preprocess
> +mergepaths = ['//target/finetuning',
> +              '//target/pkg-list',
> +              '//project/buildimage/pkg-list']
> +
>  
>  class XMLPreprocessError(Exception):
> -    def __init__(self, message):
> -        Exception.__init__(self, message)
> +    pass
> +
> +
> +def xmlpreprocess(fname, output, variants=[]):
>  
> +    # first convert variants to a set
> +    variants = set(variants)
>  
> -def xmlpreprocess(fname, output):
>      schema_file = "https://www.linutronix.de/projects/Elbe/dbsfed.xsd"
>      parser = XMLParser(huge_tree=True)
>      schema_tree = etree.parse(schema_file)
> @@ -36,18 +46,64 @@ def xmlpreprocess(fname, output):
>          xml = parse(fname, parser=parser)
>          xml.xinclude()
>  
> +        # Variant management
> +        # check all nodes for variant field, and act accordingly.
> +        # The result will not contain any variant attributes anymore.
> +        rmlist = []
> +        for tag in xml.iter('*'):
> +            if 'variant' in tag.attrib:
> +                tag_variants = set (tag.attrib['variant'].split(','))
> +
> +                # check if tag_variants intersects with
> +                # active variants.
> +                intersect = variants.intersection(tag_variants)
> +
> +                if len(intersect):
> +                    # variant is wanted, keep it and remove the variant
> +                    # attribute
> +                    tag.attrib.pop('variant')
> +                else:
> +                    # tag has a variant attribute but the variant was not
> +                    # specified: remove the tag delayed
> +                    rmlist.append(tag)
> +
> +        for tag in rmlist:
> +            tag.getparent().remove(tag)
> +
> +        # if there are multiple sections because of sth like '<finetuning
> +        # variant='A'> ...  and <finetuning variant='B'> and running preprocess
> +        # with --variant=A,B the two sections need to be merged
> +        #
> +        # Use xpath expressions to identify mergeable sections.
> +        for mergepath in mergepaths:
> +            mergenodes = xml.xpath (mergepath)
> +
> +            # if there is just one section of a type
> +            # or no section, nothing needs to be done
> +            if len(mergenodes) < 2:
> +                continue
> +
> +            # append all childrens of section[1..n] to section[0] and delete
> +            # section[1..n]
> +            for section in mergenodes[1:]:
> +                for c in section.getchildren():
> +                    mergenodes[0].append (c)
> +                section.getparent().remove(section)
> +
>          if schema.validate(xml):
> +            # if validation succedes write xml file
>              xml.write(
>                  output,
>                  encoding="UTF-8",
>                  pretty_print=True,
>                  compression=9)
> +            # the rest of the code is exception and error handling
>              return
>  
>      except etree.XMLSyntaxError:
>          raise XMLPreprocessError("XML Parse error\n" + str(sys.exc_info()[1]))
>      except BaseException:
> -        XMLPreprocessError(
> +        raise XMLPreprocessError(
>              "Unknown Exception during validation\n" + str(sys.exc_info()[1]))
>  
>      # We have errors, return them in string form...
> -- 
> 2.15.1
> 
> 
> _______________________________________________
> elbe-devel mailing list
> elbe-devel at linutronix.de
> https://lists.linutronix.de/mailman/listinfo/elbe-devel

-- 
Mit freundlichen Grüßen
Torben Hohn

Linutronix GmbH

Standort: Bremen

Phone: +49 7556 25 999 18; Fax.: +49 7556 25 999 99

Firmensitz / Registered Office: D-88690 Uhldingen, Bahnhofstr. 3
Registergericht / Local District Court: Amtsgericht Freiburg i. Br.; HRB
Nr. / Trade register no.: 700 806

Geschäftsführer / Managing Directors: Heinz Egger, Thomas Gleixner

Eine Bitte von uns: Sollten Sie diese E-Mail irrtümlich erhalten haben,
benachrichtigen Sie uns in diesem Falle bitte sobald wie es Ihnen
möglich ist, durch Antwort-Mail. Vielen Dank!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: Digital signature
URL: <http://lists.linutronix.de/pipermail/elbe-devel/attachments/20180109/a92463a4/attachment.sig>


More information about the elbe-devel mailing list