1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-12 05:20:26 +00:00
mycorrhiza/history/information.go

200 lines
5.6 KiB
Go
Raw Normal View History

2020-08-19 18:54:23 +00:00
package history
2021-05-11 10:14:00 +00:00
// information.go
// Things related to gathering existing information.
2020-08-19 18:54:23 +00:00
import (
"fmt"
2021-05-03 18:31:19 +00:00
"log"
2020-08-19 18:54:23 +00:00
"regexp"
2020-10-03 12:59:53 +00:00
"strconv"
2020-08-19 18:54:23 +00:00
"strings"
2020-11-29 17:06:45 +00:00
"time"
2020-09-26 18:19:17 +00:00
2021-06-19 04:51:10 +00:00
"github.com/bouncepaw/mycorrhiza/cfg"
"github.com/bouncepaw/mycorrhiza/files"
"github.com/gorilla/feeds"
2020-08-19 18:54:23 +00:00
)
func recentChangesFeed() *feeds.Feed {
feed := &feeds.Feed{
Title: "Recent changes",
Link: &feeds.Link{Href: cfg.URL},
Description: "List of 30 recent changes on the wiki",
Author: &feeds.Author{Name: "Wikimind", Email: "wikimind@mycorrhiza"},
Updated: time.Now(),
}
var (
2021-05-03 18:31:19 +00:00
out, err = silentGitsh(
"log", "--oneline", "--no-merges",
"--pretty=format:\"%h\t%ae\t%at\t%s\"",
"--max-count=30",
)
revs []Revision
)
if err == nil {
for _, line := range strings.Split(out.String(), "\n") {
revs = append(revs, parseRevisionLine(line))
}
}
2021-05-03 18:31:19 +00:00
log.Printf("Found %d recent changes", len(revs))
for _, rev := range revs {
feed.Add(&feeds.Item{
Title: rev.Message,
Author: &feeds.Author{Name: rev.Username},
Id: rev.Hash,
Description: rev.descriptionForFeed(),
Created: rev.Time,
Updated: rev.Time,
Link: &feeds.Link{Href: cfg.URL + rev.bestLink()},
})
}
return feed
}
// RecentChangesRSS creates recent changes feed in RSS format.
func RecentChangesRSS() (string, error) {
return recentChangesFeed().ToRss()
}
// RecentChangesAtom creates recent changes feed in Atom format.
func RecentChangesAtom() (string, error) {
return recentChangesFeed().ToAtom()
}
// RecentChangesJSON creates recent changes feed in JSON format.
func RecentChangesJSON() (string, error) {
return recentChangesFeed().ToJSON()
}
// RecentChanges gathers an arbitrary number of latest changes in form of revisions slice.
2021-02-20 16:50:25 +00:00
func RecentChanges(n int) []Revision {
2020-09-26 18:19:17 +00:00
var (
2021-05-03 18:31:19 +00:00
out, err = silentGitsh(
2020-09-26 18:19:17 +00:00
"log", "--oneline", "--no-merges",
"--pretty=format:\"%h\t%ae\t%at\t%s\"",
2020-10-03 12:59:53 +00:00
"--max-count="+strconv.Itoa(n),
2020-09-26 18:19:17 +00:00
)
revs []Revision
)
if err == nil {
for _, line := range strings.Split(out.String(), "\n") {
revs = append(revs, parseRevisionLine(line))
}
}
2021-05-03 18:31:19 +00:00
log.Printf("Found %d recent changes", len(revs))
2021-02-20 16:50:25 +00:00
return revs
2020-09-26 18:19:17 +00:00
}
2021-01-21 14:21:34 +00:00
// FileChanged tells you if the file has been changed.
func FileChanged(path string) bool {
_, err := gitsh("diff", "--exit-code", path)
return err != nil
}
// Revisions returns slice of revisions for the given hypha name.
2020-08-28 19:10:46 +00:00
func Revisions(hyphaName string) ([]Revision, error) {
2020-08-19 18:54:23 +00:00
var (
2021-05-03 18:31:19 +00:00
out, err = silentGitsh(
2020-08-19 18:54:23 +00:00
"log", "--oneline", "--no-merges",
2020-11-29 17:06:45 +00:00
// Hash, author email, author time, commit msg separated by tab
"--pretty=format:\"%h\t%ae\t%at\t%s\"",
"--", hyphaName+".*",
2020-08-19 18:54:23 +00:00
)
revs []Revision
)
if err == nil {
for _, line := range strings.Split(out.String(), "\n") {
2020-09-29 15:04:22 +00:00
if line != "" {
revs = append(revs, parseRevisionLine(line))
}
2020-08-19 18:54:23 +00:00
}
}
2021-05-03 18:31:19 +00:00
log.Printf("Found %d revisions for %s\n", len(revs), hyphaName)
2020-08-19 18:54:23 +00:00
return revs, err
}
// WithRevisions returns an html representation of `revs` that is meant to be inserted in a history page.
func WithRevisions(hyphaName string, revs []Revision) (html string) {
2020-11-29 17:06:45 +00:00
var (
currentYear int
currentMonth time.Month
)
for i, rev := range revs {
if rev.Time.Month() != currentMonth || rev.Time.Year() != currentYear {
currentYear = rev.Time.Year()
currentMonth = rev.Time.Month()
if i != 0 {
html += `
</ul>
</section>`
}
html += fmt.Sprintf(`
<section class="history__month">
<a href="#%[1]d-%[2]d" class="history__month-anchor">
<h2 id="%[1]d-%[2]d" class="history__month-title">%[3]s</h2>
</a>
<ul class="history__entries">`,
currentYear, currentMonth,
strconv.Itoa(currentYear)+" "+rev.Time.Month().String())
}
html += rev.asHistoryEntry(hyphaName)
}
return html
}
func (rev *Revision) asHistoryEntry(hyphaName string) (html string) {
author := ""
if rev.Username != "anon" {
author = fmt.Sprintf(`
2021-06-14 07:13:29 +00:00
<span class="history-entry__author">by <a href="/hypha/%[1]s/%[2]s" rel="author">%[2]s</span>`, cfg.UserHypha, rev.Username)
2020-11-29 17:06:45 +00:00
}
return fmt.Sprintf(`
<li class="history__entry">
<a class="history-entry" href="/rev/%[3]s/%[1]s">
<time class="history-entry__time">%[2]s</time>
<span class="history-entry__hash"><a href="/primitive-diff/%[3]s/%[1]s">%[3]s</a></span>
2020-11-29 17:06:45 +00:00
<span class="history-entry__msg">%[4]s</span>
</a>%[5]s
</li>
2021-01-21 13:49:22 +00:00
`, hyphaName, rev.timeToDisplay(), rev.Hash, rev.Message, author)
2020-11-29 17:06:45 +00:00
}
2021-01-21 13:49:22 +00:00
// Return time like mm-dd 13:42
func (rev *Revision) timeToDisplay() string {
D := rev.Time.Day()
2020-11-29 17:06:45 +00:00
h, m, _ := rev.Time.Clock()
2021-01-21 13:49:22 +00:00
return fmt.Sprintf("%02d — %02d:%02d", D, h, m)
2020-11-29 17:06:45 +00:00
}
2020-08-19 18:54:23 +00:00
// This regex is wrapped in "". For some reason, these quotes appear at some time and we have to get rid of them.
var revisionLinePattern = regexp.MustCompile("\"(.*)\t(.*)@.*\t(.*)\t(.*)\"")
func parseRevisionLine(line string) Revision {
results := revisionLinePattern.FindStringSubmatch(line)
return Revision{
Hash: results[1],
Username: results[2],
Time: *unixTimestampAsTime(results[3]),
Message: results[4],
}
2020-08-19 18:54:23 +00:00
}
2021-05-11 10:14:00 +00:00
// FileAtRevision shows how the file with the given file path looked at the commit with the hash. It may return an error if git fails.
func FileAtRevision(filepath, hash string) (string, error) {
2021-06-19 04:51:10 +00:00
out, err := gitsh("show", hash+":"+strings.TrimPrefix(filepath, files.HyphaeDir()+"/"))
2021-05-11 10:14:00 +00:00
if err != nil {
return "", err
}
return out.String(), err
2020-08-19 18:54:23 +00:00
}
2021-05-11 10:14:00 +00:00
// PrimitiveDiffAtRevision generates a plain-text diff for the given filepath at the commit with the given hash. It may return an error if git fails.
func PrimitiveDiffAtRevision(filepath, hash string) (string, error) {
2021-05-03 18:31:19 +00:00
out, err := silentGitsh("diff", "--unified=1", "--no-color", hash+"~", hash, "--", filepath)
2021-05-11 10:14:00 +00:00
if err != nil {
return "", err
}
return out.String(), err
}