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")
|
return done.stdout.decode("utf-8", errors="replace")
|
||||||
|
|
||||||
def disk_bytes(self) -> int:
|
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]:
|
def parents(self, sha: str) -> list[str]:
|
||||||
return self.run("rev-list", "--parents", "-n", "1", sha).split()[1:]
|
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)
|
draw, _ = e.draw_ordinary(rows, set(), set(), seed=1)
|
||||||
assert len([r for r in draw if r["size_bucket"] == 0]) == 9
|
assert len([r for r in draw if r["size_bucket"] == 0]) == 9
|
||||||
assert draw != e.draw_ordinary(rows, set(), set(), seed=2)[0]
|
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