merge

package
v0.0.0-...-e5fa29d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 27, 2021 License: Apache-2.0 Imports: 3 Imported by: 6

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func None

func None(aChange, bChange types.DiffChangeType, a, b types.Value, path types.Path) (change types.DiffChangeType, merged types.Value, ok bool)

None is the no-op ResolveFunc. Any conflict results in a merge failure.

func Ours

func Ours(aChange, bChange types.DiffChangeType, a, b types.Value, path types.Path) (change types.DiffChangeType, merged types.Value, ok bool)

Ours resolves conflicts by preferring changes from the Value currently being committed.

func Theirs

func Theirs(aChange, bChange types.DiffChangeType, a, b types.Value, path types.Path) (change types.DiffChangeType, merged types.Value, ok bool)

Theirs resolves conflicts by preferring changes in the current HEAD.

func ThreeWay

func ThreeWay(a, b, parent types.Value, vrw types.ValueReadWriter, resolve ResolveFunc, progress chan struct{}) (merged types.Value, err error)

ThreeWay attempts a three-way merge between two _candidate_ values that have both changed with respect to a common _parent_ value. The result of the algorithm is a _merged_ value or an error if merging could not be done.

The algorithm works recursively, applying the following rules for each value:

- If any of the three values have a different [kind](link): conflict - If the two candidates are identical: the result is that value - If the values are primitives or Blob: conflict - If the values are maps:

  • if the same key was inserted or updated in both candidates:
  • first run this same algorithm on those two values to attempt to merge them
  • if the two merged values are still different: conflict
  • if a key was inserted in one candidate and removed in the other: conflict

- If the values are structs:

  • Same as map, except using field names instead of map keys

- If the values are sets:

  • Apply the changes from both candidates to the parent to get the result. No conflicts are possible.

- If the values are list:

  • Apply list-merge (see below)

Merge rules for List are a bit more complex than Map, Struct, and Set due to a wider away of potential use patterns. A List might be a de-facto Map with sequential numeric keys, or it might be a sequence of objects where order matters but the caller is unlikely to go back and update the value at a given index. List modifications are expressed in terms of 'splices' (see types/edit_distance.go). Roughly, a splice indicates that some number of elements were added and/or removed at some index in |parent|. In the following example:

parent: [a, b, c, d] a: [b, c, d] b: [a, b, c, d, e] merged: [b, c, d, e]

The difference from parent -> is described by the splice {0, 1}, indicating that 1 element was removed from parent at index 0. The difference from parent -> b is described as {4, 0, e}, indicating that 0 elements were removed at parent's index 4, and the element 'e' was added. Our merge algorithm will successfully merge a and b, because these splices do not overlap; that is, neither one removes the index at which the other operates. As a general rule, the merge algorithm will refuse to merge splices that overlap, as in the following examples:

parent: [a, b, c] a: [a, d, b, c] b: [a, c] merged: conflict

parent: [a, b, c] a: [a, e, b, c] b: [a, d, b, c] merged: conflict

The splices in the first example are {1, 0, d} (remove 0 elements at index 1 and add 'd') and {1, 1} (remove 1 element at index 1). Since the latter removes the element at which the former adds an element, these splices overlap. Similarly, in the second example, both splices operate at index 1 but add different elements. Thus, they also overlap.

There is one special case for overlapping splices. If they perform the exact same operation, the algorithm considers them not to be in conflict. E.g.

parent: [a, b, c] a: [a, d, e] b: [a, d, e] merged: [a, d, e]

Types

type ErrMergeConflict

type ErrMergeConflict struct {
	// contains filtered or unexported fields
}

ErrMergeConflict indicates that a merge attempt failed and must be resolved manually for the provided reason.

func (*ErrMergeConflict) Error

func (e *ErrMergeConflict) Error() string

type Policy

type Policy func(a, b, ancestor types.Value, vrw types.ValueReadWriter, progress chan struct{}) (merged types.Value, err error)

Policy functors are used to merge two values (a and b) against a common ancestor. All three Values and their must by wholly readable from vrw. Whenever a change is merged, implementations should send a struct{} over progress.

func NewThreeWay

func NewThreeWay(resolve ResolveFunc) Policy

NewThreeWay creates a new Policy based on ThreeWay using the provided ResolveFunc.

type ResolveFunc

type ResolveFunc func(aChange, bChange types.DiffChangeType, a, b types.Value, path types.Path) (change types.DiffChangeType, merged types.Value, ok bool)

ResolveFunc is the type for custom merge-conflict resolution callbacks. When the merge algorithm encounters two non-mergeable changes (aChange and bChange) at the same path, it calls the ResolveFunc passed into ThreeWay(). The callback gets the types of the two incompatible changes (added, changed or removed) and the two Values that could not be merged (if any). If the ResolveFunc cannot devise a resolution, ok should be false upon return and the other return values are undefined. If the conflict can be resolved, the function should return the appropriate type of change to apply, the new value to be used (if any), and true.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL