csv-diff-report 0.3.2 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7c9a403ac0808911b994a8d1ecc167144d7c66d9
4
+ data.tar.gz: 9a8a75226e7845440c668375b3e57f919fe8510a
5
+ SHA512:
6
+ metadata.gz: caf42e6d6dbcbea5243d416a8165d2dcb49b07dbab81d1e2e61092c7dbdc058350746753374701628153645e60241669b7880bdf591c921545888154ac011121
7
+ data.tar.gz: 66a15dfc2bcf8376ccca15135d457ab1f4669c7f70d667078f644a6312520e6284c4d1143b67e8c7d101fbd613b52ee2d4e0e5d3f9e4c798c81bb9f5aa6865e1
data/README.md CHANGED
@@ -87,6 +87,54 @@ Output Options
87
87
 
88
88
  ```
89
89
 
90
+
91
+ ## .csvdiff Files
92
+
93
+ The csvdiff command-line tool supports both file and directory diffs. As
94
+ directories may contain files of different formats, .csvdiff files can be
95
+ used to match file names to file types, and specify the appropriate diff
96
+ settings for each file type.
97
+
98
+ A .csvdiff file can be placed in either the working directory from which the
99
+ csvdiff command is run, or the FROM directory. It consists of a YAML-formatted
100
+ file with the following top-level keys:
101
+
102
+ - defaults: Contains settings to be applied across all file types unless
103
+ overridden for a specific file type.
104
+ - file_types: A hash whose keys are the file type labels used to describe
105
+ files of that type, and whose values are the various diff settings to use
106
+ for that file type.
107
+
108
+ ### .csvdiff Settings
109
+
110
+ All settings that can be specified on the command-line can also be specified via
111
+ .csvdiff for each file type. In addition, several additional settings are
112
+ available via .csvdiff that are not available on the command-line. These
113
+ additional settings are as follows:
114
+
115
+ - pattern: Specifies the file name pattern that is used to match a file name to
116
+ a file type. File types are checked in the order listed, so more general
117
+ patterns must appear later in the .csvdiff file to avoid masking more specific
118
+ patterns; e.g. a pattern of * will match every file, so it should appear as
119
+ the pattern setting of the last entry in the file_types hash to ensure other
120
+ more specific patterns get a chance to match a given file name first.
121
+ - exclude_pattern: Specifies an exclusion pattern for file names. Can be useful
122
+ when a single pattern is correct for a file-type but for a class of exceptions.
123
+ - ignore: A boolean flag that can be used to ignore processing of matching files.
124
+ Useful when a directory contains files that should not be diffed in addition to
125
+ those that should.
126
+ - include: A Hash of field names or indexes to either a regular expression or a
127
+ lambda expression which must be satisfied for records in the source to be diffed.
128
+ Any records with values in the corresponding columns will not be included in the
129
+ diff if the value in that column does not satisfy the regular expression or
130
+ lambda.
131
+ - exclude: A Hash of field names or indexes to either a regular expression or a
132
+ lambda expression which must *not* be satisfied for records in the source to be
133
+ diffed. Any records with values in the corresponding columns will not be included
134
+ in the diff if the value in that column satisfies the regular expression or
135
+ lambda.
136
+
137
+
90
138
  ## Unique Row Identifiers
91
139
 
92
140
  CSVDiff is preferable over a standard line-by-line diff when row order is
@@ -144,6 +192,7 @@ B below Root.
144
192
  Note: If you aren't interested in changes in the order of siblings, then you could use
145
193
  CSVDiff with a :key_field option of column 1, and specify the :ignore_moves option.
146
194
 
195
+
147
196
  ## Warnings
148
197
 
149
198
  When processing and diffing files, CSVDiff may encounter problems with the data or
@@ -167,7 +216,7 @@ column in the data. In this case, a diff can be created simply via:
167
216
  diff = CSVDiff.new(file1, file2)
168
217
  ```
169
218
 
170
- ### Specifynig Unique Row Identifiers
219
+ ### Specifying Unique Row Identifiers
171
220
 
172
221
  Often however, rows are not uniquely identifiable via the first column in the file.
173
222
  In a parent-child hierarchy, for example, combinations of parent and child may be
