Updater scrubbing project

Writing an updater for my game and reached the point where I would need to scrub the project of old files and folders after update.

I currently use gradle to write a version file for the update process so I thought that may be a good place to write another file that has the desired final state of the project after update.

I could then use walkFileTree to scrub files and directories. Problem is that this doesn’t work for testing other than in the distributed project since that has nothing but the game related files.

I toasted the project once using recursion and an infinite loop that was caused by improper design using relative paths. Basically, I screwed up and set a path that allowed things to move outside the target directory and didn’t realize it till it was to late. In a split second I had a nicely compacted project with every file in it inside one folder. Git saved the project but if that was a delete and it kept going I would of been toast.

I am looking for suggestions on how best to safely approach this so I could test it with the sdk as well as the project itself.

I use lots of logging while building so I can watch the flow but even then things can go wrong very quickly.

Can you explain what this means exactly?

I don’t know that I’ve ever needed this.

Sure, after update the project would have the old jar version still or if a directory or file was renamed then the project needs to be cleaned so it matches the original.

Edit: update only updates changed files or folders in other words.

I’m still not 100% sure that I’m tracking.

This is on the client’s machine or your development machine? I assume the former because the latter seems like “gradle clean” to me.

If the former then we might need to know what kind of auto-updater thing you are using. If it’s not homegrown then it may already cover this. And if it is homegrown, it seems like you should have old manifests that you can look at to see what to delete.

I feel like we are missing parts of the picture.

Its on both because I am coding and testing the updater. Up to this point I was able to do this because I was only working on the updater.

Users machine has this folder structure.

GameClient
GameClient.bin
GameClient.lib
GameClient.Updater
GameClient.Updater.bin
GameClient.Updater.lib
GameClient.Updater.fetched
GameClient.Updater.updates

All work takes place in the fetched and updates folders. fetched is for the updater files, updates is for the GameClient.

I mimic this in the sdk by just having extracting the Updater into the root folder of the GameClient project. Works great unless I screw up a path and things travel outside the Updater folder.

My own updater.

So far I just use gradle to add a file to the distribution zip in the appropriate place. An example looks like this.

Updater/LICENSE
Updater/lib/Updater-0.4.1.jar
Updater/bin/Updater
Updater/bin/Updater.bat
Updater/updater_version.html

The GameClient version file has alot more files. In either case I download the bin folder if anything at all changes.

I strip the versioning from the zip file name so the file directory structure matches the project and that makes things big time easier since I can just use standard list comparison methods.

I would argue strongly that you never want to delete * anything on a user’s computer. You should only be deleting things you specifically know that you put there.

If the answer is “But I wasn’t tracking that before” then you provide documentation on how you can clean up previous versions. With lots of promises about how you are properly tracking this now.

That way you avoid accidentally deleting their doctoral dissertation or something because they accidentally stored it in your directory and never realized. Modern apps make it super easy to ignore where things are actually stored.

Edit: and then going forward, you need to keep a manifest of things that went into previous updates that are no longer in current updates. However that happens. Those are the things you are allowed to delete.

Right, thats what I meant by,

This means I have the old one prior to update for comparison so I can easily sort it for changes. I guess what you’re saying is stick to only those changes and leave everything else alone just for safety. This makes sense. I hadn’t thought of that.

I cant test download the GameClient or any test app except by extracting the distribution every test since the folder structure overlaps the sdk project structure. I can for the updater since its contained in the Updater folder. I was hoping there was some design that would allow me to test both. Extracting zip can be done with the build process using gradle but its a pain and I still have to disable things to continue further developement after the updater is done.

The design of updaters is common so trying to see how they test these without destroying things or jumping through so may hoops to test it.

Some way to quarantine the test so its not so dangerous.

I don’t understand enough about your approach to know why it isn’t putting the game in a game-specific directory.

It does.

The way the updater works it checks first if a new updater has downloaded, if so moves that to its proper folders starts it and exits.

If no new updater, it checks to see if theres a new update for itself, if so, it just starts the updater and exits. Updater downloads and overwrites the Client and starts it again.

Thats where things can lead to trouble. One app starts another. I figured out how things went wrong but that was after there was a problem I didnt forsee. Would like to quarantine this next phase somehow because its deleting things.

This place looks promising.

I will give feedback once I get the testing up.

Bust. Cant add manually or import any packages. sigh…

For the kinds of things that you are doing, it sounds like you would be better of testing your automated updates, etc, on an independent installation. I.E. Do all of your unit tests, etc in the SDK as usual, then install your app just like a user would, outside of the SDK. Use this installation to test your updater.

Thats what I do. I would rather test it in a sandbox environment. Even when installed it can be dangerous until debugged. Recursion in conjunction with a possible continuous loop is very dangerous.

Since one app starts another app and the apps rely on something being inside a folder to start, things can go bad real fast. The final product is safe but I found that getting to the final product can be harder than it looks.

Following Pauls advice of only deleting known quantities will make things easier and much safer though so I am feeling more confident on using my machine to test it.

Edit: It safer because I have a finite list and can test for the existence of the target whereas before I was intending to do a sync type delete where anything other than the final state is removed.

Yeah, super dangerous. lol.

Reminds of when a friend a looong time ago told me a story about the day he tried to remove a file from his root directory that started with #. rm -rf /#somefile

…it had ground way too long before he noticed his error.

I had to look that up so he basically said delete everything and added a comment “somefile”?

Crap.

1 Like

Yeah, if you want to delete a file that starts with # in your root directory, you need to escape the hash. :slight_smile: