cerrado @ 519af559f94aab1bd1446cc01144cbf2640fcc6a

  1package service
  2
  3import (
  4	"errors"
  5	"log/slog"
  6
  7	"git.gabrielgio.me/cerrado/pkg/config"
  8	"git.gabrielgio.me/cerrado/pkg/git"
  9	"github.com/go-git/go-git/v5/plumbing"
 10	"github.com/go-git/go-git/v5/plumbing/object"
 11)
 12
 13type (
 14	Repository struct {
 15		Name           string
 16		Description    string
 17		LastCommitDate string
 18		Ref            string
 19	}
 20
 21	GitService struct {
 22		configRepo configurationRepository
 23	}
 24
 25	configurationRepository interface {
 26		List() []*config.GitRepositoryConfiguration
 27		GetByName(name string) *config.GitRepositoryConfiguration
 28	}
 29)
 30
 31var (
 32	RepositoryNotFoundErr = errors.New("Repository not found")
 33)
 34
 35// TODO: make it configurable
 36const timeFormat = "2006.01.02 15:04:05"
 37
 38func NewGitService(configRepo configurationRepository) *GitService {
 39	return &GitService{
 40		configRepo: configRepo,
 41	}
 42}
 43
 44func (g *GitService) ListRepositories() ([]*Repository, error) {
 45	rs := g.configRepo.List()
 46
 47	repos := make([]*Repository, 0, len(rs))
 48	for _, r := range rs {
 49		repo, err := git.OpenRepository(r.Path)
 50		if err != nil {
 51			return nil, err
 52		}
 53
 54		obj, err := repo.LastCommit()
 55		if err != nil {
 56			slog.Error("Error fetching last commit", "repository", r.Path, "error", err)
 57			continue
 58		}
 59
 60		head, err := repo.Head()
 61		if err != nil {
 62			slog.Error("Error fetching head", "repository", r.Path, "error", err)
 63			continue
 64		}
 65
 66		repos = append(repos, &Repository{
 67			Name:           r.Name,
 68			Description:    r.Description,
 69			LastCommitDate: obj.Author.When.Format(timeFormat),
 70			Ref:            head.Name().Short(),
 71		})
 72	}
 73
 74	return repos, nil
 75}
 76
 77func (g *GitService) ListCommits(name, ref string) ([]*object.Commit, error) {
 78	r := g.configRepo.GetByName(name)
 79	if r == nil {
 80		return nil, RepositoryNotFoundErr
 81	}
 82
 83	repo, err := git.OpenRepository(r.Path)
 84	if err != nil {
 85		return nil, err
 86	}
 87
 88	err = repo.SetRef(ref)
 89	if err != nil {
 90		return nil, err
 91	}
 92	return repo.Commits()
 93}
 94
 95func (g *GitService) GetTree(name, ref, path string) (*object.Tree, error) {
 96	r := g.configRepo.GetByName(name)
 97	if r == nil {
 98		return nil, RepositoryNotFoundErr
 99	}
100
101	repo, err := git.OpenRepository(r.Path)
102	if err != nil {
103		return nil, err
104	}
105	err = repo.SetRef(ref)
106	if err != nil {
107		return nil, err
108	}
109
110	return repo.Tree(path)
111}
112
113func (g *GitService) GetFileContent(name, ref, path string) (string, error) {
114	r := g.configRepo.GetByName(name)
115	if r == nil {
116		return "", RepositoryNotFoundErr
117	}
118
119	repo, err := git.OpenRepository(r.Path)
120	if err != nil {
121		return "", err
122	}
123	err = repo.SetRef(ref)
124	if err != nil {
125		return "", err
126	}
127
128	return repo.FileContent(path)
129}
130
131func (g *GitService) ListTags(name string) ([]*object.Tag, error) {
132	r := g.configRepo.GetByName(name)
133	if r == nil {
134		return nil, RepositoryNotFoundErr
135	}
136
137	repo, err := git.OpenRepository(r.Path)
138	if err != nil {
139		return nil, err
140	}
141	return repo.Tags()
142}
143
144func (g *GitService) ListBranches(name string) ([]*plumbing.Reference, error) {
145	r := g.configRepo.GetByName(name)
146	if r == nil {
147		return nil, RepositoryNotFoundErr
148	}
149
150	repo, err := git.OpenRepository(r.Path)
151	if err != nil {
152		return nil, err
153	}
154	return repo.Branches()
155}
156
157func (g *GitService) GetHead(name string) (*plumbing.Reference, error) {
158	r := g.configRepo.GetByName(name)
159	if r == nil {
160		return nil, RepositoryNotFoundErr
161	}
162
163	repo, err := git.OpenRepository(r.Path)
164	if err != nil {
165		return nil, err
166	}
167
168	return repo.Head()
169}