# apps/api/src/api/project
dir: apps/api/src/api/project

index: apps/api/src/api/project/.pi-map.index.md

## role
Provides FastAPI REST API endpoints for project and Git repository management, serving as the HTTP interface layer for the project's core domain operations.
## files
- __init__.py | Aggregates and exports project-related API routers from submodules. | dep: src.api.project.git_repositories, src.api.project.projects
- git_repositories.py | Implements FastAPI REST endpoints for managing Git repositories, including CRUD operations, SSH key management, file browsing, branch operations, and git commands (clone, commit, push, pull, merge, etc.) for both project-scoped and external repositories. | exp: func:_get_repo(session: AsyncSession, user_id: uuid.UUID, project_id: uuid.UUID, repo_id: uuid.UUID) → GitRepository, call:_get_user, call:_get_owned_project, call:session.get, raise:HTTPException, func:_get_repo_on_disk(session: AsyncSession, user_id: uuid.UUID, project_id: uuid.UUID, repo_id: uuid.UUID) → GitRepository, call:_get_repo, call:os.path.exists, raise:HTTPException, func:_parse_remote_url(remote_url: str | None, force_original: bool) → str | None, call:parse_git_url, call:parse_result.get, raise:HTTPException, func:_commit_author(session: AsyncSession, user_id: uuid.UUID) → tuple[str, str], call:_get_user, func:list_user_repositories(user_id, session) → list[GitRepository], call:session.execute, call:select(GitRepository).where, call:list, call:result.scalars().all, func:parse_repository_url(data: URLParseRequest) → URLParseResponse, call:URLParseResponse, call:parse_git_url, func:create_external_repository(data: GitRepositoryCreate, user_id, session) → GitRepository, call:_get_user, call:session.execute, call:select(GitRepository).where, call:GitRepository.project_id.is_, call:existing.scalar_one_or_none, call:_parse_remote_url, call:uuid.UUID, call:session.get, call:preflight_remote_repository, call:session.add, call:session.flush, call:clone_working_repository, call:session.rollback, call:init_working_repository, call:session.commit, raise:HTTPException, func:list_repositories(project_id: uuid.UUID, user_id, session) → list[GitRepository], call:_get_user, call:_get_owned_project, call:session.execute, call:select(GitRepository).where, call:list, call:result.scalars().all, func:delete_repository(project_id: uuid.UUID, repo_id: uuid.UUID, user_id, session) → Response, call:_get_repo, call:os.path.exists, call:shutil.rmtree, call:session.delete, call:session.commit, call:Response, func:create_repository(project_id: uuid.UUID, data: GitRepositoryCreate, user_id, session) → GitRepository, call:_get_user, call:_get_owned_project, call:session.execute, call:select(GitRepository).where, call:existing.scalar_one_or_none, call:_parse_remote_url, call:uuid.UUID, call:session.get, call:preflight_remote_repository, call:get_repo_path, call:os.makedirs, call:os.path.dirname, call:clone_working_repository, call:init_working_repository, call:GitRepository, call:session.add, call:session.commit, call:session.refresh, raise:HTTPException, func:update_repository_ssh_key(project_id: uuid.UUID, repo_id: uuid.UUID, data: UpdateSSHKeyRequest, user_id, session) → GitRepository, call:_get_repo, call:uuid.UUID, call:session.get, call:session.commit, call:session.refresh, raise:HTTPException, func:get_repository_history(project_id: uuid.UUID, repo_id: uuid.UUID, view, branch, limit, offset, user_id, session) → dict, call:_get_repo_on_disk, call:get_commit_history, raise:HTTPException, func:get_repository_commit(project_id: uuid.UUID, repo_id: uuid.UUID, commit_hash: str, user_id, session) → dict, call:_get_repo_on_disk, call:get_commit_detail, raise:HTTPException, func:list_repository_files(project_id: uuid.UUID, repo_id: uuid.UUID, branch, path, user_id, session) → FileListResponse, call:_get_repo_on_disk, call:list_tree, call:FileListResponse, call:logger.error, call:str, raise:HTTPException, func:get_repository_file_content(project_id: uuid.UUID, repo_id: uuid.UUID, branch: str, path: str, user_id, session) → FileContentResponse, call:_get_repo_on_disk, call:get_file_content, call:FileContentResponse, raise:HTTPException, func:get_repository_branches(project_id: uuid.UUID, repo_id: uuid.UUID, user_id, session) → BranchesResponse, call:_get_repo, call:os.path.isdir, call:os.path.join, call:os.path.isfile, call:list_branches, call:BranchesResponse, call:logger.error, call:str, call:session.get, call:list_remote_branches, raise:HTTPException, func:update_repository_file(project_id: uuid.UUID, repo_id: uuid.UUID, data: FileUpdateRequest, user_id, session) → FileUpdateResponse, call:_get_repo_on_disk, call:_commit_author, call:commit_file, call:FileUpdateResponse, raise:HTTPException, func:get_repository_status(project_id: uuid.UUID, repo_id: uuid.UUID, user_id, session) → StatusResponse, call:_get_repo_on_disk, call:get_status, call:StatusResponse, raise:HTTPException, func:create_repository_branch(project_id: uuid.UUID, repo_id: uuid.UUID, data: BranchCreateRequest, user_id, session) → dict, call:_get_repo_on_disk, call:create_branch, raise:HTTPException, func:delete_repository_branch(project_id: uuid.UUID, repo_id: uuid.UUID, branch_name: str, force, user_id, session) → dict, call:_get_repo_on_disk, call:delete_branch, raise:HTTPException, func:checkout_repository_branch(project_id: uuid.UUID, repo_id: uuid.UUID, data: CheckoutRequest, user_id, session) → dict, call:_get_repo_on_disk, call:checkout_branch, raise:HTTPException, func:commit_repository_changes(project_id: uuid.UUID, repo_id: uuid.UUID, data: CommitRequest, user_id, session) → CommitResponse, call:_get_repo_on_disk, call:_commit_author, call:commit_changes, call:CommitResponse, raise:HTTPException, func:fetch_repository(project_id: uuid.UUID, repo_id: uuid.UUID, user_id, session) → FetchResponse, call:_get_repo_on_disk, call:fetch, call:FetchResponse, raise:HTTPException, func:pull_repository(project_id: uuid.UUID, repo_id: uuid.UUID, branch, user_id, session) → PullResponse, call:_get_repo_on_disk, call:pull, call:PullResponse, raise:HTTPException, func:push_repository(project_id: uuid.UUID, repo_id: uuid.UUID, branch, user_id, session) → PushResponse, call:_get_repo_on_disk, call:push, call:PushResponse, raise:HTTPException, func:merge_repository_branches(project_id: uuid.UUID, repo_id: uuid.UUID, data: MergeRequest, user_id, session) → MergeResponse, call:_get_repo_on_disk, call:merge, call:MergeResponse, raise:HTTPException | dep: logging, os, shutil, uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.schemas.project.git_repository, src.services.git.operations, src.utils.git_control, src.utils.git_files, src.utils.git_history, src.utils.git_url_parser
- projects.py | Implements FastAPI REST endpoints for CRUD operations on projects, including nested repository/workspace listing and filesystem cleanup on deletion. | exp: func:create_project(data: ProjectCreate, user_id, session) → Project, call:_get_user, call:Project, call:session.add, call:session.commit, call:session.refresh, func:list_projects(user_id, session) → list[dict], call:_get_user, call:session.execute, call:select(Project) .where(Project.owner_id == user.id) .order_by, call:Project.created_at.desc, call:result.scalars().all, call:select(GitRepository).where, call:repos_result.scalars().all, call:select(Workspace).where, call:ws_result.scalars().all, call:select(func.count()).where, call:func.count, call:inst_result.scalar, call:workspaces.append, call:str, call:repositories.append, call:enriched.append, call:project.created_at.isoformat, func:get_project(project_id: uuid.UUID, user_id, session) → Project, call:_get_user, call:_get_owned_project, func:update_project(project_id: uuid.UUID, data: ProjectUpdate, user_id, session) → Project, call:_get_user, call:_get_owned_project, call:session.commit, call:session.refresh, func:delete_project(project_id: uuid.UUID, user_id, session) → Response, call:_get_user, call:_get_owned_project, call:session.execute, call:select(GitRepository).where, call:result.scalars().all, call:os.path.exists, call:shutil.rmtree, call:session.delete, call:session.commit, call:Response, func:set_default_ssh_key(project_id: uuid.UUID, data: SetDefaultSSHKeyRequest, user_id, session) → Project, call:_get_user, call:_get_owned_project, call:session.get, call:session.commit, call:session.refresh, raise:HTTPException | dep: os, shutil, uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.models.project, src.schemas.project
## arch
Modular router-based architecture using FastAPI with separate modules for distinct resource domains (projects vs. git repositories), each implementing full CRUD plus specialized operations, aggregated via __init__.py for centralized router registration.
## tags
get, call:, repository, raise:httpexception, repo, on, disk, project
## symbols
- _get_repo
- _get_repo_on_disk
- _parse_remote_url
- _commit_author
- list_user_repositories
- parse_repository_url
- create_external_repository
- list_repositories
## workflows
- change project behavior
  read: __init__.py, git_repositories.py, projects.py
## dirty
-
