diff options
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/automated_build_scripts/opensrc-build.sh | 391 | ||||
-rwxr-xr-x | scripts/build_version.py | 54 | ||||
-rwxr-xr-x | scripts/gpu_table_tester | 293 | ||||
-rwxr-xr-x | scripts/install.py | 1162 | ||||
-rwxr-xr-x | scripts/md5check.py | 56 | ||||
-rwxr-xr-x[-rw-r--r--] | scripts/messages/message_template.msg | 70 | ||||
-rwxr-xr-x | scripts/messages/message_template.msg.sha1 | 1 | ||||
-rwxr-xr-x | scripts/packages-formatter.py | 93 | ||||
-rwxr-xr-x | scripts/setup-path.py | 42 | ||||
-rwxr-xr-x | scripts/template_verifier.py | 66 | ||||
-rwxr-xr-x | scripts/templates/template-cpp.cpp | 30 | ||||
-rwxr-xr-x | scripts/templates/template-h.h | 31 | ||||
-rwxr-xr-x | scripts/update_version_files.py | 331 |
13 files changed, 631 insertions, 1989 deletions
diff --git a/scripts/automated_build_scripts/opensrc-build.sh b/scripts/automated_build_scripts/opensrc-build.sh deleted file mode 100755 index c1b592a972..0000000000 --- a/scripts/automated_build_scripts/opensrc-build.sh +++ /dev/null @@ -1,391 +0,0 @@ -#!/bin/sh - -# This is the build script used by Linden Lab's autmated build system. -# - -set -x - -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/.*: //'` - -[ 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"$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 .. -o "$WGET_CACHE/$tarball" || fail unzip $tarball ;; - *.tar.gz|*.tgz) tar -C .. -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" - - -# 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/generic_vc - 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" - mail="$helpers"/mail.py - all_done="$helpers"/all_done.py - get_asset "$SLASSET_LIBS_DARWIN" - ;; - -CYGWIN) - helpers=/cygdrive/c/buildscripts - 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" - 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\s3curl.pl" - export CURL="C:\\cygwin\\bin\\curl.exe" - mail="C:\\buildscripts\\mail.py" - all_done="C:\\buildscripts\\all_done.py" - get_asset "$SLASSET_LIBS_WIN32" - ;; - -Linux) - helpers=/var/opt/parabuild/buildscripts/generic_vc - [ x"$CXX" = x ] && test -x /usr/bin/g++-4.1 && export CXX=/usr/bin/g++-4.1 - 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" - mail="$helpers"/mail.py - all_done="$helpers"/all_done.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 - build-linux-2 - build-linux-3 - build-linux-4 - build-linux-5" ;; - 4.*) [ x"$DISTCC_HOSTS" = x ]\ - && export DISTCC_HOSTS="build-linux-6 - build-linux-7 - build-linux-8 - build-linux-9" ;; - esac - fi - - get_asset "$SLASSET_LIBS_LINUXI386" - ;; - -*) fail undefined $arch ;; -esac - -get_asset "http://www.fmod.org/index.php/release/version/$fmod_tar" - -# Special case for Mac... -case "$arch" in - -Darwin) - 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 - ;; - -esac - -# ensure helpers are up to date -( cd "$helpers" && svn up ) - -# 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 -cp /dev/null build.log - -### 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" - # 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 \ - -DPACKAGE:BOOL=ON >>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 -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 - 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 - ( cd .. && svn log --verbose -r"$PARABUILD_PREVIOUS_CHANGE_LIST_NUMBER":"$PARABUILD_CHANGE_LIST_NUMBER" ) >>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 - diff --git a/scripts/build_version.py b/scripts/build_version.py deleted file mode 100755 index 4bef290b7d..0000000000 --- a/scripts/build_version.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/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]) diff --git a/scripts/gpu_table_tester b/scripts/gpu_table_tester new file mode 100755 index 0000000000..af0678000d --- /dev/null +++ b/scripts/gpu_table_tester @@ -0,0 +1,293 @@ +#!/usr/bin/perl +## Checks entries in the indra/newview/gpu_table.txt file against sample data +## +## Copyright (c) 2011, 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. + +use English; +use Getopt::Long; + +( $MyName = $0 ) =~ s|.*/||; +my $mini_HELP = " + $MyName {--gpu-table|-g} <gpu_table.txt> {--table-only|-t} + + Checks for duplicates and invalid lines in the gpu_table.txt file. + + $MyName {--gpu-table|-g} <gpu_table.txt> [ <gpu-strings-file> ... ] + [{--unmatched|-u}] + + Tests the recognition of values in the gpu-strings-files (or + standard input if no files are given). The results of attempting to match + each input line are displayed in report form, showing: + - NO MATCH, unsupported, or supported + - the class of the GPU + - the label for the recognizer line from the gpu_table that it matched + + If the --unmatched option is specified, then no output is produced for + values that are matched. + + $MyName {--gpu-table|-g} <gpu_table.txt> {--diff|-d} <old_results> [ <gpu-strings-file> ...] + + With the --diff option, the report compares the current results to <old-results>, + which should be the output from a previous run without --diff. The report shows each + input value with the old result and the new result if it is different. +"; + +&GetOptions("help" => \$Help + ,"unmatched" => \$UnMatchedOnly + ,"table-only" => \$TableOnly + ,"gpu-table=s" => \$GpuTable + ,"diff=s" => \$Diff + ) + || die "$mini_HELP"; + +if ($Help) +{ + print $mini_HELP; + exit 0; +} + +$ErrorsSeen = 0; +$NoMatch = 'NO MATCH'; # constant + +die "Must specify a --gpu-table <gpu_table.txt> value" + unless $GpuTable; + +open(GPUS, "<$GpuTable") + || die "Failed to open gpu table '$GpuTable':\n\t$!\n"; + +my $FirstLine = <GPUS>; +die "First line of gpu table does not begin with '//GPU_TABLE'" + unless $FirstLine =~ m|^//GPU_TABLE|; + +# Parse the GPU table into these tables, indexed by the name +my %NameLine; # name -> line number on which a given name was found (catches duplicate names) +my %RecognizerLine; # name -> line number on which a given name was found (catches duplicate names) +my %Name; # recognizer -> name +my %Recognizer; # name -> recognizer +my %Class; # recognizer -> class +my %Supported; # recognizer -> supported +my @InOrder; # lowercased recognizers in file order - these are the ones really used to match +my %StatsBased; +my %ExpectedOpenGL; + +$Name{$NoMatch} = $NoMatch; +$NameLine{$NoMatch} = '(hard-coded)'; # use this for error messages in table parsing +$Class{$NoMatch} = ''; +$Supported{$NoMatch} = ''; +$StatsBased{$NoMatch} = ''; +$ExpectedOpenGL{$NoMatch} = ''; + +while (<GPUS>) +{ + next if m|^//|; # skip comments + next if m|^\s*$|; # skip blank lines + + chomp; + my ($name, $regex, $class, $supported, $stats_based, $expected_opengl, $extra) = split('\t+'); + my $errsOnLine = $ErrorsSeen; + if (!$name) + { + print STDERR "No name found on $GpuTable line $INPUT_LINE_NUMBER\n"; + $ErrorsSeen++; + } + elsif ( defined $NameLine{$name} ) + { + print STDERR "Duplicate name '$name' on $GpuTable lines $NameLine{$name} and $INPUT_LINE_NUMBER:\n"; + print STDERR " $NameLine{$name}: /$Recognizer{$name}/ $Supported{$Recognizer{$name}} class $Class{$Recognizer{$name}}\n"; + print STDERR " $INPUT_LINE_NUMBER: /$regex/ " . ($supported ? "supported" : "unsupported") . " class $class - ignored\n"; + $ErrorsSeen++; + } + if (!$regex) + { + print STDERR "No recognizer found on $GpuTable line $INPUT_LINE_NUMBER\n"; + $ErrorsSeen++; + } + elsif ( defined $RecognizerLine{$regex} ) + { + print STDERR "Duplicate recognizer /$regex/ found on $GpuTable lines $RecognizerLine{$regex} and $INPUT_LINE_NUMBER (ignored)\n"; + print STDERR " $RecognizerLine{$regex}: name '$Name{$regex}' $Supported{$regex} class $Class{$regex}\n"; + print STDERR " $INPUT_LINE_NUMBER: name '$name' " . ($supported ? "supported" : "unsupported") . " class $class - ignored\n"; + $ErrorsSeen++; + } + if ($class !~ m/[012345]/) + { + print STDERR "Invalid class value '$class' on $GpuTable line $INPUT_LINE_NUMBER\n"; + $ErrorsSeen++; + } + if ($supported !~ m/[0123]/) + { + print STDERR "Invalid supported value '$supported' on $GpuTable line $INPUT_LINE_NUMBER\n"; + $ErrorsSeen++; + } + if ($stats_based !~ m/[01]/) + { + print STDERR "Invalid stats_based value '$stats_based' on $GpuTable line $INPUT_LINE_NUMBER\n"; + $ErrorsSeen++; + } + if ($expected_opengl !~ m/\d+(\.\d+)?/) + { + print STDERR "Invalid expected_opengl value '$expected_opengl' on $GpuTable line $INPUT_LINE_NUMBER\n"; + $ErrorsSeen++; + } + if ($extra) + { + print STDERR "Extra data '$extra' on $GpuTable line $INPUT_LINE_NUMBER\n"; + $ErrorsSeen++; + } + + if ($errsOnLine == $ErrorsSeen) # no errors found on this line + { + push @InOrder,$regex; + $NameLine{$name} = $INPUT_LINE_NUMBER; + $RecognizerLine{$regex} = $INPUT_LINE_NUMBER; + $Name{$regex} = $name; + $Recognizer{$name} = $regex; + $Class{$regex} = $class; + $Supported{$regex} = $supported ? "supported" : "unsupported"; + $StatsBased{$regex} = $stats_based; + $ExpectedOpenGL{$regex} = $expected_opengl; + } +} + +close GPUS; + +print STDERR "\n" if $ErrorsSeen; + +exit $ErrorsSeen if $TableOnly; + + +# Loop over input lines, find the results for each +my %RecognizedBy; +while (<>) +{ + chomp; + $_ = substr($_,0,100); + my $lcInput = lc $_; # the real gpu table parser lowercases the input string + my $recognizer; + $RecognizedBy{$_} = $NoMatch; + foreach $recognizer ( @InOrder ) # note early exit if recognized + { + my $lcRecognizer = lc $recognizer; # the real gpu table parser lowercases the recognizer + if ( $lcInput =~ m/$lcRecognizer/ ) + { + $RecognizedBy{$_} = $recognizer; + last; # exit recognizer loop + } + } +} + +format STDOUT_TOP = +GPU String Supported? Class Stats OpenGL Recognizer +------------------------------------------------------------------------------------------------------ ----------- ----- ----- ------ ------------------------------------ +. +format STDOUT = +@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<< @> @> @<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<... +$_, $Supported{$RecognizedBy{$_}},$Class{$RecognizedBy{$_}},$StatsBased{$RecognizedBy{$_}},$ExpectedOpenGL{$RecognizedBy{$_}},$Name{$RecognizedBy{$_}} +. + +my $ReportLineTemplate = "A102xxxA12xxxA2xxxxA2xxxxA5A*"; # Used to read a previous report - MUST match the format STDOUT above + +my ( $oldSupported, $oldClass, $newSupported, $newClass ); + +format DIFF_TOP = + ------------- OLD ------------- ----------- NEW -------------------- +GPU String Supported? Class Stats OpenGL Supported? Class Stats OpenGL Line +------------------------------------------------------------------------------------------------------ ----------- ----- ----- ------ ----------- ----- ----- ------ ----- +. +format DIFF = +@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<< @> @> @<<<< @<<<<<<<<<< @> @> @<<<< @>>>> +$_, $oldSupported, $oldClass, $oldStatsBased, $oldExpectedOpenGL, $newSupported, $newClass, $newStatsBased, $newExpectedOpenGL, $newRecognizedLine +. + +if ( ! $Diff ) +{ + ## Print results of testing each input line and how it was recognized. + foreach ( sort keys %RecognizedBy ) + { + write if ! $UnMatchedOnly || $Name{$RecognizedBy{$_}} eq $NoMatch; + $-++; # suppresses pagination + } +} +else +{ + ## Print a comparison of how the recognition this time compared to the results from the $Diff file + open OLD, "<$Diff" + || die "Failed to open --diff file '$Diff'\n\t$!\n"; + my $discard = 2; + while ( <OLD> ) + { + if ( $discard <= 0 ) + { + my ( $gpu, $supported, $class, $stats, $opengl ) = unpack $ReportLineTemplate; + $gpu =~ s/\s*$//; + ( $OldSupported{$gpu} = $supported ) =~ s/\s*$//; + ( $OldClass{$gpu} = $class ) =~ s/\s*$//; + ( $OldStatsBased{$gpu} = $stats ) =~ s/\s*$//; + ( $OldExpectedOpenGL{$gpu} = $opengl ) =~ s/\s*$//; + } + else + { + $discard--; + } + } + close OLD; + + $FORMAT_TOP_NAME = 'DIFF_TOP'; + $FORMAT_NAME = 'DIFF'; + foreach ( sort keys %RecognizedBy ) + { + $newSupported = $Supported{$RecognizedBy{$_}} || $NoMatch; + $newClass = $Class{$RecognizedBy{$_}}; + $newStatsBased = $StatsBased{$RecognizedBy{$_}}; + $newExpectedOpenGL = $ExpectedOpenGL{$RecognizedBy{$_}}; + $newRecognizedLine = $RecognizerLine{$RecognizedBy{$_}}; + + if ( ! defined $OldSupported{$_} ) + { + $oldSupported = 'NEW'; + $oldClass = '-'; + $oldStatsBased = '-'; + $oldExpectedOpenGL = '-'; + write; + $-++; # suppresses pagination + } + else + { + $oldSupported = $OldSupported{$_} || $NoMatch; + $oldClass = $OldClass{$_}; + $oldStatsBased = $OldStatsBased{$_}; + $oldExpectedOpenGL = $OldExpectedOpenGL{$_}; + + if ( ( $oldSupported ne $newSupported ) + || ( $oldClass ne $newClass ) + || ( $oldStatsBased ne $newStatsBased ) + || ( $oldExpectedOpenGL ne $newExpectedOpenGL ) + ) + { + write; + $-++; # suppresses pagination + } + } + + } +} + +exit $ErrorsSeen; diff --git a/scripts/install.py b/scripts/install.py deleted file mode 100755 index 7368af0b37..0000000000 --- a/scripts/install.py +++ /dev/null @@ -1,1162 +0,0 @@ -#!/usr/bin/env python -"""\ -@file install.py -@author Phoenix -@date 2008-01-27 -@brief Install files into an indra checkout. - -Install files as specified by: -https://wiki.lindenlab.com/wiki/User:Phoenix/Library_Installation - - -$LicenseInfo:firstyear=2007&license=mit$ - -Copyright (c) 2007-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$ -""" - -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() - -import copy -import optparse -import os -import platform -import pprint -import shutil -import tarfile -import tempfile -import urllib2 -import urlparse - -try: - # Python 2.6 - from hashlib import md5 -except ImportError: - # Python 2.5 and earlier - from md5 import new as md5 - -from indra.base import llsd -from indra.util import helpformatter - -# *HACK: Necessary for python 2.3. Consider removing this code wart -# after etch has deployed everywhere. 2008-12-23 Phoenix -try: - sorted = sorted -except NameError: - def sorted(in_list): - "Return a list which is a sorted copy of in_list." - # Copy the source to be more functional and side-effect free. - out_list = copy.copy(in_list) - out_list.sort() - return out_list - -class InstallFile(object): - "This is just a handy way to throw around details on a file in memory." - def __init__(self, pkgname, url, md5sum, cache_dir, platform_path): - self.pkgname = pkgname - self.url = url - self.md5sum = md5sum - filename = urlparse.urlparse(url)[2].split('/')[-1] - self.filename = os.path.join(cache_dir, filename) - self.platform_path = platform_path - - def __str__(self): - return "ifile{%s:%s}" % (self.pkgname, self.url) - - def _is_md5sum_match(self): - hasher = md5(file(self.filename, 'rb').read()) - if hasher.hexdigest() == self.md5sum: - return True - return False - - def is_match(self, platform): - """@brief Test to see if this ifile is part of platform - @param platform The target platform. Eg, windows or linux/i686/gcc/3.3 - @return Returns True if the ifile is in the platform. - """ - if self.platform_path[0] == 'common': - return True - req_platform_path = platform.split('/') - #print "platform:",req_platform_path - #print "path:",self.platform_path - # to match, every path part much match - match_count = min(len(req_platform_path), len(self.platform_path)) - for ii in range(0, match_count): - if req_platform_path[ii] != self.platform_path[ii]: - return False - #print "match!" - return True - - def fetch_local(self): - #print "Looking for:",self.filename - if not os.path.exists(self.filename): - pass - elif self.md5sum and not self._is_md5sum_match(): - print "md5 mismatch:", self.filename - os.remove(self.filename) - else: - print "Found matching package:", self.filename - return - print "Downloading",self.url,"to local file",self.filename - file(self.filename, 'wb').write(urllib2.urlopen(self.url).read()) - if self.md5sum and not self._is_md5sum_match(): - raise RuntimeError("Error matching md5 for %s" % self.url) - -class LicenseDefinition(object): - def __init__(self, definition): - #probably looks like: - # { text : ..., - # url : ... - # blessed : ... - # } - self._definition = definition - - -class InstallableDefinition(object): - def __init__(self, definition): - #probably looks like: - # { packages : {platform...}, - # copyright : ... - # license : ... - # description: ... - # } - self._definition = definition - - def _ifiles_from(self, tree, pkgname, cache_dir): - return self._ifiles_from_path(tree, pkgname, cache_dir, []) - - def _ifiles_from_path(self, tree, pkgname, cache_dir, path): - ifiles = [] - if 'url' in tree: - ifiles.append(InstallFile( - pkgname, - tree['url'], - tree.get('md5sum', None), - cache_dir, - path)) - else: - for key in tree: - platform_path = copy.copy(path) - platform_path.append(key) - ifiles.extend( - self._ifiles_from_path( - tree[key], - pkgname, - cache_dir, - platform_path)) - return ifiles - - def ifiles(self, pkgname, platform, cache_dir): - """@brief return a list of appropriate InstallFile instances to install - @param pkgname The name of the package to be installed, eg 'tut' - @param platform The target platform. Eg, windows or linux/i686/gcc/3.3 - @param cache_dir The directory to cache downloads. - @return Returns a list of InstallFiles which are part of this install - """ - if 'packages' not in self._definition: - return [] - all_ifiles = self._ifiles_from( - self._definition['packages'], - pkgname, - cache_dir) - if platform == 'all': - return all_ifiles - #print "Considering", len(all_ifiles), "packages for", pkgname - # split into 2 lines because pychecker thinks it might return none. - files = [ifile for ifile in all_ifiles if ifile.is_match(platform)] - return files - -class InstalledPackage(object): - def __init__(self, definition): - # looks like: - # { url1 : { files: [file1,file2,...], md5sum:... }, - # url2 : { files: [file1,file2,...], md5sum:... },... - # } - self._installed = {} - for url in definition: - self._installed[url] = definition[url] - - def urls(self): - return self._installed.keys() - - def files_in(self, url): - return self._installed[url].get('files', []) - - def get_md5sum(self, url): - return self._installed[url].get('md5sum', None) - - def remove(self, url): - self._installed.pop(url) - - def add_files(self, url, files): - if url not in self._installed: - self._installed[url] = {} - self._installed[url]['files'] = files - - def set_md5sum(self, url, md5sum): - if url not in self._installed: - self._installed[url] = {} - self._installed[url]['md5sum'] = md5sum - -class Installer(object): - def __init__(self, install_filename, installed_filename, dryrun): - self._install_filename = install_filename - self._install_changed = False - self._installed_filename = installed_filename - self._installed_changed = False - self._dryrun = dryrun - self._installables = {} - self._licenses = {} - self._installed = {} - self.load() - - def load(self): - if os.path.exists(self._install_filename): - install = llsd.parse(file(self._install_filename, 'rb').read()) - try: - for name in install['installables']: - self._installables[name] = InstallableDefinition( - install['installables'][name]) - except KeyError: - pass - try: - for name in install['licenses']: - self._licenses[name] = LicenseDefinition(install['licenses'][name]) - except KeyError: - pass - if os.path.exists(self._installed_filename): - installed = llsd.parse(file(self._installed_filename, 'rb').read()) - try: - bins = installed['installables'] - for name in bins: - self._installed[name] = InstalledPackage(bins[name]) - except KeyError: - pass - - def _write(self, filename, state): - print "Writing state to",filename - if not self._dryrun: - file(filename, 'wb').write(llsd.format_pretty_xml(state)) - - def save(self): - if self._install_changed: - state = {} - state['licenses'] = {} - for name in self._licenses: - state['licenses'][name] = self._licenses[name]._definition - #print "self._installables:",self._installables - state['installables'] = {} - for name in self._installables: - state['installables'][name] = \ - self._installables[name]._definition - self._write(self._install_filename, state) - if self._installed_changed: - state = {} - state['installables'] = {} - bin = state['installables'] - for name in self._installed: - #print "installed:",name,self._installed[name]._installed - bin[name] = self._installed[name]._installed - self._write(self._installed_filename, state) - - def is_valid_license(self, bin): - "@brief retrun true if we have valid license info for installable." - installable = self._installables[bin]._definition - if 'license' not in installable: - print >>sys.stderr, "No license info found for", bin - print >>sys.stderr, 'Please add the license with the', - print >>sys.stderr, '--add-installable option. See', \ - sys.argv[0], '--help' - return False - if installable['license'] not in self._licenses: - lic = installable['license'] - print >>sys.stderr, "Missing license info for '" + lic + "'.", - print >>sys.stderr, 'Please add the license with the', - print >>sys.stderr, '--add-license option. See', sys.argv[0], - print >>sys.stderr, '--help' - return False - return True - - def list_installables(self): - "Return a list of all known installables." - return sorted(self._installables.keys()) - - def detail_installable(self, name): - "Return a installable definition detail" - return self._installables[name]._definition - - def list_licenses(self): - "Return a list of all known licenses." - return sorted(self._licenses.keys()) - - def detail_license(self, name): - "Return a license definition detail" - return self._licenses[name]._definition - - def list_installed(self): - "Return a list of installed packages." - return sorted(self._installed.keys()) - - def detail_installed(self, name): - "Return file list for specific installed package." - filelist = [] - for url in self._installed[name]._installed.keys(): - filelist.extend(self._installed[name].files_in(url)) - return filelist - - def _update_field(self, description, field, value, multiline=False): - """Given a block and a field name, add or update it. - @param description a dict containing all the details of a description. - @param field the name of the field to update. - @param value the value of the field to update; if omitted, interview - will ask for value. - @param multiline boolean specifying whether field is multiline or not. - """ - if value: - description[field] = value - else: - if field in description: - print "Update value for '" + field + "'" - print "(Leave blank to keep current value)" - print "Current Value: '" + description[field] + "'" - else: - print "Specify value for '" + field + "'" - if not multiline: - new_value = raw_input("Enter New Value: ") - else: - print "Please enter " + field + ". End input with EOF (^D)." - new_value = sys.stdin.read() - - if field in description and not new_value: - pass - elif new_value: - description[field] = new_value - - self._install_changed = True - return True - - def _update_installable(self, name, platform, url, md5sum): - """Update installable entry with specific package information. - @param installable[in,out] a dict containing installable details. - @param platform Platform info, i.e. linux/i686, windows/i686 etc. - @param url URL of tar file - @param md5sum md5sum of tar file - """ - installable = self._installables[name]._definition - path = platform.split('/') - if 'packages' not in installable: - installable['packages'] = {} - update = installable['packages'] - for child in path: - if child not in update: - update[child] = {} - parent = update - update = update[child] - parent[child]['url'] = llsd.uri(url) - parent[child]['md5sum'] = md5sum - - self._install_changed = True - return True - - - def add_installable_package(self, name, **kwargs): - """Add an url for a platform path to the installable. - @param installable[in,out] a dict containing installable details. - """ - platform_help_str = """\ -Please enter a new package location and url. Some examples: -common -- specify a package for all platforms -linux -- specify a package for all arch and compilers on linux -darwin/universal -- specify a mac os x universal -windows/i686/vs/2003 -- specify a windows visual studio 2003 package""" - if name not in self._installables: - print "Error: must add library with --add-installable or " \ - +"--add-installable-metadata before using " \ - +"--add-installable-package option" - return False - else: - print "Updating installable '" + name + "'." - for arg in ('platform', 'url', 'md5sum'): - if not kwargs[arg]: - if arg == 'platform': - print platform_help_str - kwargs[arg] = raw_input("Package "+arg+":") - #path = kwargs['platform'].split('/') - - return self._update_installable(name, kwargs['platform'], - kwargs['url'], kwargs['md5sum']) - - def add_installable_metadata(self, name, **kwargs): - """Interactively add (only) library metadata into install, - w/o adding installable""" - if name not in self._installables: - print "Adding installable '" + name + "'." - self._installables[name] = InstallableDefinition({}) - else: - print "Updating installable '" + name + "'." - installable = self._installables[name]._definition - for field in ('copyright', 'license', 'description'): - self._update_field(installable, field, kwargs[field]) - print "Added installable '" + name + "':" - pprint.pprint(self._installables[name]) - - return True - - def add_installable(self, name, **kwargs): - "Interactively pull a new installable into the install" - ret_a = self.add_installable_metadata(name, **kwargs) - ret_b = self.add_installable_package(name, **kwargs) - return (ret_a and ret_b) - - def remove_installable(self, name): - self._installables.pop(name) - self._install_changed = True - - def add_license(self, name, **kwargs): - if name not in self._licenses: - print "Adding license '" + name + "'." - self._licenses[name] = LicenseDefinition({}) - else: - print "Updating license '" + name + "'." - the_license = self._licenses[name]._definition - for field in ('url', 'text'): - multiline = False - if field == 'text': - multiline = True - self._update_field(the_license, field, kwargs[field], multiline) - self._install_changed = True - return True - - def remove_license(self, name): - self._licenses.pop(name) - self._install_changed = True - - def _uninstall(self, installables): - """@brief Do the actual removal of files work. - *NOTE: This method is not transactionally safe -- ie, if it - raises an exception, internal state may be inconsistent. How - should we address this? - @param installables The package names to remove - """ - remove_file_list = [] - for pkgname in installables: - for url in self._installed[pkgname].urls(): - remove_file_list.extend( - self._installed[pkgname].files_in(url)) - self._installed[pkgname].remove(url) - if not self._dryrun: - self._installed_changed = True - if not self._dryrun: - self._installed.pop(pkgname) - remove_dir_set = set() - for filename in remove_file_list: - print "rm",filename - if not self._dryrun: - if os.path.exists(filename): - remove_dir_set.add(os.path.dirname(filename)) - try: - os.remove(filename) - except OSError: - # This is just for cleanup, so we don't care - # about normal failures. - pass - for dirname in remove_dir_set: - try: - os.removedirs(dirname) - except OSError: - # This is just for cleanup, so we don't care about - # normal failures. - pass - - def uninstall(self, installables, install_dir): - """@brief Remove the packages specified. - @param installables The package names to remove - @param install_dir The directory to work from - """ - print "uninstall",installables,"from",install_dir - cwd = os.getcwdu() - os.chdir(install_dir) - try: - self._uninstall(installables) - finally: - os.chdir(cwd) - - def _build_ifiles(self, platform, cache_dir): - """@brief determine what files to install - @param platform The target platform. Eg, windows or linux/i686/gcc/3.3 - @param cache_dir The directory to cache downloads. - @return Returns the ifiles to install - """ - ifiles = [] - for bin in self._installables: - ifiles.extend(self._installables[bin].ifiles(bin, - platform, - cache_dir)) - to_install = [] - #print "self._installed",self._installed - for ifile in ifiles: - if ifile.pkgname not in self._installed: - to_install.append(ifile) - elif ifile.url not in self._installed[ifile.pkgname].urls(): - to_install.append(ifile) - elif ifile.md5sum != \ - self._installed[ifile.pkgname].get_md5sum(ifile.url): - # *TODO: We may want to uninstall the old version too - # when we detect it is installed, but the md5 sum is - # different. - to_install.append(ifile) - else: - #print "Installation up to date:", - # ifile.pkgname,ifile.platform_path - pass - #print "to_install",to_install - return to_install - - def _install(self, to_install, install_dir): - for ifile in to_install: - tar = tarfile.open(ifile.filename, 'r') - print "Extracting",ifile.filename,"to",install_dir - if not self._dryrun: - # *NOTE: try to call extractall, which first appears - # in python 2.5. Phoenix 2008-01-28 - try: - tar.extractall(path=install_dir) - except AttributeError: - _extractall(tar, path=install_dir) - if ifile.pkgname in self._installed: - self._installed[ifile.pkgname].add_files( - ifile.url, - tar.getnames()) - self._installed[ifile.pkgname].set_md5sum( - ifile.url, - ifile.md5sum) - else: - # *HACK: this understands the installed package syntax. - definition = { ifile.url : - {'files': tar.getnames(), - 'md5sum' : ifile.md5sum } } - self._installed[ifile.pkgname] = InstalledPackage(definition) - self._installed_changed = True - - def install(self, installables, platform, install_dir, cache_dir): - """@brief Do the installation for for the platform. - @param installables The requested installables to install. - @param platform The target platform. Eg, windows or linux/i686/gcc/3.3 - @param install_dir The root directory to install into. Created - if missing. - @param cache_dir The directory to cache downloads. Created if - missing. - """ - # The ordering of steps in the method is to help reduce the - # likelihood that we break something. - install_dir = os.path.realpath(install_dir) - cache_dir = os.path.realpath(cache_dir) - _mkdir(install_dir) - _mkdir(cache_dir) - to_install = self._build_ifiles(platform, cache_dir) - - # Filter for files which we actually requested to install. - to_install = [ifl for ifl in to_install if ifl.pkgname in installables] - for ifile in to_install: - ifile.fetch_local() - self._install(to_install, install_dir) - - def do_install(self, installables, platform, install_dir, cache_dir=None, - check_license=True, scp=None): - """Determine what installables should be installed. If they were - passed in on the command line, use them, otherwise install - all known installables. - """ - if not cache_dir: - cache_dir = _default_installable_cache() - all_installables = self.list_installables() - if not len(installables): - install_installables = all_installables - else: - # passed in on the command line. We'll need to verify we - # know about them here. - install_installables = installables - for installable in install_installables: - if installable not in all_installables: - raise RuntimeError('Unknown installable: %s' % - (installable,)) - if check_license: - # *TODO: check against a list of 'known good' licenses. - # *TODO: check for urls which conflict -- will lead to - # problems. - for installable in install_installables: - if not self.is_valid_license(installable): - return 1 - - # Set up the 'scp' handler - opener = urllib2.build_opener() - scp_or_http = SCPOrHTTPHandler(scp) - opener.add_handler(scp_or_http) - urllib2.install_opener(opener) - - # Do the work of installing the requested installables. - self.install( - install_installables, - platform, - install_dir, - cache_dir) - scp_or_http.cleanup() - - def do_uninstall(self, installables, install_dir): - # Do not bother to check license if we're uninstalling. - all_installed = self.list_installed() - if not len(installables): - uninstall_installables = all_installed - else: - # passed in on the command line. We'll need to verify we - # know about them here. - uninstall_installables = installables - for installable in uninstall_installables: - if installable not in all_installed: - raise RuntimeError('Installable not installed: %s' % - (installable,)) - self.uninstall(uninstall_installables, install_dir) - -class SCPOrHTTPHandler(urllib2.BaseHandler): - """Evil hack to allow both the build system and developers consume - proprietary binaries. - To use http, export the environment variable: - INSTALL_USE_HTTP_FOR_SCP=true - """ - def __init__(self, scp_binary): - self._scp = scp_binary - self._dir = None - - def scp_open(self, request): - #scp:codex.lindenlab.com:/local/share/install_pkgs/package.tar.bz2 - remote = request.get_full_url()[4:] - if os.getenv('INSTALL_USE_HTTP_FOR_SCP', None) == 'true': - return self.do_http(remote) - try: - return self.do_scp(remote) - except: - self.cleanup() - raise - - def do_http(self, remote): - url = remote.split(':',1) - if not url[1].startswith('/'): - # in case it's in a homedir or something - url.insert(1, '/') - url.insert(0, "http://") - url = ''.join(url) - print "Using HTTP:",url - return urllib2.urlopen(url) - - def do_scp(self, remote): - if not self._dir: - self._dir = tempfile.mkdtemp() - local = os.path.join(self._dir, remote.split('/')[-1:][0]) - command = [] - for part in (self._scp, remote, local): - if ' ' in part: - # I hate shell escaping. - part.replace('\\', '\\\\') - part.replace('"', '\\"') - command.append('"%s"' % part) - else: - command.append(part) - #print "forking:", command - rv = os.system(' '.join(command)) - if rv != 0: - raise RuntimeError("Cannot fetch: %s" % remote) - return file(local, 'rb') - - def cleanup(self): - if self._dir: - shutil.rmtree(self._dir) - - -# -# *NOTE: PULLED FROM PYTHON 2.5 tarfile.py Phoenix 2008-01-28 -# -def _extractall(tar, path=".", members=None): - """Extract all members from the archive to the current working - directory and set owner, modification time and permissions on - directories afterwards. `path' specifies a different directory - to extract to. `members' is optional and must be a subset of the - list returned by getmembers(). - """ - directories = [] - - if members is None: - members = tar - - for tarinfo in members: - if tarinfo.isdir(): - # Extract directory with a safe mode, so that - # all files below can be extracted as well. - try: - os.makedirs(os.path.join(path, tarinfo.name), 0777) - except EnvironmentError: - pass - directories.append(tarinfo) - else: - tar.extract(tarinfo, path) - - # Reverse sort directories. - directories.sort(lambda a, b: cmp(a.name, b.name)) - directories.reverse() - - # Set correct owner, mtime and filemode on directories. - for tarinfo in directories: - path = os.path.join(path, tarinfo.name) - try: - tar.chown(tarinfo, path) - tar.utime(tarinfo, path) - tar.chmod(tarinfo, path) - except tarfile.ExtractError, e: - if tar.errorlevel > 1: - raise - else: - tar._dbg(1, "tarfile: %s" % e) - - -def _mkdir(directory): - "Safe, repeatable way to make a directory." - if not os.path.exists(directory): - os.makedirs(directory) - -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] - if this_platform == 'linux': - if platform.architecture()[0] == '64bit': - # TODO -- someday when install.py accepts a platform of the form - # os/arch/compiler/compiler_version then we can replace the - # 'linux64' platform with 'linux/x86_64/gcc/4.1' - this_platform = 'linux' - return this_platform - -def _getuser(): - "Get the user" - try: - # Unix-only. - import getpass - return getpass.getuser() - except ImportError: - import ctypes - MAX_PATH = 260 # according to a recent WinDef.h - name = ctypes.create_unicode_buffer(MAX_PATH) - namelen = ctypes.c_int(len(name)) # len in chars, NOT bytes - if not ctypes.windll.advapi32.GetUserNameW(name, ctypes.byref(namelen)): - raise ctypes.WinError() - return name.value - -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 - -def parse_args(): - parser = optparse.OptionParser( - usage="usage: %prog [options] [installable1 [installable2...]]", - formatter = helpformatter.Formatter(), - description="""This script fetches and installs installable packages. -It also handles uninstalling those packages and manages the mapping between -packages and their license. - -The process is to open and read an install manifest file which specifies -what files should be installed. For each installable to be installed. - * make sure it has a license - * check the installed version - ** if not installed and needs to be, download and install - ** if installed version differs, download & install - -If no installables are specified on the command line, then the defaut -behavior is to install all known installables appropriate for the platform -specified or uninstall all installables if --uninstall is set. You can specify -more than one installable on the command line. - -When specifying a platform, you can specify 'all' to install all -packages, or any platform of the form: - -OS[/arch[/compiler[/compiler_version]]] - -Where the supported values for each are: -OS: darwin, linux, windows, solaris -arch: i686, x86_64, ppc, universal -compiler: vs, gcc -compiler_version: 2003, 2005, 2008, 3.3, 3.4, 4.0, etc. - -No checks are made to ensure a valid combination of platform -parts. Some exmples of valid platforms: - -windows -windows/i686/vs/2005 -linux/x86_64/gcc/3.3 -linux/x86_64/gcc/4.0 -darwin/universal/gcc/4.0 -""") - parser.add_option( - '--dry-run', - action='store_true', - default=False, - dest='dryrun', - help='Do not actually install files. Downloads will still happen.') - parser.add_option( - '--install-manifest', - type='string', - default=os.path.join(base_dir, 'install.xml'), - dest='install_filename', - help='The file used to describe what should be installed.') - parser.add_option( - '--installed-manifest', - type='string', - default=os.path.join(base_dir, 'installed.xml'), - dest='installed_filename', - help='The file used to record what is installed.') - parser.add_option( - '--export-manifest', - action='store_true', - default=False, - dest='export_manifest', - help="Print the install manifest to stdout and exit.") - parser.add_option( - '-p', '--platform', - type='string', - default=_get_platform(), - dest='platform', - help="""Override the automatically determined platform. \ -You can specify 'all' to do a installation of installables for all platforms.""") - 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.') - parser.add_option( - '--list-installed', - action='store_true', - default=False, - dest='list_installed', - help="List the installed package names and exit.") - parser.add_option( - '--skip-license-check', - action='store_false', - default=True, - dest='check_license', - help="Do not perform the license check.") - parser.add_option( - '--list-licenses', - action='store_true', - default=False, - dest='list_licenses', - help="List known licenses and exit.") - parser.add_option( - '--detail-license', - type='string', - default=None, - dest='detail_license', - help="Get detailed information on specified license and exit.") - parser.add_option( - '--add-license', - type='string', - default=None, - dest='new_license', - help="""Add a license to the install file. Argument is the name of \ -license. Specify --license-url if the license is remote or specify \ ---license-text, otherwse the license text will be read from standard \ -input.""") - parser.add_option( - '--license-url', - type='string', - default=None, - dest='license_url', - help="""Put the specified url into an added license. \ -Ignored if --add-license is not specified.""") - parser.add_option( - '--license-text', - type='string', - default=None, - dest='license_text', - help="""Put the text into an added license. \ -Ignored if --add-license is not specified.""") - parser.add_option( - '--remove-license', - type='string', - default=None, - dest='remove_license', - help="Remove a named license.") - parser.add_option( - '--remove-installable', - type='string', - default=None, - dest='remove_installable', - help="Remove a installable from the install file.") - parser.add_option( - '--add-installable', - type='string', - default=None, - dest='add_installable', - help="""Add a installable into the install file. Argument is \ -the name of the installable to add.""") - parser.add_option( - '--add-installable-metadata', - type='string', - default=None, - dest='add_installable_metadata', - help="""Add package for library into the install file. Argument is \ -the name of the library to add.""") - parser.add_option( - '--installable-copyright', - type='string', - default=None, - dest='installable_copyright', - help="""Copyright for specified new package. Ignored if \ ---add-installable is not specified.""") - parser.add_option( - '--installable-license', - type='string', - default=None, - dest='installable_license', - help="""Name of license for specified new package. Ignored if \ ---add-installable is not specified.""") - parser.add_option( - '--installable-description', - type='string', - default=None, - dest='installable_description', - help="""Description for specified new package. Ignored if \ ---add-installable is not specified.""") - parser.add_option( - '--add-installable-package', - type='string', - default=None, - dest='add_installable_package', - help="""Add package for library into the install file. Argument is \ -the name of the library to add.""") - parser.add_option( - '--package-platform', - type='string', - default=None, - dest='package_platform', - help="""Platform for specified new package. \ -Ignored if --add-installable or --add-installable-package is not specified.""") - parser.add_option( - '--package-url', - type='string', - default=None, - dest='package_url', - help="""URL for specified package. \ -Ignored if --add-installable or --add-installable-package is not specified.""") - parser.add_option( - '--package-md5', - type='string', - default=None, - dest='package_md5', - help="""md5sum for new package. \ -Ignored if --add-installable or --add-installable-package is not specified.""") - parser.add_option( - '--list', - action='store_true', - default=False, - dest='list_installables', - help="List the installables in the install manifest and exit.") - parser.add_option( - '--detail', - type='string', - default=None, - dest='detail_installable', - help="Get detailed information on specified installable and exit.") - parser.add_option( - '--detail-installed', - type='string', - default=None, - dest='detail_installed', - help="Get list of files for specified installed installable and exit.") - parser.add_option( - '--uninstall', - action='store_true', - default=False, - dest='uninstall', - help="""Remove the installables specified in the arguments. Just like \ -during installation, if no installables are listed then all installed \ -installables are removed.""") - parser.add_option( - '--scp', - type='string', - default='scp', - dest='scp', - help="Specify the path to your scp program.") - - return parser.parse_args() - -def main(): - options, args = parse_args() - installer = Installer( - options.install_filename, - options.installed_filename, - options.dryrun) - - # - # Handle the queries for information - # - if options.list_installed: - print "installed list:", installer.list_installed() - return 0 - if options.list_installables: - print "installable list:", installer.list_installables() - return 0 - if options.detail_installable: - try: - detail = installer.detail_installable(options.detail_installable) - print "Detail on installable",options.detail_installable+":" - pprint.pprint(detail) - except KeyError: - print "Installable '"+options.detail_installable+"' not found in", - print "install file." - return 0 - if options.detail_installed: - try: - detail = installer.detail_installed(options.detail_installed) - #print "Detail on installed",options.detail_installed+":" - for line in detail: - print line - except: - raise - print "Installable '"+options.detail_installed+"' not found in ", - print "install file." - return 0 - if options.list_licenses: - print "license list:", installer.list_licenses() - return 0 - if options.detail_license: - try: - detail = installer.detail_license(options.detail_license) - print "Detail on license",options.detail_license+":" - pprint.pprint(detail) - except KeyError: - print "License '"+options.detail_license+"' not defined in", - print "install file." - return 0 - if options.export_manifest: - # *HACK: just re-parse the install manifest and pretty print - # it. easier than looking at the datastructure designed for - # actually determining what to install - install = llsd.parse(file(options.install_filename, 'rb').read()) - pprint.pprint(install) - return 0 - - # - # Handle updates -- can only do one of these - # *TODO: should this change the command line syntax? - # - if options.new_license: - if not installer.add_license( - options.new_license, - text=options.license_text, - url=options.license_url): - return 1 - elif options.remove_license: - installer.remove_license(options.remove_license) - elif options.remove_installable: - installer.remove_installable(options.remove_installable) - elif options.add_installable: - if not installer.add_installable( - options.add_installable, - copyright=options.installable_copyright, - license=options.installable_license, - description=options.installable_description, - platform=options.package_platform, - url=options.package_url, - md5sum=options.package_md5): - return 1 - elif options.add_installable_metadata: - if not installer.add_installable_metadata( - options.add_installable_metadata, - copyright=options.installable_copyright, - license=options.installable_license, - description=options.installable_description): - return 1 - elif options.add_installable_package: - if not installer.add_installable_package( - options.add_installable_package, - platform=options.package_platform, - url=options.package_url, - md5sum=options.package_md5): - return 1 - elif options.uninstall: - installer.do_uninstall(args, options.install_dir) - else: - installer.do_install(args, options.platform, options.install_dir, - options.cache_dir, options.check_license, - options.scp) - - # save out any changes - installer.save() - return 0 - -if __name__ == '__main__': - #print sys.argv - sys.exit(main()) diff --git a/scripts/md5check.py b/scripts/md5check.py new file mode 100755 index 0000000000..1a54a2844c --- /dev/null +++ b/scripts/md5check.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +"""\ +@file md5check.py +@brief Replacement for message template compatibility verifier. + +$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$ +""" + +import sys +import hashlib + +if len(sys.argv) != 3: + print """Usage: %s --create|<hash-digest> <file> + +Creates an md5sum hash digest of the specified file content +and compares it with the given hash digest. + +If --create is used instead of a hash digest, it will simply +print out the hash digest of specified file content. +""" % sys.argv[0] + sys.exit(1) + +if sys.argv[2] == '-': + fh = sys.stdin + filename = "<stdin>" +else: + filename = sys.argv[2] + fh = open(filename) + +hexdigest = hashlib.md5(fh.read()).hexdigest() +if sys.argv[1] == '--create': + print hexdigest +elif hexdigest == sys.argv[1]: + print "md5sum check passed:", filename +else: + print "md5sum check FAILED:", filename + sys.exit(1) diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index d4f791c202..3cec4ada1c 100644..100755 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -2061,6 +2061,15 @@ version 2.0 { IsPhantom BOOL } { CastsShadows BOOL } } + { + ExtraPhysics Variable + { PhysicsShapeType U8 } + { Density F32 } + { Friction F32 } + { Restitution F32 } + { GravityMultiplier F32 } + + } } @@ -2930,6 +2939,10 @@ version 2.0 PidStat Single { PID S32 } } + { + RegionInfo Variable + { RegionFlagsExtended U64 } + } } // viewer -> sim @@ -2966,7 +2979,7 @@ version 2.0 { BillableFactor F32 } { ObjectBonusFactor F32 } { WaterHeight F32 } - { TerrainRaiseLimit F32 } + { TerrainRaiseLimit F32 } { TerrainLowerLimit F32 } { PricePerMeter S32 } { RedirectGridX S32 } @@ -2982,6 +2995,10 @@ version 2.0 { HardMaxAgents U32 } { HardMaxObjects U32 } } + { + RegionInfo3 Variable + { RegionFlagsExtended U64 } + } } // GodUpdateRegionInfo @@ -3007,6 +3024,10 @@ version 2.0 { RedirectGridX S32 } { RedirectGridY S32 } } + { + RegionInfo2 Variable + { RegionFlagsExtended U64 } + } } //NearestLandingRegionRequest @@ -3107,6 +3128,11 @@ version 2.0 { ProductSKU Variable 1 } // string { ProductName Variable 1 } // string } + { + RegionInfo4 Variable + { RegionFlagsExtended U64 } + { RegionProtocols U64 } + } } // RegionHandshakeReply @@ -3562,6 +3588,16 @@ version 2.0 VisualParam Variable { ParamValue U8 } } + { + AppearanceData Variable + { AppearanceVersion U8 } + { CofVersion S32 } + { Flags U32 } + } + { + AppearanceHover Variable + { HoverHeight LLVector3 } + } } // AvatarSitResponse - response to a request to sit on an object @@ -4242,6 +4278,10 @@ version 2.0 Buttons Variable { ButtonLabel Variable 1 } } + { + OwnerData Variable + { OwnerID LLUUID } + } } @@ -6762,6 +6802,8 @@ version 2.0 } // And, the money transfer +// *NOTE: Unused as of 2010-04-06, because all back-end money transactions +// are done with web services via L$ API. JC { MoneyTransferBackend Low 312 Trusted Zerocoded { @@ -6812,6 +6854,19 @@ version 2.0 { SquareMetersCommitted S32 } { Description Variable 1 } // string } + // For replies that are part of a transaction (buying something) provide + // metadata for localization. If TransactionType is 0, the message is + // purely a balance update. Added for server 1.40 and viewer 2.1. JC + { + TransactionInfo Single + { TransactionType S32 } // lltransactiontype.h + { SourceID LLUUID } + { IsSourceGroup BOOL } + { DestID LLUUID } + { IsDestGroup BOOL } + { Amount S32 } + { ItemDescription Variable 1 } // string + } } @@ -6838,6 +6893,17 @@ version 2.0 { SquareMetersCommitted S32 } { Description Variable 1 } // string } + // See MoneyBalanceReply above. + { + TransactionInfo Single + { TransactionType S32 } // lltransactiontype.h + { SourceID LLUUID } + { IsSourceGroup BOOL } + { DestID LLUUID } + { IsDestGroup BOOL } + { Amount S32 } + { ItemDescription Variable 1 } // string + } } @@ -8972,5 +9038,7 @@ version 2.0 { InvType S8 } { Name Variable 1 } { Description Variable 1 } + } } + diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1 new file mode 100755 index 0000000000..e699efb03c --- /dev/null +++ b/scripts/messages/message_template.msg.sha1 @@ -0,0 +1 @@ +2286adc795b1b06eb86fdda431a71a6f0874b4f1
\ No newline at end of file diff --git a/scripts/packages-formatter.py b/scripts/packages-formatter.py new file mode 100755 index 0000000000..4e66cf9ed4 --- /dev/null +++ b/scripts/packages-formatter.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +"""\ +This module formats the package version and copyright information for the +viewer and its dependent packages. + +$LicenseInfo:firstyear=2014&license=viewerlgpl$ +Second Life Viewer Source Code +Copyright (C) 2014, 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 os +import sys +import errno +import re +import subprocess + +_autobuild=os.getenv('AUTOBUILD', 'autobuild') + +pkg_line=re.compile('^([\w-]+):\s+(.*)$') + +def autobuild(*args): + """ + Launch autobuild with specified command-line arguments. + Return its stdout pipe from which the caller can read. + """ + # subprocess wants a list, not a tuple + command = [_autobuild] + list(args) + try: + child = subprocess.Popen(command, + stdin=None, stdout=subprocess.PIPE, + universal_newlines=True) + except OSError as err: + if err.errno != errno.ENOENT: + # Don't attempt to interpret anything but ENOENT + raise + # Here it's ENOENT: subprocess can't find the autobuild executable. + print >>sys.stderr, "packages-formatter on %s: can't run autobuild:\n%s\n%s" % \ + (sys.platform, ' '.join(command), err) + sys.exit(1) + + # no exceptions yet, let caller read stdout + return child.stdout + +version={} +versions=autobuild('install', '--versions') +for line in versions: + pkg_info = pkg_line.match(line) + if pkg_info: + pkg = pkg_info.group(1) + if pkg not in version: + version[pkg] = pkg_info.group(2).strip() + else: + sys.exit("Duplicate version for %s" % pkg) + else: + sys.exit("Unrecognized --versions output: %s" % line) + +copyright={} +copyrights=autobuild('install', '--copyrights') +viewer_copyright = copyrights.readline() # first line is the copyright for the viewer itself +for line in copyrights: + pkg_info = pkg_line.match(line) + if pkg_info: + pkg = pkg_info.group(1) + if pkg not in copyright: + copyright[pkg] = pkg_info.group(2).strip() + else: + sys.exit("Duplicate copyright for %s" % pkg) + else: + sys.exit("Unrecognized --copyrights output: %s" % line) + +print viewer_copyright +for pkg in sorted(version): + print ': '.join([pkg, version[pkg]]) + if pkg in copyright: + print copyright[pkg] + else: + sys.exit("No copyright for %s" % pkg) diff --git a/scripts/setup-path.py b/scripts/setup-path.py index 157bda0027..ce83d815bf 100755 --- a/scripts/setup-path.py +++ b/scripts/setup-path.py @@ -1,34 +1,28 @@ -#!/usr/bin/python +#!/usr/bin/env 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$ +$LicenseInfo:firstyear=2007&license=viewerlgpl$ +Second Life Viewer Source Code +Copyright (C) 2010, Linden Research, Inc. -Copyright (c) 2007-2009, 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. -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. +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$ """ diff --git a/scripts/template_verifier.py b/scripts/template_verifier.py index adcfcbcae6..b44410cdd8 100755 --- a/scripts/template_verifier.py +++ b/scripts/template_verifier.py @@ -1,33 +1,27 @@ -#!/usr/bin/python +#!/usr/bin/env python """\ @file template_verifier.py @brief Message template compatibility verifier. -$LicenseInfo:firstyear=2007&license=viewergpl$ +$LicenseInfo:firstyear=2007&license=viewerlgpl$ +Second Life Viewer Source Code +Copyright (C) 2010, Linden Research, Inc. -Copyright (c) 2007-2009, 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. -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. +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$ """ @@ -72,6 +66,7 @@ add_indra_lib_path() import optparse import os import urllib +import hashlib from indra.ipc import compatibility from indra.ipc import tokenstream @@ -234,11 +229,14 @@ 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', + default='http://bitbucket.org/lindenlab/master-message-template/raw/tip/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.""") + parser.add_option( + '-f', '--force', action='store_true', dest='force_verification', + default=False, help="""Set to true to skip the sha_1 check and force template verification.""") options, args = parser.parse_args(sysargs) @@ -275,8 +273,18 @@ http://wiki.secondlife.com/wiki/Template_verifier.py print "current:", current_filename current_url = 'file://%s' % current_filename - # retrieve the contents of the local template and check for syntax + # retrieve the contents of the local template current = fetch(current_url) + hexdigest = hashlib.sha1(current).hexdigest() + if not options.force_verification: + # Early exist if the template hasn't changed. + sha_url = "%s.sha1" % current_url + current_sha = fetch(sha_url) + if hexdigest == current_sha: + print "Message template SHA_1 has not changed." + sys.exit(0) + + # and check for syntax current_parsed = llmessage.parseTemplateString(current) if options.cache_master: @@ -307,6 +315,12 @@ http://wiki.secondlife.com/wiki/Template_verifier.py if acceptable: explain("--- PASS ---", compat) + if options.force_verification == False: + print "Updating sha1 to %s" % hexdigest + sha_filename = "%s.sha1" % current_filename + sha_file = open(sha_filename, 'w') + sha_file.write(hexdigest) + sha_file.close() else: explain("*** FAIL ***", compat) return 1 diff --git a/scripts/templates/template-cpp.cpp b/scripts/templates/template-cpp.cpp new file mode 100755 index 0000000000..35d8441c87 --- /dev/null +++ b/scripts/templates/template-cpp.cpp @@ -0,0 +1,30 @@ +/** +* @file #filename#.cpp +* @brief Implementation of #filename# +* @author #getpass.getuser()#@lindenlab.com +* +* $LicenseInfo:firstyear=#datetime.datetime.now().year#&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) #datetime.datetime.now().year#, 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$ +*/ + + +#'' if ( skip_h ) else '%cinclude "%s.h"' % (35,filename)# + diff --git a/scripts/templates/template-h.h b/scripts/templates/template-h.h new file mode 100755 index 0000000000..ce7b4ddc87 --- /dev/null +++ b/scripts/templates/template-h.h @@ -0,0 +1,31 @@ +/** +* @file #filename#.h +* @brief Header file for #filename# +* @author #getpass.getuser()#@lindenlab.com +* +* $LicenseInfo:firstyear=#datetime.datetime.now().year#&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) #datetime.datetime.now().year#, 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$ +*/ +#'%c'%35#ifndef LL_#filename.upper().replace('-','_')#_H +#'%c'%35#define LL_#filename.upper().replace('-','_')#_H + + +#'%c'%35#endif // LL_#filename.upper().replace('-','_')#_H diff --git a/scripts/update_version_files.py b/scripts/update_version_files.py deleted file mode 100755 index da60fd105a..0000000000 --- a/scripts/update_version_files.py +++ /dev/null @@ -1,331 +0,0 @@ -#!/usr/bin/python -# -# Update all of the various files in the repository to a new version number, -# instead of having to figure it out by hand -# - -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 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. - --revision - Specify the revision to replace the last digit of the version. - By default, revision is computed from the version control system. - --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. - --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/llcommon/llversionserver.h'] = \ - (('const S32 LL_VERSION_MAJOR = (\d+);', - 'const S32 LL_VERSION_MAJOR = %(SERVER_VER_MAJOR)s;'), - ('const S32 LL_VERSION_MINOR = (\d+);', - 'const S32 LL_VERSION_MINOR = %(SERVER_VER_MINOR)s;'), - ('const S32 LL_VERSION_PATCH = (\d+);', - 'const S32 LL_VERSION_PATCH = %(SERVER_VER_PATCH)s;'), - ('const S32 LL_VERSION_BUILD = (\d+);', - 'const S32 LL_VERSION_BUILD = %(SERVER_VER_BUILD)s;'), - ('const char \* const LL_CHANNEL = "(.+)";', - 'const char * const LL_CHANNEL = "%(SERVER_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>'),) - -# 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=', - 'revision=', - 'channel=', - 'server_channel=', - 'skip-on-branch=', - 'verbose', - 'server', - 'viewer', - 'help']) - update_server = False - update_viewer = False - new_version = None - new_revision = None - new_viewer_channel = None - new_server_channel = None - skip_on_branch_re = None - for o,a in opts: - if o in ('--version'): - new_version = a - if o in ('--revision'): - new_revision = 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 ('--server_channel'): - new_server_channel = 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_server or update_viewer): - update_server = True - 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 - - try: - server_channel = llversion.get_server_channel() - server_version = llversion.get_server_version() - except IOError: - print "Server version file not present, skipping..." - server_channel = None - server_version = None - update_server = False - - if verbose: - print "Source Path:", src_root - if viewer_channel != None: - print "Current viewer channel/version: '%(viewer_channel)s' / '%(viewer_version)s'" % locals() - if server_channel != None: - print "Current server channel/version: '%(server_channel)s' / '%(server_version)s'" % locals() - print - - # Determine new channel(s) - if new_viewer_channel != None and len(new_viewer_channel) > 0: - viewer_channel = new_viewer_channel - if new_server_channel != None and len(new_server_channel) > 0: - server_channel = new_server_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 - if update_server: - server_version = new_version - else: - - if llversion.using_svn(): - if new_revision: - revision = new_revision - else: - revision = llversion.get_svn_revision() - branch = llversion.get_svn_branch() - elif llversion.using_hg(): - if new_revision: - revision = new_revision - else: - revision = llversion.get_hg_changeset() - branch = llversion.get_hg_repo() - elif new_revision: - revision = new_revision - branch = "unknown" - else: - print >>sys.stderr, "ERROR: could not determine revision and branch" - return -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 update_server: - m = version_re.match(server_version) - server_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() - if update_server: - print "Setting server channel/version: '%(server_channel)s' / '%(server_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) - - if server_version != None: - m = version_re.match(server_version) - SERVER_VER_MAJOR = m.group(1) - SERVER_VER_MINOR = m.group(2) - SERVER_VER_PATCH = m.group(3) - SERVER_VER_BUILD = m.group(4) - - # For readability and symmetry with version strings: - VIEWER_CHANNEL = viewer_channel - SERVER_CHANNEL = server_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() - |