Skip to content

AUpdater#

Updater class.

Header:#include <AUI/Updater/AUpdater.h>
CMake:aui_link(my_target PUBLIC aui::updater)

Detailed Description#

Experimental Feature

This API is experimental. Experimental APIs are likely to contain bugs, might be changed or removed in the future.

AUpdater follows a strategy pattern, i.e., you are excepted to call its functions, but the behavior and conditions are up to you.

Refer to aui::updater for the update process overview.

Public Types#

InstallCmdline#


struct AUpdater::InstallCmdline

Data required to launch installation child process.

Field Description
APath installerExecutable Absolute path to installer executable. By default, installerExecutable is a copy of your application executable. The installation process is triggered via installerArguments.
AVector<AString> installerArguments Arguments passed to installer.

GetInstallationDirectoryContext#


struct AUpdater::GetInstallationDirectoryContext

Context for AUpdater::getInstallationDirectory

Field Description
APath selfProcessExePath Self process exe. Typically AProcess::self()->getPathToExecutable().
APath updaterDir Updater dir. Typically parent of selfProcessExePath.
APath originExe The path to executable who invoked the installation process. Typically full path to the original exe to replace.

StatusIdle#


struct AUpdater::StatusIdle

Idling.

Empty structure.

StatusCheckingForUpdates#


struct AUpdater::StatusCheckingForUpdates

Checking for updates.

Empty structure.

StatusDownloading#


struct AUpdater::StatusDownloading

Downloading state.

Empty structure.

StatusNotAvailable#


struct AUpdater::StatusNotAvailable

AUpdater::isAvailable() evaluated to false.

Empty structure.

StatusWaitingForApplyAndRestart#


struct AUpdater::StatusWaitingForApplyAndRestart

Waiting to applyUpdateAndRestart call state.

Field Description
InstallCmdline installCmdline

Public fields and Signals#


mAsync#

AAsyncHolder mAsync

Holder for async operations.


status#

AProperty<std::any> status

State of the updater.

Status of the AUpdater to observe from outside, i.e., by UI.

status is updated in UI thread only.

status is designed in such a way the user can use their own custom status types or any of predefined ones:

These statuses might be set by AUpdater itself.

Typical observer of status is a UI projection displaying its value. You can even display controls in it:

CustomLayout {} & mUpdater->status.readProjected([&updater = mUpdater](const std::any& status) -> _<AView> {
    if (std::any_cast<AUpdater::StatusIdle>(&status)) {
        return _new<AButton>("Check for updates").connect(&AView::clicked, AUI_SLOT(updater)::checkForUpdates);
    }
    if (std::any_cast<AUpdater::StatusCheckingForUpdates>(&status)) {
        return Label { "Checking for updates..." };
    }
    if (auto downloading = std::any_cast<AUpdater::StatusDownloading>(&status)) {
        return Vertical {
            Label { "Downloading..." },
            _new<AProgressBar>() & downloading->progress,
        };
    }
    if (std::any_cast<AUpdater::StatusWaitingForApplyAndRestart>(&status)) {
        return _new<AButton>("Apply update and restart")
            .connect(&AView::clicked, AUI_SLOT(updater)::applyUpdateAndRestart);
    }
    return nullptr;
}),

Public Methods#

applyUpdateAndRestart#


virtual void AUpdater::applyUpdateAndRestart()

Deploy the downloaded update.

Basically about replacing files (no network operations will be performed).

Requires AUpdater::status = StatusWaitingForApplyAndRestart, otherwise has no effect.

Terminates current process with std::exit(0)

Debugging update deployment#

You can locate update deployment logs by locating deployment process id (pid). The PID is printed by this function:

[06:49:33][UI thread][AUpdater][INFO]: applyUpdateAndRestart: started process pid=3708325, exe=...

Log files location are printed in the beginning of every AUI-based programs (if they use ALogger):

[06:49:14][UI thread][Logger][INFO]: Log file: /tmp/aui.3707546.log

You can now locate the log file by using subprocess' PID printed earlier:

