Skip to content

Commit b46401e

Browse files
committed
feat: add DELETE /repos/{repo_id} endpoint
Bug fix: Settings page 'Delete All' was calling non-existent endpoint Backend: - Add DELETE /repos/{repo_id} route with ownership verification - Add repo_manager.delete_repo() method that: - Deletes from Supabase (cascades to embeddings, dependencies) - Cleans up local clone directory - Removes from in-memory cache This completes the Settings page danger zone functionality.
1 parent 61ae5b3 commit b46401e

2 files changed

Lines changed: 56 additions & 0 deletions

File tree

backend/routes/repos.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,35 @@ async def add_repository(
146146
raise HTTPException(status_code=400, detail=str(e))
147147

148148

149+
@router.delete("/{repo_id}")
150+
async def delete_repository(
151+
repo_id: str,
152+
auth: AuthContext = Depends(require_auth)
153+
):
154+
"""Delete a repository and all its indexed data."""
155+
user_id = auth.user_id
156+
157+
if not user_id:
158+
raise HTTPException(status_code=401, detail="User ID required")
159+
160+
# Verify ownership
161+
repo = get_repo_or_404(repo_id, user_id)
162+
163+
try:
164+
success = repo_manager.delete_repo(repo_id)
165+
if not success:
166+
raise HTTPException(status_code=500, detail="Failed to delete repository")
167+
168+
logger.info("Repository deleted", repo_id=repo_id, user_id=user_id)
169+
return {"message": "Repository deleted successfully"}
170+
except HTTPException:
171+
raise
172+
except Exception as e:
173+
logger.error("Failed to delete repository", repo_id=repo_id, error=str(e))
174+
capture_exception(e)
175+
raise HTTPException(status_code=500, detail=str(e))
176+
177+
149178
@router.post("/{repo_id}/index")
150179
async def index_repository(
151180
repo_id: str,

backend/services/repo_manager.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,30 @@ def get_last_indexed_commit(self, repo_id: str) -> str:
156156
def update_last_commit(self, repo_id: str, commit_sha: str, function_count: int = 0):
157157
"""Update last indexed commit"""
158158
self.db.update_last_indexed(repo_id, commit_sha, function_count)
159+
160+
def delete_repo(self, repo_id: str) -> bool:
161+
"""Delete repository and clean up local files"""
162+
import shutil
163+
164+
repo = self.get_repo(repo_id)
165+
if not repo:
166+
return False
167+
168+
# Delete from database (cascades to embeddings, dependencies, etc.)
169+
self.db.delete_repository(repo_id)
170+
171+
# Clean up local clone if it exists
172+
local_path = repo.get("local_path")
173+
if local_path and Path(local_path).exists():
174+
try:
175+
shutil.rmtree(local_path)
176+
logger.info("Deleted local repo files", repo_id=repo_id, path=local_path)
177+
except Exception as e:
178+
logger.warning("Failed to delete local files", repo_id=repo_id, error=str(e))
179+
180+
# Remove from in-memory cache
181+
if repo_id in self.repos:
182+
del self.repos[repo_id]
183+
184+
logger.info("Deleted repository", repo_id=repo_id)
185+
return True

0 commit comments

Comments
 (0)