diff --git a/assets/issues/issue-222/from.yml b/assets/issues/issue-222/from.yml new file mode 100644 index 0000000..c608964 --- /dev/null +++ b/assets/issues/issue-222/from.yml @@ -0,0 +1,3 @@ +--- +foo: | + bar \ No newline at end of file diff --git a/assets/issues/issue-222/to.yml b/assets/issues/issue-222/to.yml new file mode 100644 index 0000000..c310db6 --- /dev/null +++ b/assets/issues/issue-222/to.yml @@ -0,0 +1,3 @@ +--- +foo: |+ + bar diff --git a/internal/cmd/between.go b/internal/cmd/between.go index 24f6e37..23665d8 100644 --- a/internal/cmd/between.go +++ b/internal/cmd/between.go @@ -86,6 +86,7 @@ types are: YAML (http://yaml.org/) and JSON (http://json.org/). report, err := dyff.CompareInputFiles(from, to, dyff.IgnoreOrderChanges(reportOptions.ignoreOrderChanges), + dyff.IgnoreWhitespaceChanges(reportOptions.ignoreWhitespaceChanges), dyff.KubernetesEntityDetection(reportOptions.kubernetesEntityDetection), dyff.AdditionalIdentifiers(reportOptions.additionalIdentifiers...), ) diff --git a/internal/cmd/cmds_test.go b/internal/cmd/cmds_test.go index 59c4803..a78b239 100644 --- a/internal/cmd/cmds_test.go +++ b/internal/cmd/cmds_test.go @@ -580,6 +580,17 @@ spec.replicas (apps/v1/Deployment/test) Expect(err).ToNot(HaveOccurred()) Expect(out).To(BeEquivalentTo("\n")) }) + + It("should ignore the 'whitespace only' changes", func() { + out, err := dyff("between", + "--omit-header", + "--ignore-whitespace-changes", + assets("issues", "issue-222", "from.yml"), + assets("issues", "issue-222", "to.yml")) + + Expect(err).ToNot(HaveOccurred()) + Expect(out).To(BeEquivalentTo("\n")) + }) }) Context("last-applied command", func() { diff --git a/internal/cmd/common.go b/internal/cmd/common.go index 0392b7a..9b0b47c 100644 --- a/internal/cmd/common.go +++ b/internal/cmd/common.go @@ -40,6 +40,7 @@ import ( type reportConfig struct { style string ignoreOrderChanges bool + ignoreWhitespaceChanges bool kubernetesEntityDetection bool noTableStyle bool doNotInspectCerts bool @@ -58,6 +59,7 @@ type reportConfig struct { var defaults = reportConfig{ style: "human", ignoreOrderChanges: false, + ignoreWhitespaceChanges: false, kubernetesEntityDetection: true, noTableStyle: false, doNotInspectCerts: false, @@ -78,6 +80,7 @@ var reportOptions reportConfig func applyReportOptionsFlags(cmd *cobra.Command) { // Compare options cmd.Flags().BoolVarP(&reportOptions.ignoreOrderChanges, "ignore-order-changes", "i", defaults.ignoreOrderChanges, "ignore order changes in lists") + cmd.Flags().BoolVar(&reportOptions.ignoreWhitespaceChanges, "ignore-whitespace-changes", defaults.ignoreWhitespaceChanges, "ignore leading or trailing whitespace changes") cmd.Flags().BoolVarP(&reportOptions.kubernetesEntityDetection, "detect-kubernetes", "", defaults.kubernetesEntityDetection, "detect kubernetes entities") cmd.Flags().StringArrayVar(&reportOptions.additionalIdentifiers, "additional-identifier", defaults.additionalIdentifiers, "use additional identifier candidates in named entry lists") cmd.Flags().StringSliceVar(&reportOptions.filters, "filter", defaults.filters, "filter reports to a subset of differences based on supplied arguments") diff --git a/pkg/dyff/compare_test.go b/pkg/dyff/compare_test.go index e616ba1..f63a2f3 100644 --- a/pkg/dyff/compare_test.go +++ b/pkg/dyff/compare_test.go @@ -217,6 +217,15 @@ some: dyff.REMOVAL, yml(`version: v1`), nil, dyff.ADDITION, nil, yml(`release: v1`)))) }) + + It("should ignore leading and trailing whitespace changes if configured", func() { + from := yml(`{"foo": "bar"}`) + to := yml(`{"foo": "bar "}`) + + diffs, err := compare(from, to, dyff.IgnoreWhitespaceChanges(true)) + Expect(err).To(BeNil()) + Expect(diffs).To(BeNil()) + }) }) Context("Given two YAML structures with simple lists", func() { diff --git a/pkg/dyff/core.go b/pkg/dyff/core.go index 64dde67..77c300e 100644 --- a/pkg/dyff/core.go +++ b/pkg/dyff/core.go @@ -38,6 +38,7 @@ type CompareOption func(*compareSettings) type compareSettings struct { NonStandardIdentifierGuessCountThreshold int IgnoreOrderChanges bool + IgnoreWhitespaceChanges bool KubernetesEntityDetection bool AdditionalIdentifiers []string } @@ -71,6 +72,13 @@ func IgnoreOrderChanges(value bool) CompareOption { } } +// IgnoreWhitespaceChanges disables the detection for whitespace only changes +func IgnoreWhitespaceChanges(value bool) CompareOption { + return func(settings *compareSettings) { + settings.IgnoreWhitespaceChanges = value + } +} + // KubernetesEntityDetection enabled detecting entity identifiers from Kubernetes "kind:" and "metadata:" fields. func KubernetesEntityDetection(value bool) CompareOption { return func(settings *compareSettings) { @@ -595,19 +603,24 @@ func (compare *compare) namedEntryLists(path ytbx.Path, identifier listItemIdent } func (compare *compare) nodeValues(path ytbx.Path, from *yamlv3.Node, to *yamlv3.Node) ([]Diff, error) { - result := make([]Diff, 0) if strings.Compare(from.Value, to.Value) != 0 { - result = append(result, Diff{ + // leave and don't report any differences if ignore whitespaces changes is + // configured and it is really only a whitespace only change between the strings + if compare.settings.IgnoreWhitespaceChanges && isWhitespaceOnlyChange(from.Value, to.Value) { + return nil, nil + } + + return []Diff{{ &path, []Detail{{ Kind: MODIFICATION, From: from, To: to, }}, - }) + }}, nil } - return result, nil + return nil, nil } func (compare *compare) boolValues(path ytbx.Path, from *yamlv3.Node, to *yamlv3.Node) ([]Diff, error) { @@ -1135,3 +1148,7 @@ func grab(node *yamlv3.Node, pathString string) (*yamlv3.Node, error) { pathString, ) } + +func isWhitespaceOnlyChange(from string, to string) bool { + return strings.Trim(from, " \n") == strings.Trim(to, " \n") +} diff --git a/pkg/dyff/output_human.go b/pkg/dyff/output_human.go index 66c864f..d3d9dd2 100644 --- a/pkg/dyff/output_human.go +++ b/pkg/dyff/output_human.go @@ -632,10 +632,6 @@ func isMultiLine(from string, to string) bool { return strings.Contains(from, "\n") || strings.Contains(to, "\n") } -func isWhitespaceOnlyChange(from string, to string) bool { - return strings.Trim(from, " \n") == strings.Trim(to, " \n") -} - func showWhitespaceCharacters(text string) string { return strings.Replace(strings.Replace(text, "\n", bold("↵\n"), -1), " ", bold("·"), -1) }