-
-
Notifications
You must be signed in to change notification settings - Fork 777
feat: add UI configuration for custom worktree location #456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
sbeardsley
wants to merge
8
commits into
AndyMik90:develop
Choose a base branch
from
sbeardsley:feature/worktree-ui-config
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+392
−88
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
33d736d
feat: add UI configuration for custom worktree location
sbeardsley d19b159
fix: use browser-compatible path utilities in WorktreeSettings
sbeardsley 87f2aa8
fix: load project .env file and use WORKTREE_BASE_PATH in WorktreeMan…
sbeardsley efbbc38
Merge upstream develop into feature/worktree-ui-config
sbeardsley 4f35d76
refactor: address PR review feedback
sbeardsley 93f507a
Merge remote-tracking branch 'upstream/develop' into feature/worktree…
sbeardsley dd24545
docs: enhance docstrings in config.py to improve coverage
sbeardsley 432bd64
refactor: improve path validation and move imports to module level
sbeardsley File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| """ | ||
| Core configuration for Auto Claude. | ||
|
|
||
| This module provides centralized configuration management for Auto Claude, | ||
| including worktree path resolution and validation. It ensures consistent | ||
| configuration access across the entire backend codebase. | ||
|
|
||
| Constants: | ||
| WORKTREE_BASE_PATH_VAR (str): Environment variable name for custom worktree base path. | ||
| DEFAULT_WORKTREE_PATH (str): Default worktree directory name relative to project root. | ||
|
|
||
| Example: | ||
| >>> from core.config import get_worktree_base_path | ||
| >>> from pathlib import Path | ||
| >>> | ||
| >>> # Get worktree path with validation | ||
| >>> project_dir = Path("/path/to/project") | ||
| >>> worktree_path = get_worktree_base_path(project_dir) | ||
| >>> full_path = project_dir / worktree_path | ||
| """ | ||
|
|
||
| import os | ||
| from pathlib import Path | ||
|
|
||
| # Environment variable names | ||
| WORKTREE_BASE_PATH_VAR = "WORKTREE_BASE_PATH" | ||
| """str: Environment variable name for configuring custom worktree base path. | ||
|
|
||
| Users can set this environment variable in their project's .env file to specify | ||
| a custom location for worktree directories, supporting both relative and absolute paths. | ||
| """ | ||
|
|
||
| # Default values | ||
| DEFAULT_WORKTREE_PATH = ".worktrees" | ||
| """str: Default worktree directory name. | ||
|
|
||
| This is the fallback value used when WORKTREE_BASE_PATH is not set or when | ||
| validation fails (e.g., path points to .auto-claude/ or .git/ directories). | ||
| """ | ||
|
|
||
|
|
||
| def get_worktree_base_path(project_dir: Path | None = None) -> str: | ||
| """ | ||
| Get the worktree base path from environment variables with security validation. | ||
|
|
||
| This function reads the WORKTREE_BASE_PATH environment variable and validates | ||
| it to prevent security issues. It supports both relative and absolute paths, | ||
| enabling users to place worktrees on external drives or temporary directories. | ||
|
|
||
| Supported path types: | ||
| - Relative paths: 'worktrees', '.cache/worktrees', '../shared-worktrees' | ||
| - Absolute paths: '/tmp/worktrees', '/Volumes/FastSSD/worktrees', 'C:\\worktrees' | ||
|
|
||
| Security validations: | ||
| - Prevents paths inside .auto-claude/ directory (avoids data loss during cleanup) | ||
| - Prevents paths inside .git/ directory (avoids repository corruption) | ||
| - Falls back to DEFAULT_WORKTREE_PATH if validation fails | ||
|
|
||
| Args: | ||
| project_dir (Path | None): Project root directory for full validation. | ||
| If None, only basic pattern validation is performed (checks for | ||
| .auto-claude and .git in path string). If provided, performs | ||
| full path resolution and validation. | ||
|
|
||
| Returns: | ||
| str: The validated worktree base path string. Returns DEFAULT_WORKTREE_PATH | ||
| ('.worktrees') if the configured path is invalid or dangerous. | ||
|
|
||
| Examples: | ||
| >>> # Basic usage without validation | ||
| >>> path = get_worktree_base_path() | ||
| >>> print(path) | ||
| '.worktrees' | ||
|
|
||
| >>> # Full validation with project directory | ||
| >>> from pathlib import Path | ||
| >>> project = Path("/home/user/my-project") | ||
| >>> path = get_worktree_base_path(project) | ||
| >>> full_path = project / path | ||
|
|
||
| >>> # With WORKTREE_BASE_PATH="/tmp/worktrees" in environment | ||
| >>> os.environ['WORKTREE_BASE_PATH'] = '/tmp/worktrees' | ||
| >>> path = get_worktree_base_path(project) | ||
| >>> print(path) | ||
| '/tmp/worktrees' | ||
|
|
||
| Note: | ||
| The function intentionally allows absolute paths outside the project | ||
| directory to support use cases like external drives or shared build | ||
| directories. This is a design decision, not a security flaw. | ||
| """ | ||
| worktree_base_path = os.getenv(WORKTREE_BASE_PATH_VAR, DEFAULT_WORKTREE_PATH) | ||
|
|
||
| # If no project_dir provided, return as-is (basic validation only) | ||
| if not project_dir: | ||
| # Check for .auto-claude or .git as path components, not substrings | ||
| parts = set(Path(worktree_base_path).parts) | ||
| if ".auto-claude" in parts or ".git" in parts: | ||
| return DEFAULT_WORKTREE_PATH | ||
| return worktree_base_path | ||
|
|
||
| # Resolve the absolute path | ||
| if Path(worktree_base_path).is_absolute(): | ||
| resolved = Path(worktree_base_path).resolve() | ||
| else: | ||
| resolved = (project_dir / worktree_base_path).resolve() | ||
|
|
||
| # Prevent paths inside .auto-claude/ or .git/ | ||
| auto_claude_dir = (project_dir / ".auto-claude").resolve() | ||
| git_dir = (project_dir / ".git").resolve() | ||
|
|
||
| resolved_str = str(resolved) | ||
| if resolved_str.startswith(str(auto_claude_dir)) or resolved_str.startswith( | ||
| str(git_dir) | ||
| ): | ||
| return DEFAULT_WORKTREE_PATH | ||
|
|
||
| return worktree_base_path | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix security check to avoid false positives for similar directory names.
The
startswithcheck on string paths creates false positives. For example:/project/.auto-claude-backupwould incorrectly match/project/.auto-claude/project/.git-hookswould incorrectly match/project/.gitUse
Path.is_relative_to()(available since Python 3.9, compatible with the Python 3.12+ requirement) to check true parent-child relationships.🔎 Use Path.is_relative_to() for accurate directory containment checks
# Prevent paths inside .auto-claude/ or .git/ auto_claude_dir = (project_dir / ".auto-claude").resolve() git_dir = (project_dir / ".git").resolve() - resolved_str = str(resolved) - if resolved_str.startswith(str(auto_claude_dir)) or resolved_str.startswith( - str(git_dir) - ): + if resolved.is_relative_to(auto_claude_dir) or resolved.is_relative_to(git_dir): return DEFAULT_WORKTREE_PATH return worktree_base_path📝 Committable suggestion
🤖 Prompt for AI Agents