Imported existing code

This commit is contained in:
Hazim Gazov
2010-04-02 02:48:44 -03:00
parent 48fbc5ae91
commit 7a86d01598
13996 changed files with 2468699 additions and 0 deletions

View File

@@ -0,0 +1,458 @@
#!/bin/sh
# This is the build script used by Linden Lab's autmated build system.
#
set -x
export INSTALL_USE_HTTP_FOR_SCP=true
export PATH=/bin:/usr/bin:$PATH
arch=`uname | cut -b-6`
here=`echo $0 | sed 's:[^/]*$:.:'`
year=`date +%Y`
branch=`svn info | grep '^URL:' | sed 's:.*/::'`
revision=`svn info | grep '^Revision:' | sed 's/.*: //'`
top=`cd "$here/../../.." && pwd`
[ x"$WGET_CACHE" = x ] && export WGET_CACHE=/var/tmp/parabuild/wget
[ x"$S3GET_URL" = x ] && export S3GET_URL=http://viewer-source-downloads.s3.amazonaws.com/$year
[ x"$S3PUT_URL" = x ] && export S3PUT_URL=https://s3.amazonaws.com/viewer-source-downloads/$year
[ x"$S3SYMBOL_URL" = x ] && export S3SYMBOL_URL=https://s3.amazonaws.com/automated-builds-secondlife-com/binaries
[ x"$PUBLIC_URL" = x ] && export PUBLIC_URL=http://secondlife.com/developers/opensource/downloads/$year
[ x"$PUBLIC_EMAIL" = x ] && export PUBLIC_EMAIL=sldev-commits@lists.secondlife.com
# Make sure command worked and bail out if not, reporting failure to parabuild
fail()
{
release_lock
echo "BUILD FAILED" $@
exit 1
}
pass()
{
release_lock
echo "BUILD SUCCESSFUL"
exit 0
}
# Locking to avoid contention with u-s-c
LOCK_CREATE=/usr/bin/lockfile-create
LOCK_TOUCH=/usr/bin/lockfile-touch
LOCK_REMOVE=/usr/bin/lockfile-remove
LOCK_PROCESS=
locking_available()
{
test -x "$LOCK_CREATE"\
-a -x "$LOCK_TOUCH"\
-a -x "$LOCK_REMOVE"
}
acquire_lock()
{
if locking_available
then
if "$LOCK_CREATE" /var/lock/update-system-config --retry 99
then
"$LOCK_TOUCH" /var/lock/update-system-config &
LOCK_PROCESS="$!"
else
fail acquire lock
fi
else
true
fi
}
release_lock()
{
if locking_available
then
if test x"$LOCK_PROCESS" != x
then
kill "$LOCK_PROCESS"
"$LOCK_REMOVE" /var/lock/update-system-config
else
echo No Lock Acquired >&2
fi
else
true
fi
}
get_asset()
{
mkdir -p "$WGET_CACHE" || fail creating WGET_CACHE
local tarball=`basename "$1"`
test -r "$WGET_CACHE/$tarball" || ( cd "$WGET_CACHE" && curl --location --remote-name "$1" || fail getting $1 )
case "$tarball" in
*.zip) unzip -qq -d "$top" -o "$WGET_CACHE/$tarball" || fail unzip $tarball ;;
*.tar.gz|*.tgz) tar -C "$top" -xzf "$WGET_CACHE/$tarball" || fail untar $tarball ;;
*) fail unrecognized filetype: $tarball ;;
esac
}
s3_available()
{
test -x "$helpers/s3get.sh" -a -x "$helpers/s3put.sh" -a -r "$helpers/s3curl.pl"
}
build_dir_Darwin()
{
echo build-darwin-universal
}
build_dir_Linux()
{
echo viewer-linux-i686-`echo $1 | tr A-Z a-z`
}
build_dir_CYGWIN()
{
echo build-vc80
}
installer_Darwin()
{
ls -1td "`build_dir_Darwin Release`/newview/"*.dmg 2>/dev/null | sed 1q
}
installer_Linux()
{
ls -1td "`build_dir_Linux Release`/newview/"*.tar.bz2 2>/dev/null | sed 1q
}
installer_CYGWIN()
{
d=`build_dir_CYGWIN Release`
p=`sed 's:.*=::' "$d/newview/Release/touched.bat"`
echo "$d/newview/Release/$p"
}
# deal with aborts etc..
trap fail 1 2 3 14 15
# Check location
cd "$here/../.."
test -x ../linden/scripts/automated_build_scripts/opensrc-build.sh\
|| fail 'The parent dir of your checkout needs to be named "linden"'
. doc/asset_urls.txt
get_asset "$SLASSET_ART"
update_version_files=
# Set up platform specific stuff
case "$arch" in
# Note that we can only build the "Release" variant for Darwin, because of a compiler bug:
# ld: bl out of range (-16777272 max is +/-16M)
# from __static_initialization_and_destruction_0(int, int)at 0x033D319C
# in __StaticInit of
# indra/build-darwin-universal/newview/SecondLife.build/Debug/Second Life.build/Objects-normal/ppc/llvoicevisualizer.o
# to ___cxa_atexit$island_2 at 0x023D50F8
# in __text of
# indra/build-darwin-universal/newview/SecondLife.build/Debug/Second Life.build/Objects-normal/ppc/Second Life
# in __static_initialization_and_destruction_0(int, int)
# from indra/build-darwin-universal/newview/SecondLife.build/Debug/Second Life.build/Objects-normal/ppc/llvoicevisualizer.o
Darwin)
helpers=/usr/local/buildscripts/shared/latest
variants="Release"
cmake_generator="Xcode"
fmod=fmodapi375mac
fmod_tar="$fmod.zip"
fmod_so=libfmod.a
fmod_lib=lib
target_dirs="libraries/universal-darwin/lib_debug
libraries/universal-darwin/lib_release
libraries/universal-darwin/lib_release_client"
other_archs="$S3GET_URL/$branch/$revision/CYGWIN $S3GET_URL/$branch/$revision/Linux"
symbolfiles=
mail="$helpers"/mail.py
all_done="$helpers"/all_done.py
test -r "$helpers/update_version_files.py" && update_version_files="$helpers/update_version_files.py"
libs_asset="$SLASSET_LIBS_DARWIN"
;;
CYGWIN)
helpers=/cygdrive/c/buildscripts/shared/latest
variants="Debug RelWithDebInfo Release"
#variants="Release"
cmake_generator="vc80"
fmod=fmodapi375win
fmod_tar=fmodapi375win.zip
fmod_so=fmodvc.lib
fmod_lib=lib
target_dirs="libraries/i686-win32/lib/debug
libraries/i686-win32/lib/release"
other_archs="$S3GET_URL/$branch/$revision/Darwin $S3GET_URL/$branch/$revision/Linux"
symbolfiles="newview/Release/secondlife-bin.pdb newview/Release/secondlife-bin.map newview/Release/secondlife-bin.exe"
export PATH="/cygdrive/c/Python25:/cygdrive/c/Program Files/Cmake 2.6/bin":$PATH
export PERL="/cygdrive/c/Perl/bin/perl.exe"
export S3CURL="C:\\buildscripts\\shared\\latest\\hg\\bin\\s3curl.py"
export SIGN_PY="C:\\buildscripts\\shared\\latest\\code-signing\\sign.py"
export CURL="C:\\cygwin\\bin\\curl.exe"
mail="C:\\buildscripts\\shared\\latest\\mail.py"
all_done="C:\\buildscripts\\shared\\latest\\all_done.py"
test -r "$helpers/update_version_files.py" && update_version_files="C:\\buildscripts\\shared\\latest\\update_version_files.py"
libs_asset="$SLASSET_LIBS_WIN32"
;;
Linux)
helpers=/var/opt/parabuild/buildscripts/shared/latest
if [ x"$CXX" = x ]
then
if test -x /usr/bin/g++-4.1
then
if test -x /usr/bin/distcc
then
export CXX="/usr/bin/distcc /usr/bin/g++-4.1"
else
export CXX=/usr/bin/g++-4.1
fi
fi
fi
acquire_lock
variants="Debug RelWithDebInfo Release"
#variants="Release"
cmake_generator="Unix Makefiles"
fmod=fmodapi375linux
fmod_tar="$fmod".tar.gz
fmod_so=libfmod-3.75.so
fmod_lib=.
target_dirs="libraries/i686-linux/lib_debug
libraries/i686-linux/lib_release
libraries/i686-linux/lib_release_client"
other_archs="$S3GET_URL/$branch/$revision/Darwin $S3GET_URL/$branch/$revision/CYGWIN"
symbolfiles=
mail="$helpers"/mail.py
all_done="$helpers"/all_done.py
test -r "$helpers/update_version_files.py" && update_version_files="$helpers/update_version_files.py"
# Change the DISTCC_DIR to be somewhere that the parabuild process can write to
if test -r /etc/debian_version
then
[ x"$DISTCC_DIR" = x ] && export DISTCC_DIR=/var/tmp/parabuild
#case `cat /etc/debian_version` in
#3.*) [ x"$DISTCC_HOSTS" = x ]\
# && export DISTCC_HOSTS="build-linux-1/3
# station30/2,lzo" ;;
#4.*) [ x"$DISTCC_HOSTS" = x ]\
# && export DISTCC_HOSTS="build-linux-6/2,lzo
# build-linux-2/2,lzo
# build-linux-3/2,lzo
# build-linux-4/2,lzo
# build-linux-5/2,lzo
# build-linux-7/2,lzo
# build-linux-8/2,lzo
# build-linux-9/2,lzo" ;;
#esac
# Temp fix for Linux so that parabuild passes: use the new Linux build farm
export hostname=`hostname -f`
export phx_DISTCC_HOSTS="build-linux0.phx.lindenlab.com/2 build-linux1.phx.lindenlab.com/2 build-linux2.phx.lindenlab.com/2 build-linux3.phx.lindenlab.com/2 build-linux5.phx.lindenlab.com/2 build-linux5.phx.lindenlab.com/2 build-linux6.phx.lindenlab.com/2 "
export dfw_DISTCC_HOSTS="build-linux7.dfw.lindenlab.com/2 build-linux8.dfw.lindenlab.com/2 build-linux9.dfw.lindenlab.com/2 build-linux10.dfw.lindenlab.com/2 build-linux11.dfw.lindenlab.com/2 build-linux12.dfw.lindenlab.com/2 build-linux13.dfw.lindenlab.com/2 build-linux14.dfw.lindenlab.com/2 build-linux15.dfw.lindenlab.com/2"
case "$hostname" in
*.dfw.*) export DISTCC_HOSTS="$dfw_DISTCC_HOSTS" ;;
*.phx.*) export DISTCC_HOSTS="$phx_DISTCC_HOSTS" ;;
esac
fi
libs_asset="$SLASSET_LIBS_LINUXI386"
;;
*) fail undefined $arch ;;
esac
get_asset "http://www.fmod.org/index.php/release/version/$fmod_tar"
case "$arch" in
Darwin)
# Create fat binary on Mac...
if lipo -create -output "../$fmod"/api/$fmod_lib/libfmod-universal.a\
"../$fmod"/api/$fmod_lib/libfmod.a\
"../$fmod"/api/$fmod_lib/libfmodx86.a
then
mv "../$fmod"/api/$fmod_lib/libfmod.a "../$fmod"/api/$fmod_lib/libfmodppc.a
mv "../$fmod"/api/$fmod_lib/libfmod-universal.a "../$fmod"/api/$fmod_lib/libfmod.a
echo Created fat binary
else
fail running lipo
fi
;;
CYGWIN)
# install Quicktime. This will fail outside of Linden's network
scripts/install.py quicktime
;;
esac
# Only run this if the script exists
if test x"$update_version_files" = x
then
echo "Private Build..." > indra/build.log
[ x"$VIEWER_CHANNEL" = x ] && export VIEWER_CHANNEL="CommunityDeveloper"
else
# By right, this should be in the branched source tree, but for now it will be a helper
python "$update_version_files" --verbose --src-root=. --viewer > indra/build.log
[ x"$VIEWER_CHANNEL" = x ] && export VIEWER_CHANNEL="Snowglobe Test Build"
fi
# First, go into the directory where the code was checked out by Parabuild
cd indra
# This is the way it works now, but it will soon work on a variant dependent way
for target_dir in $target_dirs
do
mkdir -p "../$target_dir"
cp -f "../../$fmod/api/$fmod_lib/$fmod_so" "../$target_dir"
done
mkdir -p "../libraries/include"
cp -f "../../$fmod/api/inc/"* "../libraries/include"
# Special Windows case
test -r "../../$fmod/api/fmod.dll" && cp -f "../../$fmod/api/fmod.dll" newview
# Now run the build command over all variants
succeeded=true
### TEST CODE - remove when done
### variants=
### echo "Artificial build failure to test notifications" > build.log
### succeeded=false
### END TEST CODE
for variant in $variants
do
build_dir=`build_dir_$arch $variant`
rm -rf "$build_dir"
get_asset "$libs_asset" # Thus plunks stuff into the build dir, so have to restore it now.
# This is the way it will work in future
#for target_dir in $target_dirs
#do
# mkdir -p "$build_dir/$target_dir"
# cp "../../$fmod/api/$fmod_lib/$fmod_so" "$build_dir/$target_dir"
#done
#mkdir -p "$build_dir/libraries/include"
#cp "../../$fmod/api/inc/"* "$build_dir/libraries/include"
echo "==== $variant ====" >> build.log
if ./develop.py \
--unattended \
--incredibuild \
-t $variant \
-G "$cmake_generator" \
configure \
-DVIEWER_CHANNEL:STRING="$VIEWER_CHANNEL"\
-DVIEWER_LOGIN_CHANNEL:STRING="$VIEWER_CHANNEL"\
-DPACKAGE:BOOL=ON >>build.log 2>&1
then
if ./develop.py\
--unattended\
--incredibuild \
-t $variant\
-G "$cmake_generator" \
build prepare >>build.log 2>&1
then
if ./develop.py\
--unattended\
--incredibuild \
-t $variant\
-G "$cmake_generator" \
build package >>build.log 2>&1
then
# run tests if needed
true
else
succeeded=false
fi
else
succeeded=false
fi
else
succeeded=false
fi
done
# check statuis and upload results to S3
subject=
if $succeeded
then
package=`installer_$arch`
test -r "$package" || fail not found: $package
package_file=`echo $package | sed 's:.*/::'`
if s3_available
then
echo "$PUBLIC_URL/$branch/$revision/$package_file" > "$arch"
echo "$PUBLIC_URL/$branch/$revision/good-build.$arch" >> "$arch"
"$helpers/s3put.sh" "$package" "$S3PUT_URL/$branch/$revision/$package_file" binary/octet-stream\
|| fail Uploading "$package"
"$helpers/s3put.sh" build.log "$S3PUT_URL/$branch/$revision/good-build.$arch" text/plain\
|| fail Uploading build.log
"$helpers/s3put.sh" "$arch" "$S3PUT_URL/$branch/$revision/$arch" text/plain\
|| fail Uploading token file
for symbolfile in $symbolfiles
do
targetfile="`echo $symbolfile | sed 's:.*/::'`"
"$helpers/s3put.sh" "$build_dir/$symbolfile" "$S3SYMBOL_URL/$revision/$targetfile" binary/octet-stream\
|| fail Uploading "$symbolfile"
done
if python "$all_done"\
curl\
"$S3GET_URL/$branch/$revision/$arch"\
$other_archs > message
then
subject="Successful Build for $branch ($revision)"
fi
else
true s3 is not available
fi
else
if s3_available
then
"$helpers/s3put.sh" build.log "$S3PUT_URL/$branch/$revision/failed-build.$arch" text/plain\
|| fail Uploading build.log
subject="Failed Build for $branch ($revision) on $arch"
cat >message <<EOF
Build for $branch ($revision) failed for $arch.
Please see the build log for details:
$PUBLIC_URL/$branch/$revision/failed-build.$arch
EOF
else
true s3 is not available
fi
fi
# We have something to say...
if [ x"$subject" != x ]
then
# Extract change list since last build
if [ x"$PARABUILD_CHANGE_LIST_NUMBER" = x ]
then
echo "No change information available" >> message
elif [ x"$PARABUILD_PREVIOUS_CHANGE_LIST_NUMBER" = x ]
then
( cd .. && svn log --verbose --stop-on-copy --limit 50 ) >>message
else
if [ "$PARABUILD_PREVIOUS_CHANGE_LIST_NUMBER" -lt "$PARABUILD_CHANGE_LIST_NUMBER" ]
then
range=`expr 1 + "$PARABUILD_PREVIOUS_CHANGE_LIST_NUMBER"`:"$PARABUILD_CHANGE_LIST_NUMBER"
else
range="$PARABUILD_CHANGE_LIST_NUMBER"
fi
( cd .. && svn log --verbose -r"$range" ) >>message
fi
# $PUBLIC_EMAIL can be a list, so no quotes
python "$mail" "$subject" $PUBLIC_EMAIL <message
fi
if $succeeded
then
pass
else
fail
fi

