// Copyright (C) 2025, Jakob Wakeling // All rights reserved. package repo import ( "errors" "net/http" "path/filepath" "time" "github.com/Jamozed/Goit/src/goit" "github.com/Jamozed/Goit/src/util" "github.com/go-chi/chi/v5" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" ) func HandleTag(w http.ResponseWriter, r *http.Request) { auth, user, err := goit.Auth(w, r, true) if err != nil { util.PrintFuncError(err) goit.HttpError(w, http.StatusInternalServerError) return } repo, err := goit.GetRepoByName(chi.URLParam(r, "repo")) if err != nil { goit.HttpError(w, http.StatusInternalServerError) return } else if repo == nil || !goit.IsVisible(repo, auth, user) { goit.HttpError(w, http.StatusNotFound) return } data := struct { HeaderFields Title string Tag, Author, Date, Commit string Parents []string Message string }{ HeaderFields: GetHeaderFields(auth, user, repo, r.Host), Title: repo.Name + " - Tags", } gr, err := git.PlainOpen(goit.RepoPath(repo.Name, true)) if err != nil { util.PrintFuncError(err) goit.HttpError(w, http.StatusInternalServerError) return } head, err := gr.Head() if err != nil { if !errors.Is(err, plumbing.ErrReferenceNotFound) { util.PrintFuncError(err) goit.HttpError(w, http.StatusInternalServerError) return } } else { if readme, _ := findPattern(gr, head, readmePattern); readme != "" { data.Readme = filepath.Join("/", repo.Name, "file", readme) } if licence, _ := findPattern(gr, head, licencePattern); licence != "" { data.Licence = filepath.Join("/", repo.Name, "file", licence) } } ref, err := gr.Tag(chi.URLParam(r, "tag")) if errors.Is(err, plumbing.ErrReferenceNotFound) { goit.HttpError(w, http.StatusNotFound) return } else if err != nil { util.PrintFuncError(err) goit.HttpError(w, http.StatusInternalServerError) return } data.Tag = ref.Name().Short() var commit *object.Commit if tag, err := gr.TagObject(ref.Hash()); err != nil { if !errors.Is(err, plumbing.ErrObjectNotFound) { util.PrintFuncError(err) goit.HttpError(w, http.StatusInternalServerError) return } /* Tag is not annotated. */ if commit, err = gr.CommitObject(ref.Hash()); err != nil { util.PrintFuncError(err) goit.HttpError(w, http.StatusInternalServerError) return } data.Author = commit.Author.String() data.Message = commit.Message } else { /* Tag is annotated. */ if commit, err = gr.CommitObject(tag.Target); err != nil { util.PrintFuncError(err) goit.HttpError(w, http.StatusInternalServerError) return } data.Author = tag.Tagger.String() data.Message = tag.Message } data.Date = commit.Author.When.UTC().Format(time.DateTime) data.Commit = commit.Hash.String() if err := goit.Tmpl.ExecuteTemplate(w, "repo/tag", data); err != nil { util.PrintFuncError(err) } }