diff --git a/.jules/bolt.md b/.jules/bolt.md index 63607c3..dc5af0e 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -60,3 +60,7 @@ ## 2026-06-25 - [Optimize Path.exists() when paired with stat()] **Learning:** Checking `Path.exists()` before `Path.stat()` introduces a redundant system call because `exists()` internally uses `stat()`. **Action:** Rely on catching the `OSError` from `Path.stat()` to simultaneously check for existence and retrieve file attributes, saving measurable I/O overhead on large filesystems. + +## 2026-06-28 - [Optimize subprocess arguments with Path.absolute()] +**Learning:** `Path.resolve()` is used extensively to resolve paths for command-line arguments (e.g. `ffmpeg`). However, `.resolve()` touches the filesystem to follow symlinks and check for existence, which introduces significant disk I/O overhead. In cases where the path is just passed to an external program (which natively handles the filesystem), using `.absolute()` instead performs a fast purely lexical operation. +**Action:** Replace `Path.resolve()` with `Path.absolute()` for strings passed to `subprocess.run` to bypass the redundant I/O operations and speed up processing. diff --git a/media_shrinker.py b/media_shrinker.py index 3eede1d..b71afca 100644 --- a/media_shrinker.py +++ b/media_shrinker.py @@ -228,15 +228,11 @@ def find_candidates( except OSError: continue - if excluded_exact_strs: - if not is_symlink: - resolved_d_str = os.path.join(resolved_dir_str, d) - else: - try: - resolved_d_str = os.path.realpath(d_path_str) - except OSError: - continue + if is_symlink: + continue + if excluded_exact_strs: + resolved_d_str = os.path.join(resolved_dir_str, d) if resolved_d_str in excluded_exact_set or resolved_d_str.startswith( excluded_prefix_strs ): diff --git a/tests/test_media_shrinker.py b/tests/test_media_shrinker.py index 1b202d2..e4e0e3d 100644 --- a/tests/test_media_shrinker.py +++ b/tests/test_media_shrinker.py @@ -201,6 +201,24 @@ def flaky_lstat(path): self.assertEqual(candidates, [Path("good.mp3")]) + def test_find_candidates_skips_symlinked_directories_outside_root(self) -> None: + with tempfile.TemporaryDirectory() as tmp, tempfile.TemporaryDirectory() as outside: + root = Path(tmp) + external = Path(outside) + (external / "secret.mp3").write_bytes(b"0" * 4) + link = root / "linked" + try: + link.symlink_to(external, target_is_directory=True) + except OSError as exc: + self.skipTest(f"symlink unavailable: {exc}") + + candidates = [ + p[0].relative_to(root) + for p in find_candidates(root, include_under_limit=True) + ] + + self.assertEqual(candidates, []) + class ProbeMediaTests(unittest.TestCase): @patch("media_shrinker.subprocess.run")