github.com/tomwright/dasel@v1.27.3/node_put.go (about)

     1  package dasel
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/tomwright/dasel/storage"
     6  	"reflect"
     7  )
     8  
     9  // Put finds the node using the given selector and updates it's value.
    10  // It then attempts to propagate the value back up the chain to the root element.
    11  func (n *Node) Put(selector string, newValue interface{}) error {
    12  	if selector != "." {
    13  		n.Selector.Remaining = selector
    14  	}
    15  
    16  	if err := buildPutChain(n); err != nil {
    17  		return err
    18  	}
    19  
    20  	final := lastNode(n)
    21  
    22  	_, isRealValue := newValue.(storage.RealValue)
    23  	if isRealValue {
    24  		final.setRealValue(newValue)
    25  	} else {
    26  		final.setValue(newValue)
    27  	}
    28  
    29  	if final.Selector.Type != "ROOT" {
    30  		if err := propagate(final); err != nil {
    31  			return err
    32  		}
    33  	}
    34  
    35  	return nil
    36  }
    37  
    38  // PutMultiple all applicable nodes for the given selector and updates all of their values to the given value.
    39  // It then attempts to propagate the value back up the chain to the root element.
    40  func (n *Node) PutMultiple(selector string, newValue interface{}) error {
    41  	if selector != "." {
    42  		n.Selector.Remaining = selector
    43  	}
    44  
    45  	if err := buildPutMultipleChain(n); err != nil {
    46  		return err
    47  	}
    48  
    49  	final := lastNodes(n)
    50  
    51  	val := reflect.ValueOf(newValue)
    52  	_, isRealValue := newValue.(storage.RealValue)
    53  
    54  	for _, n := range final {
    55  		if isRealValue {
    56  			n.setRealReflectValue(val)
    57  		} else {
    58  			n.setReflectValue(val)
    59  		}
    60  		if err := propagate(n); err != nil {
    61  			return err
    62  		}
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  func buildPutChain(n *Node) error {
    69  	if isFinalSelector(n.Selector.Remaining) {
    70  		// We've reached the end
    71  		return nil
    72  	}
    73  
    74  	var err error
    75  	nextNode := &Node{}
    76  
    77  	// Parse the selector.
    78  	nextNode.Selector, err = ParseSelector(n.Selector.Remaining)
    79  	if err != nil {
    80  		return fmt.Errorf("failed to parse selector: %w", err)
    81  	}
    82  
    83  	// Link the nodes.
    84  	n.Next = nextNode
    85  	nextNode.Previous = n
    86  
    87  	// Populate the value for the new node.
    88  	nextNode.Value, err = findValue(nextNode, true)
    89  	if err != nil {
    90  		return fmt.Errorf("could not find put value: %w", err)
    91  	}
    92  
    93  	return buildPutChain(nextNode)
    94  }
    95  
    96  func buildPutMultipleChain(n *Node) error {
    97  	if isFinalSelector(n.Selector.Remaining) {
    98  		// We've reached the end
    99  		return nil
   100  	}
   101  
   102  	var err error
   103  
   104  	// Parse the selector.
   105  	nextSelector, err := ParseSelector(n.Selector.Remaining)
   106  	if err != nil {
   107  		return fmt.Errorf("failed to parse selector: %w", err)
   108  	}
   109  
   110  	// Populate the value for the new node.
   111  	n.NextMultiple, err = findNodes(nextSelector, n, true)
   112  
   113  	if err != nil {
   114  		return fmt.Errorf("could not find put multiple value: %w", err)
   115  	}
   116  
   117  	for _, next := range n.NextMultiple {
   118  		// Add the back reference
   119  		if next.Previous == nil {
   120  			// This can already be set in some cases - SEARCH.
   121  			next.Previous = n
   122  		}
   123  
   124  		if err := buildPutMultipleChain(next); err != nil {
   125  			return err
   126  		}
   127  	}
   128  
   129  	return nil
   130  }