package main import ( "bufio" "bytes" "github.com/sergi/go-diff/diffmatchpatch" "html" "html/template" "io/ioutil" "log" "os" "os/exec" "path/filepath" "strings" ) type FilePages struct { dirname string } func NewFilePages(dirname string) PagesRepository { fp := &FilePages{dirname} return fp } func (fp *FilePages) Get(p string) Page { f, err := os.Open(filepath.Join(fp.dirname, strings.Replace(p, " ", "_", -1))) if err != nil { return Page{} } defer f.Close() body, err := ioutil.ReadAll(f) if err != nil { return Page{} } return Page{Content: string(body)} } func (fp *FilePages) Save(p string, page Page, summary, author string) { f, err := os.Create(filepath.Join(fp.dirname, strings.Replace(p, " ", "_", -1))) if err != nil { return } defer f.Close() f.WriteString(strings.Replace(page.Content, "\r\n", "\n", -1)) saveWithGit(fp, p, summary, author) return } func saveWithGit(fp *FilePages, p string, summary, author string) { cmd := exec.Command("git", "add", ".") cmd.Dir = fp.dirname err := cmd.Run() if err != nil { log.Println(err) return } cmd = exec.Command("git", "commit", "-m", "Changes to "+p+" by "+author+"\n\n"+summary) cmd.Dir = fp.dirname err = cmd.Run() if err != nil { log.Println(err) return } } func (fp *FilePages) Exist(p string) bool { f, err := os.Open(filepath.Join(fp.dirname, strings.Replace(p, " ", "_", -1))) if err != nil { return os.IsExist(err) } f.Close() return true } func DiffPrettyHtml(diffs []diffmatchpatch.Diff) string { var buff bytes.Buffer for _, diff := range diffs { // text := strings.Replace(html.EscapeString(diff.Text), "\n", "
", -1) text := html.EscapeString(diff.Text) switch diff.Type { case diffmatchpatch.DiffInsert: _, _ = buff.WriteString("") _, _ = buff.WriteString(text) _, _ = buff.WriteString("") case diffmatchpatch.DiffDelete: _, _ = buff.WriteString("") _, _ = buff.WriteString(text) _, _ = buff.WriteString("") case diffmatchpatch.DiffEqual: _, _ = buff.WriteString("") _, _ = buff.WriteString(text) _, _ = buff.WriteString("") } } return buff.String() } func (fp *FilePages) PageHistory(p string) ([]Revision, error) { page := strings.Replace(p, " ", "_", -1) cmd := exec.Command("git", "log", "--pretty=oneline", "--no-decorate", "--color=never", page) cmd.Dir = fp.dirname output, err := cmd.StdoutPipe() if err != nil { return nil, err } defer output.Close() err = cmd.Start() if err != nil { log.Println("Start") return nil, err } buf := bufio.NewScanner(output) var revisions []Revision for buf.Scan() { line := buf.Text() start := strings.Index(line, " ") commitId := line[0:start] rest := line[start+1:] pageText := gitRevision(fp.dirname, page, commitId) revisions = append(revisions, Revision{ Version: commitId, Page: DiffPage{Content: pageText}, Summary: rest, }) } dmp := diffmatchpatch.New() prevText := "" for i := len(revisions) - 1; i >= 0; i-- { diffs := dmp.DiffMain(prevText, revisions[i].Page.Content, false) revisions[i].Page.Diff = template.HTML(DiffPrettyHtml(diffs)) prevText = revisions[i].Page.Content } if err := cmd.Wait(); err != nil { log.Println("wait") return nil, err } return revisions, nil } func gitRevision(dirname, page, version string) string { cmd := exec.Command("git", "show", version+":"+page) cmd.Dir = dirname buf := bytes.Buffer{} cmd.Stdout = &buf cmd.Start() cmd.Wait() return buf.String() }