diff-lcs 1.4.3 → 1.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Contributing.md +83 -49
- data/History.md +41 -0
- data/Rakefile +23 -6
- data/lib/diff/lcs.rb +8 -1
- data/lib/diff/lcs/block.rb +1 -1
- data/lib/diff/lcs/hunk.rb +107 -40
- data/lib/diff/lcs/ldiff.rb +16 -20
- data/spec/fixtures/ldiff/output.diff-c +2 -2
- data/spec/fixtures/ldiff/output.diff-u +2 -2
- data/spec/hunk_spec.rb +21 -10
- data/spec/issues_spec.rb +60 -4
- data/spec/ldiff_spec.rb +33 -32
- data/spec/spec_helper.rb +19 -19
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20a82b46de7966bb69d8293ece23c885ff05a3a6f1828d99466079026200e3bd
|
4
|
+
data.tar.gz: af785a974e010578214c66694d3e2fd232b26a452d41049a55a9127c07f4b4d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f9ef284f2af3cb47d73100700dbfc39ac16802735f6751637025ed803604b7e27272b34ed1deccc2ddc4813b6e170c7ae2b3012afb094fc5e72d446866455e4
|
7
|
+
data.tar.gz: 0b5b56817c536cd55c52e43f2e9ac5b70d76ef1edf9dcf1e7639917da16fcd65f1bf4472df7c44d8d44603c2f5caa2748ce6ddbd41bb7b0215ad3fd0c38fb49a
|
data/Contributing.md
CHANGED
@@ -1,32 +1,35 @@
|
|
1
1
|
## Contributing
|
2
2
|
|
3
|
-
I value any contribution to Diff::LCS you can provide: a bug report, a
|
4
|
-
request, or code contributions. Code contributions to Diff::LCS are
|
5
|
-
<del>welcome</del>encouraged. Because Diff::LCS is a complex
|
6
|
-
are a few guidelines:
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
3
|
+
I value any contribution to Diff::LCS you can provide: a bug report, a
|
4
|
+
feature request, or code contributions. Code contributions to Diff::LCS are
|
5
|
+
especially <del>welcome</del>encouraged. Because Diff::LCS is a complex
|
6
|
+
codebase, there are a few guidelines:
|
7
|
+
|
8
|
+
- Code changes _will not_ be accepted without tests. The test suite is
|
9
|
+
written with [RSpec][].
|
10
|
+
- Match my coding style.
|
11
|
+
- Use a thoughtfully-named topic branch that contains your change. Rebase
|
12
|
+
your commits into logical chunks as necessary.
|
13
|
+
- Use [quality commit messages][].
|
14
|
+
- Do not change the version number; when your patch is accepted and a release
|
15
|
+
is made, the version will be updated at that point.
|
16
|
+
- Submit a GitHub pull request with your changes.
|
17
|
+
- New or changed behaviours require appropriate documentation.
|
18
18
|
|
19
19
|
### Test Dependencies
|
20
20
|
|
21
|
-
Diff::LCS uses Ryan Davis’s [Hoe][] to manage the release process, and it
|
22
|
-
a number of rake tasks. You will mostly be interested in:
|
21
|
+
Diff::LCS uses Ryan Davis’s [Hoe][] to manage the release process, and it
|
22
|
+
adds a number of rake tasks. You will mostly be interested in:
|
23
23
|
|
24
|
-
|
24
|
+
```sh
|
25
|
+
$ rake
|
26
|
+
```
|
25
27
|
|
26
28
|
which runs the tests the same way that:
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
+
```sh
|
31
|
+
$ rake spec
|
32
|
+
```
|
30
33
|
|
31
34
|
will do.
|
32
35
|
|
@@ -34,51 +37,82 @@ To assist with the installation of the development dependencies, I have
|
|
34
37
|
provided a Gemfile pointing to the (generated) `diff-lcs.gemspec` file. This
|
35
38
|
will permit you to do:
|
36
39
|
|
37
|
-
|
40
|
+
```sh
|
41
|
+
$ bundle install
|
42
|
+
```
|
38
43
|
|
39
44
|
to get the development dependencies. If you aleady have `hoe` installed, you
|
40
45
|
can accomplish the same thing with:
|
41
46
|
|
42
|
-
|
47
|
+
```sh
|
48
|
+
$ rake newb
|
49
|
+
```
|
43
50
|
|
44
51
|
This task will install any missing dependencies, run the tests/specs, and
|
45
52
|
generate the RDoc.
|
46
53
|
|
47
54
|
You can run tests with code coverage analysis by running:
|
48
55
|
|
49
|
-
|
56
|
+
```sh
|
57
|
+
$ rake spec:coverage
|
58
|
+
```
|
50
59
|
|
51
60
|
### Workflow
|
52
61
|
|
53
62
|
Here's the most direct way to get your work merged into the project:
|
54
63
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
change does and the why you think it should be merged.
|
64
|
+
- Fork the project.
|
65
|
+
- Clone down your fork (`git clone git://github.com/<username>/diff-lcs.git`).
|
66
|
+
- Create a topic branch to contain your change (`git checkout -b my_awesome_feature`).
|
67
|
+
- Hack away, add tests. Not necessarily in that order.
|
68
|
+
- Make sure everything still passes by running `rake`.
|
69
|
+
- If necessary, rebase your commits into logical chunks, without errors.
|
70
|
+
- Push the branch up (`git push origin my_awesome_feature`).
|
71
|
+
- Create a pull request against halostatue/diff-lcs and describe what your
|
72
|
+
change does and the why you think it should be merged.
|
65
73
|
|
66
74
|
### Contributors
|
67
75
|
|
68
|
-
|
69
|
-
|
70
|
-
Thanks to everyone else who has contributed to Diff::LCS:
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
76
|
+
- Austin Ziegler created Diff::LCS.
|
77
|
+
|
78
|
+
Thanks to everyone else who has contributed code or bug reports to Diff::LCS:
|
79
|
+
|
80
|
+
- @ginriki
|
81
|
+
- @joshbronson
|
82
|
+
- @kevinmook
|
83
|
+
- @mckaz
|
84
|
+
- Akinori Musha
|
85
|
+
- Artem Ignatyev
|
86
|
+
- Brandon Fish
|
87
|
+
- Camille Drapier
|
88
|
+
- Cédric Boutillier
|
89
|
+
- Gregg Kellogg
|
90
|
+
- Jagdeep Singh
|
91
|
+
- Jason Gladish
|
92
|
+
- Jon Rowe
|
93
|
+
- Josef Strzibny
|
94
|
+
- Josep (@apuratepp)
|
95
|
+
- Josh Bronson
|
96
|
+
- Jun Aruga
|
97
|
+
- Kenichi Kamiya
|
98
|
+
- Kensuke Nagae
|
99
|
+
- Kevin Ansfield
|
100
|
+
- Koichi Ito
|
101
|
+
- Mark Friedgan
|
102
|
+
- Michael Granger
|
103
|
+
- Myron Marston
|
104
|
+
- Nicolas Leger
|
105
|
+
- Oleg Orlov
|
106
|
+
- Paul Kunysch
|
107
|
+
- Pete Higgins
|
108
|
+
- Peter Wagenet
|
109
|
+
- Philippe Lafoucrière
|
110
|
+
- Ryan Lovelett
|
111
|
+
- Scott Steele
|
112
|
+
- Simon Courtois
|
113
|
+
- Tomas Jura
|
114
|
+
- Vít Ondruch
|
115
|
+
|
116
|
+
[rspec]: http://rspec.info/documentation/
|
83
117
|
[quality commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
84
|
-
[
|
118
|
+
[hoe]: https://github.com/seattlerb/hoe
|
data/History.md
CHANGED
@@ -1,5 +1,42 @@
|
|
1
1
|
# History
|
2
2
|
|
3
|
+
## 1.4.4 / 2020-07-01
|
4
|
+
|
5
|
+
- Fixed an issue reported by Jun Aruga in the Diff::LCS::Ldiff binary text
|
6
|
+
detection. [#44][]
|
7
|
+
- Fixed a theoretical issue reported by Jun Aruga in Diff::LCS::Hunk to raise
|
8
|
+
a more useful exception. [#43][]
|
9
|
+
- Added documentation that should address custom object issues as reported in
|
10
|
+
[#35][].
|
11
|
+
|
12
|
+
- Fixed more diff errors, in part reported in [#65][].
|
13
|
+
|
14
|
+
- The use of `Numeric#abs` is incorrect in `Diff::LCS::Block#diff_size`.
|
15
|
+
The diff size _must_ be accurate for correct change placement.
|
16
|
+
- When selecting @max_diff_size in Diff::LCS::Hunk, choose it based on
|
17
|
+
`block.diff_size.abs`.
|
18
|
+
- Made a number of changes that will, unfortunately, increase allocations
|
19
|
+
at the cost of being safe with frozen strings.
|
20
|
+
- Add some knowledge that when `Diff::LCS::Hunk#diff` is called, that we
|
21
|
+
are processing the _last_ hunk, so some changes will be made to how the
|
22
|
+
output is generated.
|
23
|
+
|
24
|
+
- `old`, `ed`, and `reverse_ed` formats have no differences.
|
25
|
+
- `unified` format will report `` given the
|
26
|
+
correct conditions, at most once. Unified range reporting also
|
27
|
+
differs for the last hunk such that the `length` of the range is
|
28
|
+
reduced by one.
|
29
|
+
- `context` format will report `\No newline at end of file` given the
|
30
|
+
correct conditions, up to once per "file". Context range reporting also
|
31
|
+
differs for the last hunk such that the `end` part of the range is
|
32
|
+
reduced by one to a minimum of one.
|
33
|
+
|
34
|
+
- Added a bunch more tests for the cases above, and fixed `hunk_spec.rb` so
|
35
|
+
that the phrase being compared isn't nonsense French.
|
36
|
+
|
37
|
+
- Updated formatting.
|
38
|
+
- Added a Rake task to assist with manual testing on Ruby 1.8.
|
39
|
+
|
3
40
|
## 1.4.3 / 2020-06-29
|
4
41
|
|
5
42
|
- Fixed several issues with the 1.4 on Rubies older than 2.0. Some of this was
|
@@ -263,8 +300,11 @@
|
|
263
300
|
[#29]: https://github.com/halostatue/diff-lcs/pull/29
|
264
301
|
[#33]: https://github.com/halostatue/diff-lcs/issues/33
|
265
302
|
[#34]: https://github.com/halostatue/diff-lcs/pull/34
|
303
|
+
[#35]: https://github.com/halostatue/diff-lcs/issues/35
|
266
304
|
[#36]: https://github.com/halostatue/diff-lcs/pull/36
|
267
305
|
[#38]: https://github.com/halostatue/diff-lcs/issues/38
|
306
|
+
[#43]: https://github.com/halostatue/diff-lcs/issues/43
|
307
|
+
[#44]: https://github.com/halostatue/diff-lcs/issues/44
|
268
308
|
[#47]: https://github.com/halostatue/diff-lcs/pull/47
|
269
309
|
[#48]: https://github.com/halostatue/diff-lcs/issues/48
|
270
310
|
[#49]: https://github.com/halostatue/diff-lcs/pull/49
|
@@ -276,3 +316,4 @@
|
|
276
316
|
[#60]: https://github.com/halostatue/diff-lcs/issues/60
|
277
317
|
[#61]: https://github.com/halostatue/diff-lcs/pull/61
|
278
318
|
[#63]: https://github.com/halostatue/diff-lcs/issues/63
|
319
|
+
[#65]: https://github.com/halostatue/diff-lcs/issues/65
|
data/Rakefile
CHANGED
@@ -10,18 +10,19 @@ Hoe.plugin :gemspec2
|
|
10
10
|
Hoe.plugin :git
|
11
11
|
|
12
12
|
if RUBY_VERSION < '1.9'
|
13
|
-
class Array
|
13
|
+
class Array #:nodoc:
|
14
14
|
def to_h
|
15
|
-
Hash[*
|
15
|
+
Hash[*flatten(1)]
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
class Gem::Specification
|
20
|
-
def metadata=(*)
|
21
|
-
|
19
|
+
class Gem::Specification #:nodoc:
|
20
|
+
def metadata=(*); end
|
21
|
+
|
22
|
+
def default_value(*); end
|
22
23
|
end
|
23
24
|
|
24
|
-
class Object
|
25
|
+
class Object #:nodoc:
|
25
26
|
def caller_locations(*)
|
26
27
|
[]
|
27
28
|
end
|
@@ -55,3 +56,19 @@ if RUBY_VERSION >= '2.0' && RUBY_ENGINE == 'ruby'
|
|
55
56
|
end
|
56
57
|
end
|
57
58
|
end
|
59
|
+
|
60
|
+
task :ruby18 do
|
61
|
+
puts <<-MESSAGE
|
62
|
+
You are starting a barebones Ruby 1.8 docker environment. You will need to
|
63
|
+
do the following:
|
64
|
+
|
65
|
+
- mv Gemfile.lock{,.v2}
|
66
|
+
- gem install bundler --version 1.17.2 --no-ri --no-rdoc
|
67
|
+
- ruby -S bundle
|
68
|
+
- rake
|
69
|
+
|
70
|
+
Don't forget to restore your Gemfile.lock after testing.
|
71
|
+
|
72
|
+
MESSAGE
|
73
|
+
sh "docker run -it --rm -v #{Dir.pwd}:/root/diff-lcs bellbind/docker-ruby18-rails2 bash -l"
|
74
|
+
end
|
data/lib/diff/lcs.rb
CHANGED
@@ -49,7 +49,7 @@ module Diff; end unless defined? Diff # rubocop:disable Style/Documentation
|
|
49
49
|
# a x b y c z p d q
|
50
50
|
# a b c a x b y c z
|
51
51
|
module Diff::LCS
|
52
|
-
VERSION = '1.4.
|
52
|
+
VERSION = '1.4.4'
|
53
53
|
end
|
54
54
|
|
55
55
|
require 'diff/lcs/callbacks'
|
@@ -60,6 +60,13 @@ module Diff::LCS # rubocop:disable Style/Documentation
|
|
60
60
|
# +self+ and +other+. See Diff::LCS#lcs.
|
61
61
|
#
|
62
62
|
# lcs = seq1.lcs(seq2)
|
63
|
+
#
|
64
|
+
# A note when using objects: Diff::LCS only works properly when each object
|
65
|
+
# can be used as a key in a Hash, which typically means that the objects must
|
66
|
+
# implement Object#eql? in a way that two identical values compare
|
67
|
+
# identically for key purposes. That is:
|
68
|
+
#
|
69
|
+
# O.new('a').eql?(O.new('a')) == true
|
63
70
|
def lcs(other, &block) #:yields self[i] if there are matched subsequences:
|
64
71
|
Diff::LCS.lcs(self, other, &block)
|
65
72
|
end
|
data/lib/diff/lcs/block.rb
CHANGED
data/lib/diff/lcs/hunk.rb
CHANGED
@@ -6,26 +6,38 @@ require 'diff/lcs/block'
|
|
6
6
|
# each block. (So if we're not using context, every hunk will contain one
|
7
7
|
# block.) Used in the diff program (bin/ldiff).
|
8
8
|
class Diff::LCS::Hunk
|
9
|
+
OLD_DIFF_OP_ACTION = { '+' => 'a', '-' => 'd', '!' => 'c' }.freeze #:nodoc:
|
10
|
+
ED_DIFF_OP_ACTION = { '+' => 'a', '-' => 'd', '!' => 'c' }.freeze #:nodoc:
|
11
|
+
|
12
|
+
private_constant :OLD_DIFF_OP_ACTION, :ED_DIFF_OP_ACTION if respond_to?(:private_constant)
|
13
|
+
|
9
14
|
# Create a hunk using references to both the old and new data, as well as the
|
10
15
|
# piece of data.
|
11
16
|
def initialize(data_old, data_new, piece, flag_context, file_length_difference)
|
12
17
|
# At first, a hunk will have just one Block in it
|
13
18
|
@blocks = [Diff::LCS::Block.new(piece)]
|
19
|
+
|
20
|
+
if @blocks[0].remove.empty? && @blocks[0].insert.empty?
|
21
|
+
fail "Cannot build a hunk from #{piece.inspect}; has no add or remove actions"
|
22
|
+
end
|
23
|
+
|
14
24
|
if String.method_defined?(:encoding)
|
15
25
|
@preferred_data_encoding = data_old.fetch(0, data_new.fetch(0, '')).encoding
|
16
26
|
end
|
27
|
+
|
17
28
|
@data_old = data_old
|
18
29
|
@data_new = data_new
|
19
30
|
|
20
31
|
before = after = file_length_difference
|
21
32
|
after += @blocks[0].diff_size
|
22
33
|
@file_length_difference = after # The caller must get this manually
|
23
|
-
@max_diff_size = @blocks.map { |e| e.diff_size }.max
|
34
|
+
@max_diff_size = @blocks.map { |e| e.diff_size.abs }.max
|
35
|
+
|
24
36
|
|
25
37
|
# Save the start & end of each array. If the array doesn't exist (e.g.,
|
26
|
-
# we're only adding items in this block), then figure out the line
|
27
|
-
#
|
28
|
-
#
|
38
|
+
# we're only adding items in this block), then figure out the line number
|
39
|
+
# based on the line number of the other file and the current difference in
|
40
|
+
# file lengths.
|
29
41
|
if @blocks[0].remove.empty?
|
30
42
|
a1 = a2 = nil
|
31
43
|
else
|
@@ -55,7 +67,7 @@ class Diff::LCS::Hunk
|
|
55
67
|
|
56
68
|
# Change the "start" and "end" fields to note that context should be added
|
57
69
|
# to this hunk.
|
58
|
-
attr_accessor :flag_context
|
70
|
+
attr_accessor :flag_context # rubocop:disable Layout/EmptyLinesAroundAttributeAccessor
|
59
71
|
undef :flag_context=
|
60
72
|
def flag_context=(context) #:nodoc: # rubocop:disable Lint/DuplicateMethods
|
61
73
|
return if context.nil? or context.zero?
|
@@ -101,18 +113,18 @@ class Diff::LCS::Hunk
|
|
101
113
|
end
|
102
114
|
|
103
115
|
# Returns a diff string based on a format.
|
104
|
-
def diff(format)
|
116
|
+
def diff(format, last = false)
|
105
117
|
case format
|
106
118
|
when :old
|
107
|
-
old_diff
|
119
|
+
old_diff(last)
|
108
120
|
when :unified
|
109
|
-
unified_diff
|
121
|
+
unified_diff(last)
|
110
122
|
when :context
|
111
|
-
context_diff
|
123
|
+
context_diff(last)
|
112
124
|
when :ed
|
113
125
|
self
|
114
126
|
when :reverse_ed, :ed_finish
|
115
|
-
ed_diff(format)
|
127
|
+
ed_diff(format, last)
|
116
128
|
else
|
117
129
|
fail "Unknown diff format #{format}."
|
118
130
|
end
|
@@ -120,35 +132,34 @@ class Diff::LCS::Hunk
|
|
120
132
|
|
121
133
|
# Note that an old diff can't have any context. Therefore, we know that
|
122
134
|
# there's only one block in the hunk.
|
123
|
-
def old_diff
|
135
|
+
def old_diff(_last = false)
|
124
136
|
warn 'Expecting only one block in an old diff hunk!' if @blocks.size > 1
|
125
|
-
op_act = { '+' => 'a', '-' => 'd', '!' => 'c' }
|
126
137
|
|
127
138
|
block = @blocks[0]
|
128
139
|
|
129
140
|
# Calculate item number range. Old diff range is just like a context
|
130
141
|
# diff range, except the ranges are on one line with the action between
|
131
142
|
# them.
|
132
|
-
s = encode("#{context_range(:old)}#{
|
143
|
+
s = encode("#{context_range(:old, ',')}#{OLD_DIFF_OP_ACTION[block.op]}#{context_range(:new, ',')}\n")
|
133
144
|
# If removing anything, just print out all the remove lines in the hunk
|
134
145
|
# which is just all the remove lines in the block.
|
135
146
|
unless block.remove.empty?
|
136
|
-
@data_old[@start_old..@end_old].each { |e| s << encode('< ') + e + encode("\n") }
|
147
|
+
@data_old[@start_old..@end_old].each { |e| s << encode('< ') + e.chomp + encode("\n") }
|
137
148
|
end
|
138
149
|
|
139
150
|
s << encode("---\n") if block.op == '!'
|
140
151
|
|
141
152
|
unless block.insert.empty?
|
142
|
-
@data_new[@start_new..@end_new].each { |e| s << encode('> ') + e + encode("\n") }
|
153
|
+
@data_new[@start_new..@end_new].each { |e| s << encode('> ') + e.chomp + encode("\n") }
|
143
154
|
end
|
144
155
|
|
145
156
|
s
|
146
157
|
end
|
147
158
|
private :old_diff
|
148
159
|
|
149
|
-
def unified_diff
|
160
|
+
def unified_diff(last = false)
|
150
161
|
# Calculate item number range.
|
151
|
-
s = encode("@@ -#{unified_range(:old)} +#{unified_range(:new)} @@\n")
|
162
|
+
s = encode("@@ -#{unified_range(:old, last)} +#{unified_range(:new, last)} @@\n")
|
152
163
|
|
153
164
|
# Outlist starts containing the hunk of the old file. Removing an item
|
154
165
|
# just means putting a '-' in front of it. Inserting an item requires
|
@@ -161,7 +172,14 @@ class Diff::LCS::Hunk
|
|
161
172
|
# file -- don't take removed items into account.
|
162
173
|
lo, hi, num_added, num_removed = @start_old, @end_old, 0, 0
|
163
174
|
|
164
|
-
outlist = @data_old[lo..hi].map { |e|
|
175
|
+
outlist = @data_old[lo..hi].map { |e| String.new("#{encode(' ')}#{e.chomp}") }
|
176
|
+
|
177
|
+
last_block = blocks[-1]
|
178
|
+
|
179
|
+
if last
|
180
|
+
old_missing_newline = missing_last_newline?(@data_old)
|
181
|
+
new_missing_newline = missing_last_newline?(@data_new)
|
182
|
+
end
|
165
183
|
|
166
184
|
@blocks.each do |block|
|
167
185
|
block.remove.each do |item|
|
@@ -170,67 +188,100 @@ class Diff::LCS::Hunk
|
|
170
188
|
outlist[offset][0, 1] = encode(op)
|
171
189
|
num_removed += 1
|
172
190
|
end
|
191
|
+
|
192
|
+
if last && block == last_block && old_missing_newline && !new_missing_newline
|
193
|
+
outlist << encode('\')
|
194
|
+
num_removed += 1
|
195
|
+
end
|
196
|
+
|
173
197
|
block.insert.each do |item|
|
174
198
|
op = item.action.to_s # +
|
175
199
|
offset = item.position - @start_new + num_removed
|
176
|
-
outlist[offset, 0] = encode(op) + @data_new[item.position]
|
200
|
+
outlist[offset, 0] = encode(op) + @data_new[item.position].chomp
|
177
201
|
num_added += 1
|
178
202
|
end
|
179
203
|
end
|
180
204
|
|
205
|
+
outlist << encode('\') if last && new_missing_newline
|
206
|
+
|
181
207
|
s << outlist.join(encode("\n"))
|
208
|
+
|
209
|
+
s
|
182
210
|
end
|
183
211
|
private :unified_diff
|
184
212
|
|
185
|
-
def context_diff
|
213
|
+
def context_diff(last = false)
|
186
214
|
s = encode("***************\n")
|
187
|
-
s << encode("*** #{context_range(:old)} ****\n")
|
188
|
-
r = context_range(:new)
|
215
|
+
s << encode("*** #{context_range(:old, ',', last)} ****\n")
|
216
|
+
r = context_range(:new, ',', last)
|
217
|
+
|
218
|
+
if last
|
219
|
+
old_missing_newline = missing_last_newline?(@data_old)
|
220
|
+
new_missing_newline = missing_last_newline?(@data_new)
|
221
|
+
end
|
189
222
|
|
190
223
|
# Print out file 1 part for each block in context diff format if there
|
191
224
|
# are any blocks that remove items
|
192
225
|
lo, hi = @start_old, @end_old
|
193
226
|
removes = @blocks.reject { |e| e.remove.empty? }
|
194
|
-
|
195
|
-
|
227
|
+
|
228
|
+
unless removes.empty?
|
229
|
+
outlist = @data_old[lo..hi].map { |e| String.new("#{encode(' ')}#{e.chomp}") }
|
230
|
+
|
231
|
+
last_block = removes[-1]
|
196
232
|
|
197
233
|
removes.each do |block|
|
198
234
|
block.remove.each do |item|
|
199
|
-
outlist[item.position - lo]
|
235
|
+
outlist[item.position - lo][0, 1] = encode(block.op) # - or !
|
236
|
+
end
|
237
|
+
|
238
|
+
if last && block == last_block && old_missing_newline
|
239
|
+
outlist << encode('\')
|
200
240
|
end
|
201
241
|
end
|
202
|
-
|
242
|
+
|
243
|
+
s << outlist.join(encode("\n")) << encode("\n")
|
203
244
|
end
|
204
245
|
|
205
|
-
s << encode("
|
246
|
+
s << encode("--- #{r} ----\n")
|
206
247
|
lo, hi = @start_new, @end_new
|
207
248
|
inserts = @blocks.reject { |e| e.insert.empty? }
|
208
|
-
|
209
|
-
|
249
|
+
|
250
|
+
unless inserts.empty?
|
251
|
+
outlist = @data_new[lo..hi].map { |e| String.new("#{encode(' ')}#{e.chomp}") }
|
252
|
+
|
253
|
+
last_block = inserts[-1]
|
254
|
+
|
210
255
|
inserts.each do |block|
|
211
256
|
block.insert.each do |item|
|
212
|
-
outlist[item.position - lo]
|
257
|
+
outlist[item.position - lo][0, 1] = encode(block.op) # + or !
|
258
|
+
end
|
259
|
+
|
260
|
+
if last && block == last_block && new_missing_newline
|
261
|
+
outlist << encode('\')
|
213
262
|
end
|
214
263
|
end
|
215
|
-
s << outlist.join("\n")
|
264
|
+
s << outlist.join(encode("\n"))
|
216
265
|
end
|
266
|
+
|
217
267
|
s
|
218
268
|
end
|
219
269
|
private :context_diff
|
220
270
|
|
221
|
-
def ed_diff(format)
|
222
|
-
op_act = { '+' => 'a', '-' => 'd', '!' => 'c' }
|
271
|
+
def ed_diff(format, _last = false)
|
223
272
|
warn 'Expecting only one block in an old diff hunk!' if @blocks.size > 1
|
224
273
|
|
225
274
|
s =
|
226
275
|
if format == :reverse_ed
|
227
|
-
encode("#{
|
276
|
+
encode("#{ED_DIFF_OP_ACTION[@blocks[0].op]}#{context_range(:old, ',')}\n")
|
228
277
|
else
|
229
|
-
encode("#{context_range(:old, ' ')}#{
|
278
|
+
encode("#{context_range(:old, ' ')}#{ED_DIFF_OP_ACTION[@blocks[0].op]}\n")
|
230
279
|
end
|
231
280
|
|
232
281
|
unless @blocks[0].insert.empty?
|
233
|
-
@data_new[@start_new..@end_new].each do |e|
|
282
|
+
@data_new[@start_new..@end_new].each do |e|
|
283
|
+
s << e.chomp + encode("\n")
|
284
|
+
end
|
234
285
|
s << encode(".\n")
|
235
286
|
end
|
236
287
|
s
|
@@ -239,7 +290,7 @@ class Diff::LCS::Hunk
|
|
239
290
|
|
240
291
|
# Generate a range of item numbers to print. Only print 1 number if the
|
241
292
|
# range has only one item in it. Otherwise, it's 'start,end'
|
242
|
-
def context_range(mode, op =
|
293
|
+
def context_range(mode, op, last = false)
|
243
294
|
case mode
|
244
295
|
when :old
|
245
296
|
s, e = (@start_old + 1), (@end_old + 1)
|
@@ -247,6 +298,9 @@ class Diff::LCS::Hunk
|
|
247
298
|
s, e = (@start_new + 1), (@end_new + 1)
|
248
299
|
end
|
249
300
|
|
301
|
+
e -= 1 if last
|
302
|
+
e = 1 if e.zero?
|
303
|
+
|
250
304
|
s < e ? "#{s}#{op}#{e}" : e.to_s
|
251
305
|
end
|
252
306
|
private :context_range
|
@@ -254,7 +308,7 @@ class Diff::LCS::Hunk
|
|
254
308
|
# Generate a range of item numbers to print for unified diff. Print number
|
255
309
|
# where block starts, followed by number of lines in the block
|
256
310
|
# (don't print number of lines if it's 1)
|
257
|
-
def unified_range(mode)
|
311
|
+
def unified_range(mode, last)
|
258
312
|
case mode
|
259
313
|
when :old
|
260
314
|
s, e = (@start_old + 1), (@end_old + 1)
|
@@ -262,12 +316,25 @@ class Diff::LCS::Hunk
|
|
262
316
|
s, e = (@start_new + 1), (@end_new + 1)
|
263
317
|
end
|
264
318
|
|
265
|
-
length = e - s + 1
|
319
|
+
length = e - s + (last ? 0 : 1)
|
320
|
+
|
266
321
|
first = length < 2 ? e : s # "strange, but correct"
|
267
|
-
length
|
322
|
+
length <= 1 ? first.to_s : "#{first},#{length}"
|
268
323
|
end
|
269
324
|
private :unified_range
|
270
325
|
|
326
|
+
def missing_last_newline?(data)
|
327
|
+
newline = encode("\n")
|
328
|
+
|
329
|
+
if data[-2]
|
330
|
+
data[-2].end_with?(newline) && !data[-1].end_with?(newline)
|
331
|
+
elsif data[-1]
|
332
|
+
!data[-1].end_with?(newline)
|
333
|
+
else
|
334
|
+
true
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
271
338
|
if String.method_defined?(:encoding)
|
272
339
|
def encode(literal, target_encoding = @preferred_data_encoding)
|
273
340
|
literal.encode target_encoding
|
data/lib/diff/lcs/ldiff.rb
CHANGED
@@ -98,24 +98,19 @@ class << Diff::LCS::Ldiff
|
|
98
98
|
# items we've read from each file will differ by FLD (could be 0).
|
99
99
|
file_length_difference = 0
|
100
100
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
end
|
101
|
+
data_old = IO.read(file_old)
|
102
|
+
data_new = IO.read(file_new)
|
103
|
+
|
104
|
+
# Test binary status
|
105
|
+
if @binary.nil?
|
106
|
+
old_txt = data_old[0, 4096].scan(/\0/).empty?
|
107
|
+
new_txt = data_new[0, 4096].scan(/\0/).empty?
|
108
|
+
@binary = !old_txt || !new_txt
|
109
|
+
end
|
111
110
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
116
|
-
else
|
117
|
-
data_old = IO.readlines(file_old).map { |e| e.chomp }
|
118
|
-
data_new = IO.readlines(file_new).map { |e| e.chomp }
|
111
|
+
unless @binary
|
112
|
+
data_old = data_old.lines.to_a
|
113
|
+
data_new = data_new.lines.to_a
|
119
114
|
end
|
120
115
|
|
121
116
|
# diff yields lots of pieces, each of which is basically a Block object
|
@@ -150,20 +145,21 @@ class << Diff::LCS::Ldiff
|
|
150
145
|
end
|
151
146
|
|
152
147
|
diffs.each do |piece|
|
153
|
-
begin
|
148
|
+
begin # rubocop:disable Style/RedundantBegin
|
154
149
|
hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, @lines, file_length_difference)
|
155
150
|
file_length_difference = hunk.file_length_difference
|
156
151
|
|
157
152
|
next unless oldhunk
|
158
153
|
next if @lines.positive? and hunk.merge(oldhunk)
|
159
154
|
|
160
|
-
output << oldhunk.diff(@format)
|
155
|
+
output << oldhunk.diff(@format)
|
156
|
+
output << "\n" if @format == :unified
|
161
157
|
ensure
|
162
158
|
oldhunk = hunk
|
163
159
|
end
|
164
160
|
end
|
165
161
|
|
166
|
-
last = oldhunk.diff(@format)
|
162
|
+
last = oldhunk.diff(@format, true)
|
167
163
|
last << "\n" if last.respond_to?(:end_with?) && !last.end_with?("\n")
|
168
164
|
|
169
165
|
output << last
|
@@ -1,5 +1,5 @@
|
|
1
|
-
*** spec/fixtures/aX
|
2
|
-
--- spec/fixtures/bXaX
|
1
|
+
*** spec/fixtures/aX 2020-06-23 11:15:32.000000000 -0400
|
2
|
+
--- spec/fixtures/bXaX 2020-06-23 11:15:32.000000000 -0400
|
3
3
|
***************
|
4
4
|
*** 1 ****
|
5
5
|
! aX
|
data/spec/hunk_spec.rb
CHANGED
@@ -6,28 +6,39 @@ if String.method_defined?(:encoding)
|
|
6
6
|
require 'diff/lcs/hunk'
|
7
7
|
|
8
8
|
describe Diff::LCS::Hunk do
|
9
|
-
let(:old_data) { ['Tu
|
10
|
-
let(:new_data) { ['Tu
|
9
|
+
let(:old_data) { ['Tu a un carté avec {count} itéms'.encode('UTF-16LE')] }
|
10
|
+
let(:new_data) { ['Tu a un carte avec {count} items'.encode('UTF-16LE')] }
|
11
11
|
let(:pieces) { Diff::LCS.diff old_data, new_data }
|
12
12
|
let(:hunk) { Diff::LCS::Hunk.new(old_data, new_data, pieces[0], 3, 0) }
|
13
13
|
|
14
14
|
it 'produces a unified diff from the two pieces' do
|
15
15
|
expected = <<-EXPECTED.gsub(/^\s+/, '').encode('UTF-16LE').chomp
|
16
16
|
@@ -1 +1 @@
|
17
|
-
-Tu
|
18
|
-
+Tu
|
17
|
+
-Tu a un carté avec {count} itéms
|
18
|
+
+Tu a un carte avec {count} items
|
19
19
|
EXPECTED
|
20
20
|
|
21
21
|
expect(hunk.diff(:unified)).to eq(expected)
|
22
22
|
end
|
23
23
|
|
24
|
+
it 'produces a unified diff from the two pieces (last entry)' do
|
25
|
+
expected = <<-EXPECTED.gsub(/^\s+/, '').encode('UTF-16LE').chomp
|
26
|
+
@@ -1 +1 @@
|
27
|
+
-Tu a un carté avec {count} itéms
|
28
|
+
+Tu a un carte avec {count} items
|
29
|
+
\
|
30
|
+
EXPECTED
|
31
|
+
|
32
|
+
expect(hunk.diff(:unified, true)).to eq(expected)
|
33
|
+
end
|
34
|
+
|
24
35
|
it 'produces a context diff from the two pieces' do
|
25
36
|
expected = <<-EXPECTED.gsub(/^\s+/, '').encode('UTF-16LE').chomp
|
26
37
|
***************
|
27
38
|
*** 1 ****
|
28
|
-
! Tu
|
39
|
+
! Tu a un carté avec {count} itéms
|
29
40
|
--- 1 ----
|
30
|
-
! Tu
|
41
|
+
! Tu a un carte avec {count} items
|
31
42
|
EXPECTED
|
32
43
|
|
33
44
|
expect(hunk.diff(:context)).to eq(expected)
|
@@ -36,9 +47,9 @@ if String.method_defined?(:encoding)
|
|
36
47
|
it 'produces an old diff from the two pieces' do
|
37
48
|
expected = <<-EXPECTED.gsub(/^ +/, '').encode('UTF-16LE').chomp
|
38
49
|
1c1
|
39
|
-
< Tu
|
50
|
+
< Tu a un carté avec {count} itéms
|
40
51
|
---
|
41
|
-
> Tu
|
52
|
+
> Tu a un carte avec {count} items
|
42
53
|
|
43
54
|
EXPECTED
|
44
55
|
|
@@ -48,7 +59,7 @@ if String.method_defined?(:encoding)
|
|
48
59
|
it 'produces a reverse ed diff from the two pieces' do
|
49
60
|
expected = <<-EXPECTED.gsub(/^ +/, '').encode('UTF-16LE').chomp
|
50
61
|
c1
|
51
|
-
Tu
|
62
|
+
Tu a un carte avec {count} items
|
52
63
|
.
|
53
64
|
|
54
65
|
EXPECTED
|
@@ -62,7 +73,7 @@ if String.method_defined?(:encoding)
|
|
62
73
|
it 'produces a unified diff' do
|
63
74
|
expected = <<-EXPECTED.gsub(/^\s+/, '').encode('UTF-16LE').chomp
|
64
75
|
@@ -1 +1,2 @@
|
65
|
-
+Tu
|
76
|
+
+Tu a un carte avec {count} items
|
66
77
|
EXPECTED
|
67
78
|
|
68
79
|
expect(hunk.diff(:unified)).to eq(expected)
|
data/spec/issues_spec.rb
CHANGED
@@ -56,17 +56,17 @@ describe 'Diff::LCS Issues' do
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
describe
|
59
|
+
describe 'issue #57' do
|
60
60
|
it 'should fail with a correct error' do
|
61
61
|
expect {
|
62
|
-
actual = {:category=>
|
63
|
-
expected = {:category=>
|
62
|
+
actual = { :category => 'app.rack.request' }
|
63
|
+
expected = { :category => 'rack.middleware', :title => 'Anonymous Middleware' }
|
64
64
|
expect(actual).to eq(expected)
|
65
65
|
}.to raise_error(RSpec::Expectations::ExpectationNotMetError)
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
describe
|
69
|
+
describe 'issue #60' do
|
70
70
|
it 'should produce unified output with correct context' do
|
71
71
|
old_data = <<-DATA_OLD.strip.split("\n").map(&:chomp)
|
72
72
|
{
|
@@ -95,4 +95,60 @@ describe 'Diff::LCS Issues' do
|
|
95
95
|
EXPECTED
|
96
96
|
end
|
97
97
|
end
|
98
|
+
|
99
|
+
describe 'issue #65' do
|
100
|
+
def diff_lines(old_lines, new_lines)
|
101
|
+
file_length_difference = 0
|
102
|
+
previous_hunk = nil
|
103
|
+
output = []
|
104
|
+
|
105
|
+
Diff::LCS.diff(old_lines, new_lines).each do |piece|
|
106
|
+
hunk = Diff::LCS::Hunk.new(old_lines, new_lines, piece, 3, file_length_difference)
|
107
|
+
file_length_difference = hunk.file_length_difference
|
108
|
+
maybe_contiguous_hunks = (previous_hunk.nil? || hunk.merge(previous_hunk))
|
109
|
+
|
110
|
+
output << "#{previous_hunk.diff(:unified)}\n" unless maybe_contiguous_hunks
|
111
|
+
|
112
|
+
previous_hunk = hunk
|
113
|
+
end
|
114
|
+
output << "#{previous_hunk.diff(:unified, true)}\n" unless previous_hunk.nil?
|
115
|
+
output.join
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should not misplace the new chunk' do
|
119
|
+
old_data = [
|
120
|
+
'recipe[a::default]', 'recipe[b::default]', 'recipe[c::default]',
|
121
|
+
'recipe[d::default]', 'recipe[e::default]', 'recipe[f::default]',
|
122
|
+
'recipe[g::default]', 'recipe[h::default]', 'recipe[i::default]',
|
123
|
+
'recipe[j::default]', 'recipe[k::default]', 'recipe[l::default]',
|
124
|
+
'recipe[m::default]', 'recipe[n::default]'
|
125
|
+
]
|
126
|
+
|
127
|
+
new_data = [
|
128
|
+
'recipe[a::default]', 'recipe[c::default]', 'recipe[d::default]',
|
129
|
+
'recipe[e::default]', 'recipe[f::default]', 'recipe[g::default]',
|
130
|
+
'recipe[h::default]', 'recipe[i::default]', 'recipe[j::default]',
|
131
|
+
'recipe[k::default]', 'recipe[l::default]', 'recipe[m::default]',
|
132
|
+
'recipe[n::default]', 'recipe[o::new]', 'recipe[p::new]',
|
133
|
+
'recipe[q::new]', 'recipe[r::new]'
|
134
|
+
]
|
135
|
+
|
136
|
+
expect(diff_lines(old_data, new_data)).to eq(<<-EODIFF)
|
137
|
+
@@ -1,5 +1,4 @@
|
138
|
+
recipe[a::default]
|
139
|
+
-recipe[b::default]
|
140
|
+
recipe[c::default]
|
141
|
+
recipe[d::default]
|
142
|
+
recipe[e::default]
|
143
|
+
@@ -12,3 +11,7 @@
|
144
|
+
recipe[l::default]
|
145
|
+
recipe[m::default]
|
146
|
+
recipe[n::default]
|
147
|
+
+recipe[o::new]
|
148
|
+
+recipe[p::new]
|
149
|
+
+recipe[q::new]
|
150
|
+
+recipe[r::new]
|
151
|
+
EODIFF
|
152
|
+
end
|
153
|
+
end
|
98
154
|
end
|
data/spec/ldiff_spec.rb
CHANGED
@@ -5,40 +5,39 @@ require 'spec_helper'
|
|
5
5
|
RSpec.describe 'bin/ldiff' do
|
6
6
|
include CaptureSubprocessIO
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
fixtures = [
|
9
|
+
{ :name => 'output.diff', :left => 'aX', :right => 'bXaX' },
|
10
|
+
{ :name => 'output.diff.chef', :left => 'old-chef', :right => 'new-chef' },
|
11
|
+
{ :name => 'output.diff.chef2', :left => 'old-chef2', :right => 'new-chef2' }
|
12
|
+
].product([nil, '-e', '-f', '-c', '-u']).map { |(fixture, flag)|
|
13
|
+
fixture = fixture.dup
|
14
|
+
fixture[:flag] = flag
|
15
|
+
fixture
|
16
|
+
}
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
expect(run_ldiff('-c')).to eq(output_diff_c)
|
25
|
-
end
|
18
|
+
def self.test_ldiff(fixture)
|
19
|
+
desc = [
|
20
|
+
fixture[:flag],
|
21
|
+
"spec/fixtures/#{fixture[:left]}",
|
22
|
+
"spec/fixtures/#{fixture[:right]}",
|
23
|
+
'#',
|
24
|
+
'=>',
|
25
|
+
"spec/fixtures/ldiff/#{fixture[:name]}#{fixture[:flag]}"
|
26
|
+
].join(' ')
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
specify do
|
32
|
-
expect(run_ldiff('-f')).to eq(output_diff_f)
|
28
|
+
it desc do
|
29
|
+
expect(run_ldiff(fixture)).to eq(read_fixture(fixture))
|
30
|
+
end
|
33
31
|
end
|
34
32
|
|
35
|
-
|
36
|
-
|
33
|
+
fixtures.each do |fixture|
|
34
|
+
test_ldiff(fixture)
|
37
35
|
end
|
38
36
|
|
39
|
-
def read_fixture(
|
40
|
-
|
41
|
-
|
37
|
+
def read_fixture(options)
|
38
|
+
fixture = options.fetch(:name)
|
39
|
+
flag = options.fetch(:flag)
|
40
|
+
name = "spec/fixtures/ldiff/#{fixture}#{flag}"
|
42
41
|
data = IO.__send__(IO.respond_to?(:binread) ? :binread : :read, name)
|
43
42
|
clean_data(data, flag)
|
44
43
|
end
|
@@ -68,13 +67,15 @@ RSpec.describe 'bin/ldiff' do
|
|
68
67
|
\s*
|
69
68
|
(?:[-+]\d{4}|Z)
|
70
69
|
}x,
|
71
|
-
'*** spec/fixtures/\1 0000-00-00
|
70
|
+
'*** spec/fixtures/\1 0000-00-00 :00 =>:00 =>00.000000000 -0000'
|
72
71
|
)
|
73
72
|
end
|
74
73
|
|
75
|
-
def run_ldiff(
|
76
|
-
|
77
|
-
|
74
|
+
def run_ldiff(options)
|
75
|
+
flag = options.fetch(:flag)
|
76
|
+
left = options.fetch(:left)
|
77
|
+
right = options.fetch(:right)
|
78
|
+
|
78
79
|
stdout, stderr = capture_subprocess_io do
|
79
80
|
system("ruby -Ilib bin/ldiff #{flag} spec/fixtures/#{left} spec/fixtures/#{right}")
|
80
81
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -5,7 +5,6 @@ require 'pathname'
|
|
5
5
|
|
6
6
|
require 'psych' if RUBY_VERSION >= '1.9'
|
7
7
|
|
8
|
-
|
9
8
|
if ENV['COVERAGE']
|
10
9
|
require 'simplecov'
|
11
10
|
|
@@ -45,30 +44,31 @@ module CaptureSubprocessIO
|
|
45
44
|
end
|
46
45
|
|
47
46
|
def capture_subprocess_io
|
48
|
-
_synchronize
|
49
|
-
|
50
|
-
|
47
|
+
_synchronize { _capture_subprocess_io { yield } }
|
48
|
+
end
|
49
|
+
|
50
|
+
def _capture_subprocess_io
|
51
|
+
require 'tempfile'
|
51
52
|
|
52
|
-
|
53
|
+
captured_stdout, captured_stderr = Tempfile.new('out'), Tempfile.new('err')
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
orig_stdout, orig_stderr = $stdout.dup, $stderr.dup
|
56
|
+
$stdout.reopen captured_stdout
|
57
|
+
$stderr.reopen captured_stderr
|
57
58
|
|
58
|
-
|
59
|
+
yield
|
59
60
|
|
60
|
-
|
61
|
-
|
61
|
+
$stdout.rewind
|
62
|
+
$stderr.rewind
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
end
|
64
|
+
[captured_stdout.read, captured_stderr.read]
|
65
|
+
ensure
|
66
|
+
captured_stdout.unlink
|
67
|
+
captured_stderr.unlink
|
68
|
+
$stdout.reopen orig_stdout
|
69
|
+
$stderr.reopen orig_stderr
|
71
70
|
end
|
71
|
+
private :_capture_subprocess_io
|
72
72
|
end
|
73
73
|
|
74
74
|
require 'diff-lcs'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diff-lcs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Austin Ziegler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hoe-doofus
|