From 57b8fef824b6d7f37c5be5812ebffa39ab2e8093 Mon Sep 17 00:00:00 2001 From: Tess Chu Date: Wed, 11 Jul 2007 21:29:02 +0000 Subject: svn merge --ignore-ancestry svn+ssh://svn/svn/linden/release@65088 svn+ssh://svn/svn/linden/branches/release-candidate@65078 -> release Paired by Tess and rdw. --- scripts/template_verifier.py | 155 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100755 scripts/template_verifier.py (limited to 'scripts/template_verifier.py') diff --git a/scripts/template_verifier.py b/scripts/template_verifier.py new file mode 100755 index 0000000000..83f3ae61f5 --- /dev/null +++ b/scripts/template_verifier.py @@ -0,0 +1,155 @@ +#!/usr/bin/python +# @file template_verifier.py +# @brief Message template compatibility verifier. +# +# Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. +# $License$ + +"""template_verifier is a script which will compare the +current repository message template with the "master" message template, accessible +via http://secondlife.com/app/message_template/master_message_template.msg +If [FILE] is specified, it will be checked against the master template. +If [FILE] [FILE] is specified, two local files will be checked against +each other. +""" + +from os.path import realpath, dirname, join, exists +setup_path = join(dirname(realpath(__file__)), "setup-path.py") +if exists(setup_path): + execfile(setup_path) +import optparse +import os +import sys +import urllib + +from indra import compatibility +from indra import llmessage + +def die(msg): + print >>sys.stderr, msg + sys.exit(1) + +MESSAGE_TEMPLATE = 'message_template.msg' + +PRODUCTION_ACCEPTABLE = (compatibility.Same, compatibility.Newer) +DEVELOPMENT_ACCEPTABLE = ( + compatibility.Same, compatibility.Newer, + compatibility.Older, compatibility.Mixed) + +def getstatusall(command): + """ Like commands.getstatusoutput, but returns stdout and + stderr separately(to get around "killed by signal 15" getting + included as part of the file). Also, works on Windows.""" + (input, out, err) = os.popen3(command, 't') + input.close() # send no input to the command + output = out.read() + error = err.read() + out.close() + status = err.close() # the status comes from the *last* pipe you close + return status, output, error + +def getstatusoutput(command): + status, output, error = getstatusall(command) + return status, output + +def compare(base, current, mode): + """Compare the current template against the base template using the given + 'mode' strictness: + + development: Allows Same, Newer, Older, and Mixed + production: Allows only Same or Newer + + Print out information about whether the current template is compatible + with the base template. + + Returns a tuple of (bool, Compatibility) + Return True if they are compatible in this mode, False if not. + """ + base = llmessage.parseTemplateString(base) + current = llmessage.parseTemplateString(current) + + compat = current.compatibleWithBase(base) + if mode == 'production': + acceptable = PRODUCTION_ACCEPTABLE + else: + acceptable = DEVELOPMENT_ACCEPTABLE + + if type(compat) in acceptable: + return True, compat + return False, compat + +def local_template_filename(): + """Returns the message template's default location relative to template_verifier.py: + ./messages/message_template.msg.""" + d = os.path.dirname(os.path.realpath(__file__)) + return os.path.join(d, 'messages', MESSAGE_TEMPLATE) + +def run(sysargs): + parser = optparse.OptionParser( + usage="usage: %prog [FILE] [FILE]", + description=__doc__) + parser.add_option( + '-m', '--mode', type='string', dest='mode', + default='development', + help="""[development|production] The strictness mode to use +while checking the template; see the wiki page for details about +what is allowed and disallowed by each mode: +http://wiki.secondlife.com/wiki/Template_verifier.py +""") + parser.add_option( + '-u', '--master_url', type='string', dest='master_url', + default='http://secondlife.com/app/message_template/master_message_template.msg', + help="""The url of the master message template.""") + + options, args = parser.parse_args(sysargs) + + # both current and master supplied in positional params + if len(args) == 2: + master_filename, current_filename = args + print "base:", master_filename + print "current:", current_filename + master = file(master_filename).read() + current = file(current_filename).read() + # only current supplied in positional param + elif len(args) == 1: + master = None + current_filename = args[0] + print "base: " + print "current:", current_filename + current = file(current_filename).read() + # nothing specified, use defaults for everything + elif len(args) == 0: + master = None + current = None + else: + die("Too many arguments") + + # fetch the master from the url (default or supplied) + if master is None: + master = urllib.urlopen(options.master_url).read() + + # fetch the template for this build + if current is None: + current_filename = local_template_filename() + print "base: " + print "current:", current_filename + current = file(current_filename).read() + + acceptable, compat = compare( + master, current, options.mode) + + def explain(header, compat): + print header + # indent compatibility explanation + print '\n\t'.join(compat.explain().split('\n')) + + if acceptable: + explain("--- PASS ---", compat) + else: + explain("*** FAIL ***", compat) + return 1 + +if __name__ == '__main__': + sys.exit(run(sys.argv[1:])) + + -- cgit v1.2.3