mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
unseen: make clone disk-size guard tolerate git's mid-walk churn
disk_bytes() summed the clone tree with rglob + stat() as a size cap before every git command. On a blob:none clone, `git show` triggers an on-demand blob fetch that writes and deletes transient .git/objects/pack/*.rev files, so a path rglob had just listed could be gone by the stat() call -> FileNotFoundError aborted the whole draft as an instrument_failure. The race can hit any candidate, so it was a non-deterministic draft-killer (observed extracting a real npm repo). Skip a file that raises OSError mid-walk; the size cap is unaffected. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
0a637e8989
commit
f4c7143525
@@ -57,7 +57,16 @@ class Git:
|
||||
return done.stdout.decode("utf-8", errors="replace")
|
||||
|
||||
def disk_bytes(self) -> int:
|
||||
return sum(p.stat().st_size for p in self.path.rglob("*") if p.is_file() and not p.is_symlink())
|
||||
# git churns .git/objects/pack (incl. transient *.rev) during on-demand blob
|
||||
# fetches, so a path rglob just listed can vanish before stat(): skip it.
|
||||
total = 0
|
||||
for p in self.path.rglob("*"):
|
||||
try:
|
||||
if p.is_file() and not p.is_symlink():
|
||||
total += p.stat().st_size
|
||||
except OSError:
|
||||
continue
|
||||
return total
|
||||
|
||||
def parents(self, sha: str) -> list[str]:
|
||||
return self.run("rev-list", "--parents", "-n", "1", sha).split()[1:]
|
||||
|
||||
@@ -312,3 +312,25 @@ def test_unbalanced_cells_remain_proportional_and_seed_changes_draw():
|
||||
draw, _ = e.draw_ordinary(rows, set(), set(), seed=1)
|
||||
assert len([r for r in draw if r["size_bucket"] == 0]) == 9
|
||||
assert draw != e.draw_ordinary(rows, set(), set(), seed=2)[0]
|
||||
|
||||
|
||||
def test_disk_bytes_skips_files_that_vanish_mid_walk(tmp_path):
|
||||
# git churns .git/objects/pack (transient *.rev) during on-demand blob fetches,
|
||||
# so a path rglob just listed can be gone by the time disk_bytes stat()s it.
|
||||
git = e.Git(tmp_path, runner=subprocess.run)
|
||||
(tmp_path / "a").write_bytes(b"x" * 10)
|
||||
(tmp_path / "b").write_bytes(b"y" * 20)
|
||||
real = [p for p in tmp_path.rglob("*")]
|
||||
|
||||
class Vanished:
|
||||
def is_file(self):
|
||||
return True
|
||||
|
||||
def is_symlink(self):
|
||||
return False
|
||||
|
||||
def stat(self):
|
||||
raise FileNotFoundError(2, "No such file or directory")
|
||||
|
||||
git.path = type("P", (), {"rglob": lambda self, pattern: iter([*real, Vanished()])})()
|
||||
assert git.disk_bytes() == 30
|
||||
|
||||
Reference in New Issue
Block a user