mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-18 09:23:26 -05:00
fix: tell an offline cache miss from absence
Offline, fetch_file answered None for a path the cache never stored, the same answer as a path known to be absent, and profile_sync reported existing files as gone. A miss now raises NotCachedError and the profile is reported unverified.
This commit is contained in:
1 parent
b91449590d
commit
9802804a9a
6 files changed
+59
-9
No files matched your search
@@ -124,9 +124,13 @@ def main() -> None:
|
||||
|
||||
total = 0
|
||||
for name in args.emulators:
|
||||
findings, agreed, unjudged = audit(
|
||||
name, args.emulators_dir, args.cache_dir, args.offline
|
||||
)
|
||||
try:
|
||||
findings, agreed, unjudged = audit(
|
||||
name, args.emulators_dir, args.cache_dir, args.offline
|
||||
)
|
||||
except upstream.UpstreamError as exc:
|
||||
print(f"{name}: unreachable, {exc}", file=sys.stderr)
|
||||
continue
|
||||
total += len(findings)
|
||||
print(
|
||||
f"{name}: {agreed} agree, {len(findings)} point elsewhere, "
|
||||
|
||||
@@ -1803,7 +1803,7 @@ def build_report(
|
||||
return None
|
||||
try:
|
||||
return upstream.fetch_file(repo, sha, wanted, cache_dir, offline)
|
||||
except upstream.RateLimitError:
|
||||
except (upstream.RateLimitError, upstream.NotCachedError):
|
||||
raise
|
||||
except upstream.UpstreamError as exc:
|
||||
mute.add(key)
|
||||
@@ -3677,6 +3677,13 @@ def main() -> None:
|
||||
)
|
||||
except upstream.RateLimitError:
|
||||
raise
|
||||
except upstream.NotCachedError as exc:
|
||||
# Offline with a cache that never stored this file: the profile
|
||||
# is unverified, not wrong. Reporting GONE sent readers after
|
||||
# files that exist.
|
||||
report = ProfileReport(
|
||||
name=name, entries=[], counts={}, skipped=f"offline: {exc}"
|
||||
)
|
||||
except upstream.GoneError as exc:
|
||||
# The forge is not coming back: a takedown, or a host that no
|
||||
# longer resolves. Saying so once in the summary beats repeating
|
||||
|
||||
+14
-2
@@ -80,6 +80,14 @@ class RateLimitError(UpstreamError):
|
||||
"""The forge refused the request for quota reasons."""
|
||||
|
||||
|
||||
class NotCachedError(UpstreamError):
|
||||
"""An offline read of something the cache never stored.
|
||||
|
||||
Distinct from absence: returning None made profile_sync report a file
|
||||
that exists as GONE, "absent at HEAD, no rename found".
|
||||
"""
|
||||
|
||||
|
||||
class GoneError(UpstreamError):
|
||||
"""The upstream is not coming back.
|
||||
|
||||
@@ -317,13 +325,17 @@ def fetch_file(
|
||||
cache_dir: str,
|
||||
offline: bool = False,
|
||||
) -> list[str] | None:
|
||||
"""Lines of one path at one revision, or None when absent."""
|
||||
"""Lines of one path at one revision, or None when absent.
|
||||
|
||||
Offline, a path the cache never stored raises NotCachedError: nothing
|
||||
is known about it, which is not the same as knowing it is absent.
|
||||
"""
|
||||
target = cache_path(cache_dir, repo, sha, path)
|
||||
if target.is_file():
|
||||
text = target.read_text(encoding="utf-8")
|
||||
return None if text == ABSENT else text.splitlines()
|
||||
if offline:
|
||||
return None
|
||||
raise NotCachedError(f"{repo.slug}@{sha[:8]}:{path} is not in the offline cache")
|
||||
text = _http_text(raw_url(repo, sha, path))
|
||||
write_cache(target, ABSENT if text is None else text)
|
||||
return None if text is None else text.splitlines()
|
||||
|
||||
@@ -115,7 +115,11 @@ class TestCorpusIsAnswered(unittest.TestCase):
|
||||
read = []
|
||||
|
||||
def counted(*args, **kwargs):
|
||||
lines = fetch(*args, **kwargs)
|
||||
# A cold path is unread here, not absent.
|
||||
try:
|
||||
lines = fetch(*args, **kwargs)
|
||||
except fileless_audit.upstream.NotCachedError:
|
||||
return None
|
||||
if lines is not None:
|
||||
read.append(args[2])
|
||||
return lines
|
||||
|
||||
@@ -3932,5 +3932,19 @@ class UpstreamVendoredAsASubmodule(unittest.TestCase):
|
||||
self.assertEqual(views[1].head, "nesbox-tip")
|
||||
|
||||
|
||||
class OfflineCacheMissIsNotGone(TestBuildReport):
|
||||
"""Offline, a file the cache never stored came back as None and the
|
||||
report read "GONE (absent at HEAD, no rename found)" for files that
|
||||
exist. The miss now stops the profile as unverified."""
|
||||
|
||||
def test_an_uncached_file_is_not_reported_gone(self):
|
||||
def cold(repo, sha, path, cache_dir, offline=False):
|
||||
raise profile_sync.upstream.NotCachedError(f"{path} not cached")
|
||||
|
||||
profile_sync.upstream.fetch_file = cold
|
||||
with self.assertRaises(profile_sync.upstream.NotCachedError):
|
||||
build_report("test", self._profile(["a.c:2"]), self.dir, offline=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
+11
-2
@@ -379,9 +379,18 @@ class TestCache(unittest.TestCase):
|
||||
self.assertEqual(second, first)
|
||||
self.assertEqual(len(self.calls), 1)
|
||||
|
||||
def test_offline_miss_returns_none_without_request(self):
|
||||
self.assertIsNone(
|
||||
def test_offline_miss_is_not_absence(self):
|
||||
# Returning None made profile_sync report an existing file as GONE.
|
||||
with self.assertRaises(upstream.NotCachedError):
|
||||
upstream.fetch_file(self.repo, "abc", "a.c", self.dir, offline=True)
|
||||
self.assertEqual(self.calls, [])
|
||||
|
||||
def test_offline_cached_absence_stays_absence(self):
|
||||
upstream.write_cache(
|
||||
upstream.cache_path(self.dir, self.repo, "abc", "gone.c"), upstream.ABSENT
|
||||
)
|
||||
self.assertIsNone(
|
||||
upstream.fetch_file(self.repo, "abc", "gone.c", self.dir, offline=True)
|
||||
)
|
||||
self.assertEqual(self.calls, [])
|
||||
|
||||
|
||||
Reference in new issue
Block a user