changeset 0:aa664e434d43

init backup project
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Wed, 16 Dec 2020 14:07:18 +0900
parents
children b8ad430d968d
files .hgignore Makefile backup.go go.sum run.go
diffstat 5 files changed, 164 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Wed Dec 16 14:07:18 2020 +0900
@@ -0,0 +1,27 @@
+syntax:glob
+
+# Created by https://www.toptal.com/developers/gitignore/api/go
+# Edit at https://www.toptal.com/developers/gitignore?templates=go
+
+### Go ###
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+# vendor/
+
+### Go Patch ###
+/vendor/
+/Godeps/
+
+# End of https://www.toptal.com/developers/gitignore/api/go
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Wed Dec 16 14:07:18 2020 +0900
@@ -0,0 +1,3 @@
+all:
+	go build ./cmd/growibackup
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/backup.go	Wed Dec 16 14:07:18 2020 +0900
@@ -0,0 +1,120 @@
+package growibackup
+
+import (
+	"bufio"
+	"encoding/json"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
+
+	"golang.org/x/xerrors"
+)
+
+// Revision is growy entry struct
+type Revision struct {
+	ID            string    `json:"_id"`
+	Format        string    `json:"format"`
+	CreatedAt     time.Time `json:"createdAt"`
+	Path          string    `json:"path"`
+	Body          string    `json:"body"`
+	Author        string    `json:"author"`
+	HasDiffToPrev bool      `json:"hasDiffToPrev"`
+	V             int       `json:"__v"`
+}
+
+// Revisions is as equal as revision.json
+type Revisions []Revision
+
+func convertStructFromJSON(jsonPATH string) (*Revisions, error) {
+	file, err := ioutil.ReadFile(jsonPATH)
+	if err != nil {
+		return nil, xerrors.Errorf("[error] failed open %s, %+w", jsonPATH, err)
+	}
+
+	revs := Revisions{}
+	err = json.Unmarshal([]byte(file), &revs)
+
+	if err != nil {
+		return nil, xerrors.Errorf("[error] failed unmarshal json %s, %+w", jsonPATH, err)
+	}
+
+	return &revs, nil
+}
+
+func (revs *Revisions) createUniqRevisions() *Revisions {
+	path2Revision := make(map[string]Revision)
+	for _, rev := range *revs {
+		if prevRev, ok := path2Revision[rev.Path]; ok {
+			if prevRev.CreatedAt.After(rev.CreatedAt) {
+				path2Revision[rev.Path] = rev
+			}
+			continue
+		}
+		path2Revision[rev.Path] = rev
+	}
+
+	newRevs := make(Revisions, 0, len(path2Revision))
+	for _, rev := range path2Revision {
+		newRevs = append(newRevs, rev)
+	}
+	return &newRevs
+}
+
+func (revs *Revisions) backup(outputPATH string) error {
+	var sbuilder strings.Builder
+	path2Exists := make(map[string]bool)
+
+	oPATH, err := getAbsRootPATH(outputPATH)
+	if err != nil {
+		return xerrors.Errorf("[error] failed get abs at %s %+w", outputPATH, err)
+	}
+
+	for _, rev := range *revs {
+		sbuilder.WriteString(rev.Path)
+		sbuilder.WriteString(".md")
+		path := sbuilder.String()
+		sbuilder.Reset()
+
+		mdPATH := filepath.Join(oPATH, path)
+		dirPATH := filepath.Dir(mdPATH)
+		if _, ok := path2Exists[dirPATH]; !ok {
+			err := checkAfterMkdir(dirPATH)
+			if err != nil {
+				return err
+			}
+		}
+
+		f, err := os.Create(mdPATH)
+		if err != nil {
+			return xerrors.Errorf("[error] failed create %s, %+w", mdPATH, err)
+		}
+		w := bufio.NewWriter(f)
+		w.WriteString(rev.Body)
+		w.Flush()
+		f.Close()
+	}
+	return nil
+}
+
+func checkAfterMkdir(dirpath string) error {
+	if _, err := os.Stat(dirpath); os.IsNotExist(err) {
+		err := os.MkdirAll(dirpath, 0755)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func getAbsRootPATH(outputPath string) (string, error) {
+	if !filepath.IsAbs(outputPath) {
+		oPATH, err := filepath.Abs(outputPath)
+		if err != nil {
+			return "", err
+		}
+		return oPATH, nil
+	}
+	return outputPath, nil
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/go.sum	Wed Dec 16 14:07:18 2020 +0900
@@ -0,0 +1,2 @@
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/run.go	Wed Dec 16 14:07:18 2020 +0900
@@ -0,0 +1,12 @@
+package growibackup
+
+import "golang.org/x/xerrors"
+
+func Run(jsonPATH, outputRootPATH string) error {
+	revisions, err := convertStructFromJSON(jsonPATH)
+	if err != nil {
+		return xerrors.Errorf("[error] fialed convert struct from json %+w", err)
+	}
+	revisions = revisions.createUniqRevisions()
+	return revisions.backup(outputRootPATH)
+}