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.
- checksums.yaml +7 -0
- data/README.md +67 -1
- data/lib/csv-diff-report/cli.rb +53 -30
- data/lib/csv-diff-report/excel.rb +9 -7
- data/lib/csv-diff-report/html.rb +16 -11
- data/lib/csv-diff-report/report.rb +32 -7
- data/lib/csv-diff-report/text.rb +7 -9
- metadata +32 -35
checksums.yaml
ADDED
@@ -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
|
-
###
|
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
|
data/lib/csv-diff-report/cli.rb
CHANGED
@@ -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|
|
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
|
-
'
|
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 :
|
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 :
|
44
|
-
short_key: '
|
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 :
|
48
|
-
|
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
|
-
|
53
|
-
|
54
|
-
usage_break 'Diff Options'
|
55
|
-
|
56
|
-
|
57
|
-
|
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
|
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, :
|
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 =>
|
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
|
-
|
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
|
-
(
|
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(
|
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
|
-
|
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
|
-
|
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
|
data/lib/csv-diff-report/html.rb
CHANGED
@@ -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>
|
80
|
+
body << '<p>Files:</p>'
|
80
81
|
body << '<table>'
|
81
|
-
body << '<thead
|
82
|
-
body <<
|
83
|
-
body <<
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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[:
|
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
|
-
|
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
|
-
|
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, :
|
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
|
data/lib/csv-diff-report/text.rb
CHANGED
@@ -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))}.
|
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
|
-
|
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 =
|
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.
|
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:
|
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:
|
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:
|
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:
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
-
|
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:
|
120
|
+
rubygems_version: 2.0.14.1
|
124
121
|
signing_key:
|
125
|
-
specification_version:
|
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: []
|