Skip to content

Commit 96d1ea8

Browse files
authored
Merge pull request #69 from github/kpaulisse-misc-fixes
Miscellaneous fixes for 0.99.rc1
2 parents 7d42cdf + f63f88e commit 96d1ea8

17 files changed

Lines changed: 181 additions & 111 deletions

File tree

doc/advanced-filter.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Please note that there are other options to ignore specified diffs, including:
99

1010
Here is the list of available filters and an explanation of each:
1111

12-
- [Absent file](/doc/advanced-filter.md#absent-file) - Ignore parameter changes of a file that is declared to be absent
12+
- [Absent File](/doc/advanced-filter.md#absent-file) - Ignore parameter changes of a file that is declared to be absent
1313
- [YAML](/doc/advanced-filter.md#yaml) - Ignore whitespace/comment differences if YAML parses to the same object
1414

1515
## Absent File

lib/octocatalog-diff/api/v1/catalog-diff.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def self.catalog_diff(options = nil)
5757

5858
# Return diffs and catalogs in expected format
5959
OpenStruct.new(
60-
diffs: diffs.map { |x| OctocatalogDiff::API::V1::Diff.new(x) },
60+
diffs: diffs.map { |x| OctocatalogDiff::API::V1::Diff.factory(x) },
6161
from: OctocatalogDiff::API::V1::Catalog.new(catalogs[:from]),
6262
to: OctocatalogDiff::API::V1::Catalog.new(catalogs[:to])
6363
)

lib/octocatalog-diff/api/v1/common.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ def self.logger_from_options(options)
1212
logger = options[:logger] || Logger.new(StringIO.new)
1313

1414
# We can't keep :logger in the options due to marshal/unmarshal as part of parallelization.
15-
pass_opts = options.merge(logger: nil)
15+
pass_opts = options.dup
16+
pass_opts.delete(:logger)
1617

1718
# Return cleaned options and logger
1819
[pass_opts, logger]

lib/octocatalog-diff/api/v1/diff.rb

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,30 @@ module V1
1717
# easier to deal with. We recommend using the named options, rather than #raw or the indexed array,
1818
# as the raw object and indexed array are not guaranteed to be stable.
1919
class Diff
20-
attr_reader :raw
20+
attr_reader :raw, :diff_type, :type, :title, :structure
21+
22+
# Public: Construct a OctocatalogDiff::API::V1::Diff object from many different types of
23+
# input. This includes passing a OctocatalogDiff::API::V1::Diff object and getting that
24+
# identical object back.
25+
# @param object_in [?] Object in
26+
# @return [OctocatalogDiff::API::V1::Diff] Object out
27+
def self.factory(object_in)
28+
return object_in if object_in.is_a?(OctocatalogDiff::API::V1::Diff)
29+
30+
return new(object_in) if object_in.is_a?(Array)
31+
32+
raise ArgumentError, "Cannot construct OctocatalogDiff::API::V1::Diff from #{object_in.class}"
33+
end
2134

2235
# Constructor: Accepts a diff in the traditional array format and stores it.
2336
# @param raw [Array] Diff in the traditional format
2437
def initialize(raw)
25-
if raw.is_a?(OctocatalogDiff::API::V1::Diff)
26-
@raw = raw.raw
27-
return
28-
end
29-
3038
unless raw.is_a?(Array)
3139
raise ArgumentError, "OctocatalogDiff::API::V1::Diff#initialize expects Array argument (got #{raw.class})"
3240
end
41+
3342
@raw = raw
43+
initialize_helper
3444
end
3545

3646
# Public: Retrieve an indexed value from the array
@@ -39,12 +49,6 @@ def [](i)
3949
@raw[i]
4050
end
4151

42-
# Public: Get the change type
43-
# @return [String] Change type symbol (~, !, +, -)
44-
def diff_type
45-
@raw[0]
46-
end
47-
4852
# Public: Is this an addition?
4953
# @return [Boolean] True if this is an addition
5054
def addition?
@@ -63,35 +67,17 @@ def change?
6367
diff_type == '~' || diff_type == '!'
6468
end
6569

66-
# Public: Get the resource type
67-
# @return [String] Resource type
68-
def type
69-
@raw[1].split(/\f/)[0]
70-
end
71-
72-
# Public: Get the resource title
73-
# @return [String] Resource title
74-
def title
75-
@raw[1].split(/\f/)[1]
76-
end
77-
78-
# Public: Get the structure of the resource as an array
79-
# @return [Array] Structure of resource
80-
def structure
81-
@raw[1].split(/\f/)[2..-1]
82-
end
83-
8470
# Public: Get the "old" value, i.e. "from" catalog
8571
# @return [?] "old" value
8672
def old_value
87-
return nil if addition?
73+
return if addition?
8874
@raw[2]
8975
end
9076

9177
# Public: Get the "new" value, i.e. "to" catalog
92-
# @return [?] "old" value
78+
# @return [?] "new" value
9379
def new_value
94-
return nil if removal?
80+
return if removal?
9581
return @raw[2] if addition?
9682
@raw[3]
9783
end
@@ -127,7 +113,7 @@ def new_line
127113
# Public: Get the "old" location, i.e. location in the "from" catalog
128114
# @return [Hash] <file:, line:> of resource
129115
def old_location
130-
return nil if addition?
116+
return if addition?
131117
return @raw[3] if removal?
132118
@raw[4]
133119
end
@@ -136,7 +122,7 @@ def old_location
136122
# @return [Hash] <file:, line:> of resource
137123
def new_location
138124
return @raw[3] if addition?
139-
return nil if removal?
125+
return if removal?
140126
@raw[5]
141127
end
142128

@@ -178,6 +164,24 @@ def inspect
178164
def to_s
179165
raw.inspect
180166
end
167+
168+
private
169+
170+
# Private: Initialize further instance variables
171+
def initialize_helper
172+
unless ['+', '-', '~', '!'].include?(@raw[0])
173+
raise ArgumentError, 'Invalid first element array: diff type needs to be one of: +, -, ~, !'
174+
end
175+
@diff_type = @raw[0]
176+
177+
unless @raw[1].is_a?(String)
178+
raise ArgumentError, "Invalid second element array: type-title-structure needs to be a string not #{@raw[1].class}"
179+
end
180+
raw_1_split = @raw[1].split(/\f/)
181+
@type = raw_1_split[0]
182+
@title = raw_1_split[1]
183+
@structure = raw_1_split[2..-1]
184+
end
181185
end
182186
end
183187
end

lib/octocatalog-diff/catalog-diff/differ.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,8 @@ def catdiff
191191

192192
# Legacy options which are now filters
193193
@opts[:filters] ||= []
194-
if @opts[:suppress_absent_file_details] && !@opts[:filters].include?('AbsentFile')
195-
@opts[:filters] << 'AbsentFile'
196-
end
197-
@opts[:filters] << 'CompilationDir' unless @opts[:filters].include?('CompilationDir')
194+
add_element_to_array(@opts[:filters], 'CompilationDir')
195+
add_element_to_array(@opts[:filters], 'AbsentFile') if @opts[:suppress_absent_file_details]
198196

199197
# Apply any additional pluggable filters.
200198
filter_opts = {
@@ -209,6 +207,13 @@ def catdiff
209207
result
210208
end
211209

210+
# Add an element to an array if it doesn't already exist in that array
211+
# @param array_in [Array] Array to have element added (**mutated** by this method)
212+
# @param element [?] Element to add
213+
def add_element_to_array(array_in, element)
214+
array_in << element unless array_in.include?(element)
215+
end
216+
212217
# Filter the differences for any items that were ignored, by some combination of type, title, and
213218
# attribute. This modifies the array itself by selecting only items that do not meet the ignored
214219
# filter.

lib/octocatalog-diff/catalog-diff/display.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class Display
2525
def self.output(diff_in, options = {}, logger = nil)
2626
diff_x = diff_in.is_a?(OctocatalogDiff::CatalogDiff::Differ) ? diff_in.diff : diff_in
2727
raise ArgumentError, "text_output requires Array<Diff results>; passed in #{diff_in.class}" unless diff_x.is_a?(Array)
28-
diff = diff_x.map { |x| OctocatalogDiff::API::V1::Diff.new(x) }
28+
diff = diff_x.map { |x| OctocatalogDiff::API::V1::Diff.factory(x) }
2929

3030
# req_format means 'requested format' because 'format' has a built-in meaning to Ruby
3131
req_format = options.fetch(:format, :color_text)

lib/octocatalog-diff/catalog-diff/filter.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
require_relative '../api/v1/diff'
12
require_relative 'filter/absent_file'
23
require_relative 'filter/compilation_dir'
34
require_relative 'filter/yaml'
@@ -49,8 +50,14 @@ def self.apply_filters(result, filter_names, options = {})
4950
def self.filter(result, filter_class_name, options = {})
5051
assert_that_filter_exists(filter_class_name)
5152
filter_class_name = [name.to_s, filter_class_name].join('::')
52-
obj = Kernel.const_get(filter_class_name).new(result, options[:logger])
53-
result.reject! { |item| obj.filtered?(item, options) }
53+
54+
# Need to convert each of the results array to the OctocatalogDiff::API::V1::Diff object, if
55+
# it isn't already. The comparison is done on that array which is then applied back to the
56+
# original array.
57+
result_hash = {}
58+
result.each { |x| result_hash[x] = OctocatalogDiff::API::V1::Diff.factory(x) }
59+
obj = Kernel.const_get(filter_class_name).new(result_hash.values, options[:logger])
60+
result.reject! { |item| obj.filtered?(result_hash[item], options) }
5461
end
5562

5663
# Inherited: Constructor. Some filters require working on the entire data set and

lib/octocatalog-diff/catalog-diff/filter/absent_file.rb

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
# frozen_string_literal: true
22

3+
require_relative '../filter'
4+
35
require 'set'
46

57
module OctocatalogDiff
68
module CatalogDiff
79
class Filter
810
# Filter out changes in parameters when the "to" resource has ensure => absent.
911
class AbsentFile < OctocatalogDiff::CatalogDiff::Filter
12+
KEEP_ATTRIBUTES = (Set.new %w(ensure backup force provider)).freeze
13+
1014
# Constructor: Since this filter requires knowledge of the entire array of diffs,
1115
# override the inherited method to store those diffs in an instance variable.
16+
# @param diffs [Array<OctocatalogDiff::API::V1::Diff>] Difference array
17+
# @param _logger [?] Ignored
1218
def initialize(diffs, _logger = nil)
1319
@diffs = diffs
1420
@results = nil
@@ -19,7 +25,7 @@ def initialize(diffs, _logger = nil)
1925
# Return true if the difference is in a resource where `ensure => absent` has been
2026
# declared. Return false if they this is not the case.
2127
#
22-
# @param diff [internal diff format] Difference
28+
# @param diff [OctocatalogDiff::API::V1::Diff] Difference
2329
# @param _options [Hash] Additional options (there are none for this filter)
2430
# @return [Boolean] true if this difference is a YAML file with identical objects, false otherwise
2531
def filtered?(diff, _options = {})
@@ -35,10 +41,9 @@ def build_results
3541
# Which files can we ignore?
3642
@files_to_ignore = Set.new
3743
@diffs.each do |diff|
38-
next unless diff[0] == '~' || diff[0] == '!'
39-
next unless diff[1] =~ /^File\f([^\f]+)\fparameters\fensure$/
40-
next unless ['absent', 'false', false].include?(diff[3])
41-
@files_to_ignore.add Regexp.last_match(1)
44+
next unless diff.change? && diff.type == 'File' && diff.structure == %w(parameters ensure)
45+
next unless ['absent', 'false', false].include?(diff.new_value)
46+
@files_to_ignore.add diff.title
4247
end
4348

4449
# Based on that, which diffs can we ignore?
@@ -49,13 +54,10 @@ def build_results
4954
# @param diff [OctocatalogDiff::API::V1::Diff] Difference under consideration
5055
# @return [Boolean] true = keep, false = discard
5156
def keep_diff?(diff)
52-
keep = %w(ensure backup force provider)
53-
if (diff[0] == '!' || diff[0] == '~') && diff[1] =~ /^File\f(.+)\fparameters\f(.+)$/
54-
if @files_to_ignore.include?(Regexp.last_match(1)) && !keep.include?(Regexp.last_match(2))
55-
return false
56-
end
57-
end
58-
true
57+
return true unless diff.change? && diff.type == 'File' && diff.structure.first == 'parameters'
58+
return true unless @files_to_ignore.include?(diff.title)
59+
return true if KEEP_ATTRIBUTES.include?(diff.structure.last)
60+
false
5961
end
6062
end
6163
end

lib/octocatalog-diff/catalog-diff/filter/compilation_dir.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# frozen_string_literal: true
22

3-
require_relative '../../api/v1/diff'
43
require_relative '../filter'
54

65
module OctocatalogDiff
@@ -13,19 +12,18 @@ class CompilationDir < OctocatalogDiff::CatalogDiff::Filter
1312
# (supplied via options) and checking the differences. If the only thing different
1413
# is the compilation directory, filter it out with a warning.
1514
#
16-
# @param diff_in [Array (Internal Diff Format)] Difference
15+
# @param diff [OctocatalogDiff::API::V1::Diff] Difference
1716
# @param options [Hash] Additional options:
1817
# :from_compilation_dir [String] Compilation directory for the "from" catalog
1918
# :to_compilation_dir [String] Compilation directory for the "to" catalog
2019
# @return [Boolean] true if this difference is a YAML file with identical objects, false otherwise
21-
def filtered?(diff_in, options = {})
20+
def filtered?(diff, options = {})
2221
return false unless options[:from_compilation_dir] && options[:to_compilation_dir]
2322
dir1 = options[:to_compilation_dir]
2423
dir1_rexp = Regexp.escape(dir1)
2524
dir2 = options[:from_compilation_dir]
2625
dir2_rexp = Regexp.escape(dir2)
2726
dir = Regexp.new("(?:#{dir1_rexp}|#{dir2_rexp})")
28-
diff = OctocatalogDiff::API::V1::Diff.new(diff_in)
2927

3028
# Check for added/removed resources where the title of the resource includes the compilation directory
3129
if (diff.addition? || diff.removal?) && diff.title.match(dir)

lib/octocatalog-diff/catalog-diff/filter/yaml.rb

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# frozen_string_literal: true
22

3+
require_relative '../filter'
4+
35
require 'yaml'
46

57
module OctocatalogDiff
@@ -11,20 +13,21 @@ class YAML < OctocatalogDiff::CatalogDiff::Filter
1113
# Return true if the YAML objects are known to be equivalent. Return false if they
1214
# are not equivalent, or if equivalence cannot be determined.
1315
#
14-
# @param diff [Array] Difference
16+
# @param diff_in [OctocatalogDiff::API::V1::Diff] Difference
1517
# @param _options [Hash] Additional options (there are none for this filter)
1618
# @return [Boolean] true if this difference is a YAML file with identical objects, false otherwise
1719
def filtered?(diff, _options = {})
1820
# Skip additions or removals - focus only on changes
19-
return false unless diff[0] == '~' || diff[0] == '!'
21+
return false unless diff.change?
2022

2123
# Make sure we are comparing file content for a file ending in .yaml or .yml extension
22-
return false unless diff[1] =~ /^File\f([^\f]+)\.ya?ml\fparameters\fcontent$/
24+
return false unless diff.type == 'File' && diff.structure == %w(parameters content)
25+
return false unless diff.title =~ /\.ya?ml\z/
2326

24-
# Attempt to convert the old (diff[2]) and new (diff[3]) into YAML objects. Assuming
27+
# Attempt to convert the old value and new value into YAML objects. Assuming
2528
# that doesn't error out, the return value is whether or not they're equal.
26-
obj_old = ::YAML.load(diff[2])
27-
obj_new = ::YAML.load(diff[3])
29+
obj_old = ::YAML.load(diff.old_value)
30+
obj_new = ::YAML.load(diff.new_value)
2831
obj_old == obj_new
2932
rescue # Rescue everything - if something failed, we aren't sure what's going on, so we'll return false.
3033
false

0 commit comments

Comments
 (0)