54
scripts/build_version.py Executable file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python
#
# Print the build information embedded in a header file.
#
# Expects to be invoked from the command line with a file name and a
# list of directories to search. The file name will be one of the
# following:
#
# llversionserver.h
# llversionviewer.h
#
# The directory list that follows will include indra/llcommon, where
# these files live.
import errno, os, re
def get_version(filename):
fp = open(filename)
data = fp.read()
fp.close()
vals = {}
m = re.search('const S32 LL_VERSION_MAJOR = (\d+);', data)
vals['major'] = m.group(1)
m = re.search('const S32 LL_VERSION_MINOR = (\d+);', data)
vals['minor'] = m.group(1)
m = re.search('const S32 LL_VERSION_PATCH = (\d+);', data)
vals['patch'] = m.group(1)
m = re.search('const S32 LL_VERSION_BUILD = (\d+);', data)
vals['build'] = m.group(1)
return "%(major)s.%(minor)s.%(patch)s.%(build)s" % vals
if __name__ == '__main__':
import sys
try:
for path in sys.argv[2:]:
name = os.path.join(path, sys.argv[1])
try:
print get_version(name)
break
except OSError, err:
if err.errno != errno.ENOENT:
raise
else:
print >> sys.stderr, 'File not found:', sys.argv[1]
sys.exit(1)
except AttributeError:
print >> sys.stderr, 'Error: malformatted file: ', name
sys.exit(1)
except IndexError:
print >> sys.stderr, ('Usage: %s llversion[...].h [directories]' %
sys.argv[0])

