github.com/ndau/noms@v1.0.5/go/merge/three_way.go (about) 1 // Copyright 2016 Attic Labs, Inc. All rights reserved. 2 // Licensed under the Apache License, version 2.0: 3 // http://www.apache.org/licenses/LICENSE-2.0 4 5 package merge 6 7 import ( 8 "fmt" 9 10 "github.com/ndau/noms/go/d" 11 "github.com/ndau/noms/go/types" 12 ) 13 14 // Policy functors are used to merge two values (a and b) against a common 15 // ancestor. All three Values and their must by wholly readable from vrw. 16 // Whenever a change is merged, implementations should send a struct{} over 17 // progress. 18 type Policy func(a, b, ancestor types.Value, vrw types.ValueReadWriter, progress chan struct{}) (merged types.Value, err error) 19 20 // ResolveFunc is the type for custom merge-conflict resolution callbacks. 21 // When the merge algorithm encounters two non-mergeable changes (aChange and 22 // bChange) at the same path, it calls the ResolveFunc passed into ThreeWay(). 23 // The callback gets the types of the two incompatible changes (added, changed 24 // or removed) and the two Values that could not be merged (if any). If the 25 // ResolveFunc cannot devise a resolution, ok should be false upon return and 26 // the other return values are undefined. If the conflict can be resolved, the 27 // function should return the appropriate type of change to apply, the new value 28 // to be used (if any), and true. 29 type ResolveFunc func(aChange, bChange types.DiffChangeType, a, b types.Value, path types.Path) (change types.DiffChangeType, merged types.Value, ok bool) 30 31 // None is the no-op ResolveFunc. Any conflict results in a merge failure. 32 func None(aChange, bChange types.DiffChangeType, a, b types.Value, path types.Path) (change types.DiffChangeType, merged types.Value, ok bool) { 33 return change, merged, false 34 } 35 36 // Ours resolves conflicts by preferring changes from the Value currently being committed. 37 func Ours(aChange, bChange types.DiffChangeType, a, b types.Value, path types.Path) (change types.DiffChangeType, merged types.Value, ok bool) { 38 return aChange, a, true 39 } 40 41 // Theirs resolves conflicts by preferring changes in the current HEAD. 42 func Theirs(aChange, bChange types.DiffChangeType, a, b types.Value, path types.Path) (change types.DiffChangeType, merged types.Value, ok bool) { 43 return bChange, b, true 44 } 45 46 // ErrMergeConflict indicates that a merge attempt failed and must be resolved 47 // manually for the provided reason. 48 type ErrMergeConflict struct { 49 msg string 50 } 51 52 func (e *ErrMergeConflict) Error() string { 53 return e.msg 54 } 55 56 func newMergeConflict(format string, args ...interface{}) *ErrMergeConflict { 57 return &ErrMergeConflict{fmt.Sprintf(format, args...)} 58 } 59 60 // NewThreeWay creates a new Policy based on ThreeWay using the provided 61 // ResolveFunc. 62 func NewThreeWay(resolve ResolveFunc) Policy { 63 return func(a, b, parent types.Value, vrw types.ValueReadWriter, progress chan struct{}) (merged types.Value, err error) { 64 return ThreeWay(a, b, parent, vrw, resolve, progress) 65 } 66 } 67 68 // ThreeWay attempts a three-way merge between two _candidate_ values that 69 // have both changed with respect to a common _parent_ value. The result of 70 // the algorithm is a _merged_ value or an error if merging could not be done. 71 // 72 // The algorithm works recursively, applying the following rules for each value: 73 // 74 // - If any of the three values have a different [kind](link): conflict 75 // - If the two candidates are identical: the result is that value 76 // - If the values are primitives or Blob: conflict 77 // - If the values are maps: 78 // - if the same key was inserted or updated in both candidates: 79 // - first run this same algorithm on those two values to attempt to merge them 80 // - if the two merged values are still different: conflict 81 // - if a key was inserted in one candidate and removed in the other: conflict 82 // - If the values are structs: 83 // - Same as map, except using field names instead of map keys 84 // - If the values are sets: 85 // - Apply the changes from both candidates to the parent to get the result. No conflicts are possible. 86 // - If the values are list: 87 // - Apply list-merge (see below) 88 // 89 // Merge rules for List are a bit more complex than Map, Struct, and Set due 90 // to a wider away of potential use patterns. A List might be a de-facto Map 91 // with sequential numeric keys, or it might be a sequence of objects where 92 // order matters but the caller is unlikely to go back and update the value at 93 // a given index. List modifications are expressed in terms of 'splices' (see 94 // types/edit_distance.go). Roughly, a splice indicates that some number of 95 // elements were added and/or removed at some index in |parent|. In the 96 // following example: 97 // 98 // parent: [a, b, c, d] 99 // a: [b, c, d] 100 // b: [a, b, c, d, e] 101 // merged: [b, c, d, e] 102 // 103 // The difference from parent -> is described by the splice {0, 1}, indicating 104 // that 1 element was removed from parent at index 0. The difference from 105 // parent -> b is described as {4, 0, e}, indicating that 0 elements were 106 // removed at parent's index 4, and the element 'e' was added. Our merge 107 // algorithm will successfully merge a and b, because these splices do not 108 // overlap; that is, neither one removes the index at which the other 109 // operates. As a general rule, the merge algorithm will refuse to merge 110 // splices that overlap, as in the following examples: 111 // 112 // parent: [a, b, c] 113 // a: [a, d, b, c] 114 // b: [a, c] 115 // merged: conflict 116 // 117 // parent: [a, b, c] 118 // a: [a, e, b, c] 119 // b: [a, d, b, c] 120 // merged: conflict 121 // 122 // The splices in the first example are {1, 0, d} (remove 0 elements at index 123 // 1 and add 'd') and {1, 1} (remove 1 element at index 1). Since the latter 124 // removes the element at which the former adds an element, these splices 125 // overlap. Similarly, in the second example, both splices operate at index 1 126 // but add different elements. Thus, they also overlap. 127 // 128 // There is one special case for overlapping splices. If they perform the 129 // exact same operation, the algorithm considers them not to be in conflict. 130 // E.g. 131 // 132 // parent: [a, b, c] 133 // a: [a, d, e] 134 // b: [a, d, e] 135 // merged: [a, d, e] 136 func ThreeWay(a, b, parent types.Value, vrw types.ValueReadWriter, resolve ResolveFunc, progress chan struct{}) (merged types.Value, err error) { 137 describe := func(v types.Value) string { 138 if v != nil { 139 return types.TypeOf(v).Describe() 140 } 141 return "nil Value" 142 } 143 144 if a == nil && b == nil { 145 return parent, nil 146 } else if unmergeable(a, b) { 147 return parent, newMergeConflict("Cannot merge %s with %s.", describe(a), describe(b)) 148 } 149 150 if resolve == nil { 151 resolve = None 152 } 153 m := &merger{vrw, resolve, progress} 154 return m.threeWay(a, b, parent, types.Path{}) 155 } 156 157 // a and b cannot be merged if they are of different NomsKind, or if at least one of the two is nil, or if either is a Noms primitive. 158 func unmergeable(a, b types.Value) bool { 159 if a != nil && b != nil { 160 aKind, bKind := a.Kind(), b.Kind() 161 return aKind != bKind || types.IsPrimitiveKind(aKind) || types.IsPrimitiveKind(bKind) 162 } 163 return true 164 } 165 166 type merger struct { 167 vrw types.ValueReadWriter 168 resolve ResolveFunc 169 progress chan<- struct{} 170 } 171 172 func updateProgress(progress chan<- struct{}) { 173 // TODO: Eventually we'll want more information than a single bit :). 174 if progress != nil { 175 progress <- struct{}{} 176 } 177 } 178 179 func (m *merger) threeWay(a, b, parent types.Value, path types.Path) (merged types.Value, err error) { 180 defer updateProgress(m.progress) 181 if a == nil || b == nil { 182 d.Panic("Merge candidates cannont be nil: a = %v, b = %v", a, b) 183 } 184 185 switch a.Kind() { 186 case types.ListKind: 187 if aList, bList, pList, ok := listAssert(m.vrw, a, b, parent); ok { 188 return threeWayListMerge(aList, bList, pList) 189 } 190 191 case types.MapKind: 192 if aMap, bMap, pMap, ok := mapAssert(m.vrw, a, b, parent); ok { 193 return m.threeWayMapMerge(aMap, bMap, pMap, path) 194 } 195 196 case types.RefKind: 197 if aValue, bValue, pValue, ok := refAssert(a, b, parent, m.vrw); ok { 198 merged, err := m.threeWay(aValue, bValue, pValue, path) 199 if err != nil { 200 return parent, err 201 } 202 return m.vrw.WriteValue(merged), nil 203 } 204 205 case types.SetKind: 206 if aSet, bSet, pSet, ok := setAssert(m.vrw, a, b, parent); ok { 207 return m.threeWaySetMerge(aSet, bSet, pSet, path) 208 } 209 210 case types.StructKind: 211 if aStruct, bStruct, pStruct, ok := structAssert(a, b, parent); ok { 212 return m.threeWayStructMerge(aStruct, bStruct, pStruct, path) 213 } 214 } 215 216 pDescription := "<nil>" 217 if parent != nil { 218 pDescription = types.TypeOf(parent).Describe() 219 } 220 return parent, newMergeConflict("Cannot merge %s and %s on top of %s.", types.TypeOf(a).Describe(), types.TypeOf(b).Describe(), pDescription) 221 } 222 223 func (m *merger) threeWayMapMerge(a, b, parent types.Map, path types.Path) (merged types.Value, err error) { 224 apply := func(target candidate, change types.ValueChanged, newVal types.Value) candidate { 225 defer updateProgress(m.progress) 226 switch change.ChangeType { 227 case types.DiffChangeAdded, types.DiffChangeModified: 228 return mapCandidate{target.getValue().(types.Map).Edit().Set(change.Key, newVal).Map()} 229 case types.DiffChangeRemoved: 230 return mapCandidate{target.getValue().(types.Map).Edit().Remove(change.Key).Map()} 231 default: 232 panic("Not Reached") 233 } 234 } 235 return m.threeWayOrderedSequenceMerge(mapCandidate{a}, mapCandidate{b}, mapCandidate{parent}, apply, path) 236 } 237 238 func (m *merger) threeWaySetMerge(a, b, parent types.Set, path types.Path) (merged types.Value, err error) { 239 apply := func(target candidate, change types.ValueChanged, newVal types.Value) candidate { 240 defer updateProgress(m.progress) 241 switch change.ChangeType { 242 case types.DiffChangeAdded, types.DiffChangeModified: 243 return setCandidate{target.getValue().(types.Set).Edit().Insert(newVal).Set()} 244 case types.DiffChangeRemoved: 245 return setCandidate{target.getValue().(types.Set).Edit().Remove(newVal).Set()} 246 default: 247 panic("Not Reached") 248 } 249 } 250 return m.threeWayOrderedSequenceMerge(setCandidate{a}, setCandidate{b}, setCandidate{parent}, apply, path) 251 } 252 253 func (m *merger) threeWayStructMerge(a, b, parent types.Struct, path types.Path) (merged types.Value, err error) { 254 apply := func(target candidate, change types.ValueChanged, newVal types.Value) candidate { 255 defer updateProgress(m.progress) 256 // Right now, this always iterates over all fields to create a new Struct, because there's no API for adding/removing a field from an existing struct type. 257 targetVal := target.getValue().(types.Struct) 258 if f, ok := change.Key.(types.String); ok { 259 field := string(f) 260 data := types.StructData{} 261 targetVal.IterFields(func(name string, v types.Value) bool { 262 if name != field { 263 data[name] = v 264 } 265 266 return false 267 }) 268 if change.ChangeType == types.DiffChangeAdded || change.ChangeType == types.DiffChangeModified { 269 data[field] = newVal 270 } 271 return structCandidate{types.NewStruct(targetVal.Name(), data)} 272 } 273 panic(fmt.Errorf("Bad key type in diff: %s", types.TypeOf(change.Key).Describe())) 274 } 275 return m.threeWayOrderedSequenceMerge(structCandidate{a}, structCandidate{b}, structCandidate{parent}, apply, path) 276 } 277 278 func listAssert(vrw types.ValueReadWriter, a, b, parent types.Value) (aList, bList, pList types.List, ok bool) { 279 var aOk, bOk, pOk bool 280 aList, aOk = a.(types.List) 281 bList, bOk = b.(types.List) 282 if parent != nil { 283 pList, pOk = parent.(types.List) 284 } else { 285 pList, pOk = types.NewList(vrw), true 286 } 287 return aList, bList, pList, aOk && bOk && pOk 288 } 289 290 func mapAssert(vrw types.ValueReadWriter, a, b, parent types.Value) (aMap, bMap, pMap types.Map, ok bool) { 291 var aOk, bOk, pOk bool 292 aMap, aOk = a.(types.Map) 293 bMap, bOk = b.(types.Map) 294 if parent != nil { 295 pMap, pOk = parent.(types.Map) 296 } else { 297 pMap, pOk = types.NewMap(vrw), true 298 } 299 return aMap, bMap, pMap, aOk && bOk && pOk 300 } 301 302 func refAssert(a, b, parent types.Value, vrw types.ValueReadWriter) (aValue, bValue, pValue types.Value, ok bool) { 303 var aOk, bOk, pOk bool 304 var aRef, bRef, pRef types.Ref 305 aRef, aOk = a.(types.Ref) 306 bRef, bOk = b.(types.Ref) 307 if !aOk || !bOk { 308 return 309 } 310 311 aValue = aRef.TargetValue(vrw) 312 bValue = bRef.TargetValue(vrw) 313 if parent != nil { 314 if pRef, pOk = parent.(types.Ref); pOk { 315 pValue = pRef.TargetValue(vrw) 316 } 317 } else { 318 pOk = true // parent == nil is still OK. It just leaves pValue as nil. 319 } 320 return aValue, bValue, pValue, aOk && bOk && pOk 321 } 322 323 func setAssert(vrw types.ValueReadWriter, a, b, parent types.Value) (aSet, bSet, pSet types.Set, ok bool) { 324 var aOk, bOk, pOk bool 325 aSet, aOk = a.(types.Set) 326 bSet, bOk = b.(types.Set) 327 if parent != nil { 328 pSet, pOk = parent.(types.Set) 329 } else { 330 pSet, pOk = types.NewSet(vrw), true 331 } 332 return aSet, bSet, pSet, aOk && bOk && pOk 333 } 334 335 func structAssert(a, b, parent types.Value) (aStruct, bStruct, pStruct types.Struct, ok bool) { 336 var aOk, bOk, pOk bool 337 aStruct, aOk = a.(types.Struct) 338 bStruct, bOk = b.(types.Struct) 339 if aOk && bOk { 340 if aStruct.Name() == bStruct.Name() { 341 if parent != nil { 342 pStruct, pOk = parent.(types.Struct) 343 } else { 344 pStruct, pOk = types.NewStruct(aStruct.Name(), nil), true 345 } 346 return aStruct, bStruct, pStruct, pOk 347 } 348 } 349 return 350 }