vole
Clone
Read only, no credentials:
https://rodent.software/vole.git
Write over SSH with a registered key:
git clone ssh://git@rodent.software:2222/vole.git
A free and open-source forge that lives in your Git repo.
Show real accounts as repository contributors
a32a859a08276681497be390d6f7195098a97ab4 · Keenan Nemetz · 5d ago · parent 802e0e52
Show real accounts as repository contributors Count contributors from the change and issue records instead of the author text in commits: changes merged, issues those changes fixed, issues the reporter opened that were fixed, and reviews that named the merged head. The overview lists accounts by that work with compact icon counts and full labels in tooltips. The shortlog-derived contributor table and its refresh path are gone.
server/web/cache.go +5−28
| @@ -3,11 +3,11 @@ package web | |||
| 3 | 3 | // Answers that cannot change while a commit id stays the same. | |
| 4 | 4 | // | |
| 5 | 5 | // The overview summarises a repository by walking its history: how many commits | |
| 6 | // it has, who wrote them, and what it is made of. Those are properties of the | ||
| 7 | // commit graph, and a commit is content-addressed — its ancestors are part of | ||
| 8 | // its identity — so remembering them by commit id is not a stale-data risk. It | ||
| 9 | // is a cheaper second read of the same bytes, which matters because a | ||
| 10 | // repository page is read far more often than its history is written. | ||
| 6 | // it has and what it is made of. Those are properties of the commit graph, and a | ||
| 7 | // commit is content-addressed — its ancestors are part of its identity — so | ||
| 8 | // remembering them by commit id is not a stale-data risk. It is a cheaper second | ||
| 9 | // read of the same bytes, which matters because a repository page is read far | ||
| 10 | // more often than its history is written. | ||
| 11 | 11 | // | |
| 12 | 12 | // The cache belongs to the process, not to an account or a request: the values | |
| 13 | 13 | // depend on nothing about the viewer. It is bounded and evicts oldest-first, so | |
| @@ -82,29 +82,6 @@ func (w *Web) countCommits(g *git.Repo, rev string) (int, error) { | |||
| 82 | 82 | return n, nil | |
| 83 | 83 | } | |
| 84 | 84 | ||
| 85 | // contributors returns the authors of rev's history. `shortlog` walks every | ||
| 86 | // commit, which is the single most expensive read on the overview page and one | ||
| 87 | // whose answer never changes for a given commit. | ||
| 88 | func (w *Web) contributors(g *git.Repo, rev string) []contributorView { | ||
| 89 | if rev == "" { | ||
| 90 | return nil | ||
| 91 | } | ||
| 92 | key := commitKey(g.Dir, rev) | ||
| 93 | if list, ok := w.commitAuthors.get(key); ok { | ||
| 94 | return list | ||
| 95 | } | ||
| 96 | authors, err := g.Contributors(rev) | ||
| 97 | if err != nil { | ||
| 98 | return nil | ||
| 99 | } | ||
| 100 | list := make([]contributorView, 0, len(authors)) | ||
| 101 | for _, c := range authors { | ||
| 102 | list = append(list, contributorView{Name: c.Name, Commits: c.Commits}) | ||
| 103 | } | ||
| 104 | w.commitAuthors.put(key, list) | ||
| 105 | return list | ||
| 106 | } | ||
| 107 | |||
| 108 | 85 | // The README is the overview's largest read that is not a count: a cat-file | |
| 109 | 86 | // spawn for the blob and a markdown render, for a file that changes only when | |
| 110 | 87 | // its commit does. Relative links resolve against the branch the reader is on, | |