fix: delete stale index-v2-<hash>.json files from prior rehash runs
Build fdroidserver-ipfs image / build (push) Successful in 1m10s

Without this, every update left another renamed index lying in repo/
forever — pinning the repo to IPFS would keep re-pinning all of them.

Also strip a pre-existing -<hex12> suffix from the stem before computing
the new one, so re-running rehash standalone (without an intervening
fdroid update) is idempotent instead of producing index-v2-abc-def.json.

diff/*.json doesn't need the same treatment: fdroidserver's make_v2()
already wipes the whole diff/ directory at the start of every update.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
mrambossek
2026-05-24 22:54:10 +02:00
co-authored by Claude Opus 4.7
parent a6168221d1
commit 917ddbe550
+27 -1
View File
@@ -15,6 +15,7 @@ import argparse
import hashlib import hashlib
import json import json
import os import os
import re
import subprocess import subprocess
import sys import sys
from pathlib import Path from pathlib import Path
@@ -35,6 +36,10 @@ from fdroidserver import common, signindex
HASH_SUFFIX_LEN = 12 HASH_SUFFIX_LEN = 12
# Matches a trailing "-<12 lowercase hex>" right before the extension. Used to
# strip the prior suffix when re-rehashing the same file, so we don't accrete
# index-v2-abc-def-ghi.json from repeated runs.
_HASH_SUFFIX_RE = re.compile(r'-[0-9a-f]{12}$')
def sha256_last_chars(path: Path) -> str: def sha256_last_chars(path: Path) -> str:
@@ -50,12 +55,30 @@ def write_entry_json(entry: dict, path: Path) -> None:
json.dump(entry, fp, ensure_ascii=False, sort_keys=True) json.dump(entry, fp, ensure_ascii=False, sort_keys=True)
def cleanup_stale_indexes(repodir: Path, keep_filename: str) -> None:
"""Remove leftover index-v2-<hash>.json files (and their .asc) from prior runs.
`fdroid update` always writes the fresh index back to the stable
`index-v2.json` name, so anything matching `index-v2-*.json` in this
directory is from a previous rehash. Skip `keep_filename` to make
re-running the script standalone safe.
"""
for stale in repodir.glob('index-v2-*.json'):
if stale.name == keep_filename:
continue
stale.unlink()
asc = stale.with_suffix(stale.suffix + '.asc')
if asc.exists():
asc.unlink()
def rehash_entry_file(repodir: Path, file_entry: dict) -> None: def rehash_entry_file(repodir: Path, file_entry: dict) -> None:
"""Rename the file referenced by file_entry["name"] and update name/ipfsCIDv1 in place.""" """Rename the file referenced by file_entry["name"] and update name/ipfsCIDv1 in place."""
old_rel = file_entry['name'].lstrip('/') old_rel = file_entry['name'].lstrip('/')
old_path = repodir / old_rel old_path = repodir / old_rel
suffix = sha256_last_chars(old_path) suffix = sha256_last_chars(old_path)
new_path = old_path.with_name(f"{old_path.stem}-{suffix}{old_path.suffix}") base_stem = _HASH_SUFFIX_RE.sub('', old_path.stem)
new_path = old_path.with_name(f"{base_stem}-{suffix}{old_path.suffix}")
cid = common.calculate_IPFS_cid(str(old_path)) cid = common.calculate_IPFS_cid(str(old_path))
@@ -76,6 +99,9 @@ def rehash_repodir(repodir_name: str) -> bool:
with entry_json.open(encoding='utf-8') as fp: with entry_json.open(encoding='utf-8') as fp:
entry = json.load(fp) entry = json.load(fp)
current_index = Path(entry['index']['name'].lstrip('/')).name
cleanup_stale_indexes(repodir, keep_filename=current_index)
rehash_entry_file(repodir, entry['index']) rehash_entry_file(repodir, entry['index'])
for diff_entry in entry.get('diffs', {}).values(): for diff_entry in entry.get('diffs', {}).values():
rehash_entry_file(repodir, diff_entry) rehash_entry_file(repodir, diff_entry)