package main import ( "flag" "fmt" "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" "github.com/anytypeio/go-anytype-middleware/pb" "github.com/gogo/protobuf/proto" "io/ioutil" "log" "os/exec" "runtime" "time" "github.com/anytypeio/go-anytype-middleware/core/debug/debugtree" "github.com/anytypeio/go-anytype-middleware/pkg/lib/core/smartblock" "github.com/anytypeio/go-anytype-middleware/util/pbtypes" "github.com/goccy/go-graphviz" ) var ( file = flag.String("f", "", "path to debug 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...") st := time.Now() dt, err := debugtree.Open(*file) if err != nil { log.Fatal("can't open debug file:", err) } defer dt.Close() fmt.Printf("open tree done in %.1fs\n", time.Since(st).Seconds()) fmt.Println(dt.Stats().MlString()) if *changeIdx != -1 { id := "" i := 0 dt.IterateFrom(dt.Root().Id, func(decrypted []byte) (any, error) { ch := &pb.Change{} err = proto.Unmarshal(decrypted, ch) if err != nil { return nil, err } return ch, nil }, func(change *objecttree.Change) bool { if change.Id == dt.Id() { return true } model := change.Model.(*pb.Change) if i == *changeIdx { id = change.Id fmt.Println("Change:") fmt.Println(pbtypes.Sprint(model)) return false } else { i++ } return true }) // TODO: [MR] Add full tree //if id != "" { // if t, err = change.BuildTreeBefore(context.TODO(), dt, id, true); err != nil { // log.Fatal("build tree before error:", err) // } //} } //fmt.Printf("Tree len:\t%d\n", .Len()) fmt.Printf("Tree root:\t%s\n", t.RootId()) if *printState { fmt.Println("Building state...") stt := time.Now() s, err := dt.BuildState() if err != nil { log.Fatal("can't build state:", err) } dur := time.Since(stt) fmt.Println(s.StringDebug()) sbt, _ := smartblock.SmartBlockTypeFromID(s.RootId()) 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..") ls, err := dt.LocalStore() if err != nil { fmt.Println("can't open objectStore info:", err) } else { fmt.Println(pbtypes.Sprint(ls)) } } if *makeTree { fmt.Println("saving tree file...") gv, err := t.Graphviz() if err != nil { log.Fatal("can't make graphviz data:", err) } gvo, err := graphviz.ParseBytes([]byte(gv)) 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) } g := graphviz.New() g.Render(gvo, graphviz.SVG, tf) 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) } }