vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Merge change request 01M70WES5ZZDJ6RP226WB11BBZ: Let people rename and remove their own passkeys
keenan · 2h ago
4b8c9e1d
| 1 | package index |
| 2 | |
| 3 | // The overview's stored summaries: the default branch's recent commits, the |
| 4 | // languages it is mostly made of, and the repository's tags. |
| 5 | // |
| 6 | // All three change when a ref moves, so they are written then (see RefreshHead |
| 7 | // and RefreshTags) and read as rows. A repository page then has no reason to |
| 8 | // walk the tree or the history. |
| 9 | |
| 10 | import "rodent.software/vole/internal/lang" |
| 11 | |
| 12 | type CommitRow struct { |
| 13 | SHA string |
| 14 | Subject string |
| 15 | Author string |
| 16 | When int64 |
| 17 | } |
| 18 | |
| 19 | // TagRow is one entry of refs/tags, peeled to the commit it names. |
| 20 | type TagRow struct { |
| 21 | Name string |
| 22 | OID string |
| 23 | Commit string |
| 24 | Annotated bool |
| 25 | Tagger string |
| 26 | When int64 |
| 27 | Subject string |
| 28 | } |
| 29 | |
| 30 | // RecentCommits returns the default branch's newest commits, newest first. It is |
| 31 | // the first page of the history, recorded when the tip was pushed. |
| 32 | func (s *Store) RecentCommits(repoID string, n int) ([]CommitRow, error) { |
| 33 | q := `SELECT sha, subject, author, when_at FROM repo_commits WHERE repo_id=? ORDER BY pos` |
| 34 | args := []any{repoID} |
| 35 | if n > 0 { |
| 36 | q += ` LIMIT ?` |
| 37 | args = append(args, n) |
| 38 | } |
| 39 | rows, err := s.db.Query(q, args...) |
| 40 | if err != nil { |
| 41 | return nil, err |
| 42 | } |
| 43 | defer rows.Close() |
| 44 | var out []CommitRow |
| 45 | for rows.Next() { |
| 46 | var c CommitRow |
| 47 | if err := rows.Scan(&c.SHA, &c.Subject, &c.Author, &c.When); err != nil { |
| 48 | return nil, err |
| 49 | } |
| 50 | out = append(out, c) |
| 51 | } |
| 52 | return out, rows.Err() |
| 53 | } |
| 54 | |
| 55 | // Languages returns the default branch's language groups by size, largest first. |
| 56 | // The rows include "Other", so a percentage has a total to divide by. |
| 57 | func (s *Store) Languages(repoID string) ([]lang.Share, error) { |
| 58 | rows, err := s.db.Query(`SELECT name, bytes FROM repo_languages WHERE repo_id=? ORDER BY bytes DESC, name`, repoID) |
| 59 | if err != nil { |
| 60 | return nil, err |
| 61 | } |
| 62 | defer rows.Close() |
| 63 | var out []lang.Share |
| 64 | for rows.Next() { |
| 65 | var sh lang.Share |
| 66 | if err := rows.Scan(&sh.Name, &sh.Bytes); err != nil { |
| 67 | return nil, err |
| 68 | } |
| 69 | out = append(out, sh) |
| 70 | } |
| 71 | return out, rows.Err() |
| 72 | } |
| 73 | |
| 74 | // Tags returns the repository's tags, newest first, which is the order the |
| 75 | // releases section shows. |
| 76 | func (s *Store) Tags(repoID string, n int) ([]TagRow, error) { |
| 77 | q := `SELECT name, oid, commit_sha, annotated, tagger, when_at, subject |
| 78 | FROM repo_tags WHERE repo_id=? ORDER BY when_at DESC, name` |
| 79 | args := []any{repoID} |
| 80 | if n > 0 { |
| 81 | q += ` LIMIT ?` |
| 82 | args = append(args, n) |
| 83 | } |
| 84 | rows, err := s.db.Query(q, args...) |
| 85 | if err != nil { |
| 86 | return nil, err |
| 87 | } |
| 88 | defer rows.Close() |
| 89 | var out []TagRow |
| 90 | for rows.Next() { |
| 91 | var t TagRow |
| 92 | if err := rows.Scan(&t.Name, &t.OID, &t.Commit, &t.Annotated, &t.Tagger, &t.When, &t.Subject); err != nil { |
| 93 | return nil, err |
| 94 | } |
| 95 | out = append(out, t) |
| 96 | } |
| 97 | return out, rows.Err() |
| 98 | } |
| 99 |