this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

add missing file

why ddd8201b 1af365ef

+205
+205
mst/diff.go
··· 1 + package mst 2 + 3 + import ( 4 + "context" 5 + "fmt" 6 + "sort" 7 + 8 + cid "github.com/ipfs/go-cid" 9 + blockstore "github.com/ipfs/go-ipfs-blockstore" 10 + cbor "github.com/ipfs/go-ipld-cbor" 11 + ) 12 + 13 + type DiffOp struct { 14 + Depth int 15 + Op string 16 + Tid string 17 + OldCid cid.Cid 18 + NewCid cid.Cid 19 + } 20 + 21 + func DiffTrees(ctx context.Context, bs blockstore.Blockstore, from, to cid.Cid) ([]*DiffOp, error) { 22 + cst := cbor.NewCborStore(bs) 23 + 24 + ft := LoadMST(cst, 32, from) 25 + tt := LoadMST(cst, 32, to) 26 + 27 + return diffTreesRec(ctx, cst, ft, tt, 1) 28 + } 29 + 30 + func checkDiffSort(diffs []*DiffOp) { 31 + if !sort.SliceIsSorted(diffs, func(i, j int) bool { 32 + return diffs[i].Tid < diffs[j].Tid 33 + }) { 34 + panic(fmt.Sprintf("diff results not properly sorted! %d", len(diffs))) 35 + } 36 + } 37 + 38 + func diffTreesRec(ctx context.Context, cst cbor.IpldStore, ft, tt *MerkleSearchTree, depth int) ([]*DiffOp, error) { 39 + // TODO: this code isnt great, should be rewritten on top of the baseline datastructures once functional and correct 40 + fents, err := ft.getEntries(ctx) 41 + if err != nil { 42 + return nil, err 43 + } 44 + 45 + tents, err := tt.getEntries(ctx) 46 + if err != nil { 47 + return nil, err 48 + } 49 + 50 + var ixf, ixt int 51 + var out []*DiffOp 52 + for ixf < len(fents) && ixt < len(tents) { 53 + ef := fents[ixf] 54 + et := tents[ixt] 55 + 56 + if nodeEntriesEqual(&ef, &et) { 57 + ixf++ 58 + ixt++ 59 + continue 60 + } 61 + 62 + if ef.isLeaf() && et.isLeaf() { 63 + if ef.Key == et.Key { 64 + if ef.Val == et.Val { 65 + return nil, fmt.Errorf("hang on, why are these leaves equal?") 66 + } 67 + 68 + out = append(out, &DiffOp{ 69 + Op: "mut", 70 + Tid: ef.Key, 71 + OldCid: ef.Val, 72 + NewCid: et.Val, 73 + }) 74 + ixf++ 75 + ixt++ 76 + continue 77 + } 78 + // different keys... what do? 79 + 80 + // if the 'to' key is earlier than the 'from' key, call it an insert 81 + // otherwise call it a deletion? 82 + 83 + if ef.Key > et.Key { 84 + out = append(out, &DiffOp{ 85 + Op: "add", 86 + Tid: et.Key, 87 + NewCid: et.Val, 88 + }) 89 + // only walk forward the pointer that was 'behind' 90 + ixt++ 91 + } else { 92 + out = append(out, &DiffOp{ 93 + Op: "del", 94 + Tid: ef.Key, 95 + OldCid: ef.Val, 96 + }) 97 + // only walk forward the pointer that was 'behind' 98 + ixf++ 99 + } 100 + 101 + // call it an insertion? 102 + continue 103 + } 104 + 105 + if ef.isTree() { 106 + sub, err := ef.Tree.getEntries(ctx) 107 + if err != nil { 108 + return nil, err 109 + } 110 + 111 + fents = append(sub, fents[ixf+1:]...) 112 + ixf = 0 113 + continue 114 + } 115 + 116 + if et.isTree() { 117 + sub, err := et.Tree.getEntries(ctx) 118 + if err != nil { 119 + return nil, err 120 + } 121 + 122 + tents = append(sub, tents[ixt+1:]...) 123 + ixt = 0 124 + continue 125 + } 126 + } 127 + 128 + for ; ixf < len(fents); ixf++ { 129 + // deletions 130 + 131 + e := fents[ixf] 132 + if e.isLeaf() { 133 + out = append(out, &DiffOp{ 134 + Op: "del", 135 + Tid: e.Key, 136 + OldCid: e.Val, 137 + }) 138 + 139 + } else if e.isTree() { 140 + if err := e.Tree.WalkLeavesFrom(ctx, "", func(n NodeEntry) error { 141 + out = append(out, &DiffOp{ 142 + Op: "del", 143 + Tid: n.Key, 144 + OldCid: n.Val, 145 + }) 146 + return nil 147 + }); err != nil { 148 + return nil, err 149 + } 150 + } 151 + } 152 + 153 + for ; ixt < len(tents); ixt++ { 154 + // insertions 155 + 156 + e := tents[ixt] 157 + if e.isLeaf() { 158 + out = append(out, &DiffOp{ 159 + Op: "add", 160 + Tid: e.Key, 161 + NewCid: e.Val, 162 + }) 163 + 164 + } else if e.isTree() { 165 + if err := e.Tree.WalkLeavesFrom(ctx, "", func(n NodeEntry) error { 166 + out = append(out, &DiffOp{ 167 + Op: "add", 168 + Tid: n.Key, 169 + NewCid: n.Val, 170 + }) 171 + return nil 172 + }); err != nil { 173 + return nil, err 174 + } 175 + } 176 + } 177 + 178 + return out, nil 179 + } 180 + 181 + func nodeEntriesEqual(a, b *NodeEntry) bool { 182 + if !(a.Key == b.Key && a.Val == b.Val) { 183 + return false 184 + } 185 + 186 + if a.Tree == nil && b.Tree == nil { 187 + return true 188 + } 189 + 190 + if a.Tree != nil && b.Tree != nil && a.Tree.pointer == b.Tree.pointer { 191 + return true 192 + } 193 + 194 + return false 195 + } 196 + 197 + func sameCidPtr(a, b *cid.Cid) bool { 198 + if a == nil && b == nil { 199 + return true 200 + } 201 + if a != nil && b != nil && *a == *b { 202 + return true 203 + } 204 + return false 205 + }