1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-01-05 17:40:26 +00:00

WIP history page

This commit is contained in:
Timur Ismagilov 2020-08-19 23:54:23 +05:00
parent c03f8be5cd
commit 60fcbdd30d
10 changed files with 169 additions and 42 deletions

1
data Submodule

@ -0,0 +1 @@
Subproject commit b2e78031973e4a6844d943333e823c0714e7a673

6
go.mod
View File

@ -2,8 +2,4 @@ module github.com/bouncepaw/mycorrhiza
go 1.14
require (
github.com/go-git/go-git/v5 v5.1.0
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6 // indirect
)
require github.com/go-git/go-git/v5 v5.1.0

28
go.sum
View File

@ -12,8 +12,6 @@ github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
github.com/go-git/go-git v1.0.0 h1:YcN9iDGDoXuIw0vHls6rINwV416HYa0EB2X+RBsyYp4=
github.com/go-git/go-git v4.7.0+incompatible h1:+W9rgGY4DOKKdX2x6HxSR7HNeTxqiKrOvKnuittYVdA=
github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
github.com/go-git/go-git/v5 v5.1.0 h1:HxJn9g/E7eYvKW3Fm7Jt4ee8LXfPOm/H1cdDu8vEssk=
github.com/go-git/go-git/v5 v5.1.0/go.mod h1:ZKfuPUoY1ZqIG4QG9BDBh3G4gLM5zvPuSJAozQrZuyM=
@ -40,41 +38,21 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 h1:EBZoQjiKKPaLbPrbpssUfuHtwM6KV/vb4U85g/cigFY=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6 h1:qKpj8TpV+LEhel7H/fR788J+KvhWZ3o3V6N2fU/iuLU=
golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -3,6 +3,7 @@ package history
import (
"fmt"
"log"
"os"
"time"
"github.com/bouncepaw/mycorrhiza/util"
@ -107,9 +108,10 @@ func (hop *HistoryOp) Apply() *HistoryOp {
return hop
}
// Rename renames from `from` to `to`. NB. It uses os.Rename internally rather than git.Move because git.Move works wrong for some reason.
func Rename(from, to string) error {
log.Println(util.ShorterPath(from), util.ShorterPath(to))
_, err := Worktree.Move(util.ShorterPath(from), util.ShorterPath(to))
err := os.Rename(from, to)
return err
}

100
history/sh.go Normal file
View File

@ -0,0 +1,100 @@
package history
import (
"bytes"
"fmt"
"log"
"os/exec"
"regexp"
"strconv"
"strings"
"time"
)
type Revision struct {
Hash string
Username string
Time time.Time
Message string
}
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͡ʃ].
func gitsh(args ...string) (out bytes.Buffer, err error) {
cmd := exec.Command(gitpath, args...)
cmd.Stdout = &out
cmd.Run()
if err != nil {
log.Println("gitsh:", err)
}
return out, err
}
func Revisions(filepath string) ([]Revision, error) {
if filepath == "" {
return []Revision{}, nil
}
var (
out, err = gitsh(
"log", "--oneline", "--no-merges",
// Hash, Commiter email, Commiter time, Commit msg separated by tab
"--pretty=format:\"%h\t%ce\t%ct\t%s\"",
"--", filepath,
)
revs []Revision
)
if err == nil {
for _, line := range strings.Split(out.String(), "\n") {
if rev := parseRevisionLine(line); rev != nil {
revs = append(revs, *rev)
}
}
}
return revs, err
}
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
}
// 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 {
var (
results = revisionLinePattern.FindStringSubmatch(line)
rev = Revision{
Hash: results[1],
Username: results[2],
Time: *unixTimestampAsTime(results[3]),
Message: results[4],
}
)
return &rev
}
func (rev *Revision) AsHtmlTableRow() string {
return fmt.Sprintf(`
<tr>
<td>%s</td>
<td>%s</td>
<td><time>%s</time></td>
<td>%s</td>
</tr>`, rev.Hash, rev.Username, rev.Time.String(), rev.Message)
}

View File

