summaryrefslogtreecommitdiff
path: root/scripts/template_verifier.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/template_verifier.py')
-rwxr-xr-xscripts/template_verifier.py82
1 files changed, 70 insertions, 12 deletions
diff --git a/scripts/template_verifier.py b/scripts/template_verifier.py
index 67728d73d8..6fbb787f6f 100755
--- a/scripts/template_verifier.py
+++ b/scripts/template_verifier.py
@@ -54,6 +54,7 @@ DEVELOPMENT_ACCEPTABLE = (
compatibility.Same, compatibility.Newer,
compatibility.Older, compatibility.Mixed)
+MAX_MASTER_AGE = 60 * 60 * 4 # refresh master cache every 4 hours
def compare(base, current, mode):
"""Compare the current template against the base template using the given
@@ -68,6 +69,8 @@ def compare(base, current, mode):
Returns a tuple of (bool, Compatibility)
Return True if they are compatible in this mode, False if not.
"""
+
+ # catch this exception so we can print a message explaining which template is scr0d
try:
base = llmessage.parseTemplateString(base)
except tokenstream.ParseError, e:
@@ -90,12 +93,45 @@ def compare(base, current, mode):
return True, compat
return False, compat
+def fetch(url):
+ # *FIX: this doesn't throw an exception for a 404, and oddly enough the sl.com 404 page actually gets parsed successfully
+ return ''.join(urllib.urlopen(url).readlines())
+
+def cache_master(master_url):
+ """Using the url for the master, updates the local cache, and returns an url to the local cache."""
+ master_cache = local_master_cache_filename()
+ master_cache_url = 'file://' + master_cache
+ # decide whether to refresh the master cache based on its age
+ import time
+ if (os.path.exists(master_cache)
+ and time.time() - os.path.getmtime(master_cache) < MAX_MASTER_AGE):
+ return master_cache_url # our cache is fresh
+ # new master doesn't exist or isn't fresh
+ print "Refreshing master cache from %s" % master_url
+ try:
+ new_master_contents = fetch(master_url)
+ except IOError, e:
+ # the refresh failed, so we should just soldier on
+ print "WARNING: unable to download new master, probably due to network error. Your message template compatibility may be suspect."
+ return master_cache_url
+ mc = open(master_cache, 'wb')
+ mc.write(new_master_contents)
+ mc.close()
+ return master_cache_url
+
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 local_master_cache_filename():
+ """Returns the location of the master template cache relative to template_verifier.py
+ ./messages/master_message_template_cache.msg"""
+ d = os.path.dirname(os.path.realpath(__file__))
+ return os.path.join(d, 'messages', 'master_message_template_cache.msg')
+
+
def run(sysargs):
parser = optparse.OptionParser(
usage="usage: %prog [FILE] [FILE]",
@@ -112,43 +148,65 @@ http://wiki.secondlife.com/wiki/Template_verifier.py
'-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.""")
+ parser.add_option(
+ '-c', '--cache_master', action='store_true', dest='cache_master',
+ default=False, help="""Set to true to attempt use local cached copy of the master template.""")
options, args = parser.parse_args(sysargs)
+ if options.mode == 'production':
+ options.cache_master = False
+
# 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()
+ master_url = 'file://%s' % master_filename
+ current_url = 'file://%s' % current_filename
# only current supplied in positional param
elif len(args) == 1:
- master = None
+ master_url = None
current_filename = args[0]
print "base: <master template from repository>"
print "current:", current_filename
- current = file(current_filename).read()
+ current_url = 'file://%s' % current_filename
# nothing specified, use defaults for everything
elif len(args) == 0:
- master = None
- current = None
+ master_url = None
+ current_url = None
else:
die("Too many arguments")
- # fetch the master from the url (default or supplied)
- if master is None:
- master = ''.join(urllib.urlopen(options.master_url).readlines())
-
+ if master_url is None:
+ master_url = options.master_url
+
# fetch the template for this build
- if current is None:
+ if current_url is None:
current_filename = local_template_filename()
print "base: <master template from repository>"
print "current:", current_filename
- current = file(current_filename).read()
+ current_url = 'file://%s' % current_filename
+
+ if options.cache_master:
+ # optionally return a url to a locally-cached master so we don't hit the network all the time
+ master_url = cache_master(master_url)
+
+ current = fetch(current_url)
+ try:
+ master = fetch(master_url)
+ except IOError, e:
+ if options.mode == 'production':
+ raise e
+ else:
+ print "WARNING: problems fetching the master from %s. Syntax-checking the local template ONLY, no compatibility check is being run." % master_url
+ llmessage.parseTemplateString(current)
+ return 0
+
acceptable, compat = compare(
master, current, options.mode)
+
def explain(header, compat):
print header