claude-dev-env 8.51.0 → 8.51.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -36,12 +36,29 @@ def _log_walk_error(os_error: OSError) -> None:
|
|
|
36
36
|
logging.warning("cannot scan %s -- %s", os_error.filename, os_error.strerror)
|
|
37
37
|
|
|
38
38
|
|
|
39
|
+
def _is_older_than(directory_path: str, now: float, min_age_seconds: int) -> bool:
|
|
40
|
+
"""Report whether a directory ctime precedes *now* by more than the minimum age."""
|
|
41
|
+
try:
|
|
42
|
+
raw_ctime = os.path.getctime(directory_path)
|
|
43
|
+
except FileNotFoundError:
|
|
44
|
+
return False
|
|
45
|
+
except PermissionError:
|
|
46
|
+
logging.warning("permission denied -- %s", directory_path)
|
|
47
|
+
return False
|
|
48
|
+
except OSError:
|
|
49
|
+
return False
|
|
50
|
+
ctime = min(raw_ctime, now)
|
|
51
|
+
return now - ctime > min_age_seconds
|
|
52
|
+
|
|
53
|
+
|
|
39
54
|
def sweep(root: str, min_age_seconds: int) -> list[str]:
|
|
40
55
|
"""Remove empty directories under *root* older than *min_age_seconds*.
|
|
41
56
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
57
|
+
Reads the age of every directory before the first removal, because on
|
|
58
|
+
POSIX removing a child directory moves its parent's ctime to the present.
|
|
59
|
+
Then removes bottom-up so nested empty directories are cleaned from the
|
|
60
|
+
leaves inward. os.rmdir decides emptiness and fails harmlessly for a
|
|
61
|
+
directory that still holds an entry.
|
|
45
62
|
|
|
46
63
|
Args:
|
|
47
64
|
root: Root directory to walk; directories below the root are
|
|
@@ -56,35 +73,28 @@ def sweep(root: str, min_age_seconds: int) -> list[str]:
|
|
|
56
73
|
all_removed: list[str] = []
|
|
57
74
|
|
|
58
75
|
now = time.time()
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
76
|
+
all_expired_directories = [
|
|
77
|
+
each_directory_path
|
|
78
|
+
for each_directory_path, _, _ in os.walk(
|
|
79
|
+
root, onerror=_log_walk_error, topdown=False
|
|
80
|
+
)
|
|
81
|
+
if each_directory_path != root
|
|
82
|
+
and _is_older_than(each_directory_path, now, min_age_seconds)
|
|
83
|
+
]
|
|
84
|
+
for each_directory_path in all_expired_directories:
|
|
64
85
|
try:
|
|
65
|
-
|
|
86
|
+
os.rmdir(each_directory_path)
|
|
87
|
+
logging.info("deleted: %s", each_directory_path)
|
|
88
|
+
all_removed.append(each_directory_path)
|
|
66
89
|
except FileNotFoundError:
|
|
67
|
-
|
|
68
|
-
except
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
try:
|
|
76
|
-
os.rmdir(each_directory_path)
|
|
77
|
-
logging.info("deleted: %s", each_directory_path)
|
|
78
|
-
all_removed.append(each_directory_path)
|
|
79
|
-
except FileNotFoundError:
|
|
80
|
-
pass
|
|
81
|
-
except OSError as e:
|
|
82
|
-
if e.errno not in (errno.ENOTEMPTY, errno.EEXIST):
|
|
83
|
-
logging.warning(
|
|
84
|
-
"could not remove %s -- %s",
|
|
85
|
-
each_directory_path,
|
|
86
|
-
e,
|
|
87
|
-
)
|
|
90
|
+
pass
|
|
91
|
+
except OSError as e:
|
|
92
|
+
if e.errno not in (errno.ENOTEMPTY, errno.EEXIST):
|
|
93
|
+
logging.warning(
|
|
94
|
+
"could not remove %s -- %s",
|
|
95
|
+
each_directory_path,
|
|
96
|
+
e,
|
|
97
|
+
)
|
|
88
98
|
|
|
89
99
|
return all_removed
|
|
90
100
|
|
|
@@ -107,6 +107,17 @@ def test_sweep_removes_nested_empty_dirs(tmp_path: Path) -> None:
|
|
|
107
107
|
assert not (tmp_path / "level1").exists()
|
|
108
108
|
|
|
109
109
|
|
|
110
|
+
def test_sweep_reports_a_nested_chain_removed_leaf_first_in_one_pass(tmp_path: Path) -> None:
|
|
111
|
+
"""sweep reads every age before it removes, so one pass clears the whole chain."""
|
|
112
|
+
outer = tmp_path / "outer"
|
|
113
|
+
inner = outer / "inner"
|
|
114
|
+
inner.mkdir(parents=True)
|
|
115
|
+
|
|
116
|
+
removed = sweep(str(tmp_path), min_age_seconds=0)
|
|
117
|
+
|
|
118
|
+
assert removed == [str(inner), str(outer)]
|
|
119
|
+
|
|
120
|
+
|
|
110
121
|
def test_sweep_removes_only_old_enough_directories(tmp_path: Path) -> None:
|
|
111
122
|
"""sweep does not remove directories newer than the age threshold."""
|
|
112
123
|
young_dir = tmp_path / "young"
|