Skip to content

Commit

Permalink
Adding compare cmd (#4)
Browse files Browse the repository at this point in the history
This allow users to compare paths between two YAML files. Return equal paths in both files.

Enable `by-value` flag for `compare` cmd: This enable/disable a comparison for paths with the same value.
  • Loading branch information
qu1queee authored and HeavyWombat committed Feb 1, 2019
1 parent 114f894 commit add5930
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 0 deletions.
17 changes: 17 additions & 0 deletions assets/testbed/sample_a.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
# structure with maps
yaml:
structure:
somekey: foo
dot: samevalue

# structure with a list of maps
list:
- name: one
somekey: foo
- name: sametwo
somekey: samekey

# structure with a simple list
simpleList:
- one
13 changes: 13 additions & 0 deletions assets/testbed/sample_b.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
# structure with maps
yaml:
structure:
somekey: bar
dot: samevalue

# structure with a list of maps
list:
- name: two
somekey: bar
- name: sametwo
somekey: samekey
51 changes: 51 additions & 0 deletions internal/cmd/compare.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright © 2018 Matthias Diester
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package cmd

import (
"fmt"

"github.com/HeavyWombat/ytbx/pkg/v1/ytbx"
"github.com/spf13/cobra"
)

var comparePathsByValue bool

// compareCmd represents the compare command
var compareCmd = &cobra.Command{
Use: "compare <from_file> <to_file>",
Args: cobra.RangeArgs(1, 2),
Short: "Compare YAML paths",
Long: `Compare YAML paths between two files.`,
Run: func(cmd *cobra.Command, args []string) {
list, err := ytbx.ComparePaths(args[0], args[1], ytbx.GoPatchStyle, comparePathsByValue)
if err != nil {
exitWithError("Failed to get paths from file", err)
}
for _, entry := range list {
fmt.Println(entry)
}
},
}

func init() {
rootCmd.AddCommand(compareCmd)
compareCmd.PersistentFlags().BoolVar(&comparePathsByValue, "by-value", false, "compare only paths with same value")
}
68 changes: 68 additions & 0 deletions pkg/v1/ytbx/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package ytbx

import (
"fmt"
"reflect"
"strconv"
"strings"

Expand Down Expand Up @@ -138,6 +139,73 @@ func NewPathWithIndexedListElement(path Path, idx int) Path {
})
}

// ComparePathsByValue returns all Path structure that have the same path value
func ComparePathsByValue(fromLocation string, toLocation string, duplicatePaths []Path) ([]Path, error) {
from, err := LoadFile(fromLocation)
if err != nil {
return nil, err
}

to, err := LoadFile(toLocation)
if err != nil {
return nil, err
}

if len(from.Documents) > 1 || len(to.Documents) > 1 {
return nil, fmt.Errorf("input files have more than one document, which is not supported yet")
}

duplicatePathsWithTheSameValue := []Path{}

for _, path := range duplicatePaths {
fromValue, err := Grab(from.Documents[0], path.ToGoPatchStyle())
if err != nil {
return nil, err
}

toValue, err := Grab(to.Documents[0], path.ToGoPatchStyle())
if err != nil {
return nil, err
}

if reflect.DeepEqual(fromValue, toValue) {
duplicatePathsWithTheSameValue = append(duplicatePathsWithTheSameValue, path)
}
}
return duplicatePathsWithTheSameValue, nil
}

// ComparePaths returns all duplicate Path structures between two documents.
func ComparePaths(fromLocation string, toLocation string, style PathStyle, compareByValue bool) ([]Path, error) {
var duplicatePaths []Path

pathsFromLocation, err := ListPaths(fromLocation, style)
if err != nil {
return nil, err
}
pathsToLocation, err := ListPaths(toLocation, style)
if err != nil {
return nil, err
}

lookup := map[string]struct{}{}
for _, pathsFrom := range pathsFromLocation {
lookup[pathsFrom.ToGoPatchStyle()] = struct{}{}
}

for _, pathsTo := range pathsToLocation {
if _, ok := lookup[pathsTo.ToGoPatchStyle()]; ok {
duplicatePaths = append(duplicatePaths, pathsTo)
}
}

if !compareByValue {
return duplicatePaths, nil
}

return ComparePathsByValue(fromLocation, toLocation, duplicatePaths)
}

// ListPaths returns all paths in the documents using the provided choice of
// path style.
func ListPaths(location string, style PathStyle) ([]Path, error) {
Expand Down
42 changes: 42 additions & 0 deletions pkg/v1/ytbx/path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,46 @@ var _ = Describe("path tests", func() {
}}))
})
})

Context("compare paths between two files", func() {
It("should find only duplicate paths", func() {
list, err := ComparePaths(assetsDirectory+"/testbed/sample_a.yml", assetsDirectory+"/testbed/sample_b.yml", GoPatchStyle, false)
Expect(err).ToNot(HaveOccurred())

listOfPaths := make([]Path, 5)
listOfPaths = []Path{{DocumentIdx: 0, PathElements: []PathElement{
{Idx: -1, Key: "", Name: "yaml"},
{Idx: -1, Key: "", Name: "structure"},
{Idx: -1, Key: "", Name: "somekey"},
}}, {DocumentIdx: 0, PathElements: []PathElement{
{Idx: -1, Key: "", Name: "yaml"},
{Idx: -1, Key: "", Name: "structure"},
{Idx: -1, Key: "", Name: "dot"},
}}, {DocumentIdx: 0, PathElements: []PathElement{
{Idx: -1, Key: "", Name: "list"},
{Idx: -1, Key: "name", Name: "sametwo"},
{Idx: -1, Key: "", Name: "somekey"},
}}}

Expect(list).To(BeEquivalentTo(listOfPaths))
})

It("should find only paths with the same value", func() {
list, err := ComparePaths(assetsDirectory+"/testbed/sample_a.yml", assetsDirectory+"/testbed/sample_b.yml", GoPatchStyle, true)
Expect(err).ToNot(HaveOccurred())

listOfPathsWithSameValue := make([]Path, 5)
listOfPathsWithSameValue = []Path{{DocumentIdx: 0, PathElements: []PathElement{
{Idx: -1, Key: "", Name: "yaml"},
{Idx: -1, Key: "", Name: "structure"},
{Idx: -1, Key: "", Name: "dot"},
}}, {DocumentIdx: 0, PathElements: []PathElement{
{Idx: -1, Key: "", Name: "list"},
{Idx: -1, Key: "name", Name: "sametwo"},
{Idx: -1, Key: "", Name: "somekey"},
}}}

Expect(list).To(BeEquivalentTo(listOfPathsWithSameValue))
})
})
})

0 comments on commit add5930

Please sign in to comment.