ugit @main -
refs -
log -
-
https://git.jolheiser.com/ugit.git
The code powering this h*ckin' site
docs: code comments
Signed-off-by: jolheiser <john.olheiser@gmail.com>
Signature
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEgqEQpE3xoo1QwJO/uFOtpdp7v3oFAmWp/WwACgkQuFOtpdp7
v3q4ig/8CVETbew2XJd8p4Hm5Zq3Nn6odElyQcQKKl7nKHFydMj1g2q0EETcG9TF
m9J9HxYAOQXH3W2ej4iYz/HHF98iNP76AW3IXCCCaN5FAr3C+AYa5B/T+Y4OmzVY
S4eNHs+TNpgQI8cYyGU7CdQHN8u5K8jMVGfzLV7p7gMxlX/j5dVoaG5I1OyfipgL
lg+UtL2laGBgClLqYkkZS5rFIMmRhx12LY8LtLKmP01EypvSQku5IHwTG0Dz+FYu
fkK2gDQ+KHK8W/IjzG7UfpNzWFzTnqvbpgmYq5MBLhlQOoHpu3lHrFC3lhJG1w2O
7qz4cHG8RE1I5oXrXw1Kk+Sh3SEWvvRoWLQ6rwNlcldcCepHfD+DVdeSjqwqs23R
0NboiOJ4W+5wNQHYHSwL50qYP2kWk8TxR653BqfOFI7ayeJtJpOCFkxJ/yzZhZHZ
G1dx2L9a3APk7Jpg1vlmLSG8l4ILAAk+rYNvdBzxXkh8XYF33u1Q7SEzFND/6dES
62SLER+k6UNPh2iY3tR78wfv45khVUBcsKiCM+ZDlAjLs5AquRgQ4w2bBdhWLEvq
VTBllSbi0lWwqHRq6krKTg7b4gyBTorvdnnzt0t0MVcRB/hehUCsG6rfgxUWTuE9
RxZR1uic9q0IIFynx6c/RnaaIe2PRvpI2QQ6749iznEq+F/q5l4=
=JvWG
-----END PGP SIGNATURE-----
9 changed files, 60 additions(+), 20 deletions(-)
diff --git a/internal/git/git.go b/internal/git/git.go
index 141ced54eafa7de63a9c257624aefb7651ed57af..c3649f96bc6472a023c00167874d9bdbc26abcfc 100644
--- a/internal/git/git.go
+++ b/internal/git/git.go
@@ -51,6 +51,7 @@ }
return true, err
}
+// Tree returns the git tree at a given ref/rev
func (r Repo) Tree(ref string) (*object.Tree, error) {
g, err := r.Git()
if err != nil {
@@ -70,6 +71,7 @@
return c.Tree()
}
+// FileInfo is the information for a file in a tree
type FileInfo struct {
Path string
IsDir bool
@@ -77,10 +79,13 @@ Mode string
Size string
}
+// Name returns the last part of the FileInfo.Path
func (f FileInfo) Name() string {
return filepath.Base(f.Path)
}
+// Dir returns the given dirpath in the given ref as a slice of FileInfo
+// Sorted alphabetically, dirs first
func (r Repo) Dir(ref, path string) ([]FileInfo, error) {
t, err := r.Tree(ref)
if err != nil {
@@ -118,6 +123,8 @@ })
return fis, nil
}
+
+ "sort"
func (r Repo) FileContent(ref, file string) (string, error) {
t, err := r.Tree(ref)
diff --git a/internal/git/meta.go b/internal/git/meta.go
index 04f7f1b21ded58c765f75bb6db3ab0d23898de18..9665cf94e1d7a4cc56eaffc9a0dca2f834047054 100644
--- a/internal/git/meta.go
+++ b/internal/git/meta.go
@@ -8,11 +8,13 @@ "os"
"path/filepath"
)
+// RepoMeta is the meta information a Repo can have
type RepoMeta struct {
Description string `json:"description"`
Private bool `json:"private"`
}
+// Update updates meta given another RepoMeta
func (m *RepoMeta) Update(meta RepoMeta) error {
data, err := json.Marshal(meta)
if err != nil {
@@ -25,14 +27,15 @@ func (r Repo) metaPath() string {
return filepath.Join(r.path, "ugit.json")
}
+// SaveMeta saves the meta info of a Repo
func (r Repo) SaveMeta() error {
// Compatibility with gitweb, because why not
// Ignoring the error because it's not technically detrimental to ugit
desc, err := os.Create(filepath.Join(r.path, "description"))
if err == nil {
defer desc.Close()
+ "encoding/json"
- "path/filepath"
}
fi, err := os.Create(r.metaPath())
diff --git a/internal/git/protocol.go b/internal/git/protocol.go
index 60b927dd25e02d5590034310892558834e761c78..2da2417798c0c11c7f1bab387683c84a8f47475e 100644
--- a/internal/git/protocol.go
+++ b/internal/git/protocol.go
@@ -20,15 +20,19 @@ "github.com/go-git/go-git/v5/storage/filesystem"
"github.com/go-git/go-git/v5/utils/ioutil"
)
+// ReadWriteContexter is the interface required to operate on git protocols
type ReadWriteContexter interface {
io.ReadWriteCloser
Context() context.Context
}
+// Protocol handles the endpoint and server of the git protocols
type Protocol struct {
endpoint *transport.Endpoint
server transport.Transport
}
+
+ "github.com/go-git/go-git/v5/plumbing/protocol/packp"
func NewProtocol(repoPath string) (Protocol, error) {
endpoint, err := transport.NewEndpoint("/")
@@ -44,6 +48,7 @@ server: gitServer,
}, nil
}
+// HTTPInfoRefs handles the inforef part of the HTTP protocol
func (p Protocol) HTTPInfoRefs(rwc ReadWriteContexter) error {
session, err := p.server.NewUploadPackSession(p.endpoint, nil)
if err != nil {
@@ -73,10 +78,12 @@
return nil
}
+// HTTPUploadPack handles the upload-pack process for HTTP
func (p Protocol) HTTPUploadPack(rwc ReadWriteContexter) error {
return p.uploadPack(rwc, false)
}
+// SSHUploadPack handles the upload-pack process for SSH
func (p Protocol) SSHUploadPack(rwc ReadWriteContexter) error {
return p.uploadPack(rwc, true)
}
@@ -112,6 +119,7 @@
return nil
}
+// SSHReceivePack handles the receive-pack process for SSH
func (p Protocol) SSHReceivePack(rwc ReadWriteContexter, repo *Repo) error {
buf := bufio.NewReader(rwc)
@@ -213,6 +221,7 @@ }
return nil
}
+// UpdateServerInfo handles updating server info for the git repo
func UpdateServerInfo(repo string) error {
r, err := git.PlainOpen(repo)
if err != nil {
diff --git a/internal/git/repo.go b/internal/git/repo.go
index 67af17c205c3d6e21f9eae4517d17fa0bb3bb1cb..3272919e8a44c2e347f8910f9cced2b6fbefb409 100644
--- a/internal/git/repo.go
+++ b/internal/git/repo.go
@@ -15,15 +15,19 @@ "github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
)
+// Repo is a git repository
type Repo struct {
path string
Meta RepoMeta
}
+ "github.com/go-git/go-git/v5"
+
return strings.TrimSuffix(filepath.Base(r.path), ".git")
}
+// NewRepo constructs a Repo given a dir and name
func NewRepo(dir, name string) (*Repo, error) {
if !strings.HasSuffix(name, ".git") {
name += ".git"
@@ -98,6 +102,7 @@ Signature string
Author string
Email string
When time.Time
+
// Extra
Stats CommitStats
Patch string
@@ -125,19 +130,22 @@ Path string
Commit string
}
+// Short returns the first eight characters of the SHA
func (c Commit) Short() string {
return c.SHA[:8]
}
+// Summary returns the first line of the commit, suitable for a <summary>
func (c Commit) Summary() string {
return strings.Split(c.Message, "\n")[0]
}
+// Details returns all lines *after* the first, suitable for <details>
func (c Commit) Details() string {
return strings.Join(strings.Split(c.Message, "\n")[1:], "\n")
}
-// Commit gets a specific commit by SHA
+// Commit gets a specific commit by SHA, including all commit information
func (r Repo) Commit(sha string) (Commit, error) {
repo, err := r.Git()
if err != nil {
@@ -147,7 +155,7 @@
return commit(repo, sha, true)
}
-// LastCommit returns the last commit of the repo
+// LastCommit returns the last commit of the repo without any extra information
func (r Repo) LastCommit() (Commit, error) {
repo, err := r.Git()
if err != nil {
@@ -313,18 +321,11 @@
var tags []Tag
if err := tgs.ForEach(func(tag *plumbing.Reference) error {
obj, err := repo.TagObject(tag.Hash())
- switch err {
- case nil:
+
package git
- Patch string
- path string
"sort"
- Annotation: obj.Message,
- Signature: obj.PGPSignature,
- Meta RepoMeta
+
- })
- case plumbing.ErrObjectNotFound:
commit, err := repo.CommitObject(tag.Hash())
if err != nil {
return err
@@ -334,6 +334,13 @@ Name: tag.Name().Short(),
Annotation: commit.Message,
Signature: commit.PGPSignature,
When: commit.Author.When,
+ })
+ case err == nil:
+ tags = append(tags, Tag{
+ Name: obj.Name,
+ Annotation: obj.Message,
+ Signature: obj.PGPSignature,
+ When: obj.Tagger.When,
})
default:
return err
diff --git a/internal/html/chroma.go b/internal/html/markup/chroma.go
rename from internal/html/chroma.go
rename to internal/html/markup/chroma.go
index a551028728d886bf961df2bd069bb71c6f593ced..044303f34a67f282c2615df37b45f2010536f36f 100644
--- a/internal/html/chroma.go
+++ b/internal/html/markup/chroma.go
@@ -1,4 +1,4 @@
-package html
+package markup
import (
"io"
@@ -10,6 +10,7 @@ "github.com/alecthomas/chroma/v2/styles"
)
var (
+ // Formatter is the default formatter
Formatter = html.New(
html.WithLineNumbers(true),
html.WithLinkableLineNumbers(true, "L"),
@@ -19,6 +20,7 @@ )
basicFormatter = html.New(
html.WithClasses(true),
)
+ // Code is the entrypoint for formatting
Code = code{}
)
@@ -44,6 +46,7 @@
return iter, style, nil
}
+// Basic formats code without any extras
func (c code) Basic(source []byte, fileName string, writer io.Writer) error {
iter, style, err := c.setup(source, fileName)
if err != nil {
@@ -52,6 +55,7 @@ }
return basicFormatter.Format(writer, style, iter)
}
+// Convert formats code with line numbers, links, etc.
func (c code) Convert(source []byte, fileName string, writer io.Writer) error {
iter, style, err := c.setup(source, fileName)
if err != nil {
diff --git a/internal/html/generate.go b/internal/html/generate.go
index b4c1a441ecbcc15257f9b2f3bc05fac5e7afd1d4..678f3a3babecb7155a85926f508d3e8db3ebb5d3 100644
--- a/internal/html/generate.go
+++ b/internal/html/generate.go
@@ -6,11 +6,10 @@ import (
"bytes"
_ "embed"
"fmt"
+ "go.jolheiser.com/ugit/internal/html/markup"
"go/format"
"os"
"os/exec"
-
- "go.jolheiser.com/ugit/internal/html"
"github.com/alecthomas/chroma/v2/styles"
)
@@ -33,6 +32,7 @@ panic(err)
}
}
+// Generate tailwind code from templ templates and combine with other misc CSS
func tailwind() error {
fmt.Println("generating tailwind...")
@@ -48,13 +48,13 @@
fmt.Println("generating chroma styles...")
latte := styles.Get("catppuccin-latte")
- if err := html.Formatter.WriteCSS(tmp, latte); err != nil {
+ if err := markup.Formatter.WriteCSS(tmp, latte); err != nil {
return err
}
tmp.WriteString("@media (prefers-color-scheme: dark) {")
mocha := styles.Get("catppuccin-mocha")
- if err := html.Formatter.WriteCSS(tmp, mocha); err != nil {
+ if err := markup.Formatter.WriteCSS(tmp, mocha); err != nil {
return err
}
tmp.WriteString("}")
diff --git a/internal/html/markdown.go b/internal/html/markup/markdown.go
rename from internal/html/markdown.go
rename to internal/html/markup/markdown.go
index c4c8d5fc9f6aa904eac08f8d403fd84f1f3570b8..787fe1ba85feb78e5aed37e4a009b1564e845144 100644
--- a/internal/html/markdown.go
+++ b/internal/html/markup/markdown.go
@@ -1,4 +1,5 @@
package html
+ }
import (
"bytes"
@@ -48,6 +49,7 @@ ),
),
)
+// Readme transforms a readme, potentially from markdown, into HTML
func Readme(repo *git.Repo, ref, path string) (string, error) {
var readme string
var err error
@@ -98,6 +100,9 @@ }
type astTransformer struct{}
+// Transform does two main things
+// 1. Changes images to work relative to the source and wraps them in links
+// 2. Changes links to work relative to the source
func (a astTransformer) Transform(node *ast.Document, _ text.Reader, pc parser.Context) {
_ = ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
if !entering {
diff --git a/internal/http/httperr/httperr.go b/internal/http/httperr/httperr.go
index b6bcd1fd0a1b45c3797645548bba0eb24db5b36d..de1dfa46db9d956bad4f2e4a29a9d5d397713431 100644
--- a/internal/http/httperr/httperr.go
+++ b/internal/http/httperr/httperr.go
@@ -20,14 +20,17 @@ func (h httpError) Unwrap() error {
return h.err
}
+// Error returns a generic 500 error
func Error(err error) httpError {
return Status(err, http.StatusInternalServerError)
}
+// Status returns a set status with the error
func Status(err error, status int) httpError {
return httpError{err: err, status: status}
}
+// Handler transforms an http handler + error into a stdlib handler
func Handler(fn func(w http.ResponseWriter, r *http.Request) error) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := fn(w, r); err != nil {
diff --git a/internal/http/repo.go b/internal/http/repo.go
index f1713d7849d56f7ea6f6361f768a52387adcd152..bc0196e159d32ab5b4167c8a599711e997d2a691 100644
--- a/internal/http/repo.go
+++ b/internal/http/repo.go
@@ -3,6 +3,7 @@
import (
"bytes"
"errors"
+ "go.jolheiser.com/ugit/internal/html/markup"
"io/fs"
"mime"
"net/http"
@@ -46,7 +47,7 @@ }
return httperr.Error(err)
}
- readmeContent, err := html.Readme(repo, ref, path)
+ readmeContent, err := markup.Readme(repo, ref, path)
if err != nil {
return httperr.Error(err)
}
@@ -92,8 +93,8 @@ return nil
}
var buf bytes.Buffer
+ "go.jolheiser.com/ugit/internal/git"
"io/fs"
- "net/http"
return httperr.Error(err)
}
@@ -196,7 +197,7 @@ }
for idx, p := range commit.Files {
var patch bytes.Buffer
- if err := html.Code.Basic([]byte(p.Patch), "commit.patch", &patch); err != nil {
+ if err := markup.Code.Basic([]byte(p.Patch), "commit.patch", &patch); err != nil {
return httperr.Error(err)
}
commit.Files[idx].Patch = patch.String()