@ -134,11 +134,6 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) {
if err := os.MkdirAll(filepath.Dir(fullPath), 0777); err != nil {
log.Println(err)
}
if err = ioutil.WriteFile(fullPath, data, 0644); err != nil {
HttpErr(w, http.StatusInternalServerError, hyphaName, "Error",
"Could not save passed data")
return
}
if !isOld {
HyphaStorage[hyphaName] = &HyphaData{
binaryPath: fullPath,
@ -155,9 +150,14 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) {
hyphaData.binaryPath = fullPath
hyphaData.binaryType = mimeType
}
if err = ioutil.WriteFile(fullPath, data, 0644); err != nil {
HttpErr(w, http.StatusInternalServerError, hyphaName, "Error",
"Could not save passed data")
return
}
log.Println("Written", len(data), "of binary data for", hyphaName, "to path", fullPath)
history.Operation(history.TypeEditText).
WithFiles(fullPath).
WithFiles(fullPath, hyphaData.binaryPath).
WithMsg(fmt.Sprintf("Upload binary part for %s with type %s", hyphaName, mimeType.Mime())).
WithSignature("anon").
Apply()

View File

@ -8,6 +8,7 @@ import (
"os"
"github.com/bouncepaw/mycorrhiza/gemtext"
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/tree"
)
@ -15,6 +16,49 @@ func init() {
http.HandleFunc("/page/", handlerPage)
http.HandleFunc("/text/", handlerText)
http.HandleFunc("/binary/", handlerBinary)
http.HandleFunc("/history/", handlerHistory)
}
// handlerHistory lists all revisions of a hypha
func handlerHistory(w http.ResponseWriter, rq *http.Request) {
log.Println(rq.URL)
hyphaName := HyphaNameFromRq(rq, "history")
var tbody string
if data, ok := HyphaStorage[hyphaName]; ok {
revsT, err := history.Revisions(data.textPath)
if err == nil {
for _, rev := range revsT {
tbody += rev.AsHtmlTableRow()
}
}
revsB, err := history.Revisions(data.binaryPath)
if err == nil {
for _, rev := range revsB {
tbody += rev.AsHtmlTableRow()
}
}
log.Println(revsT, revsB)
}
table := fmt.Sprintf(`
<main>
<table>
<thead>
<tr>
<th>Hash</th>
<th>Username</th>
<th>Time</th>
<th>Message</th>
</tr>
</thead>
<tbody>
%s
</tbody>
</table>
</main>`, tbody)
w.Header().Set("Content-Type", "text/html;charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write([]byte(base(hyphaName, table)))
}
// handlerText serves raw source text of the hypha.

View File

@ -130,6 +130,9 @@ func main() {
if err != nil {
log.Fatal(err)
}
if err := os.Chdir(WikiDir); err != nil {
log.Fatal(err)
}
log.Println("Wiki storage directory is", WikiDir)
log.Println("Start indexing hyphae...")
Index(WikiDir)
@ -138,7 +141,7 @@ func main() {
history.Start(WikiDir)
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(WikiDir+"/static"))))
// See http_readers.go for /page/, /text/, /binary/.
// See http_readers.go for /page/, /text/, /binary/, /history/.
// See http_mutators.go for /upload-binary/, /upload-text/, /edit/.
http.HandleFunc("/list", handlerList)
http.HandleFunc("/reindex", handlerReindex)

@ -1 +1 @@
Subproject commit 30287be4496638e342878e2adf50e0a74ce71a5f
Subproject commit 2f58d4e9663806496d7edfdeb24098abe986f454

View File

@ -60,9 +60,6 @@ func (t *tree) fill() {
// It applies itself recursively on the tree's children.
func (t *tree) asHtml() (html string) {
if t.root {
for _, siblingName := range t.siblings {
html += navitreeEntry(siblingName, "navitree__sibling")
}
html += navitreeEntry(t.name, "navitree__pagename")
} else {
html += navitreeEntry(t.name, "navitree__name")
@ -72,6 +69,12 @@ func (t *tree) asHtml() (html string) {
html += subtree.asHtml()
}
if t.root {
for _, siblingName := range t.siblings {
html += navitreeEntry(siblingName, "navitree__sibling")
}
}
return `<ul class="navitree__node">` + html + `</ul>`
}