Save metadata on SHA256-mismatched downloads and verify reused hash behavior
This commit is contained in:
@@ -239,6 +239,26 @@ def download_file(
|
||||
error_msg = f"SHA256 mismatch: expected {expected_sha256}, got {actual_sha256}"
|
||||
if bad_path:
|
||||
error_msg += f"; file kept at {bad_path}"
|
||||
# Use the intended filename so removing .badsha also makes
|
||||
# the already computed hash available to local model info.
|
||||
# Never attach the rejected file's hash to an existing model.
|
||||
sidecar_model_path = bad_path if os.path.exists(dest_path) else dest_path
|
||||
try:
|
||||
payload = facade.build_model_resolver_metadata(
|
||||
sidecar_model_path,
|
||||
{"sha256": actual_sha256, "size": downloaded},
|
||||
category,
|
||||
)
|
||||
payload.update({
|
||||
"expected_sha256": expected_sha256,
|
||||
"sha256_verified": False,
|
||||
})
|
||||
metadata_path = facade.get_model_resolver_sidecar_path(sidecar_model_path)
|
||||
facade.write_json_atomic(metadata_path, payload, indent=2)
|
||||
result["metadata_path"] = metadata_path
|
||||
log.info(f"Metadata saved for SHA256-mismatched download: {metadata_path}")
|
||||
except Exception as exc:
|
||||
log.warning(f"Could not save metadata for {bad_path}: {exc}")
|
||||
with download_lock:
|
||||
download_progress[download_id]["status"] = "error"
|
||||
download_progress[download_id]["error"] = error_msg
|
||||
|
||||
@@ -371,7 +371,6 @@ class ModelResolverRobustnessTests(unittest.TestCase):
|
||||
{},
|
||||
),
|
||||
),
|
||||
patch("core.download.api.context.write_model_resolver_metadata") as write_metadata,
|
||||
):
|
||||
result = download_model(
|
||||
"https://example.com/mismatched.safetensors",
|
||||
@@ -391,7 +390,23 @@ class ModelResolverRobustnessTests(unittest.TestCase):
|
||||
self.assertTrue(os.path.isfile(bad_path))
|
||||
with open(bad_path, "rb") as bad_handle:
|
||||
self.assertEqual(payload, bad_handle.read())
|
||||
write_metadata.assert_not_called()
|
||||
with open(result["metadata_path"], encoding="utf-8") as handle:
|
||||
saved = json.load(handle)
|
||||
actual_sha256 = hashlib.sha256(payload).hexdigest()
|
||||
self.assertEqual(actual_sha256, saved["sha256"])
|
||||
self.assertEqual(expected_sha256, saved["expected_sha256"])
|
||||
self.assertFalse(saved["sha256_verified"])
|
||||
self.assertEqual("completed", saved["hash_status"])
|
||||
self.assertEqual(len(payload), saved["size"])
|
||||
self.assertFalse(saved["from_civitai"])
|
||||
os.replace(bad_path, model_path)
|
||||
with patch("core.path_utils.hashlib.sha256", side_effect=AssertionError("must reuse saved hash")):
|
||||
self.assertEqual(actual_sha256, read_completed_metadata_sha256(model_path))
|
||||
from core.sources.civitai import get_model_info_for_file
|
||||
|
||||
with patch("core.sources.civitai.calculate_file_sha256", side_effect=AssertionError("must reuse saved hash")):
|
||||
info = get_model_info_for_file(model_path, local_only=True)
|
||||
self.assertEqual(actual_sha256, info["sha256"])
|
||||
response.close.assert_called_once_with()
|
||||
|
||||
def test_base_model_mapping_fuzzy_resolution(self):
|
||||
|
||||
Reference in New Issue
Block a user