github.com/wrgl/wrgl@v0.14.0/pkg/merge/row_resolver.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright © 2022 Wrangle Ltd
     3  
     4  package merge
     5  
     6  import (
     7  	"bytes"
     8  	"sort"
     9  
    10  	"github.com/wrgl/wrgl/pkg/diff"
    11  	"github.com/wrgl/wrgl/pkg/objects"
    12  )
    13  
    14  type RowResolver struct {
    15  	buf     *diff.BlockBuffer
    16  	cd      *diff.ColDiff
    17  	rows    *Rows
    18  	nCols   int
    19  	nLayers int
    20  	rowDec  *objects.StrListDecoder
    21  }
    22  
    23  func NewRowResolver(db objects.Store, cd *diff.ColDiff, buf *diff.BlockBuffer) *RowResolver {
    24  	nCols := cd.Len()
    25  	nLayers := cd.Layers()
    26  	return &RowResolver{
    27  		buf:     buf,
    28  		cd:      cd,
    29  		nCols:   nCols,
    30  		nLayers: nLayers,
    31  		rows:    NewRows(nLayers),
    32  		rowDec:  objects.NewStrListDecoder(false),
    33  	}
    34  }
    35  
    36  func (r *RowResolver) getRow(m *Merge, layer int) ([]string, error) {
    37  	rowOff := m.BaseOffset
    38  	sum := m.Base
    39  	if layer >= 0 {
    40  		rowOff = m.OtherOffsets[layer]
    41  		sum = m.Others[layer]
    42  	}
    43  	if sum == nil {
    44  		return nil, nil
    45  	}
    46  	blk, off := diff.RowToBlockAndOffset(rowOff)
    47  	row, err := r.buf.GetRow(byte(layer+1), blk, off)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	if layer < 0 {
    52  		row = r.cd.RearrangeBaseRow(row)
    53  	} else {
    54  		row = r.cd.RearrangeRow(layer, row)
    55  	}
    56  	return row, nil
    57  }
    58  
    59  func (r *RowResolver) tryResolve(m *Merge) (err error) {
    60  	uniqSums := map[string]int{}
    61  	layersWhereRowIsRemoved := []int{}
    62  	for i, sum := range m.Others {
    63  		if sum != nil {
    64  			uniqSums[string(sum)] = i
    65  		} else {
    66  			layersWhereRowIsRemoved = append(layersWhereRowIsRemoved, i)
    67  		}
    68  	}
    69  	if m.Base == nil {
    70  		layersWhereRowIsRemoved = nil
    71  	}
    72  	r.rows.Reset()
    73  	for _, layer := range uniqSums {
    74  		row, err := r.getRow(m, layer)
    75  		if err != nil {
    76  			return err
    77  		}
    78  		r.rows.Append(layer, row)
    79  	}
    80  	baseRow, err := r.getRow(m, -1)
    81  	if err != nil {
    82  		return
    83  	}
    84  	m.UnresolvedCols = map[uint32]struct{}{}
    85  	sort.Sort(r.rows)
    86  	m.ResolvedRow = make([]string, r.nCols)
    87  	copy(m.ResolvedRow, baseRow)
    88  	var i uint32
    89  	unresolveCol := func(i uint32) {
    90  		if baseRow != nil {
    91  			m.ResolvedRow[i] = baseRow[i]
    92  		} else {
    93  			m.ResolvedRow[i] = ""
    94  		}
    95  		m.UnresolvedCols[i] = struct{}{}
    96  	}
    97  	for i = 0; i < uint32(r.nCols); i++ {
    98  		var add *string
    99  		var mod *string
   100  		var rem bool
   101  		for _, layer := range layersWhereRowIsRemoved {
   102  			if _, ok := r.cd.Added[layer][i]; !ok {
   103  				rem = true
   104  			}
   105  		}
   106  		for j, row := range r.rows.Values {
   107  			layer := r.rows.Layers[j]
   108  			if _, ok := r.cd.Added[layer][i]; ok {
   109  				// column added in this layer
   110  				if add == nil {
   111  					add = &row[i]
   112  				} else if *add != row[i] {
   113  					// another layer added a different value
   114  					unresolveCol(i)
   115  					continue
   116  				}
   117  			} else if add != nil {
   118  				continue
   119  			} else if _, ok := r.cd.Removed[layer][i]; ok {
   120  				// column removed in this layer
   121  				if mod == nil {
   122  					rem = true
   123  				} else {
   124  					// another layer modified this column
   125  					unresolveCol(i)
   126  					continue
   127  				}
   128  			} else if baseRow == nil || baseRow[i] != row[i] {
   129  				// column modified in this layer
   130  				if rem {
   131  					// modified and removed
   132  					unresolveCol(i)
   133  					continue
   134  				} else if mod == nil {
   135  					mod = &row[i]
   136  				} else if *mod != row[i] {
   137  					// another layer modified this column differently
   138  					unresolveCol(i)
   139  					continue
   140  				}
   141  			} else if rem || mod != nil {
   142  				continue
   143  			}
   144  			m.ResolvedRow[i] = row[i]
   145  		}
   146  	}
   147  	if len(layersWhereRowIsRemoved) > 0 {
   148  		// it isn't clear whether this row should be removed or modified so not resolved
   149  		m.Resolved = false
   150  	} else {
   151  		m.Resolved = len(m.UnresolvedCols) == 0
   152  	}
   153  	if len(m.UnresolvedCols) == 0 {
   154  		m.UnresolvedCols = nil
   155  	}
   156  	return
   157  }
   158  
   159  func (r *RowResolver) Resolve(m *Merge) (err error) {
   160  	nonNils := 0
   161  	unchanges := 0
   162  	for _, sum := range m.Others {
   163  		if sum != nil {
   164  			nonNils++
   165  			if bytes.Equal(sum, m.Base) {
   166  				unchanges++
   167  			}
   168  		}
   169  	}
   170  	if nonNils == 0 || unchanges == nonNils {
   171  		// removed in all layers or never changed in the first place
   172  		m.Resolved = true
   173  		return
   174  	}
   175  	return r.tryResolve(m)
   176  }