Hello community, here is the log from the commit of package rubygem-diff-lcs for openSUSE:Factory checked in at 2020-07-16 12:10:45 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-diff-lcs (Old) and /work/SRC/openSUSE:Factory/.rubygem-diff-lcs.new.3592 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-diff-lcs" Thu Jul 16 12:10:45 2020 rev:8 rq:820739 version:1.4.4 Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-diff-lcs/rubygem-diff-lcs.changes 2020-06-29 21:15:56.117332854 +0200 +++ /work/SRC/openSUSE:Factory/.rubygem-diff-lcs.new.3592/rubygem-diff-lcs.changes 2020-07-16 12:11:36.922549941 +0200 @@ -1,0 +2,56 @@ +Mon Jul 13 17:24:56 UTC 2020 - Manuel Schnitzer <mschnit...@suse.com> + +- updated to version 1.4.4 + + ## 1.4.4 / 2020-07-01 + + - Fixed an issue reported by Jun Aruga in the Diff::LCS::Ldiff binary text + detection. [#44][] + - Fixed a theoretical issue reported by Jun Aruga in Diff::LCS::Hunk to raise + a more useful exception. [#43][] + - Added documentation that should address custom object issues as reported in + [#35][]. + + - Fixed more diff errors, in part reported in [#65][]. + + - The use of `Numeric#abs` is incorrect in `Diff::LCS::Block#diff_size`. + The diff size _must_ be accurate for correct change placement. + - When selecting @max_diff_size in Diff::LCS::Hunk, choose it based on + `block.diff_size.abs`. + - Made a number of changes that will, unfortunately, increase allocations + at the cost of being safe with frozen strings. + - Add some knowledge that when `Diff::LCS::Hunk#diff` is called, that we + are processing the _last_ hunk, so some changes will be made to how the + output is generated. + + - `old`, `ed`, and `reverse_ed` formats have no differences. + - `unified` format will report `\ No newline at end of file` given the + correct conditions, at most once. Unified range reporting also + differs for the last hunk such that the `length` of the range is + reduced by one. + - `context` format will report `\No newline at end of file` given the + correct conditions, up to once per "file". Context range reporting also + differs for the last hunk such that the `end` part of the range is + reduced by one to a minimum of one. + + - Added a bunch more tests for the cases above, and fixed `hunk_spec.rb` so + that the phrase being compared isn't nonsense French. + + - Updated formatting. + - Added a Rake task to assist with manual testing on Ruby 1.8. + + ## 1.4.3 / 2020-06-29 + + - Fixed several issues with the 1.4 on Rubies older than 2.0. Some of this was + providing useful shim functions to Hoe 3.x (which dropped these older + Rubies a while ago). Specifically: + + - Removed Array#lazy from a method in Diff::LCS::Hunk. + - Changed some unit tests to use old-style Symbol-keyed hashes. + - Changed some unit test helper functions to no longer use keyword + parameters, but only a trailing options hash. + - Made the use of `psych` dependent on `RUBY_VERSION >= 1.9`. + + Resolves [#63][]. + +------------------------------------------------------------------- Old: ---- diff-lcs-1.4.2.gem New: ---- diff-lcs-1.4.4.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-diff-lcs.spec ++++++ --- /var/tmp/diff_new_pack.7iqAl6/_old 2020-07-16 12:11:39.210552254 +0200 +++ /var/tmp/diff_new_pack.7iqAl6/_new 2020-07-16 12:11:39.214552259 +0200 @@ -24,7 +24,7 @@ # Name: rubygem-diff-lcs -Version: 1.4.2 +Version: 1.4.4 Release: 0 %define mod_name diff-lcs %define mod_full_name %{mod_name}-%{version} @@ -49,14 +49,14 @@ Diff::LCS computes the difference between two Enumerable sequences using the McIlroy-Hunt longest common subsequence (LCS) algorithm. It includes utilities to create a simple HTML diff output format and a standard diff-like tool. -This is release 1.4, providing a simple extension that allows for -Diff::LCS::Change objects to be treated implicitly as arrays. Ruby versions -below 2.5 are soft-deprecated. -This means that older versions are no longer part of the CI test suite. If any -changes have been introduced that break those versions, bug reports and -patches -will be accepted, but it will be up to the reporter to verify any fixes prior -to release. A future release will completely break compatibility. +This is release 1.4.3, providing a simple extension that allows for +Diff::LCS::Change objects to be treated implicitly as arrays and fixes a +number of formatting issues. +Ruby versions below 2.5 are soft-deprecated, which means that older versions +are no longer part of the CI test suite. If any changes have been introduced +that break those versions, bug reports and patches will be accepted, but it +will be up to the reporter to verify any fixes prior to release. The next +major release will completely break compatibility. %prep %gem_unpack ++++++ diff-lcs-1.4.2.gem -> diff-lcs-1.4.4.gem ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Contributing.md new/Contributing.md --- old/Contributing.md 2020-06-24 05:19:27.000000000 +0200 +++ new/Contributing.md 2020-07-01 20:29:57.000000000 +0200 @@ -1,32 +1,35 @@ ## Contributing -I value any contribution to Diff::LCS you can provide: a bug report, a feature -request, or code contributions. Code contributions to Diff::LCS are especially -<del>welcome</del>encouraged. Because Diff::LCS is a complex codebase, there -are a few guidelines: - -* Code changes *will not* be accepted without tests. The test suite is - written with [RSpec][]. -* Match my coding style. -* Use a thoughtfully-named topic branch that contains your change. Rebase - your commits into logical chunks as necessary. -* Use [quality commit messages][]. -* Do not change the version number; when your patch is accepted and a release - is made, the version will be updated at that point. -* Submit a GitHub pull request with your changes. -* New or changed behaviours require appropriate documentation. +I value any contribution to Diff::LCS you can provide: a bug report, a +feature request, or code contributions. Code contributions to Diff::LCS are +especially <del>welcome</del>encouraged. Because Diff::LCS is a complex +codebase, there are a few guidelines: + +- Code changes _will not_ be accepted without tests. The test suite is + written with [RSpec][]. +- Match my coding style. +- Use a thoughtfully-named topic branch that contains your change. Rebase + your commits into logical chunks as necessary. +- Use [quality commit messages][]. +- Do not change the version number; when your patch is accepted and a release + is made, the version will be updated at that point. +- Submit a GitHub pull request with your changes. +- New or changed behaviours require appropriate documentation. ### Test Dependencies -Diff::LCS uses Ryan Davis’s [Hoe][] to manage the release process, and it adds -a number of rake tasks. You will mostly be interested in: +Diff::LCS uses Ryan Davis’s [Hoe][] to manage the release process, and it +adds a number of rake tasks. You will mostly be interested in: - $ rake +```sh +$ rake +``` which runs the tests the same way that: - $ rake spec - $ rake travis +```sh +$ rake spec +``` will do. @@ -34,51 +37,82 @@ provided a Gemfile pointing to the (generated) `diff-lcs.gemspec` file. This will permit you to do: - $ bundle install +```sh +$ bundle install +``` to get the development dependencies. If you aleady have `hoe` installed, you can accomplish the same thing with: - $ rake newb +```sh +$ rake newb +``` This task will install any missing dependencies, run the tests/specs, and generate the RDoc. You can run tests with code coverage analysis by running: - $ rake spec:coverage +```sh +$ rake spec:coverage +``` ### Workflow Here's the most direct way to get your work merged into the project: -* Fork the project. -* Clone down your fork (`git clone git://github.com/<username>/diff-lcs.git`). -* Create a topic branch to contain your change (`git checkout -b - my_awesome_feature`). -* Hack away, add tests. Not necessarily in that order. -* Make sure everything still passes by running `rake`. -* If necessary, rebase your commits into logical chunks, without errors. -* Push the branch up (`git push origin my_awesome_feature`). -* Create a pull request against halostatue/diff-lcs and describe what your - change does and the why you think it should be merged. +- Fork the project. +- Clone down your fork (`git clone git://github.com/<username>/diff-lcs.git`). +- Create a topic branch to contain your change (`git checkout -b my_awesome_feature`). +- Hack away, add tests. Not necessarily in that order. +- Make sure everything still passes by running `rake`. +- If necessary, rebase your commits into logical chunks, without errors. +- Push the branch up (`git push origin my_awesome_feature`). +- Create a pull request against halostatue/diff-lcs and describe what your + change does and the why you think it should be merged. ### Contributors -* Austin Ziegler created Diff::LCS. +- Austin Ziegler created Diff::LCS. -Thanks to everyone else who has contributed to Diff::LCS: +Thanks to everyone else who has contributed code or bug reports to Diff::LCS: -* Kenichi Kamiya -* Michael Granger -* Vít Ondruch -* Jon Rowe -* Koichi Ito -* Josef Strzibny -* Josh Bronson -* Mark Friedgan -* Akinori MUSHA +- @ginriki +- @joshbronson +- @kevinmook +- @mckaz +- Akinori Musha +- Artem Ignatyev +- Brandon Fish +- Camille Drapier +- Cédric Boutillier +- Gregg Kellogg +- Jagdeep Singh +- Jason Gladish +- Jon Rowe +- Josef Strzibny +- Josep (@apuratepp) +- Josh Bronson +- Jun Aruga +- Kenichi Kamiya +- Kensuke Nagae +- Kevin Ansfield +- Koichi Ito +- Mark Friedgan +- Michael Granger +- Myron Marston +- Nicolas Leger +- Oleg Orlov +- Paul Kunysch +- Pete Higgins +- Peter Wagenet +- Philippe Lafoucrière +- Ryan Lovelett +- Scott Steele +- Simon Courtois +- Tomas Jura +- Vít Ondruch -[Rspec]: http://rspec.info/documentation/ +[rspec]: http://rspec.info/documentation/ [quality commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html -[Hoe]: https://github.com/seattlerb/hoe +[hoe]: https://github.com/seattlerb/hoe diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/History.md new/History.md --- old/History.md 2020-06-24 05:19:27.000000000 +0200 +++ new/History.md 2020-07-01 20:29:57.000000000 +0200 @@ -1,5 +1,56 @@ # History +## 1.4.4 / 2020-07-01 + +- Fixed an issue reported by Jun Aruga in the Diff::LCS::Ldiff binary text + detection. [#44][] +- Fixed a theoretical issue reported by Jun Aruga in Diff::LCS::Hunk to raise + a more useful exception. [#43][] +- Added documentation that should address custom object issues as reported in + [#35][]. + +- Fixed more diff errors, in part reported in [#65][]. + + - The use of `Numeric#abs` is incorrect in `Diff::LCS::Block#diff_size`. + The diff size _must_ be accurate for correct change placement. + - When selecting @max_diff_size in Diff::LCS::Hunk, choose it based on + `block.diff_size.abs`. + - Made a number of changes that will, unfortunately, increase allocations + at the cost of being safe with frozen strings. + - Add some knowledge that when `Diff::LCS::Hunk#diff` is called, that we + are processing the _last_ hunk, so some changes will be made to how the + output is generated. + + - `old`, `ed`, and `reverse_ed` formats have no differences. + - `unified` format will report `\ No newline at end of file` given the + correct conditions, at most once. Unified range reporting also + differs for the last hunk such that the `length` of the range is + reduced by one. + - `context` format will report `\No newline at end of file` given the + correct conditions, up to once per "file". Context range reporting also + differs for the last hunk such that the `end` part of the range is + reduced by one to a minimum of one. + +- Added a bunch more tests for the cases above, and fixed `hunk_spec.rb` so + that the phrase being compared isn't nonsense French. + +- Updated formatting. +- Added a Rake task to assist with manual testing on Ruby 1.8. + +## 1.4.3 / 2020-06-29 + +- Fixed several issues with the 1.4 on Rubies older than 2.0. Some of this was + providing useful shim functions to Hoe 3.x (which dropped these older + Rubies a while ago). Specifically: + + - Removed Array#lazy from a method in Diff::LCS::Hunk. + - Changed some unit tests to use old-style Symbol-keyed hashes. + - Changed some unit test helper functions to no longer use keyword + parameters, but only a trailing options hash. + - Made the use of `psych` dependent on `RUBY_VERSION >= 1.9`. + + Resolves [#63][]. + ## 1.4.2 / 2020-06-23 - Camille Drapier fixed a small issue with RuboCop configuration. [#59][] @@ -249,8 +300,11 @@ [#29]: https://github.com/halostatue/diff-lcs/pull/29 [#33]: https://github.com/halostatue/diff-lcs/issues/33 [#34]: https://github.com/halostatue/diff-lcs/pull/34 +[#35]: https://github.com/halostatue/diff-lcs/issues/35 [#36]: https://github.com/halostatue/diff-lcs/pull/36 [#38]: https://github.com/halostatue/diff-lcs/issues/38 +[#43]: https://github.com/halostatue/diff-lcs/issues/43 +[#44]: https://github.com/halostatue/diff-lcs/issues/44 [#47]: https://github.com/halostatue/diff-lcs/pull/47 [#48]: https://github.com/halostatue/diff-lcs/issues/48 [#49]: https://github.com/halostatue/diff-lcs/pull/49 @@ -261,3 +315,5 @@ [#59]: https://github.com/halostatue/diff-lcs/pull/59 [#60]: https://github.com/halostatue/diff-lcs/issues/60 [#61]: https://github.com/halostatue/diff-lcs/pull/61 +[#63]: https://github.com/halostatue/diff-lcs/issues/63 +[#65]: https://github.com/halostatue/diff-lcs/issues/65 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/README.rdoc new/README.rdoc --- old/README.rdoc 2020-06-24 05:19:27.000000000 +0200 +++ new/README.rdoc 2020-07-01 20:29:57.000000000 +0200 @@ -12,14 +12,15 @@ McIlroy-Hunt longest common subsequence (LCS) algorithm. It includes utilities to create a simple HTML diff output format and a standard diff-like tool. -This is release 1.4, providing a simple extension that allows for -Diff::LCS::Change objects to be treated implicitly as arrays. Ruby versions -below 2.5 are soft-deprecated. +This is release 1.4.3, providing a simple extension that allows for +Diff::LCS::Change objects to be treated implicitly as arrays and fixes a +number of formatting issues. -This means that older versions are no longer part of the CI test suite. If any -changes have been introduced that break those versions, bug reports and patches -will be accepted, but it will be up to the reporter to verify any fixes prior -to release. A future release will completely break compatibility. +Ruby versions below 2.5 are soft-deprecated, which means that older versions +are no longer part of the CI test suite. If any changes have been introduced +that break those versions, bug reports and patches will be accepted, but it +will be up to the reporter to verify any fixes prior to release. The next +major release will completely break compatibility. == Synopsis diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Rakefile new/Rakefile --- old/Rakefile 2020-06-24 05:19:27.000000000 +0200 +++ new/Rakefile 2020-07-01 20:29:57.000000000 +0200 @@ -6,10 +6,28 @@ Hoe.plugin :bundler Hoe.plugin :doofus -Hoe.plugin :email unless ENV['CI'] or ENV['TRAVIS'] Hoe.plugin :gemspec2 Hoe.plugin :git -Hoe.plugin :travis + +if RUBY_VERSION < '1.9' + class Array #:nodoc: + def to_h + Hash[*flatten(1)] + end + end + + class Gem::Specification #:nodoc: + def metadata=(*); end + + def default_value(*); end + end + + class Object #:nodoc: + def caller_locations(*) + [] + end + end +end _spec = Hoe.spec 'diff-lcs' do developer('Austin Ziegler', 'halosta...@gmail.com') @@ -38,3 +56,19 @@ end end end + +task :ruby18 do + puts <<-MESSAGE +You are starting a barebones Ruby 1.8 docker environment. You will need to +do the following: + +- mv Gemfile.lock{,.v2} +- gem install bundler --version 1.17.2 --no-ri --no-rdoc +- ruby -S bundle +- rake + +Don't forget to restore your Gemfile.lock after testing. + + MESSAGE + sh "docker run -it --rm -v #{Dir.pwd}:/root/diff-lcs bellbind/docker-ruby18-rails2 bash -l" +end Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/diff/lcs/block.rb new/lib/diff/lcs/block.rb --- old/lib/diff/lcs/block.rb 2020-06-24 05:19:27.000000000 +0200 +++ new/lib/diff/lcs/block.rb 2020-07-01 20:29:57.000000000 +0200 @@ -19,7 +19,7 @@ end def diff_size - (@insert.size - @remove.size).abs + @insert.size - @remove.size end def op diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/diff/lcs/hunk.rb new/lib/diff/lcs/hunk.rb --- old/lib/diff/lcs/hunk.rb 2020-06-24 05:19:27.000000000 +0200 +++ new/lib/diff/lcs/hunk.rb 2020-07-01 20:29:57.000000000 +0200 @@ -6,26 +6,38 @@ # each block. (So if we're not using context, every hunk will contain one # block.) Used in the diff program (bin/ldiff). class Diff::LCS::Hunk + OLD_DIFF_OP_ACTION = { '+' => 'a', '-' => 'd', '!' => 'c' }.freeze #:nodoc: + ED_DIFF_OP_ACTION = { '+' => 'a', '-' => 'd', '!' => 'c' }.freeze #:nodoc: + + private_constant :OLD_DIFF_OP_ACTION, :ED_DIFF_OP_ACTION if respond_to?(:private_constant) + # Create a hunk using references to both the old and new data, as well as the # piece of data. def initialize(data_old, data_new, piece, flag_context, file_length_difference) # At first, a hunk will have just one Block in it @blocks = [Diff::LCS::Block.new(piece)] + + if @blocks[0].remove.empty? && @blocks[0].insert.empty? + fail "Cannot build a hunk from #{piece.inspect}; has no add or remove actions" + end + if String.method_defined?(:encoding) @preferred_data_encoding = data_old.fetch(0, data_new.fetch(0, '')).encoding end + @data_old = data_old @data_new = data_new before = after = file_length_difference after += @blocks[0].diff_size @file_length_difference = after # The caller must get this manually - @max_diff_size = @blocks.lazy.map { |e| e.diff_size }.max + @max_diff_size = @blocks.map { |e| e.diff_size.abs }.max + # Save the start & end of each array. If the array doesn't exist (e.g., - # we're only adding items in this block), then figure out the line - # number based on the line number of the other file and the current - # difference in file lengths. + # we're only adding items in this block), then figure out the line number + # based on the line number of the other file and the current difference in + # file lengths. if @blocks[0].remove.empty? a1 = a2 = nil else @@ -55,7 +67,7 @@ # Change the "start" and "end" fields to note that context should be added # to this hunk. - attr_accessor :flag_context + attr_accessor :flag_context # rubocop:disable Layout/EmptyLinesAroundAttributeAccessor undef :flag_context= def flag_context=(context) #:nodoc: # rubocop:disable Lint/DuplicateMethods return if context.nil? or context.zero? @@ -101,18 +113,18 @@ end # Returns a diff string based on a format. - def diff(format) + def diff(format, last = false) case format when :old - old_diff + old_diff(last) when :unified - unified_diff + unified_diff(last) when :context - context_diff + context_diff(last) when :ed self when :reverse_ed, :ed_finish - ed_diff(format) + ed_diff(format, last) else fail "Unknown diff format #{format}." end @@ -120,35 +132,34 @@ # Note that an old diff can't have any context. Therefore, we know that # there's only one block in the hunk. - def old_diff + def old_diff(_last = false) warn 'Expecting only one block in an old diff hunk!' if @blocks.size > 1 - op_act = { '+' => 'a', '-' => 'd', '!' => 'c' } block = @blocks[0] # Calculate item number range. Old diff range is just like a context # diff range, except the ranges are on one line with the action between # them. - s = encode("#{context_range(:old)}#{op_act[block.op]}#{context_range(:new)}\n") + s = encode("#{context_range(:old, ',')}#{OLD_DIFF_OP_ACTION[block.op]}#{context_range(:new, ',')}\n") # If removing anything, just print out all the remove lines in the hunk # which is just all the remove lines in the block. unless block.remove.empty? - @data_old[@start_old..@end_old].each { |e| s << encode('< ') + e + encode("\n") } + @data_old[@start_old..@end_old].each { |e| s << encode('< ') + e.chomp + encode("\n") } end s << encode("---\n") if block.op == '!' unless block.insert.empty? - @data_new[@start_new..@end_new].each { |e| s << encode('> ') + e + encode("\n") } + @data_new[@start_new..@end_new].each { |e| s << encode('> ') + e.chomp + encode("\n") } end s end private :old_diff - def unified_diff + def unified_diff(last = false) # Calculate item number range. - s = encode("@@ -#{unified_range(:old)} +#{unified_range(:new)} @@\n") + s = encode("@@ -#{unified_range(:old, last)} +#{unified_range(:new, last)} @@\n") # Outlist starts containing the hunk of the old file. Removing an item # just means putting a '-' in front of it. Inserting an item requires @@ -161,7 +172,14 @@ # file -- don't take removed items into account. lo, hi, num_added, num_removed = @start_old, @end_old, 0, 0 - outlist = @data_old[lo..hi].map { |e| e.insert(0, encode(' ')) } + outlist = @data_old[lo..hi].map { |e| String.new("#{encode(' ')}#{e.chomp}") } + + last_block = blocks[-1] + + if last + old_missing_newline = missing_last_newline?(@data_old) + new_missing_newline = missing_last_newline?(@data_new) + end @blocks.each do |block| block.remove.each do |item| @@ -170,67 +188,100 @@ outlist[offset][0, 1] = encode(op) num_removed += 1 end + + if last && block == last_block && old_missing_newline && !new_missing_newline + outlist << encode('\\ No newline at end of file') + num_removed += 1 + end + block.insert.each do |item| op = item.action.to_s # + offset = item.position - @start_new + num_removed - outlist[offset, 0] = encode(op) + @data_new[item.position] + outlist[offset, 0] = encode(op) + @data_new[item.position].chomp num_added += 1 end end + outlist << encode('\\ No newline at end of file') if last && new_missing_newline + s << outlist.join(encode("\n")) + + s end private :unified_diff - def context_diff + def context_diff(last = false) s = encode("***************\n") - s << encode("*** #{context_range(:old)} ****\n") - r = context_range(:new) + s << encode("*** #{context_range(:old, ',', last)} ****\n") + r = context_range(:new, ',', last) + + if last + old_missing_newline = missing_last_newline?(@data_old) + new_missing_newline = missing_last_newline?(@data_new) + end # Print out file 1 part for each block in context diff format if there # are any blocks that remove items lo, hi = @start_old, @end_old removes = @blocks.reject { |e| e.remove.empty? } - if removes - outlist = @data_old[lo..hi].map { |e| e.insert(0, encode(' ')) } + + unless removes.empty? + outlist = @data_old[lo..hi].map { |e| String.new("#{encode(' ')}#{e.chomp}") } + + last_block = removes[-1] removes.each do |block| block.remove.each do |item| - outlist[item.position - lo].insert(0, encode(block.op)) # - or ! + outlist[item.position - lo][0, 1] = encode(block.op) # - or ! + end + + if last && block == last_block && old_missing_newline + outlist << encode('\\ No newline at end of file') end end - s << outlist.join("\n") + + s << outlist.join(encode("\n")) << encode("\n") end - s << encode("\n--- #{r} ----\n") + s << encode("--- #{r} ----\n") lo, hi = @start_new, @end_new inserts = @blocks.reject { |e| e.insert.empty? } - if inserts - outlist = @data_new[lo..hi].collect { |e| e.insert(0, encode(' ')) } + + unless inserts.empty? + outlist = @data_new[lo..hi].map { |e| String.new("#{encode(' ')}#{e.chomp}") } + + last_block = inserts[-1] + inserts.each do |block| block.insert.each do |item| - outlist[item.position - lo].insert(0, encode(block.op)) # - or ! + outlist[item.position - lo][0, 1] = encode(block.op) # + or ! + end + + if last && block == last_block && new_missing_newline + outlist << encode('\\ No newline at end of file') end end - s << outlist.join("\n") + s << outlist.join(encode("\n")) end + s end private :context_diff - def ed_diff(format) - op_act = { '+' => 'a', '-' => 'd', '!' => 'c' } + def ed_diff(format, _last = false) warn 'Expecting only one block in an old diff hunk!' if @blocks.size > 1 s = if format == :reverse_ed - encode("#{op_act[@blocks[0].op]}#{context_range(:old)}\n") + encode("#{ED_DIFF_OP_ACTION[@blocks[0].op]}#{context_range(:old, ',')}\n") else - encode("#{context_range(:old, ' ')}#{op_act[@blocks[0].op]}\n") + encode("#{context_range(:old, ' ')}#{ED_DIFF_OP_ACTION[@blocks[0].op]}\n") end unless @blocks[0].insert.empty? - @data_new[@start_new..@end_new].each do |e| s << e + encode("\n") end + @data_new[@start_new..@end_new].each do |e| + s << e.chomp + encode("\n") + end s << encode(".\n") end s @@ -239,7 +290,7 @@ # Generate a range of item numbers to print. Only print 1 number if the # range has only one item in it. Otherwise, it's 'start,end' - def context_range(mode, op = ',') # rubocop:disable Naming/UncommunicativeMethodParamName + def context_range(mode, op, last = false) case mode when :old s, e = (@start_old + 1), (@end_old + 1) @@ -247,6 +298,9 @@ s, e = (@start_new + 1), (@end_new + 1) end + e -= 1 if last + e = 1 if e.zero? + s < e ? "#{s}#{op}#{e}" : e.to_s end private :context_range @@ -254,7 +308,7 @@ # Generate a range of item numbers to print for unified diff. Print number # where block starts, followed by number of lines in the block # (don't print number of lines if it's 1) - def unified_range(mode) + def unified_range(mode, last) case mode when :old s, e = (@start_old + 1), (@end_old + 1) @@ -262,12 +316,25 @@ s, e = (@start_new + 1), (@end_new + 1) end - length = e - s + 1 + length = e - s + (last ? 0 : 1) + first = length < 2 ? e : s # "strange, but correct" - length == 1 ? first.to_s : "#{first},#{length}" + length <= 1 ? first.to_s : "#{first},#{length}" end private :unified_range + def missing_last_newline?(data) + newline = encode("\n") + + if data[-2] + data[-2].end_with?(newline) && !data[-1].end_with?(newline) + elsif data[-1] + !data[-1].end_with?(newline) + else + true + end + end + if String.method_defined?(:encoding) def encode(literal, target_encoding = @preferred_data_encoding) literal.encode target_encoding diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/diff/lcs/ldiff.rb new/lib/diff/lcs/ldiff.rb --- old/lib/diff/lcs/ldiff.rb 2020-06-24 05:19:27.000000000 +0200 +++ new/lib/diff/lcs/ldiff.rb 2020-07-01 20:29:57.000000000 +0200 @@ -98,24 +98,19 @@ # items we've read from each file will differ by FLD (could be 0). file_length_difference = 0 - if @binary.nil? or @binary - data_old = IO.read(file_old) - data_new = IO.read(file_new) - - # Test binary status - if @binary.nil? - old_txt = data_old[0, 4096].scan(/\0/).empty? - new_txt = data_new[0, 4096].scan(/\0/).empty? - @binary = !old_txt or !new_txt - end + data_old = IO.read(file_old) + data_new = IO.read(file_new) - unless @binary - data_old = data_old.split($/).map { |e| e.chomp } - data_new = data_new.split($/).map { |e| e.chomp } - end - else - data_old = IO.readlines(file_old).map { |e| e.chomp } - data_new = IO.readlines(file_new).map { |e| e.chomp } + # Test binary status + if @binary.nil? + old_txt = data_old[0, 4096].scan(/\0/).empty? + new_txt = data_new[0, 4096].scan(/\0/).empty? + @binary = !old_txt || !new_txt + end + + unless @binary + data_old = data_old.lines.to_a + data_new = data_new.lines.to_a end # diff yields lots of pieces, each of which is basically a Block object @@ -150,20 +145,21 @@ end diffs.each do |piece| - begin + begin # rubocop:disable Style/RedundantBegin hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, @lines, file_length_difference) file_length_difference = hunk.file_length_difference next unless oldhunk next if @lines.positive? and hunk.merge(oldhunk) - output << oldhunk.diff(@format) << "\n" + output << oldhunk.diff(@format) + output << "\n" if @format == :unified ensure oldhunk = hunk end end - last = oldhunk.diff(@format) + last = oldhunk.diff(@format, true) last << "\n" if last.respond_to?(:end_with?) && !last.end_with?("\n") output << last diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/diff/lcs.rb new/lib/diff/lcs.rb --- old/lib/diff/lcs.rb 2020-06-24 05:19:27.000000000 +0200 +++ new/lib/diff/lcs.rb 2020-07-01 20:29:57.000000000 +0200 @@ -49,7 +49,7 @@ # a x b y c z p d q # a b c a x b y c z module Diff::LCS - VERSION = '1.4.2' + VERSION = '1.4.4' end require 'diff/lcs/callbacks' @@ -60,6 +60,13 @@ # +self+ and +other+. See Diff::LCS#lcs. # # lcs = seq1.lcs(seq2) + # + # A note when using objects: Diff::LCS only works properly when each object + # can be used as a key in a Hash, which typically means that the objects must + # implement Object#eql? in a way that two identical values compare + # identically for key purposes. That is: + # + # O.new('a').eql?(O.new('a')) == true def lcs(other, &block) #:yields self[i] if there are matched subsequences: Diff::LCS.lcs(self, other, &block) end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 2020-06-24 05:19:27.000000000 +0200 +++ new/metadata 2020-07-01 20:29:57.000000000 +0200 @@ -1,14 +1,14 @@ --- !ruby/object:Gem::Specification name: diff-lcs version: !ruby/object:Gem::Version - version: 1.4.2 + version: 1.4.4 platform: ruby authors: - Austin Ziegler autorequire: bindir: bin cert_chain: [] -date: 2020-06-24 00:00:00.000000000 Z +date: 2020-07-01 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: hoe-doofus @@ -139,14 +139,15 @@ McIlroy-Hunt longest common subsequence (LCS) algorithm. It includes utilities to create a simple HTML diff output format and a standard diff-like tool. - This is release 1.4, providing a simple extension that allows for - Diff::LCS::Change objects to be treated implicitly as arrays. Ruby versions - below 2.5 are soft-deprecated. + This is release 1.4.3, providing a simple extension that allows for + Diff::LCS::Change objects to be treated implicitly as arrays and fixes a + number of formatting issues. - This means that older versions are no longer part of the CI test suite. If any - changes have been introduced that break those versions, bug reports and patches - will be accepted, but it will be up to the reporter to verify any fixes prior - to release. A future release will completely break compatibility. + Ruby versions below 2.5 are soft-deprecated, which means that older versions + are no longer part of the CI test suite. If any changes have been introduced + that break those versions, bug reports and patches will be accepted, but it + will be up to the reporter to verify any fixes prior to release. The next + major release will completely break compatibility. email: - halosta...@gmail.com executables: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec/fixtures/ldiff/output.diff-c new/spec/fixtures/ldiff/output.diff-c --- old/spec/fixtures/ldiff/output.diff-c 2020-06-24 05:19:27.000000000 +0200 +++ new/spec/fixtures/ldiff/output.diff-c 2020-07-01 20:29:57.000000000 +0200 @@ -1,5 +1,5 @@ -*** spec/fixtures/aX 2019-02-01 22:29:34.000000000 -0500 ---- spec/fixtures/bXaX 2019-02-01 22:29:43.000000000 -0500 +*** spec/fixtures/aX 2020-06-23 11:15:32.000000000 -0400 +--- spec/fixtures/bXaX 2020-06-23 11:15:32.000000000 -0400 *************** *** 1 **** ! aX diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec/fixtures/ldiff/output.diff-u new/spec/fixtures/ldiff/output.diff-u --- old/spec/fixtures/ldiff/output.diff-u 2020-06-24 05:19:27.000000000 +0200 +++ new/spec/fixtures/ldiff/output.diff-u 2020-07-01 20:29:57.000000000 +0200 @@ -1,5 +1,5 @@ ---- spec/fixtures/aX 2019-02-01 22:29:34.000000000 -0500 -+++ spec/fixtures/bXaX 2019-02-01 22:29:43.000000000 -0500 +--- spec/fixtures/aX 2020-06-23 11:15:32.000000000 -0400 ++++ spec/fixtures/bXaX 2020-06-23 11:15:32.000000000 -0400 @@ -1 +1 @@ -aX +bXaX diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec/hunk_spec.rb new/spec/hunk_spec.rb --- old/spec/hunk_spec.rb 2020-06-24 05:19:27.000000000 +0200 +++ new/spec/hunk_spec.rb 2020-07-01 20:29:57.000000000 +0200 @@ -6,28 +6,39 @@ require 'diff/lcs/hunk' describe Diff::LCS::Hunk do - let(:old_data) { ['Tu avec carté {count} itém has'.encode('UTF-16LE')] } - let(:new_data) { ['Tu avec carte {count} item has'.encode('UTF-16LE')] } + let(:old_data) { ['Tu a un carté avec {count} itéms'.encode('UTF-16LE')] } + let(:new_data) { ['Tu a un carte avec {count} items'.encode('UTF-16LE')] } let(:pieces) { Diff::LCS.diff old_data, new_data } let(:hunk) { Diff::LCS::Hunk.new(old_data, new_data, pieces[0], 3, 0) } it 'produces a unified diff from the two pieces' do expected = <<-EXPECTED.gsub(/^\s+/, '').encode('UTF-16LE').chomp @@ -1 +1 @@ - -Tu avec carté {count} itém has - +Tu avec carte {count} item has + -Tu a un carté avec {count} itéms + +Tu a un carte avec {count} items EXPECTED expect(hunk.diff(:unified)).to eq(expected) end + it 'produces a unified diff from the two pieces (last entry)' do + expected = <<-EXPECTED.gsub(/^\s+/, '').encode('UTF-16LE').chomp + @@ -1 +1 @@ + -Tu a un carté avec {count} itéms + +Tu a un carte avec {count} items + \\ No newline at end of file + EXPECTED + + expect(hunk.diff(:unified, true)).to eq(expected) + end + it 'produces a context diff from the two pieces' do expected = <<-EXPECTED.gsub(/^\s+/, '').encode('UTF-16LE').chomp *************** *** 1 **** - ! Tu avec carté {count} itém has + ! Tu a un carté avec {count} itéms --- 1 ---- - ! Tu avec carte {count} item has + ! Tu a un carte avec {count} items EXPECTED expect(hunk.diff(:context)).to eq(expected) @@ -36,9 +47,9 @@ it 'produces an old diff from the two pieces' do expected = <<-EXPECTED.gsub(/^ +/, '').encode('UTF-16LE').chomp 1c1 - < Tu avec carté {count} itém has + < Tu a un carté avec {count} itéms --- - > Tu avec carte {count} item has + > Tu a un carte avec {count} items EXPECTED @@ -48,7 +59,7 @@ it 'produces a reverse ed diff from the two pieces' do expected = <<-EXPECTED.gsub(/^ +/, '').encode('UTF-16LE').chomp c1 - Tu avec carte {count} item has + Tu a un carte avec {count} items . EXPECTED @@ -62,7 +73,7 @@ it 'produces a unified diff' do expected = <<-EXPECTED.gsub(/^\s+/, '').encode('UTF-16LE').chomp @@ -1 +1,2 @@ - +Tu avec carte {count} item has + +Tu a un carte avec {count} items EXPECTED expect(hunk.diff(:unified)).to eq(expected) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec/issues_spec.rb new/spec/issues_spec.rb --- old/spec/issues_spec.rb 2020-06-24 05:19:27.000000000 +0200 +++ new/spec/issues_spec.rb 2020-07-01 20:29:57.000000000 +0200 @@ -56,17 +56,17 @@ end end - describe "issue #57" do + describe 'issue #57' do it 'should fail with a correct error' do expect { - actual = {:category=>"app.rack.request"} - expected = {:category=>"rack.middleware", :title=>"Anonymous Middleware"} + actual = { :category => 'app.rack.request' } + expected = { :category => 'rack.middleware', :title => 'Anonymous Middleware' } expect(actual).to eq(expected) }.to raise_error(RSpec::Expectations::ExpectationNotMetError) end end - describe "issue #60" do + describe 'issue #60' do it 'should produce unified output with correct context' do old_data = <<-DATA_OLD.strip.split("\n").map(&:chomp) { @@ -95,4 +95,60 @@ EXPECTED end end + + describe 'issue #65' do + def diff_lines(old_lines, new_lines) + file_length_difference = 0 + previous_hunk = nil + output = [] + + Diff::LCS.diff(old_lines, new_lines).each do |piece| + hunk = Diff::LCS::Hunk.new(old_lines, new_lines, piece, 3, file_length_difference) + file_length_difference = hunk.file_length_difference + maybe_contiguous_hunks = (previous_hunk.nil? || hunk.merge(previous_hunk)) + + output << "#{previous_hunk.diff(:unified)}\n" unless maybe_contiguous_hunks + + previous_hunk = hunk + end + output << "#{previous_hunk.diff(:unified, true)}\n" unless previous_hunk.nil? + output.join + end + + it 'should not misplace the new chunk' do + old_data = [ + 'recipe[a::default]', 'recipe[b::default]', 'recipe[c::default]', + 'recipe[d::default]', 'recipe[e::default]', 'recipe[f::default]', + 'recipe[g::default]', 'recipe[h::default]', 'recipe[i::default]', + 'recipe[j::default]', 'recipe[k::default]', 'recipe[l::default]', + 'recipe[m::default]', 'recipe[n::default]' + ] + + new_data = [ + 'recipe[a::default]', 'recipe[c::default]', 'recipe[d::default]', + 'recipe[e::default]', 'recipe[f::default]', 'recipe[g::default]', + 'recipe[h::default]', 'recipe[i::default]', 'recipe[j::default]', + 'recipe[k::default]', 'recipe[l::default]', 'recipe[m::default]', + 'recipe[n::default]', 'recipe[o::new]', 'recipe[p::new]', + 'recipe[q::new]', 'recipe[r::new]' + ] + + expect(diff_lines(old_data, new_data)).to eq(<<-EODIFF) +@@ -1,5 +1,4 @@ + recipe[a::default] +-recipe[b::default] + recipe[c::default] + recipe[d::default] + recipe[e::default] +@@ -12,3 +11,7 @@ + recipe[l::default] + recipe[m::default] + recipe[n::default] ++recipe[o::new] ++recipe[p::new] ++recipe[q::new] ++recipe[r::new] + EODIFF + end + end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec/ldiff_spec.rb new/spec/ldiff_spec.rb --- old/spec/ldiff_spec.rb 2020-06-24 05:19:27.000000000 +0200 +++ new/spec/ldiff_spec.rb 2020-07-01 20:29:57.000000000 +0200 @@ -5,39 +5,41 @@ RSpec.describe 'bin/ldiff' do include CaptureSubprocessIO - let(:output_diff) { read_fixture } - let(:output_diff_c) { read_fixture('-c') } - let(:output_diff_e) { read_fixture('-e') } - let(:output_diff_f) { read_fixture('-f') } - let(:output_diff_u) { read_fixture('-u') } - let(:output_diff_chef) { read_fixture('-u', base: 'output.diff.chef') } + fixtures = [ + { :name => 'output.diff', :left => 'aX', :right => 'bXaX' }, + { :name => 'output.diff.chef', :left => 'old-chef', :right => 'new-chef' }, + { :name => 'output.diff.chef2', :left => 'old-chef2', :right => 'new-chef2' } + ].product([nil, '-e', '-f', '-c', '-u']).map { |(fixture, flag)| + fixture = fixture.dup + fixture[:flag] = flag + fixture + } + + def self.test_ldiff(fixture) + desc = [ + fixture[:flag], + "spec/fixtures/#{fixture[:left]}", + "spec/fixtures/#{fixture[:right]}", + '#', + '=>', + "spec/fixtures/ldiff/#{fixture[:name]}#{fixture[:flag]}" + ].join(' ') - specify do - expect(run_ldiff('-u', left: 'old-chef', right: 'new-chef')).to eq(output_diff_chef) - end - - specify do - expect(run_ldiff).to eq(output_diff) - end - - specify do - expect(run_ldiff('-c')).to eq(output_diff_c) - end - - specify do - expect(run_ldiff('-e')).to eq(output_diff_e) - end - - specify do - expect(run_ldiff('-f')).to eq(output_diff_f) + it desc do + expect(run_ldiff(fixture)).to eq(read_fixture(fixture)) + end end - specify do - expect(run_ldiff('-u')).to eq(output_diff_u) + fixtures.each do |fixture| + test_ldiff(fixture) end - def read_fixture(flag = nil, base: 'output.diff') - clean_data(IO.binread("spec/fixtures/ldiff/#{base}#{flag}"), flag) + def read_fixture(options) + fixture = options.fetch(:name) + flag = options.fetch(:flag) + name = "spec/fixtures/ldiff/#{fixture}#{flag}" + data = IO.__send__(IO.respond_to?(:binread) ? :binread : :read, name) + clean_data(data, flag) end def clean_data(data, flag) @@ -65,15 +67,20 @@ \s* (?:[-+]\d{4}|Z) }x, - '*** spec/fixtures/\1 0000-00-00 00:00:00.000000000 -0000' + '*** spec/fixtures/\1 0000-00-00 :00 =>:00 =>00.000000000 -0000' ) end - def run_ldiff(flag = nil, left: 'aX', right: 'bXaX') + def run_ldiff(options) + flag = options.fetch(:flag) + left = options.fetch(:left) + right = options.fetch(:right) + stdout, stderr = capture_subprocess_io do system("ruby -Ilib bin/ldiff #{flag} spec/fixtures/#{left} spec/fixtures/#{right}") end - expect(stderr).to be_empty + + expect(stderr).to be_empty if RUBY_VERSION >= '1.9' expect(stdout).not_to be_empty clean_data(stdout, flag) end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/spec/spec_helper.rb new/spec/spec_helper.rb --- old/spec/spec_helper.rb 2020-06-24 05:19:27.000000000 +0200 +++ new/spec/spec_helper.rb 2020-07-01 20:29:57.000000000 +0200 @@ -2,7 +2,8 @@ require 'rubygems' require 'pathname' -require 'psych' + +require 'psych' if RUBY_VERSION >= '1.9' if ENV['COVERAGE'] require 'simplecov' @@ -43,30 +44,31 @@ end def capture_subprocess_io - _synchronize do - begin - require 'tempfile' - - captured_stdout, captured_stderr = Tempfile.new('out'), Tempfile.new('err') - - orig_stdout, orig_stderr = $stdout.dup, $stderr.dup - $stdout.reopen captured_stdout - $stderr.reopen captured_stderr - - yield - - $stdout.rewind - $stderr.rewind - - return captured_stdout.read, captured_stderr.read - ensure - captured_stdout.unlink - captured_stderr.unlink - $stdout.reopen orig_stdout - $stderr.reopen orig_stderr - end - end + _synchronize { _capture_subprocess_io { yield } } + end + + def _capture_subprocess_io + require 'tempfile' + + captured_stdout, captured_stderr = Tempfile.new('out'), Tempfile.new('err') + + orig_stdout, orig_stderr = $stdout.dup, $stderr.dup + $stdout.reopen captured_stdout + $stderr.reopen captured_stderr + + yield + + $stdout.rewind + $stderr.rewind + + [captured_stdout.read, captured_stderr.read] + ensure + captured_stdout.unlink + captured_stderr.unlink + $stdout.reopen orig_stdout + $stderr.reopen orig_stderr end + private :_capture_subprocess_io end require 'diff-lcs'