fix: detect project directory correctly for git remote parsing #71
@@ -51,11 +51,15 @@ class GiteaConfig:
|
|||||||
"cat > ~/.config/claude/gitea.env"
|
"cat > ~/.config/claude/gitea.env"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Find project directory (MCP server cwd is plugin dir, not project dir)
|
||||||
|
project_dir = self._find_project_directory()
|
||||||
|
|
||||||
# Load project config (overrides system)
|
# Load project config (overrides system)
|
||||||
project_config = Path.cwd() / '.env'
|
if project_dir:
|
||||||
if project_config.exists():
|
project_config = project_dir / '.env'
|
||||||
load_dotenv(project_config, override=True)
|
if project_config.exists():
|
||||||
logger.info(f"Loaded project configuration from {project_config}")
|
load_dotenv(project_config, override=True)
|
||||||
|
logger.info(f"Loaded project configuration from {project_config}")
|
||||||
|
|
||||||
# Extract values
|
# Extract values
|
||||||
self.api_url = os.getenv('GITEA_API_URL')
|
self.api_url = os.getenv('GITEA_API_URL')
|
||||||
@@ -63,8 +67,8 @@ class GiteaConfig:
|
|||||||
self.repo = os.getenv('GITEA_REPO') # Optional, must be owner/repo format
|
self.repo = os.getenv('GITEA_REPO') # Optional, must be owner/repo format
|
||||||
|
|
||||||
# Auto-detect repo from git remote if not specified
|
# Auto-detect repo from git remote if not specified
|
||||||
if not self.repo:
|
if not self.repo and project_dir:
|
||||||
self.repo = self._detect_repo_from_git()
|
self.repo = self._detect_repo_from_git(project_dir)
|
||||||
if self.repo:
|
if self.repo:
|
||||||
logger.info(f"Auto-detected repository from git remote: {self.repo}")
|
logger.info(f"Auto-detected repository from git remote: {self.repo}")
|
||||||
|
|
||||||
@@ -106,10 +110,57 @@ class GiteaConfig:
|
|||||||
"Check your ~/.config/claude/gitea.env file"
|
"Check your ~/.config/claude/gitea.env file"
|
||||||
)
|
)
|
||||||
|
|
||||||
def _detect_repo_from_git(self) -> Optional[str]:
|
def _find_project_directory(self) -> Optional[Path]:
|
||||||
|
"""
|
||||||
|
Find the user's project directory.
|
||||||
|
|
||||||
|
The MCP server runs with cwd set to the plugin directory, not the
|
||||||
|
user's project. We need to find the actual project directory using
|
||||||
|
various heuristics.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Path to project directory, or None if not found
|
||||||
|
"""
|
||||||
|
# Strategy 1: Check CLAUDE_PROJECT_DIR environment variable
|
||||||
|
project_dir = os.getenv('CLAUDE_PROJECT_DIR')
|
||||||
|
if project_dir:
|
||||||
|
path = Path(project_dir)
|
||||||
|
if path.exists():
|
||||||
|
logger.info(f"Found project directory from CLAUDE_PROJECT_DIR: {path}")
|
||||||
|
return path
|
||||||
|
|
||||||
|
# Strategy 2: Check PWD (original working directory before cwd override)
|
||||||
|
pwd = os.getenv('PWD')
|
||||||
|
if pwd:
|
||||||
|
path = Path(pwd)
|
||||||
|
# Verify it has .git or .env (indicates a project)
|
||||||
|
if path.exists() and ((path / '.git').exists() or (path / '.env').exists()):
|
||||||
|
logger.info(f"Found project directory from PWD: {path}")
|
||||||
|
return path
|
||||||
|
|
||||||
|
# Strategy 3: Check current working directory
|
||||||
|
# This handles test scenarios and cases where cwd is actually the project
|
||||||
|
cwd = Path.cwd()
|
||||||
|
if (cwd / '.git').exists() or (cwd / '.env').exists():
|
||||||
|
logger.info(f"Found project directory from cwd: {cwd}")
|
||||||
|
return cwd
|
||||||
|
|
||||||
|
# Strategy 4: Check if GITEA_REPO is already set (user configured it)
|
||||||
|
# If so, we don't need to find the project directory for git detection
|
||||||
|
if os.getenv('GITEA_REPO'):
|
||||||
|
logger.debug("GITEA_REPO already set, skipping project directory detection")
|
||||||
|
return None
|
||||||
|
|
||||||
|
logger.debug("Could not determine project directory")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _detect_repo_from_git(self, project_dir: Optional[Path] = None) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Auto-detect repository from git remote origin URL.
|
Auto-detect repository from git remote origin URL.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
project_dir: Directory to run git command from (defaults to cwd)
|
||||||
|
|
||||||
Supports URL formats:
|
Supports URL formats:
|
||||||
- SSH: ssh://git@host:port/owner/repo.git
|
- SSH: ssh://git@host:port/owner/repo.git
|
||||||
- SSH short: git@host:owner/repo.git
|
- SSH short: git@host:owner/repo.git
|
||||||
@@ -124,7 +175,8 @@ class GiteaConfig:
|
|||||||
['git', 'remote', 'get-url', 'origin'],
|
['git', 'remote', 'get-url', 'origin'],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
timeout=5
|
timeout=5,
|
||||||
|
cwd=str(project_dir) if project_dir else None
|
||||||
)
|
)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
logger.debug("No git remote 'origin' found")
|
logger.debug("No git remote 'origin' found")
|
||||||
|
|||||||
@@ -211,3 +211,50 @@ def test_parse_git_url_invalid_format():
|
|||||||
url = "not-a-valid-url"
|
url = "not-a-valid-url"
|
||||||
result = config._parse_git_url(url)
|
result = config._parse_git_url(url)
|
||||||
assert result is None
|
assert result is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_find_project_directory_from_env(tmp_path, monkeypatch):
|
||||||
|
"""Test finding project directory from CLAUDE_PROJECT_DIR env var"""
|
||||||
|
project_dir = tmp_path / 'my-project'
|
||||||
|
project_dir.mkdir()
|
||||||
|
(project_dir / '.git').mkdir()
|
||||||
|
|
||||||
|
monkeypatch.setenv('CLAUDE_PROJECT_DIR', str(project_dir))
|
||||||
|
|
||||||
|
config = GiteaConfig()
|
||||||
|
result = config._find_project_directory()
|
||||||
|
|
||||||
|
assert result == project_dir
|
||||||
|
|
||||||
|
|
||||||
|
def test_find_project_directory_from_cwd(tmp_path, monkeypatch):
|
||||||
|
"""Test finding project directory from cwd with .env file"""
|
||||||
|
project_dir = tmp_path / 'project'
|
||||||
|
project_dir.mkdir()
|
||||||
|
(project_dir / '.env').write_text("GITEA_REPO=test/repo")
|
||||||
|
|
||||||
|
monkeypatch.chdir(project_dir)
|
||||||
|
# Clear env vars that might interfere
|
||||||
|
monkeypatch.delenv('CLAUDE_PROJECT_DIR', raising=False)
|
||||||
|
monkeypatch.delenv('PWD', raising=False)
|
||||||
|
|
||||||
|
config = GiteaConfig()
|
||||||
|
result = config._find_project_directory()
|
||||||
|
|
||||||
|
assert result == project_dir
|
||||||
|
|
||||||
|
|
||||||
|
def test_find_project_directory_none_when_no_markers(tmp_path, monkeypatch):
|
||||||
|
"""Test returns None when no project markers found"""
|
||||||
|
empty_dir = tmp_path / 'empty'
|
||||||
|
empty_dir.mkdir()
|
||||||
|
|
||||||
|
monkeypatch.chdir(empty_dir)
|
||||||
|
monkeypatch.delenv('CLAUDE_PROJECT_DIR', raising=False)
|
||||||
|
monkeypatch.delenv('PWD', raising=False)
|
||||||
|
monkeypatch.delenv('GITEA_REPO', raising=False)
|
||||||
|
|
||||||
|
config = GiteaConfig()
|
||||||
|
result = config._find_project_directory()
|
||||||
|
|
||||||
|
assert result is None
|
||||||
|
|||||||
Reference in New Issue
Block a user