all repos

mugit @ 94608d2713d93f6a418165914057a1869ac447cc

🐮 git server that your cow will love
3 files changed, 58 insertions(+), 16 deletions(-)
handle empty repo correctly
Author: Oleksandr Smirnov olexsmir@gmail.com
Committed at: 2026-01-30 20:54:12 +0200
Change ID: tvqkmkkrplqwqyrmksyyqvpsprypzltk
Parent: 12a019f
M internal/git/repo.go

@@ -18,6 +18,8 @@ )

// Thanks https://git.icyphox.sh/legit/blob/master/git/git.go +var ErrEmptyRepo = errors.New("repository has no commits") + type Repo struct { path string r *git.Repository

@@ -37,6 +39,9 @@

if ref == "" { head, err := g.r.Head() if err != nil { + if errors.Is(err, plumbing.ErrReferenceNotFound) { + return &g, nil + } return nil, fmt.Errorf("getting head of %s: %w", path, err) } g.h = head.Hash()

@@ -50,12 +55,26 @@ }

return &g, nil } +func (g *Repo) IsEmpty() bool { + return g.h == plumbing.ZeroHash +} + +// Init creates a bare repo. +func Init(path string) error { + _, err := git.PlainInit(path, true) + return err +} + func (g *Repo) Name() string { name := filepath.Base(g.path) return strings.TrimSuffix(name, ".git") } func (g *Repo) Commits() ([]*object.Commit, error) { + if g.IsEmpty() { + return []*object.Commit{}, nil + } + ci, err := g.r.Log(&git.LogOptions{ From: g.h, Order: git.LogOrderCommitterTime,

@@ -74,6 +93,10 @@ return commits, nil

} func (g *Repo) LastCommit() (*object.Commit, error) { + if g.IsEmpty() { + return nil, ErrEmptyRepo + } + c, err := g.r.CommitObject(g.h) if err != nil { return nil, fmt.Errorf("last commit: %w", err)

@@ -189,6 +212,10 @@ return err == nil

} func (g *Repo) FindMasterBranch(masters []string) (string, error) { + if g.IsEmpty() { + return "", ErrEmptyRepo + } + for _, b := range masters { if _, err := g.r.ResolveRevision(plumbing.Revision(b)); err == nil { return b, nil
M internal/handlers/repo.go

@@ -50,6 +50,24 @@ h.write404(w, err)

return } + desc, err := repo.Description() + if err != nil { + h.write500(w, err) + return + } + + data := make(map[string]any) + data["name"] = name + data["desc"] = desc + data["servername"] = h.c.Meta.Host + data["meta"] = h.c.Meta + + if repo.IsEmpty() { + data["empty"] = true + h.templ(w, "repo_index", data) + return + } + var readmeContents template.HTML for _, readme := range h.c.Repo.Readmes { ext := filepath.Ext(readme)

@@ -76,12 +94,6 @@ h.write500(w, err)

return } - desc, err := repo.Description() - if err != nil { - h.write500(w, err) - return - } - commits, err := repo.Commits() if err != nil { h.write500(w, err)

@@ -92,14 +104,9 @@ if len(commits) >= 4 {

commits = commits[:3] } - data := make(map[string]any) - data["name"] = name data["ref"] = masterBranch - data["desc"] = desc data["readme"] = readmeContents data["commits"] = commits - data["servername"] = h.c.Meta.Host - data["meta"] = h.c.Meta data["gomod"] = repo.IsGoMod() if mirrorInfo, err := repo.MirrorInfo(); err == nil && mirrorInfo.IsMirror {

@@ -396,16 +403,21 @@ errs = append(errs, err)

continue } - lastComit, err := repo.LastCommit() + var lastCommitTime time.Time + lastCommit, err := repo.LastCommit() if err != nil { - errs = append(errs, err) - continue + if !errors.Is(err, git.ErrEmptyRepo) { + errs = append(errs, err) + continue + } + } else { + lastCommitTime = lastCommit.Author.When } repos = append(repos, repoList{ Name: normalizedName, Desc: desc, - LastCommit: lastComit.Author.When, + LastCommit: lastCommitTime, }) }
M web/templates/repo_index.html

@@ -10,7 +10,9 @@ {{ template "repo_header" . }}

<main> {{ $repo := .name }} - + {{ if .empty }} + <h3>Repository is empty</h3> + {{ else }} <section class="repo-index"> <div class="repo-index-main"> {{ range .commits }}

@@ -42,6 +44,7 @@ </p>

{{- end }} </div> </section> + {{ end }} {{- if .readme }} <article class="readme">