neogeographica / quakestarter

A package with tools for setting up a playable Quake installation and downloading/playing/managing many highly-regarded addons.
21 stars 0 forks source link

ponder a simple autoupdater #75

Closed neogeographica closed 2 years ago

neogeographica commented 2 years ago

For approximately forever now, the "update" process has been: 1) download zipfile of latest release; 2) unzip over current files. (And then presumably check the changelog to see if there are new features you should know about.)

This would be pretty easy to automate when Quakestarter runs. I'd just need a way to determine when the latest release is different from the current installation.

E.g. one (janky?) way to do that would be to have a file in the repo that contains the latest released version, and also distribute that file with the release itself. If the one in the repo is different from the one on disk, that means it's time to upgrade.

Currently the last-released version is defined in the repo as "version" in docsource/conf.py (derived from "release" in that same file). Could modify that a bit so that release/version are sourced from some text file that is also packaged with the release.

That would open a bit of a race window though, where the file in the repo gets updated a bit before the actual release is created. Hmm. Could have a separate file that gets updated AFTER the release is created/posted... or, instead of reading a file from the repo, something like:

If using curl, it's easy enough to get the headers with curl -I and then parse it. If instead we're having to do the fallback of using System.Net.WebClient ... I'm sure it's doable, probably: DownloadData (instead of DownloadFile) with the client; create a WebHeaderCollection of the client's ResponseHeaders; do Get("location") on that collection. Just need to experiment.

neogeographica commented 2 years ago

This'll do the header fetch:

powershell.exe -nologo -noprofile -command "&{trap{exit 1;} (Invoke-WebRequest -MaximumRedirection 0 -Uri \"https://github.com/neogeographica/quakestarter/releases/latest\").Headers.Location;}" 2>nul
neogeographica commented 2 years ago

Got a working thing on the update-check branch. Needs a bunch more testing and documentation.

neogeographica commented 2 years ago

Merged to the develop branch now.

Seems to be working, but there's at least one more design issue that I'm not sure about.

So, QS has both "normal" and "noengine" distributions, where the latter doesn't include vkQuake or Ironwail. Currently the autoupdate code (on develop branch) allows you to choose which of these flavors to get for your update.

If you're going from "noengine" to "noengine" the upgrade situation doesn't have to worry about touching any vkQuake or Ironwail files.

For "normal" to "normal" the situation is still pretty simple. As part of the update we remove the existing vkQuake and Ironwail files (in case the set of files is going to change with the update) and then copy in the new ones. "noengine" to "normal" is also straightforward, you just add in the engine files.

For "normal" to "noengine"... hmm. Does this indicate a desire to actually ERASE the existing engine files? Or just leave them alone? There's a good chance that "leave them alone" is the right answer. For example let's say that the user is happy with their current engine(s) and doesn't want to replace them with newer versions. Or maybe they already have the latest versions installed and they just want the smaller download size of the "noengine" package.

OK, fine. We could choose "leave them alone" for that case (as the current code actually does), and if the user really does want to delete them they can do that manually.

But now let's say that the user does this upgrade pattern: normal -> noengine -> normal. For example maybe they were holding off on accepting any engine updates for one of the reasons above, but then they later decided to pull the trigger. What do we do at this point?

The current code just sees this as a "noengine" to "normal" upgrade, so it will just copy in the new engine files without deleting any old ones. If the engine files have changed this could leave some unused files lying around.

It kind of seems like we should remove the engine files that were previously installed by the original "normal" installation, which would mean preserving that manifest through the "noengine" upgrade.

But if the user had proceeded to manually mess around with the engine files after the "noengine" upgrade, having them deleted on the next upgrade could be a weird surprise. Or how about this example: what if the package changed the bundled engines again, to use the OtherQuakeThing engine instead of vkQuake or Ironwail. On the first upgrade into this new regime, the user picks "noengine" because they want to keep vkQuake and Ironwail. Then on some later upgrade they pick the normal bundle because they want to give OtherQuakeThing a try... would they expect that to then delete vkQuake/Ironwail?

This feels like the kind of situation that really needs the right conceptual model to make the design/implementation work out elegantly, and I haven't come across that model yet.

For example, if the user chooses a "normal" to "noengine" upgrade, we could explicitly ask them if they are choosing to "cut loose" the engine files from Quakestarter management, or if QS should continue to keep track of the engine files and delete them in some future upgrade to a "normal" bundle. (And if the latter, this same question would then come up on any "noengine" to "noengine" update.) Not 100% sure how to phrase that sensibly though.

neogeographica commented 2 years ago

Will be in the next release.