1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-08 05:47:07 +09:00
anytype-heart/cmd/debugtree/debugtree.go
AnastasiaShemyakinskaya beca62db25
GO-5105: fixes for DebugTree
Signed-off-by: AnastasiaShemyakinskaya <shem98a@mail.ru>
2025-02-14 19:46:57 +01:00

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)
}
}