Perform executes the operation on the given container
(doc *yaml.Node)
| 24 | |
| 25 | // Perform executes the operation on the given container |
| 26 | func (op *Operation) Perform(doc *yaml.Node) error { |
| 27 | path, err := yamlpath.NewPath(string(op.Path)) |
| 28 | if err != nil { |
| 29 | return err |
| 30 | } |
| 31 | |
| 32 | matches, err := path.Find(doc) |
| 33 | if err != nil { |
| 34 | return err |
| 35 | } |
| 36 | |
| 37 | if len(matches) == 0 && op.Op != opAdd { |
| 38 | return fmt.Errorf("%s operation does not apply: doc is missing path: %s", op.Op, op.Path) |
| 39 | } |
| 40 | |
| 41 | // function that will actually perform the patch operation |
| 42 | var opFunc func(parent *yaml.Node, match *yaml.Node) |
| 43 | |
| 44 | switch op.Op { |
| 45 | case opAdd: |
| 46 | opFunc = op.add |
| 47 | |
| 48 | if len(matches) > 0 { |
| 49 | if matches[0].Kind == yaml.MappingNode || matches[0].Kind == yaml.SequenceNode { |
| 50 | break |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | originalMatches := matches |
| 55 | |
| 56 | matches, err = getParents(doc, op.Path) |
| 57 | if err != nil { |
| 58 | return fmt.Errorf("could not add using path: %s", op.Path) |
| 59 | } |
| 60 | |
| 61 | if len(matches) > 0 && len(originalMatches) > 0 { |
| 62 | if matches[0].Kind == yaml.SequenceNode { |
| 63 | matches = originalMatches |
| 64 | break |
| 65 | } |
| 66 | |
| 67 | // we are trying to overwrite an existing key in a map, don't do that! |
| 68 | return fmt.Errorf( |
| 69 | "attempting add operation for non array/object path '%s' which already exists", |
| 70 | op.Path, |
| 71 | ) |
| 72 | } |
| 73 | |
| 74 | parentPath := op.Path.getParentPath() |
| 75 | propertyName := op.Path.getChildName() |
| 76 | if op.Value != nil { |
| 77 | propertyValue := op.Value.Content[0] |
| 78 | op.Value = createMappingNode(propertyName, propertyValue) |
| 79 | } |
| 80 | op.Path = OpPath(parentPath) |
| 81 | |
| 82 | case opRemove: |
| 83 | opFunc = op.remove |