repo.go - staticgit - A git static site generator in GO with HTML output!
 (HTM) git clone git://jay.scot/staticgit
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
       repo.go (3132B)
       ---
            1 package repo
            2 
            3 import (
            4         "fmt"
            5         "os"
            6         "path/filepath"
            7         "sort"
            8         "strings"
            9         "time"
           10 
           11         "github.com/go-git/go-git/v5"
           12         "github.com/go-git/go-git/v5/plumbing/object"
           13 )
           14 
           15 type Repo struct {
           16         Name        string
           17         Description string
           18         LastMod     time.Time
           19         gitRepo     *git.Repository
           20 }
           21 
           22 type Commit struct {
           23         Hash    string
           24         Author  string
           25         Date    string
           26         Msg     string
           27         Added   int
           28         Removed int
           29 }
           30 
           31 func OpenRepo(path string) (*Repo, error) {
           32         gitRepo, err := git.PlainOpen(path)
           33         if err != nil {
           34                 return nil, fmt.Errorf("open repo: %w", err)
           35         }
           36 
           37         name := filepath.Base(path)
           38         desc, _ := os.ReadFile(filepath.Join(path, "description"))
           39 
           40         head, err := gitRepo.Head()
           41         if err != nil {
           42                 return nil, fmt.Errorf("get HEAD: %w", err)
           43         }
           44 
           45         commit, err := gitRepo.CommitObject(head.Hash())
           46         if err != nil {
           47                 return nil, fmt.Errorf("get commit object: %w", err)
           48         }
           49 
           50         return &Repo{
           51                 Name:        name,
           52                 Description: strings.TrimSpace(string(desc)),
           53                 LastMod:     commit.Committer.When,
           54                 gitRepo:     gitRepo,
           55         }, nil
           56 }
           57 
           58 func (r *Repo) GetCommits(maxCommits int) ([]Commit, error) {
           59         iter, err := r.gitRepo.Log(&git.LogOptions{})
           60         if err != nil {
           61                 return nil, fmt.Errorf("get commit log: %w", err)
           62         }
           63 
           64         var cs []Commit
           65         err = iter.ForEach(func(c *object.Commit) error {
           66                 if len(cs) >= maxCommits {
           67                         return nil
           68                 }
           69 
           70                 stats, err := c.Stats()
           71                 if err != nil {
           72                         return fmt.Errorf("get commit stats: %w", err)
           73                 }
           74 
           75                 add, del := 0, 0
           76                 for _, stat := range stats {
           77                         add += stat.Addition
           78                         del += stat.Deletion
           79                 }
           80 
           81                 cs = append(cs, Commit{
           82                         Hash:    c.Hash.String()[:7],
           83                         Author:  c.Author.Name,
           84                         Date:    c.Author.When.Format("02 Jan 2006 15:04:05"),
           85                         Msg:     strings.Split(c.Message, "\n")[0],
           86                         Added:   add,
           87                         Removed: del,
           88                 })
           89 
           90                 return nil
           91         })
           92 
           93         if err != nil {
           94                 return nil, fmt.Errorf("iterate commits: %w", err)
           95         }
           96 
           97         return cs, nil
           98 }
           99 
          100 func (r *Repo) GetFiles() ([]string, error) {
          101         head, err := r.gitRepo.Head()
          102         if err != nil {
          103                 return nil, fmt.Errorf("get HEAD: %w", err)
          104         }
          105 
          106         commit, err := r.gitRepo.CommitObject(head.Hash())
          107         if err != nil {
          108                 return nil, fmt.Errorf("get commit object: %w", err)
          109         }
          110 
          111         tree, err := commit.Tree()
          112         if err != nil {
          113                 return nil, fmt.Errorf("get tree: %w", err)
          114         }
          115 
          116         var fs []string
          117         err = tree.Files().ForEach(func(f *object.File) error {
          118                 fs = append(fs, f.Name)
          119                 return nil
          120         })
          121         if err != nil {
          122                 return nil, fmt.Errorf("iterate files: %w", err)
          123         }
          124 
          125         sort.Strings(fs)
          126         return fs, nil
          127 }
          128 
          129 func (r *Repo) GetReadme() (string, error) {
          130         names := []string{"README.md", "README.txt", "README"}
          131 
          132         head, err := r.gitRepo.Head()
          133         if err != nil {
          134                 return "", fmt.Errorf("get HEAD: %w", err)
          135         }
          136 
          137         commit, err := r.gitRepo.CommitObject(head.Hash())
          138         if err != nil {
          139                 return "", fmt.Errorf("get commit object: %w", err)
          140         }
          141 
          142         tree, err := commit.Tree()
          143         if err != nil {
          144                 return "", fmt.Errorf("get tree: %w", err)
          145         }
          146 
          147         for _, name := range names {
          148                 file, err := tree.File(name)
          149                 if err != nil {
          150                         continue
          151                 }
          152 
          153                 content, err := file.Contents()
          154                 if err != nil {
          155                         return "", fmt.Errorf("read file contents: %w", err)
          156                 }
          157 
          158                 return content, nil
          159         }
          160 
          161         return "No README found!", nil
          162 }