@@ -253,6 +302,23 @@ diff = CSVDiff.new(file1, file2, parent_field: 'Date', child_fields: ['HomeTeam'
253
302
  ignore_fields: ['CreatedAt', 'UpdatedAt'])
254
303
  ```
255
304
 
305
+ ### Filtering Rows
306
+
307
+ If you need to filter source data before running the diff process, you can use the :include
308
+ and :exclude options to do so. Both options take a Hash as their value; the hash should have
309
+ keys that are the field names or indexes (0-based) on which to filter, and whose values are
310
+ regular expressions or lambdas to be applied to values of the corresponding field. Rows will
311
+ only be diffed if they satisfy :include conditions, and do not satisfy :exclude conditions.
312
+ ```ruby
313
+ # Generate a diff of Arsenal home games not refereed by Clattenburg
314
+ diff = CSVDiff.new(file1, file2, parent_field: 'Date', child_fields: ['HomeTeam', 'AwayTeam'],
315
+ include: {HomeTeam: 'Arsenal'}, exclude: {Referee: /Clattenburg/})
316
+
317
+ # Generate a diff of games played over the Xmas/New Year period
318
+ diff = CSVDiff.new(file1, file2, parent_field: 'Date', child_fields: ['HomeTeam', 'AwayTeam'],
319
+ include: {Date: lambda{ |d| holiday_period.include?(Date.strptime(d, '%y/%m/%d')) } })
320
+ ```
321
+
256
322
  ### Ignoring Certain Changes
257
323
 
258
324
  CSVDiff identifies Adds, Updates, Moves and Deletes; any of these changes can be selectively
@@ -11,7 +11,20 @@ class CSVDiff
11
11
  # Define an on_parse handler for field names or indexes. Splits the
12
12
  # supplied argument value on commas, and converts numbers to Fixnums.
13
13
  register_parse_handler(:parse_fields) do |val, arg, hsh|
14
- val.split(',').map{ |fld| fld =~ /^\d+$/ ? fld.to_i : fld }
14
+ val.split(',').map{ |fld|
15
+ case fld
16
+ when /^\d+$/ then fld.to_i
17
+ when /^:(.+)/ then $1.intern
18
+ else fld
19
+ end
20
+ }
21
+ end
22
+ register_parse_handler(:parse_delimiter) do |val, arg, hsh|
23
+ case val
24
+ when /TAB/i, '\\t' then "\t"
25
+ when /COMMA/i then ','
26
+ else val
27
+ end
15
28
  end
16
29
 
17
30
  title 'CSV-Diff'
@@ -25,50 +38,60 @@ class CSVDiff
25
38
  positional_arg :pattern, 'A file name pattern to use to filter matching files if a directory ' +
26
39
  'diff is being performed', default: '*'
27
40
 
28
- usage_break 'Source Options'
41
+ usage_break 'Source Options:'
29
42
  keyword_arg :file_types, 'A comma-separated list of file-type names (supports wildcards) to process. ' +
30
43
  'Requires the presence of a .csvdiff file in the FROM or current directory to define ' +
31
- 'the file type patterns',
44
+ 'the file type patterns.',
32
45
  short_key: 't', on_parse: :split_to_array
33
46
  keyword_arg :exclude, 'A file name pattern of files to exclude from the diff if a directory ' +
34
- 'diff is being performed',
47
+ 'diff is being performed.',
35
48
  short_key: 'x'
36
- keyword_arg :field_names, 'A comma-separated list of field names for each ' +
37
- 'field in the source files',
49
+ keyword_arg :field_names, 'A comma-separated list of field names for each field in the source files.' +
50
+ 'Only required if the source files do not contain header rows, or to use different names for the fields.',
38
51
  short_key: 'f', on_parse: :split_to_array
39
- keyword_arg :parent_fields, 'The parent field name(s) or index(es)',
52
+ keyword_arg :key_fields, 'The key field name(s) or index(es). Short-hand for specifying parent and child' +
53
+ 'fields separately; assumes the child field is the last key field.',
54
+ short_key: 'k', on_parse: :parse_fields
55
+ keyword_arg :parent_fields, 'The parent field name(s) or index(es).',
40
56
  short_key: 'p', on_parse: :parse_fields
41
- keyword_arg :child_fields, 'The child field name(s) or index(es)',
57
+ keyword_arg :child_fields, 'The child field name(s) or index(es).',
42
58
  short_key: 'c', on_parse: :parse_fields
43
- keyword_arg :key_fields, 'The key field name(s) or index(es)',
44
- short_key: 'k', on_parse: :parse_fields
45
- keyword_arg :encoding, 'The encoding to use when opening the CSV files',
59
+ keyword_arg :delimiter, 'The field delimiter used within the file; use TAB for tab-delimited.',
60
+ short_key: 'd', default: ',', on_parse: :parse_delimiter
61
+ keyword_arg :encoding, 'The encoding to use when opening the CSV files.',
46
62
  short_key: 'e'
47
- flag_arg :tab_delimited, 'If true, the file is assumed to be tab-delimited rather than comma-delimited'
48
- flag_arg :diff_common_fields_only, 'If true, only fields in both files are compared'
49
- flag_arg :trim_whitespace, 'If true, trim leading/trailing whitespace before comparing fields'
63
+ flag_arg :trim_whitespace, 'If true, trim leading/trailing whitespace before comparing fields.',
64
+ short_key: 'w'
50
65
  flag_arg :ignore_header, 'If true, the first line in each source file is ignored; ' +
51
- 'requires the use of the --field-names option to name the fields'
52
- flag_arg :ignore_case, 'If true, field comparisons are performed without regard to case'
53
-
54
- usage_break 'Diff Options'
55
- keyword_arg :ignore_fields, 'The names or indexes of any fields to be ignored during the diff',
56
- short_key: 'i', on_parse: :parse_fields
57
- flag_arg :ignore_adds, "If true, items in TO that are not in FROM are ignored",
66
+ 'requires the use of the --field-names option to name the fields.',
67
+ short_key: 'i'
68
+
69
+ usage_break 'Diff Options:'
70
+ flag_arg :ignore_case, 'If true, field comparisons are performed without regard to case.'
71
+ flag_arg :diff_common_fields_only, 'If true, only fields in both files are compared.',
72
+ short_key: 'C'
73
+ keyword_arg :ignore_fields, 'The names or indexes of any fields to be ignored during the diff.',
74
+ short_key: 'I', on_parse: :parse_fields
75
+ flag_arg :ignore_adds, "If true, items in TO that are not in FROM are ignored.",
58
76
  short_key: 'A'
59
- flag_arg :ignore_deletes, "If true, items in FROM that are not in TO are ignored",
77
+ flag_arg :ignore_deletes, "If true, items in FROM that are not in TO are ignored.",
60
78
  short_key: 'D'
61
- flag_arg :ignore_updates, "If true, changes to non-key properties are ignored",
79
+ flag_arg :ignore_updates, "If true, changes to properties on existing items are ignored.",
62
80
  short_key: 'U'
63
- flag_arg :ignore_moves, "If true, changes in an item's position are ignored",
81
+ flag_arg :ignore_moves, "If true, changes in an item's position are ignored.",
64
82
  short_key: 'M'
65
83
 
66
- usage_break 'Output Options'
67
- keyword_arg :format, 'The format in which to produce the diff report',
68
- default: 'HTML', validation: /^(html|xlsx?|te?xt)$/i
84
+ usage_break 'Output Options:'
85
+ keyword_arg :format, 'The format in which to produce the diff report: HTML, XLSX, or TXT.',
86
+ default: 'HTML', validation: /^(html|xlsx?|te?xt|csv)$/i
69
87
  keyword_arg :output, 'The path to save the diff report to. If not specified, the diff ' +
70
88
  'report will be placed in the same directory as the FROM file, and will be named ' +
71
- 'Diff_<FROM>_to_<TO>.<FORMAT>'
89
+ 'Diff_<FROM>_to_<TO>.<FORMAT>',
90
+ short_key: 'o'
91
+ keyword_arg :output_fields, 'The names or indexes of the fields to include in the diff output.',
92
+ short_key: 'O', on_parse: :parse_fields
93
+ keyword_arg :include_matched, 'If true, fields that match on lines with differences are included ' +
94
+ 'in the diff output; by default, matching fields are not included in the diff output.'
72
95
 
73
96
 
74
97
  # Parses command-line options, and then performs the diff.
@@ -98,11 +121,11 @@ class CSVDiff
98
121
  # Process a CSVDiffReport using +arguments+ to determine all options.
99
122
  def process(arguments)
100
123
  options = {}
101
- exclude_args = [:from, :to, :tab_delimited, :ignore_case]
124
+ exclude_args = [:from, :to, :delimiter, :ignore_case]
102
125
  arguments.each_pair do |arg, val|
103
126
  options[arg] = val if val && !exclude_args.include?(arg)
104
127
  end
105
- options[:csv_options] = {:col_sep => "\t"} if arguments.tab_delimited
128
+ options[:csv_options] = {:col_sep => arguments.delimiter}
106
129
  options[:case_sensitive] = !arguments.ignore_case
107
130
  rep = CSVDiff::Report.new
108
131
  rep.diff(arguments.from, arguments.to, options)
@@ -37,6 +37,7 @@ class CSVDiff
37
37
  @xl_styles['Update'] = s.add_style :fg_color => '0000A0', :bg_color => 'F0F0FF'
38
38
  @xl_styles['Move'] = s.add_style :fg_color => '4040FF'
39
39
  @xl_styles['Delete'] = s.add_style :fg_color => 'FF0000', :strike => true
40
+ @xl_styles['Matched'] = s.add_style :fg_coler => 'A0A0A0'
40
41
  end
41
42
  xl
42
43
  end
@@ -79,18 +80,16 @@ class CSVDiff
79
80
  def xl_diff_sheet(xl, file_diff)
80
81
  sheet_name = file_diff.options[:sheet_name] ||
81
82
  File.basename(file_diff.left.path, File.extname(file_diff.left.path))
82
- all_fields = [:row, :action]
83
- all_fields << :sibling_position unless file_diff.options[:ignore_moves]
83
+ out_fields = output_fields(file_diff)
84
84
  freeze_cols = file_diff.options[:freeze_cols] ||
85
- (all_fields.length + file_diff.left.key_fields.max + 1)
86
- all_fields.concat(file_diff.diff_fields)
85
+ (out_fields.select{ |f| f.is_a?(Symbol) }.length + file_diff.left.key_fields.length)
87
86
  xl.workbook.add_worksheet(name: sheet_name) do |sheet|
88
- sheet.add_row(all_fields.map{ |f| f.is_a?(Symbol) ? titleize(f) : f },
87
+ sheet.add_row(out_fields.map{ |f| f.is_a?(Symbol) ? titleize(f) : f },
89
88
  :style => @xl_styles['Title'])
90
89
  file_diff.diffs.sort_by{|k, v| v[:row] }.each do |key, diff|
91
90
  sheet.add_row do |row|
92
91
  chg = diff[:action]
93
- all_fields.each_with_index do |field, i|
92
+ out_fields.each_with_index do |field, i|
94
93
  cell = nil
95
94
  comment = nil
96
95
  old = nil
@@ -108,9 +107,12 @@ class CSVDiff
108
107
  style = @xl_styles[chg]
109
108
  comment = old
110
109
  end
111
- else
110
+ elsif d
112
111
  new = d
113
112
  style = @xl_styles[chg] if i == 1
113
+ elsif file_diff.options[:include_matched]
114
+ style = @xl_styles['Matched']
115
+ d = file_diff.right[key] && file_diff.right[key][field]
114
116
  end
115
117
  case new
116
118
  when String
@@ -55,6 +55,7 @@ class CSVDiff
55
55
  .delete {background-color: white; color: #FF0000; text-decoration: line-through;}
56
56
  .update {background-color: white; color: #0000A0;}
57
57
  .move {background-color: white; color: #0000A0;}
58
+ .matched {background-color: white; color: #A0A0A0;}
58
59
  .bold {font-weight: bold;}
59
60
  .center {text-align: center;}
60
61
  .right {text-align: right;}
@@ -76,11 +77,12 @@ class CSVDiff
76
77
  body << '</tbody>'
77
78
  body << '</table>'
78
79
  body << '<br>'
79
- body << '<p>Differences:</p>'
80
+ body << '<p>Files:</p>'
80
81
  body << '<table>'
81
- body << '<thead><tr>'
82
- body << '<th>File</th><th>Adds</th><th>Deletes</th><th>Updates</th><th>Moves</th>'
83
- body << '</tr></thead>'
82
+ body << '<thead>'
83
+ body << "<tr><th rowspan=2>File</th><th colspan=2 class='center'>Lines</th><th colspan=4 class='center'>Diffs</th></tr>"
84
+ body << "<tr><th>From</th><th>To</th><th>Adds</th><th>Deletes</th><th>Updates</th><th>Moves</th></tr>"
85
+ body << '</thead>'
84
86
  body << '<tbody>'
85
87
  @diffs.each do |file_diff|
86
88
  label = File.basename(file_diff.left.path)
@@ -90,6 +92,8 @@ class CSVDiff
90
92
  else
91
93
  body << "<td>#{label}</td>"
92
94
  end
95
+ body << "<td class='right'>#{file_diff.left.line_count}</td>"
96
+ body << "<td class='right'>#{file_diff.right.line_count}</td>"
93
97
  body << "<td class='right'>#{file_diff.summary['Add']}</td>"
94
98
  body << "<td class='right'>#{file_diff.summary['Delete']}</td>"
95
99
  body << "<td class='right'>#{file_diff.summary['Update']}</td>"
@@ -126,12 +130,10 @@ class CSVDiff
126
130
  end
127
131
  body << '</p>'
128
132
 
129
- all_fields = [:row, :action]
130
- all_fields << :sibling_position unless file_diff.options[:ignore_moves]
131
- all_fields.concat(file_diff.diff_fields)
133
+ out_fields = output_fields(file_diff)
132
134
  body << '<table>'
133
135
  body << '<thead><tr>'
134
- all_fields.each do |fld|
136
+ out_fields.each do |fld|
135
137
  body << "<th>#{fld.is_a?(Symbol) ? titleize(fld) : fld}</th>"
136
138
  end
137
139
  body << '</tr></thead>'
@@ -139,8 +141,8 @@ class CSVDiff
139
141
  file_diff.diffs.sort_by{|k, v| v[:row] }.each do |key, diff|
140
142
  body << '<tr>'
141
143
  chg = diff[:action]
142
- all_fields.each_with_index do |field, i|
143
- old = nil
144
+ out_fields.each_with_index do |field, i|
145
+ old, new = nil, nil
144
146
  style = case chg
145
147
  when 'Add', 'Delete' then chg.downcase
146
148
  end
@@ -153,9 +155,12 @@ class CSVDiff
153
155
  else
154
156
  style = chg.downcase
155
157
  end
156
- else
158
+ elsif d
157
159
  new = d
158
160
  style = chg.downcase if i == 1
161
+ elsif file_diff.options[:include_matched]
162
+ style = 'matched'
163
+ d = file_diff.right[key] && file_diff.right[key][field]
159
164
  end
160
165
  body << '<td>'
161
166
  body << "<span class='delete'>#{CGI.escapeHTML(old.to_s)}</span>" if old
@@ -101,7 +101,9 @@ class CSVDiff
101
101
  diff_dir(@left, @right, options, opt_file)
102
102
  end
103
103
  else
104
- raise ArgumentError, "Left and right must both exist and be files or directories"
104
+ echo ["From path '#{@left}' not found", :red] unless @left.exist?
105
+ echo ["To path '#{@right}' not found", :red] unless @right.exist?
106
+ raise ArgumentError, "Left and right must both exist and be of the same type (files or directories)"
105
107
  end
106
108
  end
107
109
 
@@ -117,7 +119,7 @@ class CSVDiff
117
119
  xl_output(path)
118
120
  when format.to_s =~ /^html$/i || File.extname(path) =~ /html$/i
119
121
  html_output(path)
120
- when format.to_s =~ /^te?xt$/i || File.extname(path) =~ /txt$/i
122
+ when format.to_s =~ /^(te?xt|csv)$/i || File.extname(path) =~ /(csv|txt)$/i
121
123
  text_output(path)
122
124
  else
123
125
  raise ArgumentError, "Unrecognised output format: #{format}"
@@ -173,7 +175,7 @@ class CSVDiff
173
175
  echo ["No file types are defined in .csvdiff", :yellow]
174
176
  else
175
177
  echo ["The file_types option can only be used when a " +
176
- ".csvdiff is present in the LEFT or current directory", :yellow]
178
+ ".csvdiff is present in the FROM or current directory", :yellow]
177
179
  end
178
180
  end
179
181
  matched_fts.uniq
@@ -183,7 +185,7 @@ class CSVDiff
183
185
  # Diff files that exist in both +left+ and +right+ directories.
184
186
  def diff_dir(left, right, options, opt_file)
185
187
  pattern = Pathname(options[:pattern] || '*')
186
- exclude = options[:exclude]
188
+ exclude = options[:exclude_pattern]
187
189
 
188
190
  echo " Include Pattern: #{pattern}"
189
191
  echo " Exclude Pattern: #{exclude}" if exclude
@@ -209,7 +211,10 @@ class CSVDiff
209
211
  # @param options [Hash] The options to be passed to CSVDiff.
210
212
  def diff_file(left, right, options, opt_file)
211
213
  settings = find_file_type_settings(left, opt_file)
212
- return if settings[:ignore]
214
+ if settings[:ignore]
215
+ echo "Ignoring file #{left}"
216
+ return
217
+ end
213
218
  options = settings.merge(options)
214
219
  from = open_source(left, :from, options)
215
220
  to = open_source(right, :to, options)
@@ -232,11 +237,13 @@ class CSVDiff
232
237
  next if hsh[:pattern] == '-'
233
238
  unless hsh[:matched_files]
234
239
  hsh[:matched_files] = Dir[(left.dirname + hsh[:pattern]).to_s.gsub('\\', '/')]
235
- hsh[:matched_files] -= Dir[(left.dirname + hsh[:exclude]).to_s.gsub('\\', '/')] if hsh[:exclude]
240
+ if hsh[:exclude_pattern]
241
+ hsh[:matched_files] -= Dir[(left.dirname + hsh[:exclude_pattern]).to_s.gsub('\\', '/')]
242
+ end
236
243
  end
237
244
  if hsh[:matched_files].include?(left.to_s)
238
245
  settings.merge!(hsh)
239
- [:pattern, :exclude, :matched_files].each{ |k| settings.delete(k) }
246
+ [:pattern, :exclude_pattern, :matched_files].each{ |k| settings.delete(k) }
240
247
  break
241
248
  end
242
249
  end
@@ -252,11 +259,29 @@ class CSVDiff
252
259
  out = ["Opening #{left_right.to_s.upcase} file '#{File.basename(src)}'..."]
253
260
  csv_src = CSVDiff::CSVSource.new(src.to_s, options)
254
261
  out << [" #{csv_src.lines.size} lines read", :white]
262
+ if csv_src.skip_count > 0
263
+ out << [" (#{csv_src.skip_count} lines skipped)", :yellow]
264
+ end
255
265
  echo(*out)
256
266
  csv_src.warnings.each{ |warn| echo [warn, :yellow] }
257
267
  csv_src
258
268
  end
259
269
 
270
+
271
+ # Returns the fields to be output in the diff file
272
+ def output_fields(diff)
273
+ if diff.options[:output_fields]
274
+ diff.options[:output_fields].map do |fld|
275
+ fld.is_a?(Fixnum) ? diff.diff_fields[fld] : fld
276
+ end
277
+ else
278
+ out_fields = [:row, :action]
279
+ out_fields << :sibling_position unless diff.options[:ignore_moves]
280
+ out_fields.concat(diff.diff_fields)
281
+ out_fields
282
+ end
283
+ end
284
+
260
285
  end
261
286
 
262
287
  end
@@ -11,7 +11,7 @@ class CSVDiff
11
11
 
12
12
  # Generare a diff report in TEXT format.
13
13
  def text_output(output)
14
- path = "#{File.dirname(output)}/#{File.basename(output, File.extname(output))}.diff"
14
+ path = "#{File.dirname(output)}/#{File.basename(output, File.extname(output))}.csv"
15
15
  CSV.open(path, 'w') do |csv|
16
16
  @diffs.each do |file_diff|
17
17
  text_diff(csv, file_diff) if file_diff.diffs.size > 0
@@ -22,17 +22,15 @@ class CSVDiff
22
22
 
23
23
 
24
24
  def text_diff(csv, file_diff)
25
- count = 0
26
-
27
- all_fields = [:row, :action]
28
- all_fields << :sibling_position unless file_diff.options[:ignore_moves]
29
- all_fields.concat(file_diff.diff_fields)
30
-
31
- csv << all_fields.map{ |fld| fld.is_a?(Symbol) ? titleize(fld) : fld }
25
+ out_fields = output_fields(file_diff)
26
+ csv << out_fields.map{ |fld| fld.is_a?(Symbol) ? titleize(fld) : fld }
32
27
  file_diff.diffs.each do |key, diff|
33
- row = all_fields.map do |field|
28
+ row = out_fields.map do |field|
34
29
  d = diff[field]
35
30
  d = d.last if d.is_a?(Array)
31
+ if d.nil? && file_diff.options[:include_matched]
32
+ d = file_diff.right[key] && file_diff.right[key][field]
33
+ end
36
34
  d
37
35
  end
38
36
  csv << row
metadata CHANGED
@@ -1,68 +1,60 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csv-diff-report
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
5
- prerelease:
4
+ version: 0.3.4
6
5
  platform: ruby
7
6
  authors:
8
7
  - Adam Gardiner
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2016-01-26 00:00:00.000000000 Z
11
+ date: 2017-05-17 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: csv-diff
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
- version: '0.3'
19
+ version: 0.3.3
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
- version: '0.3'
26
+ version: 0.3.3
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: arg-parser
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0.2'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0.2'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: color-console
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0.1'
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0.1'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: axlsx
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ~>
68
60
  - !ruby/object:Gem::Version
@@ -70,19 +62,26 @@ dependencies:
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ~>
76
67
  - !ruby/object:Gem::Version
77
68
  version: '1.3'
78
- description: ! " This library generates diff reports of CSV files, using the
79
- diff capabilities\n of the CSV Diff gem.\n\n Unlike a standard diff
80
- that compares line by line, and is sensitive to the\n ordering of records,
81
- CSV Diff identifies common lines by key field(s), and\n then compares the
82
- contents of the fields in each line.\n\n CSV Diff Report takes the diff information
83
- calculated by CSV Diff, and uses it to produce\n Excel or HTML-based diff
84
- reports. It also provides a command-line tool for generating\n these diff
85
- reports from CSV files.\n"
69
+ description: |2
70
+ This library generates diff reports of CSV files, using the diff capabilities
71
+ of the CSV Diff gem.
72
+
73
+ Unlike a standard diff that compares line by line, and is sensitive to the
74
+ ordering of records, CSV-Diff identifies common lines by key field(s), and
75
+ then compares the contents of the fields in each line.
76
+
77
+ CSV-Diff Report takes the diff information calculated by CSV-Diff, and
78
+ uses it to produce Excel, HTML, or text diff reports. It also provides a
79
+ command-line tool (csvdiff) for generating these diff reports from CSV files.
80
+
81
+ The csvdiff command-line tool supports both file and directory diffs. As
82
+ directories may contain files of different formats, .csvdiff files can be
83
+ used to match file names to file types, and specify the appropriate diff
84
+ settings for each file type.
86
85
  email: adam.b.gardiner@gmail.com
87
86
  executables:
88
87
  - csvdiff
@@ -98,31 +97,29 @@ files:
98
97
  - lib/csv-diff-report/text.rb
99
98
  - lib/csv-diff-report.rb
100
99
  - lib/csv_diff_report.rb
101
- - !binary |-
102
- YmluL2NzdmRpZmY=
100
+ - bin/csvdiff
103
101
  homepage: https://github.com/agardiner/csv-diff-report
104
102
  licenses: []
103
+ metadata: {}
105
104
  post_install_message:
106
105
  rdoc_options: []
107
106
  require_paths:
108
107
  - lib
109
108
  required_ruby_version: !ruby/object:Gem::Requirement
110
- none: false
111
109
  requirements:
112
- - - ! '>='
110
+ - - '>='
113
111
  - !ruby/object:Gem::Version
114
112
  version: '0'
115
113
  required_rubygems_version: !ruby/object:Gem::Requirement
116
- none: false
117
114
  requirements:
118
- - - ! '>='
115
+ - - '>='
119
116
  - !ruby/object:Gem::Version
120
117
  version: '0'
121
118
  requirements: []
122
119
  rubyforge_project:
123
- rubygems_version: 1.8.21
120
+ rubygems_version: 2.0.14.1
124
121
  signing_key:
125
- specification_version: 3
122
+ specification_version: 4
126
123
  summary: CSV Diff Report is a library for generating diff reports using the CSV Diff
127
124
  gem
128
125
  test_files: []