-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #20 from bouncepaw/0.8
0.8
- Loading branch information
Showing
20 changed files
with
1,213 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ run: build | |
./mycorrhiza metarrhiza | ||
|
||
build: | ||
go generate | ||
go build . | ||
|
||
test: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,35 @@ | ||
# mycorrhiza wiki | ||
A wiki engine inspired by fungi. Not production-ready. | ||
# 🍄 MycorrhizaWiki 0.8 | ||
A wiki engine. | ||
|
||
Current version: 0.7 (or more?) | ||
## Installation | ||
```sh | ||
git clone --recurse-submodules https://github.com/bouncepaw/mycorrhiza | ||
cd mycorrhiza | ||
make | ||
# That make will: | ||
# * run the default wiki. You can edit it right away. | ||
# * create an executable called `mycorrhiza`. Run it with path to your wiki. | ||
``` | ||
|
||
## Current features | ||
* Edit pages through html forms | ||
* Responsive design | ||
* Works in text browsers | ||
* Pages (called hyphae) can be in gemtext. | ||
* Wiki pages (called hyphae) are in gemtext | ||
* Everything is stored as simple files, no database required | ||
* Page trees | ||
* Changes are saved to git | ||
* List of hyphae page | ||
* History page | ||
* Random page | ||
* Light on resources: I run a home wiki on this engine 24/7 at an [Orange π Lite](http://www.orangepi.org/orangepilite/). | ||
|
||
## Future features | ||
* Tags | ||
* Authorization | ||
* History view | ||
* Granular user rights | ||
|
||
## Installation | ||
I guess you can just clone this repo and run `make` to play around with the default wiki. | ||
## Contributing | ||
Help is always needed. We have a [tg chat](https://t.me/mycorrhizadev) where some development is coordinated. Feel free to open an issue or contact me. | ||
|
||
## Future plans | ||
* Tagging system | ||
* Authorization | ||
* Better history viewing | ||
* Recent changes page | ||
* More markups |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,15 @@ | ||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= | ||
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= | ||
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= | ||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= | ||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= | ||
github.com/valyala/fasthttp v1.15.1/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA= | ||
github.com/valyala/quicktemplate v1.6.2 h1:k0vgK7zlmFzqAoIBIOrhrfmZ6JoTGJlLRPLbkPGr2/M= | ||
github.com/valyala/quicktemplate v1.6.2/go.mod h1:mtEJpQtUiBV0SHhMX6RtiJtqxncgrfmjcUy5T68X8TM= | ||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= | ||
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-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-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/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/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-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
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= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package history | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"log" | ||
"os/exec" | ||
"strconv" | ||
"time" | ||
|
||
"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 | ||
} | ||
|
||
// 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͡ʃ]. | ||
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", from, to) | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// information.go | ||
// Things related to gathering existing information. | ||
package history | ||
|
||
import ( | ||
"fmt" | ||
"regexp" | ||
"strings" | ||
"time" | ||
) | ||
|
||
// Revisions returns slice of revisions for the given hypha name. | ||
func Revisions(hyphaName string) ([]Revision, error) { | ||
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\"", | ||
"--", hyphaName+"&.*", | ||
) | ||
revs []Revision | ||
) | ||
if err == nil { | ||
for _, line := range strings.Split(out.String(), "\n") { | ||
revs = append(revs, parseRevisionLine(line)) | ||
} | ||
} | ||
return revs, err | ||
} | ||
|
||
// 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], | ||
} | ||
} | ||
|
||
// Represent revision as a table row. | ||
func (rev *Revision) AsHtmlTableRow(hyphaName string) string { | ||
return fmt.Sprintf(` | ||
<tr> | ||
<td><time>%s</time></td> | ||
<td><a href="/rev/%s/%s">%s</a></td> | ||
<td>%s</td> | ||
</tr>`, rev.Time.Format(time.RFC822), rev.Hash, hyphaName, rev.Hash, rev.Message) | ||
} | ||
|
||
// See how the file with `filepath` looked at commit with `hash`. | ||
func FileAtRevision(filepath, hash string) (string, error) { | ||
out, err := gitsh("show", hash+":"+filepath) | ||
return out.String(), err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// history/operations.go | ||
// Things related to writing history. | ||
package history | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/bouncepaw/mycorrhiza/util" | ||
) | ||
|
||
// OpType is the type a history operation has. Callers shall set appropriate optypes when creating history operations. | ||
type OpType int | ||
|
||
const ( | ||
TypeNone OpType = iota | ||
TypeEditText | ||
TypeEditBinary | ||
) | ||
|
||
// HistoryOp is an object representing a history operation. | ||
type HistoryOp struct { | ||
// All errors are appended here. | ||
Errs []error | ||
opType OpType | ||
userMsg string | ||
name string | ||
email string | ||
} | ||
|
||
// Operation is a constructor of a history operation. | ||
func Operation(opType OpType) *HistoryOp { | ||
hop := &HistoryOp{ | ||
Errs: []error{}, | ||
opType: opType, | ||
} | ||
return hop | ||
} | ||
|
||
// git operation maker helper | ||
func (hop *HistoryOp) gitop(args ...string) *HistoryOp { | ||
out, err := gitsh(args...) | ||
if err != nil { | ||
fmt.Println("out:", out.String()) | ||
hop.Errs = append(hop.Errs, err) | ||
} | ||
return hop | ||
} | ||
|
||
// WithFiles stages all passed `paths`. Paths can be rooted or not. | ||
func (hop *HistoryOp) WithFiles(paths ...string) *HistoryOp { | ||
for i, path := range paths { | ||
paths[i] = util.ShorterPath(path) | ||
} | ||
// 1 git operation is more effective than n operations. | ||
return hop.gitop(append([]string{"add"}, paths...)...) | ||
} | ||
|
||
// Apply applies history operation by doing the commit. | ||
func (hop *HistoryOp) Apply() *HistoryOp { | ||
hop.gitop( | ||
"commit", | ||
"--author='"+hop.name+" <"+hop.email+">'", | ||
"--message="+hop.userMsg, | ||
) | ||
return hop | ||
} | ||
|
||
// WithMsg sets what message will be used for the future commit. If user message exceeds one line, it is stripped down. | ||
func (hop *HistoryOp) WithMsg(userMsg string) *HistoryOp { | ||
for _, ch := range userMsg { | ||
if ch == '\r' || ch == '\n' { | ||
break | ||
} | ||
hop.userMsg += string(ch) | ||
} | ||
return hop | ||
} | ||
|
||
// WithSignature sets a signature for the future commit. You need to pass a username only, the rest is upon us (including email and time). | ||
func (hop *HistoryOp) WithSignature(username string) *HistoryOp { | ||
hop.name = username | ||
hop.email = username + "@mycorrhiza" // A fake email, why not | ||
return hop | ||
} |
Oops, something went wrong.