summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt24
-rw-r--r--indra/newview/installers/windows/installer_template.nsi1
-rw-r--r--indra/newview/llappviewer.cpp4
-rw-r--r--indra/newview/llenvironment.h2
-rw-r--r--indra/newview/llimview.cpp2
-rw-r--r--indra/newview/lllogchat.cpp2
-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
-rwxr-xr-xindra/newview/viewer_manifest.py215
13 files changed, 186 insertions, 80 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index c37d03221c..2c45e0713c 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -2151,20 +2151,6 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
)
add_custom_target(dsym_generate DEPENDS "${VIEWER_APP_DSYM}")
add_dependencies(dsym_generate ${VIEWER_BINARY_NAME})
- add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}"
- # See above comments about "tar ...j"
- COMMAND "tar"
- ARGS
- "cjf"
- "${VIEWER_SYMBOL_FILE}"
- "-C"
- "${VIEWER_APP_DSYM}/.."
- "${product}.dSYM"
- DEPENDS "${VIEWER_APP_DSYM}"
- COMMENT "Packing dSYM into ${VIEWER_SYMBOL_FILE}"
- )
- add_custom_target(dsym_tarball DEPENDS "${VIEWER_SYMBOL_FILE}")
- add_dependencies(dsym_tarball dsym_generate)
add_custom_command(OUTPUT "${VIEWER_APP_XCARCHIVE}"
COMMAND "zip"
ARGS
@@ -2182,24 +2168,22 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/dsym.stamp"
COMMAND rm -rf "${VIEWER_APP_DSYM}"
COMMAND touch "${CMAKE_CURRENT_BINARY_DIR}/dsym.stamp"
- DEPENDS "${VIEWER_SYMBOL_FILE}" "${VIEWER_APP_XCARCHIVE}"
+ DEPENDS "${VIEWER_APP_XCARCHIVE}"
COMMENT "Cleaning up dSYM"
)
add_custom_target(generate_symbols DEPENDS
"${VIEWER_APP_DSYM}"
- "${VIEWER_SYMBOL_FILE}"
"${VIEWER_APP_XCARCHIVE}"
"${CMAKE_CURRENT_BINARY_DIR}/dsym.stamp"
)
- add_dependencies(generate_symbols dsym_tarball dsym_xcarchive)
+ add_dependencies(generate_symbols dsym_xcarchive)
endif (DARWIN)
if (LINUX)
# TBD
endif (LINUX)
- endif (USE_BUGSPLAT)
- # for both Bugsplat and Breakpad
- add_dependencies(llpackage generate_symbols)
+ add_dependencies(llpackage generate_symbols)
+ endif (USE_BUGSPLAT)
endif ()
if (LL_TESTS)
diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi
index ed37f541c8..962d6c060c 100644
--- a/indra/newview/installers/windows/installer_template.nsi
+++ b/indra/newview/installers/windows/installer_template.nsi
@@ -26,7 +26,6 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Compiler flags
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-Unicode true
SetOverwrite on # Overwrite files
SetCompress auto # Compress if saves space
SetCompressor /solid lzma # Compress whole installer as one block
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 3db5fe9260..dec849afa1 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3557,7 +3557,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();
@@ -5515,7 +5515,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/llenvironment.h b/indra/newview/llenvironment.h
index 64fd170e43..1c8a68ae02 100644
--- a/indra/newview/llenvironment.h
+++ b/indra/newview/llenvironment.h
@@ -42,6 +42,8 @@
#include <boost/signals2.hpp>
+#include <array>
+
//-------------------------------------------------------------------------
class LLViewerCamera;
class LLParcel;
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 6880cf2171..61a01d7418 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -72,6 +72,8 @@
#include "llcorehttputil.h"
#include "lluiusage.h"
+#include <array>
+
const static std::string ADHOC_NAME_SUFFIX(" Conference");
const static std::string NEARBY_P2P_BY_OTHER("nearby_P2P_by_other");
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index ba82ff0b0f..8c03292361 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -41,7 +41,7 @@
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/replace.hpp>
-#include <boost/regex/v4/match_results.hpp>
+#include <boost/regex.hpp>
#include <boost/foreach.hpp>
#if LL_MSVC
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 49756a4e09..ea936ab024 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 c37c955e8d..1e21c3fa05 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -160,7 +160,7 @@ void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, LLSD
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(),
@@ -215,7 +215,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/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 3a7c7d7f46..5039f3db83 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -35,13 +35,13 @@ import os.path
import plistlib
import random
import re
+import secrets
import shutil
-import stat
import subprocess
import sys
import tarfile
+import tempfile
import time
-import zipfile
viewer_dir = os.path.dirname(__file__)
# Add indra/lib/python to our path so we don't have to muck with PYTHONPATH.
@@ -410,6 +410,23 @@ class ViewerManifest(LLManifest):
return os.path.relpath(abspath(path), abspath(base))
+ def set_github_output_path(self, variable, path):
+ self.set_github_output(variable,
+ os.path.normpath(os.path.join(self.get_dst_prefix(), path)))
+
+ def set_github_output(self, variable, *values):
+ GITHUB_OUTPUT = os.getenv('GITHUB_OUTPUT')
+ if GITHUB_OUTPUT and values:
+ with open(GITHUB_OUTPUT, 'a') as outf:
+ if len(values) == 1:
+ print('='.join((variable, values[0])), file=outf)
+ else:
+ delim = secrets.token_hex(8)
+ print('<<'.join((variable, delim)), file=outf)
+ for value in values:
+ print(value, file=outf)
+ print(delim, file=outf)
+
class WindowsManifest(ViewerManifest):
# We want the platform, per se, for every Windows build to be 'win'. The
@@ -484,6 +501,30 @@ class WindowsManifest(ViewerManifest):
if self.is_packaging_viewer():
# Find secondlife-bin.exe in the 'configuration' dir, then rename it to the result of final_exe.
self.path(src='%s/secondlife-bin.exe' % self.args['configuration'], dst=self.final_exe())
+ # Emit the whole app image as one of the GitHub step outputs. We
+ # want the whole app -- but NOT the extraneous build products that
+ # get tossed into the same directory, such as the installer and
+ # the symbols tarball, so add exclusions. When we feed
+ # upload-artifact multiple absolute pathnames, even just for
+ # exclusion, it ends up creating several extraneous directory
+ # levels within the artifact -- so try using only relative paths.
+ # One problem: as of right now, our current directory os.getcwd()
+ # is not the same as the initial working directory for this job
+ # step, meaning paths relative to our os.getcwd() won't work for
+ # the subsequent upload-artifact step. We're a couple directory
+ # levels down. Try adjusting for those when specifying the base
+ # for self.relpath().
+ appbase = self.relpath(
+ self.get_dst_prefix(),
+ base=os.path.join(os.getcwd(), os.pardir, os.pardir))
+ self.set_github_output('viewer_app', appbase,
+ # except for this stuff
+ *(('!' + os.path.join(appbase, pattern))
+ for pattern in (
+ 'secondlife-bin.*',
+ '*_Setup.exe',
+ '*.bat',
+ '*.tar.bz2')))
with self.prefix(src=os.path.join(pkgdir, "VMP")):
# include the compiled launcher scripts so that it gets included in the file_list
@@ -679,46 +720,46 @@ class WindowsManifest(ViewerManifest):
self.package_file = "copied_deps"
def nsi_file_commands(self, install=True):
- def wpath(path):
- if path.endswith('/') or path.endswith(os.path.sep):
- path = path[:-1]
- path = path.replace('/', '\\')
- return path
-
- result = ""
+ def INSTDIR(path):
+ # Note that '$INSTDIR' is purely textual here: we write
+ # exactly that into the .nsi file for NSIS to interpret.
+ # Pass the result through normpath() to handle the case in which
+ # path is the empty string. On Windows, that produces "$INSTDIR\".
+ # Unfortunately, if that's the last item on a line, NSIS takes
+ # that as line continuation and misinterprets the following line.
+ # Ensure we don't emit a trailing backslash.
+ return os.path.normpath(os.path.join('$INSTDIR', path))
+
+ result = []
dest_files = [pair[1] for pair in self.file_list if pair[0] and os.path.isfile(pair[1])]
# sort deepest hierarchy first
dest_files.sort(key=lambda f: (f.count(os.path.sep), f), reverse=True)
out_path = None
for pkg_file in dest_files:
- rel_file = os.path.normpath(pkg_file.replace(self.get_dst_prefix()+os.path.sep,''))
- installed_dir = wpath(os.path.join('$INSTDIR', os.path.dirname(rel_file)))
- pkg_file = wpath(os.path.normpath(pkg_file))
- if installed_dir != out_path:
- if install:
- out_path = installed_dir
- result += 'SetOutPath ' + out_path + '\n'
+ pkg_file = os.path.normpath(pkg_file)
+ rel_file = self.relpath(pkg_file)
+ installed_dir = INSTDIR(os.path.dirname(rel_file))
+ if install and installed_dir != out_path:
+ out_path = installed_dir
+ # emit SetOutPath every time it changes
+ result.append('SetOutPath ' + out_path)
if install:
- result += 'File ' + pkg_file + '\n'
+ result.append('File ' + rel_file)
else:
- result += 'Delete ' + wpath(os.path.join('$INSTDIR', rel_file)) + '\n'
+ result.append('Delete ' + INSTDIR(rel_file))
# at the end of a delete, just rmdir all the directories
if not install:
- deleted_file_dirs = [os.path.dirname(pair[1].replace(self.get_dst_prefix()+os.path.sep,'')) for pair in self.file_list]
- # find all ancestors so that we don't skip any dirs that happened to have no non-dir children
- deleted_dirs = []
- for d in deleted_file_dirs:
- deleted_dirs.extend(path_ancestors(d))
+ deleted_file_dirs = [os.path.dirname(self.relpath(f)) for f in dest_files]
+ # find all ancestors so that we don't skip any dirs that happened
+ # to have no non-dir children
+ deleted_dirs = set(itertools.chain.from_iterable(path_ancestors(d)
+ for d in deleted_file_dirs))
# sort deepest hierarchy first
- deleted_dirs.sort(key=lambda f: (f.count(os.path.sep), f), reverse=True)
- prev = None
- for d in deleted_dirs:
- if d != prev: # skip duplicates
- result += 'RMDir ' + wpath(os.path.join('$INSTDIR', os.path.normpath(d))) + '\n'
- prev = d
+ for d in sorted(deleted_dirs, key=lambda f: (f.count(os.path.sep), f), reverse=True):
+ result.append('RMDir ' + INSTDIR(d))
- return result
+ return '\n'.join(result)
def package_finish(self):
# a standard map of strings for replacing in the templates
@@ -766,12 +807,23 @@ class WindowsManifest(ViewerManifest):
engage_registry="SetRegView 32"
program_files=""
+ # Dump the installers/windows directory into the raw app image tree
+ # because NSIS needs those files. But don't use path() because we
+ # don't want them installed with the viewer - they're only for use by
+ # the installer itself.
+ shutil.copytree(os.path.join(self.get_src_prefix(), 'installers', 'windows'),
+ os.path.join(self.get_dst_prefix(), 'installers', 'windows'),
+ dirs_exist_ok=True)
+
tempfile = "secondlife_setup_tmp.nsi"
# the following replaces strings in the nsi template
# it also does python-style % substitution
self.replace_in("installers/windows/installer_template.nsi", tempfile, {
"%%VERSION%%":version_vars,
- "%%SOURCE%%":self.get_src_prefix(),
+ # The template references "%%SOURCE%%\installers\windows\...".
+ # Now that we've copied that directory into the app image
+ # tree, we can just replace %%SOURCE%% with '.'.
+ "%%SOURCE%%":'.',
"%%INST_VARS%%":inst_vars_template % substitution_strings,
"%%INSTALL_FILES%%":self.nsi_file_commands(True),
"%%PROGRAMFILES%%":program_files,
@@ -791,14 +843,30 @@ class WindowsManifest(ViewerManifest):
# Check two paths, one for Program Files, and one for Program Files (x86).
# Yay 64bit windows.
nsis_path = "makensis.exe"
- for program_files in '${programfiles}', '${programfiles(x86)}':
- for nesis_path in 'NSIS', 'NSIS\\Unicode':
- possible_path = os.path.expandvars(f"{program_files}\\{nesis_path}\\makensis.exe")
- if os.path.exists(possible_path):
- nsis_path = possible_path
- break
-
- self.run_command([possible_path, '/V2', self.dst_path_of(tempfile)])
+ try:
+ for program_files in os.getenv('programfiles'), os.getenv('programfiles(x86)'):
+ if program_files:
+ for subpath in 'NSIS', r'NSIS\Unicode':
+ possible_path = os.path.join(program_files, subpath, nsis_path)
+ if os.path.isfile(possible_path):
+ nsis_path = possible_path
+ # don't just break: we need to exit multiple
+ # levels of 'for' loop
+ raise StopIteration()
+ except StopIteration:
+ pass
+
+ # Because we've written relative pathnames into tempfile, run nsis
+ # with their base directory as current.
+ try:
+ self.run_command([nsis_path, '/V2', tempfile], cwd=self.get_dst_prefix())
+ except ManifestError as err:
+ print(f' {tempfile} '.center(72, '='))
+ with open(self.dst_path_of(tempfile)) as nsi:
+ for line in nsi:
+ print(line, end='') # already includes '\n'
+ print(72 * '=')
+ raise
self.sign(installer_file)
self.created_path(self.dst_path_of(installer_file))
@@ -844,8 +912,32 @@ class DarwinManifest(ViewerManifest):
return bool(set(["package", "unpacked"]).intersection(self.args['actions']))
def construct(self):
- # copy over the build result (this is a no-op if run within the xcode script)
- self.path(os.path.join(self.args['configuration'], self.channel()+".app"), dst="")
+ # copy over the build result (this is a no-op if run within the xcode
+ # script)
+ appname = self.channel() + ".app"
+ self.path(os.path.join(self.args['configuration'], appname), dst="")
+ RUNNER_TEMP = os.getenv('RUNNER_TEMP')
+ # When running as a GitHub Action job, RUNNER_TEMP is the recommended
+ # temp directory. If we're not running on GitHub, don't create this
+ # temp directory or this tarball: we don't clean them up, trusting
+ # that the runner is itself transient. On a dev machine, that would
+ # result in temp-directory clutter.
+ if RUNNER_TEMP:
+ # Per GitHub's actions/upload-artifact documentation
+ # https://github.com/actions/upload-artifact#maintaining-file-permissions-and-case-sensitive-files
+ # we must package the app bundle with tar before posting as an
+ # artifact. Posting individual files follows symlinks, which
+ # causes problems, especially with frameworks: a framework's top
+ # level must contain symlinks into its Versions/Current, which
+ # must itself be a symlink to some specific Versions subdir.
+ tarpath = os.path.join(RUNNER_TEMP, "viewer.tar.bz2")
+ print(f'Creating {tarpath} from {self.get_dst_prefix()}')
+ with tarfile.open(tarpath, mode="w:bz2") as tarball:
+ # store in the tarball as just 'Second Life Mumble.app'
+ # instead of 'Users/someone/.../newview/Release/Second...'
+ tarball.add(self.get_dst_prefix(),
+ arcname=os.path.basename(self.get_dst_prefix()))
+ self.set_github_output_path('viewer_app', tarpath)
pkgdir = os.path.join(self.args['build'], os.pardir, 'packages')
relpkgdir = os.path.join(pkgdir, "lib", "release")
@@ -898,7 +990,8 @@ class DarwinManifest(ViewerManifest):
# work, we need the build to noisily fail!
oldpath = subprocess.check_output(
['objdump', '--macho', '--dylib-id', '--non-verbose',
- os.path.join(relpkgdir, "BugsplatMac.framework", "BugsplatMac")]
+ os.path.join(relpkgdir, "BugsplatMac.framework", "BugsplatMac")],
+ text=True
).splitlines()[-1] # take the last line of output
self.run_command(
['install_name_tool', '-change', oldpath,
@@ -1174,6 +1267,7 @@ class DarwinManifest(ViewerManifest):
volname=CHANNEL_VENDOR_BASE+" Installer" # DO NOT CHANGE without understanding comment above
imagename = self.installer_base_name()
+ self.set_github_output('imagename', imagename)
sparsename = imagename + ".sparseimage"
finalname = imagename + ".dmg"
@@ -1193,7 +1287,7 @@ class DarwinManifest(ViewerManifest):
try:
devfile = re.search("/dev/disk([0-9]+)[^s]", hdi_output).group(0).strip()
- volpath = re.search('HFS\s+(.+)', hdi_output).group(1).strip()
+ volpath = re.search(r'HFS\s+(.+)', hdi_output).group(1).strip()
# Copy everything in to the mounted .dmg
@@ -1286,6 +1380,7 @@ class DarwinManifest(ViewerManifest):
'Keychains', 'viewer.keychain')
self.run_command(['security', 'unlock-keychain',
'-p', keychain_pwd, viewer_keychain])
+ sign_retries=3
sign_retry_wait=15
resources = app_in_dmg + "/Contents/Resources/"
plain_sign = glob.glob(resources + "llplugin/*.dylib")
@@ -1294,9 +1389,10 @@ class DarwinManifest(ViewerManifest):
resources + "SLPlugin.app/Contents/MacOS/SLPlugin",
app_in_dmg,
]
- for attempt in range(3):
+ for attempt in range(sign_retries):
if attempt: # second or subsequent iteration
- print("codesign failed, waiting {:d} seconds before retrying".format(sign_retry_wait),
+ print(f"codesign attempt {attempt+1} failed, "
+ f"waiting {sign_retry_wait:d} seconds before retrying",
file=sys.stderr)
time.sleep(sign_retry_wait)
sign_retry_wait*=2
@@ -1327,14 +1423,37 @@ class DarwinManifest(ViewerManifest):
# 'err' goes out of scope
sign_failed = err
else:
- print("Maximum codesign attempts exceeded; giving up", file=sys.stderr)
+ print(f"{sign_retries} codesign attempts failed; giving up",
+ file=sys.stderr)
raise sign_failed
self.run_command(['spctl', '-a', '-texec', '-vvvv', app_in_dmg])
- self.run_command([self.src_path_of("installers/darwin/apple-notarize.sh"), app_in_dmg])
+ self.run_command([self.src_path_of("installers/darwin/apple-notarize.sh"),
+ app_in_dmg])
finally:
# Unmount the image even if exceptions from any of the above
- self.run_command(['hdiutil', 'detach', '-force', devfile])
+ detach_retries = 3
+ detach_retry_wait = 2
+ # Empirically, on GitHub we've hit errors like:
+ # hdiutil: couldn't eject "disk10" - Resource busy
+ for attempt in range(detach_retries):
+ if attempt: # second or subsequent iteration
+ print(f'detach failed, waiting {detach_retry_wait} seconds before retrying',
+ file=sys.stderr)
+ # Try waiting a bit to see if that improves reliability.
+ time.sleep(detach_retry_wait)
+ detach_retry_wait *= 2
+
+ try:
+ self.run_command(['hdiutil', 'detach', '-force', devfile])
+ # if no exception, the detach worked
+ break
+ except ManifestError as err:
+ detach_failed = err
+ else:
+ print(f'{detach_retries} detach attempts failed', file=sys.stderr)
+ ## can we carry on anyway??
+ ## raise detach_failed
print("Converting temp disk image to final disk image")
self.run_command(['hdiutil', 'convert', sparsename, '-format', 'UDZO',