fix(flake): handle file paths with line numbers in cache existence check

The is_cached method now correctly handles store paths that have line
numbers appended (e.g., /nix/store/file.nix:123:456). Previously, these
paths would fail the existence check because the exact path with line
numbers doesn't exist as a file.

The fix adds a helper method that:
- First checks if the exact path exists
- If not, and the path contains colons, validates that the suffix
  consists only of numbers (line:column format)
- If valid, strips the line numbers and checks the base file path

This ensures that cached references to specific file locations are
properly validated while avoiding false positives with files that
have colons in their names.
This commit is contained in:
lassulus
2025-07-04 14:35:33 +02:00
parent 76af63ee1c
commit bd82de6001
2 changed files with 97 additions and 2 deletions

View File

@@ -345,6 +345,23 @@ class FlakeCacheEntry:
msg = f"Cannot insert {value} into cache, already have {self.value}"
raise TypeError(msg)
def _check_path_exists(self, path_str: str) -> bool:
"""Check if a path exists, handling potential line number suffixes."""
path = Path(path_str)
if path.exists():
return True
# Try stripping line numbers if the path doesn't exist
# Handle format: /path/to/file:123 or /path/to/file:123:456
if ":" in path_str:
parts = path_str.split(":")
if len(parts) >= 2:
# Check if all parts after the first colon are numbers
if all(part.isdigit() for part in parts[1:]):
base_path = parts[0]
return Path(base_path).exists()
return False
def is_cached(self, selectors: list[Selector]) -> bool:
selector: Selector
@@ -353,12 +370,12 @@ class FlakeCacheEntry:
# Check if it's a regular nix store path
nix_store_dir = os.environ.get("NIX_STORE_DIR", "/nix/store")
if self.value.startswith(nix_store_dir):
return Path(self.value).exists()
return self._check_path_exists(self.value)
# Check if it's a test store path
test_store = os.environ.get("CLAN_TEST_STORE")
if test_store and self.value.startswith(test_store):
return Path(self.value).exists()
return self._check_path_exists(self.value)
# if self.value is not dict but we request more selectors, we assume we are cached and an error will be thrown in the select function
if isinstance(self.value, str | float | int | None):