summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yaml179
-rwxr-xr-xbuild.sh77
-rw-r--r--buildscripts_support_functions60
-rw-r--r--indra/llcommon/tests/llleap_test.cpp25
-rw-r--r--indra/llcommon/tests/llprocess_test.cpp64
-rw-r--r--indra/newview/llappviewer.cpp4
-rw-r--r--indra/newview/llpanellogin.cpp4
-rw-r--r--indra/newview/lltranslate.cpp4
-rw-r--r--indra/newview/llversioninfo.cpp2
-rw-r--r--indra/newview/llversioninfo.h2
-rw-r--r--indra/newview/llweb.cpp2
-rw-r--r--indra/newview/llxmlrpctransaction.cpp2
-rw-r--r--indra/test/namedtempfile.h31
13 files changed, 360 insertions, 96 deletions
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index d0f1b59ae6..dc5fef4177 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -4,7 +4,7 @@ on:
workflow_dispatch:
pull_request:
push:
- branches: ["actions"]
+ branches: ["actions*"]
tags: ["*"]
jobs:
@@ -15,17 +15,17 @@ jobs:
configuration: [Release]
addrsize: [64]
python-version: ["3.11"]
- include:
+ developer_dir: ["", "/Applications/Xcode_14.0.1.app/Contents/Developer"]
+ exclude:
- runner: windows-large
- configuration: Release
- addrsize: 32
- python-version: "3.11"
- - runner: macos-12-xl
developer_dir: "/Applications/Xcode_14.0.1.app/Contents/Developer"
+ ## nat 2023-07-07: trying to resolve the Windows Python permissions
+ ## problem; don't bother running Mac builds.
+ - runner: macos-12-xl
runs-on: ${{ matrix.runner }}
env:
AUTOBUILD_ADDRSIZE: ${{ matrix.addrsize }}
- AUTOBUILD_CONFIGURATION: ${{ matrix.configuration }}
+ AUTOBUILD_BUILD_ID: ${{ github.run_id }}
# authorizes fetching private constituent packages
AUTOBUILD_GITHUB_TOKEN: ${{ secrets.SHARED_AUTOBUILD_GITHUB_TOKEN }}
AUTOBUILD_INSTALLABLE_CACHE: ${{ github.workspace }}/.autobuild-installables
@@ -34,15 +34,24 @@ jobs:
DEVELOPER_DIR: ${{ matrix.developer_dir }}
# Ensure that viewer builds engage Bugsplat.
BUGSPLAT_DB: "SecondLife_Viewer_2018"
+ BUGSPLAT_PASS: ${{ secrets.BUGSPLAT_PASS }}
+ BUGSPLAT_USER: ${{ secrets.BUGSPLAT_USER }}
+ build_coverity: false
+ build_log_dir: ${{ github.workspace }}/.logs
+ build_viewer: true
+ BUILDSCRIPTS_SHARED: ${{ github.workspace }}/.shared
+ # extracted and committed to viewer repo
+ BUILDSCRIPTS_SUPPORT_FUNCTIONS: ${{ github.workspace }}/buildscripts_support_functions
+ GIT_REF: ${{ github.head_ref || github.ref }}
+ LL_SKIP_REQUIRE_SYSROOT: 1
# Setting this variable directs Linden's TUT test driver code to capture
# test-program log output at the specified level, but to display it only if
# the individual test fails.
LOGFAIL: DEBUG
- # if unit tests fail to import llsd (i.e. wrong Python interpreter),
- # make py.exe enumerate the possibilities and explain its choice
- PYLAUNCHER_DEBUG: "1"
- GIT_REF: ${{ github.head_ref || github.ref }}
- LL_SKIP_REQUIRE_SYSROOT: 1
+ master_message_template_checkout: ${{ github.workspace }}/.master-message-template
+ # Only set variants to the one configuration: don't let build.sh loop
+ # over variants, let GitHub distribute variants over multiple hosts.
+ variants: ${{ matrix.configuration }}
steps:
- name: Checkout code
uses: actions/checkout@v3
@@ -61,7 +70,13 @@ jobs:
ref: viewer
path: .build-variables
- - name: Install autobuild
+ - name: Checkout master-message-template
+ uses: actions/checkout@v3
+ with:
+ repository: secondlife/master-message-template
+ path: .master-message-template
+
+ - name: Install autobuild
run: pip3 install autobuild llsd
- name: Cache autobuild packages
@@ -84,31 +99,137 @@ jobs:
env:
RUNNER_OS: ${{ runner.os }}
run: |
+ # set up things the viewer's build.sh script expects
+ mkdir -p "$build_log_dir"
+ mkdir -p "$BUILDSCRIPTS_SHARED/packages/lib/python"
+ source "$BUILDSCRIPTS_SUPPORT_FUNCTIONS"
+ if [[ "$OSTYPE" == "cygwin" ]]
+ then
+ native_path() { cygpath --windows "$1"; }
+ shell_path() { cygpath --unix "$1"; }
+ else
+ native_path() { echo "$1"; }
+ shell_path() { echo "$1"; }
+ fi
+ finalize()
+ {
+ case "$1" in
+ true|0)
+ record_success "Build Succeeded"
+ ;;
+ *)
+ record_failure "Build Failed with $1"
+ ;;
+ esac
+ }
+ initialize_build()
+ {
+ echo "initialize_build"
+ }
+ initialize_version()
+ {
+ export revision="$AUTOBUILD_BUILD_ID"
+ }
+ python_cmd()
+ {
+ if [[ "x${1:0:1}" == "x-" ]] # -m, -c, etc.
+ then # if $1 is a switch, don't try to twiddle paths
+ "$(shell_path "$PYTHON_COMMAND")" "$@"
+ elif [[ "$(basename "$1")" == "codeticket.py" ]]
+ then # ignore any attempt to contact codeticket
+ echo "## $@"
+ else # running a script at an explicit path: fix path for Python
+ local script="$1"
+ shift
+ "$(shell_path "$PYTHON_COMMAND")" "$(native_path "$script")" "$@"
+ fi
+ }
+ repo_branch()
+ {
+ git -C "$1" branch | grep '^* ' | cut -c 3-
+ }
+ record_dependencies_graph()
+ {
+ echo "TODO: generate and post dependency graph"
+ }
+ # Since we're not uploading to codeticket, DO NOT sleep for minutes.
+ sleep()
+ {
+ echo "Not sleeping for $1 seconds"
+ }
+ export -f native_path shell_path finalize initialize_build initialize_version
+ export -f python_cmd repo_branch record_dependencies_graph sleep
+ ## Useful for diagnosing Windows LLProcess/LLLeap test failures
+ ##export APR_LOG="${RUNNER_TEMP}/apr.log"
+ export arch=$(uname | cut -b-6)
+ # Surprise! GH Windows runner's MINGW6 is a $arch value we've never
+ # seen before, so numerous tests don't know about it.
+ [[ "$arch" == "MINGW6" ]] && arch=CYGWIN
+ export AUTOBUILD="$(which autobuild)"
+ # Build with a tag like "Second Life Project Shiny:abcdef0" to get a
+ # viewer channel "Second Life Project Shiny" (ignoring ":hash",
+ # needed to disambiguate tags).
+ if [[ "${GIT_REF:0:12}" == "Second Life " ]]
+ then export viewer_channel="${GIT_REF%:*}"
+ else export viewer_channel="Second Life Test"
+ fi
+
# On windows we need to point the build to the correct python
# as neither CMake's FindPython nor our custom Python.cmake module
# will resolve the correct interpreter location.
if [[ "$RUNNER_OS" == "Windows" ]]; then
- export PYTHON="$(cygpath -m "$(which python)")"
+ export PYTHON="$(native_path "$(which python)")"
echo "Python location: $PYTHON"
+ export PYTHON_COMMAND="$PYTHON"
+ else
+ export PYTHON_COMMAND="python3"
fi
+ export PYTHON_COMMAND_NATIVE="$(native_path "$PYTHON_COMMAND")"
- autobuild configure -- -DVIEWER_CHANNEL="Second Life Test ${GIT_REF##*/}"
- autobuild build --no-configure
+ ./build.sh
- # Find artifacts
- if [[ "$RUNNER_OS" == "Windows" ]]; then
- installer_path=$(find ./build-*/newview/ | grep '_Setup\.exe')
- installer_name="$(basename $installer_path)"
- elif [[ "$RUNNER_OS" == "macOS" ]]; then
- installer_path=$(find ./build-*/newview/ | grep '\.dmg')
- installer_name="$(basename $installer_path)"
- fi
+ # Each artifact is downloaded as a distinct .zip file. Multiple jobs
+ # (per the matrix above) writing the same filepath to the same
+ # artifact name will *overwrite* that file. Moreover, they can
+ # interfere with each other, causing the upload to fail.
+ # https://github.com/actions/upload-artifact#uploading-to-the-same-artifact
+ # Given the size of our installers, and the fact that we typically
+ # only want to download just one instead of a single zip containing
+ # several, generate a distinct artifact name for each installer.
+ # Since the matrix above can run multiple builds on the same
+ # platform, we must disambiguate on more than the platform name.
+ # If we were still running Windows 32-bit builds, we'd need to
+ # qualify the artifact with bit width.
+ # DEVELOPER_DIR="/Applications/Xcode_14.0.1.app/Contents/Developer"
+ # or the empty string, so this produces dev="Xcode_14.0.1" or ".".
+ dev="$(basename "$(dirname "$(dirname "$DEVELOPER_DIR")")" .app)"
+ artifact="$RUNNER_OS $dev"
+ # For empty DEVELOPER_DIR, dev is ".", so artifact can end up with
+ # appended " ." -- ditch that if present.
+ artifact="${artifact% .}"
+ echo "artifact=$artifact" >> $GITHUB_OUTPUT
- echo "installer_path=$installer_path" >> $GITHUB_OUTPUT
- echo "installer_name=$installer_name" >> $GITHUB_OUTPUT
-
- name: Upload installer
uses: actions/upload-artifact@v3
with:
- name: ${{ steps.build.outputs.installer_name }}
- path: ${{ steps.build.outputs.installer_path }}
+ name: "${{ steps.build.outputs.artifact }} installer"
+ # emitted by build.sh, possibly multiple lines
+ path: |
+ ${{ steps.build.outputs.installer }}
+
+ # The other upload of nontrivial size is the symbol file. Use a distinct
+ # artifact for that too.
+ - name: Upload symbol file
+ uses: actions/upload-artifact@v3
+ with:
+ name: "${{ steps.build.outputs.artifact }} symbols"
+ path: |
+ ${{ steps.build.outputs.symbolfile }}
+
+ - name: Upload metadata
+ uses: actions/upload-artifact@v3
+ with:
+ name: "${{ steps.build.outputs.artifact }} metadata"
+ # emitted by build.sh, possibly multiple lines
+ path: |
+ ${{ steps.build.outputs.metadata }}
diff --git a/build.sh b/build.sh
index 89609a9ffd..bd3e84d7bd 100755
--- a/build.sh
+++ b/build.sh
@@ -16,6 +16,8 @@
# * The special style in which python is invoked is intentional to permit
# use of a native python install on windows - which requires paths in DOS form
+cleanup="true"
+
retry_cmd()
{
max_attempts="$1"; shift
@@ -110,6 +112,31 @@ installer_CYGWIN()
fi
}
+[[ -n "$GITHUB_OUTPUT" ]] || fatal "Need to export GITHUB_OUTPUT"
+# The following is based on the Warning for GitHub multiline output strings:
+# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
+EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
+
+# Build up these arrays as we go
+installer=()
+metadata=()
+symbolfile=()
+# and dump them to GITHUB_OUTPUT when done
+cleanup="$cleanup ; arrayoutput installer ; arrayoutput metadata ; arrayoutput symbolfile"
+trap "$cleanup" EXIT
+
+arrayoutput()
+{
+ local outputname="$1"
+ # append "[*]" to the array name so array indirection works
+ local array="$1[*]"
+ local IFS='
+'
+ echo "$outputname<<$EOF
+${!array}
+$EOF" >> "$GITHUB_OUTPUT"
+}
+
pre_build()
{
local variant="$1"
@@ -146,12 +173,20 @@ pre_build()
fi
# don't spew credentials into build log
- bugsplat_sh="$build_secrets_checkout/bugsplat/bugsplat.sh"
set +x
- if [ -r "$bugsplat_sh" ]
- then # show that we're doing this, just not the contents
- echo source "$bugsplat_sh"
- source "$bugsplat_sh"
+ # expect these variables to be set in the environment from GitHub secrets
+ if [[ -z "$BUGSPLAT_USER" || -z "$BUGSPLAT_PASS" ]]
+ then
+ # older mechanism involving build-secrets repo -
+ # if build_secrets_checkout isn't set, report its name
+ bugsplat_sh="${build_secrets_checkout:-\$build_secrets_checkout}/bugsplat/bugsplat.sh"
+ if [ -r "$bugsplat_sh" ]
+ then # show that we're doing this, just not the contents
+ echo source "$bugsplat_sh"
+ source "$bugsplat_sh"
+ else
+ fatal "BUGSPLAT_USER or BUGSPLAT_PASS missing, and no $bugsplat_sh"
+ fi
fi
set -x
@@ -187,7 +222,8 @@ package_llphysicsextensions_tpv()
# capture the package file name for use in upload later...
PKGTMP=`mktemp -t pgktpv.XXXXXX`
- trap "rm $PKGTMP* 2>/dev/null" 0
+ cleanup="$cleanup ; rm $PKGTMP* 2>/dev/null"
+ trap "$cleanup" EXIT
"$autobuild" package --quiet --config-file "$tpvconfig" --results-file "$(native_path $PKGTMP)" || fatal "failed to package llphysicsextensions_tpv"
tpv_status=$?
if [ -r "${PKGTMP}" ]
@@ -313,12 +349,20 @@ begin_section "coding policy check"
# this far. Running coding policy checks on one platform *should* suffice...
if [[ "$arch" == "Darwin" ]]
then
- # install the git-hooks dependencies
- pip install -r "$(native_path "$git_hooks_checkout/requirements.txt")" || \
- fatal "pip install git-hooks failed"
- # validate the branch we're about to build
- python_cmd "$git_hooks_checkout/coding_policy_git.py" --all_files || \
- fatal "coding policy check failed"
+ git_hooks_reqs="$git_hooks_checkout/requirements.txt"
+ if [[ -r "$(shell_path "$git_hooks_reqs")" ]]
+ then
+ # install the git-hooks dependencies
+ pip install -r "$(native_path "$git_hooks_reqs")" || \
+ fatal "pip install git-hooks failed"
+ fi
+ git_hooks_script="$git_hooks_checkout/coding_policy_git.py"
+ if [[ -r "$(shell_path "$git_hooks_script")" ]]
+ then
+ # validate the branch we're about to build
+ python_cmd "$(native_path "$git_hooks_script")" --all_files || \
+ fatal "coding policy check failed"
+ fi
fi
end_section "coding policy check"
@@ -353,6 +397,7 @@ do
begin_section "Autobuild metadata"
python_cmd "$helpers/codeticket.py" addoutput "Autobuild Metadata" "$build_dir/autobuild-package.xml" --mimetype text/xml \
|| fatal "Upload of autobuild metadata failed"
+ metadata+=("$build_dir/autobuild-package.xml")
if [ "$arch" != "Linux" ]
then
record_dependencies_graph "$build_dir/autobuild-package.xml" # defined in buildscripts/hg/bin/build.sh
@@ -368,6 +413,7 @@ do
begin_section "Viewer Version"
python_cmd "$helpers/codeticket.py" addoutput "Viewer Version" "$(<"$build_dir/newview/viewer_version.txt")" --mimetype inline-text \
|| fatal "Upload of viewer version failed"
+ metadata+=("$build_dir/newview/viewer_version.txt")
end_section "Viewer Version"
fi
;;
@@ -376,12 +422,14 @@ do
then
record_event "Doxygen warnings generated; see doxygen_warnings.log"
python_cmd "$helpers/codeticket.py" addoutput "Doxygen Log" "$build_dir/doxygen_warnings.log" --mimetype text/plain ## TBD
+ metadata+=("$build_dir/doxygen_warnings.log")
fi
if [ -d "$build_dir/doxygen/html" ]
then
tar -c -f "$build_dir/viewer-doxygen.tar.bz2" --strip-components 3 "$build_dir/doxygen/html"
python_cmd "$helpers/codeticket.py" addoutput "Doxygen Tarball" "$build_dir/viewer-doxygen.tar.bz2" \
|| fatal "Upload of doxygen tarball failed"
+ metadata+=("$build_dir/viewer-doxygen.tar.bz2")
fi
;;
*)
@@ -497,6 +545,7 @@ then
retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput Installer "$package" \
|| fatal "Upload of installer failed"
wait_for_codeticket
+ installer+=("$package")
# Upload additional packages.
for package_id in $additional_packages
@@ -507,6 +556,7 @@ then
retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput "Installer $package_id" "$package" \
|| fatal "Upload of installer $package_id failed"
wait_for_codeticket
+ installer+=("$package")
else
record_failure "Failed to find additional package for '$package_id'."
fi
@@ -521,6 +571,7 @@ then
retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput "Symbolfile" "$VIEWER_SYMBOL_FILE" \
|| fatal "Upload of symbolfile failed"
wait_for_codeticket
+ symbolfile+=("$VIEWER_SYMBOL_FILE")
fi
# Upload the llphysicsextensions_tpv package, if one was produced
@@ -530,6 +581,8 @@ then
llphysicsextensions_package=$(cat $build_dir/llphysicsextensions_package)
retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput "Physics Extensions Package" "$llphysicsextensions_package" --private \
|| fatal "Upload of physics extensions package failed"
+ ## how to make private?
+ ## addoutput llphysics "$llphysicsextensions_package"
fi
fi
diff --git a/buildscripts_support_functions b/buildscripts_support_functions
new file mode 100644
index 0000000000..557d2f80fb
--- /dev/null
+++ b/buildscripts_support_functions
@@ -0,0 +1,60 @@
+# standalone functions from sling-buildscripts
+
+set_build_number_to_revision()
+{
+ record_event "buildNumber $revision"
+}
+
+record_event()
+{
+ echo "=== $@"
+}
+
+begin_section()
+{
+ record_event "START $*"
+ sections+=("$*")
+}
+
+end_section()
+{
+ # accommodate dumb Mac bash 3, which doesn't understand array[-1]
+ local last=$(( ${#sections[@]} - 1 ))
+ record_event "END ${*:-${sections[$last]}}"
+ unset "sections[$last]"
+}
+
+record_success()
+{
+ record_event "SUCCESS $*"
+}
+
+record_failure()
+{
+ record_event "FAILURE $*" >&2
+}
+
+fatal()
+{
+ record_failure "$@"
+ finalize false
+ exit 1
+}
+
+# redefined fail for backward compatibility
+alias fail=fatal
+
+pass()
+{
+ exit 0
+}
+
+export -f set_build_number_to_revision
+export -f record_event
+export -f begin_section
+export -f end_section
+export -f record_success
+export -f record_failure
+export -f fatal
+export -f pass
+export sections
diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp
index 0fc741d9e1..e9edd165df 100644
--- a/indra/llcommon/tests/llleap_test.cpp
+++ b/indra/llcommon/tests/llleap_test.cpp
@@ -17,7 +17,6 @@
// std headers
#include <functional>
// external library headers
-#include <boost/assign/list_of.hpp>
// other Linden headers
#include "../test/lltut.h"
#include "../test/namedtempfile.h"
@@ -29,10 +28,6 @@
#include "stringize.h"
#include "StringVec.h"
-using boost::assign::list_of;
-
-StringVec sv(const StringVec& listof) { return listof; }
-
#if defined(LL_WINDOWS)
#define sleep(secs) _sleep((secs) * 1000)
@@ -217,9 +212,9 @@ namespace tut
"time.sleep(1)\n");
LLLeapVector instances;
instances.push_back(LLLeap::create(get_test_name(),
- sv(list_of(PYTHON)(script.getName())))->getWeak());
+ StringVec{PYTHON, script.getName()})->getWeak());
instances.push_back(LLLeap::create(get_test_name(),
- sv(list_of(PYTHON)(script.getName())))->getWeak());
+ StringVec{PYTHON, script.getName()})->getWeak());
// In this case we're simply establishing that two LLLeap instances
// can coexist without throwing exceptions or bombing in any other
// way. Wait for them to terminate.
@@ -249,7 +244,7 @@ namespace tut
"print('Hello from Python!')\n");
CaptureLog log(LLError::LEVEL_WARN);
waitfor(LLLeap::create(get_test_name(),
- sv(list_of(PYTHON)(script.getName()))));
+ StringVec{PYTHON, script.getName()}));
ensure_contains("error log line",
log.messageWith("invalid protocol"), "Hello from Python!");
}
@@ -264,7 +259,7 @@ namespace tut
"sys.stdout.write('Hello from Python!')\n");
CaptureLog log(LLError::LEVEL_WARN);
waitfor(LLLeap::create(get_test_name(),
- sv(list_of(PYTHON)(script.getName()))));
+ StringVec{PYTHON, script.getName()}));
ensure_contains("error log line",
log.messageWith("Discarding"), "Hello from Python!");
}
@@ -278,7 +273,7 @@ namespace tut
"sys.stdout.write('5a2:something')\n");
CaptureLog log(LLError::LEVEL_WARN);
waitfor(LLLeap::create(get_test_name(),
- sv(list_of(PYTHON)(script.getName()))));
+ StringVec{PYTHON, script.getName()}));
ensure_contains("error log line",
log.messageWith("invalid protocol"), "5a2:");
}
@@ -390,7 +385,8 @@ namespace tut
"result = '' if resp == dict(pump=replypump(), data='ack')\\\n"
" else 'bad: ' + str(resp)\n"
"send(pump='" << result.getName() << "', data=result)\n";});
- waitfor(LLLeap::create(get_test_name(), sv(list_of(PYTHON)(script.getName()))));
+ waitfor(LLLeap::create(get_test_name(),
+ StringVec{PYTHON, script.getName()}));
result.ensure();
}
@@ -449,7 +445,7 @@ namespace tut
" result = 'expected reqid=%s in %s' % (i, resp)\n"
" break\n"
"send(pump='" << result.getName() << "', data=result)\n";});
- waitfor(LLLeap::create(get_test_name(), sv(list_of(PYTHON)(script.getName()))),
+ waitfor(LLLeap::create(get_test_name(), StringVec{PYTHON, script.getName()}),
300); // needs more realtime than most tests
result.ensure();
}
@@ -516,10 +512,7 @@ namespace tut
" (start, large[start:end], echoed[start:end]))\n"
"sys.exit(1)\n";});
waitfor(LLLeap::create(test_name,
- sv(list_of
- (PYTHON)
- (script.getName())
- (stringize(size)))),
+ StringVec{PYTHON, script.getName(), stringize(size)}),
180); // try a longer timeout
result.ensure();
}
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 4adb8d872a..c1cb2af7fe 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -151,8 +151,38 @@ struct PythonProcessLauncher
/// Launch Python script; verify that it launched
void launch()
{
- mPy = LLProcess::create(mParams);
- tut::ensure(STRINGIZE("Couldn't launch " << mDesc << " script"), bool(mPy));
+ try
+ {
+ mPy = LLProcess::create(mParams);
+ tut::ensure(STRINGIZE("Couldn't launch " << mDesc << " script"), bool(mPy));
+ }
+ catch (const tut::failure&)
+ {
+ // On Windows, if APR_LOG is set, our version of APR's
+ // apr_create_proc() logs to the specified file. If this test
+ // failed, try to report that log.
+ const char* APR_LOG = getenv("APR_LOG");
+ if (APR_LOG && *APR_LOG)
+ {
+ std::ifstream inf(APR_LOG);
+ if (! inf.is_open())
+ {
+ LL_WARNS() << "Couldn't open '" << APR_LOG << "'" << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "==============================" << LL_ENDL;
+ LL_WARNS() << "From '" << APR_LOG << "':" << LL_ENDL;
+ std::string line;
+ while (std::getline(inf, line))
+ {
+ LL_WARNS() << line << LL_ENDL;
+ }
+ LL_WARNS() << "==============================" << LL_ENDL;
+ }
+ }
+ throw;
+ }
}
/// Run Python script and wait for it to complete.
@@ -214,30 +244,26 @@ static std::string python_out(const std::string& desc, const CONTENT& script)
class NamedTempDir: public boost::noncopyable
{
public:
- // Use python() function to create a temp directory: I've found
- // nothing in either Boost.Filesystem or APR quite like Python's
- // tempfile.mkdtemp().
- // Special extra bonus: on Mac, mkdtemp() reports a pathname
- // starting with /var/folders/something, whereas that's really a
- // symlink to /private/var/folders/something. Have to use
- // realpath() to compare properly.
NamedTempDir():
- mPath(python_out("mkdtemp()",
- "from __future__ import with_statement\n"
- "import os.path, sys, tempfile\n"
- "with open(sys.argv[1], 'w') as f:\n"
- " f.write(os.path.normcase(os.path.normpath(os.path.realpath(tempfile.mkdtemp()))))\n"))
- {}
+ mPath(NamedTempFile::temp_path()),
+ mCreated(boost::filesystem::create_directories(mPath))
+ {
+ mPath = boost::filesystem::canonical(mPath);
+ }
~NamedTempDir()
{
- aprchk(apr_dir_remove(mPath.c_str(), gAPRPoolp));
+ if (mCreated)
+ {
+ boost::filesystem::remove_all(mPath);
+ }
}
- std::string getName() const { return mPath; }
+ std::string getName() const { return mPath.string(); }
private:
- std::string mPath;
+ boost::filesystem::path mPath;
+ bool mCreated;
};
/*****************************************************************************
@@ -565,7 +591,7 @@ namespace tut
" f.write(os.path.normcase(os.path.normpath(os.getcwd())))\n");
// Before running, call setWorkingDirectory()
py.mParams.cwd = tempdir.getName();
- ensure_equals("os.getcwd()", py.run_read(), tempdir.getName());
+ ensure_equals("os.getcwd()", py.run_read(), utf8str_tolower(tempdir.getName()));
}
template<> template<>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 8235e4466c..99ace834c2 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3552,7 +3552,7 @@ void LLAppViewer::writeSystemInfo()
gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::instance().getMajor();
gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::instance().getMinor();
gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::instance().getPatch();
- gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::instance().getBuild();
+ gDebugInfo["ClientInfo"]["BuildVersion"] = std::to_string(LLVersionInfo::instance().getBuild());
gDebugInfo["ClientInfo"]["AddressSize"] = LLVersionInfo::instance().getAddressSize();
gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
@@ -5669,7 +5669,7 @@ void LLAppViewer::handleLoginComplete()
gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::instance().getMajor();
gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::instance().getMinor();
gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::instance().getPatch();
- gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::instance().getBuild();
+ gDebugInfo["ClientInfo"]["BuildVersion"] = std::to_string(LLVersionInfo::instance().getBuild());
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if ( parcel && parcel->getMusicURL()[0])
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index b14fdbf38e..c61c176530 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -300,7 +300,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
setDefaultBtn(def_btn);
std::string channel = LLVersionInfo::instance().getChannel();
- std::string version = llformat("%s (%d)",
+ std::string version = llformat("%s (%ld)",
LLVersionInfo::instance().getShortVersion().c_str(),
LLVersionInfo::instance().getBuild());
@@ -894,7 +894,7 @@ void LLPanelLogin::loadLoginPage()
}
// Channel and Version
- params["version"] = llformat("%s (%d)",
+ params["version"] = llformat("%s (%ld)",
LLVersionInfo::instance().getShortVersion().c_str(),
LLVersionInfo::instance().getBuild());
params["channel"] = LLVersionInfo::instance().getChannel();
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index 34d3ed8bb1..d7cb12826f 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -133,7 +133,7 @@ void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, std::
LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
- std::string user_agent = llformat("%s %d.%d.%d (%d)",
+ std::string user_agent = llformat("%s %d.%d.%d (%ld)",
LLVersionInfo::instance().getChannel().c_str(),
LLVersionInfo::instance().getMajor(),
LLVersionInfo::instance().getMinor(),
@@ -177,7 +177,7 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s
LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
- std::string user_agent = llformat("%s %d.%d.%d (%d)",
+ std::string user_agent = llformat("%s %d.%d.%d (%ld)",
LLVersionInfo::instance().getChannel().c_str(),
LLVersionInfo::instance().getMajor(),
LLVersionInfo::instance().getMinor(),
diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp
index 376a7fce76..62bfa24e29 100644
--- a/indra/newview/llversioninfo.cpp
+++ b/indra/newview/llversioninfo.cpp
@@ -91,7 +91,7 @@ S32 LLVersionInfo::getPatch()
return LL_VIEWER_VERSION_PATCH;
}
-S32 LLVersionInfo::getBuild()
+S64 LLVersionInfo::getBuild()
{
return LL_VIEWER_VERSION_BUILD;
}
diff --git a/indra/newview/llversioninfo.h b/indra/newview/llversioninfo.h
index 02ff0c094a..122bd5c47a 100644
--- a/indra/newview/llversioninfo.h
+++ b/indra/newview/llversioninfo.h
@@ -61,7 +61,7 @@ public:
S32 getPatch();
/// return the build number as an integer
- S32 getBuild();
+ S64 getBuild();
/// return the full viewer version as a string like "2.0.0.200030"
std::string getVersion();
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index c4d873dd22..9afe332025 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -160,7 +160,7 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url,
substitution["VERSION_MAJOR"] = LLVersionInfo::instance().getMajor();
substitution["VERSION_MINOR"] = LLVersionInfo::instance().getMinor();
substitution["VERSION_PATCH"] = LLVersionInfo::instance().getPatch();
- substitution["VERSION_BUILD"] = LLVersionInfo::instance().getBuild();
+ substitution["VERSION_BUILD"] = std::to_string(LLVersionInfo::instance().getBuild());
substitution["CHANNEL"] = LLVersionInfo::instance().getChannel();
substitution["GRID"] = LLGridManager::getInstance()->getGridId();
substitution["GRID_LOWERCASE"] = utf8str_tolower(LLGridManager::getInstance()->getGridId());
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index 8d178dbbdc..b851b7ad5c 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -384,7 +384,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip, const
httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
- std::string user_agent = llformat("%s %d.%d.%d (%d)",
+ std::string user_agent = llformat("%s %d.%d.%d (%ld)",
LLVersionInfo::instance().getChannel().c_str(),
LLVersionInfo::instance().getMajor(),
LLVersionInfo::instance().getMinor(),
diff --git a/indra/test/namedtempfile.h b/indra/test/namedtempfile.h
index c215c50f3f..525a35000d 100644
--- a/indra/test/namedtempfile.h
+++ b/indra/test/namedtempfile.h
@@ -65,8 +65,7 @@ public:
boost::filesystem::remove(mPath);
}
- // On Windows, path::native() returns a wstring
- std::string getName() const { return ll_convert<std::string>(mPath.native()); }
+ std::string getName() const { return mPath.string(); }
void peep()
{
@@ -78,21 +77,33 @@ public:
std::cout << "---\n";
}
+ static boost::filesystem::path temp_path(const std::string_view& pfx="",
+ const std::string_view& sfx="")
+ {
+ // This variable is set by GitHub actions and is the recommended place
+ // to put temp files belonging to an actions job.
+ const char* RUNNER_TEMP = getenv("RUNNER_TEMP");
+ boost::filesystem::path tempdir{
+ // if RUNNER_TEMP is set and not empty
+ (RUNNER_TEMP && *RUNNER_TEMP)?
+ boost::filesystem::path(RUNNER_TEMP) : // use RUNNER_TEMP if available
+ boost::filesystem::temp_directory_path()}; // else canonical temp dir
+ boost::filesystem::path tempname{
+ // use filename template recommended by unique_path() doc, but
+ // with underscores instead of hyphens: some use cases involve
+ // temporary Python scripts
+ tempdir / stringize(pfx, "%%%%_%%%%_%%%%_%%%%", sfx) };
+ return boost::filesystem::unique_path(tempname);
+ }
+
protected:
void createFile(const std::string_view& pfx,
const Streamer& func,
const std::string_view& sfx)
{
// Create file in a temporary place.
- boost::filesystem::path tempname{
- boost::filesystem::temp_directory_path() /
- // unique_path() recommended template, but with underscores
- // instead of hyphens: some use cases involve temporary Python
- // scripts
- stringize(pfx, "%%%%_%%%%_%%%%_%%%%", sfx) };
- mPath = boost::filesystem::unique_path(tempname);
+ mPath = temp_path(pfx, sfx);
boost::filesystem::ofstream out{ mPath };
-
// Write desired content.
func(out);
}