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  }