Unvanquished / updater

QML based updater to install, update and launch the Unvanquished game.
https://unvanquished.net/download
16 stars 7 forks source link

Store the updatable updater as any asset, the downloaded one just being a chainloader #50

Closed illwieckz closed 3 years ago

illwieckz commented 4 years ago

Original comment from https://github.com/Unvanquished/updater/issues/49#issuecomment-527712787

For the next sentences I'll assume Linux (we would adapt for other OS):

Basically what I think is that the updater would install itself as ~/.local/share/unvanquished/base/updater at first launch and then run it and close the parent, and of course that path would be the updater to update in priority, and every time the original updater is started, whatever it is stored, it would start the one in ~/.local/share/unvanquished/base before doing anything else. Autogenerated shortcuts would point to the updater in that path, not the randomly downloaded one.

We may also try to replace the binary that is stored in the wild, but even if we fail to, that would not be a problem, starting an old updater will load the newer one even before trying to update.

That would fix the started-from-zip issue (#49) at the same time.

illwieckz commented 4 years ago

Note that I'm not very happy with the Windows' updater asking for privilege elevation at startup because it's default installation directory is in %ProgramFiles%. It's not really compatible with the idea of an « updater as game launcher », not because of %ProgramFiles%, but because of the UAC prompt.

illwieckz commented 4 years ago

Here is a flow diagram of what I think how the updater must behave:

updater flow

You can click on the picture to see SVG in full size, you can find dia source there.

Note that I did this diagram before @DolceTriade answered to my question about “when does the udpater updates itself”. I'm not against redoing the diagram to adapt to the current behavior which is: the updater silently updates itself at startup, “when the splash screen is showing prior to the main screen showing”, except I'm not sure we can fix the chicken and egg problem from needing the main screen to configure the home path hence the engine dir.

In this diagram the enginedir is assumed to be homepath/base on every OS and the real updater being stored there. Random downloaded updaters would just chainload the latest one from enginedir.

Note that this flow requires some command lines to be implemented, some command line I would like to see implemented in any way. This is also thought in a way the updater is the launcher, and act as the game binary, the engine just being a component spawned by the launcher, so the launcher is expected to be started by protocol handlers and start menu entries, being at least able to pass proto://addr urls to engine.

illwieckz commented 4 years ago

It looks like that “updating at splash time” is only meaningful when self-replacing is expected to work on randomly downloaded updaters, but as soon as the self-replacement occurs on the updater stored in enginedir, we can solve the chicken-and-egg problem just by downloading updater while main window is displayed, as depicted in the diagram shown.

I also think that to be able to properly store the downloaded updater, we may store in the json file depicted in #46 the path to updater binary in distributed zip so the updater can copy this binary in enginedir properly.

slipher commented 4 years ago

Nice flowchart :)

Instead of assuming some hard-coded path for enginedir, we could look for the user's previously selected installation directory which is persisted via QT's "Settings" class.

One perverse consequence of the diagrammed flow is that if you download a new version of the updater and run it, but there is an old version already installed, the new version would launch the old version. Perhaps we could do this instead: If the running updater's binary is not located in the selected installation directory (or one has never been selected), it prompts the user to select an installation directory and moves itself to the selected directory.

illwieckz commented 4 years ago

Oh yes, nice catch!

I would avoid implementing more windows. Many we can just check if installed updater is older than the one running it, if yes then display the usual main window and when people clicks on download button, the updater is copied if downloadable is not newer, downloaded if copy fail, or the updater continue the process if either copy and download fail (basically an updater started from a zip on windows while being disconnected from the Internet).

illwieckz commented 4 years ago

Sorry if I was not clear, the hard-coded path for enginedir to homedir/base is for when the user has not customized it, otherwise it uses the one set in options. Hence I want to route user to the main window (where engine dir can be customized) everytime there is an action to do in that directory (like downloading or copying stuff).

slipher commented 4 years ago

Yeah, I am not suggesting any new UI. What I meant was that if the updater's directory is different from the one in settings, it should act like a new install, and give the user the chance to change options before doing further actions.

slipher commented 3 years ago

Updater in installation directory is implemented now, although not exactly as in the flowchart. Copying to the installation directory occurs during the game installation step. Self-updates are always in-place, regardless of where the updater is stored. When the updater relaunches itself, it is always from the same path.