cerrado @ e1664fcbc4685906d3dabc66bf947a17bce7efc0

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