Skip to content

Commit d9161e7

Browse files
authored
Merge branch 'main' into optimize-tracer-replay
2 parents 4e84286 + f828b1c commit d9161e7

3 files changed

Lines changed: 25 additions & 6 deletions

File tree

codeflash/code_utils/git_worktree_utils.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
from __future__ import annotations
22

33
import configparser
4+
import shutil
5+
import stat
46
import subprocess
57
import tempfile
68
import time
79
from pathlib import Path
8-
from typing import Optional
10+
from typing import Any, Callable, Optional
911

1012
import git
1113

@@ -95,10 +97,24 @@ def create_detached_worktree(module_root: Path) -> Optional[Path]:
9597
return worktree_dir
9698

9799

100+
def _handle_remove_readonly(
101+
func: Callable[[str], None], path: str, exc_info: tuple[type[BaseException], BaseException, Any]
102+
) -> None:
103+
"""Error handler for shutil.rmtree to handle read-only files on Windows."""
104+
if isinstance(exc_info[1], PermissionError):
105+
Path(path).chmod(stat.S_IWUSR | stat.S_IRUSR | stat.S_IXUSR)
106+
func(path)
107+
else:
108+
raise exc_info[1]
109+
110+
98111
def remove_worktree(worktree_dir: Path) -> None:
112+
"""Remove a git worktree directory."""
113+
if not worktree_dir.exists():
114+
return
99115
try:
100-
repository = git.Repo(worktree_dir, search_parent_directories=True)
101-
repository.git.worktree("remove", "--force", worktree_dir)
116+
shutil.rmtree(worktree_dir, onerror=_handle_remove_readonly)
117+
logger.debug(f"Removed worktree: {worktree_dir}")
102118
except Exception:
103119
logger.exception(f"Failed to remove worktree: {worktree_dir}")
104120

codeflash/lsp/helpers.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import os
22
import re
33
from functools import lru_cache
4+
from pathlib import Path
45

56
from rich.tree import Tree
67

78
from codeflash.models.test_type import TestType
89

910
_double_quote_pat = re.compile(r'"(.*?)"')
1011
_single_quote_pat = re.compile(r"'(.*?)'")
11-
worktree_path_regex = re.compile(r'\/[^"]*worktrees\/[^"]\S*')
12+
# Match worktree paths on both Unix (/path/to/worktrees/...) and Windows (C:\path\to\worktrees\... or C:/path/to/worktrees/...)
13+
worktree_path_regex = re.compile(r'[^"]*worktrees[\\/][^"]\S*')
1214

1315

1416
@lru_cache(maxsize=1)
@@ -47,7 +49,8 @@ def report_to_markdown_table(report: dict[TestType, dict[str, int]], title: str)
4749
def simplify_worktree_paths(msg: str, highlight: bool = True) -> str: # noqa: FBT001, FBT002
4850
path_in_msg = worktree_path_regex.search(msg)
4951
if path_in_msg:
50-
last_part_of_path = path_in_msg.group(0).split("/")[-1]
52+
# Use Path.name to handle both Unix and Windows path separators
53+
last_part_of_path = Path(path_in_msg.group(0)).name
5154
if highlight:
5255
last_part_of_path = f"`{last_part_of_path}`"
5356
return msg.replace(path_in_msg.group(0), last_part_of_path)

codeflash/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# These version placeholders will be replaced by uv-dynamic-versioning during build.
2-
__version__ = "0.19.0"
2+
__version__ = "0.19.1"

0 commit comments

Comments
 (0)