cerrado @ ba84c0d82066739adbca468846a2688e02432b6f

  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, prefix 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	err = repo.WriteTar(gw, prefix)
117	if err != nil {
118		return err
119	}
120
121	return nil
122}
123
124func (g *GitService) GetTree(name, ref, path string) (*object.Tree, error) {
125	r := g.configRepo.GetByName(name)
126	if r == nil {
127		return nil, RepositoryNotFoundErr
128	}
129
130	repo, err := git.OpenRepository(r.Path)
131	if err != nil {
132		return nil, err
133	}
134	err = repo.SetRef(ref)
135	if err != nil {
136		return nil, err
137	}
138
139	return repo.Tree(path)
140}
141
142func (g *GitService) IsBinary(name, ref, path string) (bool, error) {
143	r := g.configRepo.GetByName(name)
144	if r == nil {
145		return false, RepositoryNotFoundErr
146	}
147
148	repo, err := git.OpenRepository(r.Path)
149	if err != nil {
150		return false, err
151	}
152	err = repo.SetRef(ref)
153	if err != nil {
154		return false, err
155	}
156
157	return repo.IsBinary(path)
158}
159
160func (g *GitService) GetFileContent(name, ref, path string) ([]byte, error) {
161	r := g.configRepo.GetByName(name)
162	if r == nil {
163		return nil, RepositoryNotFoundErr
164	}
165
166	repo, err := git.OpenRepository(r.Path)
167	if err != nil {
168		return nil, err
169	}
170	err = repo.SetRef(ref)
171	if err != nil {
172		return nil, err
173	}
174
175	return repo.FileContent(path)
176}
177
178func (g *GitService) GetAbout(name string) ([]byte, error) {
179	r := g.configRepo.GetByName(name)
180	if r == nil {
181		return nil, RepositoryNotFoundErr
182	}
183
184	repo, err := git.OpenRepository(r.Path)
185	if err != nil {
186		return nil, err
187	}
188	err = repo.SetRef("")
189	if err != nil {
190		return nil, err
191	}
192
193	return repo.FileContent(r.About)
194}
195
196func (g *GitService) ListTags(name string) ([]*plumbing.Reference, error) {
197	r := g.configRepo.GetByName(name)
198	if r == nil {
199		return nil, RepositoryNotFoundErr
200	}
201
202	repo, err := git.OpenRepository(r.Path)
203	if err != nil {
204		return nil, err
205	}
206	return repo.Tags()
207}
208
209func (g *GitService) ListBranches(name string) ([]*plumbing.Reference, error) {
210	r := g.configRepo.GetByName(name)
211	if r == nil {
212		return nil, RepositoryNotFoundErr
213	}
214
215	repo, err := git.OpenRepository(r.Path)
216	if err != nil {
217		return nil, err
218	}
219	return repo.Branches()
220}
221
222func (g *GitService) GetHead(name string) (*plumbing.Reference, error) {
223	r := g.configRepo.GetByName(name)
224	if r == nil {
225		return nil, RepositoryNotFoundErr
226	}
227
228	repo, err := git.OpenRepository(r.Path)
229	if err != nil {
230		return nil, err
231	}
232
233	return repo.Head()
234}