yadtfp 1.0.2
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/.gitignore +22 -0
- data/.yardopts +9 -0
- data/CONTRIBUTING.md +9 -0
- data/Gemfile +4 -0
- data/Guardfile +16 -0
- data/MIT-LICENSE.txt +20 -0
- data/README.md +285 -0
- data/Rakefile +2 -0
- data/bin/yadtfp +3 -0
- data/lib/yadtfp.rb +21 -0
- data/lib/yadtfp/cli.rb +55 -0
- data/lib/yadtfp/configuration.rb +82 -0
- data/lib/yadtfp/outputters.rb +3 -0
- data/lib/yadtfp/outputters/diffable.rb +74 -0
- data/lib/yadtfp/outputters/pretty.rb +128 -0
- data/lib/yadtfp/outputters_factory.rb +26 -0
- data/lib/yadtfp/parsers.rb +1 -0
- data/lib/yadtfp/parsers/ox.rb +328 -0
- data/lib/yadtfp/parsers_factory.rb +24 -0
- data/lib/yadtfp/version.rb +3 -0
- data/spec/cli_spec.rb +44 -0
- data/spec/configuration_spec.rb +115 -0
- data/spec/outputters/diffable_spec.rb +119 -0
- data/spec/outputters/pretty_spec.rb +260 -0
- data/spec/outputters_factory_spec.rb +20 -0
- data/spec/parsers/ox_spec.rb +966 -0
- data/spec/parsers_factory_spec.rb +18 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/helpers.rb +22 -0
- data/spec/yadtfp_spec.rb +26 -0
- data/yadtfp.gemspec +34 -0
- metadata +206 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dc0e6391243b1ba24c96baf22543c06008664671
|
4
|
+
data.tar.gz: d704c04bc9e32111dacd3af5e3f1cb78c9f4a6f4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 75acbe5a35c0c8abfb6da4c2d433a4cf0fbfbc677bc0785c3fb9dec6dcd79440a4583f51df82a2f14887562fcde63f7ec4a34a2ed52471f4e2ce55684aaec5d9
|
7
|
+
data.tar.gz: 4c760dfd15403f535f6b4304fcd411e48d36fdf6239585a799ded329fe5643903bdc8766fe78c24e90b498913803382911819a542a866341274ba85574a95b8e
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.yardopts
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
Contributions are welcome.
|
4
|
+
|
5
|
+
1. Fork it ( https://github.com/vinodadhikary/yadtfp/fork )
|
6
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
7
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
8
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
9
|
+
5. Create a new Pull Request
|
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
guard :rspec, cmd: 'rspec --color --format doc' do
|
2
|
+
watch(%r{^spec/.+_spec\.rb$})
|
3
|
+
watch(%r{^spec/fabricators/.+_fabricator\.rb$}) { 'spec' }
|
4
|
+
watch(%r{^spec/support/.+\.rb$}) { 'spec' }
|
5
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
6
|
+
|
7
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
8
|
+
watch(%r{^lib/(.+)/(.+)\.rb$}) { |m| "spec/#{m[2]}_spec.rb" }
|
9
|
+
watch(%r{^lib/(.+)/(.+)/(.+)\.rb$}) { |m| "spec/#{m[2]}/#{m[3]}_spec.rb" }
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
# Run `yard` documentation server
|
14
|
+
guard 'yard', port: '8808' do
|
15
|
+
watch(%r{^(.+)\.md|rb$}) { 'yardoc' }
|
16
|
+
end
|
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) Vinod Adhikary 2014.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,285 @@
|
|
1
|
+
# Yadtfp
|
2
|
+
|
3
|
+
`yadtfp` is a diff tool that takes two [well formed](http://en.wikipedia.org/wiki/Well-formed_document)
|
4
|
+
[xml](https://en.wikipedia.org/wiki/XML) documents and generates the differences in an easy to read, concise output.
|
5
|
+
The difference algorithm operates on element values producing a very precise diff possible.
|
6
|
+
|
7
|
+
The name is an acronym for "Yet Another Diff Tool For Param". The original motivation of `yadtfp` was to make it a
|
8
|
+
[`CLI`](http://en.wikipedia.org/wiki/Command-line_interface) tool to compare two xml files containing application
|
9
|
+
configuration parameters, which is how it got it's name, we think.
|
10
|
+
|
11
|
+
`yadtfp` parses each input XML into an array of flat hashes, applies filter and compares the two. The result is an
|
12
|
+
array of difference hashes. The result array is then passed to the selected outputter which prints the output to
|
13
|
+
console.
|
14
|
+
|
15
|
+
|
16
|
+
## Installation
|
17
|
+
|
18
|
+
$ gem install yadtfp
|
19
|
+
|
20
|
+
|
21
|
+
## Documentation
|
22
|
+
|
23
|
+
The code base documentation is [available here](/_index.html).
|
24
|
+
|
25
|
+
|
26
|
+
## Parsers
|
27
|
+
|
28
|
+
Currently `yadtfp` supports [`Ox`](https://github.com/ohler55/ox) parser which is the default.
|
29
|
+
|
30
|
+
|
31
|
+
## Outputters
|
32
|
+
|
33
|
+
Currently `yadtfp` supports `Yadtfp::Outputters::Pretty` outputter which is the default.
|
34
|
+
|
35
|
+
|
36
|
+
### Pretty Outputter
|
37
|
+
|
38
|
+
Pretty outputter generates the output in the following format:
|
39
|
+
|
40
|
+
Changes (Replace left value with right value)
|
41
|
+
---------------------------------------------
|
42
|
+
|
43
|
+
Appends (Add values to left)
|
44
|
+
----------------------------
|
45
|
+
|
46
|
+
Deletes (Remove values from left)
|
47
|
+
---------------------------------
|
48
|
+
|
49
|
+
Summary of differences
|
50
|
+
----------------------
|
51
|
+
Number of differences: x
|
52
|
+
Changes 'c': x
|
53
|
+
Appends 'a': x
|
54
|
+
Deletes 'd': x
|
55
|
+
|
56
|
+
*where `x` is an integer value for each difference.*
|
57
|
+
|
58
|
+
**Note**: In "Summary of differences", Changes, Appends and Deletes are included only if the diff contains respective
|
59
|
+
difference, i.e. if a diff does not contain "Deletes" then "Summary of differences" excludes "Deletes", and likewise for
|
60
|
+
"Appends" and "Changes".
|
61
|
+
|
62
|
+
|
63
|
+
## Other topics of interest
|
64
|
+
|
65
|
+
|
66
|
+
### Path generation
|
67
|
+
|
68
|
+
Path to each XML component, e.g. attribute, comment, cdata, text are based on the following:
|
69
|
+
|
70
|
+
**1. Attribute**
|
71
|
+
|
72
|
+
Attributes are prefixed with `@` sign.
|
73
|
+
|
74
|
+
# Input XML
|
75
|
+
<xml id='foo' />
|
76
|
+
|
77
|
+
# Path to attribute `id`
|
78
|
+
/xml/@id
|
79
|
+
|
80
|
+
**2. Comment**
|
81
|
+
|
82
|
+
Comments are denoted by `comment()`.
|
83
|
+
|
84
|
+
# Input XML
|
85
|
+
<xml>
|
86
|
+
<!-- Root node -->
|
87
|
+
</xml>
|
88
|
+
|
89
|
+
# Path to comment
|
90
|
+
/xml/comment()
|
91
|
+
|
92
|
+
**3. CData**
|
93
|
+
|
94
|
+
CData are denoted by `cdata()`.
|
95
|
+
|
96
|
+
# Input XML
|
97
|
+
<xml>
|
98
|
+
<![CDATA[ Foo ]]>
|
99
|
+
</xml>
|
100
|
+
|
101
|
+
# Path to cdata
|
102
|
+
/xml/cdata()
|
103
|
+
|
104
|
+
**4. Text**
|
105
|
+
|
106
|
+
Texts are denoted by path to the node containing the text.
|
107
|
+
|
108
|
+
# Input XML
|
109
|
+
<xml>Foo</xml>
|
110
|
+
|
111
|
+
# Path to text
|
112
|
+
/xml
|
113
|
+
|
114
|
+
|
115
|
+
### Flat hash
|
116
|
+
|
117
|
+
Each input xml document is parsed into an array of hashes. This hash's key is the path to the element from the path
|
118
|
+
specified in the filter and it's value is the text or value in the xml. If no filter is specified, the default filter
|
119
|
+
is used.
|
120
|
+
|
121
|
+
Example of flat hash data structure, given an input xml:
|
122
|
+
|
123
|
+
# Input XML
|
124
|
+
<xml id='root'>
|
125
|
+
<!-- Root node -->
|
126
|
+
<child id='child'>Foo</child>
|
127
|
+
<![CDATA[ Bar ]]>
|
128
|
+
</xml>
|
129
|
+
|
130
|
+
# Output Array of hashes
|
131
|
+
[
|
132
|
+
{ '/xml/@id' => 'root' },
|
133
|
+
{ '/xml/comment()' => [ 'Root node' ] },
|
134
|
+
{ '/xml/cdata()' => [ 'Bar' ] },
|
135
|
+
{ '/xml/child/@id' => 'child' },
|
136
|
+
{ '/xml/child' => 'Foo' }
|
137
|
+
]
|
138
|
+
|
139
|
+
|
140
|
+
### Difference hash
|
141
|
+
|
142
|
+
There are altogether three types of differences:
|
143
|
+
|
144
|
+
1. Change - `c`
|
145
|
+
2. Append - `a`
|
146
|
+
3. Delete - `d`
|
147
|
+
|
148
|
+
Example difference hash for each difference type is as follows:
|
149
|
+
|
150
|
+
# Change
|
151
|
+
{ type: `c`, path: '', lvalue: '', rvalue: '' }
|
152
|
+
|
153
|
+
# Append
|
154
|
+
{ type: 'a', path: '', lvalue: '', rvalue: '' }
|
155
|
+
|
156
|
+
# Delete
|
157
|
+
{ type: 'd', path: '', lvalue: '', rvalue: '' }
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
### Configuration options
|
162
|
+
|
163
|
+
`yadtfp` supports the following three parameters:
|
164
|
+
|
165
|
+
1. `--filter` to filter content of xml. This is usually applied to perform diff on a subset of input xml.
|
166
|
+
Defaults to `"*"`.
|
167
|
+
|
168
|
+
2. `--parser` to parse input xml. Defaults to `:ox`.
|
169
|
+
|
170
|
+
3. `--outputter` to output result diff. Defaults to `:pretty`.
|
171
|
+
|
172
|
+
|
173
|
+
Each filter option has a shorthand to save a little typing! but **only in the CLI**. The shorthand mapping of each
|
174
|
+
options are:
|
175
|
+
|
176
|
+
1. `--filter`: `-f`
|
177
|
+
2. `--parser`: `-p`
|
178
|
+
3. `--outputter`: `-o`
|
179
|
+
|
180
|
+
Each configuration option is prefixed with double dash `--` except for shorthand notations which are prefixed by a
|
181
|
+
single dash `-`.
|
182
|
+
|
183
|
+
|
184
|
+
### Filters
|
185
|
+
|
186
|
+
Filters are based on [`::Ox::Element#locate()`](http://www.ohler.com/ox/Ox/Element.html#locate-instance_method)
|
187
|
+
|
188
|
+
Examples sourced from documentation for `#Ox::Element#locate()`:
|
189
|
+
|
190
|
+
Family/Pete/* - All children of Pete element
|
191
|
+
Family/?[1] - First element in Family element
|
192
|
+
Family/?[<3]* - First 3 elements in Family element
|
193
|
+
Family/?/@age - Age attribute for each child in Family element
|
194
|
+
Family/*/@type - Type attribute value for decendents of Family element
|
195
|
+
Family/^Comment - Comment children of Family element
|
196
|
+
|
197
|
+
|
198
|
+
|
199
|
+
## CLI Usage
|
200
|
+
|
201
|
+
**1. `yadtfp` two xml strings using default options**
|
202
|
+
|
203
|
+
$ yadtfp -- "<xml id='root' />" "<xml name='root_node' />"
|
204
|
+
Changes (Replace left value with right value)
|
205
|
+
---------------------------------------------
|
206
|
+
|
207
|
+
Appends (Add values to left)
|
208
|
+
----------------------------
|
209
|
+
|
210
|
+
1. Path: /xml/@name
|
211
|
+
Left:
|
212
|
+
Right: root_node
|
213
|
+
|
214
|
+
Deletes (Remove values from left)
|
215
|
+
---------------------------------
|
216
|
+
|
217
|
+
1. Path: /xml/@id
|
218
|
+
Left: root
|
219
|
+
Right:
|
220
|
+
|
221
|
+
|
222
|
+
Summary of differences
|
223
|
+
----------------------
|
224
|
+
Number of differences: 2
|
225
|
+
Appends 'a': 1
|
226
|
+
Deletes 'd': 1
|
227
|
+
|
228
|
+
The above command can be substituted with:
|
229
|
+
|
230
|
+
$ yadtfp --filter "*" --parser "ox" --outputter "pretty" "<xml id='root' />" "<xml name='root_node' />"
|
231
|
+
|
232
|
+
or using shorthand options:
|
233
|
+
|
234
|
+
$ yadtfp -f "*" -p "ox" -o "pretty" "<xml id='root' />" "<xml name='root_node' />"
|
235
|
+
|
236
|
+
|
237
|
+
**2. `yadtfp` two xml files using default options**
|
238
|
+
|
239
|
+
Given two xml files `file1.xml` and `file2.xml`:
|
240
|
+
|
241
|
+
# file1.xml
|
242
|
+
<?xml version='1.0' encoding='utf-8' ?>
|
243
|
+
<xml>Foo</xml>
|
244
|
+
|
245
|
+
# file2.xml
|
246
|
+
<?xml version='1.0' encoding='utf-8' ?>
|
247
|
+
<xml>Bar</xml>
|
248
|
+
|
249
|
+
Execute `yadtfp diff`:
|
250
|
+
|
251
|
+
$ yadtfp -- file1.xml file2.xml
|
252
|
+
Changes (Replace left value with right value)
|
253
|
+
---------------------------------------------
|
254
|
+
|
255
|
+
1. Path: /xml
|
256
|
+
Left: Foo
|
257
|
+
Right: Bar
|
258
|
+
|
259
|
+
Appends (Add values to left)
|
260
|
+
----------------------------
|
261
|
+
|
262
|
+
Deletes (Remove values from left)
|
263
|
+
---------------------------------
|
264
|
+
|
265
|
+
|
266
|
+
Summary of differences
|
267
|
+
----------------------
|
268
|
+
Number of differences: 1
|
269
|
+
Changes 'c': 1
|
270
|
+
|
271
|
+
|
272
|
+
The above command can be substituted with:
|
273
|
+
|
274
|
+
$ yadtfp --filter "*" -parser "ox" -outputter "pretty" file1.xml file2.xml
|
275
|
+
|
276
|
+
or using shorthand options:
|
277
|
+
|
278
|
+
$ yadtfp -f "*" -p "ox" -o "pretty" file1.xml file2.xml
|
279
|
+
|
280
|
+
**Note**: File paths may be absolute or relative from the present working directory.
|
281
|
+
|
282
|
+
|
283
|
+
## Contributing
|
284
|
+
|
285
|
+
Please see [CONTRIBUTING.md](file.CONTRIBUTING.html)
|
data/Rakefile
ADDED
data/bin/yadtfp
ADDED
data/lib/yadtfp.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'yadtfp/version'
|
2
|
+
require 'yadtfp/configuration'
|
3
|
+
require 'yadtfp/parsers'
|
4
|
+
require 'yadtfp/outputters'
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
module Yadtfp
|
9
|
+
|
10
|
+
def self.configuration
|
11
|
+
@configuration = Configuration.instance
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
def self.configure
|
18
|
+
yield(configuration)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/lib/yadtfp/cli.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'yadtfp'
|
3
|
+
|
4
|
+
module Yadtfp
|
5
|
+
|
6
|
+
class CLI < Thor
|
7
|
+
|
8
|
+
|
9
|
+
class_option :filter, aliases: '-f', type: :string, desc: 'FILTER is path to the node in unix directory structure format'
|
10
|
+
class_option :parser, aliases: '-p', type: :string, desc: "PARSER is either 'ox' or 'nokogiri'"
|
11
|
+
class_option :outputter, aliases: '-o', type: :string, desc: "OUTPUTTER is 'pretty'"
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
desc "diff [OPTIONS]... LEFT RIGHT", "Diff left and right xml documents"
|
16
|
+
long_desc <<-LONGDESC
|
17
|
+
`diff LEFT RIGHT` will compare `LEFT` and `RIGHT` and print the result to the terminal.
|
18
|
+
|
19
|
+
When none of the options are specified the default options will apply.
|
20
|
+
|
21
|
+
The default for each options are:
|
22
|
+
\x5 --filter="/"
|
23
|
+
\x5 --parser="ox"
|
24
|
+
\x5 --outputter="pretty"
|
25
|
+
|
26
|
+
Examples:
|
27
|
+
diff file1.xml file2.xml - Diffs two xml files using default options and pretty prints the result to the terminal.
|
28
|
+
LONGDESC
|
29
|
+
def diff(file1, file2)
|
30
|
+
|
31
|
+
# Load config
|
32
|
+
config = Yadtfp::Configuration.parse_options(options)
|
33
|
+
|
34
|
+
|
35
|
+
# Parse
|
36
|
+
parser = Yadtfp::ParsersFactory.create(config.parser)
|
37
|
+
|
38
|
+
left = parser.parse(file1)
|
39
|
+
right = parser.parse(file2)
|
40
|
+
|
41
|
+
|
42
|
+
# Diff
|
43
|
+
diff = parser.diff(left, right)
|
44
|
+
|
45
|
+
|
46
|
+
# Output
|
47
|
+
out = Yadtfp::OutputtersFactory.create(config.outputter, diff)
|
48
|
+
out.print
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
default_task :diff
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|