cat /tmp/aui.3708325.log
[06:49:33][UI thread][Logger][INFO]: Log file: /tmp/aui.3708325.log
[06:49:33][UI thread][AUpdater][INFO]: --aui-updater-wait-for-process: 3707546 exited with 0
[06:49:33][UI thread][AUpdater][INFO]: deploying update: /tmp/__aui_update_example_app/download -> /home/...
[06:49:33][UI thread][AUpdater][ERR]: Can't deploy update, trying to launch original: ...
 - at 0x5555558f3aae aui_entry(AStringVector const&)(main.cpp:9)
 - at 0x5555556b0028 aui_main(int, char**, int (*)(AStringVector const&))(OSDesktop.cpp:160)
 - at 0x7ffff7261248(?:0)
 - at 0x7ffff726130b(?:0)
 - at 0x555555654195(?:0)
Caused by: (AIOException) AFileOutputStream: could not open /home/...: Text file busy
 - at 0x5555556c0443 aui::impl::lastErrorToException(AString)(ErrorToExceptionImpl.cpp:21)
 - at 0x55555568ec97 AFileOutputStream::open(bool)(AFileOutputStream.cpp:67)
 - at 0x55555568ed44 AFileOutputStream::AFileOutputStream(AString, bool)(AFileOutputStream.cpp:24)
 - at 0x5555556964a2 APath::copy(APath const&, APath const&)(APath.cpp:291)
 - at 0x555555641585 AUpdater::deployUpdate(APath const&, APath const&)(AUpdater.cpp:267)
 - at 0x5555558fb2ff AUpdater::handleStartup(AStringVector const&)(AUpdater.cpp:76)
 - at 0x5555558f3aae aui_entry(AStringVector const&)(main.cpp:9)
 - at 0x5555556b0028 aui_main(int, char**, int (*)(AStringVector const&))(OSDesktop.cpp:160)
 - at 0x7ffff7261248(?:0)
 - at 0x7ffff726130b(?:0)
 - at 0x555555654195(?:0)

checkForUpdates#


void AUpdater::checkForUpdates()

Sets status to AUpdater::StatusCheckingForUpdates and calls AUpdater::checkForUpdatesImpl, implemented by user.

Requires AUpdater::status = StatusIdle, otherwise has no effect.

checkForUpdatesImpl#


virtual AFuture<void> AUpdater::checkForUpdatesImpl()

Check for updates user's implementation.

cleanupUnpackedUpdateDirBeforeDownloading#


virtual void AUpdater::cleanupUnpackedUpdateDirBeforeDownloading()

called by AUpdater::downloadUpdate before downloading update to cleanup AUpdater::getUnpackedUpdateDir() dir.

deployUpdate#


virtual void AUpdater::deployUpdate(const APath& source, const APath& destination)

Deploys update by recursively copying (moving) files from source dir to destination dir.

Called in newly downloaded executable.

downloadAndUnpack#


void AUpdater::downloadAndUnpack(AString downloadUrl, const APath& unpackedUpdateDir)

Typical download and unpack implementation.

Called by downloadUpdateImpl. Updates AUpdate::status progress.

downloadUpdate#


void AUpdater::downloadUpdate()

Sets status to AUpdater::StatusDownloading and calls AUpdater::downloadUpdateImpl, implemented by user.

An implementation might expect to checkForUpdates to be called first.

downloadUpdateImpl#


virtual AFuture<void> AUpdater::downloadUpdateImpl(const APath& unpackedUpdateDir)

Performs update delivery to the specified directory.

Arguments
unpackedUpdateDir
location to unpack an update to.

Typically implemented as download to temporary dir and unpacking the archive to the specified unpackedUpdateDir.

Unpack your application files to unpackedUpdateDir. AUpdater is responsible for cleaning this dir in the future.

getInstallationDirectory#


virtual APath AUpdater::getInstallationDirectory(const GetInstallationDirectoryContext& context)

Retrieves installation directory based on given context.

Default implementation guesses installation directory based on

getModuleName#


virtual AString AUpdater::getModuleName()

Returns a module name of your (your_app_name or your_app_name.exe, without a leading path).

