github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/merge/conflict_sink.go (about) 1 // Copyright 2019 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package merge 16 17 import ( 18 "context" 19 "errors" 20 "fmt" 21 "io" 22 23 "github.com/fatih/color" 24 25 "github.com/dolthub/dolt/go/libraries/doltcore/diff" 26 "github.com/dolthub/dolt/go/libraries/doltcore/row" 27 "github.com/dolthub/dolt/go/libraries/doltcore/schema" 28 "github.com/dolthub/dolt/go/libraries/doltcore/table/pipeline" 29 "github.com/dolthub/dolt/go/libraries/doltcore/table/untyped" 30 "github.com/dolthub/dolt/go/libraries/doltcore/table/untyped/tabular" 31 "github.com/dolthub/dolt/go/store/types" 32 ) 33 34 var WriteBufSize = 256 * 1024 35 var mergeVersionToLabel = map[MergeVersion]string{ 36 OurVersion: "ours ", 37 TheirVersion: "theirs", 38 BaseVersion: "base ", 39 Blank: " ", 40 } 41 var diffTypeToOpLabel = map[types.DiffChangeType]string{ 42 types.DiffChangeAdded: " + ", 43 types.DiffChangeRemoved: " - ", 44 types.DiffChangeModified: " * ", 45 } 46 47 var deleteColor = color.New(color.FgRed, color.CrossedOut) 48 var modifiedColor = color.New(color.FgYellow) 49 var addedColor = color.New(color.FgGreen) 50 51 var diffTypeToColor = map[types.DiffChangeType]diff.ColorFunc{ 52 types.DiffChangeAdded: addedColor.Sprint, 53 types.DiffChangeModified: modifiedColor.Sprint, 54 types.DiffChangeRemoved: deleteColor.Sprint, 55 } 56 57 type ConflictSink struct { 58 sch schema.Schema 59 ttw *tabular.TextTableWriter 60 } 61 62 const ( 63 opColTag = schema.ReservedTagMin 64 sourceColTag = schema.ReservedTagMin + 1 65 ) 66 67 func NewConflictSink(wr io.WriteCloser, sch schema.Schema, colSep string) (*ConflictSink, error) { 68 _, additionalCols := untyped.NewUntypedSchemaWithFirstTag(opColTag, "op", "source") 69 outSch, err := untyped.UntypedSchemaUnion(additionalCols, sch) 70 71 if err != nil { 72 return nil, err 73 } 74 75 ttw, err := tabular.NewTextTableWriter(wr, outSch) 76 77 if err != nil { 78 return nil, err 79 } 80 81 return &ConflictSink{outSch, ttw}, nil 82 } 83 84 // GetSchema gets the schema of the rows that this writer writes 85 func (cs *ConflictSink) GetSchema() schema.Schema { 86 return cs.sch 87 } 88 89 var noColorFunc = func(i ...interface{}) string { 90 if len(i) == 0 { 91 return "" 92 } else { 93 return fmt.Sprint(i...) 94 } 95 } 96 97 func (cs *ConflictSink) ProcRowWithProps(r row.Row, props pipeline.ReadableMap) error { 98 taggedVals := make(row.TaggedValues) 99 100 colorFunc := noColorFunc 101 mergeVersion, ok := props.Get(mergeVersionProp) 102 103 // The column header row won't have properties to read 104 if !ok { 105 mergeVersion = Blank 106 } 107 taggedVals[opColTag] = types.String(" ") 108 taggedVals[sourceColTag] = types.String(mergeVersionToLabel[mergeVersion.(MergeVersion)]) 109 110 if mergeVersion != BaseVersion { 111 mergeRowOp, ok := props.Get(mergeRowOperation) 112 // The column header row won't have properties to read 113 if ok { 114 dt := mergeRowOp.(types.DiffChangeType) 115 taggedVals[opColTag] = types.String(diffTypeToOpLabel[dt]) 116 colorFunc = diffTypeToColor[dt] 117 } else { 118 taggedVals[opColTag] = types.String(" ") 119 } 120 } 121 122 err := cs.sch.GetAllCols().Iter(func(tag uint64, col schema.Column) (stop bool, err error) { 123 if val, ok := r.GetColVal(tag); ok { 124 taggedVals[tag] = types.String(colorFunc(string(val.(types.String)))) 125 } 126 return false, nil 127 }) 128 129 if err != nil { 130 return err 131 } 132 133 r, err = row.New(r.Format(), cs.sch, taggedVals) 134 135 if err != nil { 136 return err 137 } 138 139 return cs.ttw.WriteRow(context.TODO(), r) 140 } 141 142 // Close should release resources being held 143 func (cs *ConflictSink) Close() error { 144 if cs.ttw != nil { 145 if err := cs.ttw.Close(context.TODO()); err != nil { 146 return err 147 } 148 149 cs.ttw = nil 150 return nil 151 } else { 152 return errors.New("already closed") 153 } 154 }