csv-diff-report 0.3.2 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []