195 lines
4.8 KiB
Markdown
195 lines
4.8 KiB
Markdown
# Gitocean Implementation Plan
|
|
|
|
## Product decisions
|
|
|
|
- Build a Git repository hosting platform in Go.
|
|
- Store bare Git repositories under `storage/repos/{owner}/{repo}.git`.
|
|
- Use MySQL for metadata.
|
|
- Support HTTP Smart Git only. SSH is out of scope for MVP.
|
|
- Support CLI + API only. No web UI.
|
|
- Registration is open, but registration happens through the CLI/API only.
|
|
- Users register with email, username, and password.
|
|
- Users can log in with either email + password or username + password.
|
|
- Login returns a temporary auth token that expires after 7 days.
|
|
- The CLI stores this token locally for API calls and can approve it into Git's credential helper for Git HTTP operations.
|
|
- Repository names allow lowercase letters, numbers, `.`, `_`, and `-`.
|
|
- Usernames allow lowercase letters, numbers, `_`, and `-`.
|
|
- New repositories use `main` as the default branch.
|
|
- Pull request numbers are per target repository.
|
|
|
|
## Permissions
|
|
|
|
### Repository visibility
|
|
|
|
- `public`: anyone can clone/fetch. Only the owner can push/delete/manage.
|
|
- `private`: only the owner can clone/fetch/push/delete/manage.
|
|
|
|
### Writes
|
|
|
|
- MVP is owner-only.
|
|
- There are no collaborators, organizations, teams, or fine-grained permissions yet.
|
|
- Open collaboration is supported through pull requests against public repositories.
|
|
|
|
## Storage layout
|
|
|
|
```text
|
|
storage/
|
|
repos/
|
|
alice/
|
|
demo.git/
|
|
bob/
|
|
project.git/
|
|
```
|
|
|
|
Each repository directory is a bare Git repository.
|
|
|
|
## MySQL schema
|
|
|
|
Core tables:
|
|
|
|
- `users`
|
|
- id
|
|
- email
|
|
- username
|
|
- password_hash
|
|
- created_at
|
|
- `auth_tokens`
|
|
- id
|
|
- user_id
|
|
- token_hash
|
|
- expires_at
|
|
- revoked_at
|
|
- created_at
|
|
- `repositories`
|
|
- id
|
|
- owner_user_id
|
|
- name
|
|
- visibility: `public` or `private`
|
|
- forked_from_repository_id nullable
|
|
- created_at
|
|
- updated_at
|
|
- `pull_requests`
|
|
- id
|
|
- target_repository_id
|
|
- number
|
|
- author_user_id
|
|
- source_repository_id
|
|
- source_branch
|
|
- target_branch
|
|
- title
|
|
- description
|
|
- status: `open`, `closed`, or `merged`
|
|
- closed_at nullable
|
|
- merged_at nullable
|
|
- created_at
|
|
- updated_at
|
|
|
|
## API
|
|
|
|
### Auth
|
|
|
|
```http
|
|
POST /api/register
|
|
POST /api/login
|
|
POST /api/logout
|
|
GET /api/me
|
|
```
|
|
|
|
### Repositories
|
|
|
|
```http
|
|
POST /api/repos
|
|
GET /api/repos/search?q=demo&scope=all
|
|
GET /api/repos/search?q=demo&scope=mine
|
|
GET /api/repos/{owner}/{repo}
|
|
DELETE /api/repos/{owner}/{repo}?force=false
|
|
POST /api/repos/{owner}/{repo}/fork
|
|
```
|
|
|
|
### Pull requests
|
|
|
|
```http
|
|
POST /api/repos/{owner}/{repo}/pulls
|
|
GET /api/repos/{owner}/{repo}/pulls
|
|
GET /api/repos/{owner}/{repo}/pulls/{number}
|
|
POST /api/repos/{owner}/{repo}/pulls/{number}/close
|
|
POST /api/repos/{owner}/{repo}/pulls/{number}/merge
|
|
```
|
|
|
|
### Git HTTP
|
|
|
|
```http
|
|
/{owner}/{repo}.git/info/refs
|
|
/{owner}/{repo}.git/git-upload-pack
|
|
/{owner}/{repo}.git/git-receive-pack
|
|
```
|
|
|
|
## CLI commands
|
|
|
|
```bash
|
|
gitocean server --addr :8080 --dsn 'user:pass@tcp(127.0.0.1:3306)/gitocean?parseTime=true' --storage storage
|
|
|
|
gitocean register
|
|
gitocean login
|
|
gitocean logout
|
|
gitocean whoami
|
|
|
|
gitocean repo create NAME --public
|
|
gitocean repo create NAME --private
|
|
gitocean repo delete OWNER/NAME [--force]
|
|
gitocean repo search QUERY --all
|
|
gitocean repo search QUERY --mine
|
|
gitocean repo fork OWNER/NAME [--name NEW_NAME]
|
|
|
|
gitocean clone OWNER/NAME
|
|
|
|
gitocean pr create --from OWNER/REPO:BRANCH --to OWNER/REPO:BRANCH --title TITLE --description DESC
|
|
gitocean pr create --repo OWNER/REPO --from BRANCH --to BRANCH --title TITLE --description DESC
|
|
gitocean pr list OWNER/REPO
|
|
gitocean pr view OWNER/REPO NUMBER
|
|
gitocean pr close OWNER/REPO NUMBER
|
|
gitocean pr merge OWNER/REPO NUMBER
|
|
```
|
|
|
|
## Pull request rules
|
|
|
|
### Same-repository PRs
|
|
|
|
- Source and target repository are the same.
|
|
- Only the repository owner can create same-repo PRs.
|
|
- Source and target branches must both exist.
|
|
|
|
### Cross-repository PRs
|
|
|
|
- Source repository branch points to target repository branch.
|
|
- Source repository must be owned by the PR author.
|
|
- Target repository must be public, unless the author is also the target owner.
|
|
- Source and target branches must both exist.
|
|
- Only the target repository owner can close or merge the PR.
|
|
|
|
## Merge behavior
|
|
|
|
MVP merge mode is a normal merge commit:
|
|
|
|
1. Clone target repo into a temporary worktree.
|
|
2. Checkout target branch.
|
|
3. Add/fetch source repo branch.
|
|
4. Run `git merge --no-ff FETCH_HEAD`.
|
|
5. Push the result back to the target branch.
|
|
6. Mark PR as merged.
|
|
|
|
If conflicts occur, return an error and keep the PR open.
|
|
|
|
## Implementation milestones
|
|
|
|
1. Project scaffold and build setup.
|
|
2. MySQL migrations.
|
|
3. User registration, login, logout, and token auth.
|
|
4. Repository create, delete, detail, search.
|
|
5. HTTP Smart Git integration using `git http-backend`.
|
|
6. CLI auth and repository commands.
|
|
7. Fork support.
|
|
8. Pull request create/list/view/close.
|
|
9. Pull request merge.
|
|
10. Tests, hardening, and UX polish.
|