V3 merge for most python scripts. fmod inclusion/linkage/packaging changes.
This commit is contained in:
@@ -41,14 +41,6 @@ import tarfile
|
||||
import errno
|
||||
import subprocess
|
||||
|
||||
class ManifestError(RuntimeError):
|
||||
"""Use an exception more specific than generic Python RuntimeError"""
|
||||
pass
|
||||
|
||||
class MissingError(ManifestError):
|
||||
"""You specified a file that doesn't exist"""
|
||||
pass
|
||||
|
||||
def path_ancestors(path):
|
||||
drive, path = os.path.splitdrive(os.path.normpath(path))
|
||||
result = []
|
||||
@@ -253,25 +245,15 @@ def main():
|
||||
for opt in args:
|
||||
print "Option:", opt, "=", args[opt]
|
||||
|
||||
# Build base package.
|
||||
touch = args.get('touch')
|
||||
if touch:
|
||||
print 'Creating base package'
|
||||
args['package_id'] = "" # base package has no package ID
|
||||
wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args)
|
||||
wm.do(*args['actions'])
|
||||
# Store package file for later if making touched file.
|
||||
base_package_file = ""
|
||||
if touch:
|
||||
print 'Created base package ', wm.package_file
|
||||
base_package_file = "" + wm.package_file
|
||||
|
||||
# Write out the package file in this format, so that it can easily be called
|
||||
# and used in a .bat file - yeah, it sucks, but this is the simplest...
|
||||
touch = args.get('touch')
|
||||
if touch:
|
||||
fp = open(touch, 'w')
|
||||
fp.write('set package_file=%s\n' % base_package_file)
|
||||
fp.write('set package_file=%s\n' % wm.package_file)
|
||||
fp.close()
|
||||
print 'touched', touch
|
||||
return 0
|
||||
@@ -298,13 +280,14 @@ class LLManifest(object):
|
||||
self.file_list = []
|
||||
self.excludes = []
|
||||
self.actions = []
|
||||
self.src_prefix = [args['source']]
|
||||
self.artwork_prefix = [args['artwork']]
|
||||
self.build_prefix = [args['build']]
|
||||
self.dst_prefix = [args['dest']]
|
||||
self.src_prefix = list([args['source']])
|
||||
self.artwork_prefix = list([args['artwork']])
|
||||
self.build_prefix = list([args['build']])
|
||||
self.alt_build_prefix = list([args['build']])
|
||||
self.dst_prefix = list([args['dest']])
|
||||
self.created_paths = []
|
||||
self.package_name = "Unknown"
|
||||
|
||||
|
||||
def default_grid(self):
|
||||
return self.args.get('grid', None) == ''
|
||||
def default_channel(self):
|
||||
@@ -328,7 +311,7 @@ class LLManifest(object):
|
||||
in the file list by path()."""
|
||||
self.excludes.append(glob)
|
||||
|
||||
def prefix(self, src='', build=None, dst=None):
|
||||
def prefix(self, src='', build=None, dst=None, alt_build=None):
|
||||
""" Pushes a prefix onto the stack. Until end_prefix is
|
||||
called, all relevant method calls (esp. to path()) will prefix
|
||||
paths with the entire prefix stack. Source and destination
|
||||
@@ -339,10 +322,15 @@ class LLManifest(object):
|
||||
dst = src
|
||||
if build is None:
|
||||
build = src
|
||||
if alt_build is None:
|
||||
alt_build = build
|
||||
|
||||
self.src_prefix.append(src)
|
||||
self.artwork_prefix.append(src)
|
||||
self.build_prefix.append(build)
|
||||
self.dst_prefix.append(dst)
|
||||
self.alt_build_prefix.append(alt_build)
|
||||
|
||||
return True # so that you can wrap it in an if to get indentation
|
||||
|
||||
def end_prefix(self, descr=None):
|
||||
@@ -355,25 +343,30 @@ class LLManifest(object):
|
||||
src = self.src_prefix.pop()
|
||||
artwork = self.artwork_prefix.pop()
|
||||
build = self.build_prefix.pop()
|
||||
alt_build_prefix = self.alt_build_prefix.pop()
|
||||
dst = self.dst_prefix.pop()
|
||||
if descr and not(src == descr or build == descr or dst == descr):
|
||||
raise ValueError, "End prefix '" + descr + "' didn't match '" +src+ "' or '" +dst + "'"
|
||||
|
||||
def get_src_prefix(self):
|
||||
""" Returns the current source prefix."""
|
||||
return os.path.join(*self.src_prefix)
|
||||
return os.path.relpath(os.path.normpath(os.path.join(*self.src_prefix)))
|
||||
|
||||
def get_artwork_prefix(self):
|
||||
""" Returns the current artwork prefix."""
|
||||
return os.path.join(*self.artwork_prefix)
|
||||
return os.path.relpath(os.path.normpath(os.path.join(*self.artwork_prefix)))
|
||||
|
||||
def get_build_prefix(self):
|
||||
""" Returns the current build prefix."""
|
||||
return os.path.join(*self.build_prefix)
|
||||
return os.path.relpath(os.path.normpath(os.path.join(*self.build_prefix)))
|
||||
|
||||
def get_alt_build_prefix(self):
|
||||
""" Returns the current alternate source prefix."""
|
||||
return os.path.relpath(os.path.normpath(os.path.join(*self.alt_build_prefix)))
|
||||
|
||||
def get_dst_prefix(self):
|
||||
""" Returns the current destination prefix."""
|
||||
return os.path.join(*self.dst_prefix)
|
||||
return os.path.relpath(os.path.normpath(os.path.join(*self.dst_prefix)))
|
||||
|
||||
def src_path_of(self, relpath):
|
||||
"""Returns the full path to a file or directory specified
|
||||
@@ -390,26 +383,10 @@ class LLManifest(object):
|
||||
relative to the destination directory."""
|
||||
return os.path.join(self.get_dst_prefix(), relpath)
|
||||
|
||||
def ensure_src_dir(self, reldir):
|
||||
"""Construct the path for a directory relative to the
|
||||
source path, and ensures that it exists. Returns the
|
||||
full path."""
|
||||
path = os.path.join(self.get_src_prefix(), reldir)
|
||||
self.cmakedirs(path)
|
||||
return path
|
||||
|
||||
def ensure_dst_dir(self, reldir):
|
||||
"""Construct the path for a directory relative to the
|
||||
destination path, and ensures that it exists. Returns the
|
||||
full path."""
|
||||
path = os.path.join(self.get_dst_prefix(), reldir)
|
||||
self.cmakedirs(path)
|
||||
return path
|
||||
|
||||
def run_command(self, command):
|
||||
""" Runs an external command, and returns the output. Raises
|
||||
an exception if the command returns a nonzero status code. For
|
||||
debugging/informational purposes, prints out the command's
|
||||
an exception if the command reurns a nonzero status code. For
|
||||
debugging/informational purpoases, prints out the command's
|
||||
output as it is received."""
|
||||
print "Running command:", command
|
||||
fd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
@@ -422,7 +399,7 @@ class LLManifest(object):
|
||||
print lines[-1].rstrip('\n'),
|
||||
output = ''.join(lines)
|
||||
if fd.returncode:
|
||||
raise ManifestError(
|
||||
raise RuntimeError(
|
||||
"Command %s returned non-zero status (%s) \noutput:\n%s"
|
||||
% (command, fd.returncode, output) )
|
||||
return output
|
||||
@@ -432,24 +409,14 @@ class LLManifest(object):
|
||||
a) verify that you really have created it
|
||||
b) schedule it for cleanup"""
|
||||
if not os.path.exists(path):
|
||||
raise ManifestError, "Should be something at path " + path
|
||||
raise RuntimeError, "Should be something at path " + path
|
||||
self.created_paths.append(path)
|
||||
|
||||
def put_in_file(self, contents, dst, src=None):
|
||||
def put_in_file(self, contents, dst):
|
||||
# write contents as dst
|
||||
dst_path = self.dst_path_of(dst)
|
||||
f = open(dst_path, "wb")
|
||||
try:
|
||||
f.write(contents)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
# Why would we create a file in the destination tree if not to include
|
||||
# it in the installer? The default src=None (plus the fact that the
|
||||
# src param is last) is to preserve backwards compatibility.
|
||||
if src:
|
||||
self.file_list.append([src, dst_path])
|
||||
return dst_path
|
||||
f = open(self.dst_path_of(dst), "wb")
|
||||
f.write(contents)
|
||||
f.close()
|
||||
|
||||
def replace_in(self, src, dst=None, searchdict={}):
|
||||
if dst == None:
|
||||
@@ -512,29 +479,30 @@ class LLManifest(object):
|
||||
if method is not None:
|
||||
method(src, dst)
|
||||
self.file_list.append([src, dst])
|
||||
return 1
|
||||
return [dst]
|
||||
else:
|
||||
sys.stdout.write(" (excluding %r, %r)" % (src, dst))
|
||||
sys.stdout.flush()
|
||||
return 0
|
||||
return []
|
||||
|
||||
def process_directory(self, src, dst):
|
||||
if not self.includes(src, dst):
|
||||
sys.stdout.write(" (excluding %r, %r)" % (src, dst))
|
||||
sys.stdout.flush()
|
||||
return 0
|
||||
return []
|
||||
names = os.listdir(src)
|
||||
self.cmakedirs(dst)
|
||||
errors = []
|
||||
found_files = []
|
||||
count = 0
|
||||
for name in names:
|
||||
srcname = os.path.join(src, name)
|
||||
dstname = os.path.join(dst, name)
|
||||
if os.path.isdir(srcname):
|
||||
count += self.process_directory(srcname, dstname)
|
||||
found_files.extend(self.process_directory(srcname, dstname))
|
||||
else:
|
||||
count += self.process_file(srcname, dstname)
|
||||
return count
|
||||
found_files.extend(self.process_file(srcname, dstname))
|
||||
return found_files
|
||||
|
||||
def includes(self, src, dst):
|
||||
if src:
|
||||
@@ -597,7 +565,7 @@ class LLManifest(object):
|
||||
except (IOError, os.error), why:
|
||||
errors.append((srcname, dstname, why))
|
||||
if errors:
|
||||
raise ManifestError, errors
|
||||
raise RuntimeError, errors
|
||||
|
||||
|
||||
def cmakedirs(self, path):
|
||||
@@ -614,25 +582,11 @@ class LLManifest(object):
|
||||
if os.path.exists(f):
|
||||
return f
|
||||
# didn't find it, return last item in list
|
||||
if len(list) > 0:
|
||||
if list:
|
||||
return list[-1]
|
||||
else:
|
||||
return None
|
||||
|
||||
def contents_of_tar(self, src_tar, dst_dir):
|
||||
""" Extracts the contents of the tarfile (specified
|
||||
relative to the source prefix) into the directory
|
||||
specified relative to the destination directory."""
|
||||
self.check_file_exists(src_tar)
|
||||
tf = tarfile.open(self.src_path_of(src_tar), 'r')
|
||||
for member in tf.getmembers():
|
||||
tf.extract(member, self.ensure_dst_dir(dst_dir))
|
||||
# TODO get actions working on these dudes, perhaps we should extract to a temporary directory and then process_directory on it?
|
||||
self.file_list.append([src_tar,
|
||||
self.dst_path_of(os.path.join(dst_dir,member.name))])
|
||||
tf.close()
|
||||
|
||||
|
||||
def wildcard_regex(self, src_glob, dst_glob):
|
||||
src_re = re.escape(src_glob)
|
||||
src_re = src_re.replace('\*', '([-a-zA-Z0-9._ ]*)')
|
||||
@@ -643,12 +597,7 @@ class LLManifest(object):
|
||||
i = i+1
|
||||
return re.compile(src_re), dst_temp
|
||||
|
||||
def check_file_exists(self, path):
|
||||
if not os.path.exists(path) and not os.path.islink(path):
|
||||
raise MissingError("Path %s doesn't exist" % (os.path.abspath(path),))
|
||||
|
||||
|
||||
wildcard_pattern = re.compile(r'\*')
|
||||
wildcard_pattern = re.compile('\*')
|
||||
def expand_globs(self, src, dst):
|
||||
src_list = glob.glob(src)
|
||||
src_re, d_template = self.wildcard_regex(src.replace('\\', '/'),
|
||||
@@ -675,53 +624,44 @@ class LLManifest(object):
|
||||
return self.path(os.path.join(path, file), file)
|
||||
|
||||
def path(self, src, dst=None):
|
||||
sys.stdout.write("Processing %s => %s ... " % (src, dst))
|
||||
sys.stdout.flush()
|
||||
if src == None:
|
||||
raise ManifestError("No source file, dst is " + dst)
|
||||
raise RuntimeError("No source file, dst is " + dst)
|
||||
if dst == None:
|
||||
dst = src
|
||||
dst = os.path.join(self.get_dst_prefix(), dst)
|
||||
sys.stdout.write("Processing %s => %s ... " % (src, dst))
|
||||
count = 0
|
||||
is_glob = False
|
||||
found_files = []
|
||||
|
||||
def try_path(src):
|
||||
# expand globs
|
||||
count = 0
|
||||
if self.wildcard_pattern.search(src):
|
||||
for s,d in self.expand_globs(src, dst):
|
||||
# look under each prefix for matching paths. Paths are normalized so './../blah' will match '../blah/../blah/'
|
||||
paths = set([os.path.normpath(os.path.join(self.get_src_prefix(), src)),
|
||||
os.path.normpath(os.path.join(self.get_artwork_prefix(), src)),
|
||||
os.path.normpath(os.path.join(self.get_build_prefix(), src)),
|
||||
os.path.normpath(os.path.join(self.get_alt_build_prefix(), src))]
|
||||
)
|
||||
for path in paths:
|
||||
print path
|
||||
if self.wildcard_pattern.search(path):
|
||||
is_glob = True
|
||||
for s,d in self.expand_globs(path, dst):
|
||||
assert(s != d)
|
||||
count += self.process_file(s, d)
|
||||
found_files.extend(self.process_file(s, d))
|
||||
else:
|
||||
# if we're specifying a single path (not a glob),
|
||||
# we should error out if it doesn't exist
|
||||
self.check_file_exists(src)
|
||||
# if it's a directory, recurse through it
|
||||
if os.path.isdir(src):
|
||||
count += self.process_directory(src, dst)
|
||||
else:
|
||||
count += self.process_file(src, dst)
|
||||
return count
|
||||
if os.path.isdir(path):
|
||||
found_files.extend(self.process_directory(path, dst))
|
||||
elif os.path.exists(path):
|
||||
found_files.extend(self.process_file(path, dst))
|
||||
|
||||
for pfx in self.get_src_prefix(), self.get_artwork_prefix(), self.get_build_prefix():
|
||||
try:
|
||||
count = try_path(os.path.join(pfx, src))
|
||||
except MissingError:
|
||||
# If src isn't a wildcard, and if that file doesn't exist in
|
||||
# this pfx, try next pfx.
|
||||
count = 0
|
||||
continue
|
||||
# if we're specifying a single path (not a glob),
|
||||
# we should error out if it doesn't exist
|
||||
if not found_files and not is_glob:
|
||||
raise RuntimeError("No files match %s\n" % str(paths))
|
||||
|
||||
# Here try_path() didn't raise MissingError. Did it process any files?
|
||||
if count:
|
||||
break
|
||||
# Even though try_path() didn't raise MissingError, it returned 0
|
||||
# files. src is probably a wildcard meant for some other pfx. Loop
|
||||
# back to try the next.
|
||||
|
||||
print "%d files" % count
|
||||
|
||||
# Let caller check whether we processed as many files as expected. In
|
||||
# particular, let caller notice 0.
|
||||
return count
|
||||
print "%d files" % len(found_files)
|
||||
return found_files
|
||||
|
||||
def do(self, *actions):
|
||||
self.actions = actions
|
||||
|
||||
@@ -1,4 +1,28 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
"""\
|
||||
@file llperformance.py
|
||||
|
||||
$LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
Second Life Viewer Source Code
|
||||
Copyright (C) 2010-2011, Linden Research, Inc.
|
||||
|
||||
This library 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;
|
||||
version 2.1 of the License only.
|
||||
|
||||
This library 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 this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
# ------------------------------------------------
|
||||
# Sim metrics utility functions.
|
||||
|
||||
@@ -90,6 +90,17 @@ all the output, and get the result.
|
||||
child.tochild.close()
|
||||
result = child.poll()
|
||||
if result != -1:
|
||||
# At this point, the child process has exited and result
|
||||
# is the return value from the process. Between the time
|
||||
# we called select() and poll() the process may have
|
||||
# exited so read all the data left on the child process
|
||||
# stdout and stderr.
|
||||
last = child.fromchild.read()
|
||||
if last:
|
||||
out.append(last)
|
||||
last = child.childerr.read()
|
||||
if last:
|
||||
err.append(last)
|
||||
child.tochild.close()
|
||||
child.fromchild.close()
|
||||
child.childerr.close()
|
||||
|
||||
@@ -40,7 +40,6 @@ from indra.base import llsd
|
||||
from indra.base import config
|
||||
|
||||
DEBUG = False
|
||||
|
||||
NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
|
||||
NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
|
||||
|
||||
@@ -52,6 +51,11 @@ def _init_g_named_manager(sql_dir = None):
|
||||
|
||||
This function is intended entirely for testing purposes,
|
||||
because it's tricky to control the config from inside a test."""
|
||||
global NQ_FILE_SUFFIX
|
||||
NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
|
||||
global NQ_FILE_SUFFIX_LEN
|
||||
NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
|
||||
|
||||
if sql_dir is None:
|
||||
sql_dir = config.get('named-query-base-dir')
|
||||
|
||||
@@ -65,11 +69,11 @@ def _init_g_named_manager(sql_dir = None):
|
||||
_g_named_manager = NamedQueryManager(
|
||||
os.path.abspath(os.path.realpath(sql_dir)))
|
||||
|
||||
def get(name):
|
||||
def get(name, schema = None):
|
||||
"Get the named query object to be used to perform queries"
|
||||
if _g_named_manager is None:
|
||||
_init_g_named_manager()
|
||||
return _g_named_manager.get(name)
|
||||
return _g_named_manager.get(name).for_schema(schema)
|
||||
|
||||
def sql(connection, name, params):
|
||||
# use module-global NamedQuery object to perform default substitution
|
||||
@@ -280,7 +284,10 @@ class NamedQuery(object):
|
||||
|
||||
So, we need a vendor (or extention) for LIKE_STRING. Anyone
|
||||
want to write it?"""
|
||||
utf8_value = unicode(value, "utf-8")
|
||||
if isinstance(value, unicode):
|
||||
utf8_value = value
|
||||
else:
|
||||
utf8_value = unicode(value, "utf-8")
|
||||
esc_list = []
|
||||
remove_chars = set(u"%_")
|
||||
for glyph in utf8_value:
|
||||
@@ -317,6 +324,8 @@ class NamedQuery(object):
|
||||
|
||||
def for_schema(self, db_name):
|
||||
"Look trough the alternates and return the correct query"
|
||||
if db_name is None:
|
||||
return self
|
||||
try:
|
||||
return self._alternative[db_name]
|
||||
except KeyError, e:
|
||||
@@ -341,21 +350,21 @@ class NamedQuery(object):
|
||||
cursor = connection.cursor(MySQLdb.cursors.DictCursor)
|
||||
else:
|
||||
cursor = connection.cursor()
|
||||
|
||||
statement = self.sql(connection, params)
|
||||
|
||||
full_query, params = self._construct_sql(params)
|
||||
if DEBUG:
|
||||
print "SQL:", statement
|
||||
rows = cursor.execute(statement)
|
||||
|
||||
print "SQL:", self.sql(connection, params)
|
||||
rows = cursor.execute(full_query, params)
|
||||
|
||||
# *NOTE: the expect_rows argument is a very cheesy way to get some
|
||||
# validation on the result set. If you want to add more expectation
|
||||
# logic, do something more object-oriented and flexible. Or use an ORM.
|
||||
# logic, do something more object-oriented and flexible. Or use an ORM.
|
||||
if(self._return_as_map):
|
||||
expect_rows = 1
|
||||
if expect_rows is not None and rows != expect_rows:
|
||||
cursor.close()
|
||||
raise ExpectationFailed("Statement expected %s rows, got %s. Sql: %s" % (
|
||||
expect_rows, rows, statement))
|
||||
raise ExpectationFailed("Statement expected %s rows, got %s. Sql: '%s' %s" % (
|
||||
expect_rows, rows, full_query, params))
|
||||
|
||||
# convert to dicts manually if we're not using a dictcursor
|
||||
if use_dictcursor:
|
||||
@@ -381,11 +390,9 @@ class NamedQuery(object):
|
||||
return result_set[0]
|
||||
return result_set
|
||||
|
||||
def sql(self, connection, params):
|
||||
""" Generates an SQL statement from the named query document
|
||||
and a dictionary of parameters.
|
||||
|
||||
"""
|
||||
def _construct_sql(self, params):
|
||||
""" Returns a query string and a dictionary of parameters,
|
||||
suitable for directly passing to the execute() method."""
|
||||
self.refresh()
|
||||
|
||||
# build the query from the options available and the params
|
||||
@@ -431,10 +438,23 @@ class NamedQuery(object):
|
||||
new_params[self._build_integer_key(key)] = int(params[key])
|
||||
params.update(new_params)
|
||||
|
||||
return full_query, params
|
||||
|
||||
def sql(self, connection, params):
|
||||
""" Generates an SQL statement from the named query document
|
||||
and a dictionary of parameters.
|
||||
|
||||
*NOTE: Only use for debugging, because it uses the
|
||||
non-standard MySQLdb 'literal' method.
|
||||
"""
|
||||
if not DEBUG:
|
||||
import warnings
|
||||
warnings.warn("Don't use named_query.sql() when not debugging. Used on %s" % self._location)
|
||||
# do substitution using the mysql (non-standard) 'literal'
|
||||
# function to do the escaping.
|
||||
sql = full_query % connection.literal(params)
|
||||
return sql
|
||||
full_query, params = self._construct_sql(params)
|
||||
return full_query % connection.literal(params)
|
||||
|
||||
|
||||
def refresh(self):
|
||||
""" Refresh self from the file on the filesystem.
|
||||
|
||||
@@ -3,20 +3,27 @@
|
||||
@file simperf_oprof_interface.py
|
||||
@brief Manage OProfile data collection on a host
|
||||
|
||||
$LicenseInfo:firstyear=2008&license=internal$
|
||||
$LicenseInfo:firstyear=2008&license=mit$
|
||||
|
||||
Copyright (c) 2008-2009, Linden Research, Inc.
|
||||
|
||||
The following source code is PROPRIETARY AND CONFIDENTIAL. Use of
|
||||
this source code is governed by the Linden Lab Source Code Disclosure
|
||||
Agreement ("Agreement") previously entered between you and Linden
|
||||
Lab. By accessing, using, copying, modifying or distributing this
|
||||
software, you acknowledge that you have been informed of your
|
||||
obligations under the Agreement and agree to abide by those obligations.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
COMPLETENESS OR PERFORMANCE.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,4 +1,31 @@
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
"""\
|
||||
@file simperf_proc_interface.py
|
||||
@brief Utility to extract log messages from *.<pid>.llsd files containing performance statistics.
|
||||
|
||||
$LicenseInfo:firstyear=2008&license=mit$
|
||||
|
||||
Copyright (c) 2008-2009, Linden Research, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
# ----------------------------------------------------
|
||||
# Utility to extract log messages from *.<pid>.llsd
|
||||
|
||||
146
indra/lib/python/indra/util/test_win32_manifest.py
Normal file
146
indra/lib/python/indra/util/test_win32_manifest.py
Normal file
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/env python
|
||||
"""\
|
||||
@file test_win32_manifest.py
|
||||
@brief Test an assembly binding version and uniqueness in a windows dll or exe.
|
||||
|
||||
$LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
Second Life Viewer Source Code
|
||||
Copyright (C) 2009-2011, Linden Research, Inc.
|
||||
|
||||
This library 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;
|
||||
version 2.1 of the License only.
|
||||
|
||||
This library 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 this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
import sys, os
|
||||
import tempfile
|
||||
from xml.dom.minidom import parse
|
||||
|
||||
class AssemblyTestException(Exception):
|
||||
pass
|
||||
|
||||
class NoManifestException(AssemblyTestException):
|
||||
pass
|
||||
|
||||
class MultipleBindingsException(AssemblyTestException):
|
||||
pass
|
||||
|
||||
class UnexpectedVersionException(AssemblyTestException):
|
||||
pass
|
||||
|
||||
class NoMatchingAssemblyException(AssemblyTestException):
|
||||
pass
|
||||
|
||||
def get_HKLM_registry_value(key_str, value_str):
|
||||
import _winreg
|
||||
reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
|
||||
key = _winreg.OpenKey(reg, key_str)
|
||||
value = _winreg.QueryValueEx(key, value_str)[0]
|
||||
#print 'Found: %s' % value
|
||||
return value
|
||||
|
||||
def find_vc_dir():
|
||||
supported_versions = (r'8.0', r'9.0')
|
||||
supported_products = (r'VisualStudio', r'VCExpress')
|
||||
value_str = (r'ProductDir')
|
||||
|
||||
for product in supported_products:
|
||||
for version in supported_versions:
|
||||
key_str = (r'SOFTWARE\Microsoft\%s\%s\Setup\VC' %
|
||||
(product, version))
|
||||
try:
|
||||
return get_HKLM_registry_value(key_str, value_str)
|
||||
except WindowsError, err:
|
||||
x64_key_str = (r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%s\Setup\VS' %
|
||||
version)
|
||||
try:
|
||||
return get_HKLM_registry_value(x64_key_str, value_str)
|
||||
except:
|
||||
print >> sys.stderr, "Didn't find MS %s version %s " % (product,version)
|
||||
|
||||
raise
|
||||
|
||||
def find_mt_path():
|
||||
vc_dir = find_vc_dir()
|
||||
mt_path = '\"%sbin\\mt.exe\"' % vc_dir
|
||||
return mt_path
|
||||
|
||||
def test_assembly_binding(src_filename, assembly_name, assembly_ver):
|
||||
print "checking %s dependency %s..." % (src_filename, assembly_name)
|
||||
|
||||
(tmp_file_fd, tmp_file_name) = tempfile.mkstemp(suffix='.xml')
|
||||
tmp_file = os.fdopen(tmp_file_fd)
|
||||
tmp_file.close()
|
||||
|
||||
mt_path = find_mt_path()
|
||||
resource_id = ""
|
||||
if os.path.splitext(src_filename)[1].lower() == ".dll":
|
||||
resource_id = ";#2"
|
||||
system_call = '%s -nologo -inputresource:%s%s -out:%s > NUL' % (mt_path, src_filename, resource_id, tmp_file_name)
|
||||
print "Executing: %s" % system_call
|
||||
mt_result = os.system(system_call)
|
||||
if mt_result == 31:
|
||||
print "No manifest found in %s" % src_filename
|
||||
raise NoManifestException()
|
||||
|
||||
manifest_dom = parse(tmp_file_name)
|
||||
nodes = manifest_dom.getElementsByTagName('assemblyIdentity')
|
||||
|
||||
versions = list()
|
||||
for node in nodes:
|
||||
if node.getAttribute('name') == assembly_name:
|
||||
versions.append(node.getAttribute('version'))
|
||||
|
||||
if len(versions) == 0:
|
||||
print "No matching assemblies found in %s" % src_filename
|
||||
raise NoMatchingAssemblyException()
|
||||
|
||||
elif len(versions) > 1:
|
||||
print "Multiple bindings to %s found:" % assembly_name
|
||||
print versions
|
||||
print
|
||||
raise MultipleBindingsException(versions)
|
||||
|
||||
elif versions[0] != assembly_ver:
|
||||
print "Unexpected version found for %s:" % assembly_name
|
||||
print "Wanted %s, found %s" % (assembly_ver, versions[0])
|
||||
print
|
||||
raise UnexpectedVersionException(assembly_ver, versions[0])
|
||||
|
||||
os.remove(tmp_file_name)
|
||||
|
||||
print "SUCCESS: %s OK!" % src_filename
|
||||
print
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print
|
||||
print "Running test_win32_manifest.py..."
|
||||
|
||||
usage = 'test_win32_manfest <srcFileName> <assemblyName> <assemblyVersion>'
|
||||
|
||||
try:
|
||||
src_filename = sys.argv[1]
|
||||
assembly_name = sys.argv[2]
|
||||
assembly_ver = sys.argv[3]
|
||||
except:
|
||||
print "Usage:"
|
||||
print usage
|
||||
print
|
||||
raise
|
||||
|
||||
test_assembly_binding(src_filename, assembly_name, assembly_ver)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user