main / internal/app/repo_service.go
2.0 KB · Go Raw
1package app
2
3import (
4 "context"
5 "fmt"
6 "regexp"
7 "strings"
8
9 "gitgud/internal/domain"
10)
11
12var repoNameRe = regexp.MustCompile(`^[a-z0-9][a-z0-9-_.]{0,99}$`)
13
14type RepoService struct {
15 repos domain.RepositoryRepository
16 git domain.GitService
17}
18
19func NewRepoService(repos domain.RepositoryRepository, git domain.GitService) *RepoService {
20 return &RepoService{repos: repos, git: git}
21}
22
23func (s *RepoService) CreateRepo(ctx context.Context, owner *domain.User, name, description string, private bool) (*domain.Repository, error) {
24 name = strings.ToLower(strings.TrimSpace(name))
25 if name == "." || name == ".." || !repoNameRe.MatchString(name) {
26 return nil, fmt.Errorf("name must be 1-100 chars of a-z, 0-9, -, _ or . and start with a letter or number: %w", domain.ErrValidation)
27 }
28
29 repo := &domain.Repository{
30 OwnerID: owner.ID,
31 OwnerName: owner.Username,
32 Name: name,
33 Description: strings.TrimSpace(description),
34 IsPrivate: private,
35 DefaultBranch: "main",
36 }
37
38 if err := s.repos.Create(ctx, repo); err != nil {
39 return nil, err
40 }
41
42 if err := s.git.InitBare(ctx, owner.Username, name, repo.DefaultBranch); err != nil {
43 _ = s.repos.Delete(ctx, repo.ID)
44 return nil, fmt.Errorf("init repository on disk: %w", err)
45 }
46
47 return repo, nil
48}
49
50func (s *RepoService) Get(ctx context.Context, owner, name string) (*domain.Repository, error) {
51 return s.repos.ByOwnerAndName(ctx, owner, name)
52}
53
54func (s *RepoService) ListByOwner(ctx context.Context, ownerID int64) ([]*domain.Repository, error) {
55 return s.repos.ListByOwner(ctx, ownerID)
56}
57
58func (s *RepoService) ListPublic(ctx context.Context) ([]*domain.Repository, error) {
59 return s.repos.ListPublic(ctx)
60}
61
62func CanView(repo *domain.Repository, viewer *domain.User) error {
63 if !repo.IsPrivate {
64 return nil
65 }
66 if viewer != nil && viewer.ID == repo.OwnerID {
67 return nil
68 }
69 return domain.ErrNotFound
70}
71
72func CanPush(repo *domain.Repository, viewer *domain.User) bool {
73 return viewer != nil && viewer.ID == repo.OwnerID
74}