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  }