diff --git a/history/history.go b/history/history.go index a1e897b..46937cf 100644 --- a/history/history.go +++ b/history/history.go @@ -3,6 +3,7 @@ package history import ( "bytes" "fmt" + "html" "log" "os/exec" "regexp" @@ -44,9 +45,26 @@ type Revision struct { Username string Time time.Time Message string + filesAffectedBuf []string hyphaeAffectedBuf []string } +// filesAffected tells what files have been affected by the revision. +func (rev *Revision) filesAffected() (filenames []string) { + if nil != rev.filesAffectedBuf { + return rev.filesAffectedBuf + } + // List of files affected by this revision, one per line. + out, err := silentGitsh("diff-tree", "--no-commit-id", "--name-only", "-r", rev.Hash) + // There's an error? Well, whatever, let's just assign an empty slice, who cares. + if err != nil { + rev.filesAffectedBuf = []string{} + } else { + rev.filesAffectedBuf = strings.Split(out.String(), "\n") + } + return rev.filesAffectedBuf +} + // determine what hyphae were affected by this revision func (rev *Revision) hyphaeAffected() (hyphae []string) { if nil != rev.hyphaeAffectedBuf { @@ -54,8 +72,6 @@ func (rev *Revision) hyphaeAffected() (hyphae []string) { } hyphae = make([]string, 0) 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 currently). set = make(map[string]bool) isNewName = func(hyphaName string) bool { @@ -65,11 +81,9 @@ func (rev *Revision) hyphaeAffected() (hyphae []string) { set[hyphaName] = true return true } + filesAffected = rev.filesAffected() ) - if err != nil { - return hyphae - } - for _, filename := range strings.Split(out.String(), "\n") { + for _, filename := range filesAffected { if strings.IndexRune(filename, '.') >= 0 { dotPos := strings.LastIndexByte(filename, '.') hyphaName := string([]byte(filename)[0:dotPos]) // is it safe? @@ -94,15 +108,44 @@ func (rev Revision) HyphaeLinksHTML() (html string) { if i > 0 { html += `` } - html += fmt.Sprintf(`%[1]s`, hyphaName) + html += fmt.Sprintf(`%[1]s`, hyphaName) } return html } -func (rev *Revision) descriptionForFeed() (html string) { +// descriptionForFeed generates a good enough HTML contents for a web feed. +func (rev *Revision) descriptionForFeed() (htmlDesc string) { return fmt.Sprintf( `
%s
-Hyphae affected: %s
`, rev.Message, rev.HyphaeLinksHTML()) +Hyphae affected: %s
+%s`, rev.Message, rev.HyphaeLinksHTML(), html.EscapeString(rev.textDiff()))
+}
+
+// textDiff generates a good enough diff to display in a web feed. It is not html-escaped.
+func (rev *Revision) textDiff() (diff string) {
+ filenames, ok := rev.mycoFiles()
+ if !ok {
+ return "No text changes"
+ }
+ for _, filename := range filenames {
+ text, err := PrimitiveDiffAtRevision(filename, rev.Hash)
+ if err != nil {
+ diff += "\nAn error has occured with " + filename + "\n"
+ }
+ diff += text + "\n"
+ }
+ return diff
+}
+
+// mycoFiles returns filenames of .myco file. It is not ok if there are no myco files.
+func (rev *Revision) mycoFiles() (filenames []string, ok bool) {
+ filenames = []string{}
+ for _, filename := range rev.filesAffected() {
+ if strings.HasSuffix(filename, ".myco") {
+ filenames = append(filenames, filename)
+ }
+ }
+ return filenames, len(filenames) > 0
}
// Try and guess what link is the most important by looking at the message.
@@ -113,11 +156,11 @@ func (rev *Revision) bestLink() string {
)
switch {
case renameRes != nil:
- return "/page/" + renameRes[1]
+ return "/hypha/" + renameRes[1]
case len(revs) == 0:
return ""
default:
- return "/page/" + revs[0]
+ return "/hypha/" + revs[0]
}
}
@@ -135,6 +178,15 @@ func gitsh(args ...string) (out bytes.Buffer, err error) {
return *bytes.NewBuffer(b), err
}
+// silentGitsh is like gitsh, except it writes less to the stdout.
+func silentGitsh(args ...string) (out bytes.Buffer, err error) {
+ cmd := exec.Command(gitpath, args...)
+ cmd.Dir = util.WikiDir
+
+ b, err := cmd.CombinedOutput()
+ 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)
diff --git a/history/information.go b/history/information.go
index cd22f0c..75b7501 100644
--- a/history/information.go
+++ b/history/information.go
@@ -4,6 +4,7 @@ package history
import (
"fmt"
+ "log"
"regexp"
"strconv"
"strings"
@@ -22,7 +23,7 @@ func recentChangesFeed() *feeds.Feed {
Updated: time.Now(),
}
var (
- out, err = gitsh(
+ out, err = silentGitsh(
"log", "--oneline", "--no-merges",
"--pretty=format:\"%h\t%ae\t%at\t%s\"",
"--max-count=30",
@@ -34,6 +35,7 @@ func recentChangesFeed() *feeds.Feed {
revs = append(revs, parseRevisionLine(line))
}
}
+ log.Printf("Found %d recent changes", len(revs))
for _, rev := range revs {
feed.Add(&feeds.Item{
Title: rev.Message,
@@ -62,7 +64,7 @@ func RecentChangesJSON() (string, error) {
func RecentChanges(n int) []Revision {
var (
- out, err = gitsh(
+ out, err = silentGitsh(
"log", "--oneline", "--no-merges",
"--pretty=format:\"%h\t%ae\t%at\t%s\"",
"--max-count="+strconv.Itoa(n),
@@ -74,6 +76,7 @@ func RecentChanges(n int) []Revision {
revs = append(revs, parseRevisionLine(line))
}
}
+ log.Printf("Found %d recent changes", len(revs))
return revs
}
@@ -86,7 +89,7 @@ func FileChanged(path string) bool {
// Revisions returns slice of revisions for the given hypha name.
func Revisions(hyphaName string) ([]Revision, error) {
var (
- out, err = gitsh(
+ out, err = silentGitsh(
"log", "--oneline", "--no-merges",
// Hash, author email, author time, commit msg separated by tab
"--pretty=format:\"%h\t%ae\t%at\t%s\"",
@@ -101,6 +104,7 @@ func Revisions(hyphaName string) ([]Revision, error) {
}
}
}
+ log.Printf("Found %d revisions for ā%sā\n", len(revs), hyphaName)
return revs, err
}
@@ -177,6 +181,6 @@ func FileAtRevision(filepath, hash string) (string, error) {
}
func PrimitiveDiffAtRevision(filepath, hash string) (string, error) {
- out, err := gitsh("diff", "--unified=1", "--no-color", hash+"~", hash, "--", filepath)
+ out, err := silentGitsh("diff", "--unified=1", "--no-color", hash+"~", hash, "--", filepath)
return out.String(), err
}
diff --git a/views/stuff.qtpl.go b/views/stuff.qtpl.go
index b036779..cd170a0 100644
--- a/views/stuff.qtpl.go
+++ b/views/stuff.qtpl.go
@@ -352,7 +352,7 @@ func StreamAboutHTML(qw422016 *qt422016.Writer) {
//line views/stuff.qtpl:98
qw422016.N().S(`