mirror of
https://github.com/anyproto/anytype-heart.git
synced 2025-06-08 05:47:07 +09:00
184 lines
4.6 KiB
Go
184 lines
4.6 KiB
Go
//go:build cgo
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/goccy/go-graphviz"
|
|
"github.com/gogo/protobuf/jsonpb"
|
|
"github.com/gogo/protobuf/proto"
|
|
|
|
"github.com/anyproto/anytype-heart/core/block/editor/state"
|
|
"github.com/anyproto/anytype-heart/core/debug/exporter"
|
|
"github.com/anyproto/anytype-heart/pkg/lib/core/smartblock"
|
|
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
|
"github.com/anyproto/anytype-heart/util/pbtypes"
|
|
)
|
|
|
|
var (
|
|
file = flag.String("f", "", "path to debug file")
|
|
fromRoot = flag.Bool("r", false, "build from root of the tree")
|
|
makeJson = flag.Bool("j", false, "generate json file")
|
|
makeTree = flag.Bool("t", false, "generate graphviz file")
|
|
printState = flag.Bool("s", false, "print result state debug")
|
|
changeIdx = flag.Int("c", -1, "build tree before given index and print change")
|
|
objectStore = flag.Bool("o", false, "show object store info")
|
|
fileHashes = flag.Bool("h", false, "show file hashes in state")
|
|
)
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
if *file == "" {
|
|
flag.PrintDefaults()
|
|
return
|
|
}
|
|
fmt.Println("opening file...")
|
|
var (
|
|
st = time.Now()
|
|
ctx = context.Background()
|
|
)
|
|
res, err := exporter.ImportStorage(ctx, *file)
|
|
if err != nil {
|
|
log.Fatal("can't import the tree:", err)
|
|
}
|
|
defer res.Store.Close()
|
|
objectTree, err := res.CreateReadableTree(*fromRoot, "")
|
|
if err != nil {
|
|
log.Fatal("can't create readable tree:", err)
|
|
}
|
|
fmt.Printf("open archive done in %.1fs\n", time.Since(st).Seconds())
|
|
importer := exporter.NewTreeImporter(objectTree)
|
|
if *makeJson {
|
|
treeJson, err := importer.Json()
|
|
if err != nil {
|
|
log.Fatal("can't build json:", err)
|
|
}
|
|
res, err := json.MarshalIndent(treeJson, "", " ")
|
|
if err != nil {
|
|
log.Fatal("can't marshall json:", err)
|
|
}
|
|
tf, err := ioutil.TempFile("", "tree_*.json")
|
|
if err != nil {
|
|
log.Fatal("can't create temp file:", err)
|
|
}
|
|
fmt.Println("tree json file:", tf.Name())
|
|
tf.Write(res)
|
|
tf.Close()
|
|
}
|
|
|
|
if *changeIdx != -1 {
|
|
ch, err := importer.ChangeAt(*changeIdx)
|
|
if err != nil {
|
|
log.Fatal("can't get the change in tree: ", err)
|
|
}
|
|
fmt.Println("Change:")
|
|
fmt.Println(pbtypes.Sprint(ch.Model))
|
|
objectTree, err = res.CreateReadableTree(*fromRoot, ch.Id)
|
|
if err != nil {
|
|
log.Fatal("can't create readable tree:", err)
|
|
}
|
|
importer = exporter.NewTreeImporter(objectTree)
|
|
}
|
|
ot := importer.ObjectTree()
|
|
di, err := ot.Debug(state.ChangeParser{})
|
|
if err != nil {
|
|
log.Fatal("can't get debug info from tree", err)
|
|
}
|
|
fmt.Printf("Tree root:\t%s\nTree len:\t%d\nTree heads:\t%s\n",
|
|
ot.Root().Id,
|
|
di.TreeLen,
|
|
strings.Join(di.Heads, ","))
|
|
|
|
if *printState {
|
|
fmt.Println("Building state...")
|
|
stt := time.Now()
|
|
s, err := importer.State()
|
|
if err != nil {
|
|
log.Fatal("can't build state:", err)
|
|
}
|
|
dur := time.Since(stt)
|
|
fmt.Println(s.StringDebug())
|
|
|
|
payload := &model.ObjectChangePayload{}
|
|
err = proto.Unmarshal(ot.ChangeInfo().ChangePayload, payload)
|
|
if err != nil {
|
|
return
|
|
}
|
|
sbt := smartblock.SmartBlockType(payload.SmartBlockType)
|
|
fmt.Printf("Smarblock type:\t%v\n", sbt.ToProto())
|
|
if *fileHashes {
|
|
fmt.Println("File keys:")
|
|
for _, fk := range s.GetAndUnsetFileKeys() {
|
|
fmt.Printf("\t%s: %d\n", fk.Hash, len(fk.Keys))
|
|
}
|
|
}
|
|
fmt.Println("state building time:", dur)
|
|
}
|
|
|
|
if *objectStore {
|
|
fmt.Println("fetch object store info..")
|
|
f, err := os.Open(filepath.Join(res.FolderPath, "localstore.json"))
|
|
if err != nil {
|
|
log.Fatal("can't open objectStore info:", err)
|
|
}
|
|
info := &model.ObjectInfo{}
|
|
if err = jsonpb.Unmarshal(f, info); err != nil {
|
|
log.Fatal("can't unmarshal objectStore info:", err)
|
|
}
|
|
defer f.Close()
|
|
fmt.Println(pbtypes.Sprint(info))
|
|
}
|
|
|
|
if *makeTree {
|
|
gvo, err := graphviz.ParseBytes([]byte(di.Graphviz))
|
|
if err != nil {
|
|
log.Fatal("can't open graphviz data:", err)
|
|
}
|
|
tf, err := ioutil.TempFile("", "tree_*.svg")
|
|
if err != nil {
|
|
log.Fatal("can't create temp file:", err)
|
|
}
|
|
ctx := context.Background()
|
|
g, err := graphviz.New(ctx)
|
|
if err != nil {
|
|
log.Fatal("can't open graphviz:", err)
|
|
}
|
|
err = g.Render(ctx, gvo, graphviz.SVG, tf)
|
|
if err != nil {
|
|
log.Fatal("can't render graphviz:", err)
|
|
}
|
|
fmt.Println("tree file:", tf.Name())
|
|
tf.Close()
|
|
open(tf.Name())
|
|
}
|
|
}
|
|
|
|
func open(path string) {
|
|
var err error
|
|
|
|
switch runtime.GOOS {
|
|
case "linux":
|
|
err = exec.Command("xdg-open", path).Start()
|
|
case "windows":
|
|
err = exec.Command("rundll32", "rl.dll,FileProtocolHandler", path).Start()
|
|
case "darwin":
|
|
err = exec.Command("open", path).Start()
|
|
default:
|
|
err = fmt.Errorf("unsupported platform")
|
|
}
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|