1151
scripts/install.py Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

281
scripts/public_fetch_tarballs.py Executable file
View File

@@ -0,0 +1,281 @@
#!/usr/bin/python
"""\
@file public_fetch_tarballs.py
@author Rob Lanphier
@date 2009-05-30
@brief Fetch + extract tarballs and zipfiles listed in doc/asset_urls.txt
$LicenseInfo:firstyear=2009&license=viewergpl$
Copyright (c) 2009, Linden Research, Inc.
Second Life Viewer Source Code
The source code in this file ("Source Code") is provided by Linden Lab
to you under the terms of the GNU General Public License, version 2.0
("GPL"), unless you have obtained a separate licensing agreement
("Other License"), formally executed by you and Linden Lab. Terms of
the GPL can be found in doc/GPL-license.txt in this distribution, or
online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
There are special exceptions to the terms and conditions of the GPL as
it is applied to this Source Code. View the full text of the exception
in the file doc/FLOSS-exception.txt in this software distribution, or
online at
http://secondlifegrid.net/programs/open_source/licensing/flossexception
By copying, modifying or distributing this software, you acknowledge
that you have read and understood your obligations described above,
and agree to abide by those obligations.
ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
COMPLETENESS OR PERFORMANCE.
$/LicenseInfo$
"""
import sys
import os.path
# Look for indra/lib/python in all possible parent directories ...
# This is an improvement over the setup-path.py method used previously:
# * the script may blocated anywhere inside the source tree
# * it doesn't depend on the current directory
# * it doesn't depend on another file being present.
def add_indra_lib_path():
root = os.path.realpath(__file__)
# always insert the directory of the script in the search path
dir = os.path.dirname(root)
if dir not in sys.path:
sys.path.insert(0, dir)
# Now go look for indra/lib/python in the parent dies
while root != os.path.sep:
root = os.path.dirname(root)
dir = os.path.join(root, 'indra', 'lib', 'python')
if os.path.isdir(dir):
if dir not in sys.path:
sys.path.insert(0, dir)
return root
else:
print >>sys.stderr, "This script is not inside a valid installation."
sys.exit(1)
base_dir = add_indra_lib_path()
print base_dir
import os
import sys
import re
import urllib
import zipfile
import tarfile
import optparse
import tempfile
import indra.util.helpformatter
# load + parse doc/asset_urls.txt
def get_asset_urls():
asset_urls={}
f = open(os.path.join(base_dir,"doc", "asset_urls.txt"))
for line in f:
line=line.strip()
(name, value)=re.split("=", line, 1)
asset_urls[name]=value
return asset_urls
# Filename from a URL
def get_asset_filename_from_url(asseturl, targetdir):
i = asseturl.rfind('/')
filename = os.path.join(targetdir, asseturl[i+1:])
return filename
# Extract .zip file to targetdir. Called by extract_archive_sans_linden.
def extract_zipfile_sans_linden(filename, targetdir):
archive = zipfile.ZipFile(filename, 'r')
names = archive.namelist()
for path in names:
if(path=="linden/"):
pass
target = os.path.join(targetdir, re.sub("linden/", "", path))
subdir = os.path.dirname(target)
if not os.path.exists(subdir):
os.makedirs(subdir)
if not os.path.exists(target):
fp = open(target, 'wb')
fp.write(archive.read(path))
fp.close()
archive.close()
# Extract .tar.gz file to targetdir. Called by extract_archive_sans_linden.
def extract_tarball_sans_linden(filename, targetdir):
archive = tarfile.TarFile.open(filename, 'r')
# get a series of TarInfo objects
tarentries=archive.getmembers()
for tarentry in tarentries:
target = re.sub(r'^(\./)?(linden/)?', "", tarentry.name)
if(target==""):
continue
fulltarget=os.path.join(targetdir, target)
subdir = os.path.dirname(fulltarget)
if not os.path.exists(subdir):
os.makedirs(subdir)
if not os.path.exists(fulltarget):
# Reset the name property on the TarInfo object, so it writes the
# file exactly where we want it. It's hard telling for sure if this
# property is intended to be written to, but it works for now.
tarentry.name=fulltarget
# Calling TarFile.extract with the "path" parameter doesn't work as
# we might hope, because the path components in the tarball get
# appended to the "path" parameter. Hence the reason for passing in
# the TarInfo object with the munged name property
archive.extract(tarentry)
archive.close()
# Extract either .tar.gz file or .zip file to targetdir, stripping off the
# leading "linden" directory, but leaving the directory structure otherwise
# intact.
def extract_archive_sans_linden(filename, targetdir):
if(filename.endswith('.tar.gz')):
extract_tarball_sans_linden(filename, targetdir)
elif(filename.endswith('.zip')):
extract_zipfile_sans_linden(filename, targetdir)
else:
raise Exception, "Unhandled archive type"
def get_assetnames_by_platform(platform):
assetnames=['SLASSET_ART']
if(platform=='linux' or platform=='all'):
assetnames.append('SLASSET_LIBS_LINUXI386')
if(platform=='darwin' or platform=='all'):
assetnames.append('SLASSET_LIBS_DARWIN')
if(platform=='windows' or platform=='all'):
assetnames.append('SLASSET_LIBS_WIN32')
return assetnames
# adapted from install.py
def _get_platform():
"Return appropriate platform packages for the environment."
platform_map = {
'darwin': 'darwin',
'linux2': 'linux',
'win32' : 'windows',
'cygwin' : 'windows',
'solaris' : 'solaris'
}
this_platform = platform_map[sys.platform]
return this_platform
# copied from install.py
def _default_installable_cache():
"""In general, the installable files do not change much, so find a
host/user specific location to cache files."""
user = _getuser()
cache_dir = "/var/tmp/%s/install.cache" % user
if _get_platform() == 'windows':
cache_dir = os.path.join(tempfile.gettempdir(), \
'install.cache.%s' % user)
return cache_dir
# For status messages (e.g. "Loading..."). May come in handy if
# we implement a "quiet" mode.
def _report(string):
print string
# copied from install.py
def _getuser():
"Get the user"
try:
# Unix-only.
import getpass
return getpass.getuser()
except ImportError:
import win32api
return win32api.GetUserName()
# adapted from install.py
def _parse_args():
parser = optparse.OptionParser(
usage="usage: %prog [options]",
formatter = indra.util.helpformatter.Formatter(),
description="""This script fetches and installs tarballs and \
zipfiles ("asset bundles") listed in doc/asset_urls.txt
If no asset bundles are specified on the command line, then the default \
behavior is to install all known asset bundles appropriate for the platform \
specified. You can specify more than one asset bundle on the command line.
Example:
%prog SLASSET_ART
This looks for the "SLASSET_ART" entry in doc/asset_urls.txt, and extracts
the corresponding asset bundle into your source tree.
""")
parser.add_option(
'-p', '--platform',
type='choice',
default=_get_platform(),
dest='platform',
choices=['windows', 'darwin', 'linux', 'solaris', 'all'],
help="""Override the automatically determined platform. \
You can specify 'all' to get assets for all platforms. Choices: windows, \
darwin, linux, solaris, or all. Default: autodetected (%s)""" % \
_get_platform())
parser.add_option(
'--cache-dir',
type='string',
default=_default_installable_cache(),
dest='cache_dir',
help='Where to download files. Default: %s'% \
(_default_installable_cache()))
parser.add_option(
'--install-dir',
type='string',
default=base_dir,
dest='install_dir',
help='Where to unpack the installed files. Default: %s' % base_dir)
return parser.parse_args()
def main(argv):
options, args = _parse_args()
# 1. prepare cache dir
if not os.path.exists(options.cache_dir):
os.makedirs(options.cache_dir)
# 2. read doc/asset_urls.txt
asseturls=get_asset_urls()
# 3. figure out which asset bundles we'll be downloading
if len(args)>0:
assetnames=args
else:
assetnames=get_assetnames_by_platform(options.platform)
# 4. download and extract each asset bundle
for asset in assetnames:
# 4a. get the URL for the asset bundle
try:
asseturl=asseturls[asset]
except:
print "No asset in doc/asset_urls.txt named %s" % asset
sys.exit(2)
# 4b. figure out where to put the downloaded asset bundle
filename=get_asset_filename_from_url(asseturl, options.cache_dir)
# 4c. see if we have it, and if not, get it
if os.path.exists(filename):
_report("Using already downloaded "+filename+" ...")
else:
_report("Downloading "+filename+" ...")
urllib.urlretrieve(asseturl, filename)
# 4d. extract it into the tree
extract_archive_sans_linden(filename, options.install_dir)
# execute main() only if invoked directly:
if __name__ == "__main__":
sys.exit(main(sys.argv))

