ikurotime / gitgud

public
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}