diff --git a/update.py b/update.py index 219ad94..c93cc1a 100644 --- a/update.py +++ b/update.py @@ -66,28 +66,67 @@ def ensure_config(): return cfg, first +ZIP_URL = "https://git.armoredarmadillo.com/brockdarnold/eve-watcher/archive/main.zip" + + def _git(*a): return subprocess.run(["git", "-C", HERE, *a], capture_output=True, text=True) -def git_pull(): - """Force the working tree to the latest remote commit (reset --hard). This is - bulletproof vs. `git pull` on Windows, which fails on CRLF/dirty trees. The - gitignored config.ini is never touched. Returns True if the code changed.""" - if not os.path.isdir(os.path.join(HERE, ".git")): - print("• not a git clone — can't auto-update. Reinstall via the one-liner.") +def _have_git(): + import shutil as _sh + return os.path.isdir(os.path.join(HERE, ".git")) and _sh.which("git") is not None + + +def update_code(): + """Pull the latest watcher code. Uses git when this is a clone; otherwise + downloads the repo zip and overwrites files (config.ini is never touched). + Returns True if anything changed.""" + if _have_git(): + before = _git("rev-parse", "HEAD").stdout.strip() + if _git("fetch", "-q", "origin").returncode != 0: + print("! git fetch failed (offline?). Keeping current version.") + return False + _git("reset", "--hard", "-q", "origin/main") + after = _git("rev-parse", "HEAD").stdout.strip() + if before and after and before != after: + print(f" updated: {before[:7]} -> {after[:7]}") + return True + print(" already on latest code.") return False - before = _git("rev-parse", "HEAD").stdout.strip() - if _git("fetch", "-q", "origin").returncode != 0: - print("! git fetch failed (offline?). Keeping current version.") + return _zip_update() + + +def _zip_update(): + """git-less update: download the repo zip and write any changed files.""" + import io + import urllib.request + import zipfile + try: + req = urllib.request.Request(ZIP_URL, headers={"User-Agent": "eve-watcher-updater"}) + data = urllib.request.urlopen(req, timeout=60).read() + z = zipfile.ZipFile(io.BytesIO(data)) + except Exception as e: + print(f"• update check failed (offline?): {e}") return False - _git("reset", "--hard", "-q", "origin/main") - after = _git("rev-parse", "HEAD").stdout.strip() - if before and after and before != after: - print(f" updated: {before[:7]} -> {after[:7]}") - return True - print(" already on latest code.") - return False + changed = 0 + for n in z.namelist(): + if n.endswith("/"): + continue + rel = n.split("/", 1)[1] if "/" in n else n # strip top 'eve-watcher/' + if not rel or rel == "config.ini": # never clobber local config + continue + dest = os.path.join(HERE, rel.replace("/", os.sep)) + new = z.read(n) + old = open(dest, "rb").read() if os.path.exists(dest) else None + if old != new: + os.makedirs(os.path.dirname(dest) or HERE, exist_ok=True) + with open(dest, "wb") as f: + f.write(new) + changed += 1 + print(f" code updated (zip): {changed} file(s)." if changed + else " already on latest code (zip).") + return changed > 0 def deps(): @@ -206,7 +245,7 @@ def ensure_daily_task(): def main(): print("=== Eve watcher setup / auto-update ===") cfg, first = ensure_config() - changed = git_pull() + changed = update_code() if changed or first: deps() ensure_tesseract(cfg)