mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
prepare_output: leave out files the preparer's export doesn't write
Every PR's parity job failed since #6959 with "the prepared output changed (23198 files) but OUTPUT_VERSION is still 3": CI now clones the 142 other languages and pack.mcmeta into a preparation, and the digest counted them. It also counted asset-index.json (the sounds step) and the game's run-time caches (horizon-sprites.cache, horizon-data.bin), so it depended on whether a harness had run the game before the check. With these left out, the 8 preparations on the two Mac runners (old and new, with and without languages) all give OUTPUT_VERSION 3's digest again. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
9aede76945
commit
00e717781f
2 files changed
+27
-3
No files matched your search
@@ -32,6 +32,14 @@ class PrepareOutputTests(unittest.TestCase):
|
||||
'block-behaviours.json': b'{"c": "Foo$$Lambda/0x00000ff0"}',
|
||||
'export.log': b'run 2',
|
||||
'assets/minecraft/sounds/a.ogg': b'two',
|
||||
# From the launcher's asset store (CI clones the languages in later), not the preparer's export.
|
||||
'assets/pack.mcmeta': b'{"language": {"fr_fr": {}}}',
|
||||
'assets/minecraft/lang/fr_fr.json': b'{"a": "b"}',
|
||||
'asset-index.json': b'{"objects": {}}',
|
||||
# The game's run-time caches, there once a harness ran the game on this preparation.
|
||||
'horizon-sprites.cache': b'sprites',
|
||||
'horizon-data.bin': b'data',
|
||||
'horizon-data.bin.123.tmp': b'half',
|
||||
'horizon-prepare.json': b'{"output_version": 1}',
|
||||
'.horizon-prepare.lock': b'',
|
||||
}
|
||||
@@ -48,6 +56,11 @@ class PrepareOutputTests(unittest.TestCase):
|
||||
(Path(tmp) / 'b/horizon-resources.json').write_text(json.dumps(manifest))
|
||||
(Path(tmp) / 'b/new.nbt').write_bytes(b'')
|
||||
self.assertNotEqual(first, prepare_output.digest(Path(tmp) / 'b'))
|
||||
# en_us and deprecated are the JAR's, made by the preparer: they count.
|
||||
(Path(tmp) / 'b/new.nbt').unlink()
|
||||
self.assertEqual(first, prepare_output.digest(Path(tmp) / 'b'))
|
||||
(Path(tmp) / 'b/assets/minecraft/lang/en_us.json').write_bytes(b'{}')
|
||||
self.assertNotEqual(first, prepare_output.digest(Path(tmp) / 'b'))
|
||||
|
||||
def test_the_versions_file_ends_at_the_constant(self):
|
||||
versions = prepare_output.parse_versions('# comment\n1 aa\n2 bb\n')
|
||||
|
||||
+14
-3
@@ -18,7 +18,9 @@ It only grows: the last line is the current version, and a change to the output
|
||||
The digest covers every file of the preparation, canonicalised where the preparer is not deterministic between
|
||||
runs (verified across the CI runners): JSON is compared as data (key order, the order of each `tags` list of
|
||||
creative-inventory.json, and the addresses in `$$Lambda/0x...` class names don't count); logs, compiled classes,
|
||||
the sounds (copied from the player's launcher by another step), the stamp naming the OUTPUT_VERSION
|
||||
the sounds, the languages but the JAR's and the asset index (copied from the player's launcher by another step; CI
|
||||
clones the languages into a preparation after the fact), the game's run-time caches (horizon-sprites.cache,
|
||||
horizon-data.bin), the stamp naming the OUTPUT_VERSION
|
||||
(horizon-prepare.json), the lock file (.horizon-prepare.lock) and the manifest's file hashes (raw bytes) don't count. The manifest's own scalar fields (schema, data version, jar hashes, file count) do.
|
||||
"""
|
||||
|
||||
@@ -41,6 +43,12 @@ MANIFEST = 'horizon-resources.json'
|
||||
STAMP = 'horizon-prepare.json'
|
||||
# The empty file a preparation locks while it writes (crates/horizon-prepare/src/lib.rs, LOCK).
|
||||
LOCK = '.horizon-prepare.lock'
|
||||
# Written into a preparation by something other than the preparer's export: the sounds and languages step
|
||||
# (crates/horizon-prepare/src/sounds.rs) and, at run time, the game's caches (horizon-client-render's sprite_cache.rs,
|
||||
# horizon-core's prepared_files.rs). Whether a harness ran the game before the check must not change the digest.
|
||||
DATA_FILE = 'horizon-data.bin'
|
||||
FROM_ELSEWHERE = ('assets/minecraft/sounds.json', 'assets/pack.mcmeta', 'asset-index.json', 'horizon-sprites.cache',
|
||||
DATA_FILE, STAMP, LOCK)
|
||||
LAMBDA = re.compile(r'\$\$Lambda/0x[0-9a-fA-F]+')
|
||||
CONSTANT = re.compile(r'^pub const OUTPUT_VERSION: u32 = (\d+);', re.M)
|
||||
|
||||
@@ -74,8 +82,11 @@ def canonical(rel: str, data: bytes) -> bytes:
|
||||
|
||||
def skipped(rel: str) -> bool:
|
||||
parts = rel.split('/')
|
||||
return rel.endswith(('.log', '.class')) or parts[:3] == ['assets', 'minecraft', 'sounds'] \
|
||||
or rel in ('assets/minecraft/sounds.json', STAMP, LOCK)
|
||||
# The languages but the client JAR's own come from the launcher's asset store like the sounds; CI clones them
|
||||
# into a preparation after the fact (tools/ci/vanilla-data.sh).
|
||||
languages = parts[:3] == ['assets', 'minecraft', 'lang'] and parts[3:] not in (['en_us.json'], ['deprecated.json'])
|
||||
return rel.endswith(('.log', '.class')) or parts[:3] == ['assets', 'minecraft', 'sounds'] or languages \
|
||||
or rel in FROM_ELSEWHERE or rel.startswith(f'{DATA_FILE}.')
|
||||
|
||||
|
||||
def digest(resources: Path) -> tuple[str, int]:
|
||||
|
||||
Reference in new issue
Block a user