44
scripts/setup-path.py Executable file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/python
"""\
@file setup-path.py
@brief Get the python library directory in the path, so we don't have
to screw with PYTHONPATH or symbolic links.
$LicenseInfo:firstyear=2007&license=viewergpl$
Copyright (c) 2007-2009, Linden Research, Inc.
Second Life Viewer Source Code
The source code in this file ("Source Code") is provided by Linden Lab
to you under the terms of the GNU General Public License, version 2.0
("GPL"), unless you have obtained a separate licensing agreement
("Other License"), formally executed by you and Linden Lab. Terms of
the GPL can be found in doc/GPL-license.txt in this distribution, or
online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
There are special exceptions to the terms and conditions of the GPL as
it is applied to this Source Code. View the full text of the exception
in the file doc/FLOSS-exception.txt in this software distribution, or
online at
http://secondlifegrid.net/programs/open_source/licensing/flossexception
By copying, modifying or distributing this software, you acknowledge
that you have read and understood your obligations described above,
and agree to abide by those obligations.
ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
COMPLETENESS OR PERFORMANCE.
$/LicenseInfo$
"""
import sys
from os.path import realpath, dirname, join
# Walk back to checkout base directory
dir = dirname(dirname(realpath(__file__)))
# Walk in to libraries directory
dir = join(dir, 'indra', 'lib', 'python')
if dir not in sys.path:
sys.path.insert(0, dir)

