Persist butler outside the plugin dir so plugin updates don't wipe it

OGPU wipes user://plugins/<id>/ (and everything inside it) whenever a
plugin is updated or re-extracted, so storing butler and butler.db under
user://plugins/itch/assets meant every version bump deleted the binary
and its login session. Store them in persistent user://butler instead,
and migrate any leftover install from the old location.
This commit is contained in:
Jose Falanga 2026-08-06 17:19:28 -03:00
parent 408991a693
commit e8111f89c2
2 changed files with 30 additions and 4 deletions

View file

@ -16,7 +16,10 @@ extends NodeThread
## butler update that changes a field, diff against that spec. ## butler update that changes a field, diff against that spec.
const broth_base := "https://broth.itch.zone/butler" const broth_base := "https://broth.itch.zone/butler"
const butler_dir := "user://plugins/itch/assets/butler" ## Persistent storage for the downloaded butler binary + butler.db. Kept OUT
## of user://plugins/<id>/ because OGPU wipes that directory (and everything
## inside it) whenever the plugin is updated or re-extracted.
const butler_dir := "user://butler"
const CACHE_DIR := "itch" const CACHE_DIR := "itch"
enum STATE { enum STATE {
@ -69,7 +72,9 @@ func _ready() -> void:
## Bootstraps the butler binary if it isn't present, then spawns butlerd. ## Bootstraps the butler binary if it isn't present, then spawns butlerd.
func bootstrap() -> void: func bootstrap() -> void:
var butler_bin := "/".join([ProjectSettings.globalize_path(butler_dir), "butler"]) var butler_dir_global := ProjectSettings.globalize_path(butler_dir)
_migrate_butler(butler_dir_global)
var butler_bin := "/".join([butler_dir_global, "butler"])
if not FileAccess.file_exists(butler_bin): if not FileAccess.file_exists(butler_bin):
logger.info("The butler binary wasn't found. Trying to install it.") logger.info("The butler binary wasn't found. Trying to install it.")
var success := await _install_butler() var success := await _install_butler()
@ -79,7 +84,7 @@ func bootstrap() -> void:
return return
logger.info("Successfully installed butler") logger.info("Successfully installed butler")
var dbpath := "/".join([ProjectSettings.globalize_path("user://plugins/itch/assets"), "butler.db"]) var dbpath := "/".join([butler_dir_global, "butler.db"])
var args := [ var args := [
"daemon", "daemon",
"--json", "--json",
@ -100,6 +105,27 @@ func bootstrap() -> void:
bootstrap_finished.emit() bootstrap_finished.emit()
## Moves a butler install left over in the plugin directory (OGPU wipes
## plugins/<id>/ on every plugin update, which is why older builds kept
## losing butler) to the persistent user://butler location.
func _migrate_butler(dest_dir: String) -> void:
var old_dir := ProjectSettings.globalize_path("user://plugins/itch/assets/butler")
if old_dir == dest_dir:
return
if not DirAccess.dir_exists_absolute(old_dir):
return
if not FileAccess.file_exists("/".join([old_dir, "butler"])):
return
if FileAccess.file_exists("/".join([dest_dir, "butler"])):
return
DirAccess.make_dir_recursive_absolute(dest_dir)
for file in ["butler", "7z.so", "libc7zip.so"]:
var src := "/".join([old_dir, file])
if FileAccess.file_exists(src):
DirAccess.copy_absolute(src, "/".join([dest_dir, file]))
logger.info("Migrated butler from " + old_dir + " to " + dest_dir)
## Downloads a butler binary for this platform from itch's broth distribution ## Downloads a butler binary for this platform from itch's broth distribution
## channel (the same one the official itch.io app uses to self-update). ## channel (the same one the official itch.io app uses to self-update).
func _install_butler() -> bool: func _install_butler() -> bool:

View file

@ -1,7 +1,7 @@
{ {
"plugin.id": "itch", "plugin.id": "itch",
"plugin.name": "itch.io", "plugin.name": "itch.io",
"plugin.version": "0.1.0", "plugin.version": "0.1.1",
"plugin.min-api-version": "1.1.0", "plugin.min-api-version": "1.1.0",
"plugin.link": "https://github.com/YOUR_USERNAME/OpenGamepadUI-itch", "plugin.link": "https://github.com/YOUR_USERNAME/OpenGamepadUI-itch",
"plugin.source": "https://github.com/YOUR_USERNAME/OpenGamepadUI-itch", "plugin.source": "https://github.com/YOUR_USERNAME/OpenGamepadUI-itch",