Default implementation determines module name using AProcess::self().

The module name is used to construct temporary directory and locate an executable in a downloaded portable.

getTempWorkDir#


virtual APath AUpdater::getTempWorkDir()

Working directory for AUpdater. By default, points to some path in TEMP.

getUnpackedUpdateDir#


virtual APath AUpdater::getUnpackedUpdateDir()

The path where the update is unpacked to.

The dir persists between different launches.

handlePostUpdateCleanup#


virtual void AUpdater::handlePostUpdateCleanup()

Performs post update cleanup routines.

Default implementation deletes AUpdater::getUnpackedUpdateDir() dir.

handleStartup#


virtual void AUpdater::handleStartup(const AStringVector& applicationArguments)

Performs a pre-application AUpdater routine.

Arguments
applicationArguments
arguments to your program.

The arguments starting with --aui-updater are should be ignored by your application.

Performs autoupdate-specific routines on startup of your application. In best scenario, this function should be called by your application as early as possible.

This function might terminate current process with std::exit(0), in case of performing autoupdate routines.

This function will attempt to restore InstallCmdline state (StatusWaitingForApplyAndRestart) via AUpdater::loadInstallCmdline. If the latter succeeds, AUpdate::triggerUpdateOnStartup is called to perform on-startup update.

This function handles following arguments to your application: - --aui-updater-origin - - --aui-updater-wait-for-process - maps to AUpdater::handleWaitForProcess() that instructs AUpdater to wait the specified process to finish before processing next argument(s). - --aui-updater-cleanup - maps to AUpdater::handlePostUpdateCleanup() and returns control flow to normal execution of your application (last updating step) - --aui-updater-failed - reports last error occurred while update deployment. See AUpdater::getLastDeploymentError().

Refer to aui::updater for update process overview.

handleWaitForProcess#


virtual void AUpdater::handleWaitForProcess(uint32_t pid)

Handles --aui-updater-wait-for-process.

injectWaitForMyPid#


virtual AVector<AString> AUpdater::injectWaitForMyPid(AVector<AString> args)

Injects --aui-updater-wait-for-process=THIS_PROCESS_PID as the first argument.

isAvailable#


static bool AUpdater::isAvailable()

Checks that updater functionality is available.

For cases when AUpdater is available see aui::updater

loadInstallCmdline#


virtual AOptional<InstallCmdline> AUpdater::loadInstallCmdline()

Restores install command line state, if any.

AUpdater::handleStartup will try to restore the state via loadInstallCmdline. If InstallCmdline is successfully restored, AUpdater immediately triggers update routine with triggerUpdateOnStartup which exits the application.

The implementation must ensure that subsequent startups would not trigger on-startup update to avoid endless loops in case of failure, i.e, by deleting a file.

makeDefaultInstallationCmdline#


InstallCmdline AUpdater::makeDefaultInstallationCmdline()

Constructs InstallCmdline with default arguments.

By default, installerExecutable is a copy of your application executable. The installation process is triggered via special arguments in installerArguments.

reportDownloadedPercentage#


void AUpdater::reportDownloadedPercentage(aui::float_within_0_1 progress)

Being called by downloadUpdateImpl, reports download percentage to status.

Requires AUpdater::status = StatusDownloading, otherwise has no effect. Updates the value in UI thread.

reportReadyToApplyAndRestart#


void AUpdater::reportReadyToApplyAndRestart(InstallCmdline cmdline)

Dumps InstallCmdline to temporary download directory, indicating that an update is ready to install. Updates status accordingly.

saveCmdline#


virtual void AUpdater::saveCmdline(const InstallCmdline& cmdline)

Saves install command line to restore state when application is restarted.

triggerUpdateOnStartup#


virtual void AUpdater::triggerUpdateOnStartup()

Triggers update routine.

The function is called by AUpdater::handleStartup. If triggerUpdateOnStartup succeeds, it should terminate execution of the current process.

Requires AUpdater::status = StatusWaitingForApplyAndRestart.

If you'd like to disable applying downloaded update on startup, stub this function.