312
scripts/template_verifier.py Executable file
View File

@@ -0,0 +1,312 @@
#!/usr/bin/python
"""\
@file template_verifier.py
@brief Message template compatibility verifier.
$LicenseInfo:firstyear=2007&license=viewergpl$
Copyright (c) 2007-2009, Linden Research, Inc.
Second Life Viewer Source Code
The source code in this file ("Source Code") is provided by Linden Lab
to you under the terms of the GNU General Public License, version 2.0
("GPL"), unless you have obtained a separate licensing agreement
("Other License"), formally executed by you and Linden Lab. Terms of
the GPL can be found in doc/GPL-license.txt in this distribution, or
online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
There are special exceptions to the terms and conditions of the GPL as
it is applied to this Source Code. View the full text of the exception
in the file doc/FLOSS-exception.txt in this software distribution, or
online at
http://secondlifegrid.net/programs/open_source/licensing/flossexception
By copying, modifying or distributing this software, you acknowledge
that you have read and understood your obligations described above,
and agree to abide by those obligations.
ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
COMPLETENESS OR PERFORMANCE.
$/LicenseInfo$
"""
"""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.
"""
import sys
import os.path
# Look for indra/lib/python in all possible parent directories ...
# This is an improvement over the setup-path.py method used previously:
# * the script may blocated anywhere inside the source tree
# * it doesn't depend on the current directory
# * it doesn't depend on another file being present.
def add_indra_lib_path():
root = os.path.realpath(__file__)
# always insert the directory of the script in the search path
dir = os.path.dirname(root)
if dir not in sys.path:
sys.path.insert(0, dir)
# Now go look for indra/lib/python in the parent dies
while root != os.path.sep:
root = os.path.dirname(root)
dir = os.path.join(root, 'indra', 'lib', 'python')
if os.path.isdir(dir):
if dir not in sys.path:
sys.path.insert(0, dir)
break
else:
print >>sys.stderr, "This script is not inside a valid installation."
sys.exit(1)
add_indra_lib_path()
import optparse
import os
import urllib
from indra.ipc import compatibility
from indra.ipc import tokenstream
from indra.ipc import llmessage
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')
status = input.close() # send no input to the command
output = out.read()
error = err.read()
status = out.close()
status = err.close() # the status comes from the *last* pipe that is closed
return status, output, error
def getstatusoutput(command):
status, output, error = getstatusall(command)
return status, output
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)
MAX_MASTER_AGE = 60 * 60 * 4 # refresh master cache every 4 hours
def retry(times, function, *args, **kwargs):
for i in range(times):
try:
return function(*args, **kwargs)
except Exception, e:
if i == times - 1:
raise e # we retried all the times we could
def compare(base_parsed, current_parsed, 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.
"""
compat = current_parsed.compatibleWithBase(base_parsed)
if mode == 'production':
acceptable = PRODUCTION_ACCEPTABLE
else:
acceptable = DEVELOPMENT_ACCEPTABLE
if type(compat) in acceptable:
return True, compat
return False, compat
def fetch(url):
if url.startswith('file://'):
# just open the file directly because urllib is dumb about these things
file_name = url[len('file://'):]
return open(file_name).read()
else:
# *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
def get_and_test_master():
new_master_contents = fetch(master_url)
llmessage.parseTemplateString(new_master_contents)
return new_master_contents
try:
new_master_contents = retry(3, get_and_test_master)
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."
print "Cause: %s" % e
return master_cache_url
try:
tmpname = '%s.%d' % (master_cache, os.getpid())
mc = open(tmpname, 'wb')
mc.write(new_master_contents)
mc.close()
try:
os.rename(tmpname, master_cache)
except OSError:
# We can't rename atomically on top of an existing file on
# Windows. Unlinking the existing file will fail if the
# file is being held open by a process, but there's only
# so much working around a lame I/O API one can take in
# a single day.
os.unlink(master_cache)
os.rename(tmpname, master_cache)
except IOError, e:
print "WARNING: Unable to write master message template to %s, proceeding without cache." % master_cache
print "Cause: %s" % e
return master_url
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 getuser():
try:
# Unix-only.
import getpass
return getpass.getuser()
except ImportError:
import win32api
return win32api.GetUserName()
def local_master_cache_filename():
"""Returns the location of the master template cache (which is in the system tempdir)
<temp_dir>/master_message_template_cache.msg"""
import tempfile
d = tempfile.gettempdir()
user = getuser()
return os.path.join(d, 'master_message_template_cache.%s.msg' % user)
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.""")
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 "master:", master_filename
print "current:", current_filename
master_url = 'file://%s' % master_filename
current_url = 'file://%s' % current_filename
# only current supplied in positional param
elif len(args) == 1:
master_url = None
current_filename = args[0]
print "master:", options.master_url
print "current:", current_filename
current_url = 'file://%s' % current_filename
# nothing specified, use defaults for everything
elif len(args) == 0:
master_url = None
current_url = None
else:
die("Too many arguments")
if master_url is None:
master_url = options.master_url
if current_url is None:
current_filename = local_template_filename()
print "master:", options.master_url
print "current:", current_filename
current_url = 'file://%s' % current_filename
# retrieve the contents of the local template and check for syntax
current = fetch(current_url)
current_parsed = llmessage.parseTemplateString(current)
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)
def parse_master_url():
master = fetch(master_url)
return llmessage.parseTemplateString(master)
try:
master_parsed = retry(3, parse_master_url)
except (IOError, tokenstream.ParseError), e:
if options.mode == 'production':
raise e
else:
print "WARNING: problems retrieving the master from %s." % master_url
print "Syntax-checking the local template ONLY, no compatibility check is being run."
print "Cause: %s\n\n" % e
return 0
acceptable, compat = compare(
master_parsed, current_parsed, 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:]))

