1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-10-30 11:46:16 +00:00
mycorrhiza/history/history.go

140 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package history
import (
"bytes"
"fmt"
"log"
"os/exec"
"strconv"
"strings"
"time"
"github.com/bouncepaw/mycorrhiza/user"
"github.com/bouncepaw/mycorrhiza/util"
)
// Start initializes git credentials.
func Start(wikiDir string) {
_, err := gitsh("config", "user.name", "wikimind")
if err != nil {
log.Fatal(err)
}
_, err = gitsh("config", "user.email", "wikimind@mycorrhiza")
if err != nil {
log.Fatal(err)
}
}
// Revision represents a revision, duh. Hash is usually short. Username is extracted from email.
type Revision struct {
Hash string
Username string
Time time.Time
Message string
}
// TimeString returns a human readable time representation.
func (rev Revision) TimeString() string {
return rev.Time.Format(time.RFC822)
}
// HyphaeLinks returns a comma-separated list of hyphae that were affected by this revision as HTML string.
func (rev Revision) HyphaeLinks() (html string) {
// diff-tree --no-commit-id --name-only -r
var (
// List of files affected by this revision, one per line.
out, err = gitsh("diff-tree", "--no-commit-id", "--name-only", "-r", rev.Hash)
// set is used to determine if a certain hypha has been already noted (hyphae are stored in 2 files at most).
set = make(map[string]bool)
isNewName = func(hyphaName string) bool {
if _, present := set[hyphaName]; present {
return false
} else {
set[hyphaName] = true
return true
}
}
)
if err != nil {
return ""
}
for _, filename := range strings.Split(out.String(), "\n") {
// If filename has an ampersand:
if strings.IndexRune(filename, '.') >= 0 {
// Remove ampersanded suffix from filename:
ampersandPos := strings.LastIndexByte(filename, '.')
hyphaName := string([]byte(filename)[0:ampersandPos]) // is it safe?
if isNewName(hyphaName) {
// Entries are separated by commas
if len(set) > 1 {
html += `<span aria-hidden="true">, </span>`
}
html += fmt.Sprintf(`<a href="/page/%[1]s">%[1]s</a>`, hyphaName)
}
}
}
return html
}
func (rev Revision) RecentChangesEntry() (html string) {
if user.AuthUsed && rev.Username != "anon" {
return fmt.Sprintf(`
<li class="rc-entry__time"><time>%[1]s</time></li>
<li class="rc-entry__hash">%[2]s</li>
<li class="rc-entry__links">%[5]s</li>
<li class="rc-entry__msg">%[6]s <span class="rc-entry__author">by <a href="/page/%[3]s/%[4]s" rel="author">%[4]s</a></span></li>
`, rev.TimeString(), rev.Hash, util.UserTree, rev.Username, rev.HyphaeLinks(), rev.Message)
}
return fmt.Sprintf(`
<li class="rc-entry__time"><time>%[1]s</time></li>
<li class="rc-entry__hash">%[2]s</li>
<li class="rc-entry__links">%[3]s</li>
<li class="rc-entry__msg">%[4]s</li>
`, rev.TimeString(), rev.Hash, rev.HyphaeLinks(), rev.Message)
}
// Path to git executable. Set at init()
var gitpath string
func init() {
path, err := exec.LookPath("git")
if err != nil {
log.Fatal("Cound not find the git executable. Check your $PATH.")
} else {
log.Println("Git path is", path)
}
gitpath = path
}
// I pronounce it as [gɪt͡ʃ].
// gitsh is async-safe, therefore all other git-related functions in this module are too.
func gitsh(args ...string) (out bytes.Buffer, err error) {
fmt.Printf("$ %v\n", args)
cmd := exec.Command(gitpath, args...)
cmd.Dir = util.WikiDir
b, err := cmd.CombinedOutput()
if err != nil {
log.Println("gitsh:", err)
}
return *bytes.NewBuffer(b), err
}
// Convert a UNIX timestamp as string into a time. If nil is returned, it means that the timestamp could not be converted.
func unixTimestampAsTime(ts string) *time.Time {
i, err := strconv.ParseInt(ts, 10, 64)
if err != nil {
return nil
}
tm := time.Unix(i, 0)
return &tm
}
// Rename renames from `from` to `to` using `git mv`.
func Rename(from, to string) error {
log.Println(util.ShorterPath(from), util.ShorterPath(to))
_, err := gitsh("mv", "--force", from, to)
return err
}