#!/usr/bin/python """ NAME - metagen SYNOPSIS - Adds metadata.xml to current directory AUTHOR - Rob Cakebread AUTHOR - Jesus Rivero USE - metagen --help EXAMPLES - man metagen """ import re import os import sys import tempfile from argparse import ArgumentParser from commands import getstatusoutput from textwrap import dedent from portage import config from portage.exception import FileNotFound from portage.output import red, blue, yellow from metagen.version import __version__ from metagen import metagenerator PORTDIR = config(local_config=False)["PORTDIR"] # GLEP 67 _MAINTAINER_TYPE_PERSON = 'person' _MAINTAINER_TYPE_PROJECT = 'project' _MAINTAINER_TYPE_UNKNOWN = 'unknown' _VALID_MAINTAINER_TYPES = (_MAINTAINER_TYPE_PERSON, _MAINTAINER_TYPE_PROJECT, _MAINTAINER_TYPE_UNKNOWN) def parse_echangelog_variable(name, email): """Extract developer name and email from ECHANGELOG_USER variable""" try: e = os.environ["ECHANGELOG_USER"] except KeyError: print red("!!! Environmental variable ECHANGELOG_USER not set.") print red("!!! Set ECHANGELOG_USER or use -e and -n") sys.exit(1) try: my_email = e[e.find("<") +1:e.find(">")] except: print red("!!! ECHANGELOG_USER not set properly") sys.exit(1) try: my_name = e[0:e.find("<")-1] except: print red("!!! ECHANGELOG_USER not set properly") sys.exit(1) if email: email = "%s,%s" % (my_email, email) else: email = my_email if name: name = "%s,%s" % (my_name, name) else: name = my_name return name, email def generate_xml(options): """Returns metadata.xml text""" metadata = metagenerator.MyMetadata() if options.echangelog: (options.name, options.email) = \ parse_echangelog_variable(options.name, options.email) if options.email: names, descs = [], [] if options.name: names = options.name.split(",") if options.desc: descs = options.desc.split(",") maintainer_types = options.maintainer_type.split(",") metadata.set_maintainer(options.email.split(","), names, descs, maintainer_types, ) if options.long: metadata.set_longdescription(options.long) return "%s" % metadata def validate_xml(my_xml): """Test for valid XML""" #TODO validate against DTD #This just makes sure its valid XML of some sort. #Probably not necessary since repoman validates against DTD? re_escape_quotes = re.compile('"') s = re_escape_quotes.sub('\\"', my_xml) cmd = "echo \"%s\" | xmllint --valid - 2>&1 > /dev/null" % s return getstatusoutput(cmd)[0] def _check_maintainer_type_list(text): for candidate in text.split(','): if candidate not in _VALID_MAINTAINER_TYPES: raise ValueError('"%s" not a valid maintainer type' % candidate) return text _check_maintainer_type_list.__name__ = 'maintainer type' if __name__ == '__main__': parser = ArgumentParser(prog='metagen') parser.add_argument('--version', action='version', version='%(prog)s ' + __version__) maintainer = parser.add_argument_group(title='maintainer arguments') maintainer.add_argument("--email", "-e", action="store", help="Maintainer's email address") maintainer.add_argument("--name", "-n", action="store", help="Maintainer's name") maintainer.add_argument("--echangelog", "-m", action="store_true", default=False, help="Use name and email address from ECHANGELOG_USER "+ "environmental variable. "+ "This is a shortcut for -e -n ") maintainer.add_argument("--desc", "-d", action="store", help="Description of maintainership") maintainer.add_argument("--type", "-t", dest='maintainer_type', metavar='TYPE', type=_check_maintainer_type_list, help="Maintainer type as of GLEP 67; valid values are: %s" \ % ', '.join('"%s"' % e for e in _VALID_MAINTAINER_TYPES)) package = parser.add_argument_group(title='package arguments', description=None) package.add_argument("--long", "-l", action="store", help="Long description of package.") operation = parser.add_argument_group(title='operation arguments', description=None) operation.add_argument("--output", "-o", action="store", help="Specify location of output file.") operation.add_argument("--force", "-f", action="store_true", default=False, help="Force overwrite of existing metadata.") operation.add_argument("--verbose", "-v", action="store_true", default=True, help="Verbose. Output of file to stdout. (default)") operation.add_argument("--quiet", "-q", action="store_false", dest="verbose", help="Squelch output of file to stdout.") operation.add_argument("-Q", action="store_true", dest="no_write", default=False, help="Do not write file to disk.") options = parser.parse_args() if options.desc or options.name: if not options.email and not options.echangelog: print red("!!! No maintainer's email address specified.") print red("!!! Options -d and -n are only valid with -e or -m") sys.exit(1) if not options.email and not options.echangelog: print red("!!! You must specify --echangelog|-m " + "or maintainer's email address (-e)\n") sys.exit(1) if (options.email or options.echangelog) and not options.maintainer_type: print red("!!! No maintainer type specified. Please pass one of the following, in addition:") for candidate in _VALID_MAINTAINER_TYPES: print red("!!! --type %s" % candidate) sys.exit(1) txt = generate_xml(options) error_status = validate_xml(txt) if error_status < 0: print red("!!! Error - Invalid XML") print red("!!! Please report this bug with the options you used and the output:") print error_status print txt sys.exit(1) if options.verbose: print "\n%s" % txt out_file = "./metadata.xml" if options.output: out_file = options.output if not options.no_write and os.path.exists(out_file): if not options.force: print red("!!! File %s exists." % out_file) print red("!!! Use -f to force overwrite.") sys.exit(1) if not options.no_write: open("%s" % out_file, "w").writelines(txt) print blue("%s written") % out_file