View File

@@ -0,0 +1,203 @@
#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""\
@file update_source_contributors.py
@brief Update the source contributor list in one place, instead of having
to substitute by hand. Derived from update_viewer_version.py
$LicenseInfo:firstyear=2006&license=viewergpl$
Copyright (c) 2006-2009, Linden Research, Inc.
Second Life Viewer Source Code
The source code in this file ("Source Code") is provided by Linden Lab
to you under the terms of the GNU General Public License, version 2.0
("GPL"), unless you have obtained a separate licensing agreement
("Other License"), formally executed by you and Linden Lab. Terms of
the GPL can be found in doc/GPL-license.txt in this distribution, or
online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
There are special exceptions to the terms and conditions of the GPL as
it is applied to this Source Code. View the full text of the exception
in the file doc/FLOSS-exception.txt in this software distribution, or
online at
http://secondlifegrid.net/programs/open_source/licensing/flossexception
By copying, modifying or distributing this software, you acknowledge
that you have read and understood your obligations described above,
and agree to abide by those obligations.
ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
COMPLETENESS OR PERFORMANCE.
$/LicenseInfo$
"""
import sys
import os.path
import string
import getopt, os, re, commands
lang_sep={"es":", ",
"en-us":", ",
"ru":", ",
"hu":", ",
"pl":", ",
"ko":", ",
"tr":", ",
"it":", ",
"da":", ",
"pt":", ",
"de":", ",
"zh":", ",
"fr":", ",
"ja":"",
"uk":", "}
intro="Snowglobe includes source code contributions of the following residents: "
def add_indra_lib_path():
root = os.path.realpath(__file__)
# always insert the directory of the script in the search path
dir = os.path.dirname(root)
if dir not in sys.path:
sys.path.insert(0, dir)
# Now go look for indra/lib/python in the parent dies
while root != os.path.sep:
root = os.path.dirname(root)
dir = os.path.join(root, 'indra', 'lib', 'python')
if os.path.isdir(dir):
if dir not in sys.path:
sys.path.insert(0, dir)
return root
else:
print >>sys.stderr, "This script is not inside a valid installation."
sys.exit(1)
src_root = add_indra_lib_path()
from indra.util import llversion
def usage():
print "Usage:"
print sys.argv[0] + """ [options]
Options:
--version
Specify the version string to replace current version.
--skip-on-branch
Specify a regular expression against which the current branch
is matched. If it matches, then leave version strings alone.
Use this to avoid changing version strings on release candidate
builds.
--src-root
Location of source tree
--verbose
--help
Print this message and exit.
"""
def _getstatusoutput(cmd):
"""Return Win32 (status, output) of executing cmd
in a shell."""
if os.path.sep != "/":
# stupid #%#$$ windows
cmd = 'cmd.exe /c "'+cmd+'"'
pipe = os.popen(cmd, 'r')
text = pipe.read()
sts = pipe.close()
if sts is None: sts = 0
if text[-1:] == '\n': text = text[:-1]
return sts, text
def get_contributors(filename):
f = open(filename)
credits={}
contributors=[]
thisres=''
for line in f:
m = re.search('^(\S+ +\S+)\s*$', line.strip())
if(m):
thisres=m.group(1)
credits[thisres]=[]
contributors.append(thisres)
m = re.search('^\s+(\S+\-\d+)\s*$', line)
if(m and thisres != ''):
credits[thisres].append(m.group(1))
return contributors
def main():
global src_root
global intro
svn = os.path.expandvars("${SVN}")
if not svn or svn == "${SVN}": svn = "svn"
contributors = get_contributors(src_root + "/doc/contributions.txt")
re_map = {}
#re_map['filename'] = (('pattern', 'replacement'),
# ('pattern', 'replacement')
for lang in lang_sep.keys():
filename='indra/newview/skins/default/xui/%(lang)s/floater_about.xml' % locals()
searchpattern='%(intro)s.*\n' % {'intro':intro}
replacelist=string.join(contributors, lang_sep[lang])
replacement='%(intro)s%(replacelist)s\n' % {'intro':intro,'replacelist':replacelist}
re_map[filename] = [[searchpattern, replacement]]
verbose = False
opts, args = getopt.getopt(sys.argv[1:],
"",
['skip-on-branch=',
'src-root=',
'verbose',
'help'])
skip_on_branch_re = None
for o,a in opts:
if o in ('--skip-on-branch'):
skip_on_branch_re = re.compile(a)
if o in ('--src-root'):
src_root = a
if o in ('--verbose'):
verbose = True
if o in ('--help'):
usage()
return 0
if verbose:
print "Source Path:", src_root
if viewer_channel != None:
print "Current viewer channel/version: '%(viewer_channel)s' / '%(viewer_version)s'" % locals()
print
# Iterate through all of the files in the map, and apply the
# substitution filters
for filename in re_map.keys():
try:
# Read the entire file into a string
full_fn = src_root + '/' + filename
file = open(full_fn,"r")
file_str = file.read()
file.close()
if verbose:
print "Processing file:",filename
for rule in re_map[filename]:
repl = rule[1]
file_str = re.sub(rule[0], repl, file_str)
file = open(full_fn,"w")
file.write(file_str)
file.close()
except IOError:
print "File %(filename)s not present, skipping..." % locals()
return 0
main()

307
scripts/update_version_files.py Executable file
View File

@@ -0,0 +1,307 @@
#!/usr/bin/python
"""\
@file update_version_files.py
@brief Update all of the various files in the repository to a new
version number, instead of having to figure it out by hand
$LicenseInfo:firstyear=2006&license=viewergpl$
Copyright (c) 2006-2009, Linden Research, Inc.
Second Life Viewer Source Code
The source code in this file ("Source Code") is provided by Linden Lab
to you under the terms of the GNU General Public License, version 2.0
("GPL"), unless you have obtained a separate licensing agreement
("Other License"), formally executed by you and Linden Lab. Terms of
the GPL can be found in doc/GPL-license.txt in this distribution, or
online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
There are special exceptions to the terms and conditions of the GPL as
it is applied to this Source Code. View the full text of the exception
in the file doc/FLOSS-exception.txt in this software distribution, or
online at
http://secondlifegrid.net/programs/open_source/licensing/flossexception
By copying, modifying or distributing this software, you acknowledge
that you have read and understood your obligations described above,
and agree to abide by those obligations.
ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
COMPLETENESS OR PERFORMANCE.
$/LicenseInfo$
"""
import sys
import os.path
def add_indra_lib_path():
root = os.path.realpath(__file__)
# always insert the directory of the script in the search path
dir = os.path.dirname(root)
if dir not in sys.path:
sys.path.insert(0, dir)
# Now go look for indra/lib/python in the parent dies
while root != os.path.sep:
root = os.path.dirname(root)
dir = os.path.join(root, 'indra', 'lib', 'python')
if os.path.isdir(dir):
if dir not in sys.path:
sys.path.insert(0, dir)
return root
else:
print >>sys.stderr, "This script is not inside a valid installation."
sys.exit(1)
add_indra_lib_path()
import getopt, os, re, commands
from indra.util import llversion
svn = os.path.expandvars("${SVN}")
if not svn or svn == "${SVN}": svn = "svn"
def usage():
print "Usage:"
print sys.argv[0] + """ [options]
Options:
--version
Specify the version string to replace current version.
--skip-on-branch
Specify a regular expression against which the current branch
is matched. If it matches, then leave version strings alone.
Use this to avoid changing version strings on release candidate
builds.
--server
Update llversionserver.h only with new version
--viewer
Update llversionviewer.h only with new version
--channel
Specify the viewer channel string to replace current channel.
--server_channel
Specify the server channel string to replace current channel.
--src-root
Location of source tree
--verbose
--help
Print this message and exit.
Common Uses:
# Update server and viewer build numbers to the current SVN revision:
update_version_files.py
# Update build numbers unless we are on a release branch:
update_version_files.py --skip-on-branch='^Branch_'
# Update server and viewer version numbers explicitly:
update_version_files.py --version=1.18.1.6
# Update just the viewer version number explicitly:
update_version_files.py --viewer --version=1.18.1.6
# Update just the server build number to the current SVN revision:
update_version_files.py --server
# Update the viewer channel
update_version_files.py --channel="First Look Puppeteering"
# Update the server channel
update_version_files.py --server_channel="Het Grid"
"""
def _getstatusoutput(cmd):
"""Return Win32 (status, output) of executing cmd
in a shell."""
if os.path.sep != "/":
# stupid #%#$$ windows
cmd = 'cmd.exe /c "'+cmd+'"'
pipe = os.popen(cmd, 'r')
text = pipe.read()
sts = pipe.close()
if sts is None: sts = 0
if text[-1:] == '\n': text = text[:-1]
return sts, text
re_map = {}
#re_map['filename'] = (('pattern', 'replacement'),
# ('pattern', 'replacement')
re_map['indra/llcommon/llversionviewer.h'] = \
(('const S32 LL_VERSION_MAJOR = (\d+);',
'const S32 LL_VERSION_MAJOR = %(VER_MAJOR)s;'),
('const S32 LL_VERSION_MINOR = (\d+);',
'const S32 LL_VERSION_MINOR = %(VER_MINOR)s;'),
('const S32 LL_VERSION_PATCH = (\d+);',
'const S32 LL_VERSION_PATCH = %(VER_PATCH)s;'),
('const S32 LL_VERSION_BUILD = (\d+);',
'const S32 LL_VERSION_BUILD = %(VER_BUILD)s;'),
('const char \* const LL_CHANNEL = "(.+)";',
'const char * const LL_CHANNEL = "%(VIEWER_CHANNEL)s";'))
re_map['indra/newview/res/viewerRes.rc'] = \
(('FILEVERSION [0-9,]+',
'FILEVERSION %(VER_MAJOR)s,%(VER_MINOR)s,%(VER_PATCH)s,%(VER_BUILD)s'),
('PRODUCTVERSION [0-9,]+',
'PRODUCTVERSION %(VER_MAJOR)s,%(VER_MINOR)s,%(VER_PATCH)s,%(VER_BUILD)s'),
('VALUE "FileVersion", "[0-9.]+"',
'VALUE "FileVersion", "%(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_BUILD)s"'),
('VALUE "ProductVersion", "[0-9.]+"',
'VALUE "ProductVersion", "%(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_BUILD)s"'))
# Trailing ',' in top level tuple is special form to avoid parsing issues with one element tuple
re_map['indra/newview/Info-SecondLife.plist'] = \
(('<key>CFBundleVersion</key>\n\t<string>[0-9.]+</string>',
'<key>CFBundleVersion</key>\n\t<string>%(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_BUILD)s</string>'),)
re_map['indra/newview/Info-Snowglobe.plist'] = \
(('<key>CFBundleVersion</key>\n\t<string>[0-9.]+</string>',
'<key>CFBundleVersion</key>\n\t<string>%(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_BUILD)s</string>'),)
# This will probably only work as long as InfoPlist.strings is NOT UTF16, which is should be...
re_map['indra/newview/English.lproj/InfoPlist.strings'] = \
(('CFBundleShortVersionString = "Second Life version [0-9.]+";',
'CFBundleShortVersionString = "Second Life version %(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_BUILD)s";'),
('CFBundleGetInfoString = "Second Life version [0-9.]+',
'CFBundleGetInfoString = "Second Life version %(VER_MAJOR)s.%(VER_MINOR)s.%(VER_PATCH)s.%(VER_BUILD)s'))
version_re = re.compile('(\d+).(\d+).(\d+).(\d+)')
svn_branch_re = re.compile('^URL:\s+\S+/([^/\s]+)$', re.MULTILINE)
svn_revision_re = re.compile('^Last Changed Rev: (\d+)$', re.MULTILINE)
def main():
script_path = os.path.dirname(__file__)
src_root = script_path + "/../"
verbose = False
opts, args = getopt.getopt(sys.argv[1:],
"",
['version=',
'channel=',
'server_channel=',
'skip-on-branch=',
'src-root=',
'verbose',
'viewer',
'help'])
update_viewer = False
new_version = None
new_viewer_channel = None
skip_on_branch_re = None
for o,a in opts:
if o in ('--version'):
new_version = a
if o in ('--skip-on-branch'):
skip_on_branch_re = re.compile(a)
if o in ('--channel'):
new_viewer_channel = a
if o in ('--src-root'):
src_root = a
if o in ('--verbose'):
verbose = True
if o in ('--server'):
update_server = True
if o in ('--viewer'):
update_viewer = True
if o in ('--help'):
usage()
return 0
if not(update_viewer):
update_viewer = True
# Get current channel/version from llversion*.h
try:
viewer_channel = llversion.get_viewer_channel()
viewer_version = llversion.get_viewer_version()
except IOError:
print "Viewer version file not present, skipping..."
viewer_channel = None
viewer_version = None
update_viewer = False
if verbose:
print "Source Path:", src_root
if viewer_channel != None:
print "Current viewer channel/version: '%(viewer_channel)s' / '%(viewer_version)s'" % locals()
print
# Determine new channel(s)
if new_viewer_channel != None and len(new_viewer_channel) > 0:
viewer_channel = new_viewer_channel
# Determine new version(s)
if new_version:
m = version_re.match(new_version)
if not m:
print "Invalid version string specified!"
return -1
if update_viewer:
viewer_version = new_version
else:
# Assume we're updating just the build number
cl = '%s info "%s"' % (svn, src_root)
status, output = _getstatusoutput(cl)
if verbose:
print
print "svn info output:"
print "----------------"
print output
branch_match = svn_branch_re.search(output)
revision_match = svn_revision_re.search(output)
if not branch_match or not revision_match:
print "Failed to execute svn info, output follows:"
print output
return -1
branch = branch_match.group(1)
revision = revision_match.group(1)
if skip_on_branch_re and skip_on_branch_re.match(branch):
print "Release Candidate Build, leaving version files untouched."
return 0
if update_viewer:
m = version_re.match(viewer_version)
viewer_version = m.group(1)+"."+m.group(2)+"."+m.group(3)+"."+revision
if verbose:
if update_viewer:
print "Setting viewer channel/version: '%(viewer_channel)s' / '%(viewer_version)s'" % locals()
print
# split out version parts
if viewer_version != None:
m = version_re.match(viewer_version)
VER_MAJOR = m.group(1)
VER_MINOR = m.group(2)
VER_PATCH = m.group(3)
VER_BUILD = m.group(4)
# For readability and symmetry with version strings:
VIEWER_CHANNEL = viewer_channel
# Iterate through all of the files in the map, and apply the
# substitution filters
for filename in re_map.keys():
try:
# Read the entire file into a string
full_fn = src_root + '/' + filename
file = open(full_fn,"r")
file_str = file.read()
file.close()
if verbose:
print "Processing file:",filename
for rule in re_map[filename]:
repl = rule[1] % locals()
file_str = re.sub(rule[0], repl, file_str)
file = open(full_fn,"w")
file.write(file_str)
file.close()
except IOError:
print "File %(filename)s not present, skipping..." % locals()
return 0
main()