diff --git a/doc/optionsref.md b/doc/optionsref.md index 9d3bf5df..55f92cd4 100644 --- a/doc/optionsref.md +++ b/doc/optionsref.md @@ -74,6 +74,7 @@ Usage: octocatalog-diff [command line options] --from-enc PATH Path to ENC script (for the from catalog only) --to-enc PATH Path to ENC script (for the to catalog only) --[no-]display-detail-add Display parameters and other details for added resources + --[no-]use-lcs Use the LCS algorithm to determine differences in arrays --[no-]truncate-details Truncate details with --display-detail-add --no-header Do not print a header --default-header Print default header with output diff --git a/lib/octocatalog-diff/catalog-diff/differ.rb b/lib/octocatalog-diff/catalog-diff/differ.rb index 879e8999..2580b779 100644 --- a/lib/octocatalog-diff/catalog-diff/differ.rb +++ b/lib/octocatalog-diff/catalog-diff/differ.rb @@ -535,9 +535,11 @@ def hashdiff_initial(catalog1_in, catalog2_in) catalog2_resources = catalog2_in[:catalog] @logger.debug "Entering hashdiff_initial; catalog sizes: #{catalog1_resources.size}, #{catalog2_resources.size}" + use_lcs = @opts.fetch(:use_lcs, true) + @logger.debug "HashDiff configuration: (use_lcs: #{use_lcs})" result = [] hashdiff_add_remove = Set.new - hashdiff_result = HashDiff.diff(catalog1_resources, catalog2_resources, delimiter: "\f") + hashdiff_result = HashDiff.diff(catalog1_resources, catalog2_resources, delimiter: "\f", use_lcs: use_lcs) hashdiff_result.each do |obj| # Regular change if obj[0] == '~' diff --git a/lib/octocatalog-diff/cli.rb b/lib/octocatalog-diff/cli.rb index afd31b7c..391a3f9b 100644 --- a/lib/octocatalog-diff/cli.rb +++ b/lib/octocatalog-diff/cli.rb @@ -44,7 +44,8 @@ class Cli display_datatype_changes: true, parallel: true, suppress_absent_file_details: true, - hiera_path: 'hieradata' + hiera_path: 'hieradata', + use_lcs: true }.freeze # This method is the one to call externally. It is possible to specify alternate diff --git a/lib/octocatalog-diff/cli/options/use_lcs.rb b/lib/octocatalog-diff/cli/options/use_lcs.rb new file mode 100644 index 00000000..386985de --- /dev/null +++ b/lib/octocatalog-diff/cli/options/use_lcs.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Configures using the Longest common subsequence (LCS) algorithm to determine differences in arrays +# @param parser [OptionParser object] The OptionParser argument +# @param options [Hash] Options hash being constructed; this is modified in this method. +OctocatalogDiff::Cli::Options::Option.newoption(:use_lcs) do + has_weight 250 + + def parse(parser, options) + parser.on('--[no-]use-lcs', 'Use the LCS algorithm to determine differences in arrays') do |x| + options[:use_lcs] = x + end + end +end diff --git a/spec/octocatalog-diff/tests/catalog-diff/differ_spec.rb b/spec/octocatalog-diff/tests/catalog-diff/differ_spec.rb index 522ec39b..2287e076 100644 --- a/spec/octocatalog-diff/tests/catalog-diff/differ_spec.rb +++ b/spec/octocatalog-diff/tests/catalog-diff/differ_spec.rb @@ -1611,5 +1611,55 @@ end end end + + context 'use_lcs is taken into account' do + describe '#ignore' do + before(:all) do + r1 = [ + { + 'type' => 'Example1', 'title' => 'main', 'tags' => ['stage'], 'exported' => false, + 'parameters' => { + 'name' => 'main', 'toplevel' => 'toplevel attribute', + 'nest' => { + 'toplevel' => 'toplevel_nest attribute', + 'nest' => { 'nest' => 'nested nested text' }, + 'nest2' => { 'chicken' => 'egg' }, + 'chicken' => 'egg' + } + } + } + ] + @c1 = OctocatalogDiff::Spec.build_catalog(r1) + @c2 = OctocatalogDiff::Spec.build_catalog(r1) + end + + it 'should honor the algo configuration passed in the options (false)' do + logger, logger_str = OctocatalogDiff::Spec.setup_logger + opts = { use_lcs: false, logger: logger } + testobj = OctocatalogDiff::CatalogDiff::Differ.new(opts, @c1, @c2) + testobj.diff + expect(logger_str.string).to match(/Entering hashdiff_initial; catalog sizes: 1, 1/) + expect(logger_str.string).to match(/HashDiff configuration: \(use_lcs: false\)/) + end + + it 'should honor the algo configuration passed in the options (true)' do + logger, logger_str = OctocatalogDiff::Spec.setup_logger + opts = { use_lcs: true, logger: logger } + testobj = OctocatalogDiff::CatalogDiff::Differ.new(opts, @c1, @c2) + testobj.diff + expect(logger_str.string).to match(/Entering hashdiff_initial; catalog sizes: 1, 1/) + expect(logger_str.string).to match(/HashDiff configuration: \(use_lcs: true\)/) + end + + it 'the default value is true' do + logger, logger_str = OctocatalogDiff::Spec.setup_logger + opts = { logger: logger } + testobj = OctocatalogDiff::CatalogDiff::Differ.new(opts, @c1, @c2) + testobj.diff + expect(logger_str.string).to match(/Entering hashdiff_initial; catalog sizes: 1, 1/) + expect(logger_str.string).to match(/HashDiff configuration: \(use_lcs: true\)/) + end + end + end end end diff --git a/spec/octocatalog-diff/tests/cli/options/use_lcs_spec.rb b/spec/octocatalog-diff/tests/cli/options/use_lcs_spec.rb new file mode 100644 index 00000000..7e7d8c9c --- /dev/null +++ b/spec/octocatalog-diff/tests/cli/options/use_lcs_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require_relative '../options_helper' + +describe OctocatalogDiff::Cli::Options do + describe '#opt_use_lcs' do + include_examples 'true/false option', 'use-lcs', :use_lcs + end +end diff --git a/spec/octocatalog-diff/tests/cli_spec.rb b/spec/octocatalog-diff/tests/cli_spec.rb index ac121b73..7465aabd 100644 --- a/spec/octocatalog-diff/tests/cli_spec.rb +++ b/spec/octocatalog-diff/tests/cli_spec.rb @@ -37,7 +37,8 @@ display_datatype_changes: true, parallel: true, suppress_absent_file_details: true, - hiera_path: 'hieradata' + hiera_path: 'hieradata', + use_lcs: true } logger, _logger_str = OctocatalogDiff::Spec.setup_logger expect(described_class).to receive(:catalog_only